Search in sources :

Example 11 with ExceptionHandlerBasicBlock

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

the class LICM method perform.

/**
 * Execute loop invariant code motion on the given IR.
 */
@Override
public void perform(IR ir) {
    this.ir = ir;
    if (DEBUG && ir.hasReachableExceptionHandlers()) {
        VM.sysWriteln("] " + ir.method);
        (new LiveAnalysis(false, false, true, false)).perform(ir);
        Enumeration<BasicBlock> e = ir.getBasicBlocks();
        while (e.hasMoreElements()) {
            BasicBlock b = e.nextElement();
            if (b instanceof ExceptionHandlerBasicBlock) {
                VM.sysWriteln("] " + b + ": " + ((ExceptionHandlerBasicBlock) b).getLiveSet());
            }
        }
    }
    if (ir.hasReachableExceptionHandlers() || GCP.tooBig(ir)) {
        resetLandingPads();
        return;
    }
    VERBOSE = ir.options.DEBUG_GCP;
    if (VERBOSE && ir.options.hasMETHOD_TO_PRINT()) {
        VERBOSE = ir.options.fuzzyMatchMETHOD_TO_PRINT(ir.method.toString());
        if (!VERBOSE) {
            resetLandingPads();
            return;
        }
    }
    if (VERBOSE)
        VM.sysWriteln("] " + ir.method);
    initialize(ir);
    if (VERBOSE)
        SSA.printInstructions(ir);
    Instruction inst = ir.firstInstructionInCodeOrder();
    while (inst != null) {
        Instruction next = inst.nextInstructionInCodeOrder();
        if (DEBUG)
            System.out.println("scheduleEarly: " + inst);
        scheduleEarly(inst);
        inst = next;
    }
    inst = ir.lastInstructionInCodeOrder();
    while (inst != null) {
        Instruction next = inst.prevInstructionInCodeOrder();
        scheduleLate(inst);
        inst = next;
    }
    resetLandingPads();
    if (DEBUG)
        SSA.printInstructions(ir);
    ir.actualSSAOptions.setScalarValid(false);
}
Also used : LiveAnalysis(org.jikesrvm.compilers.opt.liveness.LiveAnalysis) ExceptionHandlerBasicBlock(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) ExceptionHandlerBasicBlock(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock) Instruction(org.jikesrvm.compilers.opt.ir.Instruction)

Example 12 with ExceptionHandlerBasicBlock

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

the class OptExceptionTable method encode.

/**
 * Encode an exception table
 * @param ir the IR to encode the exception table for
 * @return the encoded exception table
 */
