diff --git a/src/hotspot/share/code/codeCache.cpp b/src/hotspot/share/code/codeCache.cpp index c853d2e..7cee4b7 100644 --- a/src/hotspot/share/code/codeCache.cpp +++ b/src/hotspot/share/code/codeCache.cpp @@ -146,6 +146,7 @@ address CodeCache::_high_bound = 0; int CodeCache::_number_of_nmethods_with_dependencies = 0; bool CodeCache::_needs_cache_clean = false; nmethod* CodeCache::_scavenge_root_nmethods = NULL; +ExceptionCache* volatile CodeCache::_exception_cache_purge_list = NULL; // Initialize arrays of CodeHeap subsets GrowableArray* CodeCache::_heaps = new(ResourceObj::C_HEAP, mtCode) GrowableArray (CodeBlobType::All, true); @@ -902,6 +903,34 @@ void CodeCache::verify_icholder_relocations() { #endif } +// Defer freeing of concurrently cleaned ExceptionCache entries until +// after a global handshake operation. +void CodeCache::release_exception_cache(ExceptionCache* entry) { + if (SafepointSynchronize::is_at_safepoint()) { + delete entry; + } else { + for (;;) { + ExceptionCache* free_list_head = Atomic::load(&_exception_cache_purge_list); + entry->set_purge_list_next(free_list_head); + if (Atomic::cmpxchg(entry, &_exception_cache_purge_list, free_list_head) == free_list_head) { + break; + } + } + } +} + +// Delete exception caches that have been concurrently unlinked, +// followed by a global handshake operation. +void CodeCache::purge_exception_caches() { + ExceptionCache* curr = _exception_cache_purge_list; + while (curr != NULL) { + ExceptionCache* next = curr->purge_list_next(); + delete curr; + curr = next; + } + _exception_cache_purge_list = NULL; +} + void CodeCache::gc_prologue() { } void CodeCache::gc_epilogue() {