src/share/vm/prims/methodHandles.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File
hotspot Cdiff src/share/vm/prims/methodHandles.cpp
src/share/vm/prims/methodHandles.cpp
Print this page
*** 943,999 ****
// return number of elements we at leasted wanted to initialize
return rfill + overflow;
}
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);
! }
}
}
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);
! }
! }
}
if (marked > 0) {
! // At least one nmethod has been marked for deoptimization
VM_Deoptimize op;
VMThread::execute(&op);
}
}
--- 943,1005 ----
// 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_purge() {
+ // 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);
! DependencyContext deps = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context);
! deps.add_dependent_nmethod(nm);
! // Try to purge stale entries.
! // 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.
! if (deps.has_unloaded_dependent() && safe_to_purge()) {
! deps.purge();
}
}
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);
! DependencyContext deps = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context);
! deps.remove_dependent_nmethod(nm);
! // Try to purge stale entries.
! if (deps.has_unloaded_dependent() && safe_to_purge()) {
! deps.purge();
}
}
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());
! 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 ****
// Walk all nmethods depending on this call site.
MutexLocker mu1(Compile_lock, thread);
int marked = 0;
{
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
}
if (marked > 0) {
// At least one nmethod has been marked for deoptimization
VM_Deoptimize op;
VMThread::execute(&op);
--- 1343,1356 ----
// 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);
! DependencyContext deps = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context());
! marked = deps.clear();
}
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