Search in sources :

Example 6 with ExceptionHandlerBasicBlock

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

the class GenerationContextTest method assertThatUnlockAndRethrowBlockIsCorrectForInlinedMethod.

private void assertThatUnlockAndRethrowBlockIsCorrectForInlinedMethod(GenerationContext parentContext, GenerationContext childContext, InlineSequence inlineSequence, BasicBlock prologue, Operand lockObject, BasicBlock epilogue) {
    ExceptionHandlerBasicBlockBag ehbb = childContext.getEnclosingHandlers();
    Enumeration<BasicBlock> enumerator = ehbb.enumerator();
    assertThat(childContext.getUnlockAndRethrow().exceptionHandlers(), is(parentContext.getEnclosingHandlers()));
    ExceptionHandlerBasicBlock rethrow = (ExceptionHandlerBasicBlock) enumerator.nextElement();
    assertSame(rethrow, childContext.getUnlockAndRethrow());
    assertThatRethrowBlockIsCorrect(inlineSequence, lockObject, rethrow);
    checkCodeOrderForRethrowBlock(childContext, prologue, epilogue, rethrow);
    ExceptionHandlerBasicBlockBag parentHandlers = parentContext.getEnclosingHandlers();
    Enumeration<BasicBlock> parentHandlerBBEnum = parentHandlers.enumerator();
    HashSet<BasicBlock> parentHandlerBBs = new HashSet<BasicBlock>();
    while (parentHandlerBBEnum.hasMoreElements()) {
        parentHandlerBBs.add(parentHandlerBBEnum.nextElement());
    }
    BasicBlock childRethrow = childContext.getUnlockAndRethrow();
    OutEdgeEnumeration outEdges = childRethrow.outEdges();
    boolean linkedToAllBlocksFromParentHandler = true;
    while (outEdges.hasMoreElements()) {
        BasicBlock target = (BasicBlock) outEdges.nextElement().to();
        if (!parentHandlerBBs.contains(target) && target != childContext.getExit()) {
            linkedToAllBlocksFromParentHandler = false;
            break;
        }
    }
    assertTrue(linkedToAllBlocksFromParentHandler);
    ExceptionHandlerBasicBlockBag ehbbb = childContext.getEnclosingHandlers();
    assertSame(parentContext.getEnclosingHandlers(), ehbbb.getCaller());
    assertThatEnclosingHandlersContainRethrow(rethrow, ehbbb);
}
Also used : OutEdgeEnumeration(org.jikesrvm.compilers.opt.util.SpaceEffGraphNode.OutEdgeEnumeration) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) ExceptionHandlerBasicBlock(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock) ExceptionHandlerBasicBlock(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock) ExceptionHandlerBasicBlockBag(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlockBag) HashSet(java.util.HashSet)

Example 7 with ExceptionHandlerBasicBlock

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

use of org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock 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)

Example 9 with ExceptionHandlerBasicBlock

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

the class BBSet method initializeExceptionHandlers.

/**
 * Initialize bble's handlers array based on startPCs/endPCs.
 * In the process, new HandlerBlockLE's may be created
 * (by the call to getOrCreateBlock). <p>
 * PRECONDITION: bble.low and bble.max have already been correctly
 * set to reflect the invariant that a basic block is in exactly one
 * "handler range."<p>
 * Also initializes bble.block.exceptionHandlers.
 *
 * @param bble the block whose handlers are to be initialized
 * @param simLocals local variables
 */
private void initializeExceptionHandlers(BasicBlockLE bble, Operand[] simLocals) {
    if (startPCs != null) {
        HashSet<TypeReference> caughtTypes = new HashSet<TypeReference>();
        for (int i = 0; i < startPCs.length; i++) {
            TypeReference caughtType = exceptionTypes[i].getTypeRef();
            if (bble.low >= startPCs[i] && bble.max <= endPCs[i] && !caughtTypes.contains(caughtType)) {
                // bble's basic block is contained within this handler's range.
                HandlerBlockLE eh = (HandlerBlockLE) getOrCreateBlock(handlerPCs[i], bble, null, simLocals);
                if (DBG_EX)
                    db("Adding handler " + eh + " to " + bble);
                caughtTypes.add(caughtType);
                bble.addHandler(eh);
            }
        }
    }
    if (bble.handlers != null) {
        ExceptionHandlerBasicBlock[] ehbbs = new ExceptionHandlerBasicBlock[bble.handlers.length];
        for (int i = 0; i < bble.handlers.length; i++) {
            ehbbs[i] = bble.handlers[i].entryBlock;
        }
        bble.block.setExceptionHandlers(new ExceptionHandlerBasicBlockBag(ehbbs, gc.getEnclosingHandlers()));
    } else {
        bble.block.setExceptionHandlers(gc.getEnclosingHandlers());
    }
}
Also used : TypeReference(org.jikesrvm.classloader.TypeReference) ExceptionHandlerBasicBlock(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock) HashSet(java.util.HashSet) ExceptionHandlerBasicBlockBag(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlockBag)

