Search in sources :

Example 21 with TypeReference

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

the class BaselineCompilerImpl method genParameterRegisterLoad.

/**
 * Copy parameters from operand stack into registers.
 * Assumption: parameters are layed out on the stack in order
 * with SP pointing to the last parameter.
 * Also, this method is called before the generation of an explicit method call.
 * @param method is the method to be called.
 * @param hasThisParam is the method virtual?
 */
protected void genParameterRegisterLoad(MethodReference method, boolean hasThisParam) {
    int max = NUM_PARAMETER_GPRS + NUM_PARAMETER_FPRS;
    // quit looking when all registers are full
    if (max == 0)
        return;
    // number of general purpose registers filled
    int gpr = 0;
    // number of floating point  registers filled
    int fpr = 0;
    // next GPR to get a parameter
    GPR T = T0;
    int params = method.getParameterWords() + (hasThisParam ? 1 : 0);
    // stack offset of first parameter word
    Offset offset = Offset.fromIntSignExtend((params - 1) << LG_WORDSIZE);
    if (hasThisParam) {
        if (gpr < NUM_PARAMETER_GPRS) {
            stackMoveHelper(T, offset);
            // at most 2 parameters can be passed in general purpose registers
            T = T1;
            gpr++;
            max--;
        }
        offset = offset.minus(WORDSIZE);
    }
    for (TypeReference type : method.getParameterTypes()) {
        // quit looking when all registers are full
        if (max == 0)
            return;
        TypeReference t = type;
        if (t.isLongType()) {
            if (gpr < NUM_PARAMETER_GPRS) {
                if (WORDSIZE == 4) {
                    // lo register := hi mem (== hi order word)
                    stackMoveHelper(T, offset);
                    // at most 2 parameters can be passed in general purpose registers
                    T = T1;
                    gpr++;
                    max--;
                    if (gpr < NUM_PARAMETER_GPRS) {
                        // hi register := lo mem (== lo order word)
                        stackMoveHelper(T, offset.minus(WORDSIZE));
                        gpr++;
                        max--;
                    }
                } else {
                    // initially offset will point at junk word, move down and over
                    stackMoveHelper(T, offset.minus(WORDSIZE));
                    // at most 2 parameters can be passed in general purpose registers
                    T = T1;
                    gpr++;
                    max--;
                }
            }
            offset = offset.minus(2 * WORDSIZE);
        } else if (t.isFloatType()) {
            if (fpr < NUM_PARAMETER_FPRS) {
                if (SSE2_FULL) {
                    asm.emitMOVSS_Reg_RegDisp(XMM.lookup(fpr), SP, offset);
                } else {
                    asm.emitFLD_Reg_RegDisp(FP0, SP, offset);
                }
                fpr++;
                max--;
            }
            offset = offset.minus(WORDSIZE);
        } else if (t.isDoubleType()) {
            if (fpr < NUM_PARAMETER_FPRS) {
                if (SSE2_FULL) {
                    asm.emitMOVSD_Reg_RegDisp(XMM.lookup(fpr), SP, offset.minus(WORDSIZE));
                } else {
                    asm.emitFLD_Reg_RegDisp_Quad(FP0, SP, offset.minus(WORDSIZE));
                }
                fpr++;
                max--;
            }
            offset = offset.minus(2 * WORDSIZE);
        } else if (t.isReferenceType() || t.isWordLikeType()) {
            if (gpr < NUM_PARAMETER_GPRS) {
                stackMoveHelper(T, offset);
                // at most 2 parameters can be passed in general purpose registers
                T = T1;
                gpr++;
                max--;
            }
            offset = offset.minus(WORDSIZE);
        } else {
            // t is object, int, short, char, byte, or boolean
            if (gpr < NUM_PARAMETER_GPRS) {
                if (offset.isZero()) {
                    asm.emitMOV_Reg_RegInd(T, SP);
                } else {
                    asm.emitMOV_Reg_RegDisp(T, SP, offset);
                }
                // at most 2 parameters can be passed in general purpose registers
                T = T1;
                gpr++;
                max--;
            }
            offset = offset.minus(WORDSIZE);
        }
    }
    if (VM.VerifyAssertions)
        VM._assert(offset.EQ(Offset.fromIntSignExtend(-WORDSIZE)));
}
Also used : GPR(org.jikesrvm.ia32.RegisterConstants.GPR) TypeReference(org.jikesrvm.classloader.TypeReference) Offset(org.vmmagic.unboxed.Offset)

