changeset 3018:5857923e563c

Fixed an issue with frame states in exception dispatch chains (now we are correctly rethrowing the exception immediately at entering the interpreter).
author Thomas Wuerthinger <thomas@wuerthinger.net>
date Sat, 18 Jun 2011 19:13:55 +0200
parents b4ba003eb11d
children 77bb196828cb
files graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompilation.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/BlockMap.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Deoptimize.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRAssembler.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameStateBuilder.java graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Node.java graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotConstantPool.java graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodResolvedImpl.java src/share/vm/c1/c1_IR.hpp src/share/vm/c1/c1_LIRAssembler.cpp src/share/vm/code/debugInfoRec.cpp src/share/vm/code/debugInfoRec.hpp src/share/vm/code/nmethod.cpp src/share/vm/code/pcDesc.hpp src/share/vm/code/scopeDesc.cpp src/share/vm/code/scopeDesc.hpp src/share/vm/graal/graalCodeInstaller.cpp src/share/vm/graal/graalJavaAccess.hpp src/share/vm/prims/jvmtiCodeBlobEvents.cpp src/share/vm/runtime/deoptimization.cpp src/share/vm/runtime/deoptimization.hpp src/share/vm/runtime/vframe_hp.hpp
diffstat 28 files changed, 105 insertions(+), 51 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompilation.java	Sat Jun 18 14:51:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompilation.java	Sat Jun 18 19:13:55 2011 +0200
@@ -95,7 +95,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 FrameState(method, 0, 0, 0, 0, graph) : null;
+        this.placeholderState = method != null && method.minimalDebugInfo() ? new FrameState(method, 0, 0, 0, 0, false, graph) : null;
 
         if (compiler.isObserved()) {
             compiler.fireCompilationStarted(new CompilationEvent(this));
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java	Sat Jun 18 14:51:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java	Sat Jun 18 19:13:55 2011 +0200
@@ -1914,7 +1914,7 @@
         if (state.outerFrameState() != null) {
             caller = computeFrameForState(state.outerFrameState(), opId, frameRefMap);
         }
-        return new CiFrame(caller, state.method, state.bci, values, state.localsSize(), state.stackSize(), state.locksSize());
+        return new CiFrame(caller, state.method, state.bci, state.rethrowException(), values, state.localsSize(), state.stackSize(), state.locksSize());
     }
 
     private void computeDebugInfo(IntervalWalker iw, LIRInstruction op) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Sat Jun 18 14:51:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Sat Jun 18 19:13:55 2011 +0200
@@ -300,7 +300,7 @@
             slot += arguments[arg].sizeInSlots();
         }
 
