Mercurial > hg > truffle
changeset 2567:b96f9fcc53b1
Merge
author | Gilles Duboscq <gilles.duboscq@oracle.com> |
---|---|
date | Mon, 02 May 2011 10:24:43 +0200 |
parents | d524ad648049 (diff) 0023bd42eefe (current diff) |
children | 95a9b8906b09 |
files | doc/design/graal_compiler_aux.tex doc/design/graal_compiler_design.tex doc/design/graal_compiler_org.tex doc/design/graph_test.aux doc/design/graph_test.log |
diffstat | 15 files changed, 380 insertions(+), 1482 deletions(-) [+] |
line wrap: on
line diff
--- a/graal/GraalCompiler/src/com/sun/c1x/C1XCompilation.java Fri Apr 29 11:14:05 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/C1XCompilation.java Mon May 02 10:24:43 2011 +0200 @@ -94,7 +94,7 @@ this.method = method; this.stats = stats == null ? new CiStatistics() : stats; this.registerConfig = method == null ? compiler.globalStubRegisterConfig : runtime.getRegisterConfig(method); - this.placeholderState = method != null && method.minimalDebugInfo() ? new MutableFrameState(new IRScope(null, null, method, -1), 0, 0, 0) : null; + this.placeholderState = method != null && method.minimalDebugInfo() ? new MutableFrameState(0, 0, 0) : null; if (compiler.isObserved()) { compiler.fireCompilationStarted(new CompilationEvent(this)); @@ -241,7 +241,7 @@ C1XTimers.LIR_CREATE.start(); } - initFrameMap(hir.topScope.maxLocks()); + initFrameMap(hir.maxLocks()); lirGenerator = compiler.backend.newLIRGenerator(this); for (BlockBegin begin : hir.linearScanOrder()) {
--- a/graal/GraalCompiler/src/com/sun/c1x/alloc/LinearScan.java Fri Apr 29 11:14:05 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/alloc/LinearScan.java Mon May 02 10:24:43 2011 +0200 @@ -2084,14 +2084,6 @@ } CiFrame computeFrameForState(int opId, FrameState state, CiBitMap frameRefMap) { - CiFrame callerFrame = null; - - FrameState callerState = state.callerState(); - if (callerState != null) { - // process recursively to compute outermost scope first - callerFrame = computeFrameForState(opId, callerState, frameRefMap); - } - CiValue[] values = new CiValue[state.valuesSize() + state.locksSize()]; int valueIndex = 0; @@ -2117,7 +2109,7 @@ } } - return new CiFrame(callerFrame, state.scope().method, state.bci, values, state.localsSize(), state.stackSize(), state.locksSize()); + return new CiFrame(null, ir.compilation.method, state.bci, values, state.localsSize(), state.stackSize(), state.locksSize()); } private void computeDebugInfo(IntervalWalker iw, LIRInstruction op) {
--- a/graal/GraalCompiler/src/com/sun/c1x/debug/BlockPrinter.java Fri Apr 29 11:14:05 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/debug/BlockPrinter.java Mon May 02 10:24:43 2011 +0200 @@ -56,8 +56,6 @@ printFrameState(block.stateBefore(), out); out.println(); - out.println("inlining depth " + block.stateBefore().scope().level); - ip.printInstructionListingHeader(); for (Instruction i = block.next(); i != null; i = i.next()) {
--- a/graal/GraalCompiler/src/com/sun/c1x/debug/CFGPrinter.java Fri Apr 29 11:14:05 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/debug/CFGPrinter.java Mon May 02 10:24:43 2011 +0200 @@ -202,73 +202,68 @@ * @param block the block for which the frame state is to be printed */ private void printState(BlockBegin block) { - begin("states"); + begin("state"); FrameState state = block.stateBefore(); - - do { - int stackSize = state.stackSize(); - if (stackSize > 0) { - begin("stack"); - out.print("size ").println(stackSize); - out.print("method \"").print(CiUtil.toLocation(state.scope().method, state.bci)).println('"'); - - int i = 0; - while (i < stackSize) { - Value value = state.stackAt(i); - out.disableIndentation(); - out.print(block.stateString(i, value)); - printOperand(value); - out.println(); - out.enableIndentation(); - if (value == null) { - i++; - } else { - i += value.kind.sizeInSlots(); - } - } - end("stack"); - } + int stackSize = state.stackSize(); + if (stackSize > 0) { + begin("stack"); + out.print("size ").println(stackSize); + out.print("bci ").println(state.bci); - if (state.locksSize() > 0) { - begin("locks"); - out.print("size ").println(state.locksSize()); - out.print("method \"").print(CiUtil.toLocation(state.scope().method, state.bci)).println('"'); - - for (int i = 0; i < state.locksSize(); ++i) { - Value value = state.lockAt(i); - out.disableIndentation(); - out.print(block.stateString(i, value)); - printOperand(value); - out.println(); - out.enableIndentation(); - } - end("locks"); - } - - begin("locals"); - out.print("size ").println(state.localsSize()); - out.print("method \"").print(CiUtil.toLocation(state.scope().method, state.bci)).println('"'); int i = 0; - while (i < state.localsSize()) { - Value value = state.localAt(i); - if (value != null) { - out.disableIndentation(); - out.print(block.stateString(i, value)); - printOperand(value); - out.println(); - out.enableIndentation(); - // also ignore illegal HiWords - i += value.isIllegal() ? 1 : value.kind.sizeInSlots(); + while (i < stackSize) { + Value value = state.stackAt(i); + out.disableIndentation(); + out.print(block.stateString(i, value)); + printOperand(value); + out.println(); + out.enableIndentation(); + if (value == null) { + i++; } else { - i++; + i += value.kind.sizeInSlots(); } } - state = state.callerState(); - end("locals"); - } while (state != null); + end("stack"); + } + + if (state.locksSize() > 0) { + begin("locks"); + out.print("size ").println(state.locksSize()); + out.print("bci ").println(state.bci); + + for (int i = 0; i < state.locksSize(); ++i) { + Value value = state.lockAt(i); + out.disableIndentation(); + out.print(block.stateString(i, value)); + printOperand(value); + out.println(); + out.enableIndentation(); + } + end("locks"); + } - end("states"); + begin("locals"); + out.print("size ").println(state.localsSize()); + out.print("bci ").println(state.bci); + int i = 0; + while (i < state.localsSize()) { + Value value = state.localAt(i); + if (value != null) { + out.disableIndentation(); + out.print(block.stateString(i, value)); + printOperand(value); + out.println(); + out.enableIndentation(); + // also ignore illegal HiWords + i += value.isIllegal() ? 1 : value.kind.sizeInSlots(); + } else { + i++; + } + } + end("locals"); + end("state"); } /** @@ -280,49 +275,45 @@ } StringBuilder buf = new StringBuilder(); - - do { - buf.append(CiUtil.toLocation(state.scope().method, state.bci)); - buf.append('\n'); - if (state.stackSize() > 0) { - int i = 0; - buf.append("stack: "); - while (i < state.stackSize()) { - if (i == 0) { - buf.append(' '); - } - Value value = state.stackAt(i); - buf.append(stateValueToString(value, operandFmt)).append(' '); - i++; - } - buf.append("\n"); - } - - if (state.locksSize() > 0) { - buf.append("locks: "); - for (int i = 0; i < state.locksSize(); ++i) { - if (i == 0) { - buf.append(' '); - } - Value value = state.lockAt(i); - buf.append(stateValueToString(value, operandFmt)).append(' '); - } - buf.append("\n"); - } - - buf.append("locals: "); + buf.append("[bci: ").append(state.bci).append("]"); + buf.append('\n'); + if (state.stackSize() > 0) { int i = 0; - while (i < state.localsSize()) { + buf.append("stack: "); + while (i < state.stackSize()) { if (i == 0) { buf.append(' '); } - Value value = state.localAt(i); + Value value = state.stackAt(i); buf.append(stateValueToString(value, operandFmt)).append(' '); i++; } buf.append("\n"); - state = state.callerState(); - } while (state != null); + } + + if (state.locksSize() > 0) { + buf.append("locks: "); + for (int i = 0; i < state.locksSize(); ++i) { + if (i == 0) { + buf.append(' '); + } + Value value = state.lockAt(i); + buf.append(stateValueToString(value, operandFmt)).append(' '); + } + buf.append("\n"); + } + + buf.append("locals: "); + int i = 0; + while (i < state.localsSize()) { + if (i == 0) { + buf.append(' '); + } + Value value = state.localAt(i); + buf.append(stateValueToString(value, operandFmt)).append(' '); + i++; + } + buf.append("\n"); return buf.toString(); }
--- a/graal/GraalCompiler/src/com/sun/c1x/gen/LIRGenerator.java Fri Apr 29 11:14:05 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/gen/LIRGenerator.java Mon May 02 10:24:43 2011 +0200 @@ -1283,17 +1283,9 @@ moveToPhi(resolver, curState.stackAt(index), suxState.stackAt(index)); } - // walk up the inlined scopes until locals match - while (curState.scope() != suxState.scope()) { - curState = curState.callerState(); - assert curState != null : "scopes don't match up"; - } - for (int index = 0; index < suxState.localsSize(); index++) { moveToPhi(resolver, curState.localAt(index), suxState.localAt(index)); } - - assert curState.scope().callerState == suxState.scope().callerState : "caller states must be equal"; resolver.dispose(); } } @@ -1390,26 +1382,20 @@ } FrameState s = state; int bci = x.bci(); + if (bci == Instruction.SYNCHRONIZATION_ENTRY_BCI) { + assert x instanceof ExceptionObject || + x instanceof Throw || + x instanceof MonitorEnter || + x instanceof MonitorExit : x + ", " + x.getClass(); + } - while (s != null) { - IRScope scope = s.scope(); - if (bci == Instruction.SYNCHRONIZATION_ENTRY_BCI) { - assert x instanceof ExceptionObject || - x instanceof Throw || - x instanceof MonitorEnter || - x instanceof MonitorExit : x + ", " + x.getClass(); - } - - for (int index = 0; index < s.localsSize(); index++) { - final Value value = s.localAt(index); - if (value != null) { - if (!value.isIllegal()) { - walkStateValue(value); - } + for (int index = 0; index < s.localsSize(); index++) { + final Value value = s.localAt(index); + if (value != null) { + if (!value.isIllegal()) { + walkStateValue(value); } } - bci = scope.callerBCI(); - s = s.callerState(); } }
--- a/graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java Fri Apr 29 11:14:05 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java Mon May 02 10:24:43 2011 +0200 @@ -30,7 +30,6 @@ import com.sun.c1x.*; import com.sun.c1x.debug.*; -import com.sun.c1x.graph.ScopeData.ReturnBlock; import com.sun.c1x.ir.*; import com.sun.c1x.opt.*; import com.sun.c1x.util.*; @@ -62,6 +61,25 @@ */ public static final int TRACELEVEL_STATE = 2; + /** + * An enumeration of flags describing scope attributes. + */ + public enum Flag { + /** + * Scope is protected by an exception handler. + * This attribute is inherited by nested scopes. + */ + HasHandler, + + /** + * Code in scope cannot contain safepoints. + * This attribute is inherited by nested scopes. + */ + NoSafepoints; + + public final int mask = 1 << ordinal(); + } + final IR ir; final C1XCompilation compilation; final CiStatistics stats; @@ -76,7 +94,27 @@ */ final MemoryMap memoryMap; - ScopeData scopeData; // Per-scope data; used for inlining + final BytecodeStream stream; // the bytecode stream + // bci-to-block mapping + BlockMap blockMap; + + // the constant pool + final RiConstantPool constantPool; + + // the worklist of blocks, managed like a sorted list + BlockBegin[] workList; + + // the current position in the worklist + int workListIndex; + + /** + * Mask of {@link Flag} values. + */ + int flags; + + // Exception handler list + List<ExceptionHandler> exceptionHandlers; + BlockBegin curBlock; // the current block MutableFrameState curState; // the current execution state Instruction lastInstr; // the last instruction added @@ -84,7 +122,6 @@ boolean skipBlock; // skip processing of the rest of this block private Value rootMethodSynchronizedObject; - /** * Creates a new, initialized, {@code GraphBuilder} instance for a given compilation. * @@ -98,13 +135,15 @@ this.memoryMap = C1XOptions.OptLocalLoadElimination ? new MemoryMap() : null; this.localValueMap = C1XOptions.OptLocalValueNumbering ? new ValueMap() : null; log = C1XOptions.TraceBytecodeParserLevel > 0 ? new LogStream(TTY.out()) : null; + stream = new BytecodeStream(compilation.method.code()); + constantPool = compilation.runtime.getConstantPool(compilation.method); } /** * Builds the graph for a the specified {@code IRScope}. * @param scope the top IRScope */ - public void build(IRScope scope) { + public void build() { RiMethod rootMethod = compilation.method; if (log != null) { @@ -112,16 +151,32 @@ log.println("Compiling " + compilation.method); } + if (rootMethod.noSafepoints()) { + flags |= Flag.NoSafepoints.mask; + } + // 1. create the start block ir.startBlock = new BlockBegin(0, ir.nextBlockNumber()); BlockBegin startBlock = ir.startBlock; - // 2. compute the block map and get the entrypoint(s) - BlockMap blockMap = compilation.getBlockMap(scope.method); + // 2. compute the block map, setup exception handlers and get the entrypoint(s) + blockMap = compilation.getBlockMap(rootMethod); BlockBegin stdEntry = blockMap.get(0); - pushRootScope(scope, blockMap, startBlock); + curBlock = startBlock; + + RiExceptionHandler[] handlers = rootMethod.exceptionHandlers(); + if (handlers != null && handlers.length > 0) { + exceptionHandlers = new ArrayList<ExceptionHandler>(handlers.length); + for (RiExceptionHandler ch : handlers) { + ExceptionHandler h = new ExceptionHandler(ch); + h.setEntryBlock(blockAt(h.handler.handlerBCI())); + exceptionHandlers.add(h); + } + flags |= Flag.HasHandler.mask; + } + MutableFrameState initialState = stateAtEntry(rootMethod); - startBlock.mergeOrClone(initialState); + startBlock.mergeOrClone(initialState, rootMethod); BlockBegin syncHandler = null; // 3. setup internal state for appending instructions @@ -145,7 +200,7 @@ ExceptionHandler h = new ExceptionHandler(new CiExceptionHandler(0, rootMethod.code().length, -1, 0, null)); h.setEntryBlock(syncHandler); - scopeData.addExceptionHandler(h); + addExceptionHandler(h); } else { // 4B.1 simply finish the start block finishStartBlock(startBlock, stdEntry); @@ -154,7 +209,7 @@ // 5. SKIPPED: look for intrinsics // 6B.1 do the normal parsing - scopeData.addToWorkList(stdEntry); + addToWorkList(stdEntry); iterateAllBlocks(); if (syncHandler != null && syncHandler.stateBefore() != null) { @@ -171,46 +226,23 @@ base.setStateAfter(stateAfter); startBlock.setEnd(base); assert stdEntry.stateBefore() == null; - stdEntry.mergeOrClone(stateAfter); - } - - void pushRootScope(IRScope scope, BlockMap blockMap, BlockBegin start) { - BytecodeStream stream = new BytecodeStream(scope.method.code()); - RiConstantPool constantPool = compilation.runtime.getConstantPool(scope.method); - scopeData = new ScopeData(null, scope, blockMap, stream, constantPool); - curBlock = start; - } - - public boolean hasHandler() { - return scopeData.hasHandler(); - } - - public IRScope scope() { - return scopeData.scope; - } - - public IRScope rootScope() { - IRScope root = scope(); - while (root.caller != null) { - root = root.caller; - } - return root; + stdEntry.mergeOrClone(stateAfter, method()); } public RiMethod method() { - return scopeData.scope.method; + return compilation.method; } public BytecodeStream stream() { - return scopeData.stream; + return stream; } public int bci() { - return scopeData.stream.currentBCI(); + return stream.currentBCI(); } public int nextBCI() { - return scopeData.stream.nextBCI(); + return stream.nextBCI(); } private void ipush(Value x) { @@ -290,98 +322,34 @@ } private void storeLocal(CiKind kind, int index) { - if (scopeData.parsingJsr()) { - // We need to do additional tracking of the location of the return - // address for jsrs since we don't handle arbitrary jsr/ret - // constructs. Here we are figuring out in which circumstances we - // need to bail out. - if (kind == CiKind.Object) { - // might be storing the JSR return address - Value x = curState.xpop(); - if (x.kind.isJsr()) { - setJsrReturnAddressLocal(index); - curState.storeLocal(index, x); - } else { - // nope, not storing the JSR return address - assert x.kind.isObject(); - curState.storeLocal(index, x); - overwriteJsrReturnAddressLocal(index); - } - return; - } else { - // not storing the JSR return address local, but might overwrite it - overwriteJsrReturnAddressLocal(index); - } - } - curState.storeLocal(index, pop(kind)); } - private void overwriteJsrReturnAddressLocal(int index) { - if (index == scopeData.jsrEntryReturnAddressLocal()) { - scopeData.setJsrEntryReturnAddressLocal(-1); - } - } - - private void setJsrReturnAddressLocal(int index) { - scopeData.setJsrEntryReturnAddressLocal(index); - - // Also check parent jsrs (if any) at this time to see whether - // they are using this local. We don't handle skipping over a - // ret. - for (ScopeData cur = scopeData.parent; cur != null && cur.parsingJsr() && cur.scope == scope(); cur = cur.parent) { - if (cur.jsrEntryReturnAddressLocal() == index) { - throw new CiBailout("subroutine overwrites return address from previous subroutine"); - } - } - } - List<ExceptionHandler> handleException(Instruction x, int bci) { if (!hasHandler()) { return Util.uncheckedCast(Collections.EMPTY_LIST); } ArrayList<ExceptionHandler> exceptionHandlers = new ArrayList<ExceptionHandler>(); - ScopeData curScopeData = scopeData; FrameState stateBefore = x.stateBefore(); int scopeCount = 0; assert stateBefore != null : "exception handler state must be available for " + x; FrameState state = stateBefore; - do { - assert curScopeData.scope == state.scope() : "scopes do not match"; - assert bci == Instruction.SYNCHRONIZATION_ENTRY_BCI || bci == curScopeData.stream.currentBCI() : "invalid bci"; + assert bci == Instruction.SYNCHRONIZATION_ENTRY_BCI || bci == bci() : "invalid bci"; - // join with all potential exception handlers - List<ExceptionHandler> handlers = curScopeData.exceptionHandlers(); - if (handlers != null) { - for (ExceptionHandler handler : handlers) { - if (handler.covers(bci)) { - // if the handler covers this bytecode index, add it to the list - if (addExceptionHandler(exceptionHandlers, handler, curScopeData, state, scopeCount)) { - // if the handler was a default handler, we are done - return exceptionHandlers; - } + // join with all potential exception handlers + if (this.exceptionHandlers != null) { + for (ExceptionHandler handler : this.exceptionHandlers) { + if (handler.covers(bci)) { + // if the handler covers this bytecode index, add it to the list + if (addExceptionHandler(exceptionHandlers, handler, state, scopeCount)) { + // if the handler was a default handler, we are done + return exceptionHandlers; } } } - // pop the scope to the next IRScope level - // if parsing a JSR, skip scopes until the next IRScope level - IRScope curScope = curScopeData.scope; - while (curScopeData.parent != null && curScopeData.parent.scope == curScope) { - curScopeData = curScopeData.parent; - } - if (curScopeData.parent == null) { - // no more levels, done - break; - } - // there is another level, pop - state = state.callerState(); - bci = curScopeData.scope.callerBCI(); - curScopeData = curScopeData.parent; - scopeCount++; - - } while (true); + } return exceptionHandlers; } @@ -397,20 +365,19 @@ * @param scopeCount * @return {@code true} if handler catches all exceptions (i.e. {@code handler.isCatchAll() == true}) */ - private boolean addExceptionHandler(ArrayList<ExceptionHandler> exceptionHandlers, ExceptionHandler handler, ScopeData curScopeData, FrameState curState, int scopeCount) { + private boolean addExceptionHandler(ArrayList<ExceptionHandler> exceptionHandlers, ExceptionHandler handler, FrameState curState, int scopeCount) { compilation.setHasExceptionHandlers(); BlockBegin entry = handler.entryBlock(); FrameState entryState = entry.stateBefore(); assert entry.bci() == handler.handler.handlerBCI(); - assert entry.bci() == -1 || entry == curScopeData.blockAt(entry.bci()) : "blocks must correspond"; - assert entryState == null || curState.locksSize() == entryState.locksSize() : "locks do not match"; + assert entryState == null || curState.locksSize() == entryState.locksSize() : "locks do not match : cur:"+curState.locksSize()+" entry:"+entryState.locksSize(); // exception handler starts with an empty expression stack curState = curState.immutableCopyWithEmptyStack(); - entry.mergeOrClone(curState); + entry.mergeOrClone(curState, method()); // add current state for correct handling of phi functions int phiOperand = entry.addExceptionState(curState); @@ -431,7 +398,7 @@ // fill in exception handler subgraph lazily if (!entry.wasVisited()) { - curScopeData.addToWorkList(entry); + addToWorkList(entry); } else { // This will occur for exception handlers that cover themselves. This code // pattern is generated by javac for synchronized blocks. See the following @@ -627,7 +594,7 @@ } void genGoto(int fromBCI, int toBCI) { - boolean isSafepoint = !scopeData.noSafepoints() && toBCI <= fromBCI; + boolean isSafepoint = !noSafepoints() && toBCI <= fromBCI; append(new Goto(blockAt(toBCI), null, isSafepoint)); } @@ -635,7 +602,7 @@ BlockBegin tsucc = blockAt(stream().readBranchDest()); BlockBegin fsucc = blockAt(stream().nextBCI()); int bci = stream().currentBCI(); - boolean isSafepoint = !scopeData.noSafepoints() && tsucc.bci() <= bci || fsucc.bci() <= bci; + boolean isSafepoint = !noSafepoints() && tsucc.bci() <= bci || fsucc.bci() <= bci; append(new If(x, cond, y, tsucc, fsucc, isSafepoint ? stateBefore : null, isSafepoint)); } @@ -662,7 +629,7 @@ void genThrow(int bci) { FrameState stateBefore = curState.immutableCopy(bci()); - Throw t = new Throw(apop(), stateBefore, !scopeData.noSafepoints()); + Throw t = new Throw(apop(), stateBefore, !noSafepoints()); appendWithoutOptimization(t, bci); } @@ -817,9 +784,7 @@ } Value[] args = curState.popArguments(target.signature().argumentSlots(false)); - if (!tryInline(target, args)) { - appendInvoke(INVOKESTATIC, target, args, cpi, constantPool); - } + appendInvoke(INVOKESTATIC, target, args, cpi, constantPool); } void genInvokeInterface(RiMethod target, int cpi, RiConstantPool constantPool) { @@ -926,10 +891,7 @@ } private void invokeDirect(RiMethod target, Value[] args, RiType knownHolder, int cpi, RiConstantPool constantPool) { - if (!tryInline(target, args)) { - // could not optimize or inline the method call - appendInvoke(INVOKESPECIAL, target, args, cpi, constantPool); - } + appendInvoke(INVOKESPECIAL, target, args, cpi, constantPool); } private void appendInvoke(int opcode, RiMethod target, Value[] args, int cpi, RiConstantPool constantPool) { @@ -1044,49 +1006,11 @@ callRegisterFinalizer(); } - // If inlining, then returns become gotos to the continuation point. - if (scopeData.continuation() != null) { - if (isSynchronized(method().accessFlags())) { - // if the inlined method is synchronized, then the monitor - // must be released before jumping to the continuation point - Value object = curState.lockAt(0); - if (object instanceof Instruction) { - Instruction obj = (Instruction) object; - if (!obj.isAppended()) { - appendWithoutOptimization(obj, Instruction.SYNCHRONIZATION_ENTRY_BCI); - } - } - genMonitorExit(object, Instruction.SYNCHRONIZATION_ENTRY_BCI); - } - - // empty stack for return value - curState.truncateStack(0); - if (x != null) { - curState.push(x.kind, x); - } - Goto gotoCallee = new Goto(scopeData.continuation(), null, false); - - // ATTN: assumption: curState is not used further down, else add .immutableCopy() - scopeData.updateSimpleInlineInfo(curBlock, lastInstr, curState); - - // State at end of inlined method is the state of the caller - // without the method parameters on stack, including the - // return value, if any, of the inlined method on operand stack. - curState = scopeData.continuationState().copy(); - if (x != null) { - curState.push(x.kind, x); - } - - // The current bci is in the wrong scope, so use the bci of the continuation point. - appendWithoutOptimization(gotoCallee, scopeData.continuation().bci()); - return; - } - curState.truncateStack(0); if (Modifier.isSynchronized(method().accessFlags())) { FrameState stateBefore = curState.immutableCopy(bci()); // unlock before exiting the method - int lockNumber = curState.totalLocksSize() - 1; + int lockNumber = curState.locksSize() - 1; MonitorAddress lockAddress = null; if (compilation.runtime.sizeOfBasicObjectLock() != 0) { lockAddress = new MonitorAddress(lockNumber); @@ -1095,7 +1019,7 @@ append(new MonitorExit(rootMethodSynchronizedObject, lockAddress, lockNumber, stateBefore)); curState.unlock(); } - append(new Return(x, !scopeData.noSafepoints())); + append(new Return(x, !noSafepoints())); } /** @@ -1114,13 +1038,13 @@ } MonitorEnter monitorEnter = new MonitorEnter(x, lockAddress, lockNumber, null); appendWithoutOptimization(monitorEnter, bci); - curState.lock(scope(), x, lockNumber + 1); + curState.lock(ir, x, lockNumber + 1); monitorEnter.setStateAfter(curState.immutableCopy(bci)); killMemoryMap(); // prevent any optimizations across synchronization } void genMonitorExit(Value x, int bci) { - int lockNumber = curState.totalLocksSize() - 1; + int lockNumber = curState.locksSize() - 1; if (lockNumber < 0) { throw new CiBailout("monitor stack underflow"); } @@ -1135,26 +1059,11 @@ } void genJsr(int dest) { - for (ScopeData cur = scopeData; cur != null && cur.parsingJsr() && cur.scope == scope(); cur = cur.parent) { - if (cur.jsrEntryBCI() == dest) { - // the jsr/ret pattern includes a recursive invocation - throw new CiBailout("recursive jsr/ret structure"); - } - } - push(CiKind.Jsr, append(Constant.forJsr(nextBCI()))); - tryInlineJsr(dest); + throw new CiBailout("jsr/ret not supported"); } void genRet(int localIndex) { - if (!scopeData.parsingJsr()) { - throw new CiBailout("ret encountered when not parsing subroutine"); - } - - if (localIndex != scopeData.jsrEntryReturnAddressLocal()) { - throw new CiBailout("jsr/ret structure is too complicated"); - } - // rets become non-safepoint gotos - append(new Goto(scopeData.jsrContinuation(), null, false)); + throw new CiBailout("jsr/ret not supported"); } void genTableswitch() { @@ -1172,7 +1081,7 @@ int offset = ts.defaultOffset(); isBackwards |= offset < 0; // if the default successor is backwards list.add(blockAt(bci + offset)); - boolean isSafepoint = isBackwards && !scopeData.noSafepoints(); + boolean isSafepoint = isBackwards && !noSafepoints(); FrameState stateBefore = isSafepoint ? curState.immutableCopy(bci()) : null; append(new TableSwitch(ipop(), list, ts.lowKey(), stateBefore, isSafepoint)); } @@ -1194,7 +1103,7 @@ int offset = ls.defaultOffset(); isBackwards |= offset < 0; // if the default successor is backwards list.add(blockAt(bci + offset)); - boolean isSafepoint = isBackwards && !scopeData.noSafepoints(); + boolean isSafepoint = isBackwards && !noSafepoints(); FrameState stateBefore = isSafepoint ? curState.immutableCopy(bci()) : null; append(new LookupSwitch(ipop(), list, keys, stateBefore, isSafepoint)); } @@ -1290,7 +1199,7 @@ } private BlockBegin blockAtOrNull(int bci) { - return scopeData.blockAt(bci); + return blockMap.get(bci); } private BlockBegin blockAt(int bci) { @@ -1299,75 +1208,8 @@ return result; } - boolean tryInlineJsr(int jsrStart) { - // start a new continuation point. - // all ret instructions will be replaced with gotos to this point - BlockBegin cont = blockAt(nextBCI()); - - // push callee scope - pushScopeForJsr(cont, jsrStart); - - BlockBegin jsrStartBlock = blockAt(jsrStart); - assert !jsrStartBlock.wasVisited(); - Goto gotoSub = new Goto(jsrStartBlock, null, false); - gotoSub.setStateAfter(curState.immutableCopy(bci())); - assert jsrStartBlock.stateBefore() == null; - jsrStartBlock.setStateBefore(curState.immutableCopy(bci())); - append(gotoSub); - curBlock.setEnd(gotoSub); - lastInstr = curBlock = jsrStartBlock; - - scopeData.addToWorkList(jsrStartBlock); - - iterateAllBlocks(); - - if (cont.stateBefore() != null) { - if (!cont.wasVisited()) { - scopeData.parent.addToWorkList(cont); - } - } - - BlockBegin jsrCont = scopeData.jsrContinuation(); - assert jsrCont == cont && (!jsrCont.wasVisited() || jsrCont.isParserLoopHeader()); - assert lastInstr != null && lastInstr instanceof BlockEnd; - - // continuation is in work list, so end iteration of current block - skipBlock = true; - popScopeForJsr(); - C1XMetrics.InlinedJsrs++; - return true; - } - - void pushScopeForJsr(BlockBegin jsrCont, int jsrStart) { - BytecodeStream stream = new BytecodeStream(scope().method.code()); - RiConstantPool constantPool = scopeData.constantPool; - ScopeData data = new ScopeData(scopeData, scope(), scopeData.blockMap, stream, constantPool, jsrStart); - BlockBegin continuation = scopeData.continuation(); - data.setContinuation(continuation); - if (continuation != null) { - assert scopeData.continuationState() != null; - data.setContinuationState(scopeData.continuationState().copy()); - } - data.setJsrContinuation(jsrCont); - scopeData = data; - } - - void pushScope(RiMethod target, BlockBegin continuation) { - // prepare callee scope - IRScope calleeScope = new IRScope(scope(), curState.immutableCopy(bci()), target, -1); - BlockMap blockMap = compilation.getBlockMap(calleeScope.method); - calleeScope.setStoresInLoops(blockMap.getStoresInLoops()); - // prepare callee state - curState = curState.pushScope(calleeScope); - BytecodeStream stream = new BytecodeStream(target.code()); - RiConstantPool constantPool = compilation.runtime.getConstantPool(target); - ScopeData data = new ScopeData(scopeData, calleeScope, blockMap, stream, constantPool); - data.setContinuation(continuation); - scopeData = data; - } - MutableFrameState stateAtEntry(RiMethod method) { - MutableFrameState state = new MutableFrameState(scope(), -1, method.maxLocals(), method.maxStackSize()); + MutableFrameState state = new MutableFrameState(-1, method.maxLocals(), method.maxStackSize()); int index = 0; if (!isStatic(method.accessFlags())) { // add the receiver and assume it is non null @@ -1393,223 +1235,6 @@ return state; } - private boolean tryInline(RiMethod target, Value[] args) { - boolean forcedInline = compilation.runtime.mustInline(target); - if (forcedInline) { - for (IRScope scope = scope().caller; scope != null; scope = scope.caller) { - if (scope.method.equals(target)) { - throw new CiBailout("Cannot recursively inline method that is force-inlined: " + target); - } - } - C1XMetrics.InlineForcedMethods++; - } - if (forcedInline || checkInliningConditions(target)) { - if (C1XOptions.TraceBytecodeParserLevel > 0) { - log.adjustIndentation(1); - log.println("\\"); - log.adjustIndentation(1); - if (C1XOptions.TraceBytecodeParserLevel < TRACELEVEL_STATE) { - log.println("| [inlining " + target + "]"); - log.println("|"); - } - } - - inline(target, args, forcedInline); - - if (C1XOptions.TraceBytecodeParserLevel > 0) { - if (C1XOptions.TraceBytecodeParserLevel < TRACELEVEL_STATE) { - log.println("|"); - log.println("| [return to " + curState.scope().method + "]"); - } - log.adjustIndentation(-1); - log.println("/"); - log.adjustIndentation(-1); - } - return true; - } - return false; - } - - private boolean checkInliningConditions(RiMethod target) { - if (!C1XOptions.OptInline) { - return false; // all inlining is turned off - } - if (!target.isResolved()) { - return cannotInline(target, "unresolved method"); - } - if (target.code() == null) { - return cannotInline(target, "method has no code"); - } - if (!target.holder().isInitialized()) { - return cannotInline(target, "holder is not initialized"); - } - if (recursiveInlineLevel(target) > C1XOptions.MaximumRecursiveInlineLevel) { - return cannotInline(target, "recursive inlining too deep"); - } - if (target.code().length > scopeData.maxInlineSize()) { - return cannotInline(target, "inlinee too large for this level"); - } - if (scopeData.scope.level + 1 > C1XOptions.MaximumInlineLevel) { - return cannotInline(target, "inlining too deep"); - } - if (stats.nodeCount > C1XOptions.MaximumDesiredSize) { - return cannotInline(target, "compilation already too big " + "(" + compilation.stats.nodeCount + " nodes)"); - } - if (compilation.runtime.mustNotInline(target)) { - C1XMetrics.InlineForbiddenMethods++; - return cannotInline(target, "inlining excluded by runtime"); - } - if (compilation.runtime.mustNotCompile(target)) { - return cannotInline(target, "compile excluded by runtime"); - } - if (isSynchronized(target.accessFlags())) { - return cannotInline(target, "is synchronized"); - } - if (target.exceptionHandlers().length != 0) { - return cannotInline(target, "has exception handlers"); - } - if (!target.hasBalancedMonitors()) { - return cannotInline(target, "has unbalanced monitors"); - } - if (target.isConstructor()) { - if (compilation.runtime.isExceptionType(target.holder())) { - // don't inline constructors of throwable classes unless the inlining tree is - // rooted in a throwable class - if (!compilation.runtime.isExceptionType(rootScope().method.holder())) { - return cannotInline(target, "don't inline Throwable constructors"); - } - } - } - return true; - } - - private boolean cannotInline(RiMethod target, String reason) { - if (C1XOptions.PrintInliningFailures) { - TTY.println("Cannot inline " + target.toString() + " into " + compilation.method.toString() + " because of " + reason); - } - return false; - } - - private void inline(RiMethod target, Value[] args, boolean forcedInline) { - BlockBegin orig = curBlock; - if (!forcedInline && !isStatic(target.accessFlags())) { - // the receiver object must be null-checked for instance methods - Value receiver = args[0]; - if (!receiver.isNonNull() && !receiver.kind.isWord()) { - NullCheck check = new NullCheck(receiver, null); - args[0] = append(check); - } - } - - // Introduce a new callee continuation point. All return instructions - // in the callee will be transformed to Goto's to the continuation - BlockBegin continuationBlock = blockAtOrNull(nextBCI()); - boolean continuationExisted = true; - if (continuationBlock == null) { - // there was not already a block starting at the next BCI - continuationBlock = new BlockBegin(nextBCI(), ir.nextBlockNumber()); - continuationBlock.setDepthFirstNumber(0); - continuationExisted = false; - } - // record the number of predecessors before inlining, to determine - // whether the inlined method has added edges to the continuation - int continuationPredecessors = continuationBlock.predecessors().size(); - - // push the target scope - pushScope(target, continuationBlock); - - // pass parameters into the callee state - FrameState calleeState = curState; - for (int i = 0; i < args.length; i++) { - Value arg = args[i]; - if (arg != null) { - calleeState.storeLocal(i, arg); - } - } - - // setup state that is used at returns from the inlined method. - // this is essentially the state of the continuation block, - // but without the return value on the stack. - scopeData.setContinuationState(scope().callerState); - - Value lock = null; - BlockBegin syncHandler = null; - // inline the locking code if the target method is synchronized - if (Modifier.isSynchronized(target.accessFlags())) { - // lock the receiver object if it is an instance method, the class object otherwise - lock = synchronizedObject(curState, target); - syncHandler = new BlockBegin(Instruction.SYNCHRONIZATION_ENTRY_BCI, ir.nextBlockNumber()); - syncHandler.setNext(null, -1); - inlineSyncEntry(lock, syncHandler); - } - - BlockBegin calleeStartBlock = blockAt(0); - if (calleeStartBlock.isParserLoopHeader()) { - // the block is a loop header, so we have to insert a goto - Goto gotoCallee = new Goto(calleeStartBlock, null, false); - gotoCallee.setStateAfter(curState.immutableCopy(bci())); - appendWithoutOptimization(gotoCallee, 0); - curBlock.setEnd(gotoCallee); - calleeStartBlock.mergeOrClone(calleeState); - lastInstr = curBlock = calleeStartBlock; - scopeData.addToWorkList(calleeStartBlock); - // now iterate over all the blocks - iterateAllBlocks(); - } else { - // ready to resume parsing inlined method into this block - iterateBytecodesForBlock(0, true); - // now iterate over the rest of the blocks - iterateAllBlocks(); - } - - assert continuationExisted || !continuationBlock.wasVisited() : "continuation should not have been parsed if we created it"; - - ReturnBlock simpleInlineInfo = scopeData.simpleInlineInfo(); - if (simpleInlineInfo != null && curBlock == orig) { - // Optimization: during parsing of the callee we - // generated at least one Goto to the continuation block. If we - // generated exactly one, and if the inlined method spanned exactly - // one block (and we didn't have to Goto its entry), then we snip - // off the Goto to the continuation, allowing control to fall - // through back into the caller block and effectively performing - // block merging. This allows local load elimination and local value numbering - // to take place across multiple callee scopes if they are relatively simple, and - // is currently essential to making inlining profitable. It also reduces the - // number of blocks in the CFG - lastInstr = simpleInlineInfo.returnPredecessor; - curState = simpleInlineInfo.returnState.popScope(); - lastInstr.setNext(null, -1); - } else if (continuationPredecessors == continuationBlock.predecessors().size()) { - // Inlining caused the instructions after the invoke in the - // caller to not reachable any more (i.e. no control flow path - // in the callee was terminated by a return instruction). - // So skip filling this block with instructions! - assert continuationBlock == scopeData.continuation(); - assert lastInstr instanceof BlockEnd; - skipBlock = true; - } else { - // Resume parsing in continuation block unless it was already parsed. - // Note that if we don't change lastInstr here, iteration in - // iterateBytecodesForBlock will stop when we return. - if (!scopeData.continuation().wasVisited()) { - // add continuation to work list instead of parsing it immediately - assert lastInstr instanceof BlockEnd; - scopeData.parent.addToWorkList(scopeData.continuation()); - skipBlock = true; - } - } - - // fill the exception handler for synchronized methods with instructions - if (syncHandler != null && syncHandler.stateBefore() != null) { - // generate unlocking code if the exception handler is reachable - fillSyncHandler(lock, syncHandler, true); - } else { - popScope(); - } - - stats.inlineCount++; - } - private Value synchronizedObject(FrameState curState2, RiMethod target) { if (isStatic(target.accessFlags())) { Constant classConstant = new Constant(target.holder().getEncoding(Representation.JavaClass)); @@ -1619,15 +1244,6 @@ } } - private void inlineSyncEntry(Value lock, BlockBegin syncHandler) { - genMonitorEnter(lock, Instruction.SYNCHRONIZATION_ENTRY_BCI); - syncHandler.setExceptionEntry(); - syncHandler.setBlockFlag(BlockBegin.BlockFlag.IsOnWorkList); - ExceptionHandler handler = new ExceptionHandler(new CiExceptionHandler(0, method().code().length, -1, 0, null)); - handler.setEntryBlock(syncHandler); - scopeData.addExceptionHandler(handler); - } - private void fillSyncHandler(Value lock, BlockBegin syncHandler, boolean inlinedMethod) { BlockBegin origBlock = curBlock; MutableFrameState origState = curState; @@ -1654,13 +1270,6 @@ // exit the monitor genMonitorExit(lock, Instruction.SYNCHRONIZATION_ENTRY_BCI); - // exit the context of the synchronized method - if (inlinedMethod) { - popScope(); - bci = curState.scope().callerBCI(); - curState = curState.popScope(); - } - apush(exception); genThrow(bci); BlockEnd end = (BlockEnd) lastInstr; @@ -1674,7 +1283,7 @@ private void iterateAllBlocks() { BlockBegin b; - while ((b = scopeData.removeFromWorkList()) != null) { + while ((b = removeFromWorkList()) != null) { if (!b.wasVisited()) { b.setWasVisited(true); // now parse the block @@ -1689,27 +1298,16 @@ } } - private void popScope() { - int maxLocks = scope().maxLocks(); - scopeData = scopeData.parent; - scope().updateMaxLocks(maxLocks); - } - - private void popScopeForJsr() { - scopeData = scopeData.parent; - } - private BlockEnd iterateBytecodesForBlock(int bci, boolean inliningIntoCurrentBlock) { skipBlock = false; assert curState != null; - BytecodeStream s = scopeData.stream; - s.setBCI(bci); + stream.setBCI(bci); BlockBegin block = curBlock; BlockEnd end = null; boolean pushException = block.isExceptionEntry() && block.next() == null; int prevBCI = bci; - int endBCI = s.endBCI(); + int endBCI = stream.endBCI(); boolean blockStart = true; while (bci < endBCI) { @@ -1729,7 +1327,7 @@ break; } // read the opcode - int opcode = s.currentBC(); + int opcode = stream.currentBC(); // push an exception object onto the stack if we are parsing an exception handler if (pushException) { @@ -1739,8 +1337,8 @@ } traceState(); - traceInstruction(bci, s, opcode, blockStart); - processBytecode(bci, s, opcode); + traceInstruction(bci, stream, opcode, blockStart); + processBytecode(bci, stream, opcode); prevBCI = bci; @@ -1748,8 +1346,8 @@ end = (BlockEnd) lastInstr; break; } - s.next(); - bci = s.currentBCI(); + stream.next(); + bci = stream.currentBCI(); blockStart = false; } @@ -1772,15 +1370,15 @@ // propagate the state for (BlockBegin succ : end.successors()) { assert succ.predecessors().contains(curBlock); - succ.mergeOrClone(end.stateAfter()); - scopeData.addToWorkList(succ); + succ.mergeOrClone(end.stateAfter(), method()); + addToWorkList(succ); } return end; } private void traceState() { if (C1XOptions.TraceBytecodeParserLevel >= TRACELEVEL_STATE && !TTY.isSuppressed()) { - log.println(String.format("| state [nr locals = %d, stack depth = %d, method = %s]", curState.localsSize(), curState.stackSize(), curState.scope().method)); + log.println(String.format("| state [nr locals = %d, stack depth = %d, method = %s]", curState.localsSize(), curState.stackSize(), method())); for (int i = 0; i < curState.localsSize(); ++i) { Value value = curState.localAt(i); log.println(String.format("| local[%d] = %-8s : %s", i, value == null ? "bogus" : value.kind.javaName, value)); @@ -2084,20 +1682,89 @@ return null; } - private int recursiveInlineLevel(RiMethod target) { - int rec = 0; - IRScope scope = scope(); - while (scope != null) { - if (scope.method != target) { - break; - } - scope = scope.caller; - rec++; + private RiConstantPool constantPool() { + return constantPool; + } + + /** + * Adds an exception handler + * @param handler the handler to add + */ + private void addExceptionHandler(ExceptionHandler handler) { + if (exceptionHandlers == null) { + exceptionHandlers = new ArrayList<ExceptionHandler>(); } - return rec; + exceptionHandlers.add(handler); + flags |= Flag.HasHandler.mask; + } + + /** + * Adds a block to the worklist, if it is not already in the worklist. + * This method will keep the worklist topologically stored (i.e. the lower + * DFNs are earlier in the list). + * @param block the block to add to the work list + */ + private void addToWorkList(BlockBegin block) { + if (!block.isOnWorkList()) { + block.setOnWorkList(true); + sortIntoWorkList(block); + } } - private RiConstantPool constantPool() { - return scopeData.constantPool; + private void sortIntoWorkList(BlockBegin top) { + // XXX: this is O(n), since the whole list is sorted; a heap could achieve O(nlogn), but + // would only pay off for large worklists + if (workList == null) { + // need to allocate the worklist + workList = new BlockBegin[5]; + } else if (workListIndex == workList.length) { + // need to grow the worklist + BlockBegin[] nworkList = new BlockBegin[workList.length * 3]; + System.arraycopy(workList, 0, nworkList, 0, workList.length); + workList = nworkList; + } + // put the block at the end of the array + workList[workListIndex++] = top; + int dfn = top.depthFirstNumber(); + assert dfn >= 0 : top + " does not have a depth first number"; + int i = workListIndex - 2; + // push top towards the beginning of the array + for (; i >= 0; i--) { + BlockBegin b = workList[i]; + if (b.depthFirstNumber() >= dfn) { + break; // already in the right position + } + workList[i + 1] = b; // bubble b down by one + workList[i] = top; // and overwrite it with top + } + } + + /** + * Removes the next block from the worklist. The list is sorted topologically, so the + * block with the lowest depth first number in the list will be removed and returned. + * @return the next block from the worklist; {@code null} if there are no blocks + * in the worklist + */ + private BlockBegin removeFromWorkList() { + if (workListIndex == 0) { + return null; + } + // pop the last item off the end + return workList[--workListIndex]; + } + + /** + * Checks whether this graph has any handlers. + * @return {@code true} if there are any exception handlers + */ + private boolean hasHandler() { + return (flags & Flag.HasHandler.mask) != 0; + } + + /** + * Checks whether this graph can contain safepoints. + */ + private boolean noSafepoints() { + return (flags & Flag.NoSafepoints.mask) != 0; } }
--- a/graal/GraalCompiler/src/com/sun/c1x/graph/IR.java Fri Apr 29 11:14:05 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/graph/IR.java Mon May 02 10:24:43 2011 +0200 @@ -54,10 +54,7 @@ */ public BlockBegin osrEntryBlock; - /** - * The top IRScope. - */ - public IRScope topScope; + private int maxLocks; /** * The linear-scan ordered list of blocks. @@ -95,10 +92,8 @@ } private void buildGraph() { - topScope = new IRScope(null, null, compilation.method, -1); - // Graph builder must set the startBlock and the osrEntryBlock - new GraphBuilder(compilation, this).build(topScope); + new GraphBuilder(compilation, this).build(); assert startBlock != null; verifyAndPrint("After graph building"); @@ -259,4 +254,23 @@ public int numLoops() { return compilation.stats.loopCount; } + + /** + * Updates the maximum number of locks held at any one time. + * + * @param locks a lock count that will replace the current {@linkplain #maxLocks() max locks} if it is greater + */ + public void updateMaxLocks(int locks) { + if (locks > maxLocks) { + maxLocks = locks; + } + } + + /** + * Gets the number of locks + * @return the number of locks + */ + public final int maxLocks() { + return maxLocks; + } }
--- a/graal/GraalCompiler/src/com/sun/c1x/graph/ScopeData.java Fri Apr 29 11:14:05 2011 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,511 +0,0 @@ -/* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.sun.c1x.graph; - -import static com.sun.c1x.graph.ScopeData.Flag.*; -import static com.sun.c1x.graph.ScopeData.ReturnBlock.*; - -import java.util.*; - -import com.sun.c1x.*; -import com.sun.c1x.ir.*; -import com.sun.c1x.value.*; -import com.sun.cri.bytecode.*; -import com.sun.cri.ri.*; - -/** - * The {@code ScopeData} class represents inlining context when parsing the bytecodes - * of an inlined method. - * - * @author Ben L. Titzer -*/ -public class ScopeData { - // XXX: refactor and split this class into ScopeData, JsrScopeData, and InlineScopeData - - /** - * An enumeration of flags describing scope attributes. - */ - public enum Flag { - /** - * Scope is protected by an exception handler. - * This attribute is inherited by nested scopes. - */ - HasHandler, - - /** - * Code in scope cannot contain safepoints. - * This attribute is inherited by nested scopes. - */ - NoSafepoints; - - public final int mask = 1 << ordinal(); - } - - - final ScopeData parent; - // the IR scope - final IRScope scope; - // bci-to-block mapping - final BlockMap blockMap; - // the bytecode stream - final BytecodeStream stream; - // the constant pool - final RiConstantPool constantPool; - // the worklist of blocks, managed like a sorted list - BlockBegin[] workList; - // the current position in the worklist - int workListIndex; - // maximum inline size for this scope - int maxInlineSize; - - /** - * Mask of {@link Flag} values. - */ - int flags; - - // Exception handler list - List<ExceptionHandler> exceptionHandlers; - - // The continuation point for the inline. Currently only used in - // multi-block inlines, but eventually would like to use this for - // all inlines for uniformity and simplicity; in this case would - // get the continuation point from the BlockList instead of - // fabricating it anew because Invokes would be considered to be - // BlockEnds. - BlockBegin continuation; - - // Without return value of inlined method on stack - FrameState continuationState; - - /** - * Field used to generate fewer blocks when inlining. If this value is {@code null}, - * then no {@code return}s have been encountered during inlining. If it is an instance - * of {@link ReturnBlock}, then it is the block info for the single {@code return} - * encountered. Otherwise, it will be {@link ReturnBlock#MULTIPLE_RETURNS}. - */ - ReturnBlock inlinedReturnBlock; - - /** - * Tracks the destination bci of the jsr. This is (currently) only used to determine - * bailout conditions, since only a subset of all of the possible jsr-ret control - * structures can (currently) be compiled. - * - * A value > 0 for this field indicates parsing of a jsr. - */ - final int jsrEntryBci; - - // We need to track the local variable in which the return address - // was stored to ensure we can handle inlining the jsr, because we - // don't handle arbitrary jsr/ret constructs. - int jsrRetAddrLocal; - - // If we are parsing a jsr, the continuation point for rets - BlockBegin jsrContinuation; - - final BlockBegin[] jsrDuplicatedBlocks; // blocks that have been duplicated for JSR inlining - - /** - * Constructs a new ScopeData instance with the specified parent ScopeData. - * @param parent the parent scope data - * @param scope the IR scope - * @param blockMap the block map for this scope - * @param stream the bytecode stream - * @param constantPool the constant pool - */ - public ScopeData(ScopeData parent, IRScope scope, BlockMap blockMap, BytecodeStream stream, RiConstantPool constantPool) { - this.parent = parent; - this.scope = scope; - this.blockMap = blockMap; - this.stream = stream; - this.constantPool = constantPool; - this.jsrEntryBci = -1; - this.jsrDuplicatedBlocks = null; - if (parent != null) { - maxInlineSize = (int) (C1XOptions.MaximumInlineRatio * parent.maxInlineSize()); - if (maxInlineSize < C1XOptions.MaximumTrivialSize) { - maxInlineSize = C1XOptions.MaximumTrivialSize; - } - if (parent.hasHandler()) { - flags |= HasHandler.mask; - } - if (parent.noSafepoints() || scope.method.noSafepoints()) { - flags |= NoSafepoints.mask; - } - } else { - maxInlineSize = C1XOptions.MaximumInlineSize; - if (scope.method.noSafepoints()) { - flags |= NoSafepoints.mask; - } - } - RiExceptionHandler[] handlers = scope.method.exceptionHandlers(); - if (handlers != null && handlers.length > 0) { - exceptionHandlers = new ArrayList<ExceptionHandler>(handlers.length); - for (RiExceptionHandler ch : handlers) { - ExceptionHandler h = new ExceptionHandler(ch); - h.setEntryBlock(blockAt(h.handler.handlerBCI())); - exceptionHandlers.add(h); - } - flags |= HasHandler.mask; - } - } - - /** - * Constructs a new ScopeData instance with the specified parent ScopeData. This constructor variant creates - * a scope data for parsing a JSR. - * @param parent the parent scope data - * @param scope the IR scope - * @param blockMap the block map for this scope - * @param stream the bytecode stream - * @param constantPool the constant pool - * @param jsrEntryBci the bytecode index of the entrypoint of the JSR - */ - public ScopeData(ScopeData parent, IRScope scope, BlockMap blockMap, BytecodeStream stream, RiConstantPool constantPool, int jsrEntryBci) { - this.parent = parent; - this.scope = scope; - this.blockMap = blockMap; - this.stream = stream; - this.constantPool = constantPool; - assert jsrEntryBci > 0 : "jsr cannot jump to BCI 0"; - assert parent != null : "jsr must have parent scope"; - this.jsrEntryBci = jsrEntryBci; - this.jsrDuplicatedBlocks = new BlockBegin[scope.method.code().length]; - this.jsrRetAddrLocal = -1; - - maxInlineSize = (int) (C1XOptions.MaximumInlineRatio * parent.maxInlineSize()); - if (maxInlineSize < C1XOptions.MaximumTrivialSize) { - maxInlineSize = C1XOptions.MaximumTrivialSize; - } - flags = parent.flags; - - // duplicate the parent scope's exception handlers, if any - List<ExceptionHandler> handlers = parent.exceptionHandlers(); - if (handlers != null && handlers.size() > 0) { - exceptionHandlers = new ArrayList<ExceptionHandler>(handlers.size()); - for (ExceptionHandler ph : handlers) { - ExceptionHandler h = new ExceptionHandler(ph); - int handlerBci = h.handler.handlerBCI(); - if (handlerBci >= 0) { - // need to duplicate the handler block because it is a "normal" handler - h.setEntryBlock(blockAt(handlerBci)); - } else { - // don't duplicate the handler block because it is a synchronization handler - // that was added by parsing/inlining a synchronized method - assert ph.entryBlock().checkBlockFlag(BlockBegin.BlockFlag.DefaultExceptionHandler); - h.setEntryBlock(ph.entryBlock()); - } - exceptionHandlers.add(h); - } - assert hasHandler(); - } - } - - /** - * Gets the block beginning at the specified bytecode index. Note that this method - * will clone the block if it the scope data is currently parsing a JSR. - * @param bci the bytecode index of the start of the block - * @return the block starting at the specified bytecode index - */ - public BlockBegin blockAt(int bci) { - if (jsrDuplicatedBlocks != null) { - // all blocks in a JSR are duplicated on demand using an internal array, - // including those for exception handlers in the scope of the method - // containing the jsr (because those exception handlers may contain ret - // instructions in some cases). - BlockBegin block = jsrDuplicatedBlocks[bci]; - if (block == null) { - BlockBegin p = this.parent.blockAt(bci); - if (p != null) { - BlockBegin newBlock = new BlockBegin(p.bci(), C1XCompilation.compilation().hir().nextBlockNumber()); - newBlock.setDepthFirstNumber(p.depthFirstNumber()); - newBlock.copyBlockFlags(p); - jsrDuplicatedBlocks[bci] = newBlock; - block = newBlock; - } - } - return block; - } - return blockMap.get(bci); - } - - /** - * Checks whether this scope has any handlers. - * @return {@code true} if there are any exception handlers - */ - public boolean hasHandler() { - return (flags & Flag.HasHandler.mask) != 0; - } - - /** - * Checks whether this scope can contain safepoints. - */ - public boolean noSafepoints() { - return (flags & Flag.NoSafepoints.mask) != 0; - } - - /** - * Gets the maximum inline size. - * @return the maximum inline size - */ - public int maxInlineSize() { - return maxInlineSize; - } - - /** - * Gets the size of the stack at the caller. - * @return the size of the stack - */ - public int callerStackSize() { - FrameState state = scope.callerState; - return state == null ? 0 : state.stackSize(); - } - - /** - * Gets the block continuation for this ScopeData. - * @return the continuation - */ - public BlockBegin continuation() { - return continuation; - } - - /** - * Sets the continuation for this ScopeData. - * @param continuation the continuation - */ - public void setContinuation(BlockBegin continuation) { - this.continuation = continuation; - } - - /** - * Gets the state at the continuation point. - * @return the state at the continuation point - */ - public FrameState continuationState() { - return continuationState; - } - - /** - * Sets the state at the continuation point. - * @param state the state at the continuation - */ - public void setContinuationState(FrameState state) { - continuationState = state; - } - - /** - * Checks whether this ScopeData is parsing a JSR. - * @return {@code true} if this scope data is parsing a JSR - */ - public boolean parsingJsr() { - return jsrEntryBci > 0; - } - - /** - * Gets the bytecode index for the JSR entry. - * @return the jsr entry bci - */ - public int jsrEntryBCI() { - return jsrEntryBci; - } - - /** - * Gets the index of the local variable containing the JSR return address. - * @return the index of the local with the JSR return address - */ - public int jsrEntryReturnAddressLocal() { - return jsrRetAddrLocal; - } - - /** - * Sets the index of the local variable containing the JSR return address. - * @param local the local - */ - public void setJsrEntryReturnAddressLocal(int local) { - jsrRetAddrLocal = local; - } - - /** - * Gets the continuation for parsing a JSR. - * @return the jsr continuation - */ - public BlockBegin jsrContinuation() { - return jsrContinuation; - } - - /** - * Sets the continuation for parsing a JSR. - * @param block the block that is the continuation - */ - public void setJsrContinuation(BlockBegin block) { - jsrContinuation = block; - } - - /** - * A block delimited by a return instruction in an inlined method. - */ - public static class ReturnBlock { - /** - * The inlined block. - */ - final BlockBegin block; - - /** - * The second last instruction in the block. That is, the one before the return instruction. - */ - final Instruction returnPredecessor; - - /** - * The frame state at the end of the block. - */ - final FrameState returnState; - - ReturnBlock(BlockBegin block, Instruction returnPredecessor, FrameState returnState) { - super(); - this.block = block; - this.returnPredecessor = returnPredecessor; - this.returnState = returnState; - } - - public static final ReturnBlock MULTIPLE_RETURNS = new ReturnBlock(null, null, null); - } - - /** - * Updates the info about blocks in this scope delimited by a return instruction. - * - * @param block a block delimited by a {@code return} instruction - * @param returnPredecessor the second last instruction in the block. That is, the one before the return instruction. - * @param returnState the frame state after the return instruction - */ - public void updateSimpleInlineInfo(BlockBegin block, Instruction returnPredecessor, FrameState returnState) { - if (inlinedReturnBlock == null) { - inlinedReturnBlock = new ReturnBlock(block, returnPredecessor, returnState); - } else { - inlinedReturnBlock = MULTIPLE_RETURNS; - } - } - - /** - * Gets the return block info for a simple inline scope. That is, a scope that contains only a - * single block delimited by a {@code return} instruction. - * - * @return the return block info for a simple inline scope or {@code null} if this is not a simple inline scope - */ - public ReturnBlock simpleInlineInfo() { - if (inlinedReturnBlock == MULTIPLE_RETURNS) { - return null; - } - return inlinedReturnBlock; - } - - /** - * Gets the list of exception handlers for this scope data. - * @return the list of exception handlers - */ - public List<ExceptionHandler> exceptionHandlers() { - return exceptionHandlers; - } - - /** - * Adds an exception handler to this scope data. - * @param handler the handler to add - */ - public void addExceptionHandler(ExceptionHandler handler) { - if (exceptionHandlers == null) { - exceptionHandlers = new ArrayList<ExceptionHandler>(); - } - assert !parsingJsr() : "jsr scope should already have all the handlers it needs"; - exceptionHandlers.add(handler); - flags |= HasHandler.mask; - } - - /** - * Adds a block to the worklist, if it is not already in the worklist. - * This method will keep the worklist topologically stored (i.e. the lower - * DFNs are earlier in the list). - * @param block the block to add to the work list - */ - public void addToWorkList(BlockBegin block) { - if (!block.isOnWorkList()) { - if (block == continuation || block == jsrContinuation) { - return; - } - block.setOnWorkList(true); - sortIntoWorkList(block); - } - } - - private void sortIntoWorkList(BlockBegin top) { - // XXX: this is O(n), since the whole list is sorted; a heap could achieve O(nlogn), but - // would only pay off for large worklists - if (workList == null) { - // need to allocate the worklist - workList = new BlockBegin[5]; - } else if (workListIndex == workList.length) { - // need to grow the worklist - BlockBegin[] nworkList = new BlockBegin[workList.length * 3]; - System.arraycopy(workList, 0, nworkList, 0, workList.length); - workList = nworkList; - } - // put the block at the end of the array - workList[workListIndex++] = top; - int dfn = top.depthFirstNumber(); - assert dfn >= 0 : top + " does not have a depth first number"; - int i = workListIndex - 2; - // push top towards the beginning of the array - for (; i >= 0; i--) { - BlockBegin b = workList[i]; - if (b.depthFirstNumber() >= dfn) { - break; // already in the right position - } - workList[i + 1] = b; // bubble b down by one - workList[i] = top; // and overwrite it with top - } - } - - /** - * Removes the next block from the worklist. The list is sorted topologically, so the - * block with the lowest depth first number in the list will be removed and returned. - * @return the next block from the worklist; {@code null} if there are no blocks - * in the worklist - */ - public BlockBegin removeFromWorkList() { - if (workListIndex == 0) { - return null; - } - // pop the last item off the end - return workList[--workListIndex]; - } - - /** - * Converts this scope data to a string for debugging purposes. - * @return a string representation of this scope data - */ - @Override - public String toString() { - if (parsingJsr()) { - return "jsr@" + jsrEntryBci + " data for " + scope.toString(); - } else { - return "data for " + scope.toString(); - } - - } -}
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/BlockBegin.java Fri Apr 29 11:14:05 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/BlockBegin.java Mon May 02 10:24:43 2011 +0200 @@ -31,6 +31,7 @@ import com.sun.c1x.util.*; import com.sun.c1x.value.*; import com.sun.cri.ci.*; +import com.sun.cri.ri.*; /** * Denotes the beginning of a basic block, and holds information @@ -394,7 +395,7 @@ v.visitBlockBegin(this); } - public void mergeOrClone(FrameState newState) { + public void mergeOrClone(FrameState newState, RiMethod method) { FrameState existingState = stateBefore; if (existingState == null) { @@ -409,7 +410,7 @@ if (C1XOptions.UseStackMapTableLiveness) { // if a liveness map is available, use it to invalidate dead locals - CiBitMap[] livenessMap = newState.scope().method.livenessMap(); + CiBitMap[] livenessMap = method.livenessMap(); if (livenessMap != null && bci() >= 0) { assert bci() < livenessMap.length; CiBitMap liveness = livenessMap[bci()]; @@ -426,19 +427,11 @@ stateBefore = newState; } else { - if (!C1XOptions.AssumeVerifiedBytecode && !existingState.isSameAcrossScopes(newState)) { + if (!C1XOptions.AssumeVerifiedBytecode && !existingState.isSame(newState)) { // stacks or locks do not match--bytecodes would not verify throw new CiBailout("stack or locks do not match"); } - // while (existingState.scope() != newState.scope()) { - // // XXX: original code is not sure if this is necessary - // newState = newState.scope().callerState(); - // assert newState != null : "could not match scopes"; - // } - // above code replaced with assert for the moment - assert existingState.scope() == newState.scope(); - assert existingState.localsSize() == newState.localsSize(); assert existingState.stackSize() == newState.stackSize(); @@ -471,19 +464,10 @@ newState.setupPhiForStack(this, i); } int localsSize = newState.localsSize(); - CiBitMap requiresPhi = newState.scope().getStoresInLoops(); for (int i = 0; i < localsSize; i++) { Value x = newState.localAt(i); if (x != null) { - if (requiresPhi != null) { - if (requiresPhi.get(i) || x.kind.isDoubleWord() && requiresPhi.get(i + 1)) { - // selectively do a phi - newState.setupPhiForLocal(this, i); - } - } else { - // always setup a phi - newState.setupPhiForLocal(this, i); - } + newState.setupPhiForLocal(this, i); } } } @@ -792,19 +776,16 @@ } } - do { - for (i = 0; !hasPhisInLocals && i < state.localsSize();) { - Value value = state.localAt(i); - hasPhisInLocals = isPhiAtBlock(value); - // also ignore illegal HiWords - if (value != null && !value.isIllegal()) { - i += value.kind.sizeInSlots(); - } else { - i++; - } + for (i = 0; !hasPhisInLocals && i < state.localsSize();) { + Value value = state.localAt(i); + hasPhisInLocals = isPhiAtBlock(value); + // also ignore illegal HiWords + if (value != null && !value.isIllegal()) { + i += value.kind.sizeInSlots(); + } else { + i++; } - state = state.callerState(); - } while (state != null); + } } // print values in locals @@ -813,21 +794,18 @@ out.println("Locals:"); FrameState state = stateBefore(); - do { - int i = 0; - while (i < state.localsSize()) { - Value value = state.localAt(i); - if (value != null) { - out.println(stateString(i, value)); - // also ignore illegal HiWords - i += value.isIllegal() ? 1 : value.kind.sizeInSlots(); - } else { - i++; - } + int i = 0; + while (i < state.localsSize()) { + Value value = state.localAt(i); + if (value != null) { + out.println(stateString(i, value)); + // also ignore illegal HiWords + i += value.isIllegal() ? 1 : value.kind.sizeInSlots(); + } else { + i++; } - out.println(); - state = state.callerState(); - } while (state != null); + } + out.println(); } // print values on stack
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/IRScope.java Fri Apr 29 11:14:05 2011 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.sun.c1x.ir; - -import com.sun.c1x.value.*; -import com.sun.cri.ci.*; -import com.sun.cri.ri.*; - -/** - * The {@code IRScope} class represents an inlining context in the compilation - * of a method. - * - * @author Ben L. Titzer - */ -public class IRScope { - - public final IRScope caller; - public final RiMethod method; - public final int level; - CiCodePos callerCodePos; - - /** - * The frame state at the call site of this scope's caller or {@code null} - * if this is not a nested scope. - */ - public final FrameState callerState; - - /** - * The maximum number of locks held in this scope at any one time - * (c.f. maxStack and maxLocals of the Code attribute in a class file). - */ - int maxLocks; - - CiBitMap storesInLoops; - - public IRScope(IRScope caller, FrameState callerState, RiMethod method, int osrBCI) { - this.caller = caller; - this.callerState = callerState; - this.method = method; - this.level = caller == null ? 0 : 1 + caller.level; - } - - /** - * Updates the maximum number of locks held in this scope at any one time. - * - * @param locks a lock count that will replace the current {@linkplain #maxLocks() max locks} for this scope if it is greater - */ - public void updateMaxLocks(int locks) { - if (locks > maxLocks) { - maxLocks = locks; - } - } - - /** - * Gets the number of locks in this IR scope. - * @return the number of locks - */ - public final int maxLocks() { - return maxLocks; - } - - /** - * Gets the bytecode index of the call site that called this method. - * @return the call site's bytecode index - */ - public final int callerBCI() { - return callerState == null ? -1 : callerState.bci; - } - - /** - * Returns whether this IR scope is the top scope (i.e. has no caller). - * @return {@code true} if this inlining scope has no parent - */ - public final boolean isTopScope() { - return caller == null; - } - - /** - * Gets the phi bitmap for this IR scope. The phi bitmap stores - * whether a phi instruction is required for each local variable. - * @return the phi bitmap for this IR scope - */ - public final CiBitMap getStoresInLoops() { - return storesInLoops; - } - - public final void setStoresInLoops(CiBitMap storesInLoops) { - this.storesInLoops = storesInLoops; - } - - @Override - public String toString() { - if (caller == null) { - return "root-scope: " + method; - } else { - return "inlined-scope: " + method + " [caller bci: " + callerState.bci + "]"; - } - } - - public CiCodePos callerCodePos() { - if (caller != null && callerCodePos == null) { - callerCodePos = caller.toCodePos(callerBCI()); - } - return callerCodePos; - } - - public CiCodePos toCodePos(int bci) { - return new CiCodePos(callerCodePos(), method, bci); - } -}
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/StateSplit.java Fri Apr 29 11:14:05 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/StateSplit.java Mon May 02 10:24:43 2011 +0200 @@ -36,7 +36,7 @@ /** * Sentinel denoting an explicitly cleared state. */ - private static final FrameState CLEARED_STATE = new MutableFrameState(null, -5, 0, 0); + private static final FrameState CLEARED_STATE = new MutableFrameState(-5, 0, 0); private FrameState stateBefore;
--- a/graal/GraalCompiler/src/com/sun/c1x/lir/FrameMap.java Fri Apr 29 11:14:05 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/lir/FrameMap.java Mon May 02 10:24:43 2011 +0200 @@ -326,7 +326,7 @@ } private int offsetForMonitorBase(int index) { - assert index >= 0 && index < monitorCount : "invalid monitor index"; + assert index >= 0 && index < monitorCount : "invalid monitor index : " + index+ " (monitorCount=" + monitorCount + ")"; int size = compilation.runtime.sizeOfBasicObjectLock(); assert size != 0 : "monitors are not on the stack in this VM"; int offset = offsetToMonitors() + index * size;
--- a/graal/GraalCompiler/src/com/sun/c1x/value/FrameState.java Fri Apr 29 11:14:05 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/value/FrameState.java Mon May 02 10:24:43 2011 +0200 @@ -28,7 +28,6 @@ import com.sun.c1x.graph.*; import com.sun.c1x.ir.*; import com.sun.cri.ci.*; -import com.sun.cri.ri.*; /** * The {@code FrameState} class encapsulates the frame state (i.e. local variables and @@ -62,8 +61,6 @@ */ protected final int maxLocals; - protected final IRScope scope; - /** * The bytecode index to which this frame state applies. This will be {@code -1} * iff this state is mutable. @@ -92,8 +89,7 @@ * @param maxLocals maximum number of locals * @param maxStack maximum size of the stack */ - public FrameState(IRScope irScope, int bci, int maxLocals, int maxStack) { - this.scope = irScope; + public FrameState(int bci, int maxLocals, int maxStack) { this.bci = bci; this.values = new Value[maxLocals + Math.max(maxStack, MINIMUM_STACK_SLOTS)]; this.maxLocals = maxLocals; @@ -111,7 +107,7 @@ * @return a new frame state with the specified components */ public MutableFrameState copy(int bci, boolean withLocals, boolean withStack, boolean withLocks) { - final MutableFrameState other = new MutableFrameState(scope, bci, localsSize(), maxStackSize()); + final MutableFrameState other = new MutableFrameState(bci, localsSize(), maxStackSize()); if (withLocals && withStack) { // fast path: use array copy int valuesSize = valuesSize(); @@ -154,7 +150,7 @@ return copy(bci, false, false, false); } - public boolean isSameAcrossScopes(FrameState other) { + public boolean isSame(FrameState other) { assert stackSize() == other.stackSize(); assert localsSize() == other.localsSize(); assert locksSize() == other.locksSize(); @@ -176,15 +172,6 @@ } /** - * Returns the inlining context associated with this frame state. - * - * @return the inlining context - */ - public IRScope scope() { - return scope; - } - - /** * Returns the size of the local variables. * * @return the size of the local variables @@ -200,10 +187,6 @@ return locks == null ? 0 : locks.size(); } - public int totalLocksSize() { - return locksSize() + ((callerState() == null) ? 0 : callerState().totalLocksSize()); - } - /** * Gets the current size (height) of the stack. */ @@ -373,11 +356,6 @@ return maxLocals + stackIndex; } - public final int callerStackSize() { - FrameState callerState = scope().callerState; - return callerState == null ? 0 : callerState.stackSize(); - } - public void checkPhis(BlockBegin block, FrameState other) { checkSize(other); final int max = valuesSize(); @@ -525,24 +503,21 @@ * @param closure the closure to apply to each value */ public static void valuesDo(FrameState state, ValueClosure closure) { - do { - final int max = state.valuesSize(); - for (int i = 0; i < max; i++) { - if (state.values[i] != null) { - Value newValue = closure.apply(state.values[i]); - state.values[i] = newValue; + final int max = state.valuesSize(); + for (int i = 0; i < max; i++) { + if (state.values[i] != null) { + Value newValue = closure.apply(state.values[i]); + state.values[i] = newValue; + } + } + if (state.locks != null) { + for (int i = 0; i < state.locks.size(); i++) { + Value instr = state.locks.get(i); + if (instr != null) { + state.locks.set(i, closure.apply(instr)); } } - if (state.locks != null) { - for (int i = 0; i < state.locks.size(); i++) { - Value instr = state.locks.get(i); - if (instr != null) { - state.locks.set(i, closure.apply(instr)); - } - } - } - state = state.callerState(); - } while (state != null); + } } /** @@ -558,95 +533,32 @@ * @param proc the call back called to process each live value traversed */ public final void forEachLiveStateValue(ValueProcedure proc) { - FrameState state = this; - while (state != null) { - final int max = state.valuesSize(); - for (int i = 0; i < max; i++) { - Value value = state.values[i]; - if (value != null) { - proc.doValue(value); - } - } - state = state.callerState(); - } - } - - public static String toString(FrameState fs) { - StringBuilder sb = new StringBuilder(); - String nl = String.format("%n"); - while (fs != null) { - if (fs.scope == null) { - sb.append("<no method>").append(" [bci: ").append(fs.bci).append(']'); - break; - } else { - CiUtil.appendLocation(sb, fs.scope.method, fs.bci).append(nl); - for (int i = 0; i < fs.localsSize(); ++i) { - Value value = fs.localAt(i); - sb.append(String.format(" local[%d] = %-8s : %s%n", i, value == null ? "bogus" : value.kind.javaName, value)); - } - for (int i = 0; i < fs.stackSize(); ++i) { - Value value = fs.stackAt(i); - sb.append(String.format(" stack[%d] = %-8s : %s%n", i, value == null ? "bogus" : value.kind.javaName, value)); - } - for (int i = 0; i < fs.locksSize(); ++i) { - Value value = fs.lockAt(i); - sb.append(String.format(" lock[%d] = %-8s : %s%n", i, value == null ? "bogus" : value.kind.javaName, value)); - } - fs = fs.callerState(); + final int max = this.valuesSize(); + for (int i = 0; i < max; i++) { + Value value = this.values[i]; + if (value != null) { + proc.doValue(value); } } - return sb.toString(); } @Override public String toString() { - return toString(this); - } - - public CiCodePos toCodePos() { - FrameState caller = callerState(); - CiCodePos callerCodePos = null; - if (caller != null) { - callerCodePos = caller.toCodePos(); + StringBuilder sb = new StringBuilder(); + String nl = String.format("%n"); + sb.append("[bci: ").append(this.bci).append("]").append(nl); + for (int i = 0; i < this.localsSize(); ++i) { + Value value = this.localAt(i); + sb.append(String.format(" local[%d] = %-8s : %s%n", i, value == null ? "bogus" : value.kind.javaName, value)); } - return new CiCodePos(callerCodePos, scope.method, bci); - } - - /** - * Creates a new {@code MutableFrameState} corresponding to inlining the specified method into this point in this frame state. - * @param scope the IRScope representing the inlined method - * @return a new frame state representing the state at the beginning of inlining the specified method into this one - */ - public MutableFrameState pushScope(IRScope scope) { - assert scope.caller == this.scope; - RiMethod method = scope.method; - return new MutableFrameState(scope, -1, method.maxLocals(), method.maxStackSize()); - } - - /** - * Creates a new {@code MutableFrameState} corresponding to the state upon returning from this inlined method into the outer - * IRScope. - * @return a new frame state representing the state at exit from this frame state - */ - public MutableFrameState popScope() { - IRScope callingScope = scope.caller; - assert callingScope != null; - FrameState callerState = scope.callerState; - MutableFrameState res = new MutableFrameState(callingScope, bci, callerState.maxLocals, callerState.maxStackSize() + stackIndex); - System.arraycopy(callerState.values, 0, res.values, 0, callerState.values.length); - System.arraycopy(values, maxLocals, res.values, res.maxLocals + callerState.stackIndex, stackIndex); - res.stackIndex = callerState.stackIndex + stackIndex; - assert res.stackIndex >= 0; - res.replaceLocks(callerState); - return res; - } - - /** - * Gets the caller frame state. - * - * @return the caller frame state or {@code null} if this is a top-level state - */ - public FrameState callerState() { - return scope.callerState; + for (int i = 0; i < this.stackSize(); ++i) { + Value value = this.stackAt(i); + sb.append(String.format(" stack[%d] = %-8s : %s%n", i, value == null ? "bogus" : value.kind.javaName, value)); + } + for (int i = 0; i < this.locksSize(); ++i) { + Value value = this.lockAt(i); + sb.append(String.format(" lock[%d] = %-8s : %s%n", i, value == null ? "bogus" : value.kind.javaName, value)); + } + return sb.toString(); } }
--- a/graal/GraalCompiler/src/com/sun/c1x/value/MutableFrameState.java Fri Apr 29 11:14:05 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/value/MutableFrameState.java Mon May 02 10:24:43 2011 +0200 @@ -24,6 +24,7 @@ import java.util.*; +import com.sun.c1x.graph.*; import com.sun.c1x.ir.*; import com.sun.c1x.util.*; import com.sun.cri.ci.*; @@ -43,8 +44,8 @@ */ public final class MutableFrameState extends FrameState { - public MutableFrameState(IRScope irScope, int bci, int maxLocals, int maxStack) { - super(irScope, bci, maxLocals, maxStack); + public MutableFrameState(int bci, int maxLocals, int maxStack) { + super(bci, maxLocals, maxStack); } /** @@ -328,12 +329,12 @@ * @param scope the IRScope in which this locking operation occurs * @param obj the object being locked */ - public void lock(IRScope scope, Value obj, int totalNumberOfLocks) { + public void lock(IR ir, Value obj, int totalNumberOfLocks) { if (locks == null) { locks = new ArrayList<Value>(4); } locks.add(obj); - scope.updateMaxLocks(totalNumberOfLocks); + ir.updateMaxLocks(totalNumberOfLocks); } /**
--- a/rundacapo.sh Fri Apr 29 11:14:05 2011 -0700 +++ b/rundacapo.sh Mon May 02 10:24:43 2011 +0200 @@ -15,4 +15,4 @@ echo "DACAPO is not defined. It must point to a SciMark benchmark directory." exit 1; fi -${JDK7}/bin/java -client -graal -Xms1g -Xmx2g -esa -classpath ${DACAPO}/dacapo-9.12-bach.jar Harness $* +${JDK7}/bin/java -client -graal -XX:-C1XBailoutIsFatal -Xms1g -Xmx2g -esa -classpath ${DACAPO}/dacapo-9.12-bach.jar Harness $*