Search in sources :

Example 51 with Offset

use of org.vmmagic.unboxed.Offset in project JikesRVM by JikesRVM.

the class ArchBridgeDataExtractor method setupArchitectureSpecificDynamicBridgeMapping.

@Override
protected void setupArchitectureSpecificDynamicBridgeMapping(Address fp) {
    fp = Magic.getCallerFramePointer(fp);
    Address ip = Magic.getNextInstructionAddress(fp);
    int callingCompiledMethodId = Magic.getCompiledMethodID(fp);
    CompiledMethod callingCompiledMethod = CompiledMethods.getCompiledMethod(callingCompiledMethodId);
    Offset callingInstructionOffset = callingCompiledMethod.getInstructionOffset(ip);
    updateWithInfoForDynamicLink(callingCompiledMethod, callingInstructionOffset);
}
Also used : Address(org.vmmagic.unboxed.Address) CompiledMethod(org.jikesrvm.compilers.common.CompiledMethod) Offset(org.vmmagic.unboxed.Offset)

Example 52 with Offset

use of org.vmmagic.unboxed.Offset in project JikesRVM by JikesRVM.

the class BURS_Helpers method mutateTrapToCall.

private void mutateTrapToCall(Instruction s, RVMMethod target) {
    Offset offset = target.getOffset();
    RegisterOperand tmp = regpool.makeTemp(TypeReference.JavaLangObjectArray);
    Register JTOC = regpool.getPhysicalRegisterSet().asPPC().getJTOC();
    MethodOperand meth = MethodOperand.STATIC(target);
    meth.setIsNonReturningCall(true);
    int valueLow = PPCMaskLower16(offset);
    if (fits(offset, 16)) {
        EMIT(MIR_Load.create(PPC_LAddr, tmp, A(JTOC), IC(valueLow)));
    } else {
        int valueHigh = PPCMaskUpper16(offset);
        if (VM.VerifyAssertions)
            VM._assert(fits(offset, 32));
        Register reg = regpool.getAddress();
        EMIT(MIR_Binary.create(PPC_ADDIS, A(reg), A(JTOC), IC(valueHigh)));
        EMIT(MIR_Load.create(PPC_LAddr, tmp, A(reg), IC(valueLow)));
    }
    EMIT(MIR_Move.create(PPC_MTSPR, A(CTR), tmp.copyD2U()));
    EMIT(MIR_Call.mutate0(s, PPC_BCTRL, null, null, meth));
}
Also used : RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Register(org.jikesrvm.compilers.opt.ir.Register) OsrPoint(org.jikesrvm.compilers.opt.ir.OsrPoint) Offset(org.vmmagic.unboxed.Offset) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand)

Example 53 with Offset

use of org.vmmagic.unboxed.Offset in project JikesRVM by JikesRVM.

the class NormalizeConstants method perform.

/**
 * Doit.
 *
 * @param ir IR to normalize
 */