-        FrameState fs = new FrameState(compilation.method, bci, compilation.method.maxLocals(), 0, 0, compilation.graph);
+        FrameState fs = new FrameState(compilation.method, bci, compilation.method.maxLocals(), 0, 0, false, compilation.graph);
         for (Node node : compilation.graph.start().usages()) {
             if (node instanceof Local) {
                 Local local = (Local) node;
@@ -534,7 +534,7 @@
     }
 
     protected FrameState stateBeforeInvokeReturn(Invoke invoke) {
-        return invoke.stateAfter().duplicateModified(getBeforeInvokeBci(invoke), invoke.kind);
+        return invoke.stateAfter().duplicateModified(getBeforeInvokeBci(invoke), invoke.stateAfter().rethrowException(), invoke.kind);
     }
 
     protected FrameState stateBeforeInvokeWithArguments(Invoke invoke) {
@@ -542,7 +542,7 @@
         for (int i = 0; i < invoke.argumentCount(); i++) {
             args[i] = invoke.argument(i);
         }
-        return invoke.stateAfter().duplicateModified(getBeforeInvokeBci(invoke), invoke.kind, args);
+        return invoke.stateAfter().duplicateModified(getBeforeInvokeBci(invoke), invoke.stateAfter().rethrowException(), invoke.kind, args);
     }
 
     private int getBeforeInvokeBci(Invoke invoke) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/BlockMap.java	Sat Jun 18 14:51:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/BlockMap.java	Sat Jun 18 19:13:55 2011 +0200
@@ -132,6 +132,7 @@
     public static class ExceptionBlock  extends Block {
         public RiExceptionHandler handler;
         public Block next;
+        public int deoptBci;
     }
 
     public static class DeoptBlock  extends Block {
@@ -157,6 +158,8 @@
 
     private final RiMethod method;
 
+    private final RiExceptionHandler[] exceptionHandlers;
+
     public final HashMap<Integer, BranchOverride> branchOverride;
 
     private Block[] blockMap;
@@ -169,6 +172,7 @@
      */
     public BlockMap(RiMethod method) {
         this.method = method;
+        exceptionHandlers = method.exceptionHandlers();
         this.blockMap = new Block[method.codeSize()];
         if (method.exceptionHandlers().length != 0) {
             this.canTrap = new BitSet(blockMap.length);
@@ -178,6 +182,10 @@
         branchOverride = new HashMap<Integer, BranchOverride>();
     }
 
+    public RiExceptionHandler[] exceptionHandlers() {
+        return exceptionHandlers;
+    }
+
     /**
      * Builds the block map and conservative CFG and numbers blocks.
      */
@@ -202,7 +210,7 @@
 
     private void makeExceptionEntries() {
         // start basic blocks at all exception handler blocks and mark them as exception entries
-        for (RiExceptionHandler h : method.exceptionHandlers()) {
+        for (RiExceptionHandler h : this.exceptionHandlers) {
             Block xhandler = makeBlock(h.handlerBCI());
             xhandler.isExceptionEntry = true;
         }
@@ -427,7 +435,7 @@
 
     private ExceptionBlock unwindBlock;
 
-    private Block makeExceptionDispatch(List<RiExceptionHandler> handlers, int index) {
+    private Block makeExceptionDispatch(List<RiExceptionHandler> handlers, int index, int bci) {
         RiExceptionHandler handler = handlers.get(index);
         if (handler.isCatchAll()) {
             return blockMap[handler.handlerBCI()];
@@ -437,10 +445,11 @@
             block = new ExceptionBlock();
             block.startBci = -1;
             block.endBci = -1;
+            block.deoptBci = bci;
             block.handler = handler;
             block.successors.add(blockMap[handler.handlerBCI()]);
             if (index < handlers.size() - 1) {
-                block.next = makeExceptionDispatch(handlers, index + 1);
+                block.next = makeExceptionDispatch(handlers, index + 1, bci);
                 block.successors.add(block.next);
             }
             exceptionDispatch.put(handler, block);
@@ -457,7 +466,7 @@
             Block block = blockMap[bci];
 
             ArrayList<RiExceptionHandler> handlers = null;
-            for (RiExceptionHandler h : method.exceptionHandlers()) {
+            for (RiExceptionHandler h : this.exceptionHandlers) {
                 if (h.startBCI() <= bci && bci < h.endBCI()) {
                     if (handlers == null) {
                         handlers = new ArrayList<RiExceptionHandler>();
@@ -469,7 +478,7 @@
                 }
             }
             if (handlers != null) {
-                Block dispatch = makeExceptionDispatch(handlers, 0);
+                Block dispatch = makeExceptionDispatch(handlers, 0, bci);
                 block.successors.add(dispatch);
             }
         }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Deoptimize.java	Sat Jun 18 14:51:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Deoptimize.java	Sat Jun 18 19:13:55 2011 +0200
@@ -39,6 +39,7 @@
         InvalidateReprofile,            // invalidate the nmethod, reset IC, maybe recompile
         InvalidateRecompile,            // invalidate the nmethod, recompile (probably)
         InvalidateStopCompiling,        // invalidate the nmethod and do not compile
+        RethrowExceptionInInterpreter,
     }
 
     private String message;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java	Sat Jun 18 14:51:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java	Sat Jun 18 19:13:55 2011 +0200
@@ -29,7 +29,6 @@
 import com.oracle.max.graal.compiler.gen.*;
 import com.oracle.max.graal.compiler.ir.*;
 import com.oracle.max.graal.graph.*;
-import com.sun.cri.ci.*;
 
 
 public class DeadCodeEliminationPhase extends Phase {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java	Sat Jun 18 14:51:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java	Sat Jun 18 19:13:55 2011 +0200
@@ -70,6 +70,7 @@
     private final RiRuntime runtime;
     private final RiMethod method;
     private final RiConstantPool constantPool;
+    private RiExceptionHandler[] exceptionHandlers;
 
     private final BytecodeStream stream;           // the bytecode stream
     private final LogStream log;
@@ -152,6 +153,7 @@
         BlockMap blockMap = compilation.getBlockMap(method);
         this.branchOverride = blockMap.branchOverride;
 
+        exceptionHandlers = blockMap.exceptionHandlers();
         blockList = new ArrayList<Block>(blockMap.blocks);
         blockFromBci = new Block[method.codeSize()];
         for (int i = 0; i < blockList.size(); i++) {
@@ -285,6 +287,9 @@
         assert first instanceof StateSplit;
 
         int bci = target.startBci;
+        if (target instanceof ExceptionBlock) {
+            bci = ((ExceptionBlock) target).deoptBci;
+        }
 
         FrameState existingState = ((StateSplit) first).stateAfter();
 
@@ -379,7 +384,6 @@
         assert bci == Instruction.SYNCHRONIZATION_ENTRY_BCI || bci == bci() : "invalid bci";
 
         RiExceptionHandler firstHandler = null;
-        RiExceptionHandler[] exceptionHandlers = method.exceptionHandlers();
         // join with all potential exception handlers
         if (exceptionHandlers != null) {
             for (RiExceptionHandler handler : exceptionHandlers) {
@@ -431,7 +435,7 @@
                 currentNext = exception;
                 currentExceptionObject = exception;
             }
-            FrameState stateWithException = entryState.duplicateModified(bci, CiKind.Void, currentExceptionObject);
+            FrameState stateWithException = entryState.duplicateWithException(bci, currentExceptionObject);
 
             currentNext.setNext(createTarget(dispatchBlock, stateWithException));
             return entry;
@@ -1281,7 +1285,7 @@
             assert frameState.stackSize() == 1 : "only exception object expected on stack, actual size: " + frameState.stackSize();
             createUnwindBlock(block);
         } else {
-            assert frameState.stackSize() == 1;
+            assert frameState.stackSize() == 1 : frameState;
 
             Block nextBlock = block.next == null ? unwindBlock() : block.next;
             if (block.handler.catchType().isResolved()) {
@@ -1289,7 +1293,7 @@
                 FixedNode nextDispatch = createTarget(nextBlock, frameState);
                 append(new ExceptionDispatch(frameState.stackAt(0), catchSuccessor, nextDispatch, block.handler.catchType(), graph));
             } else {
-                Deoptimize deopt = new Deoptimize(DeoptAction.InvalidateRecompile, graph);
+                Deoptimize deopt = new Deoptimize(DeoptAction.RethrowExceptionInInterpreter, graph);
                 deopt.setMessage("unresolved " + block.handler.catchType().name());
                 append(deopt);
 //                FixedNode nextDispatch = createTarget(nextBlock, frameState);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Sat Jun 18 14:51:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Sat Jun 18 19:13:55 2011 +0200
@@ -411,7 +411,7 @@
 
         // adjust all frame states that were copied
         if (frameStates.size() > 0) {
-            FrameState outerFrameState = stateAfter.duplicateModified(invoke.bci, invoke.kind);
+            FrameState outerFrameState = stateAfter.duplicateModified(invoke.bci, stateAfter.rethrowException(), invoke.kind);
             for (Node node : frameStates) {
                 FrameState frameState = (FrameState) duplicates.get(node);
                 if (!frameState.isDeleted()) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRAssembler.java	Sat Jun 18 14:51:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRAssembler.java	Sat Jun 18 19:13:55 2011 +0200
@@ -2087,6 +2087,9 @@
             case InvalidateStopCompiling:
                 code = 4;
                 break;
+            case RethrowExceptionInInterpreter:
+                code = 5;
+                break;
             default:
                 throw Util.shouldNotReachHere();
         }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java	Sat Jun 18 14:51:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java	Sat Jun 18 19:13:55 2011 +0200
@@ -49,6 +49,8 @@
 
     protected final int locksSize;
 
+    private final boolean rethrowException;
+
     private static final int SUCCESSOR_COUNT = 0;
 
     @Override
@@ -90,19 +92,20 @@
      * @param stackSize size of the stack
      * @param lockSize number of locks
      */
-    public FrameState(RiMethod method, int bci, int localsSize, int stackSize, int locksSize, Graph graph) {
+    public FrameState(RiMethod method, int bci, int localsSize, int stackSize, int locksSize, boolean rethrowException, Graph graph) {
         super(CiKind.Illegal, localsSize + stackSize + locksSize + INPUT_COUNT, SUCCESSOR_COUNT, graph);
         this.method = method;
         this.bci = bci;
         this.localsSize = localsSize;
         this.stackSize = stackSize;
         this.locksSize = locksSize;
+        this.rethrowException = rethrowException;
         GraalMetrics.FrameStatesCreated++;
         GraalMetrics.FrameStateValuesCreated += localsSize + stackSize + locksSize;
     }
 
-    FrameState(RiMethod method, int bci, Value[] locals, Value[] stack, int stackSize, ArrayList<Value> locks, Graph graph) {
-        this(method, bci, locals.length, stackSize, locks.size(), graph);
+    FrameState(RiMethod method, int bci, Value[] locals, Value[] stack, int stackSize, ArrayList<Value> locks, boolean rethrowException, Graph graph) {
+        this(method, bci, locals.length, stackSize, locks.size(), rethrowException, graph);
         for (int i = 0; i < locals.length; i++) {
             setValueAt(i, locals[i]);
         }
@@ -114,6 +117,10 @@
         }
     }
 
+    public boolean rethrowException() {
+        return rethrowException;
+    }
+
     /**
      * Gets a copy of this frame state.
      */
@@ -128,7 +135,7 @@
      */
     @Override
     public FrameState duplicateWithEmptyStack(int bci) {
-        FrameState other = new FrameState(method, bci, localsSize, 0, locksSize(), graph());
+        FrameState other = new FrameState(method, bci, localsSize, 0, locksSize(), rethrowException, graph());
         for (int i = 0; i < localsSize; i++) {
             other.setValueAt(i, localAt(i));
         }
@@ -139,15 +146,19 @@
         return other;
     }
 
+    public FrameState duplicateWithException(int bci, Value exceptionObject) {
+        return duplicateModified(bci, true, CiKind.Void, exceptionObject);
+    }
+
     /**
      * Creates a copy of this frame state with one stack element of type popKind popped from the stack and the
      * values in pushedValues pushed on the stack. The pushedValues are expected to be in slot encoding: a long
      * or double is followed by a null slot.
      */
-    public FrameState duplicateModified(int bci, CiKind popKind, Value... pushedValues) {
+    public FrameState duplicateModified(int bci, boolean rethrowException, CiKind popKind, Value... pushedValues) {
         int popSlots = popKind.sizeInSlots();
         int pushSlots = pushedValues.length;
-        FrameState other = new FrameState(method, bci, localsSize, stackSize - popSlots + pushSlots, locksSize(), graph());
+        FrameState other = new FrameState(method, bci, localsSize, stackSize - popSlots + pushSlots, locksSize(), rethrowException, graph());
         for (int i = 0; i < localsSize; i++) {
             other.setValueAt(i, localAt(i));
         }
@@ -481,14 +492,9 @@
         out.print("FrameState");
     }
 
-    @Override
-    public FrameState copy() {
-        return new FrameState(method, bci, localsSize, stackSize, locksSize, graph());
-    }
-
 
     private FrameState copy(int newBci) {
-        return new FrameState(method, newBci, localsSize, stackSize, locksSize, graph());
+        return new FrameState(method, newBci, localsSize, stackSize, locksSize, rethrowException, graph());
     }
 
     @Override
@@ -520,12 +526,12 @@
             str.append(i == 0 ? "" : ", ").append(lockAt(i) == null ? "_" : lockAt(i).id());
         }
         properties.put("locks", str.toString());
+        properties.put("rethrowException", rethrowException);
         return properties;
     }
 
     @Override
     public Node copy(Graph into) {
-        FrameState x = new FrameState(method, bci, localsSize, stackSize, locksSize, into);
-        return x;
+        return new FrameState(method, bci, localsSize, stackSize, locksSize, rethrowException, into);
     }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameStateBuilder.java	Sat Jun 18 14:51:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameStateBuilder.java	Sat Jun 18 19:13:55 2011 +0200
@@ -81,6 +81,11 @@
         this.locks = new ArrayList<Value>();
     }
 
+    @Override
+    public String toString() {
+        return String.format("FrameStateBuilder[stackSize=%d]", stackIndex);
+    }
+
     public void initializeFrom(FrameState other) {
         assert locals.length == other.localsSize() : "expected: " + locals.length + ", actual: " + other.localsSize();
         assert stack.length >= other.stackSize() : "expected: <=" + stack.length + ", actual: " + other.stackSize();
@@ -99,12 +104,12 @@
     }
 
     public FrameState create(int bci) {
-        return new FrameState(method, bci, locals, stack, stackIndex, locks, graph);
+        return new FrameState(method, bci, locals, stack, stackIndex, locks, false, graph);
     }
 
     @Override
     public FrameState duplicateWithEmptyStack(int bci) {
-        FrameState frameState = new FrameState(method, bci, locals, new Value[0], 0, locks, graph);
+        FrameState frameState = new FrameState(method, bci, locals, new Value[0], 0, locks, false, graph);
         frameState.setOuterFrameState(outerFrameState());
         return frameState;
     }
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Node.java	Sat Jun 18 14:51:18 2011 +0200
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Node.java	Sat Jun 18 19:13:55 2011 +0200
@@ -160,7 +160,7 @@
         return true;
     }
 
-    public Node copy() {
+    public final Node copy() {
         return copy(graph);
     }
 
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotConstantPool.java	Sat Jun 18 14:51:18 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotConstantPool.java	Sat Jun 18 19:13:55 2011 +0200
@@ -128,7 +128,9 @@
         RiType result = typeCache.get(cpi);
         if (result == null) {
             result = compiler.getVMEntries().RiConstantPool_lookupType(vmId, cpi);
-            typeCache.add(cpi, result);
+            if (result.isResolved()) {
+                typeCache.add(cpi, result);
+            }
         }
         return result;
     }
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodResolvedImpl.java	Sat Jun 18 14:51:18 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodResolvedImpl.java	Sat Jun 18 19:13:55 2011 +0200
@@ -80,10 +80,7 @@
 
     @Override
     public RiExceptionHandler[] exceptionHandlers() {
-        if (exceptionHandlers == null) {
-            exceptionHandlers = compiler.getVMEntries().RiMethod_exceptionHandlers(this);
-        }
-        return exceptionHandlers;
+        return compiler.getVMEntries().RiMethod_exceptionHandlers(this);
     }
 
     @Override
--- a/src/share/vm/c1/c1_IR.hpp	Sat Jun 18 14:51:18 2011 +0200
+++ b/src/share/vm/c1/c1_IR.hpp	Sat Jun 18 19:13:55 2011 +0200
@@ -237,7 +237,7 @@
     // reexecute allowed only for the topmost frame
     bool reexecute = topmost ? should_reexecute() : false;
     bool return_oop = false; // This flag will be ignored since it used only for C2 with escape analysis.
-    recorder->describe_scope(pc_offset, scope()->method(), bci(), reexecute, is_method_handle_invoke, return_oop, locvals, expvals, monvals);
+    recorder->describe_scope(pc_offset, scope()->method(), bci(), reexecute, false, is_method_handle_invoke, return_oop, locvals, expvals, monvals);
   }
 };
 
--- a/src/share/vm/c1/c1_LIRAssembler.cpp	Sat Jun 18 14:51:18 2011 +0200
+++ b/src/share/vm/c1/c1_LIRAssembler.cpp	Sat Jun 18 19:13:55 2011 +0200
@@ -405,7 +405,7 @@
     if (s == NULL)  break;
     IRScope* scope = s->scope();
     //Always pass false for reexecute since these ScopeDescs are never used for deopt
-    debug_info->describe_scope(pc_offset, scope->method(), s->bci(), false/*reexecute*/);
+    debug_info->describe_scope(pc_offset, scope->method(), s->bci(), false/*reexecute*/, false/*rethrow_exception*/);
   }
 
   debug_info->end_non_safepoint(pc_offset);
--- a/src/share/vm/code/debugInfoRec.cpp	Sat Jun 18 14:51:18 2011 +0200
+++ b/src/share/vm/code/debugInfoRec.cpp	Sat Jun 18 19:13:55 2011 +0200
@@ -283,6 +283,7 @@
                                               ciMethod*   method,
                                               int         bci,
                                               bool        reexecute,
+                                              bool        rethrow_exception,
                                               bool        is_method_handle_invoke,
                                               bool        return_oop,
                                               DebugToken* locals,
@@ -298,6 +299,7 @@
 
   // Record flags into pcDesc.
   last_pd->set_should_reexecute(reexecute);
+  last_pd->set_rethrow_exception(rethrow_exception);
   last_pd->set_is_method_handle_invoke(is_method_handle_invoke);
   last_pd->set_return_oop(return_oop);
 
--- a/src/share/vm/code/debugInfoRec.hpp	Sat Jun 18 14:51:18 2011 +0200
+++ b/src/share/vm/code/debugInfoRec.hpp	Sat Jun 18 19:13:55 2011 +0200
@@ -101,6 +101,7 @@
                       ciMethod*   method,
                       int         bci,
                       bool        reexecute,
+                      bool        rethrow_exception,
                       bool        is_method_handle_invoke = false,
                       bool        return_oop = false,
                       DebugToken* locals      = NULL,
--- a/src/share/vm/code/nmethod.cpp	Sat Jun 18 14:51:18 2011 +0200
+++ b/src/share/vm/code/nmethod.cpp	Sat Jun 18 19:13:55 2011 +0200
@@ -1079,7 +1079,7 @@
   PcDesc* pd = pc_desc_at(pc);
   guarantee(pd != NULL, "scope must be present");
   return new ScopeDesc(this, pd->scope_decode_offset(),
-                       pd->obj_decode_offset(), pd->should_reexecute(),
+                       pd->obj_decode_offset(), pd->should_reexecute(), pd->rethrow_exception(),
                        pd->return_oop());
 }
 
@@ -2267,7 +2267,7 @@
   PcDesc* pd = pc_desc_at(ic->end_of_call());
   assert(pd != NULL, "PcDesc must exist");
   for (ScopeDesc* sd = new ScopeDesc(this, pd->scope_decode_offset(),
-                                     pd->obj_decode_offset(), pd->should_reexecute(),
+                                     pd->obj_decode_offset(), pd->should_reexecute(), pd->rethrow_exception(),
                                      pd->return_oop());
        !sd->is_top(); sd = sd->sender()) {
     sd->verify();
@@ -2533,7 +2533,7 @@
   PcDesc* p = pc_desc_near(begin+1);
   if (p != NULL && p->real_pc(this) <= end) {
     return new ScopeDesc(this, p->scope_decode_offset(),
-                         p->obj_decode_offset(), p->should_reexecute(),
+                         p->obj_decode_offset(), p->should_reexecute(), p->rethrow_exception(),
                          p->return_oop());
   }
   return NULL;
--- a/src/share/vm/code/pcDesc.hpp	Sat Jun 18 14:51:18 2011 +0200
+++ b/src/share/vm/code/pcDesc.hpp	Sat Jun 18 19:13:55 2011 +0200
@@ -43,6 +43,7 @@
     int word;
     struct {
       unsigned int reexecute: 1;
+      unsigned int rethrow_exception: 1;
       unsigned int is_method_handle_invoke: 1;
       unsigned int return_oop: 1;
     } bits;
@@ -71,6 +72,8 @@
   // Flags
   bool     should_reexecute()              const { return _flags.bits.reexecute; }
   void set_should_reexecute(bool z)              { _flags.bits.reexecute = z;    }
+  bool     rethrow_exception()              const { return _flags.bits.rethrow_exception; }
+  void set_rethrow_exception(bool z)              { _flags.bits.rethrow_exception = z;    }
 
   // Does pd refer to the same information as pd?
   bool is_same_info(const PcDesc* pd) {
--- a/src/share/vm/code/scopeDesc.cpp	Sat Jun 18 14:51:18 2011 +0200
+++ b/src/share/vm/code/scopeDesc.cpp	Sat Jun 18 19:13:55 2011 +0200
@@ -31,21 +31,23 @@
 #include "runtime/handles.inline.hpp"
 
 
-ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute, bool return_oop) {
+ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute, bool rethrow_exception, bool return_oop) {
   _code          = code;
   _decode_offset = decode_offset;
   _objects       = decode_object_values(obj_decode_offset);
   _reexecute     = reexecute;
   _return_oop    = return_oop;
+  _rethrow_exception = rethrow_exception;
   decode_body();
 }
 
-ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, bool reexecute, bool return_oop) {
+ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, bool reexecute, bool rethrow_exception, bool return_oop) {
   _code          = code;
   _decode_offset = decode_offset;
   _objects       = decode_object_values(DebugInformationRecorder::serialized_null);
   _reexecute     = reexecute;
   _return_oop    = return_oop;
+  _rethrow_exception = rethrow_exception;
   decode_body();
 }
 
@@ -55,6 +57,7 @@
   _decode_offset = parent->_sender_decode_offset;
   _objects       = parent->_objects;
   _reexecute     = false; //reexecute only applies to the first scope
+  _rethrow_exception = false;
   _return_oop    = false;
   decode_body();
 }
--- a/src/share/vm/code/scopeDesc.hpp	Sat Jun 18 14:51:18 2011 +0200
+++ b/src/share/vm/code/scopeDesc.hpp	Sat Jun 18 19:13:55 2011 +0200
@@ -60,17 +60,18 @@
 class ScopeDesc : public ResourceObj {
  public:
   // Constructor
-  ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute, bool return_oop);
+  ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute, bool rethrow_exception, bool return_oop);
 
   // Calls above, giving default value of "serialized_null" to the
   // "obj_decode_offset" argument.  (We don't use a default argument to
   // avoid a .hpp-.hpp dependency.)
-  ScopeDesc(const nmethod* code, int decode_offset, bool reexecute, bool return_oop);
+  ScopeDesc(const nmethod* code, int decode_offset, bool reexecute, bool rethrow_exception, bool return_oop);
 
   // JVM state
   methodHandle method()   const { return _method; }
   int          bci()      const { return _bci;    }
   bool should_reexecute() const { return _reexecute; }
+  bool rethrow_exception() const { return _rethrow_exception; }
   bool return_oop()       const { return _return_oop; }
 
   GrowableArray<ScopeValue*>*   locals();
@@ -97,6 +98,7 @@
   methodHandle  _method;
   int           _bci;
   bool          _reexecute;
+  bool          _rethrow_exception;
   bool          _return_oop;
 
   // Decoding offsets
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Sat Jun 18 14:51:18 2011 +0200
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Sat Jun 18 19:13:55 2011 +0200
@@ -496,9 +496,14 @@
     DebugToken* expressions_token = _debug_recorder->create_scope_values(expressions);
     DebugToken* monitors_token = _debug_recorder->create_monitor_values(monitors);
 
-    _debug_recorder->describe_scope(pc_offset, cimethod, bci, reexecute, false, false, locals_token, expressions_token, monitors_token);
+    bool throw_exception = false;
+    if (CiFrame::rethrowException(frame)) {
+      throw_exception = true;
+    }
+
+    _debug_recorder->describe_scope(pc_offset, cimethod, bci, reexecute, throw_exception, false, false, locals_token, expressions_token, monitors_token);
   } else {
-    _debug_recorder->describe_scope(pc_offset, cimethod, bci, reexecute, false, false, NULL, NULL, NULL);
+    _debug_recorder->describe_scope(pc_offset, cimethod, bci, reexecute, false, false, false, NULL, NULL, NULL);
   }
 }
 
--- a/src/share/vm/graal/graalJavaAccess.hpp	Sat Jun 18 14:51:18 2011 +0200
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Sat Jun 18 19:13:55 2011 +0200
@@ -153,6 +153,7 @@
     int_field(CiFrame, numLocals)                                                       \
     int_field(CiFrame, numStack)                                                        \
     int_field(CiFrame, numLocks)                                                        \
+    boolean_field(CiFrame, rethrowException)                                            \
   end_class                                                                             \
   start_class(CiCodePos)                                                                \
     oop_field(CiCodePos, caller, "Lcom/sun/cri/ci/CiCodePos;")                          \
--- a/src/share/vm/prims/jvmtiCodeBlobEvents.cpp	Sat Jun 18 14:51:18 2011 +0200
+++ b/src/share/vm/prims/jvmtiCodeBlobEvents.cpp	Sat Jun 18 19:13:55 2011 +0200
@@ -251,7 +251,7 @@
 
     address scopes_data = nm->scopes_data_begin();
     for( pcd = nm->scopes_pcs_begin(); pcd < nm->scopes_pcs_end(); ++pcd ) {
-      ScopeDesc sc0(nm, pcd->scope_decode_offset(), pcd->should_reexecute(), pcd->return_oop());
+      ScopeDesc sc0(nm, pcd->scope_decode_offset(), pcd->should_reexecute(), pcd->rethrow_exception(), pcd->return_oop());
       ScopeDesc *sd  = &sc0;
       while( !sd->is_top() ) { sd = sd->sender(); }
       int bci = sd->bci();
--- a/src/share/vm/runtime/deoptimization.cpp	Sat Jun 18 14:51:18 2011 +0200
+++ b/src/share/vm/runtime/deoptimization.cpp	Sat Jun 18 19:13:55 2011 +0200
@@ -1239,6 +1239,15 @@
     int             trap_bci    = trap_scope->bci();
     Bytecodes::Code trap_bc     = trap_method->java_code_at(trap_bci);
 
+    if (trap_scope->rethrow_exception()) {
+      tty->print_cr("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Exception to be rethrown in the interpreter");
+      GrowableArray<ScopeValue*>* expressions = trap_scope->expressions();
+      ScopeValue* topOfStack = expressions->top();
+      Handle topOfStackObj = cvf->create_stack_value(topOfStack)->get_obj();
+      topOfStackObj->print();
+      THREAD->set_pending_exception(topOfStackObj(), NULL, 0);
+    }
+    
     // Record this event in the histogram.
     gather_statistics(reason, action, trap_bc);
 
@@ -1407,6 +1416,7 @@
       reprofile = true;
       break;
     case Action_make_not_entrant:
+    case Action_rethrow_exception_in_interpreter:
       // Request immediate recompilation, and get rid of the old code.
       // Make them not entrant, so next time they are called they get
       // recompiled.  Unloaded classes are loaded now so recompile before next
--- a/src/share/vm/runtime/deoptimization.hpp	Sat Jun 18 14:51:18 2011 +0200
+++ b/src/share/vm/runtime/deoptimization.hpp	Sat Jun 18 19:13:55 2011 +0200
@@ -72,6 +72,7 @@
     Action_reinterpret,           // invalidate the nmethod, reset IC, maybe recompile
     Action_make_not_entrant,      // invalidate the nmethod, recompile (probably)
     Action_make_not_compilable,   // invalidate the nmethod and do not compile
+    Action_rethrow_exception_in_interpreter,
     Action_LIMIT
     // Note:  Keep this enum in sync. with _trap_action_name.
   };
--- a/src/share/vm/runtime/vframe_hp.hpp	Sat Jun 18 14:51:18 2011 +0200
+++ b/src/share/vm/runtime/vframe_hp.hpp	Sat Jun 18 19:13:55 2011 +0200
@@ -66,7 +66,7 @@
   // Returns SynchronizationEntryBCI or bci() (used for synchronization)
   int raw_bci() const;
 
- protected:
+ //protected:
   ScopeDesc* _scope;