< prev index next >

src/share/vm/prims/methodHandles.cpp

Print this page

        

@@ -937,10 +937,39 @@
 
   // 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) {
+  assert_locked_or_safepoint(Compile_lock);
+  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.
+  }
+  if (java_lang_invoke_DependencyContext::is_default_context(context_oop)) {
+    // Extract context klass from call site target when default context is used.
+    oop mh = java_lang_invoke_CallSite::target(call_site);
+    oop lform = java_lang_invoke_MethodHandle::form(mh);
+    oop mname = java_lang_invoke_LambdaForm::vmentry(lform);
+    oop clazz = java_lang_invoke_MemberName::clazz(mname);
+    return InstanceKlass::cast(java_lang_Class::as_Klass(clazz));
+  } else {
+    // In order to extract a context the following traversal is performed:
+    //   DependencyContext.cleaner => Cleaner.referent => Class._klass => Klass
+    oop cleaner_oop = java_lang_invoke_DependencyContext::cleaner(context_oop);
+    oop context_class_oop = java_lang_ref_Reference::referent(cleaner_oop);
+    if (oopDesc::is_null(context_class_oop)) {
+      // The context reference was cleared by GC, so current DependencyContext instance
+      // isn't usable anymore. Context should be fetched from CallSite again.
+      return NULL;
+    }
+    return InstanceKlass::cast(java_lang_Class::as_Klass(context_class_oop));
+  }
+}
+
 //------------------------------------------------------------------------------
 // MemberNameTable
 //
 
 MemberNameTable::MemberNameTable(int methods_cnt)

@@ -1244,11 +1273,11 @@
 }
 JVM_END
 
 JVM_ENTRY(void, MHN_setCallSiteTargetNormal(JNIEnv* env, jobject igcls, jobject call_site_jh, jobject target_jh)) {
   Handle call_site(THREAD, JNIHandles::resolve_non_null(call_site_jh));
-  Handle target   (THREAD, JNIHandles::resolve(target_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);
     java_lang_invoke_CallSite::set_target(call_site(), target());

@@ -1256,20 +1285,47 @@
 }
 JVM_END
 
 JVM_ENTRY(void, MHN_setCallSiteTargetVolatile(JNIEnv* env, jobject igcls, jobject call_site_jh, jobject target_jh)) {
   Handle call_site(THREAD, JNIHandles::resolve_non_null(call_site_jh));
-  Handle target   (THREAD, JNIHandles::resolve(target_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);
     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));
+  {
+    // 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);
+    }
+    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);
+    }
+  }
+}
+JVM_END
+
 /**
  * Throws a java/lang/UnsupportedOperationException unconditionally.
  * This is required by the specification of MethodHandle.invoke if
  * invoked directly.
  */

@@ -1320,10 +1376,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"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 >