changeset 7000:bf2ea3ed3bce

Fixed nmethod not being unloaded after their classloader has been unloaded by initializing _graal_installed_code in an nmethod's constructor
author Gilles Duboscq <duboscq@ssw.jku.at>
date Wed, 21 Nov 2012 23:33:43 +0100
parents 679e6584c177
children 46bec43bdfc3
files src/share/vm/code/nmethod.cpp src/share/vm/code/nmethod.hpp src/share/vm/graal/graalCodeInstaller.cpp src/share/vm/graal/graalCodeInstaller.hpp src/share/vm/graal/graalCompilerToVM.cpp src/share/vm/graal/graalEnv.cpp src/share/vm/graal/graalEnv.hpp
diffstat 7 files changed, 60 insertions(+), 54 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/code/nmethod.cpp	Wed Nov 21 19:23:43 2012 +0100
+++ b/src/share/vm/code/nmethod.cpp	Wed Nov 21 23:33:43 2012 +0100
@@ -483,7 +483,7 @@
   _saved_nmethod_link      = NULL;
   _compiler                = NULL;
 #ifdef GRAAL
-  _graal_installed_code   = (oop) Universe::non_oop_word();
+  _graal_installed_code   = NULL;
 #endif
 #ifdef HAVE_DTRACE_H
   _trap_offset             = 0;
@@ -577,6 +577,9 @@
   ImplicitExceptionTable* nul_chk_table,
   AbstractCompiler* compiler,
   int comp_level
+#ifdef GRAAL
+  , Handle installed_code
+#endif
 )
 {
   assert(debug_info->oop_recorder() == code_buffer->oop_recorder(), "shared OR");
@@ -598,7 +601,11 @@
               handler_table,
               nul_chk_table,
               compiler,
-              comp_level);
+              comp_level
+#ifdef GRAAL
+              , installed_code
+#endif
+              );
     if (nm != NULL) {
       // To make dependency checking during class loading fast, record
       // the nmethod dependencies in the classes it is dependent on.
@@ -819,6 +826,9 @@
   ImplicitExceptionTable* nul_chk_table,
   AbstractCompiler* compiler,
   int comp_level
+#ifdef GRAAL
+  , Handle installed_code
+#endif
   )
   : CodeBlob("nmethod", code_buffer, sizeof(nmethod),
              nmethod_size, offsets->value(CodeOffsets::Frame_Complete), frame_size, oop_maps),
@@ -843,22 +853,24 @@
     _stub_offset             = content_offset()      + code_buffer->total_offset_of(code_buffer->stubs());
 
 #ifdef GRAAL
-      // graal produces no (!) stub section
-      if (offsets->value(CodeOffsets::Exceptions) != -1) {
-        _exception_offset        = code_offset()          + offsets->value(CodeOffsets::Exceptions);
-      } else {
-        _exception_offset = -1;
-      }
-      if (offsets->value(CodeOffsets::Deopt) != -1) {
-        _deoptimize_offset       = code_offset()          + offsets->value(CodeOffsets::Deopt);
-      } else {
-        _deoptimize_offset = -1;
-      }
-      if (offsets->value(CodeOffsets::DeoptMH) != -1) {
-        _deoptimize_mh_offset  = code_offset()          + offsets->value(CodeOffsets::DeoptMH);
-      } else {
-        _deoptimize_mh_offset  = -1;
-      }
+    _graal_installed_code = installed_code();
+
+    // graal produces no (!) stub section
+    if (offsets->value(CodeOffsets::Exceptions) != -1) {
+      _exception_offset        = code_offset()          + offsets->value(CodeOffsets::Exceptions);
+    } else {
+      _exception_offset = -1;
+    }
+    if (offsets->value(CodeOffsets::Deopt) != -1) {
+      _deoptimize_offset       = code_offset()          + offsets->value(CodeOffsets::Deopt);
+    } else {
+      _deoptimize_offset = -1;
+    }
+    if (offsets->value(CodeOffsets::DeoptMH) != -1) {
+      _deoptimize_mh_offset  = code_offset()          + offsets->value(CodeOffsets::DeoptMH);
+    } else {
+      _deoptimize_mh_offset  = -1;
+    }
 #else
     // Exception handler and deopt handler are in the stub section
     assert(offsets->value(CodeOffsets::Exceptions) != -1, "must be set");
@@ -1266,7 +1278,7 @@
   }
 
 #ifdef GRAAL