static int[] encode(IR ir) {
    int index = 0;
    int currStartOff, currEndOff;
    int tableSize = countExceptionTableSize(ir);
    int[] eTable = new int[tableSize * 4];
    MachineCodeOffsets mcOffsets = ir.MIRInfo.mcOffsets;
    // throw a subset of the exception types represented by the Bag
    for (BasicBlock bblock = ir.firstBasicBlockInCodeOrder(); bblock != null; ) {
        // Iteration is explicit in loop
        int startOff = mcOffsets.getMachineCodeOffset(bblock.firstInstruction());
        int endOff = mcOffsets.getMachineCodeOffset(bblock.lastInstruction());
        if (endOff > startOff) {
            if (!bblock.hasExceptionHandlers()) {
                bblock = bblock.nextBasicBlockInCodeOrder();
                continue;
            }
            BasicBlock followonBB;
            Enumeration<BasicBlock> reachBBe, e;
            boolean joinedBlocks;
            // First make sure at least one of the exception handlers
            // is reachable from this block
            reachBBe = bblock.getReachableExceptionHandlers();
            if (!reachBBe.hasMoreElements()) {
                bblock = bblock.nextBasicBlockInCodeOrder();
                continue;
            }
            currStartOff = startOff;
            currEndOff = endOff;
            joinedBlocks = false;
            for (followonBB = bblock.nextBasicBlockInCodeOrder(); followonBB != null; followonBB = followonBB.nextBasicBlockInCodeOrder()) {
                int fStartOff = mcOffsets.getMachineCodeOffset(followonBB.firstInstruction());
                int fEndOff = mcOffsets.getMachineCodeOffset(followonBB.lastInstruction());
                // See if followon Block has any code
                if (fEndOff > fStartOff) {
                    // See if followon Block has matching handler block bag
                    if (followonBB.hasExceptionHandlers() && bblock.isExceptionHandlerEquivalent(followonBB)) {
                        currEndOff = fEndOff;
                        joinedBlocks = true;
                    } else {
                        // Can't join any more blocks together
                        break;
                    }
                }
            }
            // Now fill in the eTable with the handlers
            if (joinedBlocks) {
                e = bblock.getExceptionHandlers();
            } else {
                e = reachBBe;
            }
            while (e.hasMoreElements()) {
                ExceptionHandlerBasicBlock eBlock = (ExceptionHandlerBasicBlock) e.nextElement();
                for (java.util.Enumeration<TypeOperand> ets = eBlock.getExceptionTypes(); ets.hasMoreElements(); ) {
                    TypeOperand type = ets.nextElement();
                    Instruction label = eBlock.firstInstruction();
                    int catchOffset;
                    if (mcOffsets.lacksMachineCodeOffset(label)) {
                        // handler block was removed from the IR and is unreachable.
                        // Make sure that we can recognize this as an error at runtime
                        // if the catch block is actually reachable.
                        catchOffset = UNREACHABLE_CATCH_BLOCK;
                    } else {
                        catchOffset = mcOffsets.getMachineCodeOffset(label);
                    }
                    eTable[index + TRY_START] = currStartOff;
                    eTable[index + TRY_END] = currEndOff;
                    eTable[index + CATCH_START] = catchOffset;
                    try {
                        eTable[index + EX_TYPE] = type.getTypeRef().resolve().getId();
                    } catch (NoClassDefFoundError except) {
                        // For now, we are forcing early loading of exception
                        // types to avoid a bunch of ugly issues in resolving the type
                        // when delivering the exception.  The problem is that we
                        // currently can't allow a GC while in the midst of delivering
                        // an exception and resolving the type reference might entail
                        // calling arbitrary classloader code.
                        VM.sysWriteln("Trouble resolving a caught exception at compile time:");
                        // sysFail won't print the stack trace
                        except.printStackTrace();
                        // that lead to the
                        // NoClassDefFoundError.
                        VM.sysFail("Unable to resolve caught exception type at compile time");
                    }
                    index += 4;
                }
            }
            bblock = followonBB;
        } else {
            // No code in bblock
            bblock = bblock.nextBasicBlockInCodeOrder();
        }
    }
    if (index != eTable.length) {
        // resize array
        int[] newETable = new int[index];
        for (int i = 0; i < index; i++) {
            newETable[i] = eTable[i];
        }
        eTable = newETable;
    }
    return eTable;
}
Also used : TypeOperand(org.jikesrvm.compilers.opt.ir.operand.TypeOperand) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) ExceptionHandlerBasicBlock(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock) MachineCodeOffsets(org.jikesrvm.compilers.opt.mir2mc.MachineCodeOffsets) ExceptionHandlerBasicBlock(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock) Instruction(org.jikesrvm.compilers.opt.ir.Instruction)

Example 13 with ExceptionHandlerBasicBlock

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

the class ExpandFPRStackConvention method perform.

/**
 * Insert the needed dummy defs and uses.
 */
