src/share/vm/prims/methodHandles.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File
*** old/src/share/vm/prims/methodHandles.cpp	Thu Nov  5 21:52:45 2015
--- new/src/share/vm/prims/methodHandles.cpp	Thu Nov  5 21:52:45 2015

*** 943,999 **** --- 943,996 ---- // return number of elements we at leasted wanted to initialize return rfill + overflow; } + // Is it safe to remove stale entries from a dependency list? + static bool safe_to_expunge() { + // Since parallel GC threads can concurrently iterate over a dependency + // list during safepoint, it is safe to remove entries only when + // CodeCache lock is held. + return CodeCache_lock->owned_by_self(); + } + 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); } ! DependencyContext deps = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context); + // Try to purge stale entries on updates. + // Since GC doesn't clean dependency contexts rooted at CallSiteContext objects, + // in order to avoid memory leak, stale entries are purged whenever a dependency list + // is changed (both on addition and removal). Though memory reclamation is delayed, + // it avoids indefinite memory usage growth. + deps.add_dependent_nmethod(nm, /*expunge_stale_entries=*/safe_to_expunge()); } 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); } } ! DependencyContext deps = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context); + deps.remove_dependent_nmethod(nm, /*expunge_stale_entries=*/safe_to_expunge()); } void MethodHandles::flush_dependent_nmethods(Handle call_site, Handle target) { assert_lock_strong(Compile_lock); int marked = 0; CallSiteDepChange changes(call_site(), target()); { + No_Safepoint_Verifier nsv; 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); } } ! DependencyContext deps = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context); + marked = deps.mark_dependent_nmethods(changes); } if (marked > 0) { ! // At least one nmethod has been marked for deoptimization. VM_Deoptimize op; VMThread::execute(&op); } }
*** 1337,1359 **** --- 1334,1347 ---- // Walk all nmethods depending on this call site. MutexLocker mu1(Compile_lock, thread); int marked = 0; { + No_Safepoint_Verifier nsv; MutexLockerEx mu2(CodeCache_lock, Mutex::_no_safepoint_check_flag); ! 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 ! DependencyContext deps = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context()); + marked = deps.remove_all_dependents(); } if (marked > 0) { // At least one nmethod has been marked for deoptimization VM_Deoptimize op; VMThread::execute(&op);

src/share/vm/prims/methodHandles.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File