提交 aeb2371c 编写于 作者: N never

6956931: assert(SafepointSynchronize::is_at_safepoint()) failed: must be executed at a safepoint

Reviewed-by: kvn, dcubed
上级 759f87fb
...@@ -1342,19 +1342,7 @@ bool nmethod::make_not_entrant_or_zombie(unsigned int state) { ...@@ -1342,19 +1342,7 @@ bool nmethod::make_not_entrant_or_zombie(unsigned int state) {
// and it hasn't already been reported for this nmethod then report it now. // and it hasn't already been reported for this nmethod then report it now.
// (the event may have been reported earilier if the GC marked it for unloading). // (the event may have been reported earilier if the GC marked it for unloading).
if (state == zombie) { if (state == zombie) {
post_compiled_method_unload();
DTRACE_METHOD_UNLOAD_PROBE(method());
if (JvmtiExport::should_post_compiled_method_unload() &&
!unload_reported()) {
assert(method() != NULL, "checking");
{
HandleMark hm;
JvmtiExport::post_compiled_method_unload_at_safepoint(
method()->jmethod_id(), code_begin());
}
set_unload_reported();
}
} }
...@@ -1506,6 +1494,12 @@ void nmethod::post_compiled_method_load_event() { ...@@ -1506,6 +1494,12 @@ void nmethod::post_compiled_method_load_event() {
} }
void nmethod::post_compiled_method_unload() { void nmethod::post_compiled_method_unload() {
if (unload_reported()) {
// During unloading we transition to unloaded and then to zombie
// and the unloading is reported during the first transition.
return;
}
assert(_method != NULL && !is_unloaded(), "just checking"); assert(_method != NULL && !is_unloaded(), "just checking");
DTRACE_METHOD_UNLOAD_PROBE(method()); DTRACE_METHOD_UNLOAD_PROBE(method());
...@@ -1515,8 +1509,7 @@ void nmethod::post_compiled_method_unload() { ...@@ -1515,8 +1509,7 @@ void nmethod::post_compiled_method_unload() {
if (JvmtiExport::should_post_compiled_method_unload()) { if (JvmtiExport::should_post_compiled_method_unload()) {
assert(!unload_reported(), "already unloaded"); assert(!unload_reported(), "already unloaded");
HandleMark hm; HandleMark hm;
JvmtiExport::post_compiled_method_unload_at_safepoint( JvmtiExport::post_compiled_method_unload(method()->jmethod_id(), code_begin());
method()->jmethod_id(), code_begin());
} }
// The JVMTI CompiledMethodUnload event can be enabled or disabled at // The JVMTI CompiledMethodUnload event can be enabled or disabled at
......
...@@ -726,6 +726,32 @@ GrowableArray<jmethodID>* JvmtiExport::_pending_compiled_method_unload_method_id ...@@ -726,6 +726,32 @@ GrowableArray<jmethodID>* JvmtiExport::_pending_compiled_method_unload_method_id
GrowableArray<const void *>* JvmtiExport::_pending_compiled_method_unload_code_begins; GrowableArray<const void *>* JvmtiExport::_pending_compiled_method_unload_code_begins;
JavaThread* JvmtiExport::_current_poster; JavaThread* JvmtiExport::_current_poster;
void JvmtiExport::post_compiled_method_unload_internal(JavaThread* self, jmethodID method, const void *code_begin) {
EVT_TRIG_TRACE(JVMTI_EVENT_COMPILED_METHOD_UNLOAD,
("JVMTI [%s] method compile unload event triggered",
JvmtiTrace::safe_get_thread_name(self)));
// post the event for each environment that has this event enabled.
JvmtiEnvIterator it;
for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
if (env->is_enabled(JVMTI_EVENT_COMPILED_METHOD_UNLOAD)) {
EVT_TRACE(JVMTI_EVENT_COMPILED_METHOD_UNLOAD,
("JVMTI [%s] class compile method unload event sent jmethodID " PTR_FORMAT,
JvmtiTrace::safe_get_thread_name(self), method));
ResourceMark rm(self);
JvmtiEventMark jem(self);
JvmtiJavaThreadEventTransition jet(self);
jvmtiEventCompiledMethodUnload callback = env->callbacks()->CompiledMethodUnload;
if (callback != NULL) {
(*callback)(env->jvmti_external(), method, code_begin);
}
}
}
}
// post any pending CompiledMethodUnload events // post any pending CompiledMethodUnload events
void JvmtiExport::post_pending_compiled_method_unload_events() { void JvmtiExport::post_pending_compiled_method_unload_events() {
...@@ -788,26 +814,7 @@ void JvmtiExport::post_pending_compiled_method_unload_events() { ...@@ -788,26 +814,7 @@ void JvmtiExport::post_pending_compiled_method_unload_events() {
// flag, cleanup _current_poster to indicate that no thread is now servicing the // flag, cleanup _current_poster to indicate that no thread is now servicing the
// pending events list, and finally notify any thread that might be waiting. // pending events list, and finally notify any thread that might be waiting.
for (;;) { for (;;) {
EVT_TRIG_TRACE(JVMTI_EVENT_COMPILED_METHOD_UNLOAD, post_compiled_method_unload_internal(self, method, code_begin);
("JVMTI [%s] method compile unload event triggered",
JvmtiTrace::safe_get_thread_name(self)));
// post the event for each environment that has this event enabled.
JvmtiEnvIterator it;
for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
if (env->is_enabled(JVMTI_EVENT_COMPILED_METHOD_UNLOAD)) {
EVT_TRACE(JVMTI_EVENT_COMPILED_METHOD_UNLOAD,
("JVMTI [%s] class compile method unload event sent jmethodID " PTR_FORMAT,
JvmtiTrace::safe_get_thread_name(self), method));
JvmtiEventMark jem(self);
JvmtiJavaThreadEventTransition jet(self);
jvmtiEventCompiledMethodUnload callback = env->callbacks()->CompiledMethodUnload;
if (callback != NULL) {
(*callback)(env->jvmti_external(), method, code_begin);
}
}
}
// event posted, now re-grab monitor and get the next event // event posted, now re-grab monitor and get the next event
// If there's no next event then we are done. If this is the first // If there's no next event then we are done. If this is the first
...@@ -1864,17 +1871,25 @@ void JvmtiExport::post_compiled_method_load(JvmtiEnv* env, const jmethodID metho ...@@ -1864,17 +1871,25 @@ void JvmtiExport::post_compiled_method_load(JvmtiEnv* env, const jmethodID metho
} }
// used at a safepoint to post a CompiledMethodUnload event // used at a safepoint to post a CompiledMethodUnload event
void JvmtiExport::post_compiled_method_unload_at_safepoint(jmethodID mid, const void *code_begin) { void JvmtiExport::post_compiled_method_unload(jmethodID mid, const void *code_begin) {
assert(SafepointSynchronize::is_at_safepoint(), "must be executed at a safepoint"); if (SafepointSynchronize::is_at_safepoint()) {
// Class unloading can cause nmethod unloading which is reported
// create list lazily // by the VMThread. These must be batched to be processed later.
if (_pending_compiled_method_unload_method_ids == NULL) { if (_pending_compiled_method_unload_method_ids == NULL) {
_pending_compiled_method_unload_method_ids = new (ResourceObj::C_HEAP) GrowableArray<jmethodID>(10,true); // create list lazily
_pending_compiled_method_unload_code_begins = new (ResourceObj::C_HEAP) GrowableArray<const void *>(10,true); _pending_compiled_method_unload_method_ids = new (ResourceObj::C_HEAP) GrowableArray<jmethodID>(10,true);
_pending_compiled_method_unload_code_begins = new (ResourceObj::C_HEAP) GrowableArray<const void *>(10,true);
}
_pending_compiled_method_unload_method_ids->append(mid);
_pending_compiled_method_unload_code_begins->append(code_begin);
_have_pending_compiled_method_unload_events = true;
} else {
// Unloading caused by the sweeper can be reported synchronously.
if (have_pending_compiled_method_unload_events()) {
post_pending_compiled_method_unload_events();
}
post_compiled_method_unload_internal(JavaThread::current(), mid, code_begin);
} }
_pending_compiled_method_unload_method_ids->append(mid);
_pending_compiled_method_unload_code_begins->append(code_begin);
_have_pending_compiled_method_unload_events = true;
} }
void JvmtiExport::post_dynamic_code_generated_internal(const char *name, const void *code_begin, const void *code_end) { void JvmtiExport::post_dynamic_code_generated_internal(const char *name, const void *code_begin, const void *code_end) {
......
...@@ -144,6 +144,9 @@ class JvmtiExport : public AllStatic { ...@@ -144,6 +144,9 @@ class JvmtiExport : public AllStatic {
// posts any pending CompiledMethodUnload events. // posts any pending CompiledMethodUnload events.
static void post_pending_compiled_method_unload_events(); static void post_pending_compiled_method_unload_events();
// Perform the actual notification to interested JvmtiEnvs.
static void post_compiled_method_unload_internal(JavaThread* self, jmethodID mid, const void* code_begin);
// posts a DynamicCodeGenerated event (internal/private implementation). // posts a DynamicCodeGenerated event (internal/private implementation).
// The public post_dynamic_code_generated* functions make use of the // The public post_dynamic_code_generated* functions make use of the
// internal implementation. // internal implementation.
...@@ -299,8 +302,8 @@ class JvmtiExport : public AllStatic { ...@@ -299,8 +302,8 @@ class JvmtiExport : public AllStatic {
static void post_compiled_method_load(nmethod *nm) KERNEL_RETURN; static void post_compiled_method_load(nmethod *nm) KERNEL_RETURN;
static void post_dynamic_code_generated(const char *name, const void *code_begin, const void *code_end) KERNEL_RETURN; static void post_dynamic_code_generated(const char *name, const void *code_begin, const void *code_end) KERNEL_RETURN;
// used at a safepoint to post a CompiledMethodUnload event // used to post a CompiledMethodUnload event
static void post_compiled_method_unload_at_safepoint(jmethodID mid, const void *code_begin) KERNEL_RETURN; static void post_compiled_method_unload(jmethodID mid, const void *code_begin) KERNEL_RETURN;
// similiar to post_dynamic_code_generated except that it can be used to // similiar to post_dynamic_code_generated except that it can be used to
// post a DynamicCodeGenerated event while holding locks in the VM. Any event // post a DynamicCodeGenerated event while holding locks in the VM. Any event
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册