--- a/hotspot/src/share/vm/prims/jvmtiExport.cpp Wed Feb 02 18:38:40 2011 -0500
+++ b/hotspot/src/share/vm/prims/jvmtiExport.cpp Wed Feb 02 14:38:01 2011 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -750,15 +750,12 @@
// pending CompiledMethodUnload support
//
-bool JvmtiExport::_have_pending_compiled_method_unload_events;
-GrowableArray<jmethodID>* JvmtiExport::_pending_compiled_method_unload_method_ids;
-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) {
+void JvmtiExport::post_compiled_method_unload(
+ jmethodID method, const void *code_begin) {
+ JavaThread* thread = JavaThread::current();
EVT_TRIG_TRACE(JVMTI_EVENT_COMPILED_METHOD_UNLOAD,
("JVMTI [%s] method compile unload event triggered",
- JvmtiTrace::safe_get_thread_name(self)));
+ JvmtiTrace::safe_get_thread_name(thread)));
// post the event for each environment that has this event enabled.
JvmtiEnvIterator it;
@@ -767,12 +764,12 @@
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));
+ JvmtiTrace::safe_get_thread_name(thread), method));
- ResourceMark rm(self);
+ ResourceMark rm(thread);
- JvmtiEventMark jem(self);
- JvmtiJavaThreadEventTransition jet(self);
+ JvmtiEventMark jem(thread);
+ JvmtiJavaThreadEventTransition jet(thread);
jvmtiEventCompiledMethodUnload callback = env->callbacks()->CompiledMethodUnload;
if (callback != NULL) {
(*callback)(env->jvmti_external(), method, code_begin);
@@ -781,90 +778,6 @@
}
}
-// post any pending CompiledMethodUnload events
-
-void JvmtiExport::post_pending_compiled_method_unload_events() {
- JavaThread* self = JavaThread::current();
- assert(!self->owns_locks(), "can't hold locks");
-
- // Indicates if this is the first activiation of this function.
- // In theory the profiler's callback could call back into VM and provoke
- // another CompiledMethodLoad event to be posted from this thread. As the
- // stack rewinds we need to ensure that the original activation does the
- // completion and notifies any waiters.
- bool first_activation = false;
-
- // the jmethodID (may not be valid) to be used for a single event
- jmethodID method;
- const void *code_begin;
-
- // grab the monitor and check if another thread is already posting
- // events. If there is another thread posting events then we wait
- // until it completes. (In theory we could check the pending events to
- // see if any of the addresses overlap with the event that we want to
- // post but as it will happen so rarely we just block any thread waiting
- // to post a CompiledMethodLoad or DynamicCodeGenerated event until all
- // pending CompiledMethodUnload events have been posted).
- //
- // If another thread isn't posting we examine the list of pending jmethodIDs.
- // If the list is empty then we are done. If it's not empty then this thread
- // (self) becomes the pending event poster and we remove the top (last)
- // event from the list. Note that this means we remove the newest event first
- // but as they are all CompiledMethodUnload events the order doesn't matter.
- // Once we have removed a jmethodID then we exit the monitor. Any other thread
- // wanting to post a CompiledMethodLoad or DynamicCodeGenerated event will
- // be forced to wait on the monitor.
- {
- MutexLocker mu(JvmtiPendingEvent_lock);
- if (_current_poster != self) {
- while (_current_poster != NULL) {
- JvmtiPendingEvent_lock->wait();
- }
- }
- if ((_pending_compiled_method_unload_method_ids == NULL) ||
- (_pending_compiled_method_unload_method_ids->length() == 0)) {
- return;
- }
- if (_current_poster == NULL) {
- _current_poster = self;
- first_activation = true;
- } else {
- // re-entrant
- guarantee(_current_poster == self, "checking");
- }
- method = _pending_compiled_method_unload_method_ids->pop();
- code_begin = _pending_compiled_method_unload_code_begins->pop();
- }
-
- // This thread is the pending event poster so it first posts the CompiledMethodUnload
- // event for the jmethodID that has been removed from the list. Once posted it
- // re-grabs the monitor and checks the list again. If the list is empty then and this
- // is the first activation of the function then we reset the _have_pending_events
- // 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 (;;) {
- 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
- // activiation of this function by this thread notify any waiters
- // so that they can post.
- {
- MutexLocker ml(JvmtiPendingEvent_lock);
- if (_pending_compiled_method_unload_method_ids->length() == 0) {
- if (first_activation) {
- _have_pending_compiled_method_unload_events = false;
- _current_poster = NULL;
- JvmtiPendingEvent_lock->notify_all();
- }
- return;
- }
- method = _pending_compiled_method_unload_method_ids->pop();
- code_begin = _pending_compiled_method_unload_code_begins->pop();
- }
- }
-}
-
///////////////////////////////////////////////////////////////
//
// JvmtiExport
@@ -1830,16 +1743,7 @@
}
void JvmtiExport::post_compiled_method_load(nmethod *nm) {
- // If there are pending CompiledMethodUnload events then these are
- // posted before this CompiledMethodLoad event. We "lock" the nmethod and
- // maintain a handle to the methodOop to ensure that the nmethod isn't
- // flushed or unloaded while posting the events.
JavaThread* thread = JavaThread::current();
- if (have_pending_compiled_method_unload_events()) {
- methodHandle mh(thread, nm->method());
- nmethodLocker nml(nm);
- post_pending_compiled_method_unload_events();
- }
EVT_TRIG_TRACE(JVMTI_EVENT_COMPILED_METHOD_LOAD,
("JVMTI [%s] method compile load event triggered",
@@ -1854,8 +1758,8 @@
JvmtiTrace::safe_get_thread_name(thread),
(nm->method() == NULL) ? "NULL" : nm->method()->klass_name()->as_C_string(),
(nm->method() == NULL) ? "NULL" : nm->method()->name()->as_C_string()));
-
ResourceMark rm(thread);
+ HandleMark hm(thread);
// Add inlining information
jvmtiCompiledMethodLoadInlineRecord* inlinerecord = create_inline_record(nm);
@@ -1899,28 +1803,6 @@
}
}
-// used at a safepoint to post a CompiledMethodUnload event
-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);
- }
-}
-
void JvmtiExport::post_dynamic_code_generated_internal(const char *name, const void *code_begin, const void *code_end) {
JavaThread* thread = JavaThread::current();
EVT_TRIG_TRACE(JVMTI_EVENT_DYNAMIC_CODE_GENERATED,
@@ -1953,9 +1835,9 @@
return;
}
- if (have_pending_compiled_method_unload_events()) {
- post_pending_compiled_method_unload_events();
- }
+ // Blocks until everything now in the queue has been posted
+ JvmtiDeferredEventQueue::flush_queue(Thread::current());
+
post_dynamic_code_generated_internal(name, code_begin, code_end);
}