public static void perform(IR ir) {
    // This greatly reduces the number of cases we have to worry about below.
    if (VM.VerifyAssertions)
        VM._assert(ir.options.SIMPLIFY_INTEGER_OPS && ir.options.SIMPLIFY_LONG_OPS && ir.options.SIMPLIFY_REF_OPS);
    for (Instruction s = ir.firstInstructionInCodeOrder(); s != null; s = s.nextInstructionInCodeOrder()) {
        // STEP ONE: Get 'large' constants into a form that the PPC BURS rules
        // are prepared to deal with.
        // Constants can't appear as defs, so only scan the uses.
        // 
        int numUses = s.getNumberOfUses();
        if (numUses > 0) {
            int numDefs = s.getNumberOfDefs();
            for (int idx = numDefs; idx < numUses + numDefs; idx++) {
                Operand use = s.getOperand(idx);
                if (use != null) {
                    if (use instanceof ObjectConstantOperand) {
                        RegisterOperand rop = ir.regpool.makeTemp(use.getType());
                        RegisterOperand jtoc = (RegisterOperand) ir.regpool.makeJTOCOp();
                        ObjectConstantOperand oc = (ObjectConstantOperand) use;
                        Offset offset = oc.offset;
                        if (offset.isZero()) {
                            if (use instanceof StringConstantOperand) {
                                throw new OptimizingCompilerException("String constant w/o valid JTOC offset");
                            } else if (use instanceof ClassConstantOperand) {
                                throw new OptimizingCompilerException("Class constant w/o valid JTOC offset");
                            }
                            offset = Offset.fromIntSignExtend(Statics.findOrCreateObjectLiteral(oc.value));
                        }
                        LocationOperand loc = new LocationOperand(offset);
                        s.insertBefore(Load.create(VM.BuildFor32Addr ? INT_LOAD : LONG_LOAD, rop, jtoc, asImmediateOrRegOffset(AC(offset), s, ir, true), loc));
                        s.putOperand(idx, rop.copyD2U());
                    } else if (use instanceof DoubleConstantOperand) {
                        RegisterOperand rop = ir.regpool.makeTemp(TypeReference.Double);
                        RegisterOperand jtoc = (RegisterOperand) ir.regpool.makeJTOCOp();
                        DoubleConstantOperand dc = (DoubleConstantOperand) use;
                        Offset offset = dc.offset;
                        if (offset.isZero()) {
                            offset = Offset.fromIntSignExtend(Statics.findOrCreateLongSizeLiteral(Double.doubleToLongBits(dc.value)));
                        }
                        LocationOperand loc = new LocationOperand(offset);
                        s.insertBefore(Load.create(DOUBLE_LOAD, rop, jtoc, asImmediateOrRegOffset(AC(offset), s, ir, true), loc));
                        s.putOperand(idx, rop.copyD2U());
                    } else if (use instanceof FloatConstantOperand) {
                        RegisterOperand rop = ir.regpool.makeTemp(TypeReference.Float);
                        RegisterOperand jtoc = (RegisterOperand) ir.regpool.makeJTOCOp();
                        FloatConstantOperand fc = (FloatConstantOperand) use;
                        Offset offset = fc.offset;
                        if (offset.isZero()) {
                            offset = Offset.fromIntSignExtend(Statics.findOrCreateIntSizeLiteral(Float.floatToIntBits(fc.value)));
                        }
                        LocationOperand loc = new LocationOperand(offset);
                        s.insertBefore(Load.create(FLOAT_LOAD, rop, jtoc, asImmediateOrRegOffset(AC(offset), s, ir, true), loc));
                        s.putOperand(idx, rop.copyD2U());
                    } else if (use instanceof LongConstantOperand) {
                        if (!VM.BuildFor64Addr) {
                            if (s.getOpcode() != TRAP_IF_opcode) {
                                RegisterOperand rop = ir.regpool.makeTemp(TypeReference.Long);
                                s.insertBefore(Move.create(LONG_MOVE, rop, use.copy()));
                                s.putOperand(idx, rop.copyD2U());
                            }
                        }
                    } else if (use instanceof NullConstantOperand) {
                        s.putOperand(idx, AC(Address.zero()));
                    } else if (use instanceof TIBConstantOperand) {
                        RegisterOperand rop = ir.regpool.makeTemp(TypeReference.JavaLangObjectArray);
                        Operand jtoc = ir.regpool.makeJTOCOp();
                        Offset offset = ((TIBConstantOperand) use).value.getTibOffset();
                        LocationOperand loc = new LocationOperand(offset);
                        s.insertBefore(Load.create(VM.BuildFor32Addr ? INT_LOAD : LONG_LOAD, rop, jtoc, asImmediateOrRegOffset(AC(offset), s, ir, true), loc));
                        s.putOperand(idx, rop.copyD2U());
                    } else if (use instanceof CodeConstantOperand) {
                        RegisterOperand rop = ir.regpool.makeTemp(TypeReference.CodeArray);
                        Operand jtoc = ir.regpool.makeJTOCOp();
                        Offset offset = ((CodeConstantOperand) use).value.findOrCreateJtocOffset();
                        LocationOperand loc = new LocationOperand(offset);
                        s.insertBefore(Load.create(VM.BuildFor32Addr ? INT_LOAD : LONG_LOAD, rop, jtoc, asImmediateOrRegOffset(AC(offset), s, ir, true), loc));
                        s.putOperand(idx, rop.copyD2U());
                    }
                }
            }
        }
        // Calling Simplifier.simplify ensures that the instruction is
        // in normalized form. This reduces the number of cases we have to
        // worry about (and does last minute constant folding on the off chance
        // we've missed an opportunity...)
        Simplifier.simplify(false, ir.regpool, ir.options, s);
        switch(s.getOpcode()) {
            // ////////
            case REF_STORE_opcode:
                s.changeOperatorTo(VM.BuildFor32Addr ? INT_STORE : LONG_STORE);
                // On PowerPC, the value being stored must be in a register
                Store.setValue(s, asRegPolymorphic(Store.getClearValue(s), s, ir));
                // Supported addressing modes are quite limited.
                Store.setAddress(s, asRegAddress(Store.getClearAddress(s), s, ir));
                Store.setOffset(s, asImmediateOrRegOffset(Store.getClearOffset(s), s, ir, true));
                break;
            case BYTE_STORE_opcode:
            case SHORT_STORE_opcode:
            case INT_STORE_opcode:
            case LONG_STORE_opcode:
                // On PowerPC, the value being stored must be in a register
                Store.setValue(s, asRegPolymorphic(Store.getClearValue(s), s, ir));
                // Supported addressing modes are quite limited.
                Store.setAddress(s, asRegAddress(Store.getClearAddress(s), s, ir));
                Store.setOffset(s, asImmediateOrRegOffset(Store.getClearOffset(s), s, ir, true));
                break;
            case FLOAT_STORE_opcode:
            case DOUBLE_STORE_opcode:
                // Supported addressing modes are quite limited.
                Store.setAddress(s, asRegAddress(Store.getClearAddress(s), s, ir));
                Store.setOffset(s, asImmediateOrRegOffset(Store.getClearOffset(s), s, ir, true));
                break;
            case REF_LOAD_opcode:
                s.changeOperatorTo(VM.BuildFor32Addr ? INT_LOAD : LONG_LOAD);
                // Supported addressing modes are quite limited.
                Load.setAddress(s, asRegAddress(Load.getClearAddress(s), s, ir));
                Load.setOffset(s, asImmediateOrRegOffset(Load.getClearOffset(s), s, ir, true));
                break;
            case BYTE_LOAD_opcode:
            case UBYTE_LOAD_opcode:
            case SHORT_LOAD_opcode:
            case USHORT_LOAD_opcode:
            case INT_LOAD_opcode:
            case LONG_LOAD_opcode:
            case FLOAT_LOAD_opcode:
            case DOUBLE_LOAD_opcode:
                // Supported addressing modes are quite limited.
                Load.setAddress(s, asRegAddress(Load.getClearAddress(s), s, ir));
                Load.setOffset(s, asImmediateOrRegOffset(Load.getClearOffset(s), s, ir, true));
                break;
            case ATTEMPT_INT_opcode:
            case ATTEMPT_LONG_opcode:
            case ATTEMPT_ADDR_opcode:
                // On PowerPC, the value being stored must be in a register
                Attempt.setNewValue(s, asRegPolymorphic(Attempt.getClearNewValue(s), s, ir));
                // not used on powerpc.
                Attempt.setOldValue(s, null);
                // Supported addressing modes are quite limited.
                Attempt.setAddress(s, asRegAddress(Attempt.getClearAddress(s), s, ir));
                Attempt.setOffset(s, asRegOffset(Attempt.getClearOffset(s), s, ir));
                break;
            case PREPARE_INT_opcode:
            case PREPARE_LONG_opcode:
            case PREPARE_ADDR_opcode:
                // Supported addressing modes are quite limited.
                Prepare.setAddress(s, asRegAddress(Prepare.getClearAddress(s), s, ir));
                Prepare.setOffset(s, asRegOffset(Prepare.getClearOffset(s), s, ir));
                break;
            case LONG_MOVE_opcode:
                if (VM.BuildFor64Addr) {
                    s.changeOperatorTo(REF_MOVE);
                }
                break;
            case INT_MOVE_opcode:
                s.changeOperatorTo(REF_MOVE);
                break;
            case REF_COND_MOVE_opcode:
                s.changeOperatorTo(VM.BuildFor32Addr ? INT_COND_MOVE : LONG_COND_MOVE);
                break;
            case REF_IFCMP_opcode:
                s.changeOperatorTo(VM.BuildFor32Addr ? INT_IFCMP : LONG_IFCMP);
                // val1 can't be a constant, val2 must be small enough.
                IfCmp.setVal1(s, asRegPolymorphic(IfCmp.getClearVal1(s), s, ir));
                IfCmp.setVal2(s, asImmediateOrRegPolymorphic(IfCmp.getClearVal2(s), s, ir, true));
            case LONG_IFCMP_opcode:
                if (VM.BuildFor64Addr) {
                    // val1 can't be a constant, val2 must be small enough.
                    IfCmp.setVal1(s, asRegPolymorphic(IfCmp.getClearVal1(s), s, ir));
                    IfCmp.setVal2(s, asImmediateOrRegPolymorphic(IfCmp.getClearVal2(s), s, ir, true));
                }
                break;
            case INT_IFCMP_opcode:
                // val1 can't be a constant, val2 must be small enough.
                IfCmp.setVal1(s, asRegPolymorphic(IfCmp.getClearVal1(s), s, ir));
                IfCmp.setVal2(s, asImmediateOrRegPolymorphic(IfCmp.getClearVal2(s), s, ir, true));
                break;
            case INT_IFCMP2_opcode:
                // val1 can't be a constant, val2 must be small enough.
                IfCmp2.setVal1(s, asRegInt(IfCmp2.getClearVal1(s), s, ir));
                IfCmp2.setVal2(s, asImmediateOrRegInt(IfCmp2.getClearVal2(s), s, ir, true));
                break;
            case BOOLEAN_CMP_INT_opcode:
            case BOOLEAN_CMP_ADDR_opcode:
                // val2 must be small enough.
                BooleanCmp.setVal2(s, asImmediateOrRegPolymorphic(BooleanCmp.getClearVal2(s), s, ir, !BooleanCmp.getCond(s).isUNSIGNED()));
                break;
            case LONG_CMP_opcode:
                Binary.setVal1(s, asRegPolymorphic(Binary.getVal1(s), s, ir));
                Binary.setVal2(s, asRegPolymorphic(Binary.getVal2(s), s, ir));
                break;
            case LONG_ADD_opcode:
                if (VM.BuildFor64Addr) {
                    s.changeOperatorTo(REF_ADD);
                    Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, true));
                }
                break;
            case INT_ADD_opcode:
                s.changeOperatorTo(REF_ADD);
                Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, true));
                break;
            case REF_ADD_opcode:
                Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, true));
                break;
            case LONG_SUB_opcode:
                if (VM.BuildFor64Addr) {
                    s.changeOperatorTo(REF_SUB);
                    Binary.setVal1(s, asImmediateOrRegPolymorphic(Binary.getClearVal1(s), s, ir, true));
                // val2 isn't be constant (if it were, Simplifier would have
                // converted this into an ADD of -Val2).
                }
                break;
            case INT_SUB_opcode:
                s.changeOperatorTo(REF_SUB);
                Binary.setVal1(s, asImmediateOrRegPolymorphic(Binary.getClearVal1(s), s, ir, true));
                // converted this into an ADD of -Val2).
                break;
            case REF_SUB_opcode:
                Binary.setVal1(s, asImmediateOrRegPolymorphic(Binary.getClearVal1(s), s, ir, true));
                // converted this into an ADD of -Val2).
                break;
            case INT_MUL_opcode:
                Binary.setVal2(s, asImmediateOrRegInt(Binary.getClearVal2(s), s, ir, true));
                break;
            case LONG_MUL_opcode:
                if (VM.BuildFor64Addr) {
                    Binary.setVal2(s, asImmediateOrRegLong(Binary.getClearVal2(s), s, ir, true));
                }
                break;
            // seem to expect constant operands at all.
            case INT_REM_opcode:
            case INT_DIV_opcode:
                GuardedBinary.setVal1(s, asRegInt(GuardedBinary.getClearVal1(s), s, ir));
                GuardedBinary.setVal2(s, asRegInt(GuardedBinary.getClearVal2(s), s, ir));
                break;
            case LONG_REM_opcode:
            case LONG_DIV_opcode:
                if (VM.BuildFor64Addr) {
                    GuardedBinary.setVal1(s, asRegLong(GuardedBinary.getClearVal1(s), s, ir));
                    GuardedBinary.setVal2(s, asRegLong(GuardedBinary.getClearVal2(s), s, ir));
                }
                break;
            case LONG_NEG_opcode:
                if (VM.BuildFor64Addr) {
                    s.changeOperatorTo(REF_NEG);
                }
                break;
            case INT_NEG_opcode:
                s.changeOperatorTo(REF_NEG);
                break;
            case LONG_NOT_opcode:
                if (VM.BuildFor64Addr) {
                    s.changeOperatorTo(REF_NOT);
                }
                break;
            case INT_NOT_opcode:
                s.changeOperatorTo(REF_NOT);
                break;
            case LONG_AND_opcode:
                if (VM.BuildFor64Addr) {
                    s.changeOperatorTo(REF_AND);
                    // unsigned immediate
                    Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, false));
                }
                break;
            case INT_AND_opcode:
                s.changeOperatorTo(REF_AND);
                // unsigned immediate
                Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, false));
                break;
            case REF_AND_opcode:
                // unsigned immediate
                Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, false));
                break;
            case LONG_OR_opcode:
                if (VM.BuildFor64Addr) {
                    s.changeOperatorTo(REF_OR);
                    // unsigned immediate
                    Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, false));
                }
                break;
            case INT_OR_opcode:
                s.changeOperatorTo(REF_OR);
                // unsigned immediate
                Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, false));
                break;
            case REF_OR_opcode:
                // unsigned immediate
                Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, false));
                break;
            case LONG_XOR_opcode:
                if (VM.BuildFor64Addr) {
                    s.changeOperatorTo(REF_XOR);
                    // unsigned immediate
                    Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, false));
                }
                break;
            case INT_XOR_opcode:
                s.changeOperatorTo(REF_XOR);
                // unsigned immediate
                Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, false));
                break;
            case REF_XOR_opcode:
                // unsigned immediate
                Binary.setVal2(s, asImmediateOrRegPolymorphic(Binary.getClearVal2(s), s, ir, false));
                break;
            case REF_SHL_opcode:
                s.changeOperatorTo(VM.BuildFor32Addr ? INT_SHL : LONG_SHL);
                // Val2 could be a constant, but Val1 apparently can't be.
                Binary.setVal1(s, asRegPolymorphic(Binary.getClearVal1(s), s, ir));
                break;
            case LONG_SHL_opcode:
                if (VM.BuildFor64Addr) {
                    // Val2 could be a constant, but Val1 apparently can't be.
                    Binary.setVal1(s, asRegPolymorphic(Binary.getClearVal1(s), s, ir));
                }
                break;
            case INT_SHL_opcode:
                // Val2 could be a constant, but Val1 apparently can't be.
                Binary.setVal1(s, asRegPolymorphic(Binary.getClearVal1(s), s, ir));
                break;
            case REF_SHR_opcode:
                s.changeOperatorTo(VM.BuildFor32Addr ? INT_SHR : LONG_SHR);
                // Val2 could be a constant, but Val1 apparently can't be.
                Binary.setVal1(s, asRegPolymorphic(Binary.getClearVal1(s), s, ir));
                break;
            case LONG_SHR_opcode:
                if (VM.BuildFor64Addr) {
                    // Val2 could be a constant, but Val1 apparently can't be.
                    Binary.setVal1(s, asRegPolymorphic(Binary.getClearVal1(s), s, ir));
                }
                break;
            case INT_SHR_opcode:
                // Val2 could be a constant, but Val1 apparently can't be.
                Binary.setVal1(s, asRegPolymorphic(Binary.getClearVal1(s), s, ir));
                break;
            case REF_USHR_opcode:
                s.changeOperatorTo(VM.BuildFor32Addr ? INT_USHR : LONG_USHR);
                // Val2 could be a constant, but Val1 apparently can't be.
                Binary.setVal1(s, asRegPolymorphic(Binary.getClearVal1(s), s, ir));
                break;
            case LONG_USHR_opcode:
                if (VM.BuildFor64Addr) {
                    // Val2 could be a constant, but Val1 apparently can't be.
                    Binary.setVal1(s, asRegPolymorphic(Binary.getClearVal1(s), s, ir));
                }
                break;
            case INT_USHR_opcode:
                // Val2 could be a constant, but Val1 apparently can't be.
                Binary.setVal1(s, asRegPolymorphic(Binary.getClearVal1(s), s, ir));
                break;
            // Deal with Simplifier.CF_FLOAT or Simplifier.CF_DOUBLE being false
            case INT_2DOUBLE_opcode:
            case INT_2FLOAT_opcode:
            case INT_BITS_AS_FLOAT_opcode:
                Unary.setVal(s, asRegInt(Unary.getVal(s), s, ir));
                break;
            case ADDR_2INT_opcode:
                s.changeOperatorTo(VM.BuildFor32Addr ? REF_MOVE : LONG_2INT);
                break;
            case ADDR_2LONG_opcode:
                s.changeOperatorTo(VM.BuildFor32Addr ? INT_2LONG : REF_MOVE);
                break;
            case INT_2ADDRSigExt_opcode:
                s.changeOperatorTo(VM.BuildFor32Addr ? REF_MOVE : INT_2LONG);
                break;
            case INT_2ADDRZerExt_opcode:
                if (VM.BuildFor32Addr) {
                    s.changeOperatorTo(REF_MOVE);
                }
                break;
            case LONG_2ADDR_opcode:
                s.changeOperatorTo(VM.BuildFor64Addr ? REF_MOVE : LONG_2INT);
                break;
            case NULL_CHECK_opcode:
                NullCheck.setRef(s, asRegAddress(NullCheck.getClearRef(s), s, ir));
                break;
            // Force all call parameters to be in registers
            case SYSCALL_opcode:
            case CALL_opcode:
                {
                    int numArgs = Call.getNumberOfParams(s);
                    for (int i = 0; i < numArgs; i++) {
                        Call.setParam(s, i, asRegPolymorphic(Call.getClearParam(s, i), s, ir));
                    }
                }
                break;
            case RETURN_opcode:
                if (Return.hasVal(s)) {
                    Return.setVal(s, asRegPolymorphic(Return.getClearVal(s), s, ir));
                }
                break;
        }
    }
}
Also used : LongConstantOperand(org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand) StringConstantOperand(org.jikesrvm.compilers.opt.ir.operand.StringConstantOperand) LongConstantOperand(org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand) DoubleConstantOperand(org.jikesrvm.compilers.opt.ir.operand.DoubleConstantOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) CodeConstantOperand(org.jikesrvm.compilers.opt.ir.operand.CodeConstantOperand) NullConstantOperand(org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand) FloatConstantOperand(org.jikesrvm.compilers.opt.ir.operand.FloatConstantOperand) TIBConstantOperand(org.jikesrvm.compilers.opt.ir.operand.TIBConstantOperand) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) ClassConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ClassConstantOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) AddressConstantOperand(org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) ObjectConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ObjectConstantOperand) StringConstantOperand(org.jikesrvm.compilers.opt.ir.operand.StringConstantOperand) ConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ConstantOperand) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) Offset(org.vmmagic.unboxed.Offset) NullConstantOperand(org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) ClassConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ClassConstantOperand) DoubleConstantOperand(org.jikesrvm.compilers.opt.ir.operand.DoubleConstantOperand) ObjectConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ObjectConstantOperand) FloatConstantOperand(org.jikesrvm.compilers.opt.ir.operand.FloatConstantOperand) TIBConstantOperand(org.jikesrvm.compilers.opt.ir.operand.TIBConstantOperand) OptimizingCompilerException(org.jikesrvm.compilers.opt.OptimizingCompilerException) CodeConstantOperand(org.jikesrvm.compilers.opt.ir.operand.CodeConstantOperand)

