mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 06:45:07 +02:00
8212160: JVMTI agent crashes with "assert(_value != 0LL) failed: resolving NULL _value"
Add local deferred event list to thread to post events outside CodeCache_lock. Reviewed-by: eosterlund, dholmes, sspitsyn
This commit is contained in:
parent
730d0ecf19
commit
8846a8043d
15 changed files with 297 additions and 90 deletions
|
@ -49,6 +49,7 @@
|
|||
#include "oops/methodData.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
#include "prims/jvmtiImpl.hpp"
|
||||
#include "prims/jvmtiThreadState.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
#include "runtime/deoptimization.hpp"
|
||||
#include "runtime/flags/flagSetting.hpp"
|
||||
|
@ -58,6 +59,7 @@
|
|||
#include "runtime/orderAccess.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
#include "runtime/safepointVerifiers.hpp"
|
||||
#include "runtime/serviceThread.hpp"
|
||||
#include "runtime/sharedRuntime.hpp"
|
||||
#include "runtime/sweeper.hpp"
|
||||
#include "runtime/vmThread.hpp"
|
||||
|
@ -428,7 +430,8 @@ void nmethod::init_defaults() {
|
|||
_has_flushed_dependencies = 0;
|
||||
_lock_count = 0;
|
||||
_stack_traversal_mark = 0;
|
||||
_unload_reported = false; // jvmti state
|
||||
_load_reported = false; // jvmti state
|
||||
_unload_reported = false;
|
||||
_is_far_code = false; // nmethods are located in CodeCache
|
||||
|
||||
#ifdef ASSERT
|
||||
|
@ -436,7 +439,6 @@ void nmethod::init_defaults() {
|
|||
#endif
|
||||
|
||||
_oops_do_mark_link = NULL;
|
||||
_jmethod_id = NULL;
|
||||
_osr_link = NULL;
|
||||
#if INCLUDE_RTM_OPT
|
||||
_rtm_state = NoRTM;
|
||||
|
@ -1563,11 +1565,11 @@ void nmethod::flush_dependencies(bool delete_immediately) {
|
|||
// post_compiled_method_load_event
|
||||
// new method for install_code() path
|
||||
// Transfer information from compilation to jvmti
|
||||
void nmethod::post_compiled_method_load_event() {
|
||||
void nmethod::post_compiled_method_load_event(JvmtiThreadState* state) {
|
||||
|
||||
// This is a bad time for a safepoint. We don't want
|
||||
// this nmethod to get unloaded while we're queueing the event.
|
||||
NoSafepointVerifier nsv;
|
||||
// This is a bad time for a safepoint. We don't want
|
||||
// this nmethod to get unloaded while we're queueing the event.
|
||||
NoSafepointVerifier nsv;
|
||||
|
||||
Method* m = method();
|
||||
HOTSPOT_COMPILED_METHOD_LOAD(
|
||||
|
@ -1579,26 +1581,22 @@ void nmethod::post_compiled_method_load_event() {
|
|||
m->signature()->utf8_length(),
|
||||
insts_begin(), insts_size());
|
||||
|
||||
if (JvmtiExport::should_post_compiled_method_load() ||
|
||||
JvmtiExport::should_post_compiled_method_unload()) {
|
||||
get_and_cache_jmethod_id();
|
||||
}
|
||||
|
||||
if (JvmtiExport::should_post_compiled_method_load()) {
|
||||
// Let the Service thread (which is a real Java thread) post the event
|
||||
MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
|
||||
JvmtiDeferredEventQueue::enqueue(
|
||||
JvmtiDeferredEvent::compiled_method_load_event(this));
|
||||
}
|
||||
}
|
||||
// Only post unload events if load events are found.
|
||||
set_load_reported();
|
||||
// Keep sweeper from turning this into zombie until it is posted.
|
||||
mark_as_seen_on_stack();
|
||||
|
||||
jmethodID nmethod::get_and_cache_jmethod_id() {
|
||||
if (_jmethod_id == NULL) {
|
||||
// Cache the jmethod_id since it can no longer be looked up once the
|
||||
// method itself has been marked for unloading.
|
||||
_jmethod_id = method()->jmethod_id();
|
||||
// If a JavaThread hasn't been passed in, let the Service thread
|
||||
// (which is a real Java thread) post the event
|
||||
JvmtiDeferredEvent event = JvmtiDeferredEvent::compiled_method_load_event(this);
|
||||
if (state == NULL) {
|
||||
ServiceThread::enqueue_deferred_event(&event);
|
||||
} else {
|
||||
state->enqueue_event(&event);
|
||||
}
|
||||
}
|
||||
return _jmethod_id;
|
||||
}
|
||||
|
||||
void nmethod::post_compiled_method_unload() {
|
||||
|
@ -1614,17 +1612,17 @@ void nmethod::post_compiled_method_unload() {
|
|||
// If a JVMTI agent has enabled the CompiledMethodUnload event then
|
||||
// post the event. Sometime later this nmethod will be made a zombie
|
||||
// by the sweeper but the Method* will not be valid at that point.
|
||||
// If the _jmethod_id is null then no load event was ever requested
|
||||
// so don't bother posting the unload. The main reason for this is
|
||||
// that the jmethodID is a weak reference to the Method* so if
|
||||
// The jmethodID is a weak reference to the Method* so if
|
||||
// it's being unloaded there's no way to look it up since the weak
|
||||
// ref will have been cleared.
|
||||
if (_jmethod_id != NULL && JvmtiExport::should_post_compiled_method_unload()) {
|
||||
|
||||
// Don't bother posting the unload if the load event wasn't posted.
|
||||
if (load_reported() && JvmtiExport::should_post_compiled_method_unload()) {
|
||||
assert(!unload_reported(), "already unloaded");
|
||||
JvmtiDeferredEvent event =
|
||||
JvmtiDeferredEvent::compiled_method_unload_event(_jmethod_id, insts_begin());
|
||||
MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag);
|
||||
JvmtiDeferredEventQueue::enqueue(event);
|
||||
JvmtiDeferredEvent::compiled_method_unload_event(
|
||||
method()->jmethod_id(), insts_begin());
|
||||
ServiceThread::enqueue_deferred_event(&event);
|
||||
}
|
||||
|
||||
// The JVMTI CompiledMethodUnload event can be enabled or disabled at
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue