Search in sources :

Example 26 with TypeReference

use of org.jikesrvm.classloader.TypeReference in project JikesRVM by JikesRVM.

the class ShortArrayReplacer method transform.

@Override
public void transform() {
    // first set up temporary scalars for the array elements
    // initialize them before the def.
    RegisterOperand[] scalars = new RegisterOperand[size];
    TypeReference elementType = vmArray.getElementType().getTypeRef();
    RegisterOperand def = reg.defList;
    Instruction defI = def.instruction;
    Operand defaultValue = IRTools.getDefaultOperand(elementType);
    for (int i = 0; i < size; i++) {
        scalars[i] = IRTools.moveIntoRegister(elementType, IRTools.getMoveOp(elementType), ir.regpool, defI, defaultValue.copy());
    }
    transform2(this.reg, defI, scalars);
}
Also used : RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) TrueGuardOperand(org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) TIBConstantOperand(org.jikesrvm.compilers.opt.ir.operand.TIBConstantOperand) TrapCodeOperand(org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand) TypeReference(org.jikesrvm.classloader.TypeReference) Instruction(org.jikesrvm.compilers.opt.ir.Instruction)

Example 27 with TypeReference

use of org.jikesrvm.classloader.TypeReference in project JikesRVM by JikesRVM.

the class ShortArrayReplacer method scalarReplace.

/**
 * Replace a given use of an array with its scalar equivalent.
 *
 * @param use the use to replace
 * @param scalars an array of scalar register operands to replace
 *                  the array with
 * @param visited TODO currently useless. Is this parameter
 *  necessary or should it be removed?
 */
