Search in sources :

Example 76 with BasicBlock

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

the class DynamicTypeCheckExpansion method mustImplementInterface.

/**
 * Expand a checkcastInterface instruction into the LIR sequence that
 * implements the dynamic type check, raising an IncompataibleClassChangeError
 * if the type check fails.
 * Ref is known to never contain a null ptr at runtime.
 *
 * @param s a MUST_IMPLEMENT_INTERFACE instruction to expand
 * @param ir the enclosing IR
 * @return the last Instruction in the generated LIR sequence.
 */
static Instruction mustImplementInterface(Instruction s, IR ir) {
    Operand ref = TypeCheck.getClearRef(s);
    RVMClass LHSClass = (RVMClass) TypeCheck.getType(s).getVMType();
    if (VM.VerifyAssertions)
        VM._assert(LHSClass != null, "Should be resolvable...");
    int interfaceIndex = LHSClass.getDoesImplementIndex();
    int interfaceMask = LHSClass.getDoesImplementBitMask();
    Operand guard = TypeCheck.getClearGuard(s);
    BasicBlock myBlock = s.getBasicBlock();
    BasicBlock failBlock = myBlock.createSubBlock(s.getBytecodeIndex(), ir, .0001f);
    BasicBlock succBlock = myBlock.splitNodeAt(s, ir);
    succBlock.firstInstruction().insertAfter(Move.create(REF_MOVE, TypeCheck.getClearResult(s), ref.copy()));
    myBlock.insertOut(failBlock);
    myBlock.insertOut(succBlock);
    ir.cfg.linkInCodeOrder(myBlock, succBlock);
    ir.cfg.addLastInCodeOrder(failBlock);
    Instruction raiseError = Trap.create(TRAP, null, TrapCodeOperand.MustImplement());
    raiseError.copyPosition(s);
    failBlock.appendInstruction(raiseError);
    Operand RHStib = getTIB(s, ir, ref, guard);
    RegisterOperand doesImpl = InsertUnary(s, ir, GET_DOES_IMPLEMENT_FROM_TIB, TypeReference.IntArray, RHStib);
    if (DynamicTypeCheck.MIN_DOES_IMPLEMENT_SIZE <= interfaceIndex) {
        RegisterOperand doesImplLength = InsertGuardedUnary(s, ir, ARRAYLENGTH, TypeReference.Int, doesImpl.copyD2U(), TG());
        Instruction lengthCheck = IfCmp.create(INT_IFCMP, ir.regpool.makeTempValidation(), doesImplLength, IC(interfaceIndex), ConditionOperand.LESS_EQUAL(), failBlock.makeJumpTarget(), BranchProfileOperand.never());
        s.insertBefore(lengthCheck);
        myBlock.splitNodeWithLinksAt(lengthCheck, ir);
        // required due to splitNode!
        myBlock.insertOut(failBlock);
    }
    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));
    IfCmp.mutate(s, INT_IFCMP, ir.regpool.makeTempValidation(), bit, IC(0), ConditionOperand.EQUAL(), failBlock.makeJumpTarget(), BranchProfileOperand.never());
    return s;
}
Also used : 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) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) RVMClass(org.jikesrvm.classloader.RVMClass)

Example 77 with BasicBlock

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

the class DynamicTypeCheckExpansion method convertToBranchingTypeCheck.

/**
 * Generate wrapper around branching type check to get a
 * value producing type check.
 * @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 TypeReference to be tested against.
 * @param RHStib   The Operand containing the TIB of the rhs.
 * @param result   The RegisterOperand that the result of dynamic
 * @return the opt instruction immediately before the instruction to
 *         continue expansion.
 */