@Override
public void perform(IR ir) {
    if (SSE2_FULL) {
        return;
    }
    PhysicalRegisterSet phys = (PhysicalRegisterSet) ir.regpool.getPhysicalRegisterSet();
    for (Enumeration<BasicBlock> b = ir.getBasicBlocks(); b.hasMoreElements(); ) {
        BasicBlock bb = b.nextElement();
        if (bb instanceof ExceptionHandlerBasicBlock) {
            // clear all floating-point state at the entry to a catch block
            for (int i = 0; i < NUM_ALLOCATABLE_FPR; i++) {
                Register fpr = phys.getFPR(i);
                bb.prependInstruction(MIR_UnaryNoRes.create(DUMMY_USE, IRTools.D(fpr)));
                bb.prependInstruction(MIR_Nullary.create(DUMMY_DEF, IRTools.D(fpr)));
            }
        }
        // The following holds the floating point stack offset from its
        // 'normal' position.
        int fpStackOffset = 0;
        for (Enumeration<Instruction> inst = bb.forwardInstrEnumerator(); inst.hasMoreElements(); ) {
            Instruction s = inst.nextElement();
            if (s.operator().isFpPop()) {
                // A pop instruction 'ends' a dummy live range.
                Register fpr = phys.getFPR(NUM_ALLOCATABLE_FPR - fpStackOffset);
                s.insertAfter(MIR_UnaryNoRes.create(DUMMY_USE, IRTools.D(fpr)));
                fpStackOffset--;
            } else if (s.operator().isFpPush()) {
                fpStackOffset++;
                Register fpr = phys.getFPR(NUM_ALLOCATABLE_FPR - fpStackOffset);
                s.insertBefore(MIR_Nullary.create(DUMMY_DEF, IRTools.D(fpr)));
            }
            if (VM.VerifyAssertions)
                VM._assert(fpStackOffset >= 0);
            if (VM.VerifyAssertions) {
                VM._assert(fpStackOffset < NUM_ALLOCATABLE_FPR);
            }
        }
    }
}
Also used : Register(org.jikesrvm.compilers.opt.ir.Register) PhysicalRegisterSet(org.jikesrvm.compilers.opt.ir.ia32.PhysicalRegisterSet) 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)

Example 14 with ExceptionHandlerBasicBlock

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

the class BC2IR method rectifyStateWithExceptionHandler.

// If exactly 1 catch block is guarenteed to catch the exception,
// then we return it.
// Returning null means that no such block was found.
private BasicBlock rectifyStateWithExceptionHandler(TypeReference exceptionType, boolean linkToExitIfUncaught) {
    currentBBLE.block.setCanThrowExceptions();
    int catchTargets = 0;
    if (DBG_EX)
        db("\tchecking exceptions of " + currentBBLE.block);
    if (currentBBLE.handlers != null) {
        for (HandlerBlockLE xbble : currentBBLE.handlers) {
            if (DBG_EX)
                db("\texception block " + xbble.entryBlock);
            byte mustCatch = xbble.mustCatchException(exceptionType);
            if (mustCatch != NO || xbble.mayCatchException(exceptionType) != NO) {
                if (DBG_EX) {
                    db("PEI of type " + exceptionType + " could be caught by " + xbble + " rectifying locals");
                }
                catchTargets++;
                blocks.rectifyLocals(_localState, xbble);
                currentBBLE.block.insertOut(xbble.entryBlock);
                if (DBG_CFG || DBG_SELECTED) {
                    db("Added CFG edge from " + currentBBLE.block + " to " + xbble.entryBlock);
                }
            }
            if (mustCatch == YES) {
                if (DBG_EX) {
                    db("\t" + xbble + " will defintely catch exceptions of type " + exceptionType);
                }
                if (DBG_EX && catchTargets == 1) {
                    db("\t  and it is the only target");
                }
                return (catchTargets == 1) ? xbble.entryBlock : null;
            }
        }
    }
    // See maybeInlineMethod.
    if (gc.getEnclosingHandlers() != null) {
        for (Enumeration<BasicBlock> e = gc.getEnclosingHandlers().enumerator(); e.hasMoreElements(); ) {
            ExceptionHandlerBasicBlock xbb = (ExceptionHandlerBasicBlock) e.nextElement();
            byte mustCatch = xbb.mustCatchException(exceptionType);
            if (mustCatch != NO || xbb.mayCatchException(exceptionType) != NO) {
                if (DBG_EX) {
                    db("PEI of type " + exceptionType + " could be caught by enclosing handler " + xbb);
                }
                catchTargets++;
                currentBBLE.block.insertOut(xbb);
                if (DBG_CFG || DBG_SELECTED) {
                    db("Added CFG edge from " + currentBBLE.block + " to " + xbb);
                }
            }
            if (mustCatch == YES) {
                if (DBG_EX) {
                    db("\t" + xbb + " will defintely catch exceptions of type " + exceptionType);
                }
                if (DBG_EX && catchTargets == 1) {
                    db("\t  and it is the only target");
                }
                return (catchTargets == 1) ? xbb : null;
            }
        }
    }
    // If we get to here, then we didn't find a handler block that
    // is guarenteed to catch the exception. Therefore deal with the
    // possibly uncaught exception.
    currentBBLE.block.setMayThrowUncaughtException();
    if (linkToExitIfUncaught) {
        if (DBG_EX) {
            db("added explicit 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");
        }
    }
    return null;
}
Also used : BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) ExceptionHandlerBasicBlock(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock) ExceptionHandlerBasicBlock(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock) OsrPoint(org.jikesrvm.compilers.opt.ir.OsrPoint)