private void scalarReplace(RegisterOperand use, RegisterOperand[] scalars, Set<Register> visited) {
    Instruction inst = use.instruction;
    RVMType type = vmArray.getElementType();
    switch(inst.getOpcode()) {
        case INT_ALOAD_opcode:
        case LONG_ALOAD_opcode:
        case FLOAT_ALOAD_opcode:
        case DOUBLE_ALOAD_opcode:
        case BYTE_ALOAD_opcode:
        case UBYTE_ALOAD_opcode:
        case USHORT_ALOAD_opcode:
        case SHORT_ALOAD_opcode:
        case REF_ALOAD_opcode:
            {
                // of a trap
                if (ALoad.getIndex(inst).isIntConstant()) {
                    Operator moveOp = IRTools.getMoveOp(type.getTypeRef());
                    int index = ALoad.getIndex(inst).asIntConstant().value;
                    if (index >= 0 && index < size) {
                        Instruction i2 = Move.create(moveOp, ALoad.getClearResult(inst), scalars[index].copyRO());
                        DefUse.replaceInstructionAndUpdateDU(inst, i2);
                    } else {
                        DefUse.removeInstructionAndUpdateDU(inst);
                    }
                } else {
                    if (VM.BuildForIA32) {
                        if (size == 0) {
                            DefUse.removeInstructionAndUpdateDU(inst);
                        } else if (size == 1) {
                            int index = 0;
                            Operator moveOp = IRTools.getMoveOp(type.getTypeRef());
                            Instruction i2 = Move.create(moveOp, ALoad.getClearResult(inst), scalars[index].copyRO());
                            DefUse.replaceInstructionAndUpdateDU(inst, i2);
                        } else {
                            Operator moveOp = IRTools.getCondMoveOp(type.getTypeRef());
                            Instruction i2 = CondMove.create(moveOp, ALoad.getClearResult(inst), ALoad.getClearIndex(inst), IC(0), ConditionOperand.EQUAL(), scalars[0].copyRO(), scalars[1].copyRO());
                            DefUse.replaceInstructionAndUpdateDU(inst, i2);
                        }
                    } else {
                        if (size == 1) {
                            int index = 0;
                            Operator moveOp = IRTools.getMoveOp(type.getTypeRef());
                            Instruction i2 = Move.create(moveOp, ALoad.getClearResult(inst), scalars[index].copyRO());
                            DefUse.replaceInstructionAndUpdateDU(inst, i2);
                        } else {
                            DefUse.removeInstructionAndUpdateDU(inst);
                        }
                    }
                }
            }
            break;
        case INT_ASTORE_opcode:
        case LONG_ASTORE_opcode:
        case FLOAT_ASTORE_opcode:
        case DOUBLE_ASTORE_opcode:
        case BYTE_ASTORE_opcode:
        case SHORT_ASTORE_opcode:
        case REF_ASTORE_opcode:
            {
                // of a trap
                if (AStore.getIndex(inst).isIntConstant()) {
                    int index = AStore.getIndex(inst).asIntConstant().value;
                    if (index >= 0 && index < size) {
                        Operator moveOp = IRTools.getMoveOp(type.getTypeRef());
                        Instruction i2 = Move.create(moveOp, scalars[index].copyRO(), AStore.getClearValue(inst));
                        DefUse.replaceInstructionAndUpdateDU(inst, i2);
                    } else {
                        DefUse.removeInstructionAndUpdateDU(inst);
                    }
                } else {
                    if (VM.BuildForIA32) {
                        if (size == 0) {
                            DefUse.removeInstructionAndUpdateDU(inst);
                        } else if (size == 1) {
                            int index = 0;
                            Operator moveOp = IRTools.getMoveOp(type.getTypeRef());
                            Instruction i2 = Move.create(moveOp, scalars[index].copyRO(), AStore.getClearValue(inst));
                            DefUse.replaceInstructionAndUpdateDU(inst, i2);
                        } else {
                            Operator moveOp = IRTools.getCondMoveOp(type.getTypeRef());
                            Operand value = AStore.getClearValue(inst);
                            Instruction i2 = CondMove.create(moveOp, scalars[0].copyRO(), AStore.getIndex(inst), IC(0), ConditionOperand.EQUAL(), value, scalars[0].copyRO());
                            DefUse.replaceInstructionAndUpdateDU(inst, i2);
                            Instruction i3 = CondMove.create(moveOp, scalars[1].copyRO(), AStore.getIndex(inst), IC(0), ConditionOperand.NOT_EQUAL(), value, scalars[1].copyRO());
                            i2.insertAfter(i3);
                            DefUse.updateDUForNewInstruction(i3);
                        }
                    } else {
                        if (size == 1) {
                            int index = 0;
                            Operator moveOp = IRTools.getMoveOp(type.getTypeRef());
                            Instruction i2 = Move.create(moveOp, scalars[index].copyRO(), AStore.getClearValue(inst));
                            DefUse.replaceInstructionAndUpdateDU(inst, i2);
                        } else {
                            DefUse.removeInstructionAndUpdateDU(inst);
                        }
                    }
                }
            }
            break;
        case NULL_CHECK_opcode:
            {
                // Null check on result of new array must succeed
                Instruction i2 = Move.create(GUARD_MOVE, NullCheck.getClearGuardResult(inst), new TrueGuardOperand());
                DefUse.replaceInstructionAndUpdateDU(inst, i2);
            }
            break;
        case BOUNDS_CHECK_opcode:
            {
                // Remove or create trap as appropriate
                Instruction i2 = TrapIf.create(TRAP_IF, BoundsCheck.getClearGuardResult(inst), IC(size), BoundsCheck.getClearIndex(inst), ConditionOperand.LOWER_EQUAL(), TrapCodeOperand.ArrayBounds());
                DefUse.replaceInstructionAndUpdateDU(inst, i2);
            }
            break;
        case CHECKCAST_opcode:
        case CHECKCAST_NOTNULL_opcode:
        case CHECKCAST_UNRESOLVED_opcode:
            {
                // We cannot handle removing the checkcast if the result of the
                // checkcast test is unknown
                TypeReference lhsType = TypeCheck.getType(inst).getTypeRef();
                if (ClassLoaderProxy.includesType(lhsType, vmArray.getTypeRef()) == YES) {
                    if (visited == null) {
                        visited = new HashSet<Register>();
                    }
                    Register copy = TypeCheck.getResult(inst).getRegister();
                    if (!visited.contains(copy)) {
                        visited.add(copy);
                        transform2(copy, inst, scalars);
                    // NB will remove inst
                    } else {
                        DefUse.removeInstructionAndUpdateDU(inst);
                    }
                } else {
                    Instruction i2 = Trap.create(TRAP, null, TrapCodeOperand.CheckCast());
                    DefUse.replaceInstructionAndUpdateDU(inst, i2);
                }
            }
            break;
        case INSTANCEOF_opcode:
        case INSTANCEOF_NOTNULL_opcode:
        case INSTANCEOF_UNRESOLVED_opcode:
            {
                // We cannot handle removing the instanceof if the result of the
                // instanceof test is unknown
                TypeReference lhsType = InstanceOf.getType(inst).getTypeRef();
                Instruction i2;
                if (ClassLoaderProxy.includesType(lhsType, vmArray.getTypeRef()) == YES) {
                    i2 = Move.create(INT_MOVE, InstanceOf.getClearResult(inst), IC(1));
                } else {
                    i2 = Move.create(INT_MOVE, InstanceOf.getClearResult(inst), IC(0));
                }
                DefUse.replaceInstructionAndUpdateDU(inst, i2);
            }
            break;
        case GET_OBJ_TIB_opcode:
            {
                Instruction i2 = Move.create(REF_MOVE, GuardedUnary.getClearResult(inst), new TIBConstantOperand(vmArray));
                DefUse.replaceInstructionAndUpdateDU(inst, i2);
            }
            break;
        case REF_MOVE_opcode:
            {
                if (visited == null) {
                    visited = new HashSet<Register>();
                }
                Register copy = Move.getResult(inst).getRegister();
                if (!visited.contains(copy)) {
                    visited.add(copy);
                    transform2(copy, inst, scalars);
                // NB will remove inst
                } else {
                    DefUse.removeInstructionAndUpdateDU(inst);
                }
            }
            break;
        default:
            throw new OptimizingCompilerException("Unexpected instruction: " + inst);
    }
}
Also used : Operator(org.jikesrvm.compilers.opt.ir.Operator) Register(org.jikesrvm.compilers.opt.ir.Register) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) TrueGuardOperand(org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) TIBConstantOperand(org.jikesrvm.compilers.opt.ir.operand.TIBConstantOperand) TrapCodeOperand(org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand) RVMType(org.jikesrvm.classloader.RVMType) TIBConstantOperand(org.jikesrvm.compilers.opt.ir.operand.TIBConstantOperand) TypeReference(org.jikesrvm.classloader.TypeReference) OptimizingCompilerException(org.jikesrvm.compilers.opt.OptimizingCompilerException) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) TrueGuardOperand(org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand) HashSet(java.util.HashSet)