private static Instruction convertToBranchingTypeCheck(Instruction s, IR ir, Operand RHSobj, TypeReference LHStype, Operand RHStib, RegisterOperand result) {
    BasicBlock myBlock = s.getBasicBlock();
    BasicBlock contBlock = myBlock.splitNodeAt(s, ir);
    int subBlockStart = s.getBytecodeIndex();
    BasicBlock trueBlock = myBlock.createSubBlock(subBlockStart, ir);
    BasicBlock falseBlock = myBlock.createSubBlock(subBlockStart, ir);
    myBlock.insertOut(trueBlock);
    myBlock.insertOut(falseBlock);
    trueBlock.insertOut(contBlock);
    falseBlock.insertOut(contBlock);
    ir.cfg.linkInCodeOrder(myBlock, trueBlock);
    ir.cfg.linkInCodeOrder(trueBlock, falseBlock);
    ir.cfg.linkInCodeOrder(falseBlock, contBlock);
    trueBlock.appendInstruction(Move.create(INT_MOVE, result, IC(1)));
    trueBlock.appendInstruction(Goto.create(GOTO, contBlock.makeJumpTarget()));
    falseBlock.appendInstruction(Move.create(INT_MOVE, result.copyD2D(), IC(0)));
    return generateBranchingTypeCheck(s, ir, RHSobj, LHStype, RHStib, trueBlock, falseBlock, ir.regpool.makeTempValidation(), new BranchProfileOperand());
}
Also used : BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand)

Example 78 with BasicBlock

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

the class DynamicTypeCheckExpansion method generateBranchingTypeCheck.

/**
 * Generate a branching dynamic type check.
 * This routine assumes that the CFG and code order are already
 * correctly established.
 * This routine must either remove s or mutate it.
 *
 * @param s          The Instruction that is to be replaced by a
 *                   branching type check
 * @param ir         The IR containing the instruction to be expanded.
 * @param RHSobj     The RegisterOperand containing the rhs object.
 * @param LHStype    The TypeReference to be tested against.
 * @param RHStib     The Operand containing the TIB of the rhs.
 * @param trueBlock  The BasicBlock to continue at if the typecheck
 *                   evaluates to true
 * @param falseBlock The BasicBlock to continue at if the typecheck
 *                   evaluates to false.
 * @param oldGuard   A suitable guard operand (not necessarily related
 *                   the instruction that is to be replaced).
 * @param falseProb   The probability that typecheck will branch to the falseBlock
 * @return the opt instruction immediately before the instruction to
 *         continue expansion.
 */
