Search in sources :

Example 6 with ExceptionHandlerBasicBlockBag

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

the class GenerationContextTest method invalidReceiverCausesException.

@Test(expected = OptimizingCompilerException.class)
public void invalidReceiverCausesException() throws Exception {
    NormalMethod nm = getNormalMethodForTest("methodForInliningTests");
    CompiledMethod cm = new OptCompiledMethod(-1, nm);
    OptOptions opts = new OptOptions();
    InlineOracle io = new DefaultInlineOracle();
    GenerationContext gc = new GenerationContext(nm, null, cm, opts, io);
    NormalMethod callee = getNormalMethodForTest("emptyInstanceMethodWithoutAnnotations");
    MethodOperand methOp = MethodOperand.VIRTUAL(callee.getMemberRef().asMethodReference(), callee);
    Instruction callInstr = Call.create(CALL, null, null, methOp, 1);
    Operand receiver = new InvalidReceiverOperand();
    Call.setParam(callInstr, 0, receiver);
    callInstr.setPosition(new InlineSequence(nm));
    ExceptionHandlerBasicBlockBag ebag = getMockEbag();
    gc.createChildContext(ebag, callee, callInstr);
}
Also used : OptCompiledMethod(org.jikesrvm.compilers.opt.runtimesupport.OptCompiledMethod) DefaultInlineOracle(org.jikesrvm.compilers.opt.inlining.DefaultInlineOracle) InlineOracle(org.jikesrvm.compilers.opt.inlining.InlineOracle) 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) ObjectConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ObjectConstantOperand) ClassConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ClassConstantOperand) OptOptions(org.jikesrvm.compilers.opt.OptOptions) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) OptCompiledMethod(org.jikesrvm.compilers.opt.runtimesupport.OptCompiledMethod) CompiledMethod(org.jikesrvm.compilers.common.CompiledMethod) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) ExceptionHandlerBasicBlockBag(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlockBag) NormalMethod(org.jikesrvm.classloader.NormalMethod) DefaultInlineOracle(org.jikesrvm.compilers.opt.inlining.DefaultInlineOracle) InlineSequence(org.jikesrvm.compilers.opt.inlining.InlineSequence) Test(org.junit.Test)

Example 7 with ExceptionHandlerBasicBlockBag

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

the class GenerationContextTest method inliningInstanceMethodWithNarrowingOfReferenceParam.

@Test
public void inliningInstanceMethodWithNarrowingOfReferenceParam() throws Exception {
    NormalMethod nm = getNormalMethodForTest("methodForInliningTests");
    CompiledMethod cm = new OptCompiledMethod(-1, nm);
    OptOptions opts = new OptOptions();
    InlineOracle io = new DefaultInlineOracle();
    GenerationContext gc = new GenerationContext(nm, null, cm, opts, io);
    Class<?>[] argumentTypes = { MethodsForTests.class };
    NormalMethod callee = getNormalMethodForTest("emptyStaticMethodWithReferenceParam", argumentTypes);
    MethodOperand methOp = MethodOperand.VIRTUAL(callee.getMemberRef().asMethodReference(), callee);
    Instruction callInstr = Call.create(CALL, null, null, methOp, 1);
    RegisterOperand objectParam = createMockRegisterOperand(TypeReference.JavaLangObject);
    assertFalse(objectParam.isPreciseType());
    assertFalse(objectParam.isDeclaredType());
    objectParam.setPreciseType();
    Call.setParam(callInstr, 0, objectParam);
    RegisterOperand objectParamCopy = objectParam.copy().asRegister();
    callInstr.setPosition(new InlineSequence(nm));
    ExceptionHandlerBasicBlockBag ebag = getMockEbag();
    int nodeNumber = 12345;
    gc.getCfg().setNumberOfNodes(nodeNumber);
    GenerationContext child = gc.createChildContext(ebag, callee, callInstr);
    assertThatStateIsCopiedFromParentToChild(gc, callee, child, ebag);
    assertThatReturnValueIsVoid(child);
    RegisterOperand objectParamArg = child.getArguments()[0].asRegister();
    TypeReference calleeClass = callee.getDeclaringClass().getTypeRef();
    assertThatRegOpWasNarrowedToCalleeClass(objectParamArg, calleeClass);
    RegisterOperand expectedLocalForObjectParam = child.makeLocal(0, objectParamArg);
    assertTrue(objectParamArg.sameRegisterPropertiesAs(expectedLocalForObjectParam));
    InlineSequence expectedInlineSequence = new InlineSequence(callee, callInstr.position(), callInstr);
    assertEquals(expectedInlineSequence, child.getInlineSequence());
    assertThatPrologueAndEpilogueAreWiredCorrectlyForChildContext(ebag, nodeNumber, child);
    Enumeration<Instruction> prologueRealInstr = child.getPrologue().forwardRealInstrEnumerator();
    Instruction objectMove = prologueRealInstr.nextElement();
    narrowRegOpToCalleeClass(objectParamCopy, calleeClass);
    assertMoveOperationIsCorrect(callInstr, REF_MOVE, expectedLocalForObjectParam, objectParamCopy, objectMove);
    assertThatNoMoreInstructionsExist(prologueRealInstr);
    BasicBlock epilogue = child.getEpilogue();
    assertThatEpilogueLabelIsCorrectForInlinedMethod(child, expectedInlineSequence, epilogue);
    assertThatEpilogueIsEmpty(epilogue);
    assertThatNoRethrowBlockExists(child);
    assertThatChecksWontBeSkipped(gc);
}
Also used : OptCompiledMethod(org.jikesrvm.compilers.opt.runtimesupport.OptCompiledMethod) DefaultInlineOracle(org.jikesrvm.compilers.opt.inlining.DefaultInlineOracle) InlineOracle(org.jikesrvm.compilers.opt.inlining.InlineOracle) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) ExceptionHandlerBasicBlock(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock) OptOptions(org.jikesrvm.compilers.opt.OptOptions) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) OptCompiledMethod(org.jikesrvm.compilers.opt.runtimesupport.OptCompiledMethod) CompiledMethod(org.jikesrvm.compilers.common.CompiledMethod) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) ExceptionHandlerBasicBlockBag(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlockBag) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) NormalMethod(org.jikesrvm.classloader.NormalMethod) DefaultInlineOracle(org.jikesrvm.compilers.opt.inlining.DefaultInlineOracle) InlineSequence(org.jikesrvm.compilers.opt.inlining.InlineSequence) TypeReference(org.jikesrvm.classloader.TypeReference) Test(org.junit.Test)

