Search in sources :

Example 31 with LocationOperand

use of org.jikesrvm.compilers.opt.ir.operand.LocationOperand in project JikesRVM by JikesRVM.

the class BURS_Helpers method GET_EXCEPTION_OBJECT.

/**
 * Emit code to get a caught exception object into a register
 */
protected final void GET_EXCEPTION_OBJECT(Instruction s) {
    burs.ir.stackManager.forceFrameAllocation();
    int offset = burs.ir.stackManager.allocateSpaceForCaughtException();
    Register FP = regpool.getPhysicalRegisterSet().asPPC().getFP();
    LocationOperand loc = new LocationOperand(-offset);
    EMIT(MIR_Load.mutate(s, PPC_LAddr, Nullary.getClearResult(s), A(FP), IC(offset), loc, TG()));
}
Also used : LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) Register(org.jikesrvm.compilers.opt.ir.Register) OsrPoint(org.jikesrvm.compilers.opt.ir.OsrPoint)

Example 32 with LocationOperand

use of org.jikesrvm.compilers.opt.ir.operand.LocationOperand in project JikesRVM by JikesRVM.

the class ComplexLIR2MIRExpansion method float_2long.

private static Instruction float_2long(Instruction s, IR ir) {
    Instruction nextInstr = s.nextInstructionInCodeOrder();
    while (Label.conforms(nextInstr) || BBend.conforms(nextInstr)) {
        nextInstr = nextInstr.nextInstructionInCodeOrder();
    }
    if (VM.BuildFor32Addr) {
        // we need 6 basic blocks (in code order)
        // 1: the current block that does a test to see if this is a regular f2l or
        // branches to the maxint/NaN case
        // 2: a block to perform a regular f2l
        // 3: a block to test for NaN
        // 4: a block to perform give maxint
        // 5: a block to perform NaN
        // 6: the next basic block
        BasicBlock testBB = s.getBasicBlock();
        BasicBlock nextBB = testBB.splitNodeAt(s, ir);
        ir.cfg.linkInCodeOrder(testBB, nextBB);
        BasicBlock nanBB = testBB.splitNodeAt(s, ir);
        ir.cfg.linkInCodeOrder(testBB, nanBB);
        BasicBlock maxintBB = testBB.splitNodeAt(s, ir);
        ir.cfg.linkInCodeOrder(testBB, maxintBB);
        BasicBlock nanTestBB = testBB.splitNodeAt(s, ir);
        ir.cfg.linkInCodeOrder(testBB, nanTestBB);
        BasicBlock f2lBB = testBB.splitNodeAt(s, ir);
        ir.cfg.linkInCodeOrder(testBB, f2lBB);
        // Move the maxlongFloat value and the value into x87 registers and compare and
        // branch if they are <= or unordered.
        RegisterOperand resultHi = Unary.getResult(s).copyRO();
        resultHi.setType(TypeReference.Int);
        RegisterOperand resultLo = new RegisterOperand(ir.regpool.getSecondReg(resultHi.getRegister()), TypeReference.Int);
        RegisterOperand value = Unary.getVal(s).asRegister().copyRO();
        RegisterOperand cw = ir.regpool.makeTempInt();
        MemoryOperand maxlong = BURS_Helpers.loadFromJTOC(ir, Entrypoints.maxlongFloatField.getOffset(), (byte) 4);
        RegisterOperand st0 = new RegisterOperand(phys(ir).getST0(), TypeReference.Float);
        RegisterOperand st1 = new RegisterOperand(phys(ir).getST1(), TypeReference.Float);
        int offset = -ir.stackManager.allocateSpaceForConversion();
        StackLocationOperand slLo = new StackLocationOperand(true, offset, 4);
        StackLocationOperand slHi = new StackLocationOperand(true, offset + 4, 4);
        StackLocationOperand sl = new StackLocationOperand(true, offset, 8);
        MemoryOperand scratchLo = new MemoryOperand(ir.regpool.makeTROp(), null, (byte) 0, Entrypoints.scratchStorageField.getOffset(), (byte) 4, new LocationOperand(Entrypoints.scratchStorageField), null);
        MemoryOperand scratchHi = new MemoryOperand(ir.regpool.makeTROp(), null, (byte) 0, Entrypoints.scratchStorageField.getOffset().plus(4), (byte) 4, new LocationOperand(Entrypoints.scratchStorageField), null);
        s.insertBefore(CPOS(s, MIR_Move.create(IA32_MOVSS, slLo, value)));
        s.insertBefore(CPOS(s, MIR_Move.create(IA32_FLD, st0, slLo.copy())));
        s.insertBefore(CPOS(s, MIR_Move.create(IA32_FLD, st0.copyRO(), maxlong)));
        MIR_Compare.mutate(s, IA32_FUCOMIP, st0.copyRO(), st1);
        testBB.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, IA32ConditionOperand.LLE(), nanTestBB.makeJumpTarget(), BranchProfileOperand.unlikely())));
        testBB.insertOut(f2lBB);
        testBB.insertOut(nanTestBB);
        // Convert float to long knowing that if the value is < min long the Intel
        // unspecified result is min long
        // TODO: this would be a lot simpler and faster with SSE3's FISTTP instruction
        f2lBB.appendInstruction(CPOS(s, MIR_UnaryNoRes.create(IA32_FNSTCW, scratchLo.copy())));
        f2lBB.appendInstruction(CPOS(s, MIR_Unary.create(IA32_MOVZX__W, cw, scratchLo.copy())));
        f2lBB.appendInstruction(CPOS(s, MIR_BinaryAcc.create(IA32_OR, cw.copyRO(), IC(0xC00))));
        f2lBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, scratchHi, cw.copyRO())));
        f2lBB.appendInstruction(CPOS(s, MIR_UnaryNoRes.create(IA32_FLDCW, scratchHi.copy())));
        f2lBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_FISTP, sl, st0.copyRO())));
        f2lBB.appendInstruction(CPOS(s, MIR_UnaryNoRes.create(IA32_FLDCW, scratchLo.copy())));
        f2lBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, resultLo, slLo.copy())));
        f2lBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, resultHi, slHi)));
        f2lBB.appendInstruction(CPOS(s, MIR_Branch.create(IA32_JMP, nextBB.makeJumpTarget())));
        f2lBB.insertOut(nextBB);
        // Did the compare find a NaN or a maximum integer?
        nanTestBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_FSTP, st0.copyRO(), st0.copyRO())));
        nanTestBB.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, IA32ConditionOperand.PE(), nanBB.makeJumpTarget(), BranchProfileOperand.unlikely())));
        nanTestBB.insertOut(nanBB);
        nanTestBB.insertOut(maxintBB);
        // Value was >= max long
        maxintBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, resultLo.copyRO(), IC((int) Long.MAX_VALUE))));
        maxintBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, resultHi.copyRO(), IC((int) (Long.MAX_VALUE >>> 32)))));
        maxintBB.appendInstruction(CPOS(s, MIR_Branch.create(IA32_JMP, nextBB.makeJumpTarget())));
        maxintBB.insertOut(nextBB);
        // In case of NaN result is 0
        nanBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, resultLo.copyRO(), IC(0))));
        nanBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, resultHi.copyRO(), IC(0))));
        nanBB.insertOut(nextBB);
    } else {
        // we need 4 basic blocks (in code order)
        // 1: the current block which includes a test for NaN
        // 2: a block to perform regular f2l
        // 3: a block to handle NaN (which gives a result of 0)
        // 4: the next basic block
        BasicBlock testBB = s.getBasicBlock();
        BasicBlock nextBB = testBB.splitNodeAt(s, ir);
        ir.cfg.linkInCodeOrder(testBB, nextBB);
        BasicBlock nanBB = testBB.splitNodeAt(s, ir);
        ir.cfg.linkInCodeOrder(testBB, nanBB);
        BasicBlock f2lBB = testBB.splitNodeAt(s, ir);
        ir.cfg.linkInCodeOrder(testBB, f2lBB);
        RegisterOperand result = Unary.getResult(s).copyRO();
        RegisterOperand value = Unary.getVal(s).asRegister().copyRO();
        RegisterOperand adjustment = ir.regpool.makeTempInt();
        testBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, adjustment.copy(), IC(0))));
        MemoryOperand maxlong = BURS_Helpers.loadFromJTOC(ir, Entrypoints.maxlongFloatField.getOffset(), (byte) 4);
        MIR_Compare.mutate(s, IA32_UCOMISS, value.copy(), maxlong);
        testBB.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, IA32ConditionOperand.PE(), nanBB.makeJumpTarget(), BranchProfileOperand.unlikely())));
        testBB.insertOut(f2lBB);
        testBB.insertOut(nanBB);
        f2lBB.appendInstruction(CPOS(s, MIR_Set.create(IA32_SET__B, adjustment.copy(), IA32ConditionOperand.LGE())));
        f2lBB.appendInstruction(CPOS(s, MIR_Unary.create(IA32_CVTTSS2SI, result.copy(), value.copy())));
        f2lBB.appendInstruction(CPOS(s, MIR_BinaryAcc.create(IA32_SUB, result.copy(), adjustment.copy())));
        f2lBB.appendInstruction(CPOS(s, MIR_Branch.create(IA32_JMP, nextBB.makeJumpTarget())));
        f2lBB.insertOut(nextBB);
        // In case of NaN result is 0.
        nanBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, result.copyRO(), LC(0))));
        nanBB.insertOut(nextBB);
    }
    return nextInstr;
}
Also used : StackLocationOperand(org.jikesrvm.compilers.opt.ir.operand.StackLocationOperand) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) MemoryOperand(org.jikesrvm.compilers.opt.ir.operand.MemoryOperand) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) StackLocationOperand(org.jikesrvm.compilers.opt.ir.operand.StackLocationOperand)

