changeset 57816:db2cc624c238

8231515: [Graal] Crash during exception throwing in InterpreterRuntime::resolve_invoke Reviewed-by: kvn, dlong, iveresov
author never
date Thu, 23 Jan 2020 08:43:22 -0800
parents 0672354bfc53
children 57f9707d8f18
files src/hotspot/share/aot/aotCodeHeap.cpp src/hotspot/share/jvmci/jvmciCompilerToVM.hpp src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp src/hotspot/share/jvmci/jvmciRuntime.cpp src/hotspot/share/jvmci/jvmciRuntime.hpp src/hotspot/share/jvmci/vmStructs_jvmci.cpp src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SubprocessTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotDeoptimizeCallerOp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotDeoptimizeOp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotDeoptimizeWithExceptionCallerOp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotEpilogueOp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64DeoptimizeOp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotDeoptimizeWithExceptionCallerOp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCDeoptimizeOp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotDeoptimizeWithExceptionCallerOp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLIRGenerator.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotDeoptExplicitExceptions.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotDeoptPostExceptions.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotDebugInfoBuilder.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotHostBackend.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerator.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DeoptimizeWithExceptionInCallerNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/FastNotifyNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/CreateExceptionStub.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FrameState.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BytecodeExceptionNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ForeignCallNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/NodePlugin.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ArrayStoreBytecodeExceptionTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/BytecodeExceptionTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ClassCastBytecodeExceptionTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/IndexOobBytecodeExceptionTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/NullBytecodeExceptionTest.java
diffstat 49 files changed, 834 insertions(+), 255 deletions(-) [+]
line wrap: on
line diff
--- a/src/hotspot/share/aot/aotCodeHeap.cpp	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/hotspot/share/aot/aotCodeHeap.cpp	Thu Jan 23 08:43:22 2020 -0800
@@ -465,6 +465,7 @@
     SET_AOT_GLOBAL_SYMBOL_VALUE("_resolve_virtual_entry", address, SharedRuntime::get_resolve_virtual_call_stub());
     SET_AOT_GLOBAL_SYMBOL_VALUE("_resolve_opt_virtual_entry", address, SharedRuntime::get_resolve_opt_virtual_call_stub());
     SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_deopt_blob_unpack", address, SharedRuntime::deopt_blob()->unpack());
+    SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_deopt_blob_unpack_with_exception_in_tls", address, SharedRuntime::deopt_blob()->unpack_with_exception_in_tls());
     SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_deopt_blob_uncommon_trap", address, SharedRuntime::deopt_blob()->uncommon_trap());
     SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_ic_miss_stub", address, SharedRuntime::get_ic_miss_stub());
     SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_handle_wrong_method_stub", address, SharedRuntime::get_handle_wrong_method_stub());
--- a/src/hotspot/share/jvmci/jvmciCompilerToVM.hpp	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.hpp	Thu Jan 23 08:43:22 2020 -0800
@@ -45,6 +45,7 @@
     static address SharedRuntime_ic_miss_stub;
     static address SharedRuntime_handle_wrong_method_stub;
     static address SharedRuntime_deopt_blob_unpack;
+    static address SharedRuntime_deopt_blob_unpack_with_exception_in_tls;
     static address SharedRuntime_deopt_blob_uncommon_trap;
 
     static size_t ThreadLocalAllocBuffer_alignment_reserve;
--- a/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp	Thu Jan 23 08:43:22 2020 -0800
@@ -44,6 +44,7 @@
 address CompilerToVM::Data::SharedRuntime_ic_miss_stub;
 address CompilerToVM::Data::SharedRuntime_handle_wrong_method_stub;
 address CompilerToVM::Data::SharedRuntime_deopt_blob_unpack;
+address CompilerToVM::Data::SharedRuntime_deopt_blob_unpack_with_exception_in_tls;
 address CompilerToVM::Data::SharedRuntime_deopt_blob_uncommon_trap;
 
 size_t CompilerToVM::Data::ThreadLocalAllocBuffer_alignment_reserve;
@@ -97,6 +98,7 @@
   SharedRuntime_ic_miss_stub = SharedRuntime::get_ic_miss_stub();
   SharedRuntime_handle_wrong_method_stub = SharedRuntime::get_handle_wrong_method_stub();
   SharedRuntime_deopt_blob_unpack = SharedRuntime::deopt_blob()->unpack();
+  SharedRuntime_deopt_blob_unpack_with_exception_in_tls = SharedRuntime::deopt_blob()->unpack_with_exception_in_tls();
   SharedRuntime_deopt_blob_uncommon_trap = SharedRuntime::deopt_blob()->uncommon_trap();
 
   ThreadLocalAllocBuffer_alignment_reserve = ThreadLocalAllocBuffer::alignment_reserve();
--- a/src/hotspot/share/jvmci/jvmciRuntime.cpp	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp	Thu Jan 23 08:43:22 2020 -0800
@@ -454,22 +454,31 @@
 
 JRT_END
 
-JRT_ENTRY(void, JVMCIRuntime::throw_and_post_jvmti_exception(JavaThread* thread, const char* exception, const char* message))
+JRT_BLOCK_ENTRY(int, JVMCIRuntime::throw_and_post_jvmti_exception(JavaThread* thread, const char* exception, const char* message))
+  JRT_BLOCK;
   TempNewSymbol symbol = SymbolTable::new_symbol(exception);
   SharedRuntime::throw_and_post_jvmti_exception(thread, symbol, message);
+  JRT_BLOCK_END;
+  return caller_is_deopted();
 JRT_END
 
-JRT_ENTRY(void, JVMCIRuntime::throw_klass_external_name_exception(JavaThread* thread, const char* exception, Klass* klass))
+JRT_BLOCK_ENTRY(int, JVMCIRuntime::throw_klass_external_name_exception(JavaThread* thread, const char* exception, Klass* klass))
+  JRT_BLOCK;
   ResourceMark rm(thread);
   TempNewSymbol symbol = SymbolTable::new_symbol(exception);
   SharedRuntime::throw_and_post_jvmti_exception(thread, symbol, klass->external_name());
+  JRT_BLOCK_END;
+  return caller_is_deopted();
 JRT_END
 
-JRT_ENTRY(void, JVMCIRuntime::throw_class_cast_exception(JavaThread* thread, const char* exception, Klass* caster_klass, Klass* target_klass))
+JRT_BLOCK_ENTRY(int, JVMCIRuntime::throw_class_cast_exception(JavaThread* thread, const char* exception, Klass* caster_klass, Klass* target_klass))
+  JRT_BLOCK;
   ResourceMark rm(thread);
   const char* message = SharedRuntime::generate_class_cast_message(caster_klass, target_klass);
   TempNewSymbol symbol = SymbolTable::new_symbol(exception);
   SharedRuntime::throw_and_post_jvmti_exception(thread, symbol, message);
+  JRT_BLOCK_END;
+  return caller_is_deopted();
 JRT_END
 
 JRT_LEAF(void, JVMCIRuntime::log_object(JavaThread* thread, oopDesc* obj, bool as_string, bool newline))
--- a/src/hotspot/share/jvmci/jvmciRuntime.hpp	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/hotspot/share/jvmci/jvmciRuntime.hpp	Thu Jan 23 08:43:22 2020 -0800
@@ -332,10 +332,10 @@
   static jboolean validate_object(JavaThread* thread, oopDesc* parent, oopDesc* child);
 
   // used to throw exceptions from compiled JVMCI code
-  static void throw_and_post_jvmti_exception(JavaThread* thread, const char* exception, const char* message);
+  static int throw_and_post_jvmti_exception(JavaThread* thread, const char* exception, const char* message);
   // helper methods to throw exception with complex messages
-  static void throw_klass_external_name_exception(JavaThread* thread, const char* exception, Klass* klass);
-  static void throw_class_cast_exception(JavaThread* thread, const char* exception, Klass* caster_klass, Klass* target_klass);
+  static int throw_klass_external_name_exception(JavaThread* thread, const char* exception, Klass* klass);
+  static int throw_class_cast_exception(JavaThread* thread, const char* exception, Klass* caster_klass, Klass* target_klass);
 
   // Test only function
   static jint test_deoptimize_call_int(JavaThread* thread, int value);
--- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp	Thu Jan 23 08:43:22 2020 -0800
@@ -48,6 +48,7 @@
   static_field(CompilerToVM::Data,             SharedRuntime_ic_miss_stub,             address)                                      \
   static_field(CompilerToVM::Data,             SharedRuntime_handle_wrong_method_stub, address)                                      \
   static_field(CompilerToVM::Data,             SharedRuntime_deopt_blob_unpack,        address)                                      \
+  static_field(CompilerToVM::Data,             SharedRuntime_deopt_blob_unpack_with_exception_in_tls,        address)                       \
   static_field(CompilerToVM::Data,             SharedRuntime_deopt_blob_uncommon_trap, address)                                      \
                                                                                                                                      \
   static_field(CompilerToVM::Data,             ThreadLocalAllocBuffer_alignment_reserve, size_t)                                     \
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java	Thu Jan 23 08:43:22 2020 -0800
@@ -36,15 +36,16 @@
 import java.util.List;
 import java.util.Map;
 
+import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
+import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
+
 import jdk.tools.jaotc.binformat.Symbol.Binding;
 import jdk.tools.jaotc.binformat.Symbol.Kind;
 import jdk.tools.jaotc.binformat.elf.JELFRelocObject;
 import jdk.tools.jaotc.binformat.macho.JMachORelocObject;
 import jdk.tools.jaotc.binformat.pecoff.JPECoffRelocObject;