Example 15 with ExceptionHandlerBasicBlock

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

the class LiveAnalysis method performLocalPropagation.

/**
 *  This method performs the last phase of the analysis, local propagation.
 *  It uses the results from the fixed point analysis to determine the
 *  local live information within a basic block.<p>
 *
 *  It walks the IR and, using the live information computed for each
 *  basic block, i.e., the results of the iterative solution, makes a single
 *  pass backward walk through the basic block, GENing and KILLing
 *  local information.  This produces the set of live variables at each
 *  instruction.<p>
 *
 *  This information is saved into two data structures:
 *  <ul>
 *    <li>at all GC points, live references are recorded
 *    <li>at all instructions, live range information is recorded
 *  </ul>
 *
 *  @param ir the IR
 *  @param createGCMaps whether GC maps need to be created
 */
private void performLocalPropagation(IR ir, boolean createGCMaps) {
    if (DEBUG) {
        System.out.println(" .... starting local propagation");
        System.out.println();
    }
    Stack<MapElement> blockStack = null;
    if (createGCMaps) {
        // We want to add GC map entries in IR instruction order. However, we are
        // visiting instructions in reverse order within a block. We solve this
        // by pushing all additions to a local stack and pop (and add)
        // the information to the GC map after the block has been processed.
        blockStack = new Stack<MapElement>();
    }
    for (BasicBlock block = ir.firstBasicBlockInCodeOrder(); block != null; block = block.nextBasicBlockInCodeOrder()) {
        if (VERBOSE) {
            System.out.print(" ....   processing block # " + block.getNumber() + " ...");
        }
        // This set will hold the live variables for the current
        // instruction.  It is initialized from the "In" set of the block's
        // successors and updated during the walk up the basic block.
        LiveSet local = new LiveSet();
        // The union of the IN sets of all exception blocks that can
        // be reached (directly) from this block
        LiveSet exceptionBlockSummary = new LiveSet();
        // statements in this block
        for (Enumeration<BasicBlock> bbEnum = block.getOut(); bbEnum.hasMoreElements(); ) {
            BasicBlock succ = bbEnum.nextElement();
            if (succ.isExceptionHandlerBasicBlock()) {
                exceptionBlockSummary.add(bbLiveInfo[succ.getNumber()].getIn());
            } else {
                local.add(bbLiveInfo[succ.getNumber()].getIn());
            }
        }
        if (VERBOSE) {
            System.out.println(" Completed succ walk. exceptionBlockSummary: " + exceptionBlockSummary + "\n local: " + local);
        }
        // For each item in "local", create live interval info for this block.
        liveIntervals.createEndLiveRange(local, block, null);
        // Process the block, an instruction at a time.
        for (Instruction inst = block.lastInstruction(); inst != block.firstInstruction(); inst = inst.prevInstructionInCodeOrder()) {
            if (VERBOSE) {
                System.out.println("Processing: " + inst);
            }
            // in "exceptionBlockSummary"
            if (inst.isPEI()) {
                local.add(exceptionBlockSummary);
                // For each item in "exceptionBlockSummary", create live interval
                // info for this block.
                liveIntervals.createEndLiveRange(exceptionBlockSummary, block, inst);
            }
            // Def loop
            for (Enumeration<Operand> defs = inst.getPureDefs(); defs.hasMoreElements(); ) {
                Operand op = defs.nextElement();
                if (op instanceof RegisterOperand) {
                    RegisterOperand regOp = (RegisterOperand) op;
                    // about validation reges.  (Reg Alloc cares about physical regs.)
                    if (isSkippableReg(regOp, ir)) {
                        continue;
                    }
                    if (regOp.getType() != null) {
                        // process the def as a kill
                        local.remove(regOp);
                        if (VERBOSE) {
                            System.out.println("  Killing: " + regOp + "\n local: " + local);
                        }
                        // mark this instruction as the start of the live range for reg
                        liveIntervals.setStartLiveRange(regOp.getRegister(), inst, block);
                    }
                }
            // if operand is a Register
            }
            // -- Feng July 15, 2003
            if (createGCMaps && !OsrPoint.conforms(inst) && inst.isGCPoint()) {
                // make deep copy (and translate to regList) because we reuse
                // local above.
                // NOTE: this translation does some screening, see GCIRMap.java
                List<RegSpillListElement> regList = map.createDU(local);
                blockStack.push(new MapElement(inst, regList));
                if (VERBOSE) {
                    System.out.println("SAVING GC Map");
                }
            }
            // now process the uses
            for (Enumeration<Operand> uses = inst.getUses(); uses.hasMoreElements(); ) {
                Operand op = uses.nextElement();
                if (op instanceof RegisterOperand) {
                    RegisterOperand regOp = (RegisterOperand) op;
                    // Do we care about this reg?
                    if (isSkippableReg(regOp, ir)) {
                        continue;
                    }
                    TypeReference regType = regOp.getType();
                    // see Def loop comment about magics
                    if (regType != null) {
                        // process the use as a gen
                        local.add(regOp);
                        if (VERBOSE) {
                            System.out.println("  Gen-ing: " + regOp);
                            System.out.println("local: " + local);
                        }
                        // mark this instruction as the end of the live range for reg
                        liveIntervals.createEndLiveRange(regOp.getRegister(), block, inst);
                    }
                }
            // if operand is a Register
            }
            if (createGCMaps && OsrPoint.conforms(inst)) {
                // delayed gc map generation for Osr instruction,
                // see comments before processing uses -- Feng, July 15, 2003
                List<RegSpillListElement> regList = map.createDU(local);
                blockStack.push(new MapElement(inst, regList));
                // collect osr info using live set
                collectOsrInfo(inst, local);
            }
        }
        // end instruction loop
        // The register allocator prefers that any registers that are live
        // on entry be listed first.  This call makes it so.
        liveIntervals.moveUpwardExposedRegsToFront(block);
        if (createGCMaps) {
            // empty the stack, insert the information into the map
            while (!blockStack.isEmpty()) {
                MapElement elem = blockStack.pop();
                map.insert(elem.getInst(), elem.getList());
            }
        }
        if (storeLiveAtHandlers && block.isExceptionHandlerBasicBlock()) {
            ExceptionHandlerBasicBlock handlerBlock = (ExceptionHandlerBasicBlock) block;
            // use local because we need to get a fresh one anyway.
            handlerBlock.setLiveSet(local);
            local = null;
        } else {
            // clear the local set for the next block
            local.clear();
        }
    }
    // end basic block for loop
    if (DEBUG) {
        System.out.println(" .... completed local propagation");
        System.out.println();
    }
}
Also used : InlinedOsrTypeInfoOperand(org.jikesrvm.compilers.opt.ir.operand.InlinedOsrTypeInfoOperand) BasicBlockOperand(org.jikesrvm.compilers.opt.ir.operand.BasicBlockOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) ExceptionHandlerBasicBlock(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) TypeReference(org.jikesrvm.classloader.TypeReference) ExceptionHandlerBasicBlock(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock) RegSpillListElement(org.jikesrvm.compilers.opt.ir.RegSpillListElement)

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