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);
}
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;
}
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);
}
}
}
}
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;
}
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();
}
}
Aggregations