-import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
-import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
-import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
 
 /**
  * A format-agnostic container class that holds various components of a binary.
@@ -145,6 +146,7 @@
     private static final String[][] map = {
         {"CompilerToVM::Data::SharedRuntime_deopt_blob_unpack",         "_aot_deopt_blob_unpack"},
         {"CompilerToVM::Data::SharedRuntime_deopt_blob_uncommon_trap",  "_aot_deopt_blob_uncommon_trap"},
+        {"CompilerToVM::Data::SharedRuntime_deopt_blob_unpack_with_exception_in_tls",  "_aot_deopt_blob_unpack_with_exception_in_tls"},
         {"CompilerToVM::Data::SharedRuntime_ic_miss_stub",              "_aot_ic_miss_stub"},
         {"CompilerToVM::Data::SharedRuntime_handle_wrong_method_stub",  "_aot_handle_wrong_method_stub"},
         {"SharedRuntime::exception_handler_for_return_address",         "_aot_exception_handler_for_return_address"},
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SubprocessTest.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SubprocessTest.java	Thu Jan 23 08:43:22 2020 -0800
@@ -51,7 +51,14 @@
             vmArgs.add(SubprocessUtil.PACKAGE_OPENING_OPTIONS);
             vmArgs.add("-D" + recursionPropName + "=true");
             configSubprocess(vmArgs);
+            boolean verbose = Boolean.getBoolean(getClass().getSimpleName() + ".verbose");
+            if (verbose) {
+                System.err.println(String.join(" ", vmArgs));
+            }
             SubprocessUtil.Subprocess proc = java(vmArgs, "com.oracle.mxtool.junit.MxJUnitWrapper", getClass().getName());
+            if (verbose) {
+                System.err.println(proc.output);
+            }
             assertTrue(proc.exitCode == 0, proc.toString() + " failed with exit code " + proc.exitCode);
         }
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java	Thu Jan 23 08:43:22 2020 -0800
@@ -41,6 +41,7 @@
 import org.graalvm.compiler.nodes.FrameState;
 import org.graalvm.compiler.nodes.ValueNode;
 import org.graalvm.compiler.nodes.spi.NodeValueMap;
+import org.graalvm.compiler.nodes.spi.NodeWithState;
 import org.graalvm.compiler.nodes.util.GraphUtil;
 import org.graalvm.compiler.nodes.virtual.EscapeObjectState;
 import org.graalvm.compiler.nodes.virtual.VirtualBoxingNode;
@@ -80,7 +81,7 @@
 
     protected final Queue<VirtualObjectNode> pendingVirtualObjects = new ArrayDeque<>();
 
-    public LIRFrameState build(FrameState topState, LabelRef exceptionEdge) {
+    public LIRFrameState build(NodeWithState node, FrameState topState, LabelRef exceptionEdge) {
         assert virtualObjects.size() == 0;
         assert objectStates.size() == 0;
         assert pendingVirtualObjects.size() == 0;
@@ -100,7 +101,8 @@
             current = current.outerFrameState();
         } while (current != null);
 
-        BytecodeFrame frame = computeFrameForState(topState);
+        assert verifyFrameState(node, topState);
+        BytecodeFrame frame = computeFrameForState(node, topState);
 
         VirtualObject[] virtualObjectsArray = null;
         if (virtualObjects.size() != 0) {
@@ -223,7 +225,18 @@
         return new LIRFrameState(frame, virtualObjectsArray, exceptionEdge);
     }
 
-    protected BytecodeFrame computeFrameForState(FrameState state) {
+    /**
+     * Perform platform dependent verification of the FrameState.
+     *
+     * @param node the node using the state
+     * @param topState the state
+     * @return true if the validation succeeded
+     */
+    protected boolean verifyFrameState(NodeWithState node, FrameState topState) {
+        return true;
+    }
+
+    protected BytecodeFrame computeFrameForState(NodeWithState node, FrameState state) {
         try {
             assert state.bci != BytecodeFrame.INVALID_FRAMESTATE_BCI;
             assert state.bci != BytecodeFrame.UNKNOWN_BCI;
@@ -249,7 +262,7 @@
 
             BytecodeFrame caller = null;
             if (state.outerFrameState() != null) {
-                caller = computeFrameForState(state.outerFrameState());
+                caller = computeFrameForState(node, state.outerFrameState());
             }
 
             if (!state.canProduceBytecodeFrame()) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java	Thu Jan 23 08:43:22 2020 -0800
@@ -104,6 +104,7 @@
 import org.graalvm.compiler.nodes.spi.LIRLowerable;
 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
 import org.graalvm.compiler.nodes.spi.NodeValueMap;
+import org.graalvm.compiler.nodes.spi.NodeWithState;
 import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
 import org.graalvm.compiler.options.OptionValues;
 
@@ -735,26 +736,26 @@
         if (!deopt.canDeoptimize()) {
             return null;
         }
-        return stateFor(getFrameState(deopt));
+        return stateFor(deopt, getFrameState(deopt));
     }
 
     public LIRFrameState stateWithExceptionEdge(DeoptimizingNode deopt, LabelRef exceptionEdge) {
         if (!deopt.canDeoptimize()) {
             return null;
         }
-        return stateForWithExceptionEdge(getFrameState(deopt), exceptionEdge);
+        return stateForWithExceptionEdge(deopt, getFrameState(deopt), exceptionEdge);
     }
 
-    public LIRFrameState stateFor(FrameState state) {
-        return stateForWithExceptionEdge(state, null);
+    public LIRFrameState stateFor(NodeWithState deopt, FrameState state) {
+        return stateForWithExceptionEdge(deopt, state, null);
     }
 
-    public LIRFrameState stateForWithExceptionEdge(FrameState state, LabelRef exceptionEdge) {
+    public LIRFrameState stateForWithExceptionEdge(NodeWithState deopt, FrameState state, LabelRef exceptionEdge) {
         if (gen.needOnlyOopMaps()) {
             return new LIRFrameState(null, null, null);
         }
-        assert state != null;
-        return getDebugInfoBuilder().build(state, exceptionEdge);
+        assert state != null : deopt;
+        return getDebugInfoBuilder().build(deopt, state, exceptionEdge);
     }
 
     @Override
@@ -765,7 +766,7 @@
 
     @Override
     public void visitFullInfopointNode(FullInfopointNode i) {
-        append(new FullInfopointOp(stateFor(i.getState()), i.getReason()));
+        append(new FullInfopointOp(stateFor(i, i.getState()), i.getReason()));
     }
 
     @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java	Thu Jan 23 08:43:22 2020 -0800
@@ -390,7 +390,7 @@
                 AArch64Call.directCall(crb, masm, linkage, helper, null);
             }
             crb.recordMark(config.MARKID_DEOPT_HANDLER_ENTRY);
-            ForeignCallLinkage linkage = foreignCalls.lookupForeignCall(DEOPTIMIZATION_HANDLER);
+            ForeignCallLinkage linkage = foreignCalls.lookupForeignCall(DEOPT_BLOB_UNPACK);
             masm.adr(lr, 0); // Warning: the argument is an offset from the instruction!
             AArch64Call.directJmp(crb, masm, linkage);
         } else {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotDeoptimizeCallerOp.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotDeoptimizeCallerOp.java	Thu Jan 23 08:43:22 2020 -0800
@@ -24,7 +24,7 @@
 
 package org.graalvm.compiler.hotspot.aarch64;
 
-import static org.graalvm.compiler.hotspot.HotSpotHostBackend.UNCOMMON_TRAP_HANDLER;
+import static org.graalvm.compiler.hotspot.HotSpotHostBackend.DEOPT_BLOB_UNCOMMON_TRAP;
 
 import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
@@ -47,6 +47,6 @@
     @Override
     public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
         leaveFrame(crb, masm, /* emitSafepoint */false, false);
-        AArch64Call.directJmp(crb, masm, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP_HANDLER));
+        AArch64Call.directJmp(crb, masm, crb.foreignCalls.lookupForeignCall(DEOPT_BLOB_UNCOMMON_TRAP));
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotDeoptimizeOp.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotDeoptimizeOp.java	Thu Jan 23 08:43:22 2020 -0800
@@ -24,7 +24,7 @@
 
 package org.graalvm.compiler.hotspot.aarch64;
 
-import static org.graalvm.compiler.hotspot.HotSpotHostBackend.UNCOMMON_TRAP_HANDLER;
+import static org.graalvm.compiler.hotspot.HotSpotHostBackend.DEOPT_BLOB_UNCOMMON_TRAP;
 
 import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
 import org.graalvm.compiler.lir.LIRFrameState;
@@ -49,7 +49,7 @@
     @Override
     public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
         try (AArch64MacroAssembler.ScratchRegister scratch = masm.getScratchRegister()) {
-            AArch64Call.directCall(crb, masm, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP_HANDLER), scratch.getRegister(), info, null);
+            AArch64Call.directCall(crb, masm, crb.foreignCalls.lookupForeignCall(DEOPT_BLOB_UNCOMMON_TRAP), scratch.getRegister(), info, null);
         }
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotDeoptimizeWithExceptionCallerOp.java	Thu Jan 23 08:43:22 2020 -0800
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013, 2018, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 org.graalvm.compiler.hotspot.aarch64;
+
+import static jdk.vm.ci.aarch64.AArch64.lr;
+import static jdk.vm.ci.code.ValueUtil.asRegister;
+import static org.graalvm.compiler.hotspot.HotSpotHostBackend.DEOPT_BLOB_UNPACK_WITH_EXCEPTION_IN_TLS;
+
+import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
+import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
+import org.graalvm.compiler.lir.LIRInstructionClass;
+import org.graalvm.compiler.lir.Opcode;
+import org.graalvm.compiler.lir.aarch64.AArch64Call;
+import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
+
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.meta.Value;
+
+/**
+ * Removes the current frame and tail calls the uncommon trap routine.
+ */
+@Opcode("DEOPT_WITH_EXCEPTION_IN_CALLER")
+public class AArch64HotSpotDeoptimizeWithExceptionCallerOp extends AArch64HotSpotEpilogueOp {
+    public static final LIRInstructionClass<AArch64HotSpotDeoptimizeWithExceptionCallerOp> TYPE = LIRInstructionClass.create(AArch64HotSpotDeoptimizeWithExceptionCallerOp.class);
+
+    @Use(OperandFlag.REG) private Value exception;
+
+    public AArch64HotSpotDeoptimizeWithExceptionCallerOp(GraalHotSpotVMConfig config, Value exception, Register thread) {
+        super(TYPE, config, thread);
+        this.exception = exception;
+    }
+
+    @Override
+    public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
+        Register exc = asRegister(exception);
+
+        leaveFrame(crb, masm, /* emitSafepoint */false, false);
+
+        // Save exception oop in TLS
+        masm.str(64, exc, masm.makeAddress(thread, config.threadExceptionOopOffset, 8));
+        // Store original return address in TLS
+        masm.str(64, lr, masm.makeAddress(thread, config.threadExceptionPcOffset, 8));
+
+        AArch64Call.directJmp(crb, masm, crb.foreignCalls.lookupForeignCall(DEOPT_BLOB_UNPACK_WITH_EXCEPTION_IN_TLS));
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotEpilogueOp.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotEpilogueOp.java	Thu Jan 23 08:43:22 2020 -0800
@@ -53,8 +53,8 @@
  */
 abstract class AArch64HotSpotEpilogueOp extends AArch64BlockEndOp {
 
-    private final GraalHotSpotVMConfig config;
-    private final Register thread;
+    protected final GraalHotSpotVMConfig config;
+    protected final Register thread;
 
     protected AArch64HotSpotEpilogueOp(LIRInstructionClass<? extends AArch64HotSpotEpilogueOp> c, GraalHotSpotVMConfig config, Register thread) {
         super(c);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java	Thu Jan 23 08:43:22 2020 -0800
@@ -400,6 +400,12 @@
     }
 
     @Override
+    public void emitDeoptimizeWithExceptionInCaller(Value exception) {
+        Register thread = getProviders().getRegisters().getThreadRegister();
+        append(new AArch64HotSpotDeoptimizeWithExceptionCallerOp(config, exception, thread));
+    }
+
+    @Override
     public void emitDeoptimize(Value actionAndReason, Value failedSpeculation, LIRFrameState state) {
         moveDeoptValuesToThread(actionAndReason, failedSpeculation);
         append(new AArch64HotSpotDeoptimizeOp(state));
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64DeoptimizeOp.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64DeoptimizeOp.java	Thu Jan 23 08:43:22 2020 -0800
@@ -24,7 +24,7 @@
 
 package org.graalvm.compiler.hotspot.amd64;
 
-import static org.graalvm.compiler.hotspot.HotSpotHostBackend.UNCOMMON_TRAP_HANDLER;
+import static org.graalvm.compiler.hotspot.HotSpotHostBackend.DEOPT_BLOB_UNCOMMON_TRAP;
 
 import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
 import org.graalvm.compiler.lir.LIRFrameState;
@@ -48,6 +48,6 @@
 
     @Override
     public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
-        AMD64Call.directCall(crb, masm, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP_HANDLER), null, false, info);
+        AMD64Call.directCall(crb, masm, crb.foreignCalls.lookupForeignCall(DEOPT_BLOB_UNCOMMON_TRAP), null, false, info);
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java	Thu Jan 23 08:43:22 2020 -0800
@@ -328,7 +328,7 @@
             crb.recordMark(config.MARKID_EXCEPTION_HANDLER_ENTRY);
             AMD64Call.directCall(crb, asm, foreignCalls.lookupForeignCall(EXCEPTION_HANDLER), null, false, null);
             crb.recordMark(config.MARKID_DEOPT_HANDLER_ENTRY);
-            AMD64Call.directCall(crb, asm, foreignCalls.lookupForeignCall(DEOPTIMIZATION_HANDLER), null, false, null);
+            AMD64Call.directCall(crb, asm, foreignCalls.lookupForeignCall(DEOPT_BLOB_UNPACK), null, false, null);
         } else {
             // No need to emit the stubs for entries back into the method since
             // it has no calls that can cause such "return" entries
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java	Thu Jan 23 08:43:22 2020 -0800
@@ -24,7 +24,7 @@
 
 package org.graalvm.compiler.hotspot.amd64;
 
-import static org.graalvm.compiler.hotspot.HotSpotHostBackend.UNCOMMON_TRAP_HANDLER;
+import static org.graalvm.compiler.hotspot.HotSpotHostBackend.DEOPT_BLOB_UNCOMMON_TRAP;
 
 import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
 import org.graalvm.compiler.lir.LIRInstructionClass;
@@ -47,6 +47,6 @@
     @Override
     public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
         leaveFrameAndRestoreRbp(crb, masm);
-        AMD64Call.directJmp(crb, masm, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP_HANDLER));
+        AMD64Call.directJmp(crb, masm, crb.foreignCalls.lookupForeignCall(DEOPT_BLOB_UNCOMMON_TRAP));
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotDeoptimizeWithExceptionCallerOp.java	Thu Jan 23 08:43:22 2020 -0800
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2012, 2018, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 org.graalvm.compiler.hotspot.amd64;
+
+import static jdk.vm.ci.code.ValueUtil.asRegister;
+import static org.graalvm.compiler.hotspot.HotSpotHostBackend.DEOPT_BLOB_UNPACK_WITH_EXCEPTION_IN_TLS;
+
+import org.graalvm.compiler.asm.amd64.AMD64Address;
+import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
+import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
+import org.graalvm.compiler.lir.LIRInstructionClass;
+import org.graalvm.compiler.lir.Opcode;
+import org.graalvm.compiler.lir.amd64.AMD64Call;
+import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
+
+import jdk.vm.ci.amd64.AMD64;
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.meta.Value;
+
+/**
+ * Removes the current frame and tail calls the uncommon trap routine.
+ */
+@Opcode("DEOPT_WITH_EXCEPTION_IN_CALLER")
+final class AMD64HotSpotDeoptimizeWithExceptionCallerOp extends AMD64HotSpotEpilogueBlockEndOp {
+
+    public static final LIRInstructionClass<AMD64HotSpotDeoptimizeWithExceptionCallerOp> TYPE = LIRInstructionClass.create(AMD64HotSpotDeoptimizeWithExceptionCallerOp.class);
+    private final GraalHotSpotVMConfig config;
+    @Use(OperandFlag.REG) private Value exception;
+
+    protected AMD64HotSpotDeoptimizeWithExceptionCallerOp(GraalHotSpotVMConfig config, Value exception) {
+        super(TYPE);
+        this.config = config;
+        this.exception = exception;
+    }
+
+    @Override
+    public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+        Register stackPointer = crb.frameMap.getRegisterConfig().getFrameRegister();
+        Register exc = asRegister(exception);
+
+        leaveFrameAndRestoreRbp(crb, masm);
+
+        // Save exception oop in TLS
+        masm.movq(new AMD64Address(AMD64.r15, config.threadExceptionOopOffset), exc);
+        // Get return address and store it into TLS
+        masm.movq(exc, new AMD64Address(stackPointer, 0));
+        masm.movq(new AMD64Address(AMD64.r15, config.threadExceptionPcOffset), exc);
+
+        // Remove return address.
+        masm.addq(stackPointer, crb.target.arch.getReturnAddressSize());
+        AMD64Call.directJmp(crb, masm, crb.foreignCalls.lookupForeignCall(DEOPT_BLOB_UNPACK_WITH_EXCEPTION_IN_TLS));
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Thu Jan 23 08:43:22 2020 -0800
@@ -545,6 +545,11 @@
     }
 
     @Override
+    public void emitDeoptimizeWithExceptionInCaller(Value exception) {
+        append(new AMD64HotSpotDeoptimizeWithExceptionCallerOp(config, exception));
+    }
+
+    @Override
     public void beforeRegisterAllocation() {
         super.beforeRegisterAllocation();
         boolean hasDebugInfo = getResult().getLIR().hasDebugInfo();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCDeoptimizeOp.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCDeoptimizeOp.java	Thu Jan 23 08:43:22 2020 -0800
@@ -24,7 +24,7 @@
 
 package org.graalvm.compiler.hotspot.sparc;
 
-import static org.graalvm.compiler.hotspot.HotSpotHostBackend.UNCOMMON_TRAP_HANDLER;
+import static org.graalvm.compiler.hotspot.HotSpotHostBackend.DEOPT_BLOB_UNCOMMON_TRAP;
 
 import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler;
 import org.graalvm.compiler.core.common.LIRKind;
@@ -62,6 +62,6 @@
         // [Deopt Handler Code]
         // 0xffffffff749bb60c: call 0xffffffff748da540 ; {runtime_call}
         // 0xffffffff749bb610: nop
-        SPARCCall.directCall(crb, masm, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP_HANDLER), null, info);
+        SPARCCall.directCall(crb, masm, crb.foreignCalls.lookupForeignCall(DEOPT_BLOB_UNCOMMON_TRAP), null, info);
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java	Thu Jan 23 08:43:22 2020 -0800
@@ -349,7 +349,7 @@
             crb.recordMark(config.MARKID_EXCEPTION_HANDLER_ENTRY);
             SPARCCall.directCall(crb, masm, foreignCalls.lookupForeignCall(EXCEPTION_HANDLER), null, null);
             crb.recordMark(config.MARKID_DEOPT_HANDLER_ENTRY);
-            SPARCCall.directCall(crb, masm, foreignCalls.lookupForeignCall(DEOPTIMIZATION_HANDLER), null, null);
+            SPARCCall.directCall(crb, masm, foreignCalls.lookupForeignCall(DEOPT_BLOB_UNPACK), null, null);
         } else {
             // No need to emit the stubs for entries back into the method since
             // it has no calls that can cause such "return" entries
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java	Thu Jan 23 08:43:22 2020 -0800
@@ -24,7 +24,7 @@
 
 package org.graalvm.compiler.hotspot.sparc;
 
-import static org.graalvm.compiler.hotspot.HotSpotHostBackend.UNCOMMON_TRAP_HANDLER;
+import static org.graalvm.compiler.hotspot.HotSpotHostBackend.DEOPT_BLOB_UNCOMMON_TRAP;
 
 import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler;
 import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler.ScratchRegister;
@@ -59,7 +59,7 @@
 
         try (ScratchRegister sc = masm.getScratchRegister()) {
             Register scratch = sc.getRegister();
-            SPARCCall.indirectJmp(crb, masm, scratch, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP_HANDLER));
+            SPARCCall.indirectJmp(crb, masm, scratch, crb.foreignCalls.lookupForeignCall(DEOPT_BLOB_UNCOMMON_TRAP));
         }
 
         // frameContext.leave(crb);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotDeoptimizeWithExceptionCallerOp.java	Thu Jan 23 08:43:22 2020 -0800
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2020, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 org.graalvm.compiler.hotspot.sparc;
+
+import static jdk.vm.ci.code.ValueUtil.asRegister;
+import static org.graalvm.compiler.hotspot.HotSpotHostBackend.DEOPT_BLOB_UNPACK_WITH_EXCEPTION_IN_TLS;
+
+import org.graalvm.compiler.asm.sparc.SPARCAddress;
+import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler;
+import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
+import org.graalvm.compiler.lir.LIRInstructionClass;
+import org.graalvm.compiler.lir.Opcode;
+import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
+import org.graalvm.compiler.lir.sparc.SPARCCall;
+
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.meta.Value;
+import jdk.vm.ci.sparc.SPARC;
+
+/**
+ * Removes the current frame and tail calls the uncommon trap routine.
+ */
+@Opcode("DEOPT_WITH_EXCEPTION_IN_CALLER")
+final class SPARCHotSpotDeoptimizeWithExceptionCallerOp extends SPARCHotSpotEpilogueOp {
+    public static final LIRInstructionClass<SPARCHotSpotDeoptimizeWithExceptionCallerOp> TYPE = LIRInstructionClass.create(SPARCHotSpotDeoptimizeWithExceptionCallerOp.class);
+    public static final SizeEstimate SIZE = SizeEstimate.create(32);
+
+    private final GraalHotSpotVMConfig config;
+    private final Register thread;
+    @Use(OperandFlag.REG) private Value exception;
+
+    protected SPARCHotSpotDeoptimizeWithExceptionCallerOp(GraalHotSpotVMConfig config, Value exception, Register thread) {
+        super(TYPE, SIZE);
+        this.config = config;
+        this.exception = exception;
+        this.thread = thread;
+    }
+
+    @Override
+    public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+        Register exc = asRegister(exception);
+
+        // Save exception oop in TLS
+        masm.stx(exc, new SPARCAddress(thread, config.threadExceptionOopOffset));
+        // Store original return address in TLS
+        masm.stx(SPARC.i7, new SPARCAddress(thread, config.threadExceptionPcOffset));
+
+        leaveFrame(crb);
+
+        try (SPARCMacroAssembler.ScratchRegister sc = masm.getScratchRegister()) {
+            Register scratch = sc.getRegister();
+            SPARCCall.indirectJmp(crb, masm, scratch, crb.foreignCalls.lookupForeignCall(DEOPT_BLOB_UNPACK_WITH_EXCEPTION_IN_TLS));
+        }
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Thu Jan 23 08:43:22 2020 -0800
@@ -239,6 +239,12 @@
     }
 
     @Override
