You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by va...@apache.org on 2008/05/27 06:54:15 UTC

svn commit: r660377 - in /harmony/enhanced/drlvm/trunk/vm: include/open/ jitrino/src/vm/ vmcore/include/ vmcore/src/class_support/

Author: varlax
Date: Mon May 26 21:54:07 2008
New Revision: 660377

URL: http://svn.apache.org/viewvc?rev=660377&view=rev
Log:
Fixed HARMONY-5822 [drlvm][vmcore] class unloading does not clean JIT recompilation callbacks

Modified:
    harmony/enhanced/drlvm/trunk/vm/include/open/vm_class_support.h
    harmony/enhanced/drlvm/trunk/vm/include/open/vm_ee.h
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/vm/VMInterface.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/include/Class.h
    harmony/enhanced/drlvm/trunk/vm/vmcore/include/class_member.h
    harmony/enhanced/drlvm/trunk/vm/vmcore/include/classloader.h
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/C_Interface.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Class.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/classloader.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/method.cpp

Modified: harmony/enhanced/drlvm/trunk/vm/include/open/vm_class_support.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/include/open/vm_class_support.h?rev=660377&r1=660376&r2=660377&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/include/open/vm_class_support.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/include/open/vm_class_support.h Mon May 26 21:54:07 2008
@@ -50,28 +50,6 @@
 void vm_patch_code_block(U_8* code_block, U_8* new_code, size_t size);
 
 /**
- * Called by a EE in order to be notified whenever the vtable entries for the given method 
- * are changed. This could happen, e.g., when a method is first compiled, or when it is 
- * recompiled.  The callback_data pointer will be passed back to the JIT during the callback.  
- * The callback method is JIT_recompiled_method_callback.
- */
-void vm_register_jit_recompiled_method_callback(JIT_Handle jit, Method_Handle method, void* callback_data);
-
-/**
- * Called by a JIT in order to be notified whenever the given method is overridden by a newly 
- * loaded class. The callback_data pointer will be passed back to the JIT during the callback.  
- * The callback function is JIT_overridden_method_callback.
- */
-void vm_register_jit_overridden_method_callback(JIT_Handle jit, Method_Handle method, void* callback_data);
-
-/**
- * Called by a JIT in order to be notified whenever the given class is extended.
- * The callback_data pointer will be passed back to the JIT during the callback. 
- * The callback function is JIT_extended_class_callback.
- */
-void vm_register_jit_extended_class_callback(JIT_Handle jit, Class_Handle clss, void* callback_data);
-
-/**
  * Called by a JIT to have the VM recompile a method using the specified JIT. After 
  * recompilation, the corresponding vtable entries will be updated, and the necessary 
  * callbacks to JIT_recompiled_method_callback will be made. It is a requirement that 

Modified: harmony/enhanced/drlvm/trunk/vm/include/open/vm_ee.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/include/open/vm_ee.h?rev=660377&r1=660376&r2=660377&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/include/open/vm_ee.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/include/open/vm_ee.h Mon May 26 21:54:07 2008
@@ -198,8 +198,10 @@
  * will be passed back to the JIT during the callback. The callback method is 
  * <code>JIT_recompiled_method_callback</code>.
  */
-DECLARE_OPEN(void, vm_register_jit_recompiled_method_callback, (JIT_Handle jit, Method_Handle method,
-                                                           void *callback_data));
+DECLARE_OPEN(void, vm_register_jit_recompiled_method_callback, (JIT_Handle jit, 
+                                Method_Handle method, 
+                                Method_Handle caller, 
+                                void *callback_data));
 
 /**
  * Called by a JIT to have the VM replace a section of executable code in a 

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/vm/VMInterface.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/vm/VMInterface.cpp?rev=660377&r1=660376&r2=660377&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/vm/VMInterface.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/vm/VMInterface.cpp Mon May 26 21:54:07 2008
@@ -1036,7 +1036,8 @@
 void         CompilationInterface::setNotifyWhenMethodIsRecompiled(MethodDesc * methodDesc, 
                                                                       void * callbackData) {
     Method_Handle drlMethod = methodDesc->getMethodHandle();
-    vm_register_jit_recompiled_method_callback(getJitHandle(),drlMethod,callbackData);
+    vm_register_jit_recompiled_method_callback(getJitHandle(),drlMethod, 
+        getMethodToCompile()->getMethodHandle(), callbackData);
 }
 
 void CompilationInterface::sendCompiledMethodLoadEvent(MethodDesc* methodDesc, MethodDesc* outerDesc,

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/include/Class.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/include/Class.h?rev=660377&r1=660376&r2=660377&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/include/Class.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/include/Class.h Mon May 26 21:54:07 2008
@@ -1059,6 +1059,8 @@
     /** Clears member variables within a class.*/
     void clear_internals();
 
