RFR: 8212989: Allow CompiledMethod ExceptionCache have unloaded klasses

Vladimir Kozlov vladimir.kozlov at oracle.com
Thu Nov 1 20:14:00 UTC 2018

Hi Erik,

It seems these  changed are not based on latest sources. I don't see call to CodeCache::do_unloading in 
CodeCache::do_unloading() which is present in latest code:


May be make some methods private, like CompiledMethod::exception_cache_acquire().

It seems you remove the only case when release_set_exception_cache() is called.

I don't see where purge_exception_caches() is used.

Next sentence seems incomplete:

+  // unlinked. That is also when the CodeCache::exception_cache_free_list()

Why you use exception_cache_acquire() in clean_exception_cache() and simple exception_cache() in 


On 11/1/18 5:58 AM, Erik Österlund wrote:
> Hi,
> The ExceptionCaches of compiled methods is traditionally pruned in safepoints during class unloading. This allows the 
> exception cache to have lock-free reads, while performing inserts under a lock, and pruning under a safepoint. With 
> concurrent class unloading, the exception caches need to be cleaned concurrently.
> To retain the lock-free reads that seem good to keep lock-free, a lock-free cleaning mechanism was introduced. Only one 
> thread per compiled method cleans each exception cache, but that thread races with both single writers (under the 
> ExceptionCache_lock) and any number of readers.
> The head of the exception cache list is concurrently cleaned by both inserting threads and cleaning threads. This allows 
> having an invariant that no newly prepended entries ever produce next pointers to dead exception caches, that are 
> concurrently removed from the list. As for the internal next pointers, they are only pruned by the one concurrent 
> cleaning thread. This happens concurrent to reads that simply skip over dead entries as they have different Klass* 
> pointers to the one being searched for.
> The single concurrent cleanup thread does not delete things removed from the list straight away. Instead, they are 
> placed on a purge list that is freed up after a subsequent global handshaking operation. That allows ABA-free CAS 
> instructions in the lock-free paths, and allows safe concurrent reading of entries in the exception cache list.
> Note that we already incorrectly "relied on memory_order_consume" for the head pointer. But it used a volatile load. 
> Assuming volatile loads retain memory_order_consume semantics is not allowed in HotSpot runtime code, so I changed those 
> loads to use acquire accordingly.
> Webrev:
> http://cr.openjdk.java.net/~eosterlund/8212989/webrev.00/
> Bug:
> https://bugs.openjdk.java.net/browse/JDK-8212989
> Thanks,
> /Erik

More information about the hotspot-dev mailing list