< prev index next >

src/share/vm/prims/methodHandles.cpp

Print this page

        

@@ -938,26 +938,60 @@
 
   // return number of elements we at leasted wanted to initialize
   return rfill + overflow;
 }
 
-// Get context class for a CallSite instance: either extract existing context or use default one.
-InstanceKlass* MethodHandles::get_call_site_context(oop call_site) {
-  // In order to extract a context the following traversal is performed:
-  //   CallSite.context => Cleaner.referent => Class._klass => Klass
-  assert(java_lang_invoke_CallSite::is_instance(call_site), "");
-  oop context_oop = java_lang_invoke_CallSite::context_volatile(call_site);
-  if (oopDesc::is_null(context_oop)) {
-    return NULL; // The context hasn't been initialized yet.
-  }
-  oop context_class_oop = java_lang_ref_Reference::referent(context_oop);
-  if (oopDesc::is_null(context_class_oop)) {
-    // The context reference was cleared by GC, so current dependency context
-    // isn't usable anymore. Context should be fetched from CallSite again.
-    return NULL;
+void MethodHandles::add_dependent_nmethod(oop call_site, nmethod* nm) {
+  assert_locked_or_safepoint(CodeCache_lock);
+
+  oop context = java_lang_invoke_CallSite::context(call_site);
+  nmethodBucket* deps = java_lang_invoke_CallSite_Context::dependencies(context);
+
+  nmethodBucket* new_deps = nmethodBucket::add_dependent_nmethod(deps, nm);
+  if (deps != new_deps) {
+    java_lang_invoke_CallSite_Context::set_dependencies(context, new_deps);
+  }
+}
+
+void MethodHandles::remove_dependent_nmethod(oop call_site, nmethod* nm) {
+  assert_locked_or_safepoint(CodeCache_lock);
+
+  oop context = java_lang_invoke_CallSite::context(call_site);
+  nmethodBucket* deps = java_lang_invoke_CallSite_Context::dependencies(context);
+
+  if (nmethodBucket::remove_dependent_nmethod(deps, nm)) {
+    nmethodBucket* new_deps = nmethodBucket::clean_dependent_nmethods(deps);
+    if (deps != new_deps) {
+      java_lang_invoke_CallSite_Context::set_dependencies(context, new_deps);
+    }
+  }
+}
+
+void MethodHandles::flush_dependent_nmethods(Handle call_site, Handle target) {
+  assert_lock_strong(Compile_lock);
+
+  int marked = 0;
+  CallSiteDepChange changes(call_site(), target());
+  {
+    MutexLockerEx mu2(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+
+    oop context = java_lang_invoke_CallSite::context(call_site());
+    nmethodBucket* deps = java_lang_invoke_CallSite_Context::dependencies(context);
+
+    marked = nmethodBucket::mark_dependent_nmethods(deps, changes);
+    if (marked > 0) {
+      nmethodBucket* new_deps = nmethodBucket::clean_dependent_nmethods(deps);
+      if (deps != new_deps) {
+        java_lang_invoke_CallSite_Context::set_dependencies(context, new_deps);
+      }
+    }
+  }
+  if (marked > 0) {
+    // At least one nmethod has been marked for deoptimization
+    VM_Deoptimize op;
+    VMThread::execute(&op);
   }
-  return InstanceKlass::cast(java_lang_Class::as_Klass(context_class_oop));
 }
 
 //------------------------------------------------------------------------------
 // MemberNameTable
 //

@@ -1272,11 +1306,11 @@
   Handle call_site(THREAD, JNIHandles::resolve_non_null(call_site_jh));
   Handle target   (THREAD, JNIHandles::resolve_non_null(target_jh));
   {
     // Walk all nmethods depending on this call site.
     MutexLocker mu(Compile_lock, thread);
-    CodeCache::flush_dependents_on(call_site, target);
+    MethodHandles::flush_dependent_nmethods(call_site, target);
     java_lang_invoke_CallSite::set_target(call_site(), target());
   }
 }
 JVM_END
 

@@ -1284,34 +1318,38 @@
   Handle call_site(THREAD, JNIHandles::resolve_non_null(call_site_jh));
   Handle target   (THREAD, JNIHandles::resolve_non_null(target_jh));
   {
     // Walk all nmethods depending on this call site.
     MutexLocker mu(Compile_lock, thread);
-    CodeCache::flush_dependents_on(call_site, target);
+    MethodHandles::flush_dependent_nmethods(call_site, target);
     java_lang_invoke_CallSite::set_target_volatile(call_site(), target());
   }
 }
 JVM_END
 
-JVM_ENTRY(void, MHN_invalidateDependentNMethods(JNIEnv* env, jobject igcls, jobject call_site_jh)) {
-  Handle call_site(THREAD, JNIHandles::resolve_non_null(call_site_jh));
+JVM_ENTRY(void, MHN_clearCallSiteContext(JNIEnv* env, jobject igcls, jobject context_jh)) {
+  Handle context(THREAD, JNIHandles::resolve_non_null(context_jh));
   {
     // Walk all nmethods depending on this call site.
     MutexLocker mu1(Compile_lock, thread);
 
-    CallSiteDepChange changes(call_site(), Handle());
-
-    InstanceKlass* ctxk = MethodHandles::get_call_site_context(call_site());
-    if (ctxk == NULL) {
-      return; // No dependencies to invalidate yet.
-    }
     int marked = 0;
     {
       MutexLockerEx mu2(CodeCache_lock, Mutex::_no_safepoint_check_flag);
-      marked = ctxk->mark_dependent_nmethods(changes);
+      nmethodBucket* b = java_lang_invoke_CallSite_Context::dependencies(context());
+      while(b != NULL) {
+        nmethod* nm = b->get_nmethod();
+        if (b->count() > 0 && nm->is_alive() && !nm->is_marked_for_deoptimization()) {
+          nm->mark_for_deoptimization();
+          marked++;
+        }
+        nmethodBucket* next = b->next();
+        delete b;
+        b = next;
+      }
+      java_lang_invoke_CallSite_Context::set_dependencies(context(), NULL); // reset context
     }
-    java_lang_invoke_CallSite::set_context_volatile(call_site(), NULL); // Reset call site to initial state
     if (marked > 0) {
       // At least one nmethod has been marked for deoptimization
       VM_Deoptimize op;
       VMThread::execute(&op);
     }

@@ -1350,10 +1388,11 @@
 
 #define OBJ   LANG"Object;"
 #define CLS   LANG"Class;"
 #define STRG  LANG"String;"
 #define CS    JLINV"CallSite;"
+#define CTX   JLINV"CallSite$Context;"
 #define MT    JLINV"MethodType;"
 #define MH    JLINV"MethodHandle;"
 #define MEM   JLINV"MemberName;"
 
 #define CC (char*)  /*cast a literal from (const char*)*/

@@ -1370,11 +1409,11 @@
   //          int matchFlags, Class<?> caller, int skip, MemberName[] results);
   {CC"getMembers",                CC"("CLS""STRG""STRG"I"CLS"I["MEM")I", FN_PTR(MHN_getMembers)},
   {CC"objectFieldOffset",         CC"("MEM")J",                          FN_PTR(MHN_objectFieldOffset)},
   {CC"setCallSiteTargetNormal",   CC"("CS""MH")V",                       FN_PTR(MHN_setCallSiteTargetNormal)},
   {CC"setCallSiteTargetVolatile", CC"("CS""MH")V",                       FN_PTR(MHN_setCallSiteTargetVolatile)},
-  {CC"invalidateDependentNMethods", CC"("CS")V",                         FN_PTR(MHN_invalidateDependentNMethods)},
+  {CC"clearCallSiteContext",      CC"("CTX")V",                          FN_PTR(MHN_clearCallSiteContext)},
   {CC"staticFieldOffset",         CC"("MEM")J",                          FN_PTR(MHN_staticFieldOffset)},
   {CC"staticFieldBase",           CC"("MEM")"OBJ,                        FN_PTR(MHN_staticFieldBase)},
   {CC"getMemberVMInfo",           CC"("MEM")"OBJ,                        FN_PTR(MHN_getMemberVMInfo)}
 };
 
< prev index next >