Example 54 with Offset

use of org.vmmagic.unboxed.Offset in project JikesRVM by JikesRVM.

the class StackManager method insertExceptionalPrologue.

/**
 * prologue for the exceptional case.
 * (1) R0 is the only available scratch register.
 * (2) stack overflow check has to come first.
 */
void insertExceptionalPrologue() {
    if (VM.VerifyAssertions) {
        VM._assert((frameSize & (STACKFRAME_ALIGNMENT - 1)) == 0, "Stack frame alignment error");
    }
    if (frameSize >= 0x7ff0) {
        throw new OptimizingCompilerException("Stackframe size exceeded!");
    }
    PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet().asPPC();
    Register FP = phys.getFP();
    Register TR = phys.getTR();
    Register TSR = phys.getTSR();
    Register R0 = phys.getTemp();
    Register S1 = phys.getGPR(LAST_SCRATCH_GPR);
    boolean interruptible = ir.method.isInterruptible();
    boolean stackOverflow = interruptible;
    boolean yp = hasPrologueYieldpoint();
    Instruction ptr = ir.firstInstructionInCodeOrder().nextInstructionInCodeOrder();
    if (VM.VerifyAssertions)
        VM._assert(ptr.getOpcode() == IR_PROLOGUE_opcode);
    // Stack overflow check
    if (stackOverflow) {
        // R0 is fairly useless (can't be operand 1 of an addi or the base ptr
        // of a load) so, free up S1 for use by briefly saving its contents in the
        // return address slot of my caller's frame
        ptr.insertBefore(MIR_Store.create(PPC_STAddr, A(S1), A(FP), IC(STACKFRAME_RETURN_ADDRESS_OFFSET.toInt())));
        Offset offset = Entrypoints.stackLimitField.getOffset();
        if (VM.VerifyAssertions)
            VM._assert(fits(offset, 16));
        ptr.insertBefore(MIR_Load.create(PPC_LAddr, A(S1), A(phys.getTR()), IC(PPCMaskLower16(offset))));
        ptr.insertBefore(MIR_Binary.create(PPC_ADDI, A(R0), A(S1), IC(frameSize)));
        ptr.insertBefore(MIR_Load.create(PPC_LAddr, A(S1), A(FP), IC(STACKFRAME_RETURN_ADDRESS_OFFSET.toInt())));
        // Mutate the Prologue holder instruction into the trap
        MIR_Trap.mutate(ptr, PPC_TAddr, PowerPCTrapOperand.LESS(), A(FP), A(R0), TrapCodeOperand.StackOverflow());
        // advance ptr because we want the remaining instructions to come after
        // the trap
        ptr = ptr.nextInstructionInCodeOrder();
    } else {
        // no stack overflow test, so we must remove the IR_Prologue instruction
        Instruction next = ptr.nextInstructionInCodeOrder();
        ptr.remove();
        ptr = next;
    }
    // Buy stack frame, save LR, caller's FP
    ptr.insertBefore(MIR_Move.create(PPC_MFSPR, A(R0), A(phys.getLR())));
    ptr.insertBefore(MIR_StoreUpdate.create(PPC_STAddrU, A(FP), A(FP), IC(-frameSize)));
    ptr.insertBefore(MIR_Store.create(PPC_STAddr, A(R0), A(FP), IC(frameSize + STACKFRAME_RETURN_ADDRESS_OFFSET.toInt())));
    // Store cmid
    int cmid = ir.compiledMethod.getId();
    if (cmid <= 0x7fff) {
        ptr.insertBefore(MIR_Unary.create(PPC_LDI, I(R0), IC(cmid)));
    } else {
        ptr.insertBefore(MIR_Unary.create(PPC_LDIS, I(R0), IC(cmid >>> 16)));
        ptr.insertBefore(MIR_Binary.create(PPC_ORI, I(R0), I(R0), IC(cmid & 0xffff)));
    }
    ptr.insertBefore(MIR_Store.create(PPC_STW, I(R0), A(FP), IC(STACKFRAME_METHOD_ID_OFFSET.toInt())));
    // Now save the volatile/nonvolatile registers
    if (ir.compiledMethod.isSaveVolatile()) {
        saveVolatiles(ptr);
    }
    saveNonVolatiles(ptr);
    // Threadswitch
    if (yp) {
        Offset offset = Entrypoints.takeYieldpointField.getOffset();
        if (VM.VerifyAssertions)
            VM._assert(fits(offset, 16));
        ptr.insertBefore(MIR_Load.create(PPC_LInt, I(R0), A(TR), IC(PPCMaskLower16(offset))));
        ptr.insertBefore(MIR_Binary.create(PPC_CMPI, I(TSR), I(R0), IC(0)));
    }
}
Also used : Register(org.jikesrvm.compilers.opt.ir.Register) PhysicalRegisterSet(org.jikesrvm.compilers.opt.ir.ppc.PhysicalRegisterSet) GenericPhysicalRegisterSet(org.jikesrvm.compilers.opt.ir.GenericPhysicalRegisterSet) OptimizingCompilerException(org.jikesrvm.compilers.opt.OptimizingCompilerException) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) Offset(org.vmmagic.unboxed.Offset)