private static Instruction generateBranchingTypeCheck(Instruction s, IR ir, Operand RHSobj, TypeReference LHStype, Operand RHStib, BasicBlock trueBlock, BasicBlock falseBlock, RegisterOperand oldGuard, BranchProfileOperand falseProb) {
    Instruction continueAt = Goto.create(GOTO, trueBlock.makeJumpTarget());
    continueAt.copyPosition(s);
    s.insertBefore(continueAt);
    s.remove();
    if (LHStype.isClassType()) {
        RVMClass LHSclass = (RVMClass) LHStype.peekType();
        if (LHSclass != null && LHSclass.isResolved()) {
            // class or interface
            if (LHSclass.isInterface()) {
                // A resolved interface (case 4)
                int interfaceIndex = LHSclass.getDoesImplementIndex();
                int interfaceMask = LHSclass.getDoesImplementBitMask();
                RegisterOperand doesImpl = InsertUnary(continueAt, ir, GET_DOES_IMPLEMENT_FROM_TIB, TypeReference.IntArray, RHStib);
                if (DynamicTypeCheck.MIN_DOES_IMPLEMENT_SIZE <= interfaceIndex) {
                    RegisterOperand doesImplLength = InsertGuardedUnary(continueAt, ir, ARRAYLENGTH, TypeReference.Int, doesImpl.copyD2U(), TG());
                    Instruction lengthCheck = IfCmp.create(INT_IFCMP, oldGuard, doesImplLength, IC(interfaceIndex), ConditionOperand.LESS_EQUAL(), falseBlock.makeJumpTarget(), BranchProfileOperand.unlikely());
                    if (oldGuard != null) {
                        oldGuard = oldGuard.copyD2D();
                    }
                    continueAt.insertBefore(lengthCheck);
                    BasicBlock oldBlock = continueAt.getBasicBlock();
                    oldBlock.splitNodeWithLinksAt(lengthCheck, ir);
                    // required due to splitNode!
                    oldBlock.insertOut(falseBlock);
                }
                RegisterOperand entry = InsertLoadOffset(continueAt, ir, INT_LOAD, TypeReference.Int, doesImpl, Offset.fromIntZeroExtend(interfaceIndex << 2), new LocationOperand(TypeReference.Int), TG());
                RegisterOperand bit = insertBinary(continueAt, ir, INT_AND, TypeReference.Int, entry, IC(interfaceMask));
                continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, bit, IC(0), ConditionOperand.EQUAL(), falseBlock.makeJumpTarget(), falseProb));
                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(continueAt, ir, LHSclass);
                    continueAt.insertBefore(IfCmp.create(REF_IFCMP, oldGuard, RHStib, classTIB, ConditionOperand.NOT_EQUAL(), falseBlock.makeJumpTarget(), falseProb));
                    return continueAt;
                } else {
                    // Do the full blown case 5 or 6 typecheck.
                    int LHSDepth = LHSclass.getTypeDepth();
                    int LHSId = LHSclass.getId();
                    RegisterOperand superclassIds = InsertUnary(continueAt, ir, GET_SUPERCLASS_IDS_FROM_TIB, TypeReference.ShortArray, RHStib);
                    if (DynamicTypeCheck.MIN_SUPERCLASS_IDS_SIZE <= LHSDepth) {
                        RegisterOperand superclassIdsLength = InsertGuardedUnary(continueAt, ir, ARRAYLENGTH, TypeReference.Int, superclassIds.copyD2U(), TG());
                        Instruction lengthCheck = IfCmp.create(INT_IFCMP, oldGuard, superclassIdsLength, IC(LHSDepth), ConditionOperand.LESS(), falseBlock.makeJumpTarget(), BranchProfileOperand.unlikely());
                        if (oldGuard != null) {
                            oldGuard = oldGuard.copyD2D();
                        }
                        continueAt.insertBefore(lengthCheck);
                        BasicBlock oldBlock = continueAt.getBasicBlock();
                        oldBlock.splitNodeWithLinksAt(lengthCheck, ir);
                        // required due to splitNode!
                        oldBlock.insertOut(falseBlock);
                    }
                    RegisterOperand refCandidate = InsertLoadOffset(continueAt, ir, USHORT_LOAD, TypeReference.Short, superclassIds, Offset.fromIntZeroExtend(LHSDepth << 1), new LocationOperand(TypeReference.Short), TG());
                    continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, refCandidate, IC(LHSId), ConditionOperand.NOT_EQUAL(), falseBlock.makeJumpTarget(), falseProb));
                    return continueAt;
                }
            }
        } else {
            // A non-resolved class or interface. Case 3 of DynamicTypeCheck
            // Branch on the result of a call to
            // RuntimeEntrypoints.instance
            RegisterOperand result = ir.regpool.makeTempInt();
            RVMMethod target = Entrypoints.instanceOfMethod;
            Instruction call = Call.create2(CALL, result, AC(target.getOffset()), MethodOperand.STATIC(target), RHSobj, IC(LHStype.getId()));
            call.copyPosition(continueAt);
            continueAt.insertBefore(call);
            call = callHelper(call, ir);
            continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, result.copyD2U(), IC(0), ConditionOperand.EQUAL(), falseBlock.makeJumpTarget(), falseProb));
            return continueAt;
        }
    }
    if (LHStype.isArrayType()) {
        // Case 2 of DynamicTypeCheck: LHS is an array.
        RVMArray LHSArray = (RVMArray) LHStype.peekType();
        if (LHSArray != null) {
            Operand classTIB = getTIB(continueAt, ir, LHSArray);
            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.
                continueAt.insertBefore(IfCmp.create(REF_IFCMP, oldGuard, RHStib, classTIB, ConditionOperand.NOT_EQUAL(), falseBlock.makeJumpTarget(), falseProb));
                return continueAt;
            }
            // TODO: branch probability calculation is somewhat bogus for this case.
            Instruction shortcircuit = IfCmp.create(REF_IFCMP, oldGuard, RHStib, classTIB, ConditionOperand.EQUAL(), trueBlock.makeJumpTarget(), new BranchProfileOperand());
            if (oldGuard != null) {
                oldGuard = oldGuard.copyD2D();
            }
            continueAt.insertBefore(shortcircuit);
            BasicBlock myBlock = shortcircuit.getBasicBlock();
            BasicBlock mainBlock = myBlock.splitNodeWithLinksAt(shortcircuit, ir);
            // must come after the splitNodeAt
            myBlock.insertOut(trueBlock);
            RegisterOperand rhsType = InsertUnary(continueAt, ir, GET_TYPE_FROM_TIB, TypeReference.Type, RHStib.copy());
            if (innermostElementType.isJavaLangObjectType()) {
                IntConstantOperand lhsDimension = IC(LHStype.getDimensionality());
                RegisterOperand rhsDimension = getField(continueAt, ir, rhsType, Entrypoints.dimensionField);
                Instruction dimTest = IfCmp2.create(INT_IFCMP2, oldGuard, rhsDimension, lhsDimension, ConditionOperand.GREATER(), trueBlock.makeJumpTarget(), ((BranchProfileOperand) falseProb.copy()).flip(), ConditionOperand.LESS(), falseBlock.makeJumpTarget(), (BranchProfileOperand) falseProb.copy());
                if (oldGuard != null) {
                    oldGuard = oldGuard.copyD2D();
                }
                continueAt.insertBefore(dimTest);
                // BasicBlock testBlock =
                mainBlock.splitNodeWithLinksAt(dimTest, ir);
                mainBlock.insertOut(trueBlock);
                mainBlock.insertOut(falseBlock);
                RegisterOperand rhsInnermostElementTypeDimension = getField(continueAt, ir, rhsType.copyU2U(), Entrypoints.innermostElementTypeDimensionField);
                continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, rhsInnermostElementTypeDimension, IC(0), ConditionOperand.NOT_EQUAL(), falseBlock.makeJumpTarget(), falseProb));
                return continueAt;
            }
        }
        // Not a case we want to handle inline
        RVMMethod target = Entrypoints.instanceOfMethod;
        RegisterOperand callResult = ir.regpool.makeTempInt();
        Instruction call = Call.create2(CALL, callResult, AC(target.getOffset()), MethodOperand.STATIC(target), RHSobj, IC(LHStype.getId()));
        call.copyPosition(continueAt);
        continueAt.insertBefore(call);
        call = callHelper(call, ir);
        continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, callResult.copyD2U(), IC(0), ConditionOperand.EQUAL(), falseBlock.makeJumpTarget(), falseProb));
        return continueAt;
    }
    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) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) 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) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) RVMClass(org.jikesrvm.classloader.RVMClass)