Example 28 with TypeReference

use of org.jikesrvm.classloader.TypeReference in project JikesRVM by JikesRVM.

the class LiveAnalysis method computeBlockGenAndKill.

/**
 * Compute summary (local) live variable analysis for a basic block, which
 * is basically Gen and Kill information.<p>
 *
 * For more details, see the paper "Efficient and Precise Modeling of
 * Exceptions for the Analysis of Java Programs" by Choi, Grove, Hind
 * and Sarkar in ACM PASTE99 workshop.
 *
 * @param bblock the basic block
 * @param ir the governing IR
 */
private void computeBlockGenAndKill(BasicBlock bblock, IR ir) {
    if (VERBOSE) {
        System.out.println(" --> Computing Gen/Kill for block " + bblock);
    }
    // Tells whether we've seen the first PEI
    boolean seenFirstPEI = false;
    // Because control flow may emanate from a potentially excepting
    // instruction (PEI) out of the basic block, care must be taken
    // when computing what can be killed by a basic block.
    // 
    // S1:  y =
    // S2:  <exception-raising inst>
    // S3:  x =
    // For example in the block above, live variables coming from
    // the normal exit of the block (i.e., after S3) can be killed
    // by S1 or S3 (depending on the variable).  However, live variables
    // coming from the PEI edge (at S2) can only be killed by S1.
    // Thus, when a block contains PEIs, we need to distinguish the
    // kill sets.  Namely, we need
    // Kill_tot  -  what can be killed anywhere in the block
    // Kill_n    -  what can be killed from PEI_n on up
    // Kill_n-1  -  what can be killed from PEI_n-1 on up
    // ...
    // Kill_1    -  what can be killed from PEI_1 on up
    // We would then compute In as follows
    // 
    // In = Out_norm - Kill_tot   (all vars entering from bottom are eligible
    // to be killed)
    // U Out_n - Kill_n
    // U Out_n-1 - Kill_n-1
    // ...
    // U Out_1 - Kill_1
    // U Gen
    // where Out_n is the out information at PEI i, i.e., the IN information
    // for whatever handlers may catch PEI i
    // ...
    // PEI 1
    // ...
    // PEI n-1
    // ...
    // PEI n
    // ...
    // If we conservatively assume all handlers for the block of interest
    // can be reached by all PEIs in this block then the equation becomes
    // In = (Out_norm - Kill_tot)
    // U (Out_hand - Kill_n)
    // U (Out_hand - Kill_n-1)
    // ...
    // U (Out_hand - Kill_1)
    // U Gen
    // where "Out_hand" is the union of the in sets for all handlers.
    // Since Kill_i is a subset of Kill_j, for i < j, we can simplify to
    // In = (Out_norm - Kill_tot)
    // U (Out_hand - Kill_1)    (1)
    // U Gen
    // Since kill_1 is a subset of kill_tot, we don't need the
    // the parenthesis (and the intermediate set)
    // If there are no handlers than (1) is empty and we don't need
    // to compute Kill_1.  We will take this approach for now.
    // So for each block we will have at most 2 kill sets: Kill_tot and Kill_1
    // This code finds the first PEI in the block
    Instruction firstPEI = null;
    if (bblock.canThrowExceptions()) {
        for (Instruction inst = bblock.firstInstruction(); inst != bblock.lastInstruction(); inst = inst.nextInstructionInCodeOrder()) {
            if (inst.isPEI() && bblock.getApplicableExceptionalOut(inst).hasMoreElements()) {
                firstPEI = inst;
                // remember that this block has a PEI with a handler for use
                // later in "processBlock"
                bbLiveInfo[bblock.getNumber()].setContainsPEIWithHandler(true);
                break;
            }
        }
    }
    // Get any uses from PHIs, which are in the successor blocks
    getUsesFromPhis(bblock);
    // Traverse instructions in reverse order within the basic block.
    for (Instruction inst = bblock.lastInstruction(); inst != bblock.firstInstruction(); inst = inst.prevInstructionInCodeOrder()) {
        // traverse from defs to uses becauses uses happen after
        // (in a backward sense) defs
        Enumeration<Operand> defs = inst.getPureDefs();
        while (defs.hasMoreElements()) {
            Operand def = defs.nextElement();
            if (def instanceof RegisterOperand) {
                RegisterOperand regOp = (RegisterOperand) def;
                // Do we care about this reg?
                if (isSkippableReg(regOp, ir)) {
                    continue;
                }
                TypeReference regType = regOp.getType();
                // include it.  It will be picked up later by local propagation phase.
                if (regOp.getRegister().spansBasicBlock() && regType != null) {
                    // if it is a DEF we place it is the BBKillSet and remove it from
                    // the GEN set, (GEN should only contain upward-exposed uses,
                    // i.e., uses that are NOT dominated by a DEF).
                    // We don't need to worry about PEIs here because
                    // later instructions (traversing backwards like we are)
                    // will always dominate earlier instructions *of this block*
                    bbLiveInfo[bblock.getNumber()].BBKillSet().add(regOp);
                    bbLiveInfo[bblock.getNumber()].getGen().remove(regOp);
                    // If there are no PEIs in this block we don't bother to add
                    if (seenFirstPEI) {
                        bbLiveInfo[bblock.getNumber()].firstPEIKillSet().add(regOp);
                    }
                }
            }
        }
        // Now process the uses, unless this is a PHI operator
        if (inst.operator() != PHI) {
            for (Enumeration<Operand> uses = inst.getUses(); uses.hasMoreElements(); ) {
                Operand use = uses.nextElement();
                if (use instanceof RegisterOperand) {
                    RegisterOperand regOp = (RegisterOperand) use;
                    // Do we care about this reg?
                    if (isSkippableReg(regOp, ir)) {
                        continue;
                    }
                    TypeReference regType = regOp.getType();
                    // later by local propagation phase.
                    if (regOp.getRegister().spansBasicBlock() && regType != null) {
                        bbLiveInfo[bblock.getNumber()].getGen().add(regOp);
                    }
                }
            // is RegOp
            }
        // foreach use
        }
        // If so, set the flag so we can start killing.
        if (firstPEI == inst) {
            seenFirstPEI = true;
        }
    }
    // foreach instruction in block
    if (VERBOSE) {
        System.out.println("  Gen: " + bbLiveInfo[bblock.getNumber()].getGen());
        System.out.println("  Kill: " + bbLiveInfo[bblock.getNumber()].BBKillSet());
        System.out.println("  1st PEI Kill: " + bbLiveInfo[bblock.getNumber()].firstPEIKillSet());
        System.out.println(" ---> Done computing Gen/Kill for block");
    }
}
Also used : RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) InlinedOsrTypeInfoOperand(org.jikesrvm.compilers.opt.ir.operand.InlinedOsrTypeInfoOperand) BasicBlockOperand(org.jikesrvm.compilers.opt.ir.operand.BasicBlockOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) TypeReference(org.jikesrvm.classloader.TypeReference) Instruction(org.jikesrvm.compilers.opt.ir.Instruction)