Example 55 with Offset

use of org.vmmagic.unboxed.Offset in project JikesRVM by JikesRVM.

the class StackManager method insertNormalPrologue.

/*
  * Insert the prologue.
  * The available scratch registers are normally: R0, S0, S1
  * However, if this is the prologue for a 'save volatile' frame,
  * then R0 is the only available scratch register.
  * The "normal" prologue must perform the following tasks:
  *    stack overflow check
  *    set TSR for the yieldpoint if there is a prologue yieldpoint instruction
  *    save lr
  *    store cmid
  *    buy stack frame
  *    store any used non volatiles
  * We schedule the prologue for this combination of operations,
  * since it is currently the common case.
  * When this changes, this code should be modifed accordingly.
  * The desired sequence is:
  *  1    mflr    00  # return addr
  *  2    l       S1 takeYieldpointOffset(PR)                # setting TSR for yield point
  *  3    stu     FP -frameSize(FP)                          # buy frame, save caller's fp
  *  4    l       S0 stackLimitOffset(S0)                    # stack overflow check
  *  5    <save used non volatiles>
  *  6    cmpi    TSR S1 0x0                                 # setting TSR for yield point (S1 is now free)
  *  7    lil     S1 CMID                                    # cmid
  *  8    st      00 STACKFRAME_RETURN_ADDRESS_OFFSET(FP)  # return addr (00 is now free)
  *  9    st      S1 STACKFRAME_METHOD_ID_OFFSET(FP)         # cmid
  *  10   tgt     S0, FP                                     # stack overflow check (already bought frame)
  */
