--- old/src/hotspot/share/runtime/globals.hpp 2020-07-02 15:14:57.000000000 -0400 +++ new/src/hotspot/share/runtime/globals.hpp 2020-07-02 15:14:57.000000000 -0400 @@ -684,9 +684,6 @@ "Disable the use of stack guard pages if the JVM is loaded " \ "on the primordial process thread") \ \ - diagnostic(bool, AsyncDeflateIdleMonitors, true, \ - "Deflate idle monitors using the ServiceThread.") \ - \ /* notice: the max range value here is max_jint, not max_intx */ \ /* because of overflow issue */ \ diagnostic(intx, AsyncDeflationInterval, 250, \ --- old/src/hotspot/share/runtime/init.cpp 2020-07-02 15:14:58.000000000 -0400 +++ new/src/hotspot/share/runtime/init.cpp 2020-07-02 15:14:58.000000000 -0400 @@ -170,10 +170,8 @@ if (log_is_enabled(Info, monitorinflation)) { // The ObjectMonitor subsystem uses perf counters so // do this before perfMemory_exit(). - // These other two audit_and_print_stats() calls are done at the + // This other audit_and_print_stats() call is done at the // Debug level at a safepoint: - // - for safepoint based deflation auditing: - // ObjectSynchronizer::finish_deflate_idle_monitors() // - for async deflation auditing: // ObjectSynchronizer::do_safepoint_work() ObjectSynchronizer::audit_and_print_stats(true /* on_exit */); --- old/src/hotspot/share/runtime/objectMonitor.cpp 2020-07-02 15:14:59.000000000 -0400 +++ new/src/hotspot/share/runtime/objectMonitor.cpp 2020-07-02 15:14:59.000000000 -0400 @@ -290,8 +290,6 @@ JavaThread * jt = (JavaThread *) Self; assert(!SafepointSynchronize::is_at_safepoint(), "invariant"); assert(jt->thread_state() != _thread_blocked, "invariant"); - assert(AsyncDeflateIdleMonitors || this->object() != NULL, "invariant"); - assert(AsyncDeflateIdleMonitors || contentions() >= 0, "must not be negative: contentions=%d", contentions()); // Keep track of contention for JVM/TI and M&M queries. add_to_contentions(1); @@ -455,12 +453,12 @@ // deflation so we're done here. return; } - ADIM_guarantee(l_object == obj, "object=" INTPTR_FORMAT " must equal obj=" - INTPTR_FORMAT, p2i(l_object), p2i(obj)); + assert(l_object == obj, "object=" INTPTR_FORMAT " must equal obj=" + INTPTR_FORMAT, p2i(l_object), p2i(obj)); markWord dmw = header(); // The dmw has to be neutral (not NULL, not locked and not marked). - ADIM_guarantee(dmw.is_neutral(), "must be neutral: dmw=" INTPTR_FORMAT, dmw.value()); + assert(dmw.is_neutral(), "must be neutral: dmw=" INTPTR_FORMAT, dmw.value()); // Install displaced mark word if the object's header still points // to this ObjectMonitor. More than one racing caller to this function @@ -487,22 +485,17 @@ // used for diagnostic output. const char* ObjectMonitor::is_busy_to_string(stringStream* ss) { ss->print("is_busy: waiters=%d, ", _waiters); - if (!AsyncDeflateIdleMonitors) { + if (contentions() > 0) { ss->print("contentions=%d, ", contentions()); + } else { + ss->print("contentions=0"); + } + if (_owner != DEFLATER_MARKER) { ss->print("owner=" INTPTR_FORMAT, p2i(_owner)); } else { - if (contentions() > 0) { - ss->print("contentions=%d, ", contentions()); - } else { - ss->print("contentions=0"); - } - if (_owner != DEFLATER_MARKER) { - ss->print("owner=" INTPTR_FORMAT, p2i(_owner)); - } else { - // We report NULL instead of DEFLATER_MARKER here because is_busy() - // ignores DEFLATER_MARKER values. - ss->print("owner=" INTPTR_FORMAT, NULL); - } + // We report NULL instead of DEFLATER_MARKER here because is_busy() + // ignores DEFLATER_MARKER values. + ss->print("owner=" INTPTR_FORMAT, NULL); } ss->print(", cxq=" INTPTR_FORMAT ", EntryList=" INTPTR_FORMAT, p2i(_cxq), p2i(_EntryList)); @@ -524,8 +517,7 @@ return; } - if (AsyncDeflateIdleMonitors && - try_set_owner_from(DEFLATER_MARKER, Self) == DEFLATER_MARKER) { + if (try_set_owner_from(DEFLATER_MARKER, Self) == DEFLATER_MARKER) { // Cancelled the in-progress async deflation by changing owner from // DEFLATER_MARKER to Self. As part of the contended enter protocol, // contentions was incremented to a positive value before EnterI() @@ -659,8 +651,7 @@ if (TryLock(Self) > 0) break; - if (AsyncDeflateIdleMonitors && - try_set_owner_from(DEFLATER_MARKER, Self) == DEFLATER_MARKER) { + if (try_set_owner_from(DEFLATER_MARKER, Self) == DEFLATER_MARKER) { // Cancelled the in-progress async deflation by changing owner from // DEFLATER_MARKER to Self. As part of the contended enter protocol, // contentions was incremented to a positive value before EnterI() --- old/src/hotspot/share/runtime/objectMonitor.hpp 2020-07-02 15:15:00.000000000 -0400 +++ new/src/hotspot/share/runtime/objectMonitor.hpp 2020-07-02 15:15:00.000000000 -0400 @@ -175,7 +175,7 @@ jint _contentions; // Number of active contentions in enter(). It is used by is_busy() // along with other fields to determine if an ObjectMonitor can be // deflated. It is also used by the async deflation protocol. See - // ObjectSynchronizer::deflate_monitor() and deflate_monitor_using_JT(). + // ObjectSynchronizer::deflate_monitor_using_JT(). protected: ObjectWaiter* volatile _WaitSet; // LL of threads wait()ing on the monitor volatile jint _waiters; // number of waiting threads @@ -243,15 +243,11 @@ intptr_t is_busy() const { // TODO-FIXME: assert _owner == null implies _recursions = 0 intptr_t ret_code = _waiters | intptr_t(_cxq) | intptr_t(_EntryList); - if (!AsyncDeflateIdleMonitors) { - ret_code |= contentions() | intptr_t(_owner); - } else { - if (contentions() > 0) { - ret_code |= contentions(); - } - if (_owner != DEFLATER_MARKER) { - ret_code |= intptr_t(_owner); - } + if (contentions() > 0) { + ret_code |= contentions(); + } + if (_owner != DEFLATER_MARKER) { + ret_code |= intptr_t(_owner); } return ret_code; } @@ -374,15 +370,4 @@ void install_displaced_markword_in_object(const oop obj); }; -// Macro to use guarantee() for more strict AsyncDeflateIdleMonitors -// checks and assert() otherwise. -#define ADIM_guarantee(p, ...) \ - do { \ - if (AsyncDeflateIdleMonitors) { \ - guarantee(p, __VA_ARGS__); \ - } else { \ - assert(p, __VA_ARGS__); \ - } \ - } while (0) - #endif // SHARE_RUNTIME_OBJECTMONITOR_HPP --- old/src/hotspot/share/runtime/objectMonitor.inline.hpp 2020-07-02 15:15:01.000000000 -0400 +++ new/src/hotspot/share/runtime/objectMonitor.inline.hpp 2020-07-02 15:15:01.000000000 -0400 @@ -67,7 +67,7 @@ // Returns true if 'this' is being async deflated and false otherwise. inline bool ObjectMonitor::is_being_async_deflated() { - return AsyncDeflateIdleMonitors && contentions() < 0; + return contentions() < 0; } inline void ObjectMonitor::clear() { @@ -80,17 +80,15 @@ } inline void ObjectMonitor::clear_common() { - if (AsyncDeflateIdleMonitors) { - // Async deflation protocol uses the header, owner and contentions - // fields. While the ObjectMonitor being deflated is on the global - // free list, we leave those three fields alone; contentions < 0 - // will force any racing threads to retry. The header field is used - // by install_displaced_markword_in_object() to restore the object's - // header so we cannot check its value here. - guarantee(_owner == NULL || _owner == DEFLATER_MARKER, - "must be NULL or DEFLATER_MARKER: owner=" INTPTR_FORMAT, - p2i(_owner)); - } + // Async deflation protocol uses the header, owner and contentions + // fields. While the ObjectMonitor being deflated is on the global + // free list, we leave those three fields alone; contentions < 0 + // will force any racing threads to retry. The header field is used + // by install_displaced_markword_in_object() to restore the object's + // header so we cannot check its value here. + guarantee(_owner == NULL || _owner == DEFLATER_MARKER, + "must be NULL or DEFLATER_MARKER: owner=" INTPTR_FORMAT, + p2i(_owner)); assert(contentions() <= 0, "must not be positive: contentions=%d", contentions()); assert(_waiters == 0, "must be 0: waiters=%d", _waiters); assert(_recursions == 0, "must be 0: recursions=" INTX_FORMAT, _recursions); @@ -124,9 +122,11 @@ // Clear _owner field; current value must match old_value. inline void ObjectMonitor::release_clear_owner(void* old_value) { +#ifdef ASSERT void* prev = Atomic::load(&_owner); - ADIM_guarantee(prev == old_value, "unexpected prev owner=" INTPTR_FORMAT - ", expected=" INTPTR_FORMAT, p2i(prev), p2i(old_value)); +#endif + assert(prev == old_value, "unexpected prev owner=" INTPTR_FORMAT + ", expected=" INTPTR_FORMAT, p2i(prev), p2i(old_value)); Atomic::release_store(&_owner, (void*)NULL); log_trace(monitorinflation, owner)("release_clear_owner(): mid=" INTPTR_FORMAT ", old_value=" INTPTR_FORMAT, @@ -136,9 +136,11 @@ // Simply set _owner field to new_value; current value must match old_value. // (Simple means no memory sync needed.) inline void ObjectMonitor::set_owner_from(void* old_value, void* new_value) { +#ifdef ASSERT void* prev = Atomic::load(&_owner); - ADIM_guarantee(prev == old_value, "unexpected prev owner=" INTPTR_FORMAT - ", expected=" INTPTR_FORMAT, p2i(prev), p2i(old_value)); +#endif + assert(prev == old_value, "unexpected prev owner=" INTPTR_FORMAT + ", expected=" INTPTR_FORMAT, p2i(prev), p2i(old_value)); Atomic::store(&_owner, new_value); log_trace(monitorinflation, owner)("set_owner_from(): mid=" INTPTR_FORMAT ", old_value=" INTPTR_FORMAT @@ -150,10 +152,10 @@ // (Simple means no memory sync needed.) inline void ObjectMonitor::set_owner_from(void* old_value1, void* old_value2, void* new_value) { void* prev = Atomic::load(&_owner); - ADIM_guarantee(prev == old_value1 || prev == old_value2, - "unexpected prev owner=" INTPTR_FORMAT ", expected1=" - INTPTR_FORMAT " or expected2=" INTPTR_FORMAT, p2i(prev), - p2i(old_value1), p2i(old_value2)); + assert(prev == old_value1 || prev == old_value2, + "unexpected prev owner=" INTPTR_FORMAT ", expected1=" + INTPTR_FORMAT " or expected2=" INTPTR_FORMAT, p2i(prev), + p2i(old_value1), p2i(old_value2)); _owner = new_value; log_trace(monitorinflation, owner)("set_owner_from(old1=" INTPTR_FORMAT ", old2=" INTPTR_FORMAT "): mid=" @@ -165,9 +167,11 @@ // Simply set _owner field to self; current value must match basic_lock_p. inline void ObjectMonitor::set_owner_from_BasicLock(void* basic_lock_p, Thread* self) { +#ifdef ASSERT void* prev = Atomic::load(&_owner); - ADIM_guarantee(prev == basic_lock_p, "unexpected prev owner=" INTPTR_FORMAT - ", expected=" INTPTR_FORMAT, p2i(prev), p2i(basic_lock_p)); +#endif + assert(prev == basic_lock_p, "unexpected prev owner=" INTPTR_FORMAT + ", expected=" INTPTR_FORMAT, p2i(prev), p2i(basic_lock_p)); // Non-null owner field to non-null owner field is safe without // cmpxchg() as long as all readers can tolerate either flavor. Atomic::store(&_owner, self); --- old/src/hotspot/share/runtime/safepoint.cpp 2020-07-02 15:15:02.000000000 -0400 +++ new/src/hotspot/share/runtime/safepoint.cpp 2020-07-02 15:15:02.000000000 -0400 @@ -490,9 +490,6 @@ } bool SafepointSynchronize::is_cleanup_needed() { - // Need a cleanup safepoint if there are too many monitors in use - // and the monitor deflation needs to be done at a safepoint. - if (ObjectSynchronizer::is_safepoint_deflation_needed()) return true; // Need a safepoint if some inline cache buffers is non-empty if (!InlineCacheBuffer::is_empty()) return true; if (StringTable::needs_rehashing()) return true; @@ -500,51 +497,24 @@ return false; } -class ParallelSPCleanupThreadClosure : public ThreadClosure { -private: - DeflateMonitorCounters* _counters; - -public: - ParallelSPCleanupThreadClosure(DeflateMonitorCounters* counters) : - _counters(counters) {} - - void do_thread(Thread* thread) { - // deflate_thread_local_monitors() handles or requests deflation of - // this thread's idle monitors. If !AsyncDeflateIdleMonitors or if - // there is a special cleanup request, deflation is handled now. - // Otherwise, async deflation is requested via a flag. - ObjectSynchronizer::deflate_thread_local_monitors(thread, _counters); - } -}; - class ParallelSPCleanupTask : public AbstractGangTask { private: SubTasksDone _subtasks; - ParallelSPCleanupThreadClosure _cleanup_threads_cl; uint _num_workers; - DeflateMonitorCounters* _counters; public: - ParallelSPCleanupTask(uint num_workers, DeflateMonitorCounters* counters) : + ParallelSPCleanupTask(uint num_workers) : AbstractGangTask("Parallel Safepoint Cleanup"), _subtasks(SafepointSynchronize::SAFEPOINT_CLEANUP_NUM_TASKS), - _cleanup_threads_cl(ParallelSPCleanupThreadClosure(counters)), - _num_workers(num_workers), - _counters(counters) {} + _num_workers(num_workers) {} void work(uint worker_id) { uint64_t safepoint_id = SafepointSynchronize::safepoint_id(); - // All threads deflate monitors and mark nmethods (if necessary). - Threads::possibly_parallel_threads_do(true, &_cleanup_threads_cl); if (_subtasks.try_claim_task(SafepointSynchronize::SAFEPOINT_CLEANUP_DEFLATE_MONITORS)) { - const char* name = "deflating global idle monitors"; + const char* name = "deflating idle monitors"; EventSafepointCleanupTask event; TraceTime timer(name, TRACETIME_LOG(Info, safepoint, cleanup)); - // AsyncDeflateIdleMonitors only uses DeflateMonitorCounters - // when a special cleanup has been requested. - // Note: This logging output will include global idle monitor - // elapsed times, but not global idle monitor deflation count. - ObjectSynchronizer::do_safepoint_work(_counters); + ObjectSynchronizer::do_safepoint_work(); post_safepoint_cleanup_task_event(event, safepoint_id, name); } @@ -615,23 +585,17 @@ TraceTime timer("safepoint cleanup tasks", TRACETIME_LOG(Info, safepoint, cleanup)); - // Prepare for monitor deflation. - DeflateMonitorCounters deflate_counters; - ObjectSynchronizer::prepare_deflate_idle_monitors(&deflate_counters); - CollectedHeap* heap = Universe::heap(); assert(heap != NULL, "heap not initialized yet?"); WorkGang* cleanup_workers = heap->get_safepoint_workers(); if (cleanup_workers != NULL) { // Parallel cleanup using GC provided thread pool. uint num_cleanup_workers = cleanup_workers->active_workers(); - ParallelSPCleanupTask cleanup(num_cleanup_workers, &deflate_counters); - StrongRootsScope srs(num_cleanup_workers); + ParallelSPCleanupTask cleanup(num_cleanup_workers); cleanup_workers->run_task(&cleanup); } else { // Serial cleanup using VMThread. - ParallelSPCleanupTask cleanup(1, &deflate_counters); - StrongRootsScope srs(1); + ParallelSPCleanupTask cleanup(1); cleanup.work(0); } @@ -644,9 +608,6 @@ ClassLoaderDataGraph::walk_metadata_and_clean_metaspaces(); } - // Finish monitor deflation. - ObjectSynchronizer::finish_deflate_idle_monitors(&deflate_counters); - assert(InlineCacheBuffer::is_empty(), "should have cleaned up ICBuffer"); } --- old/src/hotspot/share/runtime/serviceThread.cpp 2020-07-02 15:15:03.000000000 -0400 +++ new/src/hotspot/share/runtime/serviceThread.cpp 2020-07-02 15:15:03.000000000 -0400 @@ -141,10 +141,9 @@ (deflate_idle_monitors = ObjectSynchronizer::is_async_deflation_needed()) ) == 0) { // Wait until notified that there is some work to do. - // If AsyncDeflateIdleMonitors, then we wait for - // GuaranteedSafepointInterval so that is_async_deflation_needed() - // is checked at the same interval. - ml.wait(AsyncDeflateIdleMonitors ? GuaranteedSafepointInterval : 0); + // We wait for GuaranteedSafepointInterval so that + // is_async_deflation_needed() is checked at the same interval. + ml.wait(GuaranteedSafepointInterval); } if (has_jvmti_events) { --- old/src/hotspot/share/runtime/synchronizer.cpp 2020-07-02 15:15:04.000000000 -0400 +++ new/src/hotspot/share/runtime/synchronizer.cpp 2020-07-02 15:15:04.000000000 -0400 @@ -491,15 +491,11 @@ if (mark.has_monitor()) { ObjectMonitor* const m = mark.monitor(); - if (AsyncDeflateIdleMonitors) { - // An async deflation can race us before we manage to make the - // ObjectMonitor busy by setting the owner below. If we detect - // that race we just bail out to the slow-path here. - if (m->object() == NULL) { - return false; - } - } else { - assert(m->object() == obj, "invariant"); + // An async deflation can race us before we manage to make the + // ObjectMonitor busy by setting the owner below. If we detect + // that race we just bail out to the slow-path here. + if (m->object() == NULL) { + return false; } Thread* const owner = (Thread *) m->_owner; @@ -1193,8 +1189,6 @@ } // CASE: inflated. Mark (tagged pointer) points to an ObjectMonitor. - // The Object:ObjectMonitor relationship is stable as long as we're - // not at a safepoint and AsyncDeflateIdleMonitors is false. if (mark.has_monitor()) { // The first stage of async deflation does not affect any field // used by this comparison so the ObjectMonitor* is usable here. @@ -1294,9 +1288,6 @@ } bool ObjectSynchronizer::is_async_deflation_needed() { - if (!AsyncDeflateIdleMonitors) { - return false; - } if (is_async_deflation_requested()) { // Async deflation request. return true; @@ -1313,48 +1304,33 @@ return false; } -bool ObjectSynchronizer::is_safepoint_deflation_needed() { - return !AsyncDeflateIdleMonitors && - monitors_used_above_threshold(); // Too many monitors in use. -} - bool ObjectSynchronizer::request_deflate_idle_monitors() { bool is_JavaThread = Thread::current()->is_Java_thread(); bool ret_code = false; - if (AsyncDeflateIdleMonitors) { - jlong last_time = last_async_deflation_time_ns(); - set_is_async_deflation_requested(true); - { - MonitorLocker ml(Service_lock, Mutex::_no_safepoint_check_flag); - ml.notify_all(); - } - const int N_CHECKS = 5; - for (int i = 0; i < N_CHECKS; i++) { // sleep for at most 5 seconds - if (last_async_deflation_time_ns() > last_time) { - log_info(monitorinflation)("Async Deflation happened after %d check(s).", i); - ret_code = true; - break; - } - if (is_JavaThread) { - // JavaThread has to honor the blocking protocol. - ThreadBlockInVM tbivm(JavaThread::current()); - os::naked_short_sleep(999); // sleep for almost 1 second - } else { - os::naked_short_sleep(999); // sleep for almost 1 second - } + jlong last_time = last_async_deflation_time_ns(); + set_is_async_deflation_requested(true); + { + MonitorLocker ml(Service_lock, Mutex::_no_safepoint_check_flag); + ml.notify_all(); + } + const int N_CHECKS = 5; + for (int i = 0; i < N_CHECKS; i++) { // sleep for at most 5 seconds + if (last_async_deflation_time_ns() > last_time) { + log_info(monitorinflation)("Async Deflation happened after %d check(s).", i); + ret_code = true; + break; } - if (!ret_code) { - log_info(monitorinflation)("Async Deflation DID NOT happen after %d checks.", N_CHECKS); + if (is_JavaThread) { + // JavaThread has to honor the blocking protocol. + ThreadBlockInVM tbivm(JavaThread::current()); + os::naked_short_sleep(999); // sleep for almost 1 second + } else { + os::naked_short_sleep(999); // sleep for almost 1 second } - } else { - // Only need to force this safepoint if we are not using async - // deflation. The VMThread won't call this function before the - // final safepoint if we are not using async deflation so we - // don't have to reason about the VMThread executing a VM-op here. - VM_ForceSafepoint force_safepoint_op; - VMThread::execute(&force_safepoint_op); - ret_code = true; + } + if (!ret_code) { + log_info(monitorinflation)("Async Deflation DID NOT happen after %d checks.", N_CHECKS); } return ret_code; @@ -1447,23 +1423,21 @@ break; // No more are available. } guarantee(take->object() == NULL, "invariant"); - if (AsyncDeflateIdleMonitors) { - // We allowed 3 field values to linger during async deflation. - // Clear or restore them as appropriate. - take->set_header(markWord::zero()); - // DEFLATER_MARKER is the only non-NULL value we should see here. - take->try_set_owner_from(DEFLATER_MARKER, NULL); - if (take->contentions() < 0) { - // Add back max_jint to restore the contentions field to its - // proper value. - take->add_to_contentions(max_jint); + // We allowed 3 field values to linger during async deflation. + // Clear or restore them as appropriate. + take->set_header(markWord::zero()); + // DEFLATER_MARKER is the only non-NULL value we should see here. + take->try_set_owner_from(DEFLATER_MARKER, NULL); + if (take->contentions() < 0) { + // Add back max_jint to restore the contentions field to its + // proper value. + take->add_to_contentions(max_jint); #ifdef ASSERT - jint l_contentions = take->contentions(); + jint l_contentions = take->contentions(); #endif - assert(l_contentions >= 0, "must not be negative: l_contentions=%d, contentions=%d", - l_contentions, take->contentions()); - } + assert(l_contentions >= 0, "must not be negative: l_contentions=%d, contentions=%d", + l_contentions, take->contentions()); } take->Recycle(); // Since we're taking from the global free-list, take must be Free. @@ -1529,8 +1503,8 @@ // // Key constraint: all ObjectMonitors on a thread's free list and the global // free list must have their object field set to null. This prevents the -// scavenger -- deflate_monitor_list() or deflate_monitor_list_using_JT() -// -- from reclaiming them while we are trying to release them. +// scavenger -- deflate_monitor_list_using_JT() -- from reclaiming them +// while we are trying to release them. void ObjectSynchronizer::om_release(Thread* self, ObjectMonitor* m, bool from_per_thread_alloc) { @@ -1639,15 +1613,13 @@ // // We currently call om_flush() from Threads::remove() before the // thread has been excised from the thread list and is no longer a -// mutator. This means that om_flush() cannot run concurrently with -// a safepoint and interleave with deflate_idle_monitors(). In -// particular, this ensures that the thread's in-use monitors are -// scanned by a GC safepoint, either via Thread::oops_do() (before -// om_flush() is called) or via ObjectSynchronizer::oops_do() (after -// om_flush() is called). +// mutator. In particular, this ensures that the thread's in-use +// monitors are scanned by a GC safepoint, either via Thread::oops_do() +// (before om_flush() is called) or via ObjectSynchronizer::oops_do() +// (after om_flush() is called). // -// With AsyncDeflateIdleMonitors, deflate_global_idle_monitors_using_JT() -// and deflate_per_thread_idle_monitors_using_JT() (in another thread) can +// deflate_global_idle_monitors_using_JT() and +// deflate_per_thread_idle_monitors_using_JT() (in another thread) can // run at the same time as om_flush() so we have to follow a careful // protocol to prevent list corruption. @@ -1701,9 +1673,11 @@ cur_om = unmarked_next(cur_om); } guarantee(in_use_tail != NULL, "invariant"); +#ifdef ASSERT int l_om_in_use_count = Atomic::load(&self->om_in_use_count); - ADIM_guarantee(l_om_in_use_count == in_use_count, "in-use counts don't match: " - "l_om_in_use_count=%d, in_use_count=%d", l_om_in_use_count, in_use_count); +#endif + assert(l_om_in_use_count == in_use_count, "in-use counts don't match: " + "l_om_in_use_count=%d, in_use_count=%d", l_om_in_use_count, in_use_count); Atomic::store(&self->om_in_use_count, 0); // Clear the in-use list head (which also unlocks it): Atomic::store(&self->om_in_use_list, (ObjectMonitor*)NULL); @@ -1744,9 +1718,11 @@ } } guarantee(free_tail != NULL, "invariant"); +#ifdef ASSERT int l_om_free_count = Atomic::load(&self->om_free_count); - ADIM_guarantee(l_om_free_count == free_count, "free counts don't match: " - "l_om_free_count=%d, free_count=%d", l_om_free_count, free_count); +#endif + assert(l_om_free_count == free_count, "free counts don't match: " + "l_om_free_count=%d, free_count=%d", l_om_free_count, free_count); Atomic::store(&self->om_free_count, 0); Atomic::store(&self->om_free_list, (ObjectMonitor*)NULL); om_unlock(free_list); @@ -1825,7 +1801,6 @@ ObjectMonitor* inf = mark.monitor(); markWord dmw = inf->header(); assert(dmw.is_neutral(), "invariant: header=" INTPTR_FORMAT, dmw.value()); - assert(AsyncDeflateIdleMonitors || inf->object() == object, "invariant"); assert(ObjectSynchronizer::verify_objmon_isinpool(inf), "monitor is invalid"); return inf; } @@ -1911,7 +1886,7 @@ markWord dmw = mark.displaced_mark_helper(); // Catch if the object's header is not neutral (not locked and // not marked is what we care about here). - ADIM_guarantee(dmw.is_neutral(), "invariant: header=" INTPTR_FORMAT, dmw.value()); + assert(dmw.is_neutral(), "invariant: header=" INTPTR_FORMAT, dmw.value()); // Setup monitor fields to proper values -- prepare the monitor m->set_header(dmw); @@ -1921,11 +1896,7 @@ // Note that a thread can inflate an object // that it has stack-locked -- as might happen in wait() -- directly // with CAS. That is, we can avoid the xchg-NULL .... ST idiom. - if (AsyncDeflateIdleMonitors) { - m->set_owner_from(NULL, DEFLATER_MARKER, mark.locker()); - } else { - m->set_owner_from(NULL, mark.locker()); - } + m->set_owner_from(NULL, DEFLATER_MARKER, mark.locker()); m->set_object(object); // TODO-FIXME: assert BasicLock->dhw != 0. @@ -1965,15 +1936,13 @@ // Catch if the object's header is not neutral (not locked and // not marked is what we care about here). - ADIM_guarantee(mark.is_neutral(), "invariant: header=" INTPTR_FORMAT, mark.value()); + assert(mark.is_neutral(), "invariant: header=" INTPTR_FORMAT, mark.value()); ObjectMonitor* m = om_alloc(self); // prepare m for installation - set monitor to initial state m->Recycle(); m->set_header(mark); - if (AsyncDeflateIdleMonitors) { - // DEFLATER_MARKER is the only non-NULL value we should see here. - m->try_set_owner_from(DEFLATER_MARKER, NULL); - } + // DEFLATER_MARKER is the only non-NULL value we should see here. + m->try_set_owner_from(DEFLATER_MARKER, NULL); m->set_object(object); m->_Responsible = NULL; m->_SpinDuration = ObjectMonitor::Knob_SpinLimit; // consider: keep metastats by type/class @@ -2013,45 +1982,11 @@ } -// We maintain a list of in-use monitors for each thread. -// -// For safepoint based deflation: -// deflate_thread_local_monitors() scans a single thread's in-use list, while -// deflate_idle_monitors() scans only a global list of in-use monitors which -// is populated only as a thread dies (see om_flush()). -// -// These operations are called at all safepoints, immediately after mutators -// are stopped, but before any objects have moved. Collectively they traverse -// the population of in-use monitors, deflating where possible. The scavenged -// monitors are returned to the global monitor free list. -// -// Beware that we scavenge at *every* stop-the-world point. Having a large -// number of monitors in-use could negatively impact performance. We also want -// to minimize the total # of monitors in circulation, as they incur a small -// footprint penalty. -// -// Perversely, the heap size -- and thus the STW safepoint rate -- -// typically drives the scavenge rate. Large heaps can mean infrequent GC, -// which in turn can mean large(r) numbers of ObjectMonitors in circulation. -// This is an unfortunate aspect of this design. -// -// For async deflation: -// If a special deflation request is made, then the safepoint based -// deflation mechanism is used. Otherwise, an async deflation request -// is registered with the ServiceThread and it is notified. - -void ObjectSynchronizer::do_safepoint_work(DeflateMonitorCounters* counters) { +// An async deflation request is registered with the ServiceThread +// and it is notified. +void ObjectSynchronizer::do_safepoint_work() { assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); - // The per-thread in-use lists are handled in - // ParallelSPCleanupThreadClosure::do_thread(). - - if (!AsyncDeflateIdleMonitors) { - // Use the older mechanism for the global in-use list. - ObjectSynchronizer::deflate_idle_monitors(counters); - return; - } - log_debug(monitorinflation)("requesting async deflation of idle monitors."); // Request deflation of idle monitors by the ServiceThread: set_is_async_deflation_requested(true); @@ -2061,85 +1996,10 @@ if (log_is_enabled(Debug, monitorinflation)) { // exit_globals()'s call to audit_and_print_stats() is done // at the Info level and not at a safepoint. - // For safepoint based deflation, audit_and_print_stats() is called - // in ObjectSynchronizer::finish_deflate_idle_monitors() at the - // Debug level at a safepoint. ObjectSynchronizer::audit_and_print_stats(false /* on_exit */); } } -// Deflate a single monitor if not in-use -// Return true if deflated, false if in-use -bool ObjectSynchronizer::deflate_monitor(ObjectMonitor* mid, oop obj, - ObjectMonitor** free_head_p, - ObjectMonitor** free_tail_p) { - bool deflated; - // Normal case ... The monitor is associated with obj. - const markWord mark = obj->mark(); - guarantee(mark == markWord::encode(mid), "should match: mark=" - INTPTR_FORMAT ", encoded mid=" INTPTR_FORMAT, mark.value(), - markWord::encode(mid).value()); - // Make sure that mark.monitor() and markWord::encode() agree: - guarantee(mark.monitor() == mid, "should match: monitor()=" INTPTR_FORMAT - ", mid=" INTPTR_FORMAT, p2i(mark.monitor()), p2i(mid)); - const markWord dmw = mid->header(); - guarantee(dmw.is_neutral(), "invariant: header=" INTPTR_FORMAT, dmw.value()); - - if (mid->is_busy()) { - // Easy checks are first - the ObjectMonitor is busy so no deflation. - deflated = false; - } else { - // Deflate the monitor if it is no longer being used - // It's idle - scavenge and return to the global free list - // plain old deflation ... - if (log_is_enabled(Trace, monitorinflation)) { - ResourceMark rm; - log_trace(monitorinflation)("deflate_monitor: " - "object=" INTPTR_FORMAT ", mark=" - INTPTR_FORMAT ", type='%s'", p2i(obj), - mark.value(), obj->klass()->external_name()); - } - - // Restore the header back to obj - obj->release_set_mark(dmw); - if (AsyncDeflateIdleMonitors) { - // clear() expects the owner field to be NULL. - // DEFLATER_MARKER is the only non-NULL value we should see here. - mid->try_set_owner_from(DEFLATER_MARKER, NULL); - } - mid->clear(); - - assert(mid->object() == NULL, "invariant: object=" INTPTR_FORMAT, - p2i(mid->object())); - assert(mid->is_free(), "invariant"); - - // Move the deflated ObjectMonitor to the working free list - // defined by free_head_p and free_tail_p. - if (*free_head_p == NULL) *free_head_p = mid; - if (*free_tail_p != NULL) { - // We append to the list so the caller can use mid->_next_om - // to fix the linkages in its context. - ObjectMonitor* prevtail = *free_tail_p; - // Should have been cleaned up by the caller: - // Note: Should not have to lock prevtail here since we're at a - // safepoint and ObjectMonitors on the local free list should - // not be accessed in parallel. -#ifdef ASSERT - ObjectMonitor* l_next_om = prevtail->next_om(); -#endif - assert(l_next_om == NULL, "must be NULL: _next_om=" INTPTR_FORMAT, p2i(l_next_om)); - prevtail->set_next_om(mid); - } - *free_tail_p = mid; - // At this point, mid->_next_om still refers to its current - // value and another ObjectMonitor's _next_om field still - // refers to this ObjectMonitor. Those linkages have to be - // cleaned up by the caller who has the complete context. - deflated = true; - } - return deflated; -} - // Deflate the specified ObjectMonitor if not in-use using a JavaThread. // Returns true if it was deflated and false otherwise. // @@ -2156,7 +2016,6 @@ bool ObjectSynchronizer::deflate_monitor_using_JT(ObjectMonitor* mid, ObjectMonitor** free_head_p, ObjectMonitor** free_tail_p) { - assert(AsyncDeflateIdleMonitors, "sanity check"); assert(Thread::current()->is_Java_thread(), "precondition"); // A newly allocated ObjectMonitor should not be seen here so we // avoid an endless inflate/deflate cycle. @@ -2262,56 +2121,6 @@ return true; // Success, ObjectMonitor has been deflated. } -// Walk a given monitor list, and deflate idle monitors. -// The given list could be a per-thread list or a global list. -// -// In the case of parallel processing of thread local monitor lists, -// work is done by Threads::parallel_threads_do() which ensures that -// each Java thread is processed by exactly one worker thread, and -// thus avoid conflicts that would arise when worker threads would -// process the same monitor lists concurrently. -// -// See also ParallelSPCleanupTask and -// SafepointSynchronize::do_cleanup_tasks() in safepoint.cpp and -// Threads::parallel_java_threads_do() in thread.cpp. -int ObjectSynchronizer::deflate_monitor_list(ObjectMonitor** list_p, - int* count_p, - ObjectMonitor** free_head_p, - ObjectMonitor** free_tail_p) { - ObjectMonitor* cur_mid_in_use = NULL; - ObjectMonitor* mid = NULL; - ObjectMonitor* next = NULL; - int deflated_count = 0; - - // This list walk executes at a safepoint and does not race with any - // other list walkers. - - for (mid = Atomic::load(list_p); mid != NULL; mid = next) { - next = unmarked_next(mid); - oop obj = (oop) mid->object(); - if (obj != NULL && deflate_monitor(mid, obj, free_head_p, free_tail_p)) { - // Deflation succeeded and already updated free_head_p and - // free_tail_p as needed. Finish the move to the local free list - // by unlinking mid from the global or per-thread in-use list. - if (cur_mid_in_use == NULL) { - // mid is the list head so switch the list head to next: - Atomic::store(list_p, next); - } else { - // Switch cur_mid_in_use's next field to next: - cur_mid_in_use->set_next_om(next); - } - // At this point mid is disconnected from the in-use list. - deflated_count++; - Atomic::dec(count_p); - // mid is current tail in the free_head_p list so NULL terminate it: - mid->set_next_om(NULL); - } else { - cur_mid_in_use = mid; - } - } - return deflated_count; -} - // Walk a given ObjectMonitor list and deflate idle ObjectMonitors using // a JavaThread. Returns the number of deflated ObjectMonitors. The given // list could be a per-thread in-use list or the global in-use list. @@ -2323,7 +2132,6 @@ ObjectMonitor** free_head_p, ObjectMonitor** free_tail_p, ObjectMonitor** saved_mid_in_use_p) { - assert(AsyncDeflateIdleMonitors, "sanity check"); JavaThread* self = JavaThread::current(); ObjectMonitor* cur_mid_in_use = NULL; @@ -2453,75 +2261,6 @@ return deflated_count; } -void ObjectSynchronizer::prepare_deflate_idle_monitors(DeflateMonitorCounters* counters) { - counters->n_in_use = 0; // currently associated with objects - counters->n_in_circulation = 0; // extant - counters->n_scavenged = 0; // reclaimed (global and per-thread) - counters->per_thread_scavenged = 0; // per-thread scavenge total - counters->per_thread_times = 0.0; // per-thread scavenge times -} - -void ObjectSynchronizer::deflate_idle_monitors(DeflateMonitorCounters* counters) { - assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); - - if (AsyncDeflateIdleMonitors) { - // Nothing to do when global idle ObjectMonitors are deflated using - // a JavaThread. - return; - } - - bool deflated = false; - - ObjectMonitor* free_head_p = NULL; // Local SLL of scavenged monitors - ObjectMonitor* free_tail_p = NULL; - elapsedTimer timer; - - if (log_is_enabled(Info, monitorinflation)) { - timer.start(); - } - - // Note: the thread-local monitors lists get deflated in - // a separate pass. See deflate_thread_local_monitors(). - - // For moribund threads, scan om_list_globals._in_use_list - int deflated_count = 0; - if (Atomic::load(&om_list_globals._in_use_list) != NULL) { - // Update n_in_circulation before om_list_globals._in_use_count is - // updated by deflation. - Atomic::add(&counters->n_in_circulation, - Atomic::load(&om_list_globals._in_use_count)); - - deflated_count = deflate_monitor_list(&om_list_globals._in_use_list, - &om_list_globals._in_use_count, - &free_head_p, &free_tail_p); - Atomic::add(&counters->n_in_use, Atomic::load(&om_list_globals._in_use_count)); - } - - if (free_head_p != NULL) { - // Move the deflated ObjectMonitors back to the global free list. - guarantee(free_tail_p != NULL && deflated_count > 0, "invariant"); -#ifdef ASSERT - ObjectMonitor* l_next_om = free_tail_p->next_om(); -#endif - assert(l_next_om == NULL, "must be NULL: _next_om=" INTPTR_FORMAT, p2i(l_next_om)); - prepend_list_to_global_free_list(free_head_p, free_tail_p, deflated_count); - Atomic::add(&counters->n_scavenged, deflated_count); - } - timer.stop(); - - LogStreamHandle(Debug, monitorinflation) lsh_debug; - LogStreamHandle(Info, monitorinflation) lsh_info; - LogStream* ls = NULL; - if (log_is_enabled(Debug, monitorinflation)) { - ls = &lsh_debug; - } else if (deflated_count != 0 && log_is_enabled(Info, monitorinflation)) { - ls = &lsh_info; - } - if (ls != NULL) { - ls->print_cr("deflating global idle monitors, %3.7f secs, %d monitors", timer.seconds(), deflated_count); - } -} - class HandshakeForDeflation : public HandshakeClosure { public: HandshakeForDeflation() : HandshakeClosure("HandshakeForDeflation") {} @@ -2533,8 +2272,6 @@ }; void ObjectSynchronizer::deflate_idle_monitors_using_JT() { - assert(AsyncDeflateIdleMonitors, "sanity check"); - // Deflate any global idle monitors. deflate_global_idle_monitors_using_JT(); @@ -2568,7 +2305,7 @@ // (or a safepoint) for safety. ObjectMonitor* list = Atomic::load(&om_list_globals._wait_list); - ADIM_guarantee(list != NULL, "om_list_globals._wait_list must not be NULL"); + assert(list != NULL, "om_list_globals._wait_list must not be NULL"); int count = Atomic::load(&om_list_globals._wait_count); Atomic::store(&om_list_globals._wait_count, 0); Atomic::store(&om_list_globals._wait_list, (ObjectMonitor*)NULL); @@ -2576,13 +2313,17 @@ // Find the tail for prepend_list_to_common(). No need to mark // ObjectMonitors for this list walk since only the deflater // thread manages the wait list. +#ifdef ASSERT int l_count = 0; +#endif ObjectMonitor* tail = NULL; for (ObjectMonitor* n = list; n != NULL; n = unmarked_next(n)) { tail = n; +#ifdef ASSERT l_count++; +#endif } - ADIM_guarantee(count == l_count, "count=%d != l_count=%d", count, l_count); + assert(count == l_count, "count=%d != l_count=%d", count, l_count); // Will execute a safepoint if !ThreadLocalHandshakes: HandshakeForDeflation hfd_hc; @@ -2598,7 +2339,6 @@ // Deflate global idle ObjectMonitors using a JavaThread. // void ObjectSynchronizer::deflate_global_idle_monitors_using_JT() { - assert(AsyncDeflateIdleMonitors, "sanity check"); assert(Thread::current()->is_Java_thread(), "precondition"); JavaThread* self = JavaThread::current(); @@ -2608,7 +2348,6 @@ // Deflate the specified JavaThread's idle ObjectMonitors using a JavaThread. // void ObjectSynchronizer::deflate_per_thread_idle_monitors_using_JT(JavaThread* target) { - assert(AsyncDeflateIdleMonitors, "sanity check"); assert(Thread::current()->is_Java_thread(), "precondition"); deflate_common_idle_monitors_using_JT(false /* !is_global */, target); @@ -2711,94 +2450,6 @@ } } -void ObjectSynchronizer::finish_deflate_idle_monitors(DeflateMonitorCounters* counters) { - // Report the cumulative time for deflating each thread's idle - // monitors. Note: if the work is split among more than one - // worker thread, then the reported time will likely be more - // than a beginning to end measurement of the phase. - log_info(safepoint, cleanup)("deflating per-thread idle monitors, %3.7f secs, monitors=%d", counters->per_thread_times, counters->per_thread_scavenged); - - if (AsyncDeflateIdleMonitors) { - // Nothing to do when idle ObjectMonitors are deflated using - // a JavaThread. - return; - } - - if (log_is_enabled(Debug, monitorinflation)) { - // exit_globals()'s call to audit_and_print_stats() is done - // at the Info level and not at a safepoint. - // For async deflation, audit_and_print_stats() is called in - // ObjectSynchronizer::do_safepoint_work() at the Debug level - // at a safepoint. - ObjectSynchronizer::audit_and_print_stats(false /* on_exit */); - } else if (log_is_enabled(Info, monitorinflation)) { - log_info(monitorinflation)("global_population=%d, global_in_use_count=%d, " - "global_free_count=%d, global_wait_count=%d", - Atomic::load(&om_list_globals._population), - Atomic::load(&om_list_globals._in_use_count), - Atomic::load(&om_list_globals._free_count), - Atomic::load(&om_list_globals._wait_count)); - } - - OM_PERFDATA_OP(Deflations, inc(counters->n_scavenged)); - OM_PERFDATA_OP(MonExtant, set_value(counters->n_in_circulation)); - - GVars.stw_random = os::random(); - GVars.stw_cycle++; -} - -void ObjectSynchronizer::deflate_thread_local_monitors(Thread* thread, DeflateMonitorCounters* counters) { - assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); - - if (AsyncDeflateIdleMonitors) { - // Nothing to do when per-thread idle ObjectMonitors are deflated - // using a JavaThread. - return; - } - - ObjectMonitor* free_head_p = NULL; // Local SLL of scavenged monitors - ObjectMonitor* free_tail_p = NULL; - elapsedTimer timer; - - if (log_is_enabled(Info, safepoint, cleanup) || - log_is_enabled(Info, monitorinflation)) { - timer.start(); - } - - // Update n_in_circulation before om_in_use_count is updated by deflation. - Atomic::add(&counters->n_in_circulation, Atomic::load(&thread->om_in_use_count)); - - int deflated_count = deflate_monitor_list(&thread->om_in_use_list, &thread->om_in_use_count, &free_head_p, &free_tail_p); - Atomic::add(&counters->n_in_use, Atomic::load(&thread->om_in_use_count)); - - if (free_head_p != NULL) { - // Move the deflated ObjectMonitors back to the global free list. - guarantee(free_tail_p != NULL && deflated_count > 0, "invariant"); -#ifdef ASSERT - ObjectMonitor* l_next_om = free_tail_p->next_om(); -#endif - assert(l_next_om == NULL, "must be NULL: _next_om=" INTPTR_FORMAT, p2i(l_next_om)); - prepend_list_to_global_free_list(free_head_p, free_tail_p, deflated_count); - Atomic::add(&counters->n_scavenged, deflated_count); - Atomic::add(&counters->per_thread_scavenged, deflated_count); - } - - timer.stop(); - counters->per_thread_times += timer.seconds(); - - LogStreamHandle(Debug, monitorinflation) lsh_debug; - LogStreamHandle(Info, monitorinflation) lsh_info; - LogStream* ls = NULL; - if (log_is_enabled(Debug, monitorinflation)) { - ls = &lsh_debug; - } else if (deflated_count != 0 && log_is_enabled(Info, monitorinflation)) { - ls = &lsh_info; - } - if (ls != NULL) { - ls->print_cr("jt=" INTPTR_FORMAT ": deflating per-thread idle monitors, %3.7f secs, %d monitors", p2i(thread), timer.seconds(), deflated_count); - } -} - // Monitor cleanup on JavaThread::exit // Iterate through monitor cache and attempt to release thread's monitors @@ -2883,8 +2534,6 @@ // aid; pass 'true' for the 'on_exit' parameter to have in-use monitor // details logged at the Info level and 'false' for the 'on_exit' // parameter to have in-use monitor details logged at the Trace level. -// deflate_monitor_list() no longer uses spin-locking so be careful -// when adding audit_and_print_stats() calls at a safepoint. // void ObjectSynchronizer::audit_and_print_stats(bool on_exit) { assert(on_exit || SafepointSynchronize::is_at_safepoint(), "invariant"); @@ -2983,11 +2632,6 @@ "field: _header=" INTPTR_FORMAT, p2i(jt), p2i(n), n->header().value()); *error_cnt_p = *error_cnt_p + 1; - } else if (!AsyncDeflateIdleMonitors) { - out->print_cr("ERROR: monitor=" INTPTR_FORMAT ": free global monitor " - "must have NULL _header field: _header=" INTPTR_FORMAT, - p2i(n), n->header().value()); - *error_cnt_p = *error_cnt_p + 1; } } if (n->object() != NULL) { --- old/src/hotspot/share/runtime/synchronizer.hpp 2020-07-02 15:15:05.000000000 -0400 +++ new/src/hotspot/share/runtime/synchronizer.hpp 2020-07-02 15:15:05.000000000 -0400 @@ -42,14 +42,6 @@ typedef PaddedEnd PaddedObjectMonitor; -struct DeflateMonitorCounters { - volatile int n_in_use; // currently associated with objects - volatile int n_in_circulation; // extant - volatile int n_scavenged; // reclaimed (global and per-thread) - volatile int per_thread_scavenged; // per-thread scavenge total - double per_thread_times; // per-thread scavenge times -}; - class ObjectSynchronizer : AllStatic { friend class VMStructs; public: @@ -131,20 +123,11 @@ // GC: we current use aggressive monitor deflation policy // Basically we deflate all monitors that are not busy. // An adaptive profile-based deflation policy could be used if needed - static void deflate_idle_monitors(DeflateMonitorCounters* counters); static void deflate_idle_monitors_using_JT(); static void deflate_global_idle_monitors_using_JT(); static void deflate_per_thread_idle_monitors_using_JT(JavaThread* target); static void deflate_common_idle_monitors_using_JT(bool is_global, JavaThread* target); - static void deflate_thread_local_monitors(Thread* thread, DeflateMonitorCounters* counters); - static void prepare_deflate_idle_monitors(DeflateMonitorCounters* counters); - static void finish_deflate_idle_monitors(DeflateMonitorCounters* counters); - - // For a given monitor list: global or per-thread, deflate idle monitors - static int deflate_monitor_list(ObjectMonitor** list_p, - int* count_p, - ObjectMonitor** free_head_p, - ObjectMonitor** free_tail_p); + // For a given in-use monitor list: global or per-thread, deflate idle // monitors using a JavaThread. static int deflate_monitor_list_using_JT(ObjectMonitor** list_p, @@ -152,14 +135,10 @@ ObjectMonitor** free_head_p, ObjectMonitor** free_tail_p, ObjectMonitor** saved_mid_in_use_p); - static bool deflate_monitor(ObjectMonitor* mid, oop obj, - ObjectMonitor** free_head_p, - ObjectMonitor** free_tail_p); static bool deflate_monitor_using_JT(ObjectMonitor* mid, ObjectMonitor** free_head_p, ObjectMonitor** free_tail_p); static bool is_async_deflation_needed(); - static bool is_safepoint_deflation_needed(); static bool is_async_deflation_requested() { return _is_async_deflation_requested; } static jlong last_async_deflation_time_ns() { return _last_async_deflation_time_ns; } static bool request_deflate_idle_monitors(); // for whitebox test support and VM exit logging @@ -191,7 +170,7 @@ static int log_monitor_list_counts(outputStream * out); static int verify_objmon_isinpool(ObjectMonitor *addr) PRODUCT_RETURN0; - static void do_safepoint_work(DeflateMonitorCounters* counters); + static void do_safepoint_work(); private: friend class SynchronizerTest; --- old/src/hotspot/share/runtime/vmOperations.cpp 2020-07-02 15:15:06.000000000 -0400 +++ new/src/hotspot/share/runtime/vmOperations.cpp 2020-07-02 15:15:05.000000000 -0400 @@ -431,10 +431,10 @@ } bool VM_Exit::doit_prologue() { - if (AsyncDeflateIdleMonitors && log_is_enabled(Info, monitorinflation)) { - // AsyncDeflateIdleMonitors does a special deflation in order - // to reduce the in-use monitor population that is reported by - // ObjectSynchronizer::log_in_use_monitor_details() at VM exit. + if (log_is_enabled(Info, monitorinflation)) { + // Do a deflation in order to reduce the in-use monitor population + // that is reported by ObjectSynchronizer::log_in_use_monitor_details() + // at VM exit. ObjectSynchronizer::request_deflate_idle_monitors(); } return true; --- old/src/hotspot/share/runtime/vmThread.cpp 2020-07-02 15:15:07.000000000 -0400 +++ new/src/hotspot/share/runtime/vmThread.cpp 2020-07-02 15:15:07.000000000 -0400 @@ -260,10 +260,10 @@ assert(should_terminate(), "termination flag must be set"); } - if (AsyncDeflateIdleMonitors && log_is_enabled(Info, monitorinflation)) { - // AsyncDeflateIdleMonitors does a special deflation in order - // to reduce the in-use monitor population that is reported by - // ObjectSynchronizer::log_in_use_monitor_details() at VM exit. + if (log_is_enabled(Info, monitorinflation)) { + // Do a deflation in order to reduce the in-use monitor population + // that is reported by ObjectSynchronizer::log_in_use_monitor_details() + // at VM exit. ObjectSynchronizer::request_deflate_idle_monitors(); } --- old/src/hotspot/share/services/threadService.cpp 2020-07-02 15:15:08.000000000 -0400 +++ new/src/hotspot/share/services/threadService.cpp 2020-07-02 15:15:07.000000000 -0400 @@ -222,13 +222,11 @@ if (wait_obj != NULL) { // thread is doing an Object.wait() call obj = (oop) wait_obj->object(); - assert(AsyncDeflateIdleMonitors || obj != NULL, "Object.wait() should have an object"); } else { ObjectMonitor *enter_obj = thread->current_pending_monitor(); if (enter_obj != NULL) { // thread is trying to enter() an ObjectMonitor. obj = (oop) enter_obj->object(); - assert(AsyncDeflateIdleMonitors || obj != NULL, "ObjectMonitor should have an associated object!"); } } --- old/test/hotspot/gtest/oops/test_markWord.cpp 2020-07-02 15:15:08.000000000 -0400 +++ new/test/hotspot/gtest/oops/test_markWord.cpp 2020-07-02 15:15:08.000000000 -0400 @@ -138,19 +138,5 @@ assert_test_pattern(h_obj, "monitor"); done.wait_with_safepoint_check(THREAD); // wait till the thread is done. } - - if (!AsyncDeflateIdleMonitors) { - // With AsyncDeflateIdleMonitors, the collect() call below - // does not guarantee monitor deflation. - // Make the object older. Not all GCs use this field. - Universe::heap()->collect(GCCause::_java_lang_system_gc); - if (UseParallelGC) { - assert_test_pattern(h_obj, "is_neutral no_hash age 1"); - } - - // Hash the object then print it. - intx hash = h_obj->identity_hash(); - assert_test_pattern(h_obj, "is_neutral hash=0x"); - } } #endif // PRODUCT --- old/test/hotspot/jtreg/runtime/logging/SafepointCleanupTest.java 2020-07-02 15:15:09.000000000 -0400 +++ new/test/hotspot/jtreg/runtime/logging/SafepointCleanupTest.java 2020-07-02 15:15:09.000000000 -0400 @@ -29,23 +29,17 @@ * @modules java.base/jdk.internal.misc * java.management * @run driver SafepointCleanupTest - * @run driver SafepointCleanupTest -XX:+AsyncDeflateIdleMonitors */ import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; public class SafepointCleanupTest { - static final String ASYNC_DISABLE_OPTION = "-XX:-AsyncDeflateIdleMonitors"; - static final String ASYNC_ENABLE_OPTION = "-XX:+AsyncDeflateIdleMonitors"; - static final String UNLOCK_DIAG_OPTION = "-XX:+UnlockDiagnosticVMOptions"; - static void analyzeOutputOn(ProcessBuilder pb) throws Exception { OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldContain("[safepoint,cleanup]"); output.shouldContain("safepoint cleanup tasks"); - output.shouldContain("deflating global idle monitors"); - output.shouldContain("deflating per-thread idle monitors"); + output.shouldContain("deflating idle monitors"); output.shouldContain("updating inline caches"); output.shouldContain("compilation policy safepoint handler"); output.shouldHaveExitValue(0); @@ -58,40 +52,19 @@ } public static void main(String[] args) throws Exception { - String async_option; - if (args.length == 0) { - // By default test deflating idle monitors at a safepoint. - async_option = ASYNC_DISABLE_OPTION; - } else { - async_option = args[0]; - } - if (!async_option.equals(ASYNC_DISABLE_OPTION) && - !async_option.equals(ASYNC_ENABLE_OPTION)) { - throw new RuntimeException("Unknown async_option value: '" - + async_option + "'"); - } - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:safepoint+cleanup=info", - UNLOCK_DIAG_OPTION, - async_option, InnerClass.class.getName()); analyzeOutputOn(pb); pb = ProcessTools.createJavaProcessBuilder("-XX:+TraceSafepointCleanupTime", - UNLOCK_DIAG_OPTION, - async_option, InnerClass.class.getName()); analyzeOutputOn(pb); pb = ProcessTools.createJavaProcessBuilder("-Xlog:safepoint+cleanup=off", - UNLOCK_DIAG_OPTION, - async_option, InnerClass.class.getName()); analyzeOutputOff(pb); pb = ProcessTools.createJavaProcessBuilder("-XX:-TraceSafepointCleanupTime", - UNLOCK_DIAG_OPTION, - async_option, InnerClass.class.getName()); analyzeOutputOff(pb); }