8164480: Crash with assert(handler_address == SharedRuntime::compute_compiled_exc_handler(..) failed: Must be the same
authorthartmann
Tue, 30 Aug 2016 13:24:26 +0200
changeset 41057 f77b9d9e0e4c
parent 41054 29ca540a1910
child 41058 92d8f53e6419
8164480: Crash with assert(handler_address == SharedRuntime::compute_compiled_exc_handler(..) failed: Must be the same Summary: Exception checking code needs to handle pre-allocated exceptions. Reviewed-by: dnsimon, kvn
hotspot/src/share/vm/c1/c1_Runtime1.cpp
hotspot/src/share/vm/jvmci/jvmciRuntime.cpp
hotspot/src/share/vm/opto/runtime.cpp
hotspot/src/share/vm/runtime/sharedRuntime.cpp
hotspot/src/share/vm/runtime/sharedRuntime.hpp
--- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp	Tue Aug 30 09:01:33 2016 +0000
+++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp	Tue Aug 30 13:24:26 2016 +0200
@@ -576,9 +576,8 @@
     // normal bytecode execution.
     thread->clear_exception_oop_and_pc();
 
-    Handle original_exception(thread, exception());
-
-    continuation = SharedRuntime::compute_compiled_exc_handler(nm, pc, exception, false, false);
+    bool recursive_exception = false;
+    continuation = SharedRuntime::compute_compiled_exc_handler(nm, pc, exception, false, false, recursive_exception);
     // If an exception was thrown during exception dispatch, the exception oop may have changed
     thread->set_exception_oop(exception());
     thread->set_exception_pc(pc);
@@ -586,8 +585,9 @@
     // the exception cache is used only by non-implicit exceptions
     // Update the exception cache only when there didn't happen
     // another exception during the computation of the compiled
-    // exception handler.
-    if (continuation != NULL && original_exception() == exception()) {
+    // exception handler. Checking for exception oop equality is not
+    // sufficient because some exceptions are pre-allocated and reused.
+    if (continuation != NULL && !recursive_exception) {
       nm->add_handler_for_exception_and_pc(exception, pc, continuation);
     }
   }
--- a/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp	Tue Aug 30 09:01:33 2016 +0000
+++ b/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp	Tue Aug 30 13:24:26 2016 +0200
@@ -313,13 +313,18 @@
     // normal bytecode execution.
     thread->clear_exception_oop_and_pc();
 
-    continuation = SharedRuntime::compute_compiled_exc_handler(cm, pc, exception, false, false);
+    bool recursive_exception = false;
+    continuation = SharedRuntime::compute_compiled_exc_handler(cm, pc, exception, false, false, recursive_exception);
     // If an exception was thrown during exception dispatch, the exception oop may have changed
     thread->set_exception_oop(exception());
     thread->set_exception_pc(pc);
 
     // the exception cache is used only by non-implicit exceptions
-    if (continuation != NULL && !SharedRuntime::deopt_blob()->contains(continuation)) {
+    // Update the exception cache only when there didn't happen
+    // another exception during the computation of the compiled
+    // exception handler. Checking for exception oop equality is not
+    // sufficient because some exceptions are pre-allocated and reused.
+    if (continuation != NULL && !recursive_exception && !SharedRuntime::deopt_blob()->contains(continuation)) {
       cm->add_handler_for_exception_and_pc(exception, pc, continuation);
     }
   }
--- a/hotspot/src/share/vm/opto/runtime.cpp	Tue Aug 30 09:01:33 2016 +0000
+++ b/hotspot/src/share/vm/opto/runtime.cpp	Tue Aug 30 13:24:26 2016 +0200
@@ -1349,17 +1349,23 @@
         force_unwind ? NULL : nm->handler_for_exception_and_pc(exception, pc);
 
       if (handler_address == NULL) {
-        Handle original_exception(thread, exception());
-        handler_address = SharedRuntime::compute_compiled_exc_handler(nm, pc, exception, force_unwind, true);
+        bool recursive_exception = false;
+        handler_address = SharedRuntime::compute_compiled_exc_handler(nm, pc, exception, force_unwind, true, recursive_exception);
         assert (handler_address != NULL, "must have compiled handler");
         // Update the exception cache only when the unwind was not forced
         // and there didn't happen another exception during the computation of the
-        // compiled exception handler.
-        if (!force_unwind && original_exception() == exception()) {
+        // compiled exception handler. Checking for exception oop equality is not
+        // sufficient because some exceptions are pre-allocated and reused.
+        if (!force_unwind && !recursive_exception) {
           nm->add_handler_for_exception_and_pc(exception,pc,handler_address);
         }
       } else {
-        assert(handler_address == SharedRuntime::compute_compiled_exc_handler(nm, pc, exception, force_unwind, true), "Must be the same");
+#ifdef ASSERT
+        bool recursive_exception = false;
+        address computed_address = SharedRuntime::compute_compiled_exc_handler(nm, pc, exception, force_unwind, true, recursive_exception);
+        vmassert(recursive_exception || (handler_address == computed_address), "Handler address inconsistency: " PTR_FORMAT " != " PTR_FORMAT,
+                 p2i(handler_address), p2i(computed_address));
+#endif
       }
     }
 
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Tue Aug 30 09:01:33 2016 +0000
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Tue Aug 30 13:24:26 2016 +0200
@@ -621,7 +621,7 @@
 // ret_pc points into caller; we are returning caller's exception handler
 // for given exception
 address SharedRuntime::compute_compiled_exc_handler(CompiledMethod* cm, address ret_pc, Handle& exception,
-                                                    bool force_unwind, bool top_frame_only) {
+                                                    bool force_unwind, bool top_frame_only, bool& recursive_exception_occurred) {
   assert(cm != NULL, "must exist");
   ResourceMark rm;
 
@@ -677,6 +677,7 @@
         // BCI of the exception handler which caused the exception to be
         // thrown (bugs 4307310 and 4546590). Set "exception" reference
         // argument to ensure that the correct exception is thrown (4870175).
+        recursive_exception_occurred = true;
         exception = Handle(THREAD, PENDING_EXCEPTION);
         CLEAR_PENDING_EXCEPTION;
         if (handler_bci >= 0) {
--- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp	Tue Aug 30 09:01:33 2016 +0000
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp	Tue Aug 30 13:24:26 2016 +0200
@@ -189,7 +189,7 @@
 
   // exception handling and implicit exceptions
   static address compute_compiled_exc_handler(CompiledMethod* nm, address ret_pc, Handle& exception,
-                                              bool force_unwind, bool top_frame_only);
+                                              bool force_unwind, bool top_frame_only, bool& recursive_exception_occurred);
   enum ImplicitExceptionKind {
     IMPLICIT_NULL,
     IMPLICIT_DIVIDE_BY_ZERO,