/**
 * Schedule prologue for 'normal' case (see above)
 */
@Override
public void insertNormalPrologue() {
    PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet().asPPC();
    Register FP = phys.getFP();
    Register TR = phys.getTR();
    Register TSR = phys.getTSR();
    Register R0 = phys.getTemp();
    Register S0 = phys.getGPR(FIRST_SCRATCH_GPR);
    Register S1 = phys.getGPR(LAST_SCRATCH_GPR);
    boolean interruptible = ir.method.isInterruptible();
    boolean stackOverflow = interruptible;
    boolean yp = hasPrologueYieldpoint();
    int frameFixedSize = getFrameFixedSize();
    ir.compiledMethod.setFrameFixedSize(frameFixedSize);
    if (frameFixedSize >= STACK_SIZE_GUARD || ir.compiledMethod.isSaveVolatile()) {
        insertExceptionalPrologue();
        return;
    }
    Instruction ptr = ir.firstInstructionInCodeOrder().nextInstructionInCodeOrder();
    if (VM.VerifyAssertions)
        VM._assert(ptr.getOpcode() == IR_PROLOGUE_opcode);
    // 1
    ptr.insertBefore(MIR_Move.create(PPC_MFSPR, A(R0), A(phys.getLR())));
    if (yp) {
        Offset offset = Entrypoints.takeYieldpointField.getOffset();
        if (VM.VerifyAssertions)
            VM._assert(fits(offset, 16));
        // 2
        ptr.insertBefore(MIR_Load.create(PPC_LInt, I(S1), A(TR), IC(PPCMaskLower16(offset))));
    }
    // 3
    ptr.insertBefore(MIR_StoreUpdate.create(PPC_STAddrU, A(FP), A(FP), IC(-frameSize)));
    if (stackOverflow) {
        Offset offset = Entrypoints.stackLimitField.getOffset();
        if (VM.VerifyAssertions)
            VM._assert(fits(offset, 16));
        // 4
        ptr.insertBefore(MIR_Load.create(PPC_LAddr, A(S0), A(phys.getTR()), IC(PPCMaskLower16(offset))));
    }
    // Now add any instructions to save the volatiles and nonvolatiles (5)
    saveNonVolatiles(ptr);
    if (yp) {
        // 6
        ptr.insertBefore(MIR_Binary.create(PPC_CMPI, I(TSR), I(S1), IC(0)));
    }
    int cmid = ir.compiledMethod.getId();
    if (cmid <= 0x7fff) {
        // 7
        ptr.insertBefore(MIR_Unary.create(PPC_LDI, I(S1), IC(cmid)));
    } else {
        // 7 (a)
        ptr.insertBefore(MIR_Unary.create(PPC_LDIS, I(S1), IC(cmid >>> 16)));
        // 7 (b)
        ptr.insertBefore(MIR_Binary.create(PPC_ORI, I(S1), I(S1), IC(cmid & 0xffff)));
    }
    ptr.insertBefore(MIR_Store.create(PPC_STAddr, A(R0), A(FP), // 8
    IC(frameSize + STACKFRAME_RETURN_ADDRESS_OFFSET.toInt())));
    // 9
    ptr.insertBefore(MIR_Store.create(PPC_STW, I(S1), A(FP), IC(STACKFRAME_METHOD_ID_OFFSET.toInt())));
    if (stackOverflow) {
        // Mutate the Prologue instruction into the trap
        MIR_Trap.mutate(ptr, PPC_TAddr, PowerPCTrapOperand.GREATER(), A(S0), A(FP), // 10
        TrapCodeOperand.StackOverflow());
    } else {
        // no stack overflow test, so we remove the IR_Prologue instruction
        ptr.remove();
    }
}
Also used : Register(org.jikesrvm.compilers.opt.ir.Register) PhysicalRegisterSet(org.jikesrvm.compilers.opt.ir.ppc.PhysicalRegisterSet) GenericPhysicalRegisterSet(org.jikesrvm.compilers.opt.ir.GenericPhysicalRegisterSet) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) Offset(org.vmmagic.unboxed.Offset)

Aggregations

Offset (org.vmmagic.unboxed.Offset)215 Address (org.vmmagic.unboxed.Address)48 Inline (org.vmmagic.pragma.Inline)38 Entrypoint (org.vmmagic.pragma.Entrypoint)32 ObjectReference (org.vmmagic.unboxed.ObjectReference)21 CompiledMethod (org.jikesrvm.compilers.common.CompiledMethod)20 TypeReference (org.jikesrvm.classloader.TypeReference)17 RVMField (org.jikesrvm.classloader.RVMField)14 ForwardReference (org.jikesrvm.compilers.common.assembler.ForwardReference)13 OptCompiledMethod (org.jikesrvm.compilers.opt.runtimesupport.OptCompiledMethod)13 NoInline (org.vmmagic.pragma.NoInline)13 RVMMethod (org.jikesrvm.classloader.RVMMethod)11 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)10 Word (org.vmmagic.unboxed.Word)10 Instruction (org.jikesrvm.compilers.opt.ir.Instruction)9 IntConstantOperand (org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand)9 RVMType (org.jikesrvm.classloader.RVMType)8 Register (org.jikesrvm.compilers.opt.ir.Register)8 RVMClass (org.jikesrvm.classloader.RVMClass)7 Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)7