-    if (graal_installed_code() != NULL) {
+    if (_graal_installed_code != NULL) {
       HotSpotInstalledCode::set_nmethod(_graal_installed_code, 0);
       _graal_installed_code = NULL;
     }
@@ -1354,7 +1366,7 @@
     }
 
 #ifdef GRAAL
-    if (graal_installed_code() != NULL) {
+    if (_graal_installed_code != NULL) {
       HotSpotInstalledCode::set_nmethod(_graal_installed_code, 0);
       _graal_installed_code = NULL;
     }
@@ -1654,10 +1666,6 @@
 
 #ifdef GRAAL
   // Follow Graal method
-  if (_graal_installed_code == Universe::non_oop_word()) {
-    // May have not yet finished initializing a non-default nmethod
-    return;
-  }
   if (_graal_installed_code != NULL && can_unload(is_alive, (oop*)&_graal_installed_code, unloading_occurred)) {
     return;
   }
@@ -1883,7 +1891,7 @@
   }
 
 #ifdef GRAAL
-  if (graal_installed_code() != NULL) {
+  if (_graal_installed_code != NULL) {
     f->do_oop((oop*) &_graal_installed_code);
   }
 #endif
--- a/src/share/vm/code/nmethod.hpp	Wed Nov 21 19:23:43 2012 +0100
+++ b/src/share/vm/code/nmethod.hpp	Wed Nov 21 23:33:43 2012 +0100
@@ -269,7 +269,11 @@
           ExceptionHandlerTable* handler_table,
           ImplicitExceptionTable* nul_chk_table,
           AbstractCompiler* compiler,
-          int comp_level);
+          int comp_level
+#ifdef GRAAL
+          , Handle installed_code = NULL
+#endif
+          );
 
   // helper methods
   void* operator new(size_t size, int nmethod_size);
@@ -287,7 +291,7 @@
   // Inform external interfaces that a compiled method has been unloaded
   void post_compiled_method_unload();
 
-  // Initailize fields to their default values
+  // Initialize fields to their default values
   void init_defaults();
 
  public:
@@ -305,7 +309,11 @@
                               ExceptionHandlerTable* handler_table,
                               ImplicitExceptionTable* nul_chk_table,
                               AbstractCompiler* compiler,
-                              int comp_level);
+                              int comp_level
+#ifdef GRAAL
+                              , Handle installed_code = NULL
+#endif
+  );
 
   static nmethod* new_native_nmethod(methodHandle method,
                                      int compile_id,
@@ -570,7 +578,7 @@
   void set_method(Method* method) { _method = method; }
 
 #ifdef GRAAL
-  oop graal_installed_code() { return _graal_installed_code == Universe::non_oop_word() ? NULL : _graal_installed_code ; }
+  oop graal_installed_code() { return _graal_installed_code ; }
   void set_graal_installed_code(oop installed_code) { _graal_installed_code = installed_code;  }
 #endif
 
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Wed Nov 21 19:23:43 2012 +0100
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Wed Nov 21 23:33:43 2012 +0100
@@ -291,7 +291,7 @@
 }
 
 // constructor used to create a method
-CodeInstaller::CodeInstaller(Handle& comp_result, methodHandle method, nmethod*& nm, bool bind_to_method) {
+CodeInstaller::CodeInstaller(Handle& comp_result, methodHandle method, nmethod*& nm, Handle installed_code) {
   _env = CURRENT_ENV;
   GraalCompiler::initialize_buffer_blob();
   CodeBuffer buffer(JavaThread::current()->get_buffer_blob());
@@ -309,7 +309,7 @@
   int stack_slots = _total_frame_size / HeapWordSize; // conversion to words
 
   nm = GraalEnv::register_method(method, entry_bci, &_offsets, _custom_stack_area_offset, &buffer, stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table,
-    &_implicit_exception_table, GraalCompiler::instance(), _debug_recorder, _dependencies, NULL, -1, true, false, bind_to_method);
+    &_implicit_exception_table, GraalCompiler::instance(), _debug_recorder, _dependencies, NULL, -1, true, false, installed_code);
 
   method->clear_queued_for_compilation();
 }
--- a/src/share/vm/graal/graalCodeInstaller.hpp	Wed Nov 21 19:23:43 2012 +0100
+++ b/src/share/vm/graal/graalCodeInstaller.hpp	Wed Nov 21 23:33:43 2012 +0100
@@ -85,7 +85,7 @@
 public:
 
   // constructor used to create a method