Example 8 with ExceptionHandlerBasicBlockBag

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

the class GenerationContextTest method inliningInstanceMethodWithRegisterReceiverNoNarrowing.

@Test
public void inliningInstanceMethodWithRegisterReceiverNoNarrowing() throws Exception {
    NormalMethod nm = getNormalMethodForTest("methodForInliningTests");
    CompiledMethod cm = new OptCompiledMethod(-1, nm);
    OptOptions opts = new OptOptions();
    InlineOracle io = new DefaultInlineOracle();
    GenerationContext gc = new GenerationContext(nm, null, cm, opts, io);
    Class<?>[] argumentTypes = { Object.class, double.class, int.class, long.class };
    NormalMethod callee = getNormalMethodForTest("emptyInstanceMethodWithParams", argumentTypes);
    MethodOperand methOp = MethodOperand.VIRTUAL(callee.getMemberRef().asMethodReference(), callee);
    Instruction callInstr = Call.create(CALL, null, null, methOp, 5);
    RegisterOperand receiver = createMockRegisterOperand(callee.getDeclaringClass().getTypeRef());
    assertFalse(receiver.isPreciseType());
    assertFalse(receiver.isDeclaredType());
    receiver.setPreciseType();
    Call.setParam(callInstr, 0, receiver);
    RegisterOperand objectParam = prepareCallWithObjectParam(callInstr);
    RegisterOperand doubleParam = prepareCallWithDoubleParam(callInstr);
    RegisterOperand intParam = prepareCallWithIntParam(callInstr);
    RegisterOperand longParam = prepareCallWithLongParam(callInstr);
    callInstr.setPosition(new InlineSequence(nm));
    ExceptionHandlerBasicBlockBag ebag = getMockEbag();
    int nodeNumber = 12345;
    gc.getCfg().setNumberOfNodes(nodeNumber);
    GenerationContext child = gc.createChildContext(ebag, callee, callInstr);
    assertThatStateIsCopiedFromParentToChild(gc, callee, child, ebag);
    assertThatReturnValueIsVoid(child);
    RegisterOperand thisArg = child.getArguments()[0].asRegister();
    TypeReference calleeClass = callee.getDeclaringClass().getTypeRef();
    assertSame(thisArg.getType(), calleeClass);
    RegisterOperand expectedLocalForReceiverParam = child.makeLocal(0, thisArg);
    assertTrue(thisArg.sameRegisterPropertiesAs(expectedLocalForReceiverParam));
    RegisterOperand firstArg = child.getArguments()[1].asRegister();
    RegisterOperand expectedLocalForObjectParam = child.makeLocal(1, firstArg);
    assertTrue(firstArg.sameRegisterPropertiesAs(expectedLocalForObjectParam));
    RegisterOperand secondArg = child.getArguments()[2].asRegister();
    RegisterOperand expectedLocalForDoubleParam = child.makeLocal(2, secondArg);
    assertTrue(secondArg.sameRegisterPropertiesAs(expectedLocalForDoubleParam));
    RegisterOperand thirdArg = child.getArguments()[3].asRegister();
    RegisterOperand expectedLocalForIntParam = child.makeLocal(4, thirdArg);
    assertTrue(thirdArg.sameRegisterPropertiesAs(expectedLocalForIntParam));
    RegisterOperand fourthArg = child.getArguments()[4].asRegister();
    RegisterOperand expectedLocalForLongParam = child.makeLocal(5, fourthArg);
    assertTrue(fourthArg.sameRegisterPropertiesAs(expectedLocalForLongParam));
    InlineSequence expectedInlineSequence = new InlineSequence(callee, callInstr.position(), callInstr);
    assertEquals(expectedInlineSequence, child.getInlineSequence());
    assertThatPrologueAndEpilogueAreWiredCorrectlyForChildContext(ebag, nodeNumber, child);
    Enumeration<Instruction> prologueRealInstr = child.getPrologue().forwardRealInstrEnumerator();
    Instruction receiverMove = prologueRealInstr.nextElement();
    RegisterOperand expectedReceiver = receiver.copy().asRegister();
    assertMoveOperationIsCorrect(callInstr, REF_MOVE, expectedLocalForReceiverParam, expectedReceiver, receiverMove);
    Instruction objectMove = prologueRealInstr.nextElement();
    RegisterOperand objectParamCopy = objectParam.copy().asRegister();
    assertMoveOperationIsCorrect(callInstr, REF_MOVE, expectedLocalForObjectParam, objectParamCopy, objectMove);
    Instruction doubleMove = prologueRealInstr.nextElement();
    RegisterOperand doubleParamCopy = doubleParam.copy().asRegister();
    assertMoveOperationIsCorrect(callInstr, DOUBLE_MOVE, expectedLocalForDoubleParam, doubleParamCopy, doubleMove);
    Instruction intMove = prologueRealInstr.nextElement();
    RegisterOperand intParamCopy = intParam.copy().asRegister();
    assertMoveOperationIsCorrect(callInstr, INT_MOVE, expectedLocalForIntParam, intParamCopy, intMove);
    Instruction longMove = prologueRealInstr.nextElement();
    RegisterOperand longParamCopy = longParam.copy().asRegister();
    assertMoveOperationIsCorrect(callInstr, LONG_MOVE, expectedLocalForLongParam, longParamCopy, longMove);
    assertThatNoMoreInstructionsExist(prologueRealInstr);
    BasicBlock epilogue = child.getEpilogue();
    assertThatEpilogueLabelIsCorrectForInlinedMethod(child, expectedInlineSequence, epilogue);
    assertThatEpilogueIsEmpty(epilogue);
    assertThatNoRethrowBlockExists(child);
    assertThatChecksWontBeSkipped(gc);
}
Also used : OptCompiledMethod(org.jikesrvm.compilers.opt.runtimesupport.OptCompiledMethod) DefaultInlineOracle(org.jikesrvm.compilers.opt.inlining.DefaultInlineOracle) InlineOracle(org.jikesrvm.compilers.opt.inlining.InlineOracle) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) ExceptionHandlerBasicBlock(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock) OptOptions(org.jikesrvm.compilers.opt.OptOptions) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) OptCompiledMethod(org.jikesrvm.compilers.opt.runtimesupport.OptCompiledMethod) CompiledMethod(org.jikesrvm.compilers.common.CompiledMethod) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) ExceptionHandlerBasicBlockBag(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlockBag) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) NormalMethod(org.jikesrvm.classloader.NormalMethod) DefaultInlineOracle(org.jikesrvm.compilers.opt.inlining.DefaultInlineOracle) InlineSequence(org.jikesrvm.compilers.opt.inlining.InlineSequence) TypeReference(org.jikesrvm.classloader.TypeReference) Test(org.junit.Test)