Example 22 with TypeReference

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

the class BaselineCompilerImpl method emit_resolved_getfield.

@Override
protected void emit_resolved_getfield(FieldReference fieldRef) {
    TypeReference fieldType = fieldRef.getFieldContentsType();
    RVMField field = fieldRef.peekResolvedField();
    Offset fieldOffset = field.getOffset();
    if (field.isReferenceType()) {
        // 32/64bit reference load
        if (NEEDS_OBJECT_GETFIELD_BARRIER && !field.isUntraced()) {
            Barriers.compileGetfieldBarrierImm(asm, fieldOffset, fieldRef.getId());
        } else {
            // T0 is object reference
            asm.emitPOP_Reg(T0);
            // place field value on stack
            asm.emitPUSH_RegDisp(T0, fieldOffset);
        }
    } else if (fieldType.isBooleanType()) {
        // 8bit unsigned load
        // S0 is object reference
        asm.emitPOP_Reg(S0);
        // T0 is field value
        asm.emitMOVZX_Reg_RegDisp_Byte(T0, S0, fieldOffset);
        // place value on stack
        asm.emitPUSH_Reg(T0);
    } else if (fieldType.isByteType()) {
        // 8bit signed load
        // S0 is object reference
        asm.emitPOP_Reg(S0);
        // T0 is field value
        asm.emitMOVSX_Reg_RegDisp_Byte(T0, S0, fieldOffset);
        // place value on stack
        asm.emitPUSH_Reg(T0);
    } else if (fieldType.isShortType()) {
        // 16bit signed load
        // S0 is object reference
        asm.emitPOP_Reg(S0);
        // T0 is field value
        asm.emitMOVSX_Reg_RegDisp_Word(T0, S0, fieldOffset);
        // place value on stack
        asm.emitPUSH_Reg(T0);
    } else if (fieldType.isCharType()) {
        // 16bit unsigned load
        // S0 is object reference
        asm.emitPOP_Reg(S0);
        // T0 is field value
        asm.emitMOVZX_Reg_RegDisp_Word(T0, S0, fieldOffset);
        // place value on stack
        asm.emitPUSH_Reg(T0);
    } else if (fieldType.isIntType() || fieldType.isFloatType() || (VM.BuildFor32Addr && fieldType.isWordLikeType())) {
        // 32bit load
        // S0 is object reference
        asm.emitPOP_Reg(S0);
        if (VM.BuildFor32Addr) {
            // place value on stack
            asm.emitPUSH_RegDisp(S0, fieldOffset);
        } else {
            // T0 is field value
            asm.emitMOV_Reg_RegDisp(T0, S0, fieldOffset);
            // place value on stack
            asm.emitPUSH_Reg(T0);
        }
    } else {
        // 64bit load
        if (VM.VerifyAssertions) {
            VM._assert(fieldType.isLongType() || fieldType.isDoubleType() || (VM.BuildFor64Addr && fieldType.isWordLikeType()));
        }
        // T0 is object reference
        asm.emitPOP_Reg(T0);
        if (VM.BuildFor32Addr && field.isVolatile()) {
            // as a slightly optimized Intel memory copy using the FPU
            if (SSE2_BASE) {
                // XMM0 is field value
                asm.emitMOVQ_Reg_RegDisp(XMM0, T0, fieldOffset);
                // adjust stack down to hold 64bit value
                adjustStack(-2 * WORDSIZE, true);
                // replace reference with value on stack
                asm.emitMOVQ_RegInd_Reg(SP, XMM0);
            } else {
                // FP0 is field value
                asm.emitFLD_Reg_RegDisp_Quad(FP0, T0, fieldOffset);
                // adjust stack down to hold 64bit value
                adjustStack(-2 * WORDSIZE, true);
                // replace reference with value on stack
                asm.emitFSTP_RegInd_Reg_Quad(SP, FP0);
            }
        } else if (VM.BuildFor32Addr && !field.isVolatile()) {
            // place high half on stack
            asm.emitPUSH_RegDisp(T0, fieldOffset.plus(ONE_SLOT));
            // place low half on stack
            asm.emitPUSH_RegDisp(T0, fieldOffset);
        } else {
            if (!fieldType.isWordLikeType()) {
                // add empty slot
                adjustStack(-WORDSIZE, true);
            }
            // place value on stack
            asm.emitPUSH_RegDisp(T0, fieldOffset);
        }
    }
}
Also used : RVMField(org.jikesrvm.classloader.RVMField) TypeReference(org.jikesrvm.classloader.TypeReference) Offset(org.vmmagic.unboxed.Offset)