+    public void emitDeoptimizeWithExceptionInCaller(Value exception) {
+        Register thread = getProviders().getRegisters().getThreadRegister();
+        append(new SPARCHotSpotDeoptimizeWithExceptionCallerOp(config, exception, thread));
+    }
+
+    @Override
     public Variable emitLogicCompareAndSwap(LIRKind accessKind, Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) {
         ValueKind<?> kind = newValue.getValueKind();
         assert kind.equals(expectedValue.getValueKind());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotDeoptExplicitExceptions.java	Thu Jan 23 08:43:22 2020 -0800
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2019, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 org.graalvm.compiler.hotspot.test;
+
+import static org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.BytecodeExceptionMode.CheckAll;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.graalvm.compiler.core.test.SubprocessTest;
+import org.graalvm.compiler.hotspot.HotSpotBackend;
+import org.graalvm.compiler.hotspot.stubs.CreateExceptionStub;
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
+import org.junit.Assume;
+import org.junit.Test;
+
+/**
+ * This test exercises the deoptimization in the BytecodeExceptioNode foreign call path.
+ */
+public class HotSpotDeoptExplicitExceptions extends SubprocessTest {
+
+    @Override
+    protected GraphBuilderConfiguration editGraphBuilderConfiguration(GraphBuilderConfiguration conf) {
+        return super.editGraphBuilderConfiguration(conf).withBytecodeExceptionMode(CheckAll);
+    }
+
+    static String nullCheckSnippet(Object o) {
+        return o.toString();
+    }
+
+    static int divByZeroSnippet(int x, int y) {
+        return x / y;
+    }
+
+    static String classCastSnippet(Object o) {
+        return (String) o;
+    }
+
+    void testBody() {
+        test("nullCheckSnippet", (Object) null);
+        test("divByZeroSnippet", 1, 0);
+        test("classCastSnippet", Boolean.TRUE);
+    }
+
+    @Override
+    public void configSubprocess(List<String> vmArgs) {
+        vmArgs.add("-Dgraal.HotSpotDeoptExplicitExceptions=true");
+    }
+
+    @Test
+    public void explicitExceptions() throws IOException, InterruptedException {
+        Assume.assumeTrue("required entry point is missing", ((HotSpotBackend) getBackend()).getRuntime().getVMConfig().deoptBlobUnpackWithExceptionInTLS != 0);
+        if (!CreateExceptionStub.Options.HotSpotDeoptExplicitExceptions.getValue(getInitialOptions())) {
+            launchSubprocess(this::testBody);
+        } else {
+            testBody();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotDeoptPostExceptions.java	Thu Jan 23 08:43:22 2020 -0800
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2019, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 org.graalvm.compiler.hotspot.test;
+
+import static org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.BytecodeExceptionMode.CheckAll;
+
+import org.graalvm.compiler.core.phases.HighTier;
+import org.graalvm.compiler.core.test.GraalCompilerTest;
+import org.graalvm.compiler.hotspot.meta.HotSpotNodePlugin;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
+import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin;
+import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.phases.tiers.Suites;
+import org.junit.Test;
+
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+/**
+ * This test exercises the FrameState used for deoptimization in the JVMTI post_on_exceptions path.
+ */
+public class HotSpotDeoptPostExceptions extends GraalCompilerTest {
+
+    @Override
+    @SuppressWarnings("try")
+    protected Suites createSuites(OptionValues options) {
+        return super.createSuites(new OptionValues(options, HighTier.Options.Inline, false));
+    }
+
+    @Override
+    protected InlineInvokePlugin.InlineInfo bytecodeParserShouldInlineInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) {
+        return InlineInvokePlugin.InlineInfo.DO_NOT_INLINE_NO_EXCEPTION;
+    }
+
+    @Override
+    protected GraphBuilderConfiguration editGraphBuilderConfiguration(GraphBuilderConfiguration conf) {
+        return super.editGraphBuilderConfiguration(conf).withBytecodeExceptionMode(CheckAll);
+    }
+
+    static String snippet(Object o) {
+        return o.toString();
+    }
+
+    @Test
+    public void testPost() {
+        OptionValues options = new OptionValues(getInitialOptions(), HotSpotNodePlugin.Options.HotSpotPostOnExceptions, true);
+        test(options, "snippet", (Object) null);
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java	Thu Jan 23 08:43:22 2020 -0800
@@ -620,8 +620,9 @@
     public final long inlineCacheMissStub = getFieldValue("CompilerToVM::Data::SharedRuntime_ic_miss_stub", Long.class, "address");
     public final long handleWrongMethodStub = getFieldValue("CompilerToVM::Data::SharedRuntime_handle_wrong_method_stub", Long.class, "address");
 
-    public final long handleDeoptStub = getFieldValue("CompilerToVM::Data::SharedRuntime_deopt_blob_unpack", Long.class, "address");
-    public final long uncommonTrapStub = getFieldValue("CompilerToVM::Data::SharedRuntime_deopt_blob_uncommon_trap", Long.class, "address");
+    public final long deoptBlobUnpack = getFieldValue("CompilerToVM::Data::SharedRuntime_deopt_blob_unpack", Long.class, "address");
+    public final long deoptBlobUnpackWithExceptionInTLS = getFieldValue("CompilerToVM::Data::SharedRuntime_deopt_blob_unpack_with_exception_in_tls", Long.class, "address", 0L);
+    public final long deoptBlobUncommonTrap = getFieldValue("CompilerToVM::Data::SharedRuntime_deopt_blob_uncommon_trap", Long.class, "address");
 
     public final long codeCacheLowBound = versioned.codeCacheLowBound;
     public final long codeCacheHighBound = versioned.codeCacheHighBound;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotDebugInfoBuilder.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotDebugInfoBuilder.java	Thu Jan 23 08:43:22 2020 -0800
@@ -31,13 +31,19 @@
 
 import org.graalvm.compiler.api.replacements.MethodSubstitution;
 import org.graalvm.compiler.api.replacements.Snippet;
+import org.graalvm.compiler.bytecode.Bytecodes;
+import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
 import org.graalvm.compiler.core.gen.DebugInfoBuilder;
 import org.graalvm.compiler.graph.GraalGraphError;
 import org.graalvm.compiler.graph.NodeSourcePosition;
+import org.graalvm.compiler.hotspot.meta.DefaultHotSpotLoweringProvider;
 import org.graalvm.compiler.lir.VirtualStackSlot;
 import org.graalvm.compiler.nodes.FrameState;
+import org.graalvm.compiler.nodes.FullInfopointNode;
 import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.extended.ForeignCallNode;
 import org.graalvm.compiler.nodes.spi.NodeValueMap;
+import org.graalvm.compiler.nodes.spi.NodeWithState;
 
 import jdk.vm.ci.code.BytecodeFrame;
 import jdk.vm.ci.code.StackLockValue;
@@ -87,11 +93,42 @@
     }
 
     @Override
-    protected BytecodeFrame computeFrameForState(FrameState state) {
+    protected boolean verifyFrameState(NodeWithState node, FrameState topState) {
+        if (node instanceof FullInfopointNode) {
+            return true;
+        }
+        if (node instanceof ForeignCallNode) {
+            ForeignCallNode call = (ForeignCallNode) node;
+            ForeignCallDescriptor descriptor = call.getDescriptor();
+            if (DefaultHotSpotLoweringProvider.RuntimeCalls.runtimeCalls.containsValue(descriptor)) {
+                return true;
+            }
+        }
+        // There are many properties of FrameStates which could be validated though it's complicated
+        // by some of the idiomatic ways that they are used. This check specifically tries to catch
+        // cases where a FrameState that's constructed for reexecution has an incorrect stack depth
+        // at invokes.
+        if (topState.bci >= 0 && !topState.duringCall() && !topState.rethrowException()) {
+            ResolvedJavaMethod m = topState.getMethod();
+            int opcode = m.getCode()[topState.bci] & 0xff;
+            if (opcode == Bytecodes.INVOKEVIRTUAL || opcode == Bytecodes.INVOKEINTERFACE) {
+                assert topState.stackSize() > 0 : "expected non-empty stack: " + topState;
+            } else {
+                int stackEffect = Bytecodes.stackEffectOf(opcode);
+                if (stackEffect < 0) {
+                    assert topState.stackSize() >= -stackEffect : "expected at least " + (-stackEffect) + " stack depth : " + topState;
+                }
+            }
+        }
+        return true;
+    }
+
+    @Override
+    protected BytecodeFrame computeFrameForState(NodeWithState node, FrameState state) {
         if (isPlaceholderBci(state.bci) && state.bci != BytecodeFrame.BEFORE_BCI) {
             raiseInvalidFrameStateError(state);
         }
-        BytecodeFrame result = super.computeFrameForState(state);
+        BytecodeFrame result = super.computeFrameForState(node, state);
         maxInterpreterFrameSize = Math.max(maxInterpreterFrameSize, codeCacheProvider.interpreterFrameSize(result));
         return result;
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotHostBackend.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotHostBackend.java	Thu Jan 23 08:43:22 2020 -0800
@@ -67,12 +67,17 @@
     /**
      * Descriptor for {@code SharedRuntime::deopt_blob()->unpack()}.
      */
-    public static final ForeignCallDescriptor DEOPTIMIZATION_HANDLER = new ForeignCallDescriptor("deoptHandler", void.class);
+    public static final ForeignCallDescriptor DEOPT_BLOB_UNPACK = new ForeignCallDescriptor("deopt_blob()->unpack()", void.class);
+
+    /**
+     * Descriptor for {@code SharedRuntime::deopt_blob()->unpack_with_exception_in_tls()}.
+     */
+    public static final ForeignCallDescriptor DEOPT_BLOB_UNPACK_WITH_EXCEPTION_IN_TLS = new ForeignCallDescriptor("deopt_blob()->unpack_with_exception_in_tls()", void.class);
 
     /**
      * Descriptor for {@code SharedRuntime::deopt_blob()->uncommon_trap()}.
      */
-    public static final ForeignCallDescriptor UNCOMMON_TRAP_HANDLER = new ForeignCallDescriptor("uncommonTrapHandler", void.class);
+    public static final ForeignCallDescriptor DEOPT_BLOB_UNCOMMON_TRAP = new ForeignCallDescriptor("deopt_blob()->uncommon_trap()", void.class);
 
     public static final ForeignCallDescriptor ENABLE_STACK_RESERVED_ZONE = new ForeignCallDescriptor("enableStackReservedZoneEntry", void.class, Word.class);
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerator.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerator.java	Thu Jan 23 08:43:22 2020 -0800
@@ -61,9 +61,21 @@
      */
     void emitTailcall(Value[] args, Value address);
 
+    /**
+     * Emits code that jumps to the deopt blob uncommon_trap entry point with {@code action} and
+     * {@code reason}.
+     */
     void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason);
 
     /**
+     * Emits code that jumps to the deopt blob unpack_with_exception entry point with
+     * {@code exception}.
+     *
+     * @param exception
+     */
+    void emitDeoptimizeWithExceptionInCaller(Value exception);
+
+    /**
      * Emits code for a {@link LoadConstantIndirectlyNode}.
      *
      * @param constant
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java	Thu Jan 23 08:43:22 2020 -0800
@@ -722,7 +722,13 @@
 
         StructuredGraph graph = node.graph();
         ForeignCallNode foreignCallNode = graph.add(new ForeignCallNode(foreignCalls, descriptor, node.stamp(NodeView.DEFAULT), node.getArguments()));
-        foreignCallNode.setStateAfter(node.stateAfter());
+        /*
+         * The original BytecodeExceptionNode has a rethrowException FrameState which isn't suitable
+         * for deopt because the exception to be thrown come from this call so it's not available in
+         * the debug info. The foreign call needs a stateDuring instead so it can deopt with a
+         * pending exception.
+         */
+        foreignCallNode.setStateAfter(node.createStateDuring());
         graph.replaceFixedWithFixed(node, foreignCallNode);
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java	Thu Jan 23 08:43:22 2020 -0800
@@ -74,10 +74,11 @@
 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NO_VZERO;
 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.SAFEPOINT;
 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.STACK_INSPECTABLE_LEAF;
-import static org.graalvm.compiler.hotspot.HotSpotHostBackend.DEOPTIMIZATION_HANDLER;
+import static org.graalvm.compiler.hotspot.HotSpotHostBackend.DEOPT_BLOB_UNCOMMON_TRAP;
+import static org.graalvm.compiler.hotspot.HotSpotHostBackend.DEOPT_BLOB_UNPACK;
+import static org.graalvm.compiler.hotspot.HotSpotHostBackend.DEOPT_BLOB_UNPACK_WITH_EXCEPTION_IN_TLS;
 import static org.graalvm.compiler.hotspot.HotSpotHostBackend.ENABLE_STACK_RESERVED_ZONE;
 import static org.graalvm.compiler.hotspot.HotSpotHostBackend.THROW_DELAYED_STACKOVERFLOW_ERROR;
-import static org.graalvm.compiler.hotspot.HotSpotHostBackend.UNCOMMON_TRAP_HANDLER;
 import static org.graalvm.compiler.hotspot.replacements.AssertionSnippets.ASSERTION_VM_MESSAGE_C;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotG1WriteBarrierSnippets.G1WBPOSTCALL;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotG1WriteBarrierSnippets.G1WBPRECALL;
@@ -270,8 +271,11 @@
 
     public void initialize(HotSpotProviders providers, OptionValues options) {
         GraalHotSpotVMConfig c = runtime.getVMConfig();
-        registerForeignCall(DEOPTIMIZATION_HANDLER, c.handleDeoptStub, NativeCall, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS);
-        registerForeignCall(UNCOMMON_TRAP_HANDLER, c.uncommonTrapStub, NativeCall, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS);
+        registerForeignCall(DEOPT_BLOB_UNPACK, c.deoptBlobUnpack, NativeCall, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS);
+        if (c.deoptBlobUnpackWithExceptionInTLS != 0) {
+            registerForeignCall(DEOPT_BLOB_UNPACK_WITH_EXCEPTION_IN_TLS, c.deoptBlobUnpackWithExceptionInTLS, NativeCall, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS);
+        }
+        registerForeignCall(DEOPT_BLOB_UNCOMMON_TRAP, c.deoptBlobUncommonTrap, NativeCall, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS);
         registerForeignCall(IC_MISS_HANDLER, c.inlineCacheMissStub, NativeCall, LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS);
 
         if (c.enableStackReservedZoneAddress != 0) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java	Thu Jan 23 08:43:22 2020 -0800
@@ -27,6 +27,9 @@
 import static jdk.vm.ci.meta.DeoptimizationAction.None;
 import static jdk.vm.ci.meta.DeoptimizationReason.TransferToInterpreter;
 import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode;
+import static org.graalvm.compiler.hotspot.meta.HotSpotNodePlugin.Options.HotSpotPostOnExceptions;
+
+import java.util.function.Supplier;
 
 import org.graalvm.compiler.core.common.CompilationIdentifier;
 import org.graalvm.compiler.core.common.type.StampFactory;
@@ -38,6 +41,7 @@
 import org.graalvm.compiler.nodes.ConstantNode;
 import org.graalvm.compiler.nodes.FixedGuardNode;
 import org.graalvm.compiler.nodes.FixedWithNextNode;
+import org.graalvm.compiler.nodes.FrameState;
 import org.graalvm.compiler.nodes.LogicNode;
 import org.graalvm.compiler.nodes.NamedLocationIdentity;
 import org.graalvm.compiler.nodes.StructuredGraph;
@@ -54,6 +58,9 @@
 import org.graalvm.compiler.nodes.memory.address.AddressNode;
 import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode;
 import org.graalvm.compiler.nodes.util.ConstantFoldUtil;
+import org.graalvm.compiler.options.Option;
+import org.graalvm.compiler.options.OptionKey;
+import org.graalvm.compiler.options.OptionType;
 import org.graalvm.compiler.serviceprovider.GraalUnsafeAccess;
 import org.graalvm.compiler.word.Word;
 import org.graalvm.compiler.word.WordOperationPlugin;
@@ -82,6 +89,11 @@
  * </ul>
  */
 public final class HotSpotNodePlugin implements NodePlugin, TypePlugin {
+    public static class Options {
+        @Option(help = "Testing only option that forces deopts for exception throws", type = OptionType.Expert)//
+        public static final OptionKey<Boolean> HotSpotPostOnExceptions = new OptionKey<>(false);
+    }
+
     private static final Unsafe UNSAFE = GraalUnsafeAccess.getUnsafe();
     protected final WordOperationPlugin wordOperationPlugin;
     private final GraalHotSpotVMConfig config;
@@ -209,35 +221,39 @@
     }
 
     @Override
-    public FixedWithNextNode instrumentExceptionDispatch(StructuredGraph graph, FixedWithNextNode afterExceptionLoaded) {
+    public FixedWithNextNode instrumentExceptionDispatch(StructuredGraph graph, FixedWithNextNode afterExceptionLoaded, Supplier<FrameState> frameStateFunction) {
         CompilationIdentifier id = graph.compilationId();
-        if (id instanceof HotSpotCompilationIdentifier) {
+        if (id instanceof HotSpotCompilationIdentifier &&
+                        config.jvmciCompileStateCanPostOnExceptionsOffset != Integer.MIN_VALUE &&
+                        config.javaThreadShouldPostOnExceptionsFlagOffset != Integer.MIN_VALUE) {
+            boolean canPostOnExceptions = HotSpotPostOnExceptions.getValue(graph.getOptions());
             HotSpotCompilationRequest request = ((HotSpotCompilationIdentifier) id).getRequest();
             if (request != null) {
                 long compileState = request.getJvmciEnv();
-                if (compileState != 0 &&
-                                config.jvmciCompileStateCanPostOnExceptionsOffset != Integer.MIN_VALUE &&
-                                config.javaThreadShouldPostOnExceptionsFlagOffset != Integer.MIN_VALUE) {
+                if (compileState != 0) {
                     long canPostOnExceptionsOffset = compileState + config.jvmciCompileStateCanPostOnExceptionsOffset;
-                    boolean canPostOnExceptions = UNSAFE.getByte(canPostOnExceptionsOffset) != 0;
-                    if (canPostOnExceptions) {
-                        // If the exception capability is set, then generate code
-                        // to check the JavaThread.should_post_on_exceptions flag to see
-                        // if we actually need to report exception events for the current
-                        // thread. If not, take the fast path otherwise deoptimize.
-                        CurrentJavaThreadNode thread = graph.unique(new CurrentJavaThreadNode(wordTypes.getWordKind()));
-                        ValueNode offset = graph.unique(ConstantNode.forLong(config.javaThreadShouldPostOnExceptionsFlagOffset));
-                        AddressNode address = graph.unique(new OffsetAddressNode(thread, offset));
-                        ReadNode shouldPostException = graph.add(new ReadNode(address, JAVA_THREAD_SHOULD_POST_ON_EXCEPTIONS_FLAG_LOCATION, StampFactory.intValue(), BarrierType.NONE));
-                        afterExceptionLoaded.setNext(shouldPostException);
-                        ValueNode zero = graph.unique(ConstantNode.forInt(0));
-                        LogicNode cond = graph.unique(new IntegerEqualsNode(shouldPostException, zero));
-                        FixedGuardNode check = graph.add(new FixedGuardNode(cond, TransferToInterpreter, None, false));
-                        shouldPostException.setNext(check);
-                        return check;
-                    }
+                    canPostOnExceptions = UNSAFE.getByte(canPostOnExceptionsOffset) != 0;
                 }
             }
+            if (canPostOnExceptions) {
+                // If the exception capability is set, then generate code
+                // to check the JavaThread.should_post_on_exceptions flag to see
+                // if we actually need to report exception events for the current
+                // thread. If not, take the fast path otherwise deoptimize.
+                CurrentJavaThreadNode thread = graph.unique(new CurrentJavaThreadNode(wordTypes.getWordKind()));
+                ValueNode offset = graph.unique(ConstantNode.forLong(config.javaThreadShouldPostOnExceptionsFlagOffset));
+                AddressNode address = graph.unique(new OffsetAddressNode(thread, offset));
+                ReadNode shouldPostException = graph.add(new ReadNode(address, JAVA_THREAD_SHOULD_POST_ON_EXCEPTIONS_FLAG_LOCATION, StampFactory.intValue(), BarrierType.NONE));
+                afterExceptionLoaded.setNext(shouldPostException);
+                ValueNode zero = graph.unique(ConstantNode.forInt(0));
+                LogicNode cond = graph.unique(new IntegerEqualsNode(shouldPostException, zero));
+                FixedGuardNode check = graph.add(new FixedGuardNode(cond, TransferToInterpreter, None, false));
+                FrameState fs = frameStateFunction.get();
+                assert fs.stackSize() == 1 && fs.rethrowException() : "expected rethrow exception FrameState";
+                check.setStateBefore(fs);
+                shouldPostException.setNext(check);
+                return check;
+            }
         }
         return afterExceptionLoaded;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DeoptimizeWithExceptionInCallerNode.java	Thu Jan 23 08:43:22 2020 -0800
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2009, 2018, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 org.graalvm.compiler.hotspot.nodes;
+
+import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8;
+import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_8;
+
+import org.graalvm.compiler.core.common.type.StampFactory;
+import org.graalvm.compiler.graph.NodeClass;
+import org.graalvm.compiler.hotspot.HotSpotLIRGenerator;
+import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.nodes.ControlSinkNode;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.spi.LIRLowerable;
+import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
+
+import jdk.vm.ci.meta.Value;
+
+/**
+ * Removes the current frame and tail calls the uncommon trap routine.
+ */
+@NodeInfo(cycles = CYCLES_8, size = SIZE_8)
+public final class DeoptimizeWithExceptionInCallerNode extends ControlSinkNode implements LIRLowerable {
+    public static final NodeClass<DeoptimizeWithExceptionInCallerNode> TYPE = NodeClass.create(DeoptimizeWithExceptionInCallerNode.class);
+
+    @Input protected ValueNode exception;
+
+    public DeoptimizeWithExceptionInCallerNode(ValueNode exception) {
+        super(TYPE, StampFactory.forVoid());
+        this.exception = exception;
+    }
+
+    @Override
+    public void generate(NodeLIRBuilderTool gen) {
+        Value e = gen.operand(exception);
+        ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitDeoptimizeWithExceptionInCaller(e);
+    }
+
+    @NodeIntrinsic
+    public static native void deopt(Object exception);
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/FastNotifyNode.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/FastNotifyNode.java	Thu Jan 23 08:43:22 2020 -0800
@@ -24,6 +24,7 @@
 
 package org.graalvm.compiler.hotspot.replacements;
 
+import static org.graalvm.compiler.nodeinfo.InputType.Memory;
 import static org.graalvm.compiler.nodeinfo.InputType.State;
 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2;
 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0;
@@ -40,7 +41,7 @@
 import org.graalvm.compiler.nodes.spi.LoweringTool;
 import jdk.internal.vm.compiler.word.LocationIdentity;
 
-@NodeInfo(cycles = CYCLES_2, size = SIZE_0)
+@NodeInfo(cycles = CYCLES_2, size = SIZE_0, allowedUsageTypes = Memory)
 public class FastNotifyNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single, DeoptimizingNode.DeoptDuring {
 
     public static final NodeClass<FastNotifyNode> TYPE = NodeClass.create(FastNotifyNode.class);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/CreateExceptionStub.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/CreateExceptionStub.java	Thu Jan 23 08:43:22 2020 -0800
@@ -25,6 +25,7 @@
 package org.graalvm.compiler.hotspot.stubs;
 
 import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall;
+import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_OPTIONVALUES;
 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Reexecutability.REEXECUTABLE;
 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.SAFEPOINT;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.clearPendingException;
@@ -36,11 +37,16 @@
 import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
 import org.graalvm.compiler.graph.Node.NodeIntrinsic;
 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
+import org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase;
 import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
 import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl;
 import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
+import org.graalvm.compiler.hotspot.nodes.DeoptimizeWithExceptionInCallerNode;
 import org.graalvm.compiler.hotspot.nodes.StubForeignCallNode;
 import org.graalvm.compiler.hotspot.word.KlassPointer;
+import org.graalvm.compiler.options.Option;
+import org.graalvm.compiler.options.OptionKey;
+import org.graalvm.compiler.options.OptionType;
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.replacements.nodes.CStringConstant;
 import org.graalvm.compiler.word.Word;
@@ -53,11 +59,26 @@
  */
 public class CreateExceptionStub extends SnippetStub {
 
+    public static class Options {
+        @Option(help = "Testing only option that forces deopts for exception throws", type = OptionType.Expert)//
+        public static final OptionKey<Boolean> HotSpotDeoptExplicitExceptions = new OptionKey<>(false);
+    }
+
     protected CreateExceptionStub(String snippetMethodName, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) {
         super(snippetMethodName, options, providers, linkage);
     }
 
     @Fold
+    static boolean reportsDeoptimization(@Fold.InjectedParameter GraalHotSpotVMConfig config) {
+        return config.deoptBlobUnpackWithExceptionInTLS != 0;
+    }
+
+    @Fold
+    static boolean alwayDeoptimize(@Fold.InjectedParameter OptionValues options) {
+        return Options.HotSpotDeoptExplicitExceptions.getValue(options);
+    }
+
+    @Fold
     static String getInternalClassName(Class<?> cls) {
         return cls.getName().replace('.', '/');
     }
@@ -73,36 +94,44 @@
 
     protected static Object createException(Register threadRegister, Class<? extends Throwable> exception, Word message) {
         Word thread = registerAsWord(threadRegister);
-        throwAndPostJvmtiException(THROW_AND_POST_JVMTI_EXCEPTION, thread, classAsCString(exception), message);
-        return clearPendingException(thread);
+        int deoptimized = throwAndPostJvmtiException(THROW_AND_POST_JVMTI_EXCEPTION, thread, classAsCString(exception), message);
+        return handleExceptionReturn(thread, deoptimized);
     }
 
     protected static Object createException(Register threadRegister, Class<? extends Throwable> exception, KlassPointer klass) {
         Word thread = registerAsWord(threadRegister);
-        throwKlassExternalNameException(THROW_KLASS_EXTERNAL_NAME_EXCEPTION, thread, classAsCString(exception), klass);
-        return clearPendingException(thread);
+        int deoptimized = throwKlassExternalNameException(THROW_KLASS_EXTERNAL_NAME_EXCEPTION, thread, classAsCString(exception), klass);
+        return handleExceptionReturn(thread, deoptimized);
     }
 
     protected static Object createException(Register threadRegister, Class<? extends Throwable> exception, KlassPointer objKlass, KlassPointer targetKlass) {
         Word thread = registerAsWord(threadRegister);
-        throwClassCastException(THROW_CLASS_CAST_EXCEPTION, thread, classAsCString(exception), objKlass, targetKlass);
-        return clearPendingException(thread);
+        int deoptimized = throwClassCastException(THROW_CLASS_CAST_EXCEPTION, thread, classAsCString(exception), objKlass, targetKlass);
+        return handleExceptionReturn(thread, deoptimized);
     }
 
-    private static final ForeignCallDescriptor THROW_AND_POST_JVMTI_EXCEPTION = new ForeignCallDescriptor("throw_and_post_jvmti_exception", void.class, Word.class, Word.class, Word.class);
-    private static final ForeignCallDescriptor THROW_KLASS_EXTERNAL_NAME_EXCEPTION = new ForeignCallDescriptor("throw_klass_external_name_exception", void.class, Word.class, Word.class,
+    private static Object handleExceptionReturn(Word thread, int deoptimized) {
+        Object clearPendingException = clearPendingException(thread);
+        if (alwayDeoptimize(INJECTED_OPTIONVALUES) || (reportsDeoptimization(GraalHotSpotVMConfigBase.INJECTED_VMCONFIG) && deoptimized != 0)) {
+            DeoptimizeWithExceptionInCallerNode.deopt(clearPendingException);
+        }
+        return clearPendingException;
+    }
+
+    private static final ForeignCallDescriptor THROW_AND_POST_JVMTI_EXCEPTION = new ForeignCallDescriptor("throw_and_post_jvmti_exception", int.class, Word.class, Word.class, Word.class);
+    private static final ForeignCallDescriptor THROW_KLASS_EXTERNAL_NAME_EXCEPTION = new ForeignCallDescriptor("throw_klass_external_name_exception", int.class, Word.class, Word.class,
                     KlassPointer.class);
-    private static final ForeignCallDescriptor THROW_CLASS_CAST_EXCEPTION = new ForeignCallDescriptor("throw_class_cast_exception", void.class, Word.class, Word.class, KlassPointer.class,
+    private static final ForeignCallDescriptor THROW_CLASS_CAST_EXCEPTION = new ForeignCallDescriptor("throw_class_cast_exception", int.class, Word.class, Word.class, KlassPointer.class,
                     KlassPointer.class);
 
     @NodeIntrinsic(StubForeignCallNode.class)
-    private static native void throwAndPostJvmtiException(@ConstantNodeParameter ForeignCallDescriptor d, Word thread, Word type, Word message);
+    private static native int throwAndPostJvmtiException(@ConstantNodeParameter ForeignCallDescriptor d, Word thread, Word type, Word message);
 
     @NodeIntrinsic(StubForeignCallNode.class)
-    private static native void throwKlassExternalNameException(@ConstantNodeParameter ForeignCallDescriptor d, Word thread, Word type, KlassPointer klass);
+    private static native int throwKlassExternalNameException(@ConstantNodeParameter ForeignCallDescriptor d, Word thread, Word type, KlassPointer klass);
 
     @NodeIntrinsic(StubForeignCallNode.class)
-    private static native void throwClassCastException(@ConstantNodeParameter ForeignCallDescriptor d, Word thread, Word type, KlassPointer objKlass, KlassPointer targetKlass);
+    private static native int throwClassCastException(@ConstantNodeParameter ForeignCallDescriptor d, Word thread, Word type, KlassPointer objKlass, KlassPointer targetKlass);
 
     public static void registerForeignCalls(GraalHotSpotVMConfig c, HotSpotForeignCallsProviderImpl foreignCalls) {
         foreignCalls.registerForeignCall(THROW_AND_POST_JVMTI_EXCEPTION, c.throwAndPostJvmtiExceptionAddress, NativeCall, SAFEPOINT, REEXECUTABLE, any());
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java	Thu Jan 23 08:43:22 2020 -0800
@@ -30,7 +30,7 @@
 import static org.graalvm.compiler.core.common.GraalOptions.RegisterPressure;
 import static org.graalvm.compiler.debug.DebugContext.DEFAULT_LOG_STREAM;
 import static org.graalvm.compiler.debug.DebugOptions.DebugStubsAndSnippets;
-import static org.graalvm.compiler.hotspot.HotSpotHostBackend.UNCOMMON_TRAP_HANDLER;
+import static org.graalvm.compiler.hotspot.HotSpotHostBackend.DEOPT_BLOB_UNCOMMON_TRAP;
 import static org.graalvm.util.CollectionsUtil.allMatch;
 
 import java.util.ListIterator;
@@ -288,7 +288,7 @@
             Call call = (Call) infopoint;
             assert call.target instanceof HotSpotForeignCallLinkage : this + " cannot have non runtime call: " + call.target;
             HotSpotForeignCallLinkage callLinkage = (HotSpotForeignCallLinkage) call.target;
-            assert !callLinkage.isCompiledStub() || callLinkage.getDescriptor().equals(UNCOMMON_TRAP_HANDLER) : this + " cannot call compiled stub " + callLinkage;
+            assert !callLinkage.isCompiledStub() || callLinkage.getDescriptor().equals(DEOPT_BLOB_UNCOMMON_TRAP) : this + " cannot call compiled stub " + callLinkage;
         }
         return true;
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java	Thu Jan 23 08:43:22 2020 -0800
@@ -1321,10 +1321,10 @@
         AbstractBeginNode dispatchBegin;
         if (exceptionObject == null) {
             ExceptionObjectNode newExceptionObject = graph.add(new ExceptionObjectNode(getMetaAccess()));
-            dispatchBegin = newExceptionObject;
-            dispatchState.push(JavaKind.Object, dispatchBegin);
+            dispatchState.push(JavaKind.Object, newExceptionObject);
             dispatchState.setRethrowException(true);
             newExceptionObject.setStateAfter(dispatchState.create(bci, newExceptionObject));
+            dispatchBegin = newExceptionObject;
         } else {
             dispatchBegin = graph.add(new BeginNode());
             dispatchState.push(JavaKind.Object, exceptionObject);
@@ -1346,7 +1346,7 @@
     protected void createHandleExceptionTarget(FixedWithNextNode afterExceptionLoaded, int bci, FrameStateBuilder dispatchState) {
         FixedWithNextNode afterInstrumentation = afterExceptionLoaded;
         for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
-            afterInstrumentation = plugin.instrumentExceptionDispatch(graph, afterInstrumentation);
+            afterInstrumentation = plugin.instrumentExceptionDispatch(graph, afterInstrumentation, () -> dispatchState.create(bci, getNonIntrinsicAncestor(), false, null, null));
             assert afterInstrumentation.next() == null : "exception dispatch instrumentation will be linked to dispatch block";
         }
 
@@ -1611,7 +1611,7 @@
         append(new IfNode(condition, trueSuccessor, falseSuccessor, passingOnTrue ? LUDICROUSLY_FAST_PATH_PROBABILITY : LUDICROUSLY_SLOW_PATH_PROBABILITY));
         lastInstr = passingSuccessor;
 
-        exception.setStateAfter(createFrameState(bci(), exception));
+        exception.setStateAfter(createBytecodeExceptionFrameState(bci(), exception));
         exception.setNext(handleException(exception, bci(), false));
         EXPLICIT_EXCEPTIONS.increment(debug);
 
@@ -3909,12 +3909,24 @@
     }
 
     private FrameState createFrameState(int bci, StateSplit forStateSplit) {
+        assert !(forStateSplit instanceof BytecodeExceptionNode);
         if (currentBlock != null && bci > currentBlock.endBci) {
             frameState.clearNonLiveLocals(currentBlock, liveness, false);
         }
         return frameState.create(bci, forStateSplit);
     }
 
+    private FrameState createBytecodeExceptionFrameState(int bci, BytecodeExceptionNode bytecodeException) {
+        FrameStateBuilder copy = frameState.copy();
+        copy.clearStack();
+        if (currentBlock != null) {
+            copy.clearNonLiveLocals(currentBlock, liveness, false);
+        }
+        copy.setRethrowException(true);
+        copy.push(JavaKind.Object, bytecodeException);
+        return copy.create(bci, bytecodeException);
+    }
+
     @Override
     public void setStateAfter(StateSplit sideEffect) {
         assert sideEffect.hasSideEffect() || sideEffect instanceof AbstractMergeNode;
@@ -4747,7 +4759,7 @@
     @Override
     public AbstractBeginNode genExplicitExceptionEdge(BytecodeExceptionKind exceptionKind) {
         BytecodeExceptionNode exceptionNode = graph.add(new BytecodeExceptionNode(getMetaAccess(), exceptionKind));
-        exceptionNode.setStateAfter(createFrameState(bci(), exceptionNode));
+        exceptionNode.setStateAfter(createBytecodeExceptionFrameState(bci(), exceptionNode));
         AbstractBeginNode exceptionDispatch = handleException(exceptionNode, bci(), false);
         exceptionNode.setNext(exceptionDispatch);
         return BeginNode.begin(exceptionNode);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FrameState.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FrameState.java	Thu Jan 23 08:43:22 2020 -0800
@@ -351,6 +351,10 @@
         return duplicateModified(graph(), bci, rethrowException, duringCall, popKind, new JavaKind[]{pushedSlotKind}, new ValueNode[]{pushedValue});
     }
 
+    public FrameState duplicateRethrow(ValueNode exceptionObject) {
+        return duplicateModified(graph(), bci, true, duringCall, JavaKind.Void, new JavaKind[]{JavaKind.Object}, new ValueNode[]{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 will be formatted
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BytecodeExceptionNode.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BytecodeExceptionNode.java	Thu Jan 23 08:43:22 2020 -0800
@@ -38,6 +38,7 @@
 import org.graalvm.compiler.graph.spi.CanonicalizerTool;
 import org.graalvm.compiler.nodeinfo.NodeInfo;
 import org.graalvm.compiler.nodeinfo.Verbosity;
+import org.graalvm.compiler.nodes.FrameState;
 import org.graalvm.compiler.nodes.ValueNode;
 import org.graalvm.compiler.nodes.memory.AbstractMemoryCheckpoint;
 import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
@@ -45,6 +46,7 @@
 import org.graalvm.compiler.nodes.spi.LoweringTool;
 import jdk.internal.vm.compiler.word.LocationIdentity;
 
+import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.MetaAccessProvider;
 
 /**
@@ -106,7 +108,7 @@
 
     @Override
     public Node canonical(CanonicalizerTool tool) {
-        if (tool.allUsagesAvailable() && getUsageCount() == 0) {
+        if (tool.allUsagesAvailable() && (hasNoUsages() || (hasExactlyOneUsage() && usages().first() == stateAfter))) {
             return null;
         }
         return this;
@@ -120,4 +122,13 @@
     public NodeInputList<ValueNode> getArguments() {
         return arguments;
     }
+
+    /**
+     * Create a new stateDuring for use by a foreign call.
+     */
+    public FrameState createStateDuring() {
+        return stateAfter.duplicateModified(graph(), stateAfter.bci, /* rethrowException */ false, /* duringCall */ true,
+                        JavaKind.Object, null, null);
+    }
+
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ForeignCallNode.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ForeignCallNode.java	Thu Jan 23 08:43:22 2020 -0800
@@ -218,7 +218,7 @@
                         (currentStateAfter.stackSize() > 1 && currentStateAfter.stackAt(currentStateAfter.stackSize() - 2) == this)) {
             // The result of this call is on the top of stack, so roll back to the previous bci.
             assert bci != BytecodeFrame.UNKNOWN_BCI : this;
-            newStateDuring = currentStateAfter.duplicateModifiedDuringCall(bci, this.getStackKind());
+            newStateDuring = currentStateAfter.duplicateModified(currentStateAfter.graph(), bci, false, true, this.getStackKind(), null, null);
         } else {
             newStateDuring = currentStateAfter;
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/NodePlugin.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/NodePlugin.java	Thu Jan 23 08:43:22 2020 -0800
@@ -24,8 +24,11 @@
 
 package org.graalvm.compiler.nodes.graphbuilderconf;
 
+import java.util.function.Supplier;
+
 import org.graalvm.compiler.graph.Node.ValueNumberable;
 import org.graalvm.compiler.nodes.FixedWithNextNode;
+import org.graalvm.compiler.nodes.FrameState;
 import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.nodes.ValueNode;
 import org.graalvm.compiler.nodes.extended.GuardingNode;
@@ -226,9 +229,10 @@
      *
      * @param graph the graph being parsed
      * @param afterExceptionLoaded the last fixed node after loading the exception
+     * @param frameStateFunction a helper that produces a FrameState suitable for deopt
      * @return the last fixed node after instrumentation
      */
-    default FixedWithNextNode instrumentExceptionDispatch(StructuredGraph graph, FixedWithNextNode afterExceptionLoaded) {
+    default FixedWithNextNode instrumentExceptionDispatch(StructuredGraph graph, FixedWithNextNode afterExceptionLoaded, Supplier<FrameState> frameStateFunction) {
         return afterExceptionLoaded;
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ArrayStoreBytecodeExceptionTest.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ArrayStoreBytecodeExceptionTest.java	Thu Jan 23 08:43:22 2020 -0800
@@ -33,39 +33,11 @@
 import org.junit.runners.Parameterized.Parameter;
 import org.junit.runners.Parameterized.Parameters;
 
-import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode.BytecodeExceptionKind;
-import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
-import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
-import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
-
-import jdk.vm.ci.meta.ResolvedJavaMethod;
-
 @RunWith(Parameterized.class)
 public class ArrayStoreBytecodeExceptionTest extends BytecodeExceptionTest {
 
-    private static class Exceptions {
-
-        private static Object[] array = new Exceptions[1];
-
-        public static void throwArrayStore(Object obj) {
-            array[0] = obj;
-        }
-    }
-
-    @Override
-    protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) {
-        invocationPlugins.register(new InvocationPlugin() {
-            @Override
-            public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode obj) {
-                return throwBytecodeException(b, BytecodeExceptionKind.ARRAY_STORE, obj);
-            }
-        }, Exceptions.class, "throwArrayStore", Object.class);
-        super.registerInvocationPlugins(invocationPlugins);
-    }
-
-    public static void arrayStoreSnippet(Object obj) {
-        Exceptions.throwArrayStore(obj);
+    public static void arrayStoreSnippet(Object[] array, Object obj) {
+        array[0] = obj;
     }
 
     @Parameter(0) public Object object;
@@ -84,6 +56,6 @@
 
     @Test
     public void testArrayStoreException() {
-        test("arrayStoreSnippet", object);
+        test("arrayStoreSnippet", new ArrayStoreBytecodeExceptionTest[1], object);
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/BytecodeExceptionTest.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/BytecodeExceptionTest.java	Thu Jan 23 08:43:22 2020 -0800
@@ -24,18 +24,27 @@
 
 package org.graalvm.compiler.replacements.test;
 
+import static org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.BytecodeExceptionMode.CheckAll;
+
 import org.graalvm.compiler.core.test.GraalCompilerTest;
-import org.graalvm.compiler.nodes.UnwindNode;
-import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode;
-import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode.BytecodeExceptionKind;
-import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
+import org.graalvm.compiler.options.OptionValues;
+
+import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 public abstract class BytecodeExceptionTest extends GraalCompilerTest {
 
-    protected boolean throwBytecodeException(GraphBuilderContext b, BytecodeExceptionKind exception, ValueNode... arguments) {
-        BytecodeExceptionNode exceptionNode = b.add(new BytecodeExceptionNode(b.getMetaAccess(), exception, arguments));
-        b.add(new UnwindNode(exceptionNode));
-        return true;
+    @Override
+    protected GraphBuilderConfiguration editGraphBuilderConfiguration(GraphBuilderConfiguration conf) {
+        return super.editGraphBuilderConfiguration(conf).withBytecodeExceptionMode(CheckAll);
+    }
+
+    @Override
+    protected Result test(OptionValues options, ResolvedJavaMethod method, Object receiver, Object... args) {
+        StructuredGraph graph = parseEager(method, StructuredGraph.AllowAssumptions.NO);
+        assertTrue("no BytecodeExceptionNode generated", graph.getNodes().filter(BytecodeExceptionNode.class).isNotEmpty());
+        return super.test(options, method, receiver, args);
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ClassCastBytecodeExceptionTest.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ClassCastBytecodeExceptionTest.java	Thu Jan 23 08:43:22 2020 -0800
@@ -27,6 +27,7 @@
 import java.util.ArrayList;
 import java.util.Collection;
 
+import org.graalvm.compiler.api.directives.GraalDirectives;
 import org.junit.Assert;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -34,64 +35,9 @@
 import org.junit.runners.Parameterized.Parameter;
 import org.junit.runners.Parameterized.Parameters;
 
-import org.graalvm.compiler.api.directives.GraalDirectives;
-import org.graalvm.compiler.core.common.type.Stamp;
-import org.graalvm.compiler.core.common.type.StampFactory;
-import org.graalvm.compiler.core.common.type.TypeReference;
-import org.graalvm.compiler.nodes.ConstantNode;
-import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode.BytecodeExceptionKind;
-import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
-import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
-import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
-
-import jdk.vm.ci.meta.Constant;
-import jdk.vm.ci.meta.ResolvedJavaMethod;
-import jdk.vm.ci.meta.ResolvedJavaType;
-
 @RunWith(Parameterized.class)
 public class ClassCastBytecodeExceptionTest extends BytecodeExceptionTest {
 
-    private static class Exceptions {
-
-        public static void throwClassCast(Object obj, Class<?> cls) {
-            /*
-             * We don't use cls.cast(obj) here because that gives a different exception message than
-             * the checkcast bytecode.
-             */
-            if (cls == Double.class) {
-                Double cast = (Double) obj;
-                GraalDirectives.blackhole(cast);
-            } else if (cls == byte[].class) {
-                byte[] cast = (byte[]) obj;
-                GraalDirectives.blackhole(cast);
-            } else if (cls == String[].class) {
-                String[] cast = (String[]) obj;
-                GraalDirectives.blackhole(cast);
-            } else if (cls == Object[][].class) {
-                Object[][] cast = (Object[][]) obj;
-                GraalDirectives.blackhole(cast);
-            } else {
-                Assert.fail("unexpected class argument");
-            }
-        }
-    }
-
-    @Override
-    protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) {
-        invocationPlugins.register(new InvocationPlugin() {
-            @Override
-            public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode obj, ValueNode classNode) {
-                ResolvedJavaType type = b.getConstantReflection().asJavaType(classNode.asConstant());
-                Constant hub = b.getConstantReflection().asObjectHub(type);
-                Stamp hubStamp = b.getStampProvider().createHubStamp(StampFactory.object(TypeReference.createExactTrusted(type)));
-                ConstantNode hubConst = b.add(ConstantNode.forConstant(hubStamp, hub, b.getMetaAccess()));
-                return throwBytecodeException(b, BytecodeExceptionKind.CLASS_CAST, obj, hubConst);
-            }
-        }, Exceptions.class, "throwClassCast", Object.class, Class.class);
-        super.registerInvocationPlugins(invocationPlugins);
-    }
-
     @Parameter(0) public Object object;
     @Parameter(1) public Class<?> cls;
 
@@ -107,7 +53,25 @@
     }
 
     public static void castToDouble(Object obj) {
-        Exceptions.throwClassCast(obj, Double.class);
+        /*
+         * We don't use cls.cast(obj) here because that gives a different exception message than the
+         * checkcast bytecode.
+         */
+        if (Double.class == Double.class) {
+            Double cast = (Double) obj;
+            GraalDirectives.blackhole(cast);
+        } else if ((Class<?>) Double.class == byte[].class) {
+            byte[] cast = (byte[]) obj;
+            GraalDirectives.blackhole(cast);
+        } else if ((Class<?>) Double.class == String[].class) {
+            String[] cast = (String[]) obj;
+            GraalDirectives.blackhole(cast);
+        } else if ((Class<?>) Double.class == Object[][].class) {
+            Object[][] cast = (Object[][]) obj;
+            GraalDirectives.blackhole(cast);
+        } else {
+            Assert.fail("unexpected class argument");
+        }
     }
 
     @Test
@@ -116,7 +80,25 @@
     }
 
     public static void castToByteArray(Object obj) {
-        Exceptions.throwClassCast(obj, byte[].class);
+        /*
+         * We don't use cls.cast(obj) here because that gives a different exception message than the
+         * checkcast bytecode.
+         */
+        if ((Class<?>) byte[].class == Double.class) {
+            Double cast = (Double) obj;
+            GraalDirectives.blackhole(cast);
+        } else if (byte[].class == byte[].class) {
+            byte[] cast = (byte[]) obj;
+            GraalDirectives.blackhole(cast);
+        } else if ((Class<?>) byte[].class == String[].class) {
+            String[] cast = (String[]) obj;
+            GraalDirectives.blackhole(cast);
+        } else if ((Class<?>) byte[].class == Object[][].class) {
+            Object[][] cast = (Object[][]) obj;
+            GraalDirectives.blackhole(cast);
+        } else {
+            Assert.fail("unexpected class argument");
+        }
     }
 
     @Test
@@ -125,7 +107,25 @@
     }
 
     public static void castToStringArray(Object obj) {
-        Exceptions.throwClassCast(obj, String[].class);
+        /*
+         * We don't use cls.cast(obj) here because that gives a different exception message than the
+         * checkcast bytecode.
+         */
+        if ((Class<?>) String[].class == Double.class) {
+            Double cast = (Double) obj;
+            GraalDirectives.blackhole(cast);
+        } else if ((Class<?>) String[].class == byte[].class) {
+            byte[] cast = (byte[]) obj;
+            GraalDirectives.blackhole(cast);
+        } else if (String[].class == String[].class) {
+            String[] cast = (String[]) obj;
+            GraalDirectives.blackhole(cast);
+        } else if ((Class<?>) String[].class == Object[][].class) {
+            Object[][] cast = (Object[][]) obj;
+            GraalDirectives.blackhole(cast);
+        } else {
+            Assert.fail("unexpected class argument");
+        }
     }
 
     @Test
@@ -134,7 +134,25 @@
     }
 
     public static void castToArrayArray(Object obj) {
-        Exceptions.throwClassCast(obj, Object[][].class);
+        /*
+         * We don't use cls.cast(obj) here because that gives a different exception message than the
+         * checkcast bytecode.
+         */
+        if ((Class<?>) Object[][].class == Double.class) {
+            Double cast = (Double) obj;
+            GraalDirectives.blackhole(cast);
+        } else if ((Class<?>) Object[][].class == byte[].class) {
+            byte[] cast = (byte[]) obj;
+            GraalDirectives.blackhole(cast);
+        } else if ((Class<?>) Object[][].class == String[].class) {
+            String[] cast = (String[]) obj;
+            GraalDirectives.blackhole(cast);
+        } else if (Object[][].class == Object[][].class) {
+            Object[][] cast = (Object[][]) obj;
+            GraalDirectives.blackhole(cast);
+        } else {
+            Assert.fail("unexpected class argument");
+        }
     }
 
     @Test
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/IndexOobBytecodeExceptionTest.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/IndexOobBytecodeExceptionTest.java	Thu Jan 23 08:43:22 2020 -0800
@@ -27,47 +27,19 @@
 import java.util.ArrayList;
 import java.util.Collection;
 
+import org.graalvm.compiler.api.directives.GraalDirectives;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 import org.junit.runners.Parameterized.Parameter;
 import org.junit.runners.Parameterized.Parameters;
 
-import org.graalvm.compiler.api.directives.GraalDirectives;
-import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode.BytecodeExceptionKind;
-import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
-import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
-import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
-
-import jdk.vm.ci.meta.ResolvedJavaMethod;
-
 @RunWith(Parameterized.class)
 public class IndexOobBytecodeExceptionTest extends BytecodeExceptionTest {
 
-    private static class Exceptions {
-
-        private static Object[] empty = new Object[0];
-
-        public static void throwOutOfBounds(int idx, int length) {
-            GraalDirectives.blackhole(empty[idx]);
-            GraalDirectives.blackhole(length);
-        }
-    }
-
-    @Override
-    protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) {
-        invocationPlugins.register(new InvocationPlugin() {
-            @Override
-            public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode idx, ValueNode length) {
-                return throwBytecodeException(b, BytecodeExceptionKind.OUT_OF_BOUNDS, idx, length);
-            }
-        }, Exceptions.class, "throwOutOfBounds", int.class, int.class);
-        super.registerInvocationPlugins(invocationPlugins);
-    }
-
-    public static void oobSnippet(int idx, int length) {
-        Exceptions.throwOutOfBounds(idx, length);
+    public static void oobSnippet(Object[] empty, int idx, int length) {
+        GraalDirectives.blackhole(empty[idx]);
+        GraalDirectives.blackhole(length);
     }
 
     @Parameter public int index;
@@ -85,6 +57,7 @@
 
     @Test
     public void testOutOfBoundsException() {
-        test("oobSnippet", index, Exceptions.empty.length);
+        Object[] empty = new Object[0];
+        test("oobSnippet", empty, index, empty.length);
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/NullBytecodeExceptionTest.java	Thu Jan 23 02:36:42 2020 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/NullBytecodeExceptionTest.java	Thu Jan 23 08:43:22 2020 -0800
@@ -25,41 +25,15 @@
 package org.graalvm.compiler.replacements.test;
 
 import org.junit.Test;
-import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode.BytecodeExceptionKind;
-import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
-import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
-import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
-
-import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 public class NullBytecodeExceptionTest extends BytecodeExceptionTest {
 
-    private static class Exceptions {
-
-        private static Object obj = null;
-
-        public static void throwNull() {
-            obj.toString();
-        }
-    }
-
-    @Override
-    protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) {
-        invocationPlugins.register(new InvocationPlugin() {
-            @Override
-            public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
-                return throwBytecodeException(b, BytecodeExceptionKind.NULL_POINTER);
-            }
-        }, Exceptions.class, "throwNull");
-        super.registerInvocationPlugins(invocationPlugins);
-    }
-
-    public static void nullSnippet() {
-        Exceptions.throwNull();
+    public static void nullSnippet(Object obj) {
+        obj.toString();
     }
 
     @Test
     public void testNullPointerException() {
-        test("nullSnippet");
+        test("nullSnippet", (Object) null);
     }
 }