...
- ObjectSynchronizer::inflate() has to be careful how omAlloc() is called. If the inflation cause is inflate_cause_vm_internal, then it is not safe to deflate monitors on the per-thread lists so we skip that. When monitor deflation is done, inflate() has to do the oop refresh dance that is common to any code that can go to a safepoint while holding a naked oop. And, no you can't use a Handle here either. :-)
- Everything else is just monitor list management, infrastructure, logging, debugging and the like. :-)
Monitor Deflation Invocation Details
- The existing safepoint deflation mechanism is still invoked at safepoint "cleanup" time.
- SafepointSynchronize::do_cleanup_tasks() calls:
- ObjectSynchronizer::prepare_deflate_idle_monitors()
- A ParallelSPCleanupTask is used to perform the tasks (possibly using parallel tasks):
- A ParallelSPCleanupThreadClosure is used to perform the per-thread tasks:
- ObjectSynchronizer::deflate_thread_local_monitors() to deflate per-thread idle monitors
- ObjectSynchronizer::deflate_idle_monitors() to deflate global idle monitors
- ObjectSynchronizer::finish_deflate_idle_monitors()
- If MonitorUsedDeflationThreshold is exceeded (default is 90%, means off), then the ServiceThread will invoke a cleanup safepoint.
- This experimental flag was added in JDK10 via:
JDK-8181859 Monitor deflation is not checked in cleanup path
- For this option, exceeded means:
((gMonitorPopulation - gMonitorFreeCount) / gMonitorPopulation) > NN%
- When async deflation is enabled, MonitorUsedDeflationThreshold is checked for the global in-use list and for each per-thread in-use list. (Coming in CR8.)
- If MonitorBound is exceeded (default is 0 which means off), cleanup safepoint will be induced.
- For this option, exceeded means:
(gMonitorPopulation - gMonitorFreeCount) > MonitorBound
- When async deflation is enabled, MonitorBound is checked for the global in-use list and for each per-thread in-use list so a smaller, scalable value can be used. (Coming in CR8.)
- Changes to the safepoint deflation mechanism by the Async Monitor Deflation project (when async deflation is enabled):
- If System.gc() is called, then a special deflation request is made which invokes the safepoint deflation mechanism.
- Added the AsyncDeflationInterval diagnostic option (default 250 millis, 0 means off) to prevent MonitorUsedDeflationThreshold requests from swamping the ServiceThread.
- Description: Async deflate idle monitors every so many milliseconds when MonitorUsedDeflationThreshold is exceeded (0 is off).
- SafepointSynchronize::do_cleanup_tasks() now calls:
- ObjectSynchronizer::is_safepoint_deflation_needed() instead of
- ObjectSynchronizer::is_cleanup_needed().
- is_safepoint_deflation_needed() returns true only if a special deflation request is made (see above).
- ObjectSynchronizer::do_safepoint_work() only does the safepoint cleanup tasks if there is a special deflation request. Otherwise it just sets the is_async_deflation_requested flag and notifies the ServiceThread.
- ObjectSynchronizer::deflate_idle_monitors() and ObjectSynchronizer::deflate_thread_local_monitors() do nothing
Gory Details
- Counterpart function mapping for those that know the existing code:
- ObjectSynchronizer class:
- deflate_idle_monitors() has deflate_global_idle_monitors_using_JT(), deflate_per_thread_idle_monitors_using_JT(), and deflate_common_idle_monitors_using_JT().
- deflate_monitor_list() has deflate_monitor_list_using_JT()
- deflate_monitor() has deflate_monitor_using_JT()
- ObjectMonitor class:
- is_busy() has is_busy_async()
- clear() has clear_using_JT()
- These functions recognize the Async Monitor Deflation protocol and adapt their operations:
- ObjectMonitor::EnterI()
- ObjectMonitor::ReenterI()
- Also these functions had to adapt and retry their operations:
- ObjectSynchronizer::quick_enter()
- ObjectSynchronizer::FastHashCode()
- ObjectSynchronizer::current_thread_holds_lock()
- ObjectSynchronizer::query_lock_ownership()
- ObjectSynchronizer::get_lock_owner()
- ObjectSynchronizer::monitors_iterate()
- ObjectSynchronizer::inflate_helper()
- ObjectSynchronizer::inflate()
- Various assertions had to be modified to pass without their real check when AsyncDeflateIdleMonitors is true; this is due to the change in semantics for the ObjectMonitor owner field.
- ObjectMonitor has a new allocation_state field that supports three states: 'Free', 'New', 'Old'. Async Monitor Deflation is only applied to ObjectMonitors that have reached the 'Old' state.
- Note: Prior to CR1/v2.01/4-for-jdk13, the allocation state was transitioned from 'New' to 'Old' in deflate_monitor_via_JT(). This meant that deflate_monitor_via_JT() had to see an ObjectMonitor twice before deflating it. This policy was intended to prevent oscillation from 'New' → 'Old' and back again.
- In CR1/v2.01/4-for-jdk13, the allocation state is transitioned from 'New' -> "Old" in inflate(). This makes ObjectMonitors available for deflation earlier. So far there has been no signs of oscillation from 'New' → 'Old' and back again.
- ObjectMonitor has a new ref_count field that is used as part of the async deflation protocol and to indicate that an ObjectMonitor* is in use so the ObjectMonitor should not be deflated; this is needed for operations on non-busy monitors so that ObjectMonitor values don't change while they are being queried. There is a new ObjectMonitorHandle helper to manage the ref_count.
- The ObjectMonitor::owner() accessor detects DEFLATER_MARKER and returns NULL in that case to minimize the places that need to understand the new DEFLATER_MARKER value.
- System.gc()/JVM_GC() causes a special monitor list cleanup request which uses the safepoint based monitor list mechanism. So even if AsyncDeflateIdleMonitors is enabled, the safepoint based mechanism is still used by this special case.
- This is necessary for those tests that do something to cause an object's monitor to be inflated, clear the only reference to the object and then expect that enough System.gc() calls will eventually cause the object to be GC'ed even when the thread never inflates another object's monitor. Yes, we have several tests like that. :-)