Example 23 with TypeReference

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

the class InlineTools method inlinedSizeEstimate.

/**
 * Given the currently available information at the call site,
 * what's our best guess on the inlined size of the callee?
 * @param callee the method to be inlined
 * @param state the compilation state decribing the call site where it
 *              is to be inlined
 * @return an inlined size estimate (number of machine code instructions)
 */
public static int inlinedSizeEstimate(NormalMethod callee, CompilationState state) {
    int sizeEstimate = callee.inlinedSizeEstimate();
    // Adjust size estimate downward to account for optimizations
    // that are typically enabled by constant parameters.
    Instruction callInstr = state.getCallInstruction();
    int numArgs = Call.getNumberOfParams(callInstr);
    // no reduction.
    double reductionFactor = 1.0;
    OptOptions opts = state.getOptions();
    for (int i = 0; i < numArgs; i++) {
        Operand op = Call.getParam(callInstr, i);
        if (op instanceof RegisterOperand) {
            RegisterOperand rop = (RegisterOperand) op;
            TypeReference type = rop.getType();
            if (type.isReferenceType()) {
                if (type.isArrayType()) {
                    // Reductions only come from optimization of dynamic type checks; all virtual methods on arrays are defined on Object.
                    if (rop.isPreciseType()) {
                        reductionFactor -= opts.INLINE_PRECISE_REG_ARRAY_ARG_BONUS;
                    } else if (rop.isDeclaredType() && callee.hasArrayWrite() && type.getArrayElementType().isReferenceType()) {
                        // potential to optimize checkstore portion of aastore bytecode on parameter
                        reductionFactor -= opts.INLINE_DECLARED_AASTORED_ARRAY_ARG_BONUS;
                    }
                } else {
                    // Reductions come from optimization of dynamic type checks and improved inlining of virtual/interface calls
                    if (rop.isPreciseType()) {
                        reductionFactor -= opts.INLINE_PRECISE_REG_CLASS_ARG_BONUS;
                    } else if (rop.isExtant()) {
                        reductionFactor -= opts.INLINE_EXTANT_REG_CLASS_ARG_BONUS;
                    }
                }
            }
        } else if (op.isIntConstant()) {
            reductionFactor -= opts.INLINE_INT_CONST_ARG_BONUS;
        } else if (op.isNullConstant()) {
            reductionFactor -= opts.INLINE_NULL_CONST_ARG_BONUS;
        } else if (op.isObjectConstant()) {
            reductionFactor -= opts.INLINE_OBJECT_CONST_ARG_BONUS;
        }
    }
    reductionFactor = Math.max(reductionFactor, 1.0 - opts.INLINE_MAX_ARG_BONUS);
    if (opts.INLINE_CALL_DEPTH_COST != 0.00) {
        double depthCost = Math.pow(1.0 + opts.INLINE_CALL_DEPTH_COST, state.getInlineDepth() + 1);
        return (int) (sizeEstimate * reductionFactor * depthCost);
    } else {
        return (int) (sizeEstimate * reductionFactor);
    }
}
Also used : RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) OptOptions(org.jikesrvm.compilers.opt.OptOptions) TypeReference(org.jikesrvm.classloader.TypeReference) Instruction(org.jikesrvm.compilers.opt.ir.Instruction)

Example 24 with TypeReference

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

the class Inliner method execute.

/**
 * Return a generation context that represents the
 * execution of inlDec in the context <code>&lt;parent,ebag&gt;</code> for
 * the call instruction callSite.
 * <p> PRECONDITION: inlDec.isYes()
 * <p> POSTCONDITIONS:
 * Let gc be the returned generation context.
 * <ul>
 *  <li> gc.cfg.firstInCodeOrder is the entry to the inlined context
 *  <li>gc.cfg.lastInCodeOrder is the exit from the inlined context
 *  <li> GenerationContext.transferState(parent, child) has been called.
 * </ul>
 *
 * @param inlDec the inlining decision to execute
 * @param parent the caller generation context
 * @param ebag exception handler scope for the caller
 * @param callSite the callsite to execute
 * @return a generation context that represents the execution of the
 *         inline decision in the given context
 */
