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
--- 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,