Example 33 with LocationOperand

use of org.jikesrvm.compilers.opt.ir.operand.LocationOperand in project JikesRVM by JikesRVM.

the class NormalizeConstants method perform.

/**
 * Only thing we do for IA32 is to restrict the usage of
 * String, Float, and Double constants.  The rules are prepared
 * to deal with everything else.
 *
 * @param ir IR to normalize
 */
public static void perform(IR ir) {
    for (Instruction s = ir.firstInstructionInCodeOrder(); s != null; s = s.nextInstructionInCodeOrder()) {
        // Get 'large' constants into a form the the 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) {
                        ObjectConstantOperand oc = (ObjectConstantOperand) use;
                        if (oc.isMovableObjectConstant()) {
                            RegisterOperand rop = ir.regpool.makeTemp(use.getType());
                            Operand jtoc = ir.regpool.makeJTOCOp();
                            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(IA32_REF_LOAD, rop, jtoc, wordOperandForReference(offset.toWord()), loc));
                            s.putOperand(idx, rop.copyD2U());
                        } else {
                            // Ensure object is in JTOC to keep it alive
                            Statics.findOrCreateObjectLiteral(oc.value);
                            s.putOperand(idx, wordOperandForReference(Magic.objectAsAddress(oc.value).toWord()));
                        }
                    } else if (use instanceof DoubleConstantOperand) {
                        RegisterOperand rop = ir.regpool.makeTemp(TypeReference.Double);
                        Operand jtoc = ir.regpool.makeJTOCOp();
                        DoubleConstantOperand dc = (DoubleConstantOperand) use.copy();
                        if (dc.offset.isZero()) {
                            dc.offset = Offset.fromIntSignExtend(Statics.findOrCreateLongSizeLiteral(Double.doubleToLongBits(dc.value)));
                        }
                        s.insertBefore(Binary.create(MATERIALIZE_FP_CONSTANT, rop, jtoc, dc));
                        s.putOperand(idx, rop.copyD2U());
                    } else if (use instanceof FloatConstantOperand) {
                        RegisterOperand rop = ir.regpool.makeTemp(TypeReference.Float);
                        Operand jtoc = ir.regpool.makeJTOCOp();
                        FloatConstantOperand fc = (FloatConstantOperand) use.copy();
                        if (fc.offset.isZero()) {
                            fc.offset = Offset.fromIntSignExtend(Statics.findOrCreateIntSizeLiteral(Float.floatToIntBits(fc.value)));
                        }
                        s.insertBefore(Binary.create(MATERIALIZE_FP_CONSTANT, rop, jtoc, fc));
                        s.putOperand(idx, rop.copyD2U());
                    } else if (use instanceof NullConstantOperand) {
                        s.putOperand(idx, wordOperandForReference(Word.zero()));
                    } else if (use instanceof AddressConstantOperand) {
                        s.putOperand(idx, wordOperandForReference(((AddressConstantOperand) use).value.toWord()));
                    } else if (use instanceof TIBConstantOperand) {
                        RegisterOperand rop = ir.regpool.makeTemp(TypeReference.TIB);
                        Operand jtoc = ir.regpool.makeJTOCOp();
                        Offset offset = ((TIBConstantOperand) use).value.getTibOffset();
                        LocationOperand loc = new LocationOperand(offset);
                        s.insertBefore(Load.create(IA32_REF_LOAD, rop, jtoc, wordOperandForReference(offset.toWord()), 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(IA32_REF_LOAD, rop, jtoc, wordOperandForReference(offset.toWord()), loc));
                        s.putOperand(idx, rop.copyD2U());
                    }
                }
            }
        }
    }
}
Also used : StringConstantOperand(org.jikesrvm.compilers.opt.ir.operand.StringConstantOperand) AddressConstantOperand(org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand) NullConstantOperand(org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand) FloatConstantOperand(org.jikesrvm.compilers.opt.ir.operand.FloatConstantOperand) StringConstantOperand(org.jikesrvm.compilers.opt.ir.operand.StringConstantOperand) TIBConstantOperand(org.jikesrvm.compilers.opt.ir.operand.TIBConstantOperand) LongConstantOperand(org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand) DoubleConstantOperand(org.jikesrvm.compilers.opt.ir.operand.DoubleConstantOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) ClassConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ClassConstantOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) CodeConstantOperand(org.jikesrvm.compilers.opt.ir.operand.CodeConstantOperand) ObjectConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ObjectConstantOperand) AddressConstantOperand(org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand) 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 34 with LocationOperand