-  CodeInstaller(Handle& comp_result, methodHandle method, nmethod*& nm, bool bind_to_method);
+  CodeInstaller(Handle& comp_result, methodHandle method, nmethod*& nm, Handle installed_code);
 
   // constructor used to create a stub
   CodeInstaller(Handle& target_method, BufferBlob*& blob, jlong& id);
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Wed Nov 21 19:23:43 2012 +0100
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Wed Nov 21 23:33:43 2012 +0100
@@ -774,8 +774,8 @@
   methodHandle method = getMethodFromHotSpotMethod(HotSpotCompilationResult::method(compResult));
   Arena arena;
   ciEnv env(&arena);
-  bool bind_to_method = installed_code == NULL;
-  CodeInstaller installer(compResultHandle, method, nm, bind_to_method);
+  Handle installed_code_handle = JNIHandles::resolve(installed_code);
+  CodeInstaller installer(compResultHandle, method, nm, installed_code_handle);
 
   if (info != NULL) {
     arrayOop codeCopy = oopFactory::new_byteArray(nm->code_size(), CHECK_0);
@@ -784,22 +784,12 @@
     HotSpotCodeInfo::set_start(info, (jlong) nm->code_begin());
   }
 
-  if (installed_code != NULL && nm != NULL) {
-    Handle obj = JNIHandles::resolve(installed_code);
-    assert(obj->is_a(HotSpotInstalledCode::klass()), "wrong type");
-    HotSpotInstalledCode::set_nmethod(obj, (jlong) nm);
-    HotSpotInstalledCode::set_method(obj, HotSpotCompilationResult::method(compResult));
-    nm->set_graal_installed_code(obj());
-    assert(nm->graal_installed_code() == obj(), "must be");
-    if (!nm->on_scavenge_root_list()) {
-      // Since the nmethod now contains a normal oop (i.e. installed_code) it must
-      // be on the list of nmethods scavenged for oops.
-      // Must hold the code cache lock when adding to the scavenger list
-      MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
-      CodeCache::add_scavenge_root_nmethod(nm);
-      assert(nm->on_scavenge_root_list(), "must be");
-    }
-    return JNIHandles::make_local(obj());
+  if (!installed_code_handle.is_null()) {
+    assert(installed_code_handle->is_a(HotSpotInstalledCode::klass()), "wrong type");
+    HotSpotInstalledCode::set_nmethod(installed_code_handle, (jlong) nm);
+    HotSpotInstalledCode::set_method(installed_code_handle, HotSpotCompilationResult::method(compResult));
+    assert(nm == NULL || !installed_code_handle->is_scavengable() || nm->on_scavenge_root_list(), "nm should be scavengable if installed_code is scavengable");
+    return installed_code;
   } else {
     return NULL;
   }
--- a/src/share/vm/graal/graalEnv.cpp	Wed Nov 21 19:23:43 2012 +0100
+++ b/src/share/vm/graal/graalEnv.cpp	Wed Nov 21 23:33:43 2012 +0100
@@ -444,7 +444,7 @@
                                 int compile_id,
                                 bool has_debug_info,
                                 bool has_unsafe_access,
-                                bool bind_to_method) {
+                                Handle installed_code) {
   EXCEPTION_CONTEXT;
   NMethodSweeper::possibly_sweep();
   nmethod* nm = NULL;
@@ -483,7 +483,7 @@
                                debug_info, dependencies, code_buffer,
                                frame_words, oop_map_set,
                                handler_table, inc_table,
-                               compiler, comp_level);
+                               compiler, comp_level, installed_code);
 
     // Free codeBlobs
     //code_buffer->free_blob();
@@ -512,7 +512,7 @@
       // (Put nm into the task handle *before* publishing to the Java heap.)
       if (task != NULL)  task->set_code(nm);
 
-      if (bind_to_method) {
+      if (installed_code.is_null()) {
         if (entry_bci == InvocationEntryBci) {
           if (TieredCompilation) {
             // If there is an old version we're done with it
--- a/src/share/vm/graal/graalEnv.hpp	Wed Nov 21 19:23:43 2012 +0100
+++ b/src/share/vm/graal/graalEnv.hpp	Wed Nov 21 23:33:43 2012 +0100
@@ -125,7 +125,7 @@
                        int                       compile_id,
                        bool                      has_debug_info,
                        bool                      has_unsafe_access,
-                       bool                      bind_to_method);
+                       Handle                    installed_code);
 
   static ciKlass*  find_system_klass(ciSymbol* klass_name);
   // Note:  To find a class from its name string, use ciSymbol::make,