+    void notify_unloading();
+
     /** Determines whether the given class has a super class.
      * @return <code>true</code> if the current class has a super class;
      *         otherwise <code>false</code>.*/

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/include/class_member.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/include/class_member.h?rev=660377&r1=660376&r2=660377&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/include/class_member.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/include/class_member.h Mon May 26 21:54:07 2008
@@ -22,6 +22,8 @@
 #include "Class.h"
 #include "vm_java_support.h"
 
+typedef std::vector<Method*> MethodSet;
+
 struct String;
 class ByteReader;
 class JIT;
@@ -347,20 +349,11 @@
 // Used to notify interested JITs whenever a method is changed: overwritten, recompiled,
 // or initially compiled.
 struct Method_Change_Notification_Record {
-    Method *method_of_interest;
+    Method *caller;
     JIT    *jit;
     void   *callback_data;
     Method_Change_Notification_Record *next;
 
-    bool equals(Method *method_of_interest_, JIT *jit_, void *callback_data_) {
-        if ((method_of_interest == method_of_interest_) &&
-            (jit == jit_) &&
-            (callback_data == callback_data_)) {
-            return true;
-        }
-        return false;
-    }
-    // Optimized equals method. Most callbacks know method of interest, so we could skip one check.
     inline bool equals(JIT *jit_, void *callback_data_) {
         if ((callback_data == callback_data_) &&
             (jit == jit_)) {
@@ -569,8 +562,9 @@
     CodeChunkInfo *create_code_chunk_info_mt();
 
     // Notify JITs whenever this method is recompiled or initially compiled.
-    void register_jit_recompiled_method_callback(JIT *jit_to_be_notified, void *callback_data);
+    void register_jit_recompiled_method_callback(JIT *jit_to_be_notified, Method* caller, void *callback_data);
     void do_jit_recompiled_method_callbacks();
+    void unregister_jit_recompiled_method_callbacks(const Method* caller);
 
     Method_Side_Effects get_side_effects()         { return _side_effects; }
     void set_side_effects(Method_Side_Effects mse) { _side_effects = mse; }
@@ -606,6 +600,7 @@
     // destructor should be instead of this function, but it's not allowed to use it because copy for Method class is
     // done with memcpy, and old value is destroyed with delete operator.
     void MethodClearInternals();
+    void NotifyUnloading();
 
     //
     // access modifiers
@@ -717,6 +712,9 @@
 
     /** Information about methods inlined to this. */
     InlineInfo* _inline_info;
+    
+
+    MethodSet* _recompilation_callbacks;
 public:
 
     /**

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/include/classloader.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/include/classloader.h?rev=660377&r1=660376&r2=660377&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/include/classloader.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/include/classloader.h Mon May 26 21:54:07 2008
@@ -240,6 +240,9 @@
         STD_FREE(m_table);
         m_table = NULL;
     }
+
+    void NotifyUnloading();
+
     inline void* Alloc(size_t size) {
         assert(pool);
         Lock();

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/C_Interface.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/C_Interface.cpp?rev=660377&r1=660376&r2=660377&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/C_Interface.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/C_Interface.cpp Mon May 26 21:54:07 2008
@@ -1729,12 +1729,14 @@
 // initially compiled. The callback_data pointer will be passed back to the JIT during the callback.
 // The callback method is JIT_recompiled_method_callback.
 void vm_register_jit_recompiled_method_callback(JIT_Handle jit, Method_Handle method,
+                                                Method_Handle caller,
                                                  void *callback_data)
 {
     assert(method);
+    assert(caller);
     JIT *jit_to_be_notified = (JIT *)jit;
     Method *m = (Method *)method;
-    m->register_jit_recompiled_method_callback(jit_to_be_notified, callback_data);
+    m->register_jit_recompiled_method_callback(jit_to_be_notified, caller, callback_data);
 } //vm_register_jit_recompiled_method_callback
 
 

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Class.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Class.cpp?rev=660377&r1=660376&r2=660377&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Class.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Class.cpp Mon May 26 21:54:07 2008
@@ -144,6 +144,13 @@
     m_verify_data = 0;
 }
 
+void Class::notify_unloading() {
+    if(m_methods != NULL) {
+        for (int i = 0; i < m_num_methods; i++){
+            m_methods[i].NotifyUnloading();
+        }
+    }
+}
 
 void Class::clear_internals() {
     if(m_fields != NULL)
@@ -615,6 +622,7 @@
     _method_sig = 0;
 
     _notify_recompiled_records = NULL;
+    _recompilation_callbacks = NULL;
     _index = 0;
     _max_stack=_max_locals=_n_exceptions=_n_handlers=0;
     _exceptions = NULL;
@@ -639,6 +647,18 @@
     _inline_info = NULL;
 } //Method::Method
 
+
+void Method::NotifyUnloading()
+{
+    if (_recompilation_callbacks != NULL) {
+        MethodSet::const_iterator it;
+        for (it = _recompilation_callbacks->begin(); it != _recompilation_callbacks->end(); it++)
+        {
+            (*it)->unregister_jit_recompiled_method_callbacks(this);
+        }
+    }
+}
+
 void Method::MethodClearInternals()
 {
     CodeChunkInfo *jit_info;
@@ -656,6 +676,10 @@
         }
         jit_info->_target_exception_handlers = NULL;
     }
+    
+    if (_recompilation_callbacks != NULL) {
+        delete _recompilation_callbacks;
+    }
 
     if (_notify_recompiled_records != NULL)
     {

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/classloader.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/classloader.cpp?rev=660377&r1=660376&r2=660377&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/classloader.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/classloader.cpp Mon May 26 21:54:07 2008
@@ -106,6 +106,22 @@
     return true;
 }
 
+void ClassLoader::NotifyUnloading() 
+{
+    Global_Env *env = VM_Global_State::loader_env;
+    env->em_interface->ClassloaderUnloadingCallback((Class_Loader_Handle)this);
+
+    ClassTable::iterator it;
+    ClassTable* LoadedClasses = GetLoadedClasses();
+    for (it = LoadedClasses->begin(); it != LoadedClasses->end(); it++)
+    {
+        Class* c;
+        c = it->second;
+        assert(c);
+        c->notify_unloading();
+    }
+}
+
 ClassLoader::~ClassLoader() 
 {
     Global_Env *env = VM_Global_State::loader_env;
@@ -147,7 +163,6 @@
         natives_unload_library(info->handle);        
     }
 
-    env->em_interface->ClassloaderUnloadingCallback((Class_Loader_Handle)this);
     delete CodeMemoryManager;
     CodeMemoryManager = NULL;
 
@@ -582,9 +597,15 @@
         unloadinglist.push_back(m_table[i]);
     }
 
+    vector<ClassLoader*>::reverse_iterator it;
+    for (it = unloadinglist.rbegin(); it != unloadinglist.rend(); it++)
+    {
+        (*it)->NotifyUnloading();
+    }
+
     // safely remove classloaders from m_table
-    vector<ClassLoader*>::iterator it;
-    for (it = unloadinglist.begin(); it != unloadinglist.end(); it++)
+    // iterate in reverse order to unload child loaders first
+    for (it = unloadinglist.rbegin(); it != unloadinglist.rend(); it++)
     {
         UnloadClassLoader(*it);
     }

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/method.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/method.cpp?rev=660377&r1=660376&r2=660377&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/method.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/method.cpp Mon May 26 21:54:07 2008
@@ -553,7 +553,9 @@
 // Notify the given JIT whenever this method is recompiled or initially compiled.
 // The callback_data pointer will be passed back to the JIT during the callback.  
 // The JIT's callback function is JIT_recompiled_method_callback.
-void Method::register_jit_recompiled_method_callback(JIT *jit_to_be_notified, void *callback_data)
+void Method::register_jit_recompiled_method_callback(JIT *jit_to_be_notified, 
+                                                     Method* caller,
+                                                     void *callback_data)
 {
     // Don't insert the same entry repeatedly on the _notify_recompiled_records list.
     Method_Change_Notification_Record *nr = _notify_recompiled_records;
@@ -567,13 +569,43 @@
     // Insert a new notification record.
     Method_Change_Notification_Record *new_nr = 
         (Method_Change_Notification_Record *)STD_MALLOC(sizeof(Method_Change_Notification_Record));
-    new_nr->method_of_interest = this;
+    new_nr->caller = caller;
     new_nr->jit                = jit_to_be_notified;
     new_nr->callback_data      = callback_data;
     new_nr->next               = _notify_recompiled_records;
     _notify_recompiled_records = new_nr;
+
+    // Record a callback in the caller method to let it unregister itself if unloaded.
+    ClassLoader* this_loader = get_class()->get_class_loader();
+    ClassLoader* caller_loader = caller->get_class()->get_class_loader();
+    if (this_loader == caller_loader || caller_loader->IsBootstrap()) return;
+
+    MethodSet *vec = caller->_recompilation_callbacks;
+    if (vec == NULL) {
+        vec = caller->_recompilation_callbacks = new MethodSet();
+    }
+    vec->push_back(this);
 } //Method::register_jit_recompiled_method_callback
 
+void Method::unregister_jit_recompiled_method_callbacks(const Method* caller) {
+    TRACE2("cu.debug", "unregister jit callback, caller=" << caller << " callee=" << this);
+    Method_Change_Notification_Record *nr,*prev = NULL;
+    for (nr = _notify_recompiled_records;  nr != NULL;  ) {
+        if (nr->caller == caller) {
+            if (prev) {
+                prev->next = nr->next;
+            } else {
+                _notify_recompiled_records = nr->next;
+            }
+            Method_Change_Notification_Record *next = nr->next;
+            STD_FREE(nr);
+            nr = next;
+        } else {
+            prev = nr;
+            nr = nr->next;
+        }
+    }
+}
 
 void Method::do_jit_recompiled_method_callbacks() 
 {