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 $*