Example 79 with BasicBlock

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

the class GenerationContext method completeExceptionHandlers.

/**
 * If the method is synchronized then we wrap it in a
 * synthetic exception handler that unlocks &amp; rethrows
 * PRECONDITION: cfg, arguments &amp; temps have been setup/initialized.
 *
 * @param isOutermost is this the outermost context (i.e. not an inlined context)
 */
private void completeExceptionHandlers(boolean isOutermost) {
    if (method.isSynchronized() && !options.ESCAPE_INVOKEE_THREAD_LOCAL) {
        ExceptionHandlerBasicBlock rethrow = new ExceptionHandlerBasicBlock(SYNTH_CATCH_BCI, inlineSequence, new TypeOperand(RVMType.JavaLangThrowableType), cfg);
        rethrow.setExceptionHandlers(enclosingHandlers);
        RegisterOperand ceo = temps.makeTemp(TypeReference.JavaLangThrowable);
        Instruction s = Nullary.create(GET_CAUGHT_EXCEPTION, ceo);
        appendInstruction(rethrow, s, SYNTH_CATCH_BCI);
        Operand lockObject = getLockObject();
        RVMMethod target = Entrypoints.unlockAndThrowMethod;
        MethodOperand methodOp = MethodOperand.STATIC(target);
        // Used to keep cfg correct
        methodOp.setIsNonReturningCall(true);
        s = Call.create2(CALL, null, new AddressConstantOperand(target.getOffset()), methodOp, lockObject, ceo.copyD2U());
        appendInstruction(rethrow, s, RUNTIME_SERVICES_BCI);
        cfg.insertBeforeInCodeOrder(epilogue, rethrow);
        // (if enclosed by another catch of Throwable...)
        if (enclosingHandlers != null) {
            for (Enumeration<BasicBlock> e = enclosingHandlers.enumerator(); e.hasMoreElements(); ) {
                BasicBlock eh = e.nextElement();
                rethrow.insertOut(eh);
            }
        }
        rethrow.setCanThrowExceptions();
        rethrow.setMayThrowUncaughtException();
        rethrow.insertOut(exit);
        // save a reference to this block so we can discard it if unused.
        unlockAndRethrow = rethrow;
        ExceptionHandlerBasicBlock[] sh = new ExceptionHandlerBasicBlock[1];
        sh[0] = rethrow;
        enclosingHandlers = new ExceptionHandlerBasicBlockBag(sh, enclosingHandlers);
        generatedExceptionHandlers = true;
    }
}
Also used : RVMMethod(org.jikesrvm.classloader.RVMMethod) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) AddressConstantOperand(org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) TypeOperand(org.jikesrvm.compilers.opt.ir.operand.TypeOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) TrueGuardOperand(org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) ClassConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ClassConstantOperand) AddressConstantOperand(org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand) TypeOperand(org.jikesrvm.compilers.opt.ir.operand.TypeOperand) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) ExceptionHandlerBasicBlock(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock) ExceptionHandlerBasicBlock(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) ExceptionHandlerBasicBlockBag(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlockBag)

Example 80 with BasicBlock

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

the class GenerationContext method createChildContext.

/**
 * Creates a child generation context from this context
 * and callerBB to generate IR for callsite.
 *
 * @param ebag the enclosing exception handlers (null if none)
 * @param callee the callee method to be inlined
 *        (may _not_ be equal to Call.getMethod(callSite).method)
 * @param callSite the Call instruction to be inlined.
 * @return the child context
 */
public GenerationContext createChildContext(ExceptionHandlerBasicBlockBag ebag, NormalMethod callee, Instruction callSite) {
    // Note: In this method, use "this" explicitly to refer to parent fields in order
    // to avoid confusing parent/child fields.
    GenerationContext child = new GenerationContext();
    child.method = callee;
    if (this.options.frequencyCounters() || this.options.inverseFrequencyCounters()) {
        child.branchProfiles = EdgeCounts.getBranchProfiles(callee);
    }
    child.parent = this;
    child.original_cm = this.original_cm;
    // Some state gets directly copied to the child
    child.options = this.options;
    child.temps = this.temps;
    child._ncGuards = this._ncGuards;
    child.exit = this.exit;
    child.inlinePlan = this.inlinePlan;
    // Now inherit state based on callSite
    child.inlineSequence = new InlineSequence(child.method, callSite.position(), callSite);
    child.enclosingHandlers = ebag;
    child.arguments = new Operand[Call.getNumberOfParams(callSite)];
    for (int i = 0; i < child.arguments.length; i++) {
        // copy instead
        child.arguments[i] = Call.getParam(callSite, i).copy();
    // of clearing in case inlining aborts.
    }
    if (Call.hasResult(callSite)) {
        child.resultReg = Call.getResult(callSite).copyD2D().getRegister();
        // it will...
        child.resultReg.setSpansBasicBlock();
    }
    // Initialize the child CFG, prologue, and epilogue blocks
    child.cfg = new ControlFlowGraph(this.cfg.numberOfNodes());
    child.prologue = new BasicBlock(PROLOGUE_BCI, child.inlineSequence, child.cfg);
    child.prologue.setExceptionHandlers(ebag);
    child.epilogue = new BasicBlock(EPILOGUE_BCI, child.inlineSequence, child.cfg);
    child.epilogue.setExceptionHandlers(ebag);
    child.cfg.addLastInCodeOrder(child.prologue);
    child.cfg.addLastInCodeOrder(child.epilogue);
    // Set up the local pool
    child.initLocalPool();
    // Insert moves from child.arguments to child's locals in prologue
    TypeReference[] params = child.method.getParameterTypes();
    int numParams = params.length;
    int argIdx = 0;
    int localNum = 0;
    if (!child.method.isStatic()) {
        Operand receiver = child.arguments[argIdx];
        argIdx++;
        RegisterOperand local = null;
        if (receiver.isRegister()) {
            RegisterOperand objPtr = receiver.asRegister();
            if (ClassLoaderProxy.includesType(child.method.getDeclaringClass().getTypeRef(), objPtr.getType()) != YES) {
                // narrow type of actual to match formal static type implied by method
                // Can be precise but not assignable if enough classes aren't loaded
                objPtr.clearPreciseType();
                objPtr.setDeclaredType();
                objPtr.setType(child.method.getDeclaringClass().getTypeRef());
            }
            local = child.makeLocal(localNum, objPtr);
            localNum++;
            // Avoid confusion in BC2IR of callee
            child.arguments[0] = local;
        // when objPtr is a local in the caller.
        } else if (receiver.isConstant()) {
            local = child.makeLocal(localNum, receiver.getType());
            localNum++;
            local.setPreciseType();
            // Constants trivially non-null
            RegisterOperand guard = child.makeNullCheckGuard(local.getRegister());
            BC2IR.setGuardForRegOp(local, guard);
            child.prologue.appendInstruction(Move.create(GUARD_MOVE, guard.copyRO(), new TrueGuardOperand()));
        } else {
            OptimizingCompilerException.UNREACHABLE("Unexpected receiver operand");
        }
        Instruction s = Move.create(REF_MOVE, local, receiver);
        s.setSourcePosition(PROLOGUE_BCI, callSite.position());
        child.prologue.appendInstruction(s);
    }
    for (int paramIdx = 0; paramIdx < numParams; paramIdx++, argIdx++) {
        TypeReference argType = params[paramIdx];
        RegisterOperand formal;
        Operand actual = child.arguments[argIdx];
        if (actual.isRegister()) {
            RegisterOperand rActual = actual.asRegister();
            if (ClassLoaderProxy.includesType(argType, rActual.getType()) != YES) {
                // narrow type of actual to match formal static type implied by method
                // Can be precise but not
                rActual.clearPreciseType();
                // assignable if enough classes aren't loaded
                rActual.setDeclaredType();
                rActual.setType(argType);
            }
            formal = child.makeLocal(localNum, rActual);
            localNum++;
            // Avoid confusion in BC2IR of
            child.arguments[argIdx] = formal;
        // callee when arg is a local in the caller.
        } else {
            formal = child.makeLocal(localNum, argType);
            localNum++;
        }
        Instruction s = Move.create(IRTools.getMoveOp(argType), formal, actual);
        s.setSourcePosition(PROLOGUE_BCI, callSite.position());
        child.prologue.appendInstruction(s);
        if (argType.isLongType() || argType.isDoubleType()) {
            // longs and doubles take two local words
            localNum++;
        }
    }
    child.completePrologue(false);
    child.completeEpilogue(false);
    child.completeExceptionHandlers(false);
    return child;
}
Also used : RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) TypeOperand(org.jikesrvm.compilers.opt.ir.operand.TypeOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) TrueGuardOperand(org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) ClassConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ClassConstantOperand) AddressConstantOperand(org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand) ControlFlowGraph(org.jikesrvm.compilers.opt.ir.ControlFlowGraph) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) ExceptionHandlerBasicBlock(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock) InlineSequence(org.jikesrvm.compilers.opt.inlining.InlineSequence) TypeReference(org.jikesrvm.classloader.TypeReference) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) TrueGuardOperand(org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand)