use of org.jikesrvm.compilers.opt.ir.operand.LocationOperand in project JikesRVM by JikesRVM.

the class ConvertToLowLevelIR method convert.

/**
 * Converts the given HIR to LIR.
 *
 * @param ir IR to convert
 * @param options the options for the conversion
 */
static void convert(IR ir, OptOptions options) {
    boolean didArrayStoreCheck = false;
    for (Instruction s = ir.firstInstructionInCodeOrder(); s != null; s = s.nextInstructionInCodeOrder()) {
        switch(s.getOpcode()) {
            case GETSTATIC_opcode:
                {
                    LocationOperand loc = GetStatic.getClearLocation(s);
                    RegisterOperand result = GetStatic.getClearResult(s);
                    Operand address = ir.regpool.makeJTOCOp();
                    Operand offset = GetStatic.getClearOffset(s);
                    Load.mutate(s, IRTools.getLoadOp(loc.getFieldRef(), true), result, address, offset, loc);
                }
                break;
            case PUTSTATIC_opcode:
                {
                    LocationOperand loc = PutStatic.getClearLocation(s);
                    Operand value = PutStatic.getClearValue(s);
                    Operand address = ir.regpool.makeJTOCOp();
                    Operand offset = PutStatic.getClearOffset(s);
                    Store.mutate(s, IRTools.getStoreOp(loc.getFieldRef(), true), value, address, offset, loc);
                }
                break;
            case PUTFIELD_opcode:
                {
                    LocationOperand loc = PutField.getClearLocation(s);
                    Operand value = PutField.getClearValue(s);
                    Operand address = PutField.getClearRef(s);
                    Operand offset = PutField.getClearOffset(s);
                    Store.mutate(s, IRTools.getStoreOp(loc.getFieldRef(), false), value, address, offset, loc, PutField.getClearGuard(s));
                }
                break;
            case GETFIELD_opcode:
                {
                    LocationOperand loc = GetField.getClearLocation(s);
                    RegisterOperand result = GetField.getClearResult(s);
                    Operand address = GetField.getClearRef(s);
                    Operand offset = GetField.getClearOffset(s);
                    Load.mutate(s, IRTools.getLoadOp(loc.getFieldRef(), false), result, address, offset, loc, GetField.getClearGuard(s));
                }
                break;
            case INT_ALOAD_opcode:
                doArrayLoad(s, ir, INT_LOAD, 2);
                break;
            case LONG_ALOAD_opcode:
                doArrayLoad(s, ir, LONG_LOAD, 3);
                break;
            case FLOAT_ALOAD_opcode:
                doArrayLoad(s, ir, FLOAT_LOAD, 2);
                break;
            case DOUBLE_ALOAD_opcode:
                doArrayLoad(s, ir, DOUBLE_LOAD, 3);
                break;
            case REF_ALOAD_opcode:
                doArrayLoad(s, ir, REF_LOAD, LOG_BYTES_IN_ADDRESS);
                break;
            case BYTE_ALOAD_opcode:
                doArrayLoad(s, ir, BYTE_LOAD, 0);
                break;
            case UBYTE_ALOAD_opcode:
                doArrayLoad(s, ir, UBYTE_LOAD, 0);
                break;
            case USHORT_ALOAD_opcode:
                doArrayLoad(s, ir, USHORT_LOAD, 1);
                break;
            case SHORT_ALOAD_opcode:
                doArrayLoad(s, ir, SHORT_LOAD, 1);
                break;
            case INT_ASTORE_opcode:
                doArrayStore(s, ir, INT_STORE, 2);
                break;
            case LONG_ASTORE_opcode:
                doArrayStore(s, ir, LONG_STORE, 3);
                break;
            case FLOAT_ASTORE_opcode:
                doArrayStore(s, ir, FLOAT_STORE, 2);
                break;
            case DOUBLE_ASTORE_opcode:
                doArrayStore(s, ir, DOUBLE_STORE, 3);
                break;
            case REF_ASTORE_opcode:
                doArrayStore(s, ir, REF_STORE, LOG_BYTES_IN_ADDRESS);
                break;
            case BYTE_ASTORE_opcode:
                doArrayStore(s, ir, BYTE_STORE, 0);
                break;
            case SHORT_ASTORE_opcode:
                doArrayStore(s, ir, SHORT_STORE, 1);
                break;
            case CALL_opcode:
                s = callHelper(s, ir);
                break;
            case SYSCALL_opcode:
                // a sequence of loads off the BootRecord to find the appropriate field.
                if (Call.getMethod(s) != null) {
                    expandSysCallTarget(s, ir);
                }
                break;
            case TABLESWITCH_opcode:
                s = tableswitch(s, ir);
                break;
            case LOOKUPSWITCH_opcode:
                s = lookup(s, ir);
                break;
            case OBJARRAY_STORE_CHECK_opcode:
                s = DynamicTypeCheckExpansion.arrayStoreCheck(s, ir, true);
                didArrayStoreCheck = true;
                break;
            case OBJARRAY_STORE_CHECK_NOTNULL_opcode:
                s = DynamicTypeCheckExpansion.arrayStoreCheck(s, ir, false);
                didArrayStoreCheck = true;
                break;
            case CHECKCAST_opcode:
            case CHECKCAST_UNRESOLVED_opcode:
                s = DynamicTypeCheckExpansion.checkcast(s, ir);
                break;
            case CHECKCAST_NOTNULL_opcode:
                s = DynamicTypeCheckExpansion.checkcastNotNull(s, ir);
                break;
            case MUST_IMPLEMENT_INTERFACE_opcode:
                s = DynamicTypeCheckExpansion.mustImplementInterface(s, ir);
                break;
            case IG_CLASS_TEST_opcode:
                IfCmp.mutate(s, REF_IFCMP, ir.regpool.makeTempValidation(), getTIB(s, ir, InlineGuard.getClearValue(s), InlineGuard.getClearGuard(s)), getTIB(s, ir, InlineGuard.getGoal(s).asType()), ConditionOperand.NOT_EQUAL(), InlineGuard.getClearTarget(s), InlineGuard.getClearBranchProfile(s));
                break;
            case IG_METHOD_TEST_opcode:
                {
                    MethodOperand methOp = InlineGuard.getClearGoal(s).asMethod();
                    Operand t1 = getTIB(s, ir, InlineGuard.getClearValue(s), InlineGuard.getClearGuard(s));
                    Operand t2 = getTIB(s, ir, methOp.getTarget().getDeclaringClass());
                    IfCmp.mutate(s, REF_IFCMP, ir.regpool.makeTempValidation(), getInstanceMethod(s, ir, t1, methOp.getTarget()), getInstanceMethod(s, ir, t2, methOp.getTarget()), ConditionOperand.NOT_EQUAL(), InlineGuard.getClearTarget(s), InlineGuard.getClearBranchProfile(s));
                    break;
                }
            case INSTANCEOF_opcode:
            case INSTANCEOF_UNRESOLVED_opcode:
                s = DynamicTypeCheckExpansion.instanceOf(s, ir);
                break;
            case INSTANCEOF_NOTNULL_opcode:
                s = DynamicTypeCheckExpansion.instanceOfNotNull(s, ir);
                break;
            case INT_ZERO_CHECK_opcode:
                {
                    TrapIf.mutate(s, TRAP_IF, ZeroCheck.getClearGuardResult(s), ZeroCheck.getClearValue(s), IC(0), ConditionOperand.EQUAL(), TrapCodeOperand.DivByZero());
                }
                break;
            case LONG_ZERO_CHECK_opcode:
                {
                    TrapIf.mutate(s, TRAP_IF, ZeroCheck.getClearGuardResult(s), ZeroCheck.getClearValue(s), LC(0), ConditionOperand.EQUAL(), TrapCodeOperand.DivByZero());
                }
                break;
            case BOUNDS_CHECK_opcode:
                {
                    // get array_length from array_ref
                    RegisterOperand array_length = InsertGuardedUnary(s, ir, ARRAYLENGTH, TypeReference.Int, BoundsCheck.getClearRef(s), BoundsCheck.getClearGuard(s));
                    // In UN-signed comparison, a negative index will look like a very
                    // large positive number, greater than array length.
                    // Thus length LLT index is false iff 0 <= index <= length
                    TrapIf.mutate(s, TRAP_IF, BoundsCheck.getClearGuardResult(s), array_length.copyD2U(), BoundsCheck.getClearIndex(s), ConditionOperand.LOWER_EQUAL(), TrapCodeOperand.ArrayBounds());
                }
                break;
            case RESOLVE_MEMBER_opcode:
                s = resolveMember(s, ir);
                break;
            default:
                break;
        }
    }
    // Eliminate possible redundant trap block from array store checks
    if (didArrayStoreCheck) {
        branchOpts.perform(ir, true);
    }
}
Also used : LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) TypeOperand(org.jikesrvm.compilers.opt.ir.operand.TypeOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) TIBConstantOperand(org.jikesrvm.compilers.opt.ir.operand.TIBConstantOperand) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) AddressConstantOperand(org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) TrapCodeOperand(org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand) BranchOperand(org.jikesrvm.compilers.opt.ir.operand.BranchOperand) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand)

