--- a/hotspot/src/share/vm/code/nmethod.cpp Wed Aug 11 10:48:20 2010 -0700
+++ b/hotspot/src/share/vm/code/nmethod.cpp Thu Aug 12 16:38:23 2010 -0700
@@ -433,6 +433,10 @@
_unload_reported = false; // jvmti state
NOT_PRODUCT(_has_debug_info = false);
+#ifdef ASSERT
+ _oops_are_stale = false;
+#endif
+
_oops_do_mark_link = NULL;
_jmethod_id = NULL;
_osr_link = NULL;
@@ -1230,11 +1234,10 @@
bool nmethod::make_not_entrant_or_zombie(unsigned int state) {
assert(state == zombie || state == not_entrant, "must be zombie or not_entrant");
- bool was_alive = false;
-
// Make sure neither the nmethod nor the method is flushed in case of a safepoint in code below.
nmethodLocker nml(this);
methodHandle the_method(method());
+ No_Safepoint_Verifier nsv;
{
// If the method is already zombie there is nothing to do
@@ -1303,13 +1306,27 @@
// state will be flushed later when the transition to zombie
// happens or they get unloaded.
if (state == zombie) {
- // zombie only - if a JVMTI agent has enabled the CompiledMethodUnload event
- // 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).
- post_compiled_method_unload();
+ {
+ // Flushing dependecies must be done before any possible
+ // safepoint can sneak in, otherwise the oops used by the
+ // dependency logic could have become stale.
+ MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+ flush_dependencies(NULL);
+ }
- MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
- flush_dependencies(NULL);
+ {
+ // zombie only - if a JVMTI agent has enabled the CompiledMethodUnload event
+ // 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).
+ Pause_No_Safepoint_Verifier pnsv(&nsv);
+ post_compiled_method_unload();
+ }
+
+#ifdef ASSERT
+ // It's no longer safe to access the oops section since zombie
+ // nmethods aren't scanned for GC.
+ _oops_are_stale = true;
+#endif
} else {
assert(state == not_entrant, "other cases may need to be handled differently");
}
--- a/hotspot/src/share/vm/code/nmethod.hpp Wed Aug 11 10:48:20 2010 -0700
+++ b/hotspot/src/share/vm/code/nmethod.hpp Thu Aug 12 16:38:23 2010 -0700
@@ -177,6 +177,10 @@
// Protected by Patching_lock
unsigned char _state; // {alive, not_entrant, zombie, unloaded)
+#ifdef ASSERT
+ bool _oops_are_stale; // indicates that it's no longer safe to access oops section
+#endif
+
enum { alive = 0,
not_entrant = 1, // uncommon trap has happened but activations may still exist
zombie = 2,
@@ -434,6 +438,7 @@
oop* oop_addr_at(int index) const { // for GC
// relocation indexes are biased by 1 (because 0 is reserved)
assert(index > 0 && index <= oops_size(), "must be a valid non-zero index");
+ assert(!_oops_are_stale, "oops are stale");
return &oops_begin()[index - 1];
}