diff src/share/vm/prims/jvmtiExport.cpp @ 1577:852d0157c696

6956931: assert(SafepointSynchronize::is_at_safepoint()) failed: must be executed at a safepoint Reviewed-by: kvn, dcubed
author never
date Wed, 02 Jun 2010 14:23:23 -0700
parents b4776199210f
children e9ff18c4ace7
line wrap: on
line diff
--- a/src/share/vm/prims/jvmtiExport.cpp	Wed Jun 02 12:02:49 2010 -0700
+++ b/src/share/vm/prims/jvmtiExport.cpp	Wed Jun 02 14:23:23 2010 -0700
@@ -726,6 +726,32 @@
 GrowableArray<const void *>* JvmtiExport::_pending_compiled_method_unload_code_begins;
 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
 
 void JvmtiExport::post_pending_compiled_method_unload_events() {
@@ -788,26 +814,7 @@
   // 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.
   for (;;) {
-    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));
-
-        JvmtiEventMark jem(self);
-        JvmtiJavaThreadEventTransition jet(self);
-        jvmtiEventCompiledMethodUnload callback = env->callbacks()->CompiledMethodUnload;
-        if (callback != NULL) {
-          (*callback)(env->jvmti_external(), method, code_begin);
-        }
-      }
-    }
+    post_compiled_method_unload_internal(self, method, code_begin);
 
     // 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
@@ -1864,17 +1871,25 @@
 }
 
 // used at a safepoint to post a CompiledMethodUnload event
-void JvmtiExport::post_compiled_method_unload_at_safepoint(jmethodID mid, const void *code_begin) {
-  assert(SafepointSynchronize::is_at_safepoint(), "must be executed at a safepoint");
-
-  // create list lazily
-  if (_pending_compiled_method_unload_method_ids == NULL) {
-    _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);
+void JvmtiExport::post_compiled_method_unload(jmethodID mid, const void *code_begin) {
+  if (SafepointSynchronize::is_at_safepoint()) {
+    // Class unloading can cause nmethod unloading which is reported
+    // by the VMThread.  These must be batched to be processed later.
+    if (_pending_compiled_method_unload_method_ids == NULL) {
+      // create list lazily
+      _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) {