Aggregations

BasicBlock (org.jikesrvm.compilers.opt.ir.BasicBlock)219 Instruction (org.jikesrvm.compilers.opt.ir.Instruction)117 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)93 Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)66 ExceptionHandlerBasicBlock (org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock)52 Register (org.jikesrvm.compilers.opt.ir.Register)50 BranchProfileOperand (org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand)48 IntConstantOperand (org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand)37 ConditionOperand (org.jikesrvm.compilers.opt.ir.operand.ConditionOperand)33 MethodOperand (org.jikesrvm.compilers.opt.ir.operand.MethodOperand)27 LocationOperand (org.jikesrvm.compilers.opt.ir.operand.LocationOperand)24 HeapOperand (org.jikesrvm.compilers.opt.ir.operand.HeapOperand)21 BasicBlockOperand (org.jikesrvm.compilers.opt.ir.operand.BasicBlockOperand)20 TrueGuardOperand (org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand)19 TypeReference (org.jikesrvm.classloader.TypeReference)18 NullConstantOperand (org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand)18 Test (org.junit.Test)17 BranchOperand (org.jikesrvm.compilers.opt.ir.operand.BranchOperand)16 InlineSequence (org.jikesrvm.compilers.opt.inlining.InlineSequence)14 MemoryOperand (org.jikesrvm.compilers.opt.ir.operand.MemoryOperand)14