Example 10 with ExceptionHandlerBasicBlock

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

the class BC2IR method rectifyStateWithExceptionHandlers.

/*
   * Very similar to the above, but since we aren't told what might be thrown,
   * we are forced to connect to every in scope handler and can't
   * identify a definite target.
   *
   */
private void rectifyStateWithExceptionHandlers(boolean linkToExitIfUncaught) {
    currentBBLE.block.setCanThrowExceptions();
    currentBBLE.block.setMayThrowUncaughtException();
    if (linkToExitIfUncaught) {
        if (DBG_EX) {
            db("PEI of unknown type caused edge from " + currentBBLE + " to outermost exit");
        }
        currentBBLE.block.insertOut(gc.getExit());
        if (DBG_CFG || DBG_SELECTED) {
            db("Added CFG edge from " + currentBBLE.block + " to exit");
        }
    }
    if (currentBBLE.handlers != null) {
        for (HandlerBlockLE xbble : currentBBLE.handlers) {
            if (DBG_EX) {
                db("PEI of unknown type could be caught by " + xbble + " rectifying locals");
            }
            blocks.rectifyLocals(_localState, xbble);
            currentBBLE.block.insertOut(xbble.entryBlock);
            if (DBG_CFG || DBG_SELECTED) {
                db("Added CFG edge from " + currentBBLE.block + " to " + xbble.entryBlock);
            }
        }
    }
    // Now, consider the enclosing exception context; ditto NOTE above.
    if (gc.getEnclosingHandlers() != null) {
        for (Enumeration<BasicBlock> e = gc.getEnclosingHandlers().enumerator(); e.hasMoreElements(); ) {
            ExceptionHandlerBasicBlock xbb = (ExceptionHandlerBasicBlock) e.nextElement();
            if (DBG_EX) {
                db("PEI of unknown type could be caught by enclosing handler " + xbb);
            }
            currentBBLE.block.insertOut(xbb);
            if (DBG_CFG || DBG_SELECTED) {
                db("Added CFG edge from " + currentBBLE.block + " to " + xbb);
            }
        }
    }
}
Also used : BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) ExceptionHandlerBasicBlock(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock) ExceptionHandlerBasicBlock(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock)

Aggregations

ExceptionHandlerBasicBlock (org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock)17 BasicBlock (org.jikesrvm.compilers.opt.ir.BasicBlock)16 ExceptionHandlerBasicBlockBag (org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlockBag)6 Instruction (org.jikesrvm.compilers.opt.ir.Instruction)5 HashSet (java.util.HashSet)2 TypeReference (org.jikesrvm.classloader.TypeReference)2 Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)2 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)2 TypeOperand (org.jikesrvm.compilers.opt.ir.operand.TypeOperand)2 OutEdgeEnumeration (org.jikesrvm.compilers.opt.util.SpaceEffGraphNode.OutEdgeEnumeration)2 RVMMethod (org.jikesrvm.classloader.RVMMethod)1 GenerationContext (org.jikesrvm.compilers.opt.bc2ir.GenerationContext)1 OsrPoint (org.jikesrvm.compilers.opt.ir.OsrPoint)1 RegSpillListElement (org.jikesrvm.compilers.opt.ir.RegSpillListElement)1 Register (org.jikesrvm.compilers.opt.ir.Register)1 PhysicalRegisterSet (org.jikesrvm.compilers.opt.ir.ia32.PhysicalRegisterSet)1 AddressConstantOperand (org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand)1 BasicBlockOperand (org.jikesrvm.compilers.opt.ir.operand.BasicBlockOperand)1 BranchProfileOperand (org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand)1 ClassConstantOperand (org.jikesrvm.compilers.opt.ir.operand.ClassConstantOperand)1