Example 9 with ExceptionHandlerBasicBlockBag

use of org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlockBag 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 10 with ExceptionHandlerBasicBlockBag

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

the class BBSet method finalPass.

/**
 * Do a final pass over the generated basic blocks to create
 * the initial code ordering. All blocks generated for the method
 * will be inserted after gc.prologue.
 * <p>
 * NOTE: Only some CFG edges are created here.....
 * we're mainly just patching together a code linearization.
 *
 * @param inlinedSomething was a normal method (i.e. non-magic) inlined?
 */
void finalPass(boolean inlinedSomething) {
    BBSet.TreeEnumerator e = TreeEnumerator.enumFromRoot(root);
    BasicBlock cop = gc.getPrologue();
    BasicBlockLE curr = getEntry();
    BasicBlockLE next = null;
    top: while (true) {
        // inject synthetic entry block too.
        if (curr instanceof HandlerBlockLE) {
            // tell our caller that we actually put a handler in the final CFG.
            gc.markExceptionHandlersAsGenerated();
            HandlerBlockLE hcurr = (HandlerBlockLE) curr;
            if (DBG_FLATTEN) {
                db("injecting handler entry block " + hcurr.entryBlock + " before " + hcurr);
            }
            gc.getCfg().insertAfterInCodeOrder(cop, hcurr.entryBlock);
            cop = hcurr.entryBlock;
        }
        // Step 1: Insert curr in the code order (after cop, updating cop).
        if (DBG_FLATTEN)
            db("flattening: " + curr + " (" + curr.block + ")");
        curr.setInCodeOrder();
        gc.getCfg().insertAfterInCodeOrder(cop, curr.block);
        cop = curr.block;
        if (DBG_FLATTEN) {
            db("Current Code order for " + gc.getMethod() + "\n");
            for (BasicBlock bb = gc.getPrologue(); bb != null; bb = (BasicBlock) bb.getNext()) {
                VM.sysWriteln(bb.toString());
            }
        }
        // make a new, filtered EHBBB to avoid later confusion.
        if (curr.handlers != null) {
            int notGenerated = 0;
            for (HandlerBlockLE handler : curr.handlers) {
                if (!handler.isGenerated()) {
                    if (DBG_EX || DBG_FLATTEN) {
                        db("Will remove unreachable handler " + handler + " from " + curr);
                    }
                    notGenerated++;
                }
            }
            if (notGenerated > 0) {
                if (notGenerated == curr.handlers.length) {
                    if (DBG_EX || DBG_FLATTEN) {
                        db("No (local) handlers were actually reachable for " + curr + "; setting to caller");
                    }
                    curr.block.setExceptionHandlers(curr.block.exceptionHandlers().getCaller());
                } else {
                    ExceptionHandlerBasicBlock[] nlh = new ExceptionHandlerBasicBlock[curr.handlers.length - notGenerated];
                    for (int i = 0, j = 0; i < curr.handlers.length; i++) {
                        if (curr.handlers[i].isGenerated()) {
                            nlh[j++] = curr.handlers[i].entryBlock;
                        } else {
                            if (VM.VerifyAssertions) {
                                VM._assert(curr.handlers[i].entryBlock.hasZeroIn(), "Non-generated handler with CFG edges");
                            }
                        }
                    }
                    curr.block.setExceptionHandlers(new ExceptionHandlerBasicBlockBag(nlh, curr.block.exceptionHandlers().getCaller()));
                }
            }
        }
        // all fits together....--dave
        if (curr.fallThrough != null && curr.fallThrough instanceof InliningBlockLE) {
            InliningBlockLE icurr = (InliningBlockLE) curr.fallThrough;
            BasicBlock forw = cop.nextBasicBlockInCodeOrder();
            BasicBlock calleeEntry = icurr.gc.getCfg().firstInCodeOrder();
            BasicBlock calleeExit = icurr.gc.getCfg().lastInCodeOrder();
            gc.getCfg().breakCodeOrder(cop, forw);
            gc.getCfg().linkInCodeOrder(cop, icurr.gc.getCfg().firstInCodeOrder());
            gc.getCfg().linkInCodeOrder(icurr.gc.getCfg().lastInCodeOrder(), forw);
            if (DBG_CFG || BC2IR.DBG_SELECTED) {
                db("Added CFG edge from " + cop + " to " + calleeEntry);
            }
            if (icurr.epilogueBBLE != null) {
                if (DBG_FLATTEN) {
                    db("injected " + icurr + " between " + curr + " and " + icurr.epilogueBBLE.fallThrough);
                }
                if (VM.VerifyAssertions) {
                    VM._assert(icurr.epilogueBBLE.block == icurr.gc.getCfg().lastInCodeOrder());
                }
                curr = icurr.epilogueBBLE;
                cop = curr.block;
            } else {
                if (DBG_FLATTEN)
                    db("injected " + icurr + " after " + curr);
                curr = icurr;
                cop = calleeExit;
            }
        }
        next = curr.fallThrough;
        if (DBG_FLATTEN && next == null) {
            db(curr + " has no fallthrough case, getting next block");
        }
        if (next != null) {
            if (DBG_CFG || BC2IR.DBG_SELECTED) {
                db("Added CFG edge from " + curr.block + " to " + next.block);
            }
            if (next.isInCodeOrder()) {
                if (DBG_FLATTEN) {
                    db("fallthrough " + next + " is already flattened, adding goto");
                }
                curr.block.appendInstruction(next.block.makeGOTO());
                // set next to null to indicate no "real" fall through
                next = null;
            }
        }
        if (next == null) {
            // Can't process fallthroughblock, so get next BBLE from enumeration
            while (true) {
                if (!e.hasMoreElements()) {
                    // all done.
                    if (DBG_FLATTEN)
                        db("no more blocks! all done");
                    break top;
                }
                next = e.next();
                if (DBG_FLATTEN)
                    db("looking at " + next);
                if (!next.isGenerated()) {
                    if (DBG_FLATTEN)
                        db("block " + next + " was not generated");
                    continue;
                }
                if (!next.isInCodeOrder()) {
                    break;
                }
            }
            if (DBG_FLATTEN)
                db("found unflattened block: " + next);
        }
        curr = next;
    }
    // If the epilogue was unreachable, remove it from the code order and cfg
    // and set gc.epilogue to null.
    boolean removedSomethingFromCodeOrdering = inlinedSomething;
    if (gc.getEpilogue().hasZeroIn()) {
        if (DBG_FLATTEN || DBG_CFG) {
            db("Deleting unreachable epilogue " + gc.getEpilogue());
        }
        gc.getCfg().removeFromCodeOrder(gc.getEpilogue());
        removedSomethingFromCodeOrdering = true;
        // remove the node from the graph AND adjust its edge info
        gc.getEpilogue().remove();
        gc.getEpilogue().deleteIn();
        gc.getEpilogue().deleteOut();
        if (VM.VerifyAssertions)
            VM._assert(gc.getEpilogue().hasZeroOut());
        gc.setEpilogue(null);
    }
    // if gc has an unlockAndRethrow block that was not used, then remove it
    if (gc.getUnlockAndRethrow() != null && gc.getUnlockAndRethrow().hasZeroIn()) {
        gc.getCfg().removeFromCFGAndCodeOrder(gc.getUnlockAndRethrow());
        removedSomethingFromCodeOrdering = true;
        gc.getEnclosingHandlers().remove(gc.getUnlockAndRethrow());
    }
    // if we removed a basic block then we should compact the node numbering
    if (removedSomethingFromCodeOrdering) {
        gc.getCfg().compactNodeNumbering();
    }
    if (DBG_FLATTEN) {
        db("Current Code order for " + gc.getMethod() + "\n");
        for (BasicBlock bb = gc.getPrologue(); bb != null; bb = (BasicBlock) bb.getNext()) {
            bb.printExtended();
        }
    }
    if (DBG_FLATTEN) {
        db("Final CFG for " + gc.getMethod() + "\n");
        gc.getCfg().printDepthFirst();
    }
}
Also used : ExceptionHandlerBasicBlock(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) ExceptionHandlerBasicBlockBag(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlockBag)