Example 35 with LocationOperand

use of org.jikesrvm.compilers.opt.ir.operand.LocationOperand in project JikesRVM by JikesRVM.

the class DynamicTypeCheckExpansion method generateValueProducingTypeCheck.

/**
 * Generate a value-producing dynamic type check.
 * This routine assumes that the CFG and code order are
 * already correctly established.
 * This routine must either remove s or mutuate it.
 *
 * @param s        The Instruction that is to be replaced by
 *                  a value producing type check
 * @param ir       The IR containing the instruction to be expanded.
 * @param RHSobj   The RegisterOperand containing the rhs object.
 * @param LHStype  The RVMType to be tested against.
 * @param RHStib   The Operand containing the TIB of the rhs.
 * @param result   The RegisterOperand that the result of dynamic
 *                 type check is to be stored in.
 * @return the opt instruction immediately before the
 *         instruction to continue expansion.
 */
private static Instruction generateValueProducingTypeCheck(Instruction s, IR ir, Operand RHSobj, TypeReference LHStype, Operand RHStib, RegisterOperand result) {
    // Is LHStype a class?
    if (LHStype.isClassType()) {
        RVMClass LHSclass = (RVMClass) LHStype.peekType();
        if (LHSclass != null && LHSclass.isResolved()) {
            // resolved class or interface
            if (LHSclass.isInterface()) {
                // A resolved interface (case 4)
                int interfaceIndex = LHSclass.getDoesImplementIndex();
                int interfaceMask = LHSclass.getDoesImplementBitMask();
                RegisterOperand doesImpl = InsertUnary(s, ir, GET_DOES_IMPLEMENT_FROM_TIB, TypeReference.IntArray, RHStib);
                RegisterOperand entry = InsertLoadOffset(s, ir, INT_LOAD, TypeReference.Int, doesImpl, Offset.fromIntZeroExtend(interfaceIndex << 2), new LocationOperand(TypeReference.Int), TG());
                RegisterOperand bit = insertBinary(s, ir, INT_AND, TypeReference.Int, entry, IC(interfaceMask));
                // save to use the cheaper ADDR version of BOOLEAN_CMP
                s.insertBefore(BooleanCmp.create(BOOLEAN_CMP_ADDR, result, bit, AC(Address.zero()), ConditionOperand.NOT_EQUAL(), new BranchProfileOperand()));
                if (DynamicTypeCheck.MIN_DOES_IMPLEMENT_SIZE <= interfaceIndex) {
                    RegisterOperand doesImplLength = InsertGuardedUnary(s, ir, ARRAYLENGTH, TypeReference.Int, doesImpl.copy(), TG());
                    RegisterOperand boundscheck = ir.regpool.makeTempInt();
                    // save to use the cheaper ADDR version of BOOLEAN_CMP
                    s.insertBefore(BooleanCmp.create(BOOLEAN_CMP_ADDR, boundscheck, doesImplLength, AC(Address.fromIntSignExtend(interfaceIndex)), ConditionOperand.GREATER(), new BranchProfileOperand()));
                    s.insertBefore(Binary.create(INT_AND, result.copyD2D(), result.copyD2U(), boundscheck.copyD2U()));
                }
                Instruction continueAt = s.prevInstructionInCodeOrder();
                s.remove();
                return continueAt;
            } else {
                // A resolved class (cases 5 and 6 in DynamicTypeCheck)
                if (LHSclass.isFinal()) {
                    // For a final class, we can do a PTR compare of
                    // rhsTIB and the TIB of the class
                    Operand classTIB = getTIB(s, ir, LHSclass);
                    BooleanCmp.mutate(s, BOOLEAN_CMP_ADDR, result, RHStib, classTIB, ConditionOperand.EQUAL(), new BranchProfileOperand());
                    return s.prevInstructionInCodeOrder();
                } else {
                    // Do the full blown case 5 or 6 typecheck.
                    int LHSDepth = LHSclass.getTypeDepth();
                    int LHSId = LHSclass.getId();
                    RegisterOperand superclassIds = InsertUnary(s, ir, GET_SUPERCLASS_IDS_FROM_TIB, TypeReference.ShortArray, RHStib);
                    RegisterOperand refCandidate = InsertLoadOffset(s, ir, USHORT_LOAD, TypeReference.Short, superclassIds, Offset.fromIntZeroExtend(LHSDepth << 1), new LocationOperand(TypeReference.Short), TG());
                    // save to use the cheaper ADDR version of BOOLEAN_CMP
                    s.insertBefore(BooleanCmp.create(BOOLEAN_CMP_ADDR, result, refCandidate, AC(Address.fromIntZeroExtend(LHSId)), ConditionOperand.EQUAL(), new BranchProfileOperand()));
                    if (DynamicTypeCheck.MIN_SUPERCLASS_IDS_SIZE <= LHSDepth) {
                        RegisterOperand superclassIdsLength = InsertGuardedUnary(s, ir, ARRAYLENGTH, TypeReference.Int, superclassIds.copyD2U(), TG());
                        RegisterOperand boundscheck = ir.regpool.makeTempInt();
                        // save to use the cheaper ADDR version of BOOLEAN_CMP
                        s.insertBefore(BooleanCmp.create(BOOLEAN_CMP_ADDR, boundscheck, superclassIdsLength, AC(Address.fromIntSignExtend(LHSDepth)), ConditionOperand.GREATER(), new BranchProfileOperand()));
                        s.insertBefore(Binary.create(INT_AND, result.copyD2D(), result.copyD2U(), boundscheck.copyD2U()));
                    }
                    Instruction continueAt = s.prevInstructionInCodeOrder();
                    s.remove();
                    return continueAt;
                }
            }
        } else {
            // A non-resolved class or interface.
            // We expect these to be extremely uncommon in opt code in AOS.
            // Mutate s into a call to RuntimeEntrypoints.instanceOf
            RVMMethod target = Entrypoints.instanceOfMethod;
            Call.mutate2(s, CALL, result, AC(target.getOffset()), MethodOperand.STATIC(target), RHSobj, IC(LHStype.getId()));
            return callHelper(s, ir);
        }
    }
    if (LHStype.isArrayType()) {
        // Case 2 of DynamicTypeCheck: LHS is an array.
        RVMArray LHSArray = (RVMArray) LHStype.peekType();
        if (LHSArray != null) {
            RVMType innermostElementType = LHSArray.getInnermostElementType();
            if (innermostElementType.isPrimitiveType() || innermostElementType.isUnboxedType() || (innermostElementType.asClass().isResolved() && innermostElementType.asClass().isFinal())) {
                // [^k of primitive or [^k of final class. Just like final classes,
                // a PTR compare of rhsTIB and the TIB of the class gives the answer.
                Operand classTIB = getTIB(s, ir, LHSArray);
                BooleanCmp.mutate(s, BOOLEAN_CMP_ADDR, result, RHStib, classTIB, ConditionOperand.EQUAL(), new BranchProfileOperand());
                return s;
            }
        }
        // and do the real work there.
        return convertToBranchingTypeCheck(s, ir, RHSobj, LHStype, RHStib, result);
    }
    OptimizingCompilerException.UNREACHABLE();
    return null;
}
Also used : RVMMethod(org.jikesrvm.classloader.RVMMethod) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) 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) NullConstantOperand(org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) TrapCodeOperand(org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) RVMArray(org.jikesrvm.classloader.RVMArray) RVMType(org.jikesrvm.classloader.RVMType) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) RVMClass(org.jikesrvm.classloader.RVMClass)

