diff -r e3040e4dde63 -r 01a5c5fa5681 hotspot/src/share/vm/prims/methodHandles.cpp --- a/hotspot/src/share/vm/prims/methodHandles.cpp Fri May 15 19:21:46 2015 +0300 +++ b/hotspot/src/share/vm/prims/methodHandles.cpp Fri May 15 19:23:11 2015 +0300 @@ -942,22 +942,56 @@ 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. +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_MethodHandleNatives_CallSiteContext::vmdependencies(context); + + nmethodBucket* new_deps = nmethodBucket::add_dependent_nmethod(deps, nm); + if (deps != new_deps) { + java_lang_invoke_MethodHandleNatives_CallSiteContext::set_vmdependencies(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_MethodHandleNatives_CallSiteContext::vmdependencies(context); + + if (nmethodBucket::remove_dependent_nmethod(deps, nm)) { + nmethodBucket* new_deps = nmethodBucket::clean_dependent_nmethods(deps); + if (deps != new_deps) { + java_lang_invoke_MethodHandleNatives_CallSiteContext::set_vmdependencies(context, new_deps); + } } - 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::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_MethodHandleNatives_CallSiteContext::vmdependencies(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_MethodHandleNatives_CallSiteContext::set_vmdependencies(context, new_deps); + } + } } - return InstanceKlass::cast(java_lang_Class::as_Klass(context_class_oop)); + if (marked > 0) { + // At least one nmethod has been marked for deoptimization + VM_Deoptimize op; + VMThread::execute(&op); + } } //------------------------------------------------------------------------------ @@ -1276,7 +1310,7 @@ { // 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()); } } @@ -1288,30 +1322,34 @@ { // 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_MethodHandleNatives_CallSiteContext::vmdependencies(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_MethodHandleNatives_CallSiteContext::set_vmdependencies(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; @@ -1357,6 +1395,7 @@ #define MT JLINV"MethodType;" #define MH JLINV"MethodHandle;" #define MEM JLINV"MemberName;" +#define CTX JLINV"MethodHandleNatives$CallSiteContext;" #define CC (char*) /*cast a literal from (const char*)*/ #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f) @@ -1374,7 +1413,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"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)}