diff -r 5f1a3a275862 -r 95baefac8485 hotspot/src/share/vm/prims/methodHandles.cpp --- a/hotspot/src/share/vm/prims/methodHandles.cpp Wed Apr 15 11:01:56 2015 +0200 +++ b/hotspot/src/share/vm/prims/methodHandles.cpp Fri Apr 17 18:17:06 2015 +0300 @@ -939,6 +939,24 @@ 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; + } + return InstanceKlass::cast(java_lang_Class::as_Klass(context_class_oop)); +} + //------------------------------------------------------------------------------ // MemberNameTable // @@ -1231,7 +1249,7 @@ 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); @@ -1243,7 +1261,7 @@ 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); @@ -1253,6 +1271,33 @@ } 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 @@ -1306,6 +1351,7 @@ {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)}