Aggregations

LocationOperand (org.jikesrvm.compilers.opt.ir.operand.LocationOperand)38 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)28 Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)23 IntConstantOperand (org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand)22 Instruction (org.jikesrvm.compilers.opt.ir.Instruction)20 BranchProfileOperand (org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand)16 ConditionOperand (org.jikesrvm.compilers.opt.ir.operand.ConditionOperand)14 MethodOperand (org.jikesrvm.compilers.opt.ir.operand.MethodOperand)14 TrapCodeOperand (org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand)13 AddressConstantOperand (org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand)11 BasicBlock (org.jikesrvm.compilers.opt.ir.BasicBlock)10 BranchOperand (org.jikesrvm.compilers.opt.ir.operand.BranchOperand)8 MemoryOperand (org.jikesrvm.compilers.opt.ir.operand.MemoryOperand)8 TrueGuardOperand (org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand)8 NullConstantOperand (org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand)7 FieldReference (org.jikesrvm.classloader.FieldReference)6 RVMClass (org.jikesrvm.classloader.RVMClass)6 TypeReference (org.jikesrvm.classloader.TypeReference)6 TIBConstantOperand (org.jikesrvm.compilers.opt.ir.operand.TIBConstantOperand)6 TypeOperand (org.jikesrvm.compilers.opt.ir.operand.TypeOperand)6