Aggregations

ExceptionHandlerBasicBlockBag (org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlockBag)22 Instruction (org.jikesrvm.compilers.opt.ir.Instruction)16 Test (org.junit.Test)16 NormalMethod (org.jikesrvm.classloader.NormalMethod)15 CompiledMethod (org.jikesrvm.compilers.common.CompiledMethod)14 OptOptions (org.jikesrvm.compilers.opt.OptOptions)14 DefaultInlineOracle (org.jikesrvm.compilers.opt.inlining.DefaultInlineOracle)14 InlineOracle (org.jikesrvm.compilers.opt.inlining.InlineOracle)14 OptCompiledMethod (org.jikesrvm.compilers.opt.runtimesupport.OptCompiledMethod)14 ExceptionHandlerBasicBlock (org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock)10 MethodOperand (org.jikesrvm.compilers.opt.ir.operand.MethodOperand)10 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)10 InlineSequence (org.jikesrvm.compilers.opt.inlining.InlineSequence)9 BasicBlock (org.jikesrvm.compilers.opt.ir.BasicBlock)9 TypeReference (org.jikesrvm.classloader.TypeReference)4 ClassConstantOperand (org.jikesrvm.compilers.opt.ir.operand.ClassConstantOperand)4 Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)4 TrueGuardOperand (org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand)4 TypeOperand (org.jikesrvm.compilers.opt.ir.operand.TypeOperand)4 ObjectConstantOperand (org.jikesrvm.compilers.opt.ir.operand.ObjectConstantOperand)3