Example 29 with TypeReference

use of org.jikesrvm.classloader.TypeReference in project JikesRVM by JikesRVM.

the class CallingConvention method expandPrologue.

private static void expandPrologue(IR ir) {
    boolean useDU = ir.options.getOptLevel() >= 1;
    if (useDU) {
        // set up register lists for dead code elimination.
        DefUse.computeDU(ir);
    }
    Instruction p = ir.firstInstructionInCodeOrder().nextInstructionInCodeOrder();
    if (VM.VerifyAssertions)
        VM._assert(p.operator() == IR_PROLOGUE);
    Instruction start = p.nextInstructionInCodeOrder();
    PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet().asIA32();
    int gprIndex = 0;
    int fprIndex = 0;
    int paramByteOffset = ir.incomingParameterBytes() + 2 * WORDSIZE;
    // count the number of FPR params in a pre-pass
    int FPRRegisterParams = countFPRParamsInPrologue(p);
    FPRRegisterParams = Math.min(FPRRegisterParams, PhysicalRegisterSet.getNumberOfFPRParams());
    ir.MIRInfo.fpStackHeight = Math.max(ir.MIRInfo.fpStackHeight, FPRRegisterParams);
    // deal with each parameter
    for (Enumeration<Operand> e = p.getDefs(); e.hasMoreElements(); ) {
        RegisterOperand symbOp = (RegisterOperand) e.nextElement();
        TypeReference rType = symbOp.getType();
        if (rType.isFloatingPointType()) {
            int size;
            if (rType.isFloatType()) {
                size = BYTES_IN_FLOAT;
                paramByteOffset -= WORDSIZE;
            } else {
                size = BYTES_IN_DOUBLE;
                paramByteOffset -= 2 * WORDSIZE;
            }
            // if optimizing, only define the register if it has uses
            if (!useDU || symbOp.getRegister().useList != null) {
                if (fprIndex < PhysicalRegisterSet.getNumberOfFPRParams()) {
                    // the 2nd goes in F(k-2), etc...
                    if (SSE2_FULL) {
                        Register param = phys.getFPRParam(fprIndex);
                        if (rType.isFloatType()) {
                            start.insertBefore(MIR_Move.create(IA32_MOVSS, symbOp.copyRO(), F(param)));
                        } else {
                            start.insertBefore(MIR_Move.create(IA32_MOVSD, symbOp.copyRO(), D(param)));
                        }
                    } else {
                        Register param = phys.getFPRParam(FPRRegisterParams - fprIndex - 1);
                        start.insertBefore(MIR_Move.create(IA32_FMOV, symbOp.copyRO(), D(param)));
                    }
                } else {
                    Operand M = new StackLocationOperand(true, paramByteOffset, size);
                    if (SSE2_FULL) {
                        if (rType.isFloatType()) {
                            start.insertBefore(MIR_Move.create(IA32_MOVSS, symbOp.copyRO(), M));
                        } else {
                            start.insertBefore(MIR_Move.create(IA32_MOVSD, symbOp.copyRO(), M));
                        }
                    } else {
                        start.insertBefore(MIR_Move.create(IA32_FMOV, symbOp.copyRO(), M));
                    }
                }
            }
            fprIndex++;
        } else {
            // if optimizing, only define the register if it has uses
            paramByteOffset -= WORDSIZE;
            if (paramIsNativeLongOn64Bit(symbOp)) {
                paramByteOffset -= WORDSIZE;
            }
            if (!useDU || symbOp.getRegister().useList != null) {
                // t is object, 1/2 of a long, int, short, char, byte, or boolean
                if (gprIndex < PhysicalRegisterSet.getNumberOfGPRParams()) {
                    // to give the register allocator more freedom, we
                    // insert two move instructions to get the physical into
                    // the symbolic.  First a move from the physical to a fresh temp
                    // before start and second a move from the temp to the
                    // 'real' parameter symbolic after start.
                    RegisterOperand tmp = ir.regpool.makeTemp(rType);
                    Register param = phys.getGPRParam(gprIndex);
                    RegisterOperand pOp = new RegisterOperand(param, rType);
                    start.insertBefore(PhysicalRegisterTools.makeMoveInstruction(tmp, pOp));
                    Instruction m2 = PhysicalRegisterTools.makeMoveInstruction(symbOp.copyRO(), tmp.copyD2U());
                    start.insertBefore(m2);
                    start = m2;
                } else {
                    int stackLocSize = WORDSIZE;
                    if (VM.BuildFor64Addr && rType.getMemoryBytes() <= BYTES_IN_INT) {
                        stackLocSize = BYTES_IN_INT;
                    }
                    Operand M = new StackLocationOperand(true, paramByteOffset, stackLocSize);
                    start.insertBefore(MIR_Move.create(IA32_MOV, symbOp.copyRO(), M));
                }
            }
            gprIndex++;
        }
    }
    if (VM.VerifyAssertions && paramByteOffset != 2 * WORDSIZE) {
        String msg = "pb = " + paramByteOffset + "; expected " + 2 * WORDSIZE;
        VM._assert(VM.NOT_REACHED, msg);
    }
    removeDefsFromPrologue(p);
}
Also used : RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Register(org.jikesrvm.compilers.opt.ir.Register) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) IA32ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ia32.IA32ConditionOperand) StackLocationOperand(org.jikesrvm.compilers.opt.ir.operand.StackLocationOperand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) MemoryOperand(org.jikesrvm.compilers.opt.ir.operand.MemoryOperand) GenericPhysicalRegisterSet(org.jikesrvm.compilers.opt.ir.GenericPhysicalRegisterSet) PhysicalRegisterSet(org.jikesrvm.compilers.opt.ir.ia32.PhysicalRegisterSet) TypeReference(org.jikesrvm.classloader.TypeReference) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) StackLocationOperand(org.jikesrvm.compilers.opt.ir.operand.StackLocationOperand)

Example 30 with TypeReference

use of org.jikesrvm.classloader.TypeReference in project JikesRVM by JikesRVM.

the class CallingConvention method expandParametersToSysCall.

/**
 * Explicitly copy parameters to a system call into the appropriate physical
 * registers as defined by the calling convention.  Note that for a system
 * call (ie., a call to C), the order of parameters on the stack is
 * <em> reversed </em> compared to the normal RVM calling convention<p>
 *
 * Note: Assumes that ESP points to the word before the slot where the
 * first parameter should be stored.<p>
 *
 * TODO: much of this code is exactly the same as in expandParametersToCall().
 *       factor out the common code.
 *
 * @param call the call instruction
 * @param ir the IR that contains the call
 * @return the number of bytes necessary to hold the parameters
 */
private static int expandParametersToSysCall(Instruction call, IR ir) {
    int nGPRParams = 0;
    int nFPRParams = 0;
    int parameterBytes = 0;
    int numParams = MIR_Call.getNumberOfParams(call);
    if (VM.BuildFor32Addr) {
        // NOTE: All params to syscall are passed on the stack!
        for (int i = numParams - 1; i >= 0; i--) {
            Operand param = MIR_Call.getClearParam(call, i);
            MIR_Call.setParam(call, i, null);
            TypeReference paramType = param.getType();
            if (paramType.isFloatingPointType()) {
                nFPRParams++;
                int size;
                if (paramType.isFloatType()) {
                    size = BYTES_IN_FLOAT;
                    parameterBytes -= WORDSIZE;
                } else {
                    size = BYTES_IN_DOUBLE;
                    parameterBytes -= 2 * WORDSIZE;
                }
                Operand M = new StackLocationOperand(false, parameterBytes, size);
                if (SSE2_FULL) {
                    if (paramType.isFloatType()) {
                        call.insertBefore(MIR_Move.create(IA32_MOVSS, M, param));
                    } else {
                        call.insertBefore(MIR_Move.create(IA32_MOVSD, M, param));
                    }
                } else {
                    call.insertBefore(MIR_Move.create(IA32_FMOV, M, param));
                }
            } else {
                nGPRParams++;
                parameterBytes -= WORDSIZE;
                call.insertBefore(MIR_UnaryNoRes.create(REQUIRE_ESP, IC(parameterBytes + WORDSIZE)));
                call.insertBefore(MIR_UnaryNoRes.create(IA32_PUSH, param));
            }
        }
        return parameterBytes;
    } else {
        if (VM.VerifyAssertions)
            VM._assert(SSE2_FULL, "x64 builds must have SSE2_FULL enabled");
        PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet().asIA32();
        // count the number FPR parameters in a pre-pass
        int FPRRegisterParams = countFPRParams(call);
        FPRRegisterParams = Math.min(FPRRegisterParams, PhysicalRegisterSet.getNumberOfNativeFPRParams());
        // offset, in bytes, from the SP, for the next parameter slot on the
        // stack
        parameterBytes = -2 * WORDSIZE;
        RegisterOperand fpCount = new RegisterOperand(phys.getEAX(), TypeReference.Int);
        // Save count of vector parameters (= XMM) in EAX as defined by
        // the ABI for varargs convention
        call.insertBefore(MIR_Move.create(IA32_MOV, fpCount, IC(FPRRegisterParams)));
        // Save volatiles to non-volatiles that are currently not used
        call.insertBefore(MIR_Move.create(IA32_MOV, new RegisterOperand(phys.getGPR(R14), TypeReference.Long), new RegisterOperand(phys.getESI(), TypeReference.Long)));
        call.insertBefore(MIR_Move.create(IA32_MOV, new RegisterOperand(phys.getGPR(R13), TypeReference.Long), new RegisterOperand(phys.getEDI(), TypeReference.Long)));
        // Restore volatiles from non-volatiles
        call.insertAfter(MIR_Move.create(IA32_MOV, new RegisterOperand(phys.getESI(), TypeReference.Long), new RegisterOperand(phys.getGPR(R14), TypeReference.Long)));
        call.insertAfter(MIR_Move.create(IA32_MOV, new RegisterOperand(phys.getEDI(), TypeReference.Long), new RegisterOperand(phys.getGPR(R13), TypeReference.Long)));
        if (VM.BuildFor64Addr) {
            // Add a marker instruction. When processing x64 syscalls, the block of the syscall
            // needs to be split up to copy the code for the call. Copying has to occur
            // to be able to ensure stack alignment for the x64 ABI. This instruction
            // marks the border for the copy: everything before this instruction isn't duplicated.
            call.insertBefore(MIR_UnaryNoRes.create(REQUIRE_ESP, IC(MARKER)));
        }
        // Require ESP to be at bottom of frame before a call,
        call.insertBefore(MIR_UnaryNoRes.create(REQUIRE_ESP, IC(0)));
        // Determine if a parameter is in a register or not
        boolean[] inRegister = new boolean[numParams];
        nFPRParams = 0;
        nGPRParams = 0;
        for (int i = 0; i < numParams; i++) {
            Operand param = MIR_Call.getParam(call, i);
            TypeReference paramType = param.getType();
            if (paramType.isFloatingPointType()) {
                nFPRParams++;
                inRegister[i] = nFPRParams <= PhysicalRegisterSet.getNumberOfNativeFPRParams();
            } else {
                nGPRParams++;
                inRegister[i] = nGPRParams <= PhysicalRegisterSet.getNumberOfNativeGPRParams();
            }
        }
        // Walk over non-register parameters from right-to-left and assign stack slots
        int[] stackSlot = new int[numParams];
        for (int i = numParams - 1; i >= 0; i--) {
            if (!inRegister[i]) {
                parameterBytes -= BYTES_IN_STACKSLOT;
                stackSlot[i] = parameterBytes;
            }
        }
        // Pass stack slot parameters from right-to-left
        for (int i = numParams - 1; i >= 0; i--) {
            if (!inRegister[i]) {
                Operand param = MIR_Call.getClearParam(call, i);
                TypeReference paramType = param.getType();
                if (paramType.isFloatingPointType()) {
                    // pass the FP parameter on the stack
                    Operand M = new StackLocationOperand(false, stackSlot[i], BYTES_IN_STACKSLOT);
                    if (paramType.isFloatType()) {
                        call.insertBefore(MIR_Move.create(IA32_MOVSS, M, param));
                    } else {
                        call.insertBefore(MIR_Move.create(IA32_MOVSD, M, param));
                    }
                } else {
                    // Write the parameter into the appropriate stack frame location.
                    call.insertBefore(MIR_UnaryNoRes.create(REQUIRE_ESP, IC(stackSlot[i] + BYTES_IN_STACKSLOT)));
                    call.insertBefore(MIR_UnaryNoRes.create(IA32_PUSH, param));
                }
            }
        }
        // Pass register parameters from left-to-right
        int nParamsInRegisters = 0;
        nFPRParams = 0;
        nGPRParams = 0;
        for (int i = 0; i < numParams; i++) {
            if (inRegister[i]) {
                Operand param = MIR_Call.getClearParam(call, i);
                TypeReference paramType = param.getType();
                if (paramType.isFloatingPointType()) {
                    // Pass the parameter in a register.
                    RegisterOperand real = new RegisterOperand(phys.getNativeFPRParam(nFPRParams), paramType);
                    nFPRParams++;
                    if (paramType.isFloatType()) {
                        call.insertBefore(MIR_Move.create(IA32_MOVSS, real, param));
                    } else {
                        call.insertBefore(MIR_Move.create(IA32_MOVSD, real, param));
                    }
                    // Record that the call now has a use of the real register.
                    MIR_Call.setParam(call, nParamsInRegisters++, real.copy());
                } else {
                    Register phy = phys.getNativeGPRParam(nGPRParams);
                    nGPRParams++;
                    RegisterOperand real = new RegisterOperand(phy, paramType);
                    call.insertBefore(MIR_Move.create(IA32_MOV, real, param));
                    // Record that the call now has a use of the real register.
                    MIR_Call.setParam(call, nParamsInRegisters++, real.copy());
                }
            }
        }
        return parameterBytes;
    }
}
Also used : RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Register(org.jikesrvm.compilers.opt.ir.Register) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) IA32ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ia32.IA32ConditionOperand) StackLocationOperand(org.jikesrvm.compilers.opt.ir.operand.StackLocationOperand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) MemoryOperand(org.jikesrvm.compilers.opt.ir.operand.MemoryOperand) GenericPhysicalRegisterSet(org.jikesrvm.compilers.opt.ir.GenericPhysicalRegisterSet) PhysicalRegisterSet(org.jikesrvm.compilers.opt.ir.ia32.PhysicalRegisterSet) TypeReference(org.jikesrvm.classloader.TypeReference) StackLocationOperand(org.jikesrvm.compilers.opt.ir.operand.StackLocationOperand)

Aggregations

TypeReference (org.jikesrvm.classloader.TypeReference)164 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)58 Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)43 Instruction (org.jikesrvm.compilers.opt.ir.Instruction)38 MethodOperand (org.jikesrvm.compilers.opt.ir.operand.MethodOperand)30 BranchProfileOperand (org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand)28 TrueGuardOperand (org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand)27 IntConstantOperand (org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand)25 ConditionOperand (org.jikesrvm.compilers.opt.ir.operand.ConditionOperand)24 RVMClass (org.jikesrvm.classloader.RVMClass)23 RVMField (org.jikesrvm.classloader.RVMField)21 Register (org.jikesrvm.compilers.opt.ir.Register)21 LocationOperand (org.jikesrvm.compilers.opt.ir.operand.LocationOperand)21 NullConstantOperand (org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand)21 Address (org.vmmagic.unboxed.Address)21 RVMType (org.jikesrvm.classloader.RVMType)18 BasicBlock (org.jikesrvm.compilers.opt.ir.BasicBlock)18 AddressConstantOperand (org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand)18 TrapCodeOperand (org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand)18 RVMMethod (org.jikesrvm.classloader.RVMMethod)17