< prev index next >

src/hotspot/share/runtime/synchronizer.cpp

Print this page
rev 58110 : v2.09a with 8235795, 8235931 and 8236035 extracted; rebased to jdk-14+28; merge with 8236035.patch.cr1; merge with 8235795.patch.cr1; merge with 8236035.patch.cr2; merge with 8235795.patch.cr2; merge with 8235795.patch.cr3.
rev 58111 : See CR9-to-CR10-changes; merge with jdk-15+11.

*** 137,151 **** // Global ObjectMonitor in-use list. When a JavaThread is exiting, // ObjectMonitors on its per-thread in-use list are prepended here. ObjectMonitor* _in_use_list; DEFINE_PAD_MINUS_SIZE(2, OM_CACHE_LINE_SIZE, sizeof(ObjectMonitor*)); ! // Global ObjectMonitor wait list. If HandshakeAfterDeflateIdleMonitors ! // is true, deflated ObjectMonitors wait on this list until after a ! // handshake or a safepoint for platforms that don't support handshakes. ! // After the handshake or safepoint, the deflated ObjectMonitors are ! // prepended to free_list. ObjectMonitor* _wait_list; DEFINE_PAD_MINUS_SIZE(3, OM_CACHE_LINE_SIZE, sizeof(ObjectMonitor*)); int _free_count; // # on free_list DEFINE_PAD_MINUS_SIZE(4, OM_CACHE_LINE_SIZE, sizeof(int)); --- 137,150 ---- // Global ObjectMonitor in-use list. When a JavaThread is exiting, // ObjectMonitors on its per-thread in-use list are prepended here. ObjectMonitor* _in_use_list; DEFINE_PAD_MINUS_SIZE(2, OM_CACHE_LINE_SIZE, sizeof(ObjectMonitor*)); ! // Global ObjectMonitor wait list. Deflated ObjectMonitors wait on ! // this list until after a handshake or a safepoint for platforms ! // that don't support handshakes. After the handshake or safepoint, ! // the deflated ObjectMonitors are prepended to free_list. ObjectMonitor* _wait_list; DEFINE_PAD_MINUS_SIZE(3, OM_CACHE_LINE_SIZE, sizeof(ObjectMonitor*)); int _free_count; // # on free_list DEFINE_PAD_MINUS_SIZE(4, OM_CACHE_LINE_SIZE, sizeof(int));
*** 318,328 **** // Prepend a list of ObjectMonitors to om_list_globals._wait_list. // 'tail' is the last ObjectMonitor in the list and there are 'count' // on the list. Also updates om_list_globals._wait_count. static void prepend_list_to_global_wait_list(ObjectMonitor* list, ObjectMonitor* tail, int count) { - assert(HandshakeAfterDeflateIdleMonitors, "sanity check"); prepend_list_to_common(list, tail, count, &om_list_globals._wait_list, &om_list_globals._wait_count); } // Prepend a list of ObjectMonitors to om_list_globals._in_use_list. --- 317,326 ----
*** 533,544 **** if (AsyncDeflateIdleMonitors && m->try_set_owner_from(DEFLATER_MARKER, self) == DEFLATER_MARKER) { // The deflation protocol finished the first part (setting owner), // but it failed the second part (making ref_count negative) and ! // bailed. Or the ObjectMonitor was async deflated and reused. ! // Acquired the monitor. assert(m->_recursions == 0, "invariant"); return true; } } break; --- 531,541 ---- if (AsyncDeflateIdleMonitors && m->try_set_owner_from(DEFLATER_MARKER, self) == DEFLATER_MARKER) { // The deflation protocol finished the first part (setting owner), // but it failed the second part (making ref_count negative) and ! // bailed. Acquired the monitor. assert(m->_recursions == 0, "invariant"); return true; } } break;
*** 1033,1046 **** assert(AsyncDeflateIdleMonitors, "sanity check"); continue; } monitor = omh.om_ptr(); temp = monitor->header(); ! // Allow for a lagging install_displaced_markword_in_object() to ! // have marked the ObjectMonitor's header/dmw field. ! assert(temp.is_neutral() || (AsyncDeflateIdleMonitors && temp.is_marked()), ! "invariant: header=" INTPTR_FORMAT, temp.value()); hash = temp.hash(); if (hash != 0) { // if it has a hash, just return it return hash; } // Fall thru so we only have one place that installs the hash in --- 1030,1040 ---- assert(AsyncDeflateIdleMonitors, "sanity check"); continue; } monitor = omh.om_ptr(); temp = monitor->header(); ! assert(temp.is_neutral(), "invariant: header=" INTPTR_FORMAT, temp.value()); hash = temp.hash(); if (hash != 0) { // if it has a hash, just return it return hash; } // Fall thru so we only have one place that installs the hash in
*** 1068,1107 **** ObjectMonitorHandle omh; inflate(&omh, self, obj, inflate_cause_hash_code); monitor = omh.om_ptr(); // Load ObjectMonitor's header/dmw field and see if it has a hash. mark = monitor->header(); ! // Allow for a lagging install_displaced_markword_in_object() to ! // have marked the ObjectMonitor's header/dmw field. ! assert(mark.is_neutral() || (AsyncDeflateIdleMonitors && mark.is_marked()), ! "invariant: header=" INTPTR_FORMAT, mark.value()); hash = mark.hash(); if (hash == 0) { // if it does not have a hash hash = get_next_hash(self, obj); // get a new hash temp = mark.copy_set_hash(hash); // merge the hash into header - if (AsyncDeflateIdleMonitors && temp.is_marked()) { - // A lagging install_displaced_markword_in_object() has marked - // the ObjectMonitor's header/dmw field. We clear it to avoid - // any confusion if we are able to set the hash. - temp.set_unmarked(); - } assert(temp.is_neutral(), "invariant: header=" INTPTR_FORMAT, temp.value()); uintptr_t v = Atomic::cmpxchg((volatile uintptr_t*)monitor->header_addr(), mark.value(), temp.value()); test = markWord(v); if (test != mark) { // The attempt to update the ObjectMonitor's header/dmw field // did not work. This can happen if another thread managed to ! // merge in the hash just before our cmpxchg(). With async ! // deflation, a lagging install_displaced_markword_in_object() ! // could have just marked or just unmarked the header/dmw field. // If we add any new usages of the header/dmw field, this code // will need to be updated. - if (AsyncDeflateIdleMonitors) { - // Since async deflation gives us two possible reasons for - // the cmwxchg() to fail, it is easier to simply retry. - continue; - } hash = test.hash(); assert(test.is_neutral(), "invariant: header=" INTPTR_FORMAT, test.value()); assert(hash != 0, "should only have lost the race to a thread that set a non-zero hash"); } } --- 1062,1085 ---- ObjectMonitorHandle omh; inflate(&omh, self, obj, inflate_cause_hash_code); monitor = omh.om_ptr(); // Load ObjectMonitor's header/dmw field and see if it has a hash. mark = monitor->header(); ! assert(mark.is_neutral(), "invariant: header=" INTPTR_FORMAT, mark.value()); hash = mark.hash(); if (hash == 0) { // if it does not have a hash hash = get_next_hash(self, obj); // get a new hash temp = mark.copy_set_hash(hash); // merge the hash into header assert(temp.is_neutral(), "invariant: header=" INTPTR_FORMAT, temp.value()); uintptr_t v = Atomic::cmpxchg((volatile uintptr_t*)monitor->header_addr(), mark.value(), temp.value()); test = markWord(v); if (test != mark) { // The attempt to update the ObjectMonitor's header/dmw field // did not work. This can happen if another thread managed to ! // merge in the hash just before our cmpxchg(). // If we add any new usages of the header/dmw field, this code // will need to be updated. hash = test.hash(); assert(test.is_neutral(), "invariant: header=" INTPTR_FORMAT, test.value()); assert(hash != 0, "should only have lost the race to a thread that set a non-zero hash"); } }
*** 1263,1273 **** while (block != NULL) { assert(block->object() == CHAINMARKER, "must be a block header"); for (int i = _BLOCKSIZE - 1; i > 0; i--) { ObjectMonitor* mid = (ObjectMonitor *)(block + i); ObjectMonitorHandle omh; ! if (!mid->is_free() && omh.set_om_ptr_if_safe(mid)) { // The ObjectMonitor* is not free and it has been made safe. if (mid->object() == NULL) { // Only process with closure if the object is set. continue; } --- 1241,1251 ---- while (block != NULL) { assert(block->object() == CHAINMARKER, "must be a block header"); for (int i = _BLOCKSIZE - 1; i > 0; i--) { ObjectMonitor* mid = (ObjectMonitor *)(block + i); ObjectMonitorHandle omh; ! if (!mid->is_free() && omh.save_om_ptr_if_safe(mid)) { // The ObjectMonitor* is not free and it has been made safe. if (mid->object() == NULL) { // Only process with closure if the object is set. continue; }
*** 1284,1297 **** int population = Atomic::load(&om_list_globals._population); if (population == 0) { return false; } if (MonitorUsedDeflationThreshold > 0) { ! int monitors_used = population - Atomic::load(&om_list_globals._free_count); ! if (HandshakeAfterDeflateIdleMonitors) { ! monitors_used -= Atomic::load(&om_list_globals._wait_count); ! } int monitor_usage = (monitors_used * 100LL) / population; return monitor_usage > MonitorUsedDeflationThreshold; } return false; } --- 1262,1273 ---- int population = Atomic::load(&om_list_globals._population); if (population == 0) { return false; } if (MonitorUsedDeflationThreshold > 0) { ! int monitors_used = population - Atomic::load(&om_list_globals._free_count) - ! Atomic::load(&om_list_globals._wait_count); int monitor_usage = (monitors_used * 100LL) / population; return monitor_usage > MonitorUsedDeflationThreshold; } return false; }
*** 1320,1333 **** // in order to not swamp the ServiceThread. _last_async_deflation_time_ns = os::javaTimeNanos(); return true; } int monitors_used = Atomic::load(&om_list_globals._population) - ! Atomic::load(&om_list_globals._free_count); ! if (HandshakeAfterDeflateIdleMonitors) { ! monitors_used -= Atomic::load(&om_list_globals._wait_count); ! } if (is_MonitorBound_exceeded(monitors_used)) { // Not enough ObjectMonitors on the global free list. return true; } return false; --- 1296,1307 ---- // in order to not swamp the ServiceThread. _last_async_deflation_time_ns = os::javaTimeNanos(); return true; } int monitors_used = Atomic::load(&om_list_globals._population) - ! Atomic::load(&om_list_globals._free_count) - ! Atomic::load(&om_list_globals._wait_count); if (is_MonitorBound_exceeded(monitors_used)) { // Not enough ObjectMonitors on the global free list. return true; } return false;
*** 1496,1510 **** break; // No more are available. } guarantee(take->object() == NULL, "invariant"); if (AsyncDeflateIdleMonitors) { // We allowed 3 field values to linger during async deflation. ! // We clear header and restore ref_count here, but we leave ! // owner == DEFLATER_MARKER so the simple C2 ObjectMonitor ! // enter optimization can no longer race with async deflation ! // and reuse. take->set_header(markWord::zero()); if (take->ref_count() < 0) { // Add back max_jint to restore the ref_count field to its // proper value. Atomic::add(&take->_ref_count, max_jint); --- 1470,1483 ---- 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->ref_count() < 0) { // Add back max_jint to restore the ref_count field to its // proper value. Atomic::add(&take->_ref_count, max_jint);
*** 2041,2053 **** ADIM_guarantee(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 we leave _owner == DEFLATER_MARKER here, then the simple C2 ! // ObjectMonitor enter optimization can no longer race with async ! // deflation and reuse. m->set_object(object); m->_Responsible = NULL; m->_SpinDuration = ObjectMonitor::Knob_SpinLimit; // consider: keep metastats by type/class omh_p->set_om_ptr(m); --- 2014,2027 ---- ADIM_guarantee(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); ! } m->set_object(object); m->_Responsible = NULL; m->_SpinDuration = ObjectMonitor::Knob_SpinLimit; // consider: keep metastats by type/class omh_p->set_om_ptr(m);
*** 2179,2192 **** } // Restore the header back to obj obj->release_set_mark(dmw); if (AsyncDeflateIdleMonitors) { ! // clear() expects the owner field to be NULL and we won't race ! // with the simple C2 ObjectMonitor enter optimization since ! // we're at a safepoint. 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, --- 2153,2164 ---- } // 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,
*** 2309,2320 **** p2i(mid->object())); assert(mid->is_free(), "must be free: allocation_state=%d", (int) mid->allocation_state()); // Move the deflated ObjectMonitor to the working free list ! // defined by free_head_p and free_tail_p. No races on this list ! // so no need for load_acquire() or store_release(). if (*free_head_p == NULL) { // First one on the list. *free_head_p = mid; } if (*free_tail_p != NULL) { --- 2281,2291 ---- p2i(mid->object())); assert(mid->is_free(), "must be free: allocation_state=%d", (int) mid->allocation_state()); // Move the deflated ObjectMonitor to the working free list ! // defined by free_head_p and free_tail_p. if (*free_head_p == NULL) { // First one on the list. *free_head_p = mid; } if (*free_tail_p != NULL) {
*** 2467,2478 **** om_lock(mid); next = unmarked_next(mid); } while (true) { ! // The current mid's next field is marked at this point. If we have ! // a cur_mid_in_use, then its next field is also marked at this point. if (next != NULL) { // We lock next so that an om_flush() thread that is behind us // cannot pass us when we unlock the current mid. om_lock(next); --- 2438,2449 ---- om_lock(mid); next = unmarked_next(mid); } while (true) { ! // The current mid is locked at this point. If we have a ! // cur_mid_in_use, then it is also locked at this point. if (next != NULL) { // We lock next so that an om_flush() thread that is behind us // cannot pass us when we unlock the current mid. om_lock(next);
*** 2667,2678 **** Atomic::load(&om_list_globals._wait_count)); // The ServiceThread's async deflation request has been processed. set_is_async_deflation_requested(false); ! if (HandshakeAfterDeflateIdleMonitors && ! Atomic::load(&om_list_globals._wait_count) > 0) { // There are deflated ObjectMonitors waiting for a handshake // (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"); --- 2638,2648 ---- Atomic::load(&om_list_globals._wait_count)); // The ServiceThread's async deflation request has been processed. set_is_async_deflation_requested(false); ! if (Atomic::load(&om_list_globals._wait_count) > 0) { // There are deflated ObjectMonitors waiting for a handshake // (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");
*** 2749,2759 **** deflate_monitor_list_using_JT(&om_list_globals._in_use_list, &om_list_globals._in_use_count, &free_head_p, &free_tail_p, &saved_mid_in_use_p); } else { ! local_deflated_count = deflate_monitor_list_using_JT(&target->om_in_use_list, &target->om_in_use_count, &free_head_p, &free_tail_p, &saved_mid_in_use_p); } deflated_count += local_deflated_count; if (free_head_p != NULL) { // Move the deflated ObjectMonitors to the global free list. --- 2719,2732 ---- deflate_monitor_list_using_JT(&om_list_globals._in_use_list, &om_list_globals._in_use_count, &free_head_p, &free_tail_p, &saved_mid_in_use_p); } else { ! local_deflated_count = ! deflate_monitor_list_using_JT(&target->om_in_use_list, ! &target->om_in_use_count, &free_head_p, ! &free_tail_p, &saved_mid_in_use_p); } deflated_count += local_deflated_count; if (free_head_p != NULL) { // Move the deflated ObjectMonitors to the global free list.
*** 2769,2783 **** #ifdef ASSERT ObjectMonitor* l_next_om = unmarked_next(free_tail_p); #endif assert(l_next_om == NULL, "must be NULL: _next_om=" INTPTR_FORMAT, p2i(l_next_om)); - if (HandshakeAfterDeflateIdleMonitors) { prepend_list_to_global_wait_list(free_head_p, free_tail_p, local_deflated_count); - } else { - prepend_list_to_global_free_list(free_head_p, free_tail_p, local_deflated_count); - } OM_PERFDATA_OP(Deflations, inc(local_deflated_count)); } if (saved_mid_in_use_p != NULL) { --- 2742,2752 ----
*** 3041,3054 **** chk_global_in_use_list_and_count(ls, &error_cnt); // Check om_list_globals._free_list and om_list_globals._free_count: chk_global_free_list_and_count(ls, &error_cnt); - if (HandshakeAfterDeflateIdleMonitors) { // Check om_list_globals._wait_list and om_list_globals._wait_count: chk_global_wait_list_and_count(ls, &error_cnt); - } ls->print_cr("Checking per-thread lists:"); for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) { // Check om_in_use_list and om_in_use_count: --- 3010,3021 ----
*** 3431,3444 **** int l_free_count = Atomic::load(&om_list_globals._free_count); int l_wait_count = Atomic::load(&om_list_globals._wait_count); out->print_cr("%18s %10d %10d %10d %10d", "", l_in_use_count, l_free_count, l_wait_count, Atomic::load(&om_list_globals._population)); ! pop_count += l_in_use_count + l_free_count; ! if (HandshakeAfterDeflateIdleMonitors) { ! pop_count += l_wait_count; ! } out->print_cr("%18s %10s %10s %10s", "Per-Thread Lists:", "InUse", "Free", "Provision"); out->print_cr("================== ========== ========== =========="); --- 3398,3408 ---- int l_free_count = Atomic::load(&om_list_globals._free_count); int l_wait_count = Atomic::load(&om_list_globals._wait_count); out->print_cr("%18s %10d %10d %10d %10d", "", l_in_use_count, l_free_count, l_wait_count, Atomic::load(&om_list_globals._population)); ! pop_count += l_in_use_count + l_free_count + l_wait_count; out->print_cr("%18s %10s %10s %10s", "Per-Thread Lists:", "InUse", "Free", "Provision"); out->print_cr("================== ========== ========== ==========");
< prev index next >