public static GenerationContext execute(InlineDecision inlDec, GenerationContext parent, ExceptionHandlerBasicBlockBag ebag, Instruction callSite) {
    if (inlDec.needsGuard()) {
        // Step 1: create the synthetic generation context we'll
        // return to our caller.
        GenerationContext container = GenerationContext.createSynthetic(parent, ebag);
        container.getCfg().breakCodeOrder(container.getPrologue(), container.getEpilogue());
        // Step 2: (a) Print a message (optional)
        // (b) Generate the child GC for each target
        RVMMethod[] targets = inlDec.getTargets();
        byte[] guards = inlDec.getGuards();
        GenerationContext[] children = new GenerationContext[targets.length];
        for (int i = 0; i < targets.length; i++) {
            NormalMethod callee = (NormalMethod) targets[i];
            // (a)
            if (parent.getOptions().PRINT_INLINE_REPORT) {
                String guard = guards[i] == OptOptions.INLINE_GUARD_CLASS_TEST ? " (class test) " : " (method test) ";
                VM.sysWriteln("\tGuarded inline" + guard + " " + callee + " into " + callSite.position().getMethod() + " at bytecode " + callSite.getBytecodeIndex());
            }
            // (b)
            children[i] = parent.createChildContext(ebag, callee, callSite);
            BC2IR.generateHIR(children[i]);
            children[i].transferStateToParent();
        }
        // special purpose coding wrapping the calls to Operand.meet.
        if (Call.hasResult(callSite)) {
            Register reg = Call.getResult(callSite).getRegister();
            container.setResult(children[0].getResult());
            for (int i = 1; i < targets.length; i++) {
                if (children[i].getResult() != null) {
                    container.setResult((container.getResult() == null) ? children[i].getResult() : Operand.meet(container.getResult(), children[i].getResult(), reg));
                }
            }
            if (!inlDec.OSRTestFailed()) {
                // Account for the non-predicted case as well...
                RegisterOperand failureCaseResult = Call.getResult(callSite).copyRO();
                container.setResult((container.getResult() == null) ? failureCaseResult : Operand.meet(container.getResult(), failureCaseResult, reg));
            }
        }
        // Step 4: Create a block to contain a copy of the original call or an OSR_Yieldpoint
        // to cover the case that all predictions fail.
        BasicBlock testFailed = new BasicBlock(callSite.getBytecodeIndex(), callSite.position(), parent.getCfg());
        testFailed.setExceptionHandlers(ebag);
        if (COUNT_FAILED_GUARDS && Controller.options.INSERT_DEBUGGING_COUNTERS) {
            // Get a dynamic count of how many times guards fail at runtime.
            // Need a name for the event to count.  In this example, a
            // separate counter for each method by using the method name
            // as the event name.  You could also have used just the string
            // "Guarded inline failed" to keep only one counter.
            String eventName = "Guarded inline failed: " + callSite.position().getMethod().toString();
            // Create instruction that will increment the counter
            // corresponding to the named event.
            Instruction counterInst = AOSDatabase.debuggingCounterData.getCounterInstructionForEvent(eventName);
            testFailed.appendInstruction(counterInst);
        }
        if (inlDec.OSRTestFailed()) {
            // note where we're storing the osr barrier instruction
            Instruction lastOsrBarrier = parent.getOSRBarrierFromInst(callSite);
            Instruction s = BC2IR._osrHelper(lastOsrBarrier, parent);
            s.copyPosition(callSite);
            testFailed.appendInstruction(s);
            testFailed.insertOut(parent.getExit());
        } else {
            Instruction call = callSite.copyWithoutLinks();
            Call.getMethod(call).setIsGuardedInlineOffBranch(true);
            call.copyPosition(callSite);
            testFailed.appendInstruction(call);
            testFailed.insertOut(container.getEpilogue());
            // BC2IR.maybeInlineMethod).
            if (ebag != null) {
                for (Enumeration<BasicBlock> e = ebag.enumerator(); e.hasMoreElements(); ) {
                    BasicBlock handler = e.nextElement();
                    testFailed.insertOut(handler);
                }
            }
            testFailed.setCanThrowExceptions();
            testFailed.setMayThrowUncaughtException();
        }
        container.getCfg().linkInCodeOrder(testFailed, container.getEpilogue());
        testFailed.setInfrequent();
        // Step 5: Patch together all the callees by generating guard blocks
        BasicBlock firstIfBlock = testFailed;
        // Note: We know that receiver must be a register
        // operand (and not a string constant) because we are doing a
        // guarded inlining....if it was a string constant we'd have
        // been able to inline without a guard.
        Operand receiver = Call.getParam(callSite, 0);
        MethodOperand mo = Call.getMethod(callSite);
        boolean isInterface = mo.isInterface();
        if (isInterface) {
            if (VM.BuildForIMTInterfaceInvocation) {
                RVMType interfaceType = mo.getTarget().getDeclaringClass();
                TypeReference recTypeRef = receiver.getType();
                RVMClass recType = (RVMClass) recTypeRef.peekType();
                // Attempt to avoid inserting the check by seeing if the
                // known static type of the receiver implements the interface.
                boolean requiresImplementsTest = true;
                if (recType != null && recType.isResolved() && !recType.isInterface()) {
                    byte doesImplement = ClassLoaderProxy.includesType(interfaceType.getTypeRef(), recTypeRef);
                    requiresImplementsTest = doesImplement != YES;
                }
                if (requiresImplementsTest) {
                    RegisterOperand checkedReceiver = parent.getTemps().makeTemp(receiver);
                    Instruction dtc = TypeCheck.create(MUST_IMPLEMENT_INTERFACE, checkedReceiver, receiver.copy(), new TypeOperand(interfaceType), Call.getGuard(callSite).copy());
                    dtc.copyPosition(callSite);
                    checkedReceiver.refine(interfaceType.getTypeRef());
                    Call.setParam(callSite, 0, checkedReceiver.copyRO());
                    testFailed.prependInstruction(dtc);
                }
            }
        }
        // "logical" test and to share test insertion for interfaces/virtuals.
        for (int i = children.length - 1; i >= 0; i--, testFailed = firstIfBlock) {
            firstIfBlock = new BasicBlock(callSite.getBytecodeIndex(), callSite.position(), parent.getCfg());
            firstIfBlock.setExceptionHandlers(ebag);
            BasicBlock lastIfBlock = firstIfBlock;
            RVMMethod target = children[i].getMethod();
            Instruction tmp;
            if (isInterface) {
                RVMClass callDeclClass = mo.getTarget().getDeclaringClass();
                if (!callDeclClass.isInterface()) {
                    // the entire compilation.
                    throw new OptimizingCompilerException("Attempted guarded inline of invoke interface when decl class of target method may not be an interface");
                }
                // We potentially have to generate IR to perform two tests here:
                // (1) Does the receiver object implement callDeclClass?
                // (2) Given that it does, is target the method that would
                // be invoked for this receiver?
                // It is quite common to be able to answer (1) "YES" at compile
                // time, in which case we only have to generate IR to establish
                // (2) at runtime.
                byte doesImplement = ClassLoaderProxy.includesType(callDeclClass.getTypeRef(), target.getDeclaringClass().getTypeRef());
                if (doesImplement != YES) {
                    // implements the interface).
                    if (parent.getOptions().PRINT_INLINE_REPORT) {
                        VM.sysWriteln("\t\tRequired additional instanceof " + callDeclClass + " test");
                    }
                    firstIfBlock = new BasicBlock(callSite.getBytecodeIndex(), callSite.position(), parent.getCfg());
                    firstIfBlock.setExceptionHandlers(ebag);
                    RegisterOperand instanceOfResult = parent.getTemps().makeTempInt();
                    tmp = InstanceOf.create(INSTANCEOF_NOTNULL, instanceOfResult, new TypeOperand(callDeclClass), receiver.copy(), Call.getGuard(callSite));
                    tmp.copyPosition(callSite);
                    firstIfBlock.appendInstruction(tmp);
                    tmp = IfCmp.create(INT_IFCMP, parent.getTemps().makeTempValidation(), instanceOfResult.copyD2U(), new IntConstantOperand(0), ConditionOperand.EQUAL(), testFailed.makeJumpTarget(), BranchProfileOperand.unlikely());
                    tmp.copyPosition(callSite);
                    firstIfBlock.appendInstruction(tmp);
                    firstIfBlock.insertOut(testFailed);
                    firstIfBlock.insertOut(lastIfBlock);
                    container.getCfg().linkInCodeOrder(firstIfBlock, lastIfBlock);
                }
            }
            if (guards[i] == OptOptions.INLINE_GUARD_CLASS_TEST) {
                tmp = InlineGuard.create(IG_CLASS_TEST, receiver.copy(), Call.getGuard(callSite).copy(), new TypeOperand(target.getDeclaringClass()), testFailed.makeJumpTarget(), BranchProfileOperand.unlikely());
            } else if (guards[i] == OptOptions.INLINE_GUARD_METHOD_TEST) {
                // declaring class.
                if (isInterface) {
                    RegisterOperand t = parent.getTemps().makeTempInt();
                    Instruction test = InstanceOf.create(INSTANCEOF_NOTNULL, t, new TypeOperand(target.getDeclaringClass().getTypeRef()), receiver.copy());
                    test.copyPosition(callSite);
                    lastIfBlock.appendInstruction(test);
                    Instruction cmp = IfCmp.create(INT_IFCMP, parent.getTemps().makeTempValidation(), t.copyD2U(), new IntConstantOperand(0), ConditionOperand.EQUAL(), testFailed.makeJumpTarget(), BranchProfileOperand.unlikely());
                    cmp.copyPosition(callSite);
                    lastIfBlock.appendInstruction(cmp);
                    BasicBlock subclassTest = new BasicBlock(callSite.getBytecodeIndex(), callSite.position(), parent.getCfg());
                    lastIfBlock.insertOut(testFailed);
                    lastIfBlock.insertOut(subclassTest);
                    container.getCfg().linkInCodeOrder(lastIfBlock, subclassTest);
                    lastIfBlock = subclassTest;
                }
                tmp = InlineGuard.create(IG_METHOD_TEST, receiver.copy(), Call.getGuard(callSite).copy(), MethodOperand.VIRTUAL(target.getMemberRef().asMethodReference(), target), testFailed.makeJumpTarget(), BranchProfileOperand.unlikely());
            } else {
                tmp = InlineGuard.create(IG_PATCH_POINT, receiver.copy(), Call.getGuard(callSite).copy(), MethodOperand.VIRTUAL(target.getMemberRef().asMethodReference(), target), testFailed.makeJumpTarget(), inlDec.OSRTestFailed() ? BranchProfileOperand.never() : BranchProfileOperand.unlikely());
            }
            tmp.copyPosition(callSite);
            lastIfBlock.appendInstruction(tmp);
            lastIfBlock.insertOut(testFailed);
            lastIfBlock.insertOut(children[i].getPrologue());
            container.getCfg().linkInCodeOrder(lastIfBlock, children[i].getCfg().firstInCodeOrder());
            if (children[i].getEpilogue() != null) {
                children[i].getEpilogue().appendInstruction(container.getEpilogue().makeGOTO());
                children[i].getEpilogue().insertOut(container.getEpilogue());
            }
            container.getCfg().linkInCodeOrder(children[i].getCfg().lastInCodeOrder(), testFailed);
        }
        // Step 6: finish by linking container.prologue & testFailed
        container.getPrologue().insertOut(testFailed);
        container.getCfg().linkInCodeOrder(container.getPrologue(), testFailed);
        return container;
    } else {
        if (VM.VerifyAssertions)
            VM._assert(inlDec.getNumberOfTargets() == 1);
        NormalMethod callee = (NormalMethod) inlDec.getTargets()[0];
        if (parent.getOptions().PRINT_INLINE_REPORT) {
            VM.sysWriteln("\tInline " + callee + " into " + callSite.position().getMethod() + " at bytecode " + callSite.getBytecodeIndex());
        }
        GenerationContext child = parent.createChildContext(ebag, callee, callSite);
        BC2IR.generateHIR(child);
        child.transferStateToParent();
        return child;
    }
}
Also used : GenerationContext(org.jikesrvm.compilers.opt.bc2ir.GenerationContext) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) TypeOperand(org.jikesrvm.compilers.opt.ir.operand.TypeOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) RVMType(org.jikesrvm.classloader.RVMType) ExceptionHandlerBasicBlock(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) RVMClass(org.jikesrvm.classloader.RVMClass) RVMMethod(org.jikesrvm.classloader.RVMMethod) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Register(org.jikesrvm.compilers.opt.ir.Register) NormalMethod(org.jikesrvm.classloader.NormalMethod) TypeOperand(org.jikesrvm.compilers.opt.ir.operand.TypeOperand) TypeReference(org.jikesrvm.classloader.TypeReference) OptimizingCompilerException(org.jikesrvm.compilers.opt.OptimizingCompilerException)

Example 25 with TypeReference

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

the class ObjectReplacer method scalarReplace.

/**
 * Replace a given use of a object with its scalar equivalent
 *
 * @param use the use to replace
 * @param scalars an array of scalar register operands to replace
 *                  the object's fields with
 * @param fields the object's fields
 * @param visited the registers that were already seen
 */
private void scalarReplace(RegisterOperand use, RegisterOperand[] scalars, ArrayList<RVMField> fields, Set<Register> visited) {
    Instruction inst = use.instruction;
    try {
        switch(inst.getOpcode()) {
            case PUTFIELD_opcode:
                {
                    FieldReference fr = PutField.getLocation(inst).getFieldRef();
                    if (VM.VerifyAssertions)
                        VM._assert(fr.isResolved());
                    RVMField f = fr.peekResolvedField();
                    int index = fields.indexOf(f);
                    TypeReference type = scalars[index].getType();
                    Operator moveOp = IRTools.getMoveOp(type);
                    Instruction i = Move.create(moveOp, scalars[index].copyRO(), PutField.getClearValue(inst));
                    inst.insertBefore(i);
                    DefUse.removeInstructionAndUpdateDU(inst);
                    DefUse.updateDUForNewInstruction(i);
                }
                break;
            case GETFIELD_opcode:
                {
                    FieldReference fr = GetField.getLocation(inst).getFieldRef();
                    if (VM.VerifyAssertions)
                        VM._assert(fr.isResolved());
                    RVMField f = fr.peekResolvedField();
                    int index = fields.indexOf(f);
                    TypeReference type = scalars[index].getType();
                    Operator moveOp = IRTools.getMoveOp(type);
                    Instruction i = Move.create(moveOp, GetField.getClearResult(inst), scalars[index].copyRO());
                    inst.insertBefore(i);
                    DefUse.removeInstructionAndUpdateDU(inst);
                    DefUse.updateDUForNewInstruction(i);
                }
                break;
            case MONITORENTER_opcode:
                inst.insertBefore(Empty.create(READ_CEILING));
                DefUse.removeInstructionAndUpdateDU(inst);
                break;
            case MONITOREXIT_opcode:
                inst.insertBefore(Empty.create(WRITE_FLOOR));
                DefUse.removeInstructionAndUpdateDU(inst);
                break;
            case CALL_opcode:
            case NULL_CHECK_opcode:
                // (SJF) TODO: Why wasn't this caught by BC2IR for
                // java.lang.Double.<init> (Ljava/lang/String;)V ?
                DefUse.removeInstructionAndUpdateDU(inst);
                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, klass.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, fields, visited);
                        // 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, klass.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(klass));
                    DefUse.replaceInstructionAndUpdateDU(inst, i2);
                }
                break;
            case REF_MOVE_opcode:
                {
                    if (visited == null) {
                        visited = new HashSet<Register>();
                    }
                    Register copy = Move.getResult(use.instruction).getRegister();
                    if (!visited.contains(copy)) {
                        visited.add(copy);
                        transform2(copy, inst, scalars, fields, visited);
                    // NB will remove inst
                    } else {
                        DefUse.removeInstructionAndUpdateDU(inst);
                    }
                }
                break;
            default:
                throw new OptimizingCompilerException("ObjectReplacer: unexpected use " + inst);
        }
    } catch (Exception e) {
        OptimizingCompilerException oe = new OptimizingCompilerException("Error handling use (" + use + ") of: " + inst);
        oe.initCause(e);
        throw oe;
    }
}
Also used : Operator(org.jikesrvm.compilers.opt.ir.Operator) FieldReference(org.jikesrvm.classloader.FieldReference) Register(org.jikesrvm.compilers.opt.ir.Register) TIBConstantOperand(org.jikesrvm.compilers.opt.ir.operand.TIBConstantOperand) RVMField(org.jikesrvm.classloader.RVMField) TypeReference(org.jikesrvm.classloader.TypeReference) OptimizingCompilerException(org.jikesrvm.compilers.opt.OptimizingCompilerException) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) OptimizingCompilerException(org.jikesrvm.compilers.opt.OptimizingCompilerException) HashSet(java.util.HashSet)

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