From a272696813f2e5e896ac9de9985246aaeb9d476c Mon Sep 17 00:00:00 2001 From: Fredrik Bredberg Date: Mon, 8 Sep 2025 10:28:18 +0000 Subject: [PATCH] 8365190: Remove LockingMode related code from share Reviewed-by: aboldtch, dholmes, ayang, coleenp, lmesnik, rcastanedalo --- src/hotspot/cpu/zero/zeroInterpreter_zero.cpp | 42 +- src/hotspot/share/c1/c1_LIRGenerator.cpp | 2 +- src/hotspot/share/c1/c1_Runtime1.cpp | 3 - .../share/gc/g1/g1BarrierSet.inline.hpp | 4 +- .../share/gc/g1/g1BarrierSetRuntime.cpp | 2 +- .../share/gc/g1/g1HeapRegion.inline.hpp | 6 +- .../share/gc/g1/g1SATBMarkQueueSet.cpp | 2 +- .../share/gc/shared/cardTableBarrierSet.cpp | 2 +- .../gc/shenandoah/shenandoahHeap.inline.hpp | 6 - .../interpreter/zero/bytecodeInterpreter.cpp | 127 +--- src/hotspot/share/jvmci/jvmciRuntime.cpp | 4 +- src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 5 - .../share/oops/instanceStackChunkKlass.cpp | 4 - src/hotspot/share/oops/markWord.cpp | 33 +- src/hotspot/share/oops/markWord.hpp | 20 +- src/hotspot/share/oops/oop.cpp | 22 +- src/hotspot/share/oops/oop.hpp | 4 +- .../share/oops/stackChunkOop.inline.hpp | 3 +- src/hotspot/share/opto/library_call.cpp | 16 +- src/hotspot/share/opto/phaseX.cpp | 1 + src/hotspot/share/prims/jvmtiEnv.cpp | 10 - src/hotspot/share/runtime/arguments.cpp | 18 - src/hotspot/share/runtime/basicLock.cpp | 25 +- src/hotspot/share/runtime/basicLock.hpp | 11 - .../share/runtime/basicLock.inline.hpp | 10 - src/hotspot/share/runtime/continuation.cpp | 4 - .../share/runtime/continuationFreezeThaw.cpp | 31 +- src/hotspot/share/runtime/deoptimization.cpp | 52 +- src/hotspot/share/runtime/globals.hpp | 4 - src/hotspot/share/runtime/javaCalls.cpp | 2 +- src/hotspot/share/runtime/javaThread.cpp | 52 +- src/hotspot/share/runtime/javaThread.hpp | 3 - .../share/runtime/lightweightSynchronizer.cpp | 34 +- src/hotspot/share/runtime/lockStack.cpp | 1 - src/hotspot/share/runtime/objectMonitor.cpp | 3 +- src/hotspot/share/runtime/objectMonitor.hpp | 13 +- .../share/runtime/objectMonitor.inline.hpp | 14 +- src/hotspot/share/runtime/sharedRuntime.cpp | 13 +- src/hotspot/share/runtime/synchronizer.cpp | 684 +----------------- src/hotspot/share/runtime/synchronizer.hpp | 30 +- .../share/runtime/synchronizer.inline.hpp | 18 +- src/hotspot/share/runtime/threads.cpp | 21 +- src/hotspot/share/runtime/threads.hpp | 5 +- src/hotspot/share/runtime/vmStructs.cpp | 9 - .../share/utilities/globalDefinitions.cpp | 2 - .../share/utilities/globalDefinitions.hpp | 11 - src/hotspot/share/utilities/vmError.cpp | 2 +- .../jvm/hotspot/runtime/ObjectMonitor.java | 6 +- test/hotspot/gtest/runtime/test_lockStack.cpp | 12 +- .../locking/TestRecursiveMonitorChurn.java | 3 - 50 files changed, 141 insertions(+), 1270 deletions(-) diff --git a/src/hotspot/cpu/zero/zeroInterpreter_zero.cpp b/src/hotspot/cpu/zero/zeroInterpreter_zero.cpp index 029ccbded13..28c2364315e 100644 --- a/src/hotspot/cpu/zero/zeroInterpreter_zero.cpp +++ b/src/hotspot/cpu/zero/zeroInterpreter_zero.cpp @@ -331,26 +331,9 @@ int ZeroInterpreter::native_entry(Method* method, intptr_t UNUSED, TRAPS) { monitor = nullptr; if (method->is_synchronized()) { monitor = (BasicObjectLock*) istate->stack_base(); - oop lockee = monitor->obj(); - bool success = false; - if (LockingMode == LM_LEGACY) { - markWord disp = lockee->mark().set_unlocked(); - monitor->lock()->set_displaced_header(disp); - success = true; - if (lockee->cas_set_mark(markWord::from_pointer(monitor), disp) != disp) { - // Is it simple recursive case? - if (thread->is_lock_owned((address) disp.clear_lock_bits().to_pointer())) { - monitor->lock()->set_displaced_header(markWord::from_pointer(nullptr)); - } else { - success = false; - } - } - } - if (!success) { - CALL_VM_NOCHECK(InterpreterRuntime::monitorenter(thread, monitor)); - if (HAS_PENDING_EXCEPTION) - goto unwind_and_return; - } + CALL_VM_NOCHECK(InterpreterRuntime::monitorenter(thread, monitor)); + if (HAS_PENDING_EXCEPTION) + goto unwind_and_return; } // Get the signature handler @@ -481,24 +464,7 @@ int ZeroInterpreter::native_entry(Method* method, intptr_t UNUSED, TRAPS) { // Unlock if necessary if (monitor) { - bool success = false; - if (LockingMode == LM_LEGACY) { - BasicLock* lock = monitor->lock(); - oop rcvr = monitor->obj(); - monitor->set_obj(nullptr); - success = true; - markWord header = lock->displaced_header(); - if (header.to_pointer() != nullptr) { // Check for recursive lock - markWord old_header = markWord::encode(lock); - if (rcvr->cas_set_mark(header, old_header) != old_header) { - monitor->set_obj(rcvr); - success = false; - } - } - } - if (!success) { - InterpreterRuntime::monitorexit(monitor); - } + InterpreterRuntime::monitorexit(monitor); } unwind_and_return: diff --git a/src/hotspot/share/c1/c1_LIRGenerator.cpp b/src/hotspot/share/c1/c1_LIRGenerator.cpp index cbd84b3a11e..b30667dcac3 100644 --- a/src/hotspot/share/c1/c1_LIRGenerator.cpp +++ b/src/hotspot/share/c1/c1_LIRGenerator.cpp @@ -635,7 +635,7 @@ void LIRGenerator::monitor_exit(LIR_Opr object, LIR_Opr lock, LIR_Opr new_hdr, L // setup registers LIR_Opr hdr = lock; lock = new_hdr; - CodeStub* slow_path = new MonitorExitStub(lock, LockingMode != LM_MONITOR, monitor_no); + CodeStub* slow_path = new MonitorExitStub(lock, true, monitor_no); __ load_stack_address_monitor(monitor_no, lock); __ unlock_object(hdr, object, lock, scratch, slow_path); } diff --git a/src/hotspot/share/c1/c1_Runtime1.cpp b/src/hotspot/share/c1/c1_Runtime1.cpp index 4a1969788f3..fbf2bfb0f53 100644 --- a/src/hotspot/share/c1/c1_Runtime1.cpp +++ b/src/hotspot/share/c1/c1_Runtime1.cpp @@ -778,9 +778,6 @@ JRT_BLOCK_ENTRY(void, Runtime1::monitorenter(JavaThread* current, oopDesc* obj, _monitorenter_slowcase_cnt++; } #endif - if (LockingMode == LM_MONITOR) { - lock->set_obj(obj); - } assert(obj == lock->obj(), "must match"); SharedRuntime::monitor_enter_helper(obj, lock->lock(), current); JRT_END diff --git a/src/hotspot/share/gc/g1/g1BarrierSet.inline.hpp b/src/hotspot/share/gc/g1/g1BarrierSet.inline.hpp index 33c153e9e5d..9678da190af 100644 --- a/src/hotspot/share/gc/g1/g1BarrierSet.inline.hpp +++ b/src/hotspot/share/gc/g1/g1BarrierSet.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,7 @@ inline void G1BarrierSet::enqueue_preloaded(oop pre_val) { // Nulls should have been already filtered. - assert(oopDesc::is_oop(pre_val, true), "Error"); + assert(oopDesc::is_oop(pre_val), "Error"); G1SATBMarkQueueSet& queue_set = G1BarrierSet::satb_mark_queue_set(); if (!queue_set.is_active()) return; diff --git a/src/hotspot/share/gc/g1/g1BarrierSetRuntime.cpp b/src/hotspot/share/gc/g1/g1BarrierSetRuntime.cpp index ce0d53e4891..205829bba1a 100644 --- a/src/hotspot/share/gc/g1/g1BarrierSetRuntime.cpp +++ b/src/hotspot/share/gc/g1/g1BarrierSetRuntime.cpp @@ -47,7 +47,7 @@ void G1BarrierSetRuntime::write_ref_array_post_entry(HeapWord* dst, size_t lengt JRT_LEAF(void, G1BarrierSetRuntime::write_ref_field_pre_entry(oopDesc* orig, JavaThread* thread)) assert(thread == JavaThread::current(), "pre-condition"); assert(orig != nullptr, "should be optimized out"); - assert(oopDesc::is_oop(orig, true /* ignore mark word */), "Error"); + assert(oopDesc::is_oop(orig), "Error"); // store the original value that was in the field reference SATBMarkQueue& queue = G1ThreadLocalData::satb_mark_queue(thread); G1BarrierSet::satb_mark_queue_set().enqueue_known_active(queue, orig); diff --git a/src/hotspot/share/gc/g1/g1HeapRegion.inline.hpp b/src/hotspot/share/gc/g1/g1HeapRegion.inline.hpp index c2e5c5df4b1..236e72aeb91 100644 --- a/src/hotspot/share/gc/g1/g1HeapRegion.inline.hpp +++ b/src/hotspot/share/gc/g1/g1HeapRegion.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -350,7 +350,7 @@ inline HeapWord* G1HeapRegion::oops_on_memregion_iterate_in_unparsable(MemRegion assert(bitmap->is_marked(cur), "inv"); oop obj = cast_to_oop(cur); - assert(oopDesc::is_oop(obj, true), "Not an oop at " PTR_FORMAT, p2i(cur)); + assert(oopDesc::is_oop(obj), "Not an oop at " PTR_FORMAT, p2i(cur)); cur += obj->size(); bool is_precise; @@ -418,7 +418,7 @@ inline HeapWord* G1HeapRegion::oops_on_memregion_iterate(MemRegion mr, Closure* // All objects >= pb are parsable. So we can just take object sizes directly. while (true) { oop obj = cast_to_oop(cur); - assert(oopDesc::is_oop(obj, true), "Not an oop at " PTR_FORMAT, p2i(cur)); + assert(oopDesc::is_oop(obj), "Not an oop at " PTR_FORMAT, p2i(cur)); bool is_precise = false; diff --git a/src/hotspot/share/gc/g1/g1SATBMarkQueueSet.cpp b/src/hotspot/share/gc/g1/g1SATBMarkQueueSet.cpp index f0b29a5bbab..7d197c37158 100644 --- a/src/hotspot/share/gc/g1/g1SATBMarkQueueSet.cpp +++ b/src/hotspot/share/gc/g1/g1SATBMarkQueueSet.cpp @@ -89,7 +89,7 @@ static inline bool requires_marking(const void* entry, G1CollectedHeap* g1h) { return false; } - assert(oopDesc::is_oop(cast_to_oop(entry), true /* ignore mark word */), + assert(oopDesc::is_oop(cast_to_oop(entry)), "Invalid oop in SATB buffer: " PTR_FORMAT, p2i(entry)); return true; diff --git a/src/hotspot/share/gc/shared/cardTableBarrierSet.cpp b/src/hotspot/share/gc/shared/cardTableBarrierSet.cpp index 84bf3eac130..dfa00636dec 100644 --- a/src/hotspot/share/gc/shared/cardTableBarrierSet.cpp +++ b/src/hotspot/share/gc/shared/cardTableBarrierSet.cpp @@ -162,7 +162,7 @@ void CardTableBarrierSet::flush_deferred_card_mark_barrier(JavaThread* thread) { DEBUG_ONLY(oop old_obj = cast_to_oop(deferred.start());) assert(!_card_table->is_in_young(old_obj), "Else should have been filtered in on_slowpath_allocation_exit()"); - assert(oopDesc::is_oop(old_obj, true), "Not an oop"); + assert(oopDesc::is_oop(old_obj), "Not an oop"); assert(deferred.word_size() == old_obj->size(), "Mismatch: multiple objects?"); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp index cf9d808f7ce..4de6ccead51 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp @@ -312,11 +312,6 @@ void ShenandoahHeap::increase_object_age(oop obj, uint additional_age) { // For all these reasons, we take the conservative approach and not attempt // to increase the age when the header is displaced. markWord w = obj->mark(); - // The mark-word has been copied from the original object. It can not be - // inflating, because inflation can not be interrupted by a safepoint, - // and after a safepoint, a Java thread would first have to successfully - // evacuate the object before it could inflate the monitor. - assert(!w.is_being_inflated() || LockingMode == LM_LIGHTWEIGHT, "must not inflate monitor before evacuation of object succeeds"); // It is possible that we have copied the object after another thread has // already successfully completed evacuation. While harmless (we would never // publish our copy), don't even attempt to modify the age when that @@ -334,7 +329,6 @@ uint ShenandoahHeap::get_object_age(oop obj) { markWord w = obj->mark(); assert(!w.is_marked(), "must not be forwarded"); if (UseObjectMonitorTable) { - assert(LockingMode == LM_LIGHTWEIGHT, "Must use LW locking, too"); assert(w.age() <= markWord::max_age, "Impossible!"); return w.age(); } diff --git a/src/hotspot/share/interpreter/zero/bytecodeInterpreter.cpp b/src/hotspot/share/interpreter/zero/bytecodeInterpreter.cpp index bfed16f2769..e9adfce6372 100644 --- a/src/hotspot/share/interpreter/zero/bytecodeInterpreter.cpp +++ b/src/hotspot/share/interpreter/zero/bytecodeInterpreter.cpp @@ -624,26 +624,7 @@ void BytecodeInterpreter::run(interpreterState istate) { // The initial monitor is ours for the taking. BasicObjectLock* mon = &istate->monitor_base()[-1]; mon->set_obj(rcvr); - - bool success = false; - if (LockingMode == LM_LEGACY) { - // Traditional fast locking. - markWord displaced = rcvr->mark().set_unlocked(); - mon->lock()->set_displaced_header(displaced); - success = true; - if (rcvr->cas_set_mark(markWord::from_pointer(mon), displaced) != displaced) { - // Is it simple recursive case? - if (THREAD->is_lock_owned((address) displaced.clear_lock_bits().to_pointer())) { - mon->lock()->set_displaced_header(markWord::from_pointer(nullptr)); - } else { - success = false; - } - } - } - if (!success) { - CALL_VM(InterpreterRuntime::monitorenter(THREAD, mon), handle_exception); - } - + CALL_VM(InterpreterRuntime::monitorenter(THREAD, mon), handle_exception); } THREAD->set_do_not_unlock_if_synchronized(false); @@ -725,26 +706,7 @@ void BytecodeInterpreter::run(interpreterState istate) { BasicObjectLock* entry = (BasicObjectLock*) istate->stack_base(); assert(entry->obj() == nullptr, "Frame manager didn't allocate the monitor"); entry->set_obj(lockee); - - bool success = false; - if (LockingMode == LM_LEGACY) { - // Traditional fast locking. - markWord displaced = lockee->mark().set_unlocked(); - entry->lock()->set_displaced_header(displaced); - success = true; - if (lockee->cas_set_mark(markWord::from_pointer(entry), displaced) != displaced) { - // Is it simple recursive case? - if (THREAD->is_lock_owned((address) displaced.clear_lock_bits().to_pointer())) { - entry->lock()->set_displaced_header(markWord::from_pointer(nullptr)); - } else { - success = false; - } - } - } - if (!success) { - CALL_VM(InterpreterRuntime::monitorenter(THREAD, entry), handle_exception); - } - + CALL_VM(InterpreterRuntime::monitorenter(THREAD, entry), handle_exception); UPDATE_PC_AND_TOS(1, -1); goto run; } @@ -1657,26 +1619,7 @@ run: } if (entry != nullptr) { entry->set_obj(lockee); - - bool success = false; - if (LockingMode == LM_LEGACY) { - // Traditional fast locking. - markWord displaced = lockee->mark().set_unlocked(); - entry->lock()->set_displaced_header(displaced); - success = true; - if (lockee->cas_set_mark(markWord::from_pointer(entry), displaced) != displaced) { - // Is it simple recursive case? - if (THREAD->is_lock_owned((address) displaced.clear_lock_bits().to_pointer())) { - entry->lock()->set_displaced_header(markWord::from_pointer(nullptr)); - } else { - success = false; - } - } - } - if (!success) { - CALL_VM(InterpreterRuntime::monitorenter(THREAD, entry), handle_exception); - } - + CALL_VM(InterpreterRuntime::monitorenter(THREAD, entry), handle_exception); UPDATE_PC_AND_TOS_AND_CONTINUE(1, -1); } else { istate->set_msg(more_monitors); @@ -1694,25 +1637,7 @@ run: while (most_recent != limit ) { if ((most_recent)->obj() == lockee) { BasicLock* lock = most_recent->lock(); - - bool success = false; - if (LockingMode == LM_LEGACY) { - // If it isn't recursive we either must swap old header or call the runtime - most_recent->set_obj(nullptr); - success = true; - markWord header = lock->displaced_header(); - if (header.to_pointer() != nullptr) { - markWord old_header = markWord::encode(lock); - if (lockee->cas_set_mark(header, old_header) != old_header) { - // restore object for the slow case - most_recent->set_obj(lockee); - success = false; - } - } - } - if (!success) { - InterpreterRuntime::monitorexit(most_recent); - } + InterpreterRuntime::monitorexit(most_recent); UPDATE_PC_AND_TOS_AND_CONTINUE(1, -1); } most_recent++; @@ -3137,27 +3062,7 @@ run: while (end < base) { oop lockee = end->obj(); if (lockee != nullptr) { - BasicLock* lock = end->lock(); - - bool success = false; - if (LockingMode == LM_LEGACY) { - markWord header = lock->displaced_header(); - end->set_obj(nullptr); - - // If it isn't recursive we either must swap old header or call the runtime - success = true; - if (header.to_pointer() != nullptr) { - markWord old_header = markWord::encode(lock); - if (lockee->cas_set_mark(header, old_header) != old_header) { - // restore object for the slow case - end->set_obj(lockee); - success = false; - } - } - } - if (!success) { - InterpreterRuntime::monitorexit(end); - } + InterpreterRuntime::monitorexit(end); // One error is plenty if (illegal_state_oop() == nullptr && !suppress_error) { @@ -3204,32 +3109,12 @@ run: illegal_state_oop = Handle(THREAD, THREAD->pending_exception()); THREAD->clear_pending_exception(); } - } else if (LockingMode != LM_LEGACY) { + } else { InterpreterRuntime::monitorexit(base); if (THREAD->has_pending_exception()) { if (!suppress_error) illegal_state_oop = Handle(THREAD, THREAD->pending_exception()); THREAD->clear_pending_exception(); } - } else { - BasicLock* lock = base->lock(); - markWord header = lock->displaced_header(); - base->set_obj(nullptr); - - // If it isn't recursive we either must swap old header or call the runtime - bool dec_monitor_count = true; - if (header.to_pointer() != nullptr) { - markWord old_header = markWord::encode(lock); - if (rcvr->cas_set_mark(header, old_header) != old_header) { - // restore object for the slow case - base->set_obj(rcvr); - dec_monitor_count = false; - InterpreterRuntime::monitorexit(base); - if (THREAD->has_pending_exception()) { - if (!suppress_error) illegal_state_oop = Handle(THREAD, THREAD->pending_exception()); - THREAD->clear_pending_exception(); - } - } - } } } } diff --git a/src/hotspot/share/jvmci/jvmciRuntime.cpp b/src/hotspot/share/jvmci/jvmciRuntime.cpp index c0335e7c67e..33aa40acbc2 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp @@ -565,8 +565,8 @@ JRT_LEAF(void, JVMCIRuntime::log_object(JavaThread* thread, oopDesc* obj, bool a if (obj == nullptr) { tty->print("null"); - } else if (oopDesc::is_oop_or_null(obj, true) && (!as_string || !java_lang_String::is_instance(obj))) { - if (oopDesc::is_oop_or_null(obj, true)) { + } else if (oopDesc::is_oop_or_null(obj) && (!as_string || !java_lang_String::is_instance(obj))) { + if (oopDesc::is_oop_or_null(obj)) { char buf[O_BUFLEN]; tty->print("%s@" INTPTR_FORMAT, obj->klass()->name()->as_C_string(buf, O_BUFLEN), p2i(obj)); } else { diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index 737718096c5..47ebe5aa7a7 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -341,7 +341,6 @@ volatile_nonstatic_field(ObjectMonitor, _recursions, intptr_t) \ volatile_nonstatic_field(ObjectMonitor, _entry_list, ObjectWaiter*) \ volatile_nonstatic_field(ObjectMonitor, _succ, int64_t) \ - volatile_nonstatic_field(ObjectMonitor, _stack_locker, BasicLock*) \ \ volatile_nonstatic_field(oopDesc, _mark, markWord) \ volatile_nonstatic_field(oopDesc, _metadata._klass, Klass*) \ @@ -780,10 +779,6 @@ declare_constant(InstanceKlass::being_initialized) \ declare_constant(InstanceKlass::fully_initialized) \ \ - declare_constant(LockingMode::LM_MONITOR) \ - declare_constant(LockingMode::LM_LEGACY) \ - declare_constant(LockingMode::LM_LIGHTWEIGHT) \ - \ /*********************************/ \ /* InstanceKlass _misc_flags */ \ /*********************************/ \ diff --git a/src/hotspot/share/oops/instanceStackChunkKlass.cpp b/src/hotspot/share/oops/instanceStackChunkKlass.cpp index bf08cfd25ab..db60e74013f 100644 --- a/src/hotspot/share/oops/instanceStackChunkKlass.cpp +++ b/src/hotspot/share/oops/instanceStackChunkKlass.cpp @@ -164,10 +164,6 @@ void InstanceStackChunkKlass::oop_oop_iterate_stack_slow(stackChunkOop chunk, Oo template void InstanceStackChunkKlass::oop_oop_iterate_lockstack(stackChunkOop chunk, OopIterateClosure* closure, MemRegion mr) { - if (LockingMode != LM_LIGHTWEIGHT) { - return; - } - StackChunkOopIterateFilterClosure cl(closure, mr); if (chunk->has_bitmap()) { chunk->iterate_lockstack(&cl); diff --git a/src/hotspot/share/oops/markWord.cpp b/src/hotspot/share/oops/markWord.cpp index 2ba57cddc67..001666b0439 100644 --- a/src/hotspot/share/oops/markWord.cpp +++ b/src/hotspot/share/oops/markWord.cpp @@ -36,35 +36,18 @@ STATIC_ASSERT(markWord::klass_shift == markWord::hash_bits + markWord::hash_shif markWord markWord::displaced_mark_helper() const { assert(has_displaced_mark_helper(), "check"); - if (has_monitor()) { - // Has an inflated monitor. Must be checked before has_locker(). - ObjectMonitor* monitor = this->monitor(); - return monitor->header(); - } - if (has_locker()) { // has a stack lock - BasicLock* locker = this->locker(); - return locker->displaced_header(); - } - // This should never happen: - fatal("bad header=" INTPTR_FORMAT, value()); - return markWord(value()); + // Make sure we have an inflated monitor. + guarantee(has_monitor(), "bad header=" INTPTR_FORMAT, value()); + ObjectMonitor* monitor = this->monitor(); + return monitor->header(); } void markWord::set_displaced_mark_helper(markWord m) const { assert(has_displaced_mark_helper(), "check"); - if (has_monitor()) { - // Has an inflated monitor. Must be checked before has_locker(). - ObjectMonitor* monitor = this->monitor(); - monitor->set_header(m); - return; - } - if (has_locker()) { // has a stack lock - BasicLock* locker = this->locker(); - locker->set_displaced_header(m); - return; - } - // This should never happen: - fatal("bad header=" INTPTR_FORMAT, value()); + // Make sure we have an inflated monitor. + guarantee(has_monitor(), "bad header=" INTPTR_FORMAT, value()); + ObjectMonitor* monitor = this->monitor(); + monitor->set_header(m); } void markWord::print_on(outputStream* st, bool print_monitor_info) const { diff --git a/src/hotspot/share/oops/markWord.hpp b/src/hotspot/share/oops/markWord.hpp index 9cb46f4697d..08234709c97 100644 --- a/src/hotspot/share/oops/markWord.hpp +++ b/src/hotspot/share/oops/markWord.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -198,17 +198,8 @@ class markWord { markWord set_unlocked() const { return markWord(value() | unlocked_value); } - bool has_locker() const { - assert(LockingMode == LM_LEGACY, "should only be called with legacy stack locking"); - return (value() & lock_mask_in_place) == locked_value; - } - BasicLock* locker() const { - assert(has_locker(), "check"); - return (BasicLock*) value(); - } bool is_fast_locked() const { - assert(LockingMode == LM_LIGHTWEIGHT, "should only be called with new lightweight locking"); return (value() & lock_mask_in_place) == locked_value; } markWord set_fast_locked() const { @@ -227,11 +218,7 @@ class markWord { } bool has_displaced_mark_helper() const { intptr_t lockbits = value() & lock_mask_in_place; - if (LockingMode == LM_LIGHTWEIGHT) { - return !UseObjectMonitorTable && lockbits == monitor_value; - } - // monitor (0b10) | stack-locked (0b00)? - return (lockbits & unlocked_value) == 0; + return !UseObjectMonitorTable && lockbits == monitor_value; } markWord displaced_mark_helper() const; void set_displaced_mark_helper(markWord m) const; @@ -304,17 +291,14 @@ class markWord { inline void* decode_pointer() const { return (void*)clear_lock_bits().value(); } inline bool is_self_forwarded() const { - NOT_LP64(assert(LockingMode != LM_LEGACY, "incorrect with LM_LEGACY on 32 bit");) return mask_bits(value(), self_fwd_mask_in_place) != 0; } inline markWord set_self_forwarded() const { - NOT_LP64(assert(LockingMode != LM_LEGACY, "incorrect with LM_LEGACY on 32 bit");) return markWord(value() | self_fwd_mask_in_place); } inline markWord unset_self_forwarded() const { - NOT_LP64(assert(LockingMode != LM_LEGACY, "incorrect with LM_LEGACY on 32 bit");) return markWord(value() & ~self_fwd_mask_in_place); } diff --git a/src/hotspot/share/oops/oop.cpp b/src/hotspot/share/oops/oop.cpp index 7f0068f7473..be6e16855bd 100644 --- a/src/hotspot/share/oops/oop.cpp +++ b/src/hotspot/share/oops/oop.cpp @@ -110,27 +110,13 @@ intptr_t oopDesc::slow_identity_hash() { } // used only for asserts and guarantees -bool oopDesc::is_oop(oop obj, bool ignore_mark_word) { - if (!Universe::heap()->is_oop(obj)) { - return false; - } - - // Header verification: the mark is typically non-zero. If we're - // at a safepoint, it must not be zero, except when using the new lightweight locking. - // Outside of a safepoint, the header could be changing (for example, - // another thread could be inflating a lock on this object). - if (ignore_mark_word) { - return true; - } - if (obj->mark().value() != 0) { - return true; - } - return LockingMode == LM_LIGHTWEIGHT || !SafepointSynchronize::is_at_safepoint(); +bool oopDesc::is_oop(oop obj) { + return Universe::heap()->is_oop(obj); } // used only for asserts and guarantees -bool oopDesc::is_oop_or_null(oop obj, bool ignore_mark_word) { - return obj == nullptr ? true : is_oop(obj, ignore_mark_word); +bool oopDesc::is_oop_or_null(oop obj) { + return obj == nullptr ? true : is_oop(obj); } VerifyOopClosure VerifyOopClosure::verify_oop; diff --git a/src/hotspot/share/oops/oop.hpp b/src/hotspot/share/oops/oop.hpp index 3ec0ce5764a..a1c1a64b050 100644 --- a/src/hotspot/share/oops/oop.hpp +++ b/src/hotspot/share/oops/oop.hpp @@ -261,8 +261,8 @@ class oopDesc { inline bool is_unlocked() const; // asserts and guarantees - static bool is_oop(oop obj, bool ignore_mark_word = false); - static bool is_oop_or_null(oop obj, bool ignore_mark_word = false); + static bool is_oop(oop obj); + static bool is_oop_or_null(oop obj); // garbage collection inline bool is_gc_marked() const; diff --git a/src/hotspot/share/oops/stackChunkOop.inline.hpp b/src/hotspot/share/oops/stackChunkOop.inline.hpp index 384dbefc10b..9c91e934328 100644 --- a/src/hotspot/share/oops/stackChunkOop.inline.hpp +++ b/src/hotspot/share/oops/stackChunkOop.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -195,7 +195,6 @@ void stackChunkOopDesc::do_barriers(const StackChunkFrameStream& f, template inline void stackChunkOopDesc::iterate_lockstack(StackChunkLockStackClosureType* closure) { - assert(LockingMode == LM_LIGHTWEIGHT, ""); int cnt = lockstack_size(); intptr_t* lockstart_addr = start_address(); for (int i = 0; i < cnt; i++) { diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index da04d6b01ac..433dacc0ee1 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -4788,19 +4788,11 @@ bool LibraryCallKit::inline_native_hashcode(bool is_virtual, bool is_static) { // Test the header to see if it is safe to read w.r.t. locking. Node *lock_mask = _gvn.MakeConX(markWord::lock_mask_in_place); Node *lmasked_header = _gvn.transform(new AndXNode(header, lock_mask)); - if (LockingMode == LM_LIGHTWEIGHT) { - Node *monitor_val = _gvn.MakeConX(markWord::monitor_value); - Node *chk_monitor = _gvn.transform(new CmpXNode(lmasked_header, monitor_val)); - Node *test_monitor = _gvn.transform(new BoolNode(chk_monitor, BoolTest::eq)); + Node *monitor_val = _gvn.MakeConX(markWord::monitor_value); + Node *chk_monitor = _gvn.transform(new CmpXNode(lmasked_header, monitor_val)); + Node *test_monitor = _gvn.transform(new BoolNode(chk_monitor, BoolTest::eq)); - generate_slow_guard(test_monitor, slow_region); - } else { - Node *unlocked_val = _gvn.MakeConX(markWord::unlocked_value); - Node *chk_unlocked = _gvn.transform(new CmpXNode(lmasked_header, unlocked_val)); - Node *test_not_unlocked = _gvn.transform(new BoolNode(chk_unlocked, BoolTest::ne)); - - generate_slow_guard(test_not_unlocked, slow_region); - } + generate_slow_guard(test_monitor, slow_region); } // Get the hash value and check to see that it has been properly assigned. diff --git a/src/hotspot/share/opto/phaseX.cpp b/src/hotspot/share/opto/phaseX.cpp index 1df2cdb179e..a4248cb2b91 100644 --- a/src/hotspot/share/opto/phaseX.cpp +++ b/src/hotspot/share/opto/phaseX.cpp @@ -1670,6 +1670,7 @@ bool PhaseIterGVN::verify_Ideal_for(Node* n, bool can_reshape) { // Found (linux x64 only?) with: // serviceability/sa/ClhsdbThreadContext.java // -XX:+UnlockExperimentalVMOptions -XX:LockingMode=1 -XX:+IgnoreUnrecognizedVMOptions -XX:VerifyIterativeGVN=1110 + // Note: The -XX:LockingMode option is not available anymore. case Op_StrEquals: return false; diff --git a/src/hotspot/share/prims/jvmtiEnv.cpp b/src/hotspot/share/prims/jvmtiEnv.cpp index bc4013a7cab..30dd1f77d23 100644 --- a/src/hotspot/share/prims/jvmtiEnv.cpp +++ b/src/hotspot/share/prims/jvmtiEnv.cpp @@ -1367,11 +1367,6 @@ JvmtiEnv::GetOwnedMonitorInfo(jthread thread, jint* owned_monitor_count_ptr, job return err; } - if (LockingMode == LM_LEGACY && java_thread == nullptr) { - *owned_monitor_count_ptr = 0; - return JVMTI_ERROR_NONE; - } - // growable array of jvmti monitors info on the C-heap GrowableArray *owned_monitors_list = new (mtServiceability) GrowableArray(1, mtServiceability); @@ -1427,11 +1422,6 @@ JvmtiEnv::GetOwnedMonitorStackDepthInfo(jthread thread, jint* monitor_info_count return err; } - if (LockingMode == LM_LEGACY && java_thread == nullptr) { - *monitor_info_count_ptr = 0; - return JVMTI_ERROR_NONE; - } - // growable array of jvmti monitors info on the C-heap GrowableArray *owned_monitors_list = new (mtServiceability) GrowableArray(1, mtServiceability); diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index 2ebc15d0e1a..21706eb7726 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -1854,24 +1854,6 @@ bool Arguments::check_vm_args_consistency() { } #endif - if (UseObjectMonitorTable && LockingMode != LM_LIGHTWEIGHT) { - // ObjectMonitorTable requires lightweight locking. - FLAG_SET_CMDLINE(UseObjectMonitorTable, false); - warning("UseObjectMonitorTable requires LM_LIGHTWEIGHT"); - } - -#if !defined(X86) && !defined(AARCH64) && !defined(PPC64) && !defined(RISCV64) && !defined(S390) - if (LockingMode == LM_MONITOR) { - jio_fprintf(defaultStream::error_stream(), - "LockingMode == 0 (LM_MONITOR) is not fully implemented on this architecture\n"); - return false; - } -#endif - if (VerifyHeavyMonitors && LockingMode != LM_MONITOR) { - jio_fprintf(defaultStream::error_stream(), - "-XX:+VerifyHeavyMonitors requires LockingMode == 0 (LM_MONITOR)\n"); - return false; - } return status; } diff --git a/src/hotspot/share/runtime/basicLock.cpp b/src/hotspot/share/runtime/basicLock.cpp index 384fc493e0b..71082e24bb9 100644 --- a/src/hotspot/share/runtime/basicLock.cpp +++ b/src/hotspot/share/runtime/basicLock.cpp @@ -34,13 +34,6 @@ void BasicLock::print_on(outputStream* st, oop owner) const { if (mon != nullptr) { mon->print_on(st); } - } else if (LockingMode == LM_LEGACY) { - markWord mark_word = displaced_header(); - if (mark_word.value() != 0) { - // Print monitor info if there's an owning oop and it refers to this BasicLock. - bool print_monitor_info = (owner != nullptr) && (owner->mark() == markWord::from_pointer((void*)this)); - mark_word.print_on(st, print_monitor_info); - } } } @@ -73,23 +66,7 @@ void BasicLock::move_to(oop obj, BasicLock* dest) { // small (given the support for inflated fast-path locking in the fast_lock, etc) // we'll leave that optimization for another time. - if (LockingMode == LM_LEGACY) { - if (displaced_header().is_neutral()) { - // The object is locked and the resulting ObjectMonitor* will also be - // locked so it can't be async deflated until ownership is dropped. - ObjectSynchronizer::inflate_helper(obj); - // WARNING: We cannot put a check here, because the inflation - // will not update the displaced header. Once BasicLock is inflated, - // no one should ever look at its content. - } else { - // Typically the displaced header will be 0 (recursive stack lock) or - // unused_mark. Naively we'd like to assert that the displaced mark - // value is either 0, neutral, or 3. But with the advent of the - // store-before-CAS avoidance in fast_lock/compiler_lock_object - // we can find any flavor mark in the displaced mark. - } - dest->set_displaced_header(displaced_header()); - } else if (UseObjectMonitorTable) { + if (UseObjectMonitorTable) { // Preserve the ObjectMonitor*, the cache is cleared when a box is reused // and only read while the lock is held, so no stale ObjectMonitor* is // encountered. diff --git a/src/hotspot/share/runtime/basicLock.hpp b/src/hotspot/share/runtime/basicLock.hpp index 50de8db6bc6..8ed38747c74 100644 --- a/src/hotspot/share/runtime/basicLock.hpp +++ b/src/hotspot/share/runtime/basicLock.hpp @@ -35,12 +35,6 @@ class BasicLock { friend class VMStructs; friend class JVMCIVMStructs; private: - // * For LM_MONITOR - // Unused. - // * For LM_LEGACY - // This is either the actual displaced header from a locked object, or - // a sentinel zero value indicating a recursive stack-lock. - // * For LM_LIGHTWEIGHT // Used as a cache of the ObjectMonitor* used when locking. Must either // be nullptr or the ObjectMonitor* used when locking. volatile uintptr_t _metadata; @@ -52,15 +46,10 @@ class BasicLock { public: BasicLock() : _metadata(0) {} - // LM_MONITOR void set_bad_metadata_deopt() { set_metadata(badDispHeaderDeopt); } - // LM_LEGACY - inline markWord displaced_header() const; - inline void set_displaced_header(markWord header); static int displaced_header_offset_in_bytes() { return metadata_offset_in_bytes(); } - // LM_LIGHTWEIGHT inline ObjectMonitor* object_monitor_cache() const; inline void clear_object_monitor_cache(); inline void set_object_monitor_cache(ObjectMonitor* mon); diff --git a/src/hotspot/share/runtime/basicLock.inline.hpp b/src/hotspot/share/runtime/basicLock.inline.hpp index 773d8a1c848..2ea1fe2371c 100644 --- a/src/hotspot/share/runtime/basicLock.inline.hpp +++ b/src/hotspot/share/runtime/basicLock.inline.hpp @@ -29,16 +29,6 @@ #include "runtime/objectMonitor.inline.hpp" -inline markWord BasicLock::displaced_header() const { - assert(LockingMode == LM_LEGACY, "must be"); - return markWord(get_metadata()); -} - -inline void BasicLock::set_displaced_header(markWord header) { - assert(LockingMode == LM_LEGACY, "must be"); - Atomic::store(&_metadata, header.value()); -} - inline ObjectMonitor* BasicLock::object_monitor_cache() const { assert(UseObjectMonitorTable, "must be"); #if !defined(ZERO) && (defined(X86) || defined(AARCH64) || defined(RISCV64) || defined(PPC64) || defined(S390)) diff --git a/src/hotspot/share/runtime/continuation.cpp b/src/hotspot/share/runtime/continuation.cpp index 727dcf8fc26..8f1cbe39640 100644 --- a/src/hotspot/share/runtime/continuation.cpp +++ b/src/hotspot/share/runtime/continuation.cpp @@ -146,10 +146,6 @@ static void verify_preempt_preconditions(JavaThread* current, oop continuation) freeze_result Continuation::try_preempt(JavaThread* current, oop continuation) { verify_preempt_preconditions(current, continuation); - if (LockingMode == LM_LEGACY) { - return freeze_unsupported; - } - if (!is_vthread_safe_to_preempt(current, current->vthread())) { return freeze_pinned_native; } diff --git a/src/hotspot/share/runtime/continuationFreezeThaw.cpp b/src/hotspot/share/runtime/continuationFreezeThaw.cpp index 40a8987e139..64f9d2b9994 100644 --- a/src/hotspot/share/runtime/continuationFreezeThaw.cpp +++ b/src/hotspot/share/runtime/continuationFreezeThaw.cpp @@ -533,11 +533,7 @@ FreezeBase::FreezeBase(JavaThread* thread, ContinuationWrapper& cont, intptr_t* cont_size(), _cont.argsize(), p2i(_cont_stack_top), p2i(_cont_stack_bottom)); assert(cont_size() > 0, ""); - if (LockingMode != LM_LIGHTWEIGHT) { - _monitors_in_lockstack = 0; - } else { - _monitors_in_lockstack = _thread->lock_stack().monitor_count(); - } + _monitors_in_lockstack = _thread->lock_stack().monitor_count(); } void FreezeBase::init_rest() { // we want to postpone some initialization after chunk handling @@ -587,33 +583,12 @@ static void assert_frames_in_continuation_are_safe(JavaThread* thread) { #endif // ASSERT } -#ifdef ASSERT -static bool monitors_on_stack(JavaThread* thread) { - assert_frames_in_continuation_are_safe(thread); - ContinuationEntry* ce = thread->last_continuation(); - RegisterMap map(thread, - RegisterMap::UpdateMap::include, - RegisterMap::ProcessFrames::skip, - RegisterMap::WalkContinuation::skip); - map.set_include_argument_oops(false); - for (frame f = thread->last_frame(); Continuation::is_frame_in_continuation(ce, f); f = f.sender(&map)) { - if ((f.is_interpreted_frame() && ContinuationHelper::InterpretedFrame::is_owning_locks(f)) || - (f.is_compiled_frame() && ContinuationHelper::CompiledFrame::is_owning_locks(map.thread(), &map, f)) || - (f.is_native_frame() && ContinuationHelper::NativeFrame::is_owning_locks(map.thread(), f))) { - return true; - } - } - return false; -} -#endif // ASSERT - // Called _after_ the last possible safepoint during the freeze operation (chunk allocation) void FreezeBase::unwind_frames() { ContinuationEntry* entry = _cont.entry(); entry->flush_stack_processing(_thread); assert_frames_in_continuation_are_safe(_thread); JFR_ONLY(Jfr::check_and_process_sample_request(_thread);) - assert(LockingMode != LM_LEGACY || !monitors_on_stack(_thread), "unexpected monitors on stack"); set_anchor_to_entry(_thread, entry); } @@ -1762,8 +1737,8 @@ static inline freeze_result freeze_internal(JavaThread* current, intptr_t* const assert(entry->is_virtual_thread() == (entry->scope(current) == java_lang_VirtualThread::vthread_scope()), ""); - assert(LockingMode == LM_LEGACY || (current->held_monitor_count() == 0 && current->jni_monitor_count() == 0), - "Held monitor count should only be used for LM_LEGACY: " INT64_FORMAT " JNI: " INT64_FORMAT, (int64_t)current->held_monitor_count(), (int64_t)current->jni_monitor_count()); + assert((current->held_monitor_count() == 0 && current->jni_monitor_count() == 0), + "Held monitor count should not be used for lightweight locking: " INT64_FORMAT " JNI: " INT64_FORMAT, (int64_t)current->held_monitor_count(), (int64_t)current->jni_monitor_count()); if (entry->is_pinned() || current->held_monitor_count() > 0) { log_develop_debug(continuations)("PINNED due to critical section/hold monitor"); diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index da9a4e9cd9a..693815c6fc4 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -1645,26 +1645,17 @@ bool Deoptimization::relock_objects(JavaThread* thread, GrowableArrayowner()); markWord mark = obj->mark(); if (exec_mode == Unpack_none) { - if (LockingMode == LM_LEGACY && mark.has_locker() && fr.sp() > (intptr_t*)mark.locker()) { - // With exec_mode == Unpack_none obj may be thread local and locked in - // a callee frame. Make the lock in the callee a recursive lock and restore the displaced header. - markWord dmw = mark.displaced_mark_helper(); - mark.locker()->set_displaced_header(markWord::encode((BasicLock*) nullptr)); - obj->set_mark(dmw); - } if (mark.has_monitor()) { // defer relocking if the deoptee thread is currently waiting for obj ObjectMonitor* waiting_monitor = deoptee_thread->current_waiting_monitor(); if (waiting_monitor != nullptr && waiting_monitor->object() == obj()) { assert(fr.is_deoptimized_frame(), "frame must be scheduled for deoptimization"); - if (LockingMode == LM_LEGACY) { - mon_info->lock()->set_displaced_header(markWord::unused_mark()); - } else if (UseObjectMonitorTable) { + if (UseObjectMonitorTable) { mon_info->lock()->clear_object_monitor_cache(); } #ifdef ASSERT else { - assert(LockingMode == LM_MONITOR || !UseObjectMonitorTable, "must be"); + assert(!UseObjectMonitorTable, "must be"); mon_info->lock()->set_bad_metadata_deopt(); } #endif @@ -1674,29 +1665,24 @@ bool Deoptimization::relock_objects(JavaThread* thread, GrowableArraylock(); - if (LockingMode == LM_LIGHTWEIGHT) { - // We have lost information about the correct state of the lock stack. - // Entering may create an invalid lock stack. Inflate the lock if it - // was fast_locked to restore the valid lock stack. - if (UseObjectMonitorTable) { - // UseObjectMonitorTable expects the BasicLock cache to be either a - // valid ObjectMonitor* or nullptr. Right now it is garbage, set it - // to nullptr. - lock->clear_object_monitor_cache(); - } - ObjectSynchronizer::enter_for(obj, lock, deoptee_thread); - if (deoptee_thread->lock_stack().contains(obj())) { - LightweightSynchronizer::inflate_fast_locked_object(obj(), ObjectSynchronizer::InflateCause::inflate_cause_vm_internal, - deoptee_thread, thread); - } - assert(mon_info->owner()->is_locked(), "object must be locked now"); - assert(obj->mark().has_monitor(), "must be"); - assert(!deoptee_thread->lock_stack().contains(obj()), "must be"); - assert(ObjectSynchronizer::read_monitor(thread, obj(), obj->mark())->has_owner(deoptee_thread), "must be"); - } else { - ObjectSynchronizer::enter_for(obj, lock, deoptee_thread); - assert(mon_info->owner()->is_locked(), "object must be locked now"); + // We have lost information about the correct state of the lock stack. + // Entering may create an invalid lock stack. Inflate the lock if it + // was fast_locked to restore the valid lock stack. + if (UseObjectMonitorTable) { + // UseObjectMonitorTable expects the BasicLock cache to be either a + // valid ObjectMonitor* or nullptr. Right now it is garbage, set it + // to nullptr. + lock->clear_object_monitor_cache(); } + ObjectSynchronizer::enter_for(obj, lock, deoptee_thread); + if (deoptee_thread->lock_stack().contains(obj())) { + LightweightSynchronizer::inflate_fast_locked_object(obj(), ObjectSynchronizer::InflateCause::inflate_cause_vm_internal, + deoptee_thread, thread); + } + assert(mon_info->owner()->is_locked(), "object must be locked now"); + assert(obj->mark().has_monitor(), "must be"); + assert(!deoptee_thread->lock_stack().contains(obj()), "must be"); + assert(ObjectSynchronizer::read_monitor(thread, obj(), obj->mark())->has_owner(deoptee_thread), "must be"); } } } diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index 9149e389e21..e76b7474891 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -1048,10 +1048,6 @@ const int ObjectAlignmentInBytes = 8; product(bool, ErrorFileToStdout, false, \ "If true, error data is printed to stdout instead of a file") \ \ - develop(bool, VerifyHeavyMonitors, false, \ - "Checks that no stack locking happens when using " \ - "-XX:LockingMode=0 (LM_MONITOR)") \ - \ product(bool, PrintStringTableStatistics, false, \ "print statistics about the StringTable and SymbolTable") \ \ diff --git a/src/hotspot/share/runtime/javaCalls.cpp b/src/hotspot/share/runtime/javaCalls.cpp index f237886c128..ec3132220d9 100644 --- a/src/hotspot/share/runtime/javaCalls.cpp +++ b/src/hotspot/share/runtime/javaCalls.cpp @@ -553,7 +553,7 @@ class SignatureChekker : public SignatureIterator { "Bad JNI oop argument %d: " PTR_FORMAT, _pos, v); // Verify the pointee. oop vv = resolve_indirect_oop(v, _value_state[_pos]); - guarantee(oopDesc::is_oop_or_null(vv, true), + guarantee(oopDesc::is_oop_or_null(vv), "Bad JNI oop argument %d: " PTR_FORMAT " -> " PTR_FORMAT, _pos, v, p2i(vv)); } diff --git a/src/hotspot/share/runtime/javaThread.cpp b/src/hotspot/share/runtime/javaThread.cpp index 89d742e0ea8..ba98f5928aa 100644 --- a/src/hotspot/share/runtime/javaThread.cpp +++ b/src/hotspot/share/runtime/javaThread.cpp @@ -1063,11 +1063,6 @@ JavaThread* JavaThread::active() { } } -bool JavaThread::is_lock_owned(address adr) const { - assert(LockingMode != LM_LIGHTWEIGHT, "should not be called with new lightweight locking"); - return is_in_full_stack(adr); -} - oop JavaThread::exception_oop() const { return Atomic::load(&_exception_oop); } @@ -1437,9 +1432,8 @@ void JavaThread::oops_do_no_frames(OopClosure* f, NMethodClosure* cf) { entry = entry->parent(); } - if (LockingMode == LM_LIGHTWEIGHT) { - lock_stack().oops_do(f); - } + // Due to lightweight locking + lock_stack().oops_do(f); } void JavaThread::oops_do_frames(OopClosure* f, NMethodClosure* cf) { @@ -1999,22 +1993,9 @@ void JavaThread::trace_stack() { // this slow-path. void JavaThread::inc_held_monitor_count(intx i, bool jni) { #ifdef SUPPORT_MONITOR_COUNT - - if (LockingMode != LM_LEGACY) { - // Nothing to do. Just do some sanity check. - assert(_held_monitor_count == 0, "counter should not be used"); - assert(_jni_monitor_count == 0, "counter should not be used"); - return; - } - - assert(_held_monitor_count >= 0, "Must always be non-negative: %zd", _held_monitor_count); - _held_monitor_count += i; - if (jni) { - assert(_jni_monitor_count >= 0, "Must always be non-negative: %zd", _jni_monitor_count); - _jni_monitor_count += i; - } - assert(_held_monitor_count >= _jni_monitor_count, "Monitor count discrepancy detected - held count " - "%zd is less than JNI count %zd", _held_monitor_count, _jni_monitor_count); + // Nothing to do. Just do some sanity check. + assert(_held_monitor_count == 0, "counter should not be used"); + assert(_jni_monitor_count == 0, "counter should not be used"); #endif // SUPPORT_MONITOR_COUNT } @@ -2022,26 +2003,9 @@ void JavaThread::inc_held_monitor_count(intx i, bool jni) { // this slow-path. void JavaThread::dec_held_monitor_count(intx i, bool jni) { #ifdef SUPPORT_MONITOR_COUNT - - if (LockingMode != LM_LEGACY) { - // Nothing to do. Just do some sanity check. - assert(_held_monitor_count == 0, "counter should not be used"); - assert(_jni_monitor_count == 0, "counter should not be used"); - return; - } - - _held_monitor_count -= i; - assert(_held_monitor_count >= 0, "Must always be non-negative: %zd", _held_monitor_count); - if (jni) { - _jni_monitor_count -= i; - assert(_jni_monitor_count >= 0, "Must always be non-negative: %zd", _jni_monitor_count); - } - // When a thread is detaching with still owned JNI monitors, the logic that releases - // the monitors doesn't know to set the "jni" flag and so the counts can get out of sync. - // So we skip this assert if the thread is exiting. Once all monitors are unlocked the - // JNI count is directly set to zero. - assert(_held_monitor_count >= _jni_monitor_count || is_exiting(), "Monitor count discrepancy detected - held count " - "%zd is less than JNI count %zd", _held_monitor_count, _jni_monitor_count); + // Nothing to do. Just do some sanity check. + assert(_held_monitor_count == 0, "counter should not be used"); + assert(_jni_monitor_count == 0, "counter should not be used"); #endif // SUPPORT_MONITOR_COUNT } diff --git a/src/hotspot/share/runtime/javaThread.hpp b/src/hotspot/share/runtime/javaThread.hpp index bf72fac5737..32003e1962e 100644 --- a/src/hotspot/share/runtime/javaThread.hpp +++ b/src/hotspot/share/runtime/javaThread.hpp @@ -755,9 +755,6 @@ public: return (_suspend_flags & _obj_deopt) != 0; } - // Stack-locking support (not for LM_LIGHTWEIGHT) - bool is_lock_owned(address adr) const; - // Accessors for vframe array top // The linked list of vframe arrays are sorted on sp. This means when we // unpack the head must contain the vframe array to unpack. diff --git a/src/hotspot/share/runtime/lightweightSynchronizer.cpp b/src/hotspot/share/runtime/lightweightSynchronizer.cpp index 423ca990abd..6cec5c80982 100644 --- a/src/hotspot/share/runtime/lightweightSynchronizer.cpp +++ b/src/hotspot/share/runtime/lightweightSynchronizer.cpp @@ -333,8 +333,6 @@ size_t ObjectMonitorTable::_table_size = 0; volatile bool ObjectMonitorTable::_resize = false; ObjectMonitor* LightweightSynchronizer::get_or_insert_monitor_from_table(oop object, JavaThread* current, bool* inserted) { - assert(LockingMode == LM_LIGHTWEIGHT, "must be"); - ObjectMonitor* monitor = get_monitor_from_table(current, object); if (monitor != nullptr) { *inserted = false; @@ -628,7 +626,6 @@ bool LightweightSynchronizer::fast_lock_spin_enter(oop obj, LockStack& lock_stac } void LightweightSynchronizer::enter_for(Handle obj, BasicLock* lock, JavaThread* locking_thread) { - assert(LockingMode == LM_LIGHTWEIGHT, "must be"); assert(!UseObjectMonitorTable || lock->object_monitor_cache() == nullptr, "must be cleared"); JavaThread* current = JavaThread::current(); VerifyThreadState vts(locking_thread, current); @@ -657,7 +654,6 @@ void LightweightSynchronizer::enter_for(Handle obj, BasicLock* lock, JavaThread* } void LightweightSynchronizer::enter(Handle obj, BasicLock* lock, JavaThread* current) { - assert(LockingMode == LM_LIGHTWEIGHT, "must be"); assert(current == JavaThread::current(), "must be"); if (obj->klass()->is_value_based()) { @@ -718,7 +714,6 @@ void LightweightSynchronizer::enter(Handle obj, BasicLock* lock, JavaThread* cur } void LightweightSynchronizer::exit(oop object, BasicLock* lock, JavaThread* current) { - assert(LockingMode == LM_LIGHTWEIGHT, "must be"); assert(current == Thread::current(), "must be"); markWord mark = object->mark(); @@ -770,18 +765,14 @@ void LightweightSynchronizer::exit(oop object, BasicLock* lock, JavaThread* curr monitor->exit(current); } -// LightweightSynchronizer::inflate_locked_or_imse is used to to get an inflated -// ObjectMonitor* with LM_LIGHTWEIGHT. It is used from contexts which require -// an inflated ObjectMonitor* for a monitor, and expects to throw a -// java.lang.IllegalMonitorStateException if it is not held by the current -// thread. Such as notify/wait and jni_exit. LM_LIGHTWEIGHT keeps it invariant -// that it only inflates if it is already locked by the current thread or the -// current thread is in the process of entering. To maintain this invariant we -// need to throw a java.lang.IllegalMonitorStateException before inflating if -// the current thread is not the owner. -// LightweightSynchronizer::inflate_locked_or_imse facilitates this. +// LightweightSynchronizer::inflate_locked_or_imse is used to get an +// inflated ObjectMonitor* from contexts which require that, such as +// notify/wait and jni_exit. Lightweight locking keeps the invariant that it +// only inflates if it is already locked by the current thread or the current +// thread is in the process of entering. To maintain this invariant we need to +// throw a java.lang.IllegalMonitorStateException before inflating if the +// current thread is not the owner. ObjectMonitor* LightweightSynchronizer::inflate_locked_or_imse(oop obj, ObjectSynchronizer::InflateCause cause, TRAPS) { - assert(LockingMode == LM_LIGHTWEIGHT, "must be"); JavaThread* current = THREAD; for (;;) { @@ -826,12 +817,11 @@ ObjectMonitor* LightweightSynchronizer::inflate_locked_or_imse(oop obj, ObjectSy ObjectMonitor* LightweightSynchronizer::inflate_into_object_header(oop object, ObjectSynchronizer::InflateCause cause, JavaThread* locking_thread, Thread* current) { - // The JavaThread* locking_thread parameter is only used by LM_LIGHTWEIGHT and requires - // that the locking_thread == Thread::current() or is suspended throughout the call by - // some other mechanism. - // Even with LM_LIGHTWEIGHT the thread might be nullptr when called from a non + // The JavaThread* locking parameter requires that the locking_thread == JavaThread::current, + // or is suspended throughout the call by some other mechanism. + // Even with lightweight locking the thread might be nullptr when called from a non // JavaThread. (As may still be the case from FastHashCode). However it is only - // important for the correctness of the LM_LIGHTWEIGHT algorithm that the thread + // important for the correctness of the lightweight locking algorithm that the thread // is set when called from ObjectSynchronizer::enter from the owning thread, // ObjectSynchronizer::enter_for from any thread, or ObjectSynchronizer::exit. EventJavaMonitorInflate event; @@ -943,7 +933,6 @@ ObjectMonitor* LightweightSynchronizer::inflate_into_object_header(oop object, O } ObjectMonitor* LightweightSynchronizer::inflate_fast_locked_object(oop object, ObjectSynchronizer::InflateCause cause, JavaThread* locking_thread, JavaThread* current) { - assert(LockingMode == LM_LIGHTWEIGHT, "only used for lightweight"); VerifyThreadState vts(locking_thread, current); assert(locking_thread->lock_stack().contains(object), "locking_thread must have object on its lock stack"); @@ -1000,7 +989,6 @@ ObjectMonitor* LightweightSynchronizer::inflate_fast_locked_object(oop object, O } ObjectMonitor* LightweightSynchronizer::inflate_and_enter(oop object, BasicLock* lock, ObjectSynchronizer::InflateCause cause, JavaThread* locking_thread, JavaThread* current) { - assert(LockingMode == LM_LIGHTWEIGHT, "only used for lightweight"); VerifyThreadState vts(locking_thread, current); // Note: In some paths (deoptimization) the 'current' thread inflates and diff --git a/src/hotspot/share/runtime/lockStack.cpp b/src/hotspot/share/runtime/lockStack.cpp index cab54e420a9..a55c5a6451b 100644 --- a/src/hotspot/share/runtime/lockStack.cpp +++ b/src/hotspot/share/runtime/lockStack.cpp @@ -77,7 +77,6 @@ uint32_t LockStack::end_offset() { #ifndef PRODUCT void LockStack::verify(const char* msg) const { - assert(LockingMode == LM_LIGHTWEIGHT, "never use lock-stack when light weight locking is disabled"); assert((_top <= end_offset()), "lockstack overflow: _top %d end_offset %d", _top, end_offset()); assert((_top >= start_offset()), "lockstack underflow: _top %d start_offset %d", _top, start_offset()); if (SafepointSynchronize::is_at_safepoint() || (Thread::current()->is_Java_thread() && is_owning_thread())) { diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp index 9e3638ddadc..c1febe7a28c 100644 --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -296,8 +296,7 @@ ObjectMonitor::ObjectMonitor(oop object) : _contentions(0), _wait_set(nullptr), _waiters(0), - _wait_set_lock(0), - _stack_locker(nullptr) + _wait_set_lock(0) { } ObjectMonitor::~ObjectMonitor() { diff --git a/src/hotspot/share/runtime/objectMonitor.hpp b/src/hotspot/share/runtime/objectMonitor.hpp index c8daeb65b50..ab315ba0fc5 100644 --- a/src/hotspot/share/runtime/objectMonitor.hpp +++ b/src/hotspot/share/runtime/objectMonitor.hpp @@ -160,9 +160,9 @@ class ObjectMonitor : public CHeapObj { // Because of frequent access, the metadata field is at offset zero (0). // Enforced by the assert() in metadata_addr(). - // * LM_LIGHTWEIGHT with UseObjectMonitorTable: - // Contains the _object's hashCode. - // * LM_LEGACY, LM_MONITOR, LM_LIGHTWEIGHT without UseObjectMonitorTable: + // * Lightweight locking with UseObjectMonitorTable: + // Contains the _object's hashCode. + // * * Lightweight locking without UseObjectMonitorTable: // Contains the displaced object header word - mark volatile uintptr_t _metadata; // metadata WeakHandle _object; // backward object pointer @@ -204,9 +204,6 @@ class ObjectMonitor : public CHeapObj { volatile int _waiters; // number of waiting threads volatile int _wait_set_lock; // protects wait set queue - simple spinlock - // Used in LM_LEGACY mode to store BasicLock* in case of inflation by contending thread. - BasicLock* volatile _stack_locker; - public: static void Initialize(); @@ -318,10 +315,6 @@ class ObjectMonitor : public CHeapObj { set_owner_from(ANONYMOUS_OWNER, owner); } - // Get and set _stack_locker. - BasicLock* stack_locker() const; - void set_stack_locker(BasicLock* locker); - // Simply get _next_om field. ObjectMonitor* next_om() const; // Simply set _next_om field to new_value. diff --git a/src/hotspot/share/runtime/objectMonitor.inline.hpp b/src/hotspot/share/runtime/objectMonitor.inline.hpp index 7dabc50fca7..05ad06c9bf3 100644 --- a/src/hotspot/share/runtime/objectMonitor.inline.hpp +++ b/src/hotspot/share/runtime/objectMonitor.inline.hpp @@ -52,11 +52,7 @@ inline int64_t ObjectMonitor::owner_id_from(oop vthread) { inline bool ObjectMonitor::is_entered(JavaThread* current) const { if (has_anonymous_owner()) { - if (LockingMode == LM_LIGHTWEIGHT) { - return current->lock_stack().contains(object()); - } else { - return current->is_lock_owned((address)stack_locker()); - } + return current->lock_stack().contains(object()); } else { return has_owner(current); } @@ -116,14 +112,6 @@ inline int64_t ObjectMonitor::owner_raw() const { return Atomic::load(&_owner); } -inline BasicLock* ObjectMonitor::stack_locker() const { - return Atomic::load(&_stack_locker); -} - -inline void ObjectMonitor::set_stack_locker(BasicLock* locker) { - Atomic::store(&_stack_locker, locker); -} - // Returns true if owner field == DEFLATER_MARKER and false otherwise. inline bool ObjectMonitor::owner_is_DEFLATER_MARKER() const { return owner_raw() == DEFLATER_MARKER; diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp index 4d3f1327d43..60161643315 100644 --- a/src/hotspot/share/runtime/sharedRuntime.cpp +++ b/src/hotspot/share/runtime/sharedRuntime.cpp @@ -3348,18 +3348,7 @@ JRT_LEAF(intptr_t*, SharedRuntime::OSR_migration_begin( JavaThread *current) ) kptr2 = fr.next_monitor_in_interpreter_frame(kptr2) ) { if (kptr2->obj() != nullptr) { // Avoid 'holes' in the monitor array BasicLock *lock = kptr2->lock(); - if (LockingMode == LM_LEGACY) { - // Inflate so the object's header no longer refers to the BasicLock. - if (lock->displaced_header().is_unlocked()) { - // The object is locked and the resulting ObjectMonitor* will also be - // locked so it can't be async deflated until ownership is dropped. - // See the big comment in basicLock.cpp: BasicLock::move_to(). - ObjectSynchronizer::inflate_helper(kptr2->obj()); - } - // Now the displaced header is free to move because the - // object's header no longer refers to it. - buf[i] = (intptr_t)lock->displaced_header().value(); - } else if (UseObjectMonitorTable) { + if (UseObjectMonitorTable) { buf[i] = (intptr_t)lock->object_monitor_cache(); } #ifdef ASSERT diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp index f3e3072978b..ec4e91d8c6f 100644 --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -281,9 +281,7 @@ void ObjectSynchronizer::initialize() { // Start the timer for deflations, so it does not trigger immediately. _last_async_deflation_time_ns = os::javaTimeNanos(); - if (LockingMode == LM_LIGHTWEIGHT) { - LightweightSynchronizer::initialize(); - } + LightweightSynchronizer::initialize(); } MonitorList ObjectSynchronizer::_in_use_list; @@ -342,23 +340,15 @@ bool ObjectSynchronizer::quick_notify(oopDesc* obj, JavaThread* current, bool al if (obj == nullptr) return false; // slow-path for invalid obj const markWord mark = obj->mark(); - if (LockingMode == LM_LIGHTWEIGHT) { - if (mark.is_fast_locked() && current->lock_stack().contains(cast_to_oop(obj))) { - // Degenerate notify - // fast-locked by caller so by definition the implied waitset is empty. - return true; - } - } else if (LockingMode == LM_LEGACY) { - if (mark.has_locker() && current->is_lock_owned((address)mark.locker())) { - // Degenerate notify - // stack-locked by caller so by definition the implied waitset is empty. - return true; - } + if (mark.is_fast_locked() && current->lock_stack().contains(cast_to_oop(obj))) { + // Degenerate notify + // fast-locked by caller so by definition the implied waitset is empty. + return true; } if (mark.has_monitor()) { ObjectMonitor* const mon = read_monitor(current, obj, mark); - if (LockingMode == LM_LIGHTWEIGHT && mon == nullptr) { + if (mon == nullptr) { // Racing with inflation/deflation go slow path return false; } @@ -381,79 +371,6 @@ bool ObjectSynchronizer::quick_notify(oopDesc* obj, JavaThread* current, bool al return false; } -static bool useHeavyMonitors() { -#if defined(X86) || defined(AARCH64) || defined(PPC64) || defined(RISCV64) || defined(S390) - return LockingMode == LM_MONITOR; -#else - return false; -#endif -} - -// The LockNode emitted directly at the synchronization site would have -// been too big if it were to have included support for the cases of inflated -// recursive enter and exit, so they go here instead. -// Note that we can't safely call AsyncPrintJavaStack() from within -// quick_enter() as our thread state remains _in_Java. - -bool ObjectSynchronizer::quick_enter_legacy(oop obj, BasicLock* lock, JavaThread* current) { - assert(current->thread_state() == _thread_in_Java, "invariant"); - - if (useHeavyMonitors()) { - return false; // Slow path - } - - assert(LockingMode == LM_LEGACY, "legacy mode below"); - - const markWord mark = obj->mark(); - - if (mark.has_monitor()) { - - ObjectMonitor* const m = read_monitor(mark); - // An async deflation or GC 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_peek() == nullptr) { - return false; - } - - // Lock contention and Transactional Lock Elision (TLE) diagnostics - // and observability - // Case: light contention possibly amenable to TLE - // Case: TLE inimical operations such as nested/recursive synchronization - - if (m->has_owner(current)) { - m->increment_recursions(current); - current->inc_held_monitor_count(); - return true; - } - - // This Java Monitor is inflated so obj's header will never be - // displaced to this thread's BasicLock. Make the displaced header - // non-null so this BasicLock is not seen as recursive nor as - // being locked. We do this unconditionally so that this thread's - // BasicLock cannot be mis-interpreted by any stack walkers. For - // performance reasons, stack walkers generally first check for - // stack-locking in the object's header, the second check is for - // recursive stack-locking in the displaced header in the BasicLock, - // and last are the inflated Java Monitor (ObjectMonitor) checks. - lock->set_displaced_header(markWord::unused_mark()); - - if (!m->has_owner() && m->try_set_owner(current)) { - assert(m->recursions() == 0, "invariant"); - current->inc_held_monitor_count(); - return true; - } - } - - // Note that we could inflate in quick_enter. - // This is likely a useful optimization - // Critically, in quick_enter() we must not: - // -- block indefinitely, or - // -- reach a safepoint - - return false; // revert to slow-path -} - // Handle notifications when synchronizing on value based classes void ObjectSynchronizer::handle_sync_on_value_based_class(Handle obj, JavaThread* locking_thread) { assert(locking_thread == Thread::current() || locking_thread->is_obj_deopt_suspend(), "must be"); @@ -512,144 +429,7 @@ void ObjectSynchronizer::enter_for(Handle obj, BasicLock* lock, JavaThread* lock // the locking_thread with respect to the current thread. Currently only used when // deoptimizing and re-locking locks. See Deoptimization::relock_objects assert(locking_thread == Thread::current() || locking_thread->is_obj_deopt_suspend(), "must be"); - - if (LockingMode == LM_LIGHTWEIGHT) { - return LightweightSynchronizer::enter_for(obj, lock, locking_thread); - } - - if (!enter_fast_impl(obj, lock, locking_thread)) { - // Inflated ObjectMonitor::enter_for is required - - // An async deflation can race after the inflate_for() call and before - // enter_for() can make the ObjectMonitor busy. enter_for() returns false - // if we have lost the race to async deflation and we simply try again. - while (true) { - ObjectMonitor* monitor = inflate_for(locking_thread, obj(), inflate_cause_monitor_enter); - if (monitor->enter_for(locking_thread)) { - return; - } - assert(monitor->is_being_async_deflated(), "must be"); - } - } -} - -void ObjectSynchronizer::enter_legacy(Handle obj, BasicLock* lock, JavaThread* current) { - if (!enter_fast_impl(obj, lock, current)) { - // Inflated ObjectMonitor::enter is required - - // An async deflation can race after the inflate() call and before - // enter() can make the ObjectMonitor busy. enter() returns false if - // we have lost the race to async deflation and we simply try again. - while (true) { - ObjectMonitor* monitor = inflate(current, obj(), inflate_cause_monitor_enter); - if (monitor->enter(current)) { - return; - } - } - } -} - -// The interpreter and compiler assembly code tries to lock using the fast path -// of this algorithm. Make sure to update that code if the following function is -// changed. The implementation is extremely sensitive to race condition. Be careful. -bool ObjectSynchronizer::enter_fast_impl(Handle obj, BasicLock* lock, JavaThread* locking_thread) { - assert(LockingMode != LM_LIGHTWEIGHT, "Use LightweightSynchronizer"); - - if (obj->klass()->is_value_based()) { - handle_sync_on_value_based_class(obj, locking_thread); - } - - locking_thread->inc_held_monitor_count(); - - if (!useHeavyMonitors()) { - if (LockingMode == LM_LEGACY) { - markWord mark = obj->mark(); - if (mark.is_unlocked()) { - // Anticipate successful CAS -- the ST of the displaced mark must - // be visible <= the ST performed by the CAS. - lock->set_displaced_header(mark); - if (mark == obj()->cas_set_mark(markWord::from_pointer(lock), mark)) { - return true; - } - } else if (mark.has_locker() && - locking_thread->is_lock_owned((address) mark.locker())) { - assert(lock != mark.locker(), "must not re-lock the same lock"); - assert(lock != (BasicLock*) obj->mark().value(), "don't relock with same BasicLock"); - lock->set_displaced_header(markWord::from_pointer(nullptr)); - return true; - } - - // The object header will never be displaced to this lock, - // so it does not matter what the value is, except that it - // must be non-zero to avoid looking like a re-entrant lock, - // and must not look locked either. - lock->set_displaced_header(markWord::unused_mark()); - - // Failed to fast lock. - return false; - } - } else if (VerifyHeavyMonitors) { - guarantee((obj->mark().value() & markWord::lock_mask_in_place) != markWord::locked_value, "must not be lightweight/stack-locked"); - } - - return false; -} - -void ObjectSynchronizer::exit_legacy(oop object, BasicLock* lock, JavaThread* current) { - assert(LockingMode != LM_LIGHTWEIGHT, "Use LightweightSynchronizer"); - - if (!useHeavyMonitors()) { - markWord mark = object->mark(); - if (LockingMode == LM_LEGACY) { - markWord dhw = lock->displaced_header(); - if (dhw.value() == 0) { - // If the displaced header is null, then this exit matches up with - // a recursive enter. No real work to do here except for diagnostics. -#ifndef PRODUCT - if (mark != markWord::INFLATING()) { - // Only do diagnostics if we are not racing an inflation. Simply - // exiting a recursive enter of a Java Monitor that is being - // inflated is safe; see the has_monitor() comment below. - assert(!mark.is_unlocked(), "invariant"); - assert(!mark.has_locker() || - current->is_lock_owned((address)mark.locker()), "invariant"); - if (mark.has_monitor()) { - // The BasicLock's displaced_header is marked as a recursive - // enter and we have an inflated Java Monitor (ObjectMonitor). - // This is a special case where the Java Monitor was inflated - // after this thread entered the stack-lock recursively. When a - // Java Monitor is inflated, we cannot safely walk the Java - // Monitor owner's stack and update the BasicLocks because a - // Java Monitor can be asynchronously inflated by a thread that - // does not own the Java Monitor. - ObjectMonitor* m = read_monitor(mark); - assert(m->object()->mark() == mark, "invariant"); - assert(m->is_entered(current), "invariant"); - } - } -#endif - return; - } - - if (mark == markWord::from_pointer(lock)) { - // If the object is stack-locked by the current thread, try to - // swing the displaced header from the BasicLock back to the mark. - assert(dhw.is_neutral(), "invariant"); - if (object->cas_set_mark(dhw, mark) == mark) { - return; - } - } - } - } else if (VerifyHeavyMonitors) { - guarantee((object->mark().value() & markWord::lock_mask_in_place) != markWord::locked_value, "must not be lightweight/stack-locked"); - } - - // We have to take the slow-path of possible inflation and then exit. - // The ObjectMonitor* can't be async deflated until ownership is - // dropped inside exit() and the ObjectMonitor* must be !is_busy(). - ObjectMonitor* monitor = inflate(current, object, inflate_cause_vm_internal); - assert(!monitor->has_anonymous_owner(), "must not be"); - monitor->exit(current); + return LightweightSynchronizer::enter_for(obj, lock, locking_thread); } // ----------------------------------------------------------------------------- @@ -670,17 +450,8 @@ void ObjectSynchronizer::jni_enter(Handle obj, JavaThread* current) { // enter() can make the ObjectMonitor busy. enter() returns false if // we have lost the race to async deflation and we simply try again. while (true) { - ObjectMonitor* monitor; - bool entered; - if (LockingMode == LM_LIGHTWEIGHT) { - BasicLock lock; - entered = LightweightSynchronizer::inflate_and_enter(obj(), &lock, inflate_cause_jni_enter, current, current) != nullptr; - } else { - monitor = inflate(current, obj(), inflate_cause_jni_enter); - entered = monitor->enter(current); - } - - if (entered) { + BasicLock lock; + if (LightweightSynchronizer::inflate_and_enter(obj(), &lock, inflate_cause_jni_enter, current, current) != nullptr) { current->inc_held_monitor_count(1, true); break; } @@ -693,13 +464,7 @@ void ObjectSynchronizer::jni_exit(oop obj, TRAPS) { JavaThread* current = THREAD; ObjectMonitor* monitor; - if (LockingMode == LM_LIGHTWEIGHT) { - monitor = LightweightSynchronizer::inflate_locked_or_imse(obj, inflate_cause_jni_exit, CHECK); - } else { - // The ObjectMonitor* can't be async deflated until ownership is - // dropped inside exit() and the ObjectMonitor* must be !is_busy(). - monitor = inflate(current, obj, inflate_cause_jni_exit); - } + monitor = LightweightSynchronizer::inflate_locked_or_imse(obj, inflate_cause_jni_exit, CHECK); // If this thread has locked the object, exit the monitor. We // intentionally do not use CHECK on check_owner because we must exit the // monitor even if an exception was already pending. @@ -740,14 +505,7 @@ int ObjectSynchronizer::wait(Handle obj, jlong millis, TRAPS) { } ObjectMonitor* monitor; - if (LockingMode == LM_LIGHTWEIGHT) { - monitor = LightweightSynchronizer::inflate_locked_or_imse(obj(), inflate_cause_wait, CHECK_0); - } else { - // The ObjectMonitor* can't be async deflated because the _waiters - // field is incremented before ownership is dropped and decremented - // after ownership is regained. - monitor = inflate(current, obj(), inflate_cause_wait); - } + monitor = LightweightSynchronizer::inflate_locked_or_imse(obj(), inflate_cause_wait, CHECK_0); DTRACE_MONITOR_WAIT_PROBE(monitor, obj(), current, millis); monitor->wait(millis, true, THREAD); // Not CHECK as we need following code @@ -766,11 +524,7 @@ void ObjectSynchronizer::waitUninterruptibly(Handle obj, jlong millis, TRAPS) { } ObjectMonitor* monitor; - if (LockingMode == LM_LIGHTWEIGHT) { - monitor = LightweightSynchronizer::inflate_locked_or_imse(obj(), inflate_cause_wait, CHECK); - } else { - monitor = inflate(THREAD, obj(), inflate_cause_wait); - } + monitor = LightweightSynchronizer::inflate_locked_or_imse(obj(), inflate_cause_wait, CHECK); monitor->wait(millis, false, THREAD); } @@ -779,26 +533,11 @@ void ObjectSynchronizer::notify(Handle obj, TRAPS) { JavaThread* current = THREAD; markWord mark = obj->mark(); - if (LockingMode == LM_LIGHTWEIGHT) { - if ((mark.is_fast_locked() && current->lock_stack().contains(obj()))) { - // Not inflated so there can't be any waiters to notify. - return; - } - } else if (LockingMode == LM_LEGACY) { - if (mark.has_locker() && current->is_lock_owned((address)mark.locker())) { - // Not inflated so there can't be any waiters to notify. - return; - } - } - - ObjectMonitor* monitor; - if (LockingMode == LM_LIGHTWEIGHT) { - monitor = LightweightSynchronizer::inflate_locked_or_imse(obj(), inflate_cause_notify, CHECK); - } else { - // The ObjectMonitor* can't be async deflated until ownership is - // dropped by the calling thread. - monitor = inflate(current, obj(), inflate_cause_notify); + if ((mark.is_fast_locked() && current->lock_stack().contains(obj()))) { + // Not inflated so there can't be any waiters to notify. + return; } + ObjectMonitor* monitor = LightweightSynchronizer::inflate_locked_or_imse(obj(), inflate_cause_notify, CHECK); monitor->notify(CHECK); } @@ -807,26 +546,12 @@ void ObjectSynchronizer::notifyall(Handle obj, TRAPS) { JavaThread* current = THREAD; markWord mark = obj->mark(); - if (LockingMode == LM_LIGHTWEIGHT) { - if ((mark.is_fast_locked() && current->lock_stack().contains(obj()))) { - // Not inflated so there can't be any waiters to notify. - return; - } - } else if (LockingMode == LM_LEGACY) { - if (mark.has_locker() && current->is_lock_owned((address)mark.locker())) { - // Not inflated so there can't be any waiters to notify. - return; - } + if ((mark.is_fast_locked() && current->lock_stack().contains(obj()))) { + // Not inflated so there can't be any waiters to notify. + return; } - ObjectMonitor* monitor; - if (LockingMode == LM_LIGHTWEIGHT) { - monitor = LightweightSynchronizer::inflate_locked_or_imse(obj(), inflate_cause_notify, CHECK); - } else { - // The ObjectMonitor* can't be async deflated until ownership is - // dropped by the calling thread. - monitor = inflate(current, obj(), inflate_cause_notify); - } + ObjectMonitor* monitor = LightweightSynchronizer::inflate_locked_or_imse(obj(), inflate_cause_notify, CHECK); monitor->notifyAll(CHECK); } @@ -846,67 +571,6 @@ struct SharedGlobals { static SharedGlobals GVars; -static markWord read_stable_mark(oop obj) { - markWord mark = obj->mark_acquire(); - if (!mark.is_being_inflated() || LockingMode == LM_LIGHTWEIGHT) { - // New lightweight locking does not use the markWord::INFLATING() protocol. - return mark; // normal fast-path return - } - - int its = 0; - for (;;) { - markWord mark = obj->mark_acquire(); - if (!mark.is_being_inflated()) { - return mark; // normal fast-path return - } - - // The object is being inflated by some other thread. - // The caller of read_stable_mark() must wait for inflation to complete. - // Avoid live-lock. - - ++its; - if (its > 10000 || !os::is_MP()) { - if (its & 1) { - os::naked_yield(); - } else { - // Note that the following code attenuates the livelock problem but is not - // a complete remedy. A more complete solution would require that the inflating - // thread hold the associated inflation lock. The following code simply restricts - // the number of spinners to at most one. We'll have N-2 threads blocked - // on the inflationlock, 1 thread holding the inflation lock and using - // a yield/park strategy, and 1 thread in the midst of inflation. - // A more refined approach would be to change the encoding of INFLATING - // to allow encapsulation of a native thread pointer. Threads waiting for - // inflation to complete would use CAS to push themselves onto a singly linked - // list rooted at the markword. Once enqueued, they'd loop, checking a per-thread flag - // and calling park(). When inflation was complete the thread that accomplished inflation - // would detach the list and set the markword to inflated with a single CAS and - // then for each thread on the list, set the flag and unpark() the thread. - - // Index into the lock array based on the current object address. - static_assert(is_power_of_2(inflation_lock_count()), "must be"); - size_t ix = (cast_from_oop(obj) >> 5) & (inflation_lock_count() - 1); - int YieldThenBlock = 0; - assert(ix < inflation_lock_count(), "invariant"); - inflation_lock(ix)->lock(); - while (obj->mark_acquire() == markWord::INFLATING()) { - // Beware: naked_yield() is advisory and has almost no effect on some platforms - // so we periodically call current->_ParkEvent->park(1). - // We use a mixed spin/yield/block mechanism. - if ((YieldThenBlock++) >= 16) { - Thread::current()->_ParkEvent->park(1); - } else { - os::naked_yield(); - } - } - inflation_lock(ix)->unlock(); - } - } else { - SpinPause(); // SMP-polite spinning - } - } -} - // hashCode() generation : // // Possibilities: @@ -965,7 +629,7 @@ static intptr_t get_next_hash(Thread* current, oop obj) { } static intptr_t install_hash_code(Thread* current, oop obj) { - assert(UseObjectMonitorTable && LockingMode == LM_LIGHTWEIGHT, "must be"); + assert(UseObjectMonitorTable, "must be"); markWord mark = obj->mark_acquire(); for (;;) { @@ -996,12 +660,8 @@ intptr_t ObjectSynchronizer::FastHashCode(Thread* current, oop obj) { ObjectMonitor* monitor = nullptr; markWord temp, test; intptr_t hash; - markWord mark = read_stable_mark(obj); - if (VerifyHeavyMonitors) { - assert(LockingMode == LM_MONITOR, "+VerifyHeavyMonitors requires LockingMode == 0 (LM_MONITOR)"); - guarantee((obj->mark().value() & markWord::lock_mask_in_place) != markWord::locked_value, "must not be lightweight/stack-locked"); - } - if (mark.is_unlocked() || (LockingMode == LM_LIGHTWEIGHT && mark.is_fast_locked())) { + markWord mark = obj->mark_acquire(); + if (mark.is_unlocked() || mark.is_fast_locked()) { hash = mark.hash(); if (hash != 0) { // if it has a hash, just return it return hash; @@ -1013,10 +673,9 @@ intptr_t ObjectSynchronizer::FastHashCode(Thread* current, oop obj) { if (test == mark) { // if the hash was installed, return it return hash; } - if (LockingMode == LM_LIGHTWEIGHT) { - // CAS failed, retry - continue; - } + // CAS failed, retry + continue; + // Failed to install the hash. It could be that another thread // installed the hash just before our attempt or inflation has // occurred or... so we fall thru to inflate the monitor for @@ -1048,34 +707,14 @@ intptr_t ObjectSynchronizer::FastHashCode(Thread* current, oop obj) { } // Fall thru so we only have one place that installs the hash in // the ObjectMonitor. - } else if (LockingMode == LM_LEGACY && mark.has_locker() - && current->is_Java_thread() - && JavaThread::cast(current)->is_lock_owned((address)mark.locker())) { - // This is a stack-lock owned by the calling thread so fetch the - // displaced markWord from the BasicLock on the stack. - temp = mark.displaced_mark_helper(); - 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; - } - // WARNING: - // The displaced header in the BasicLock on a thread's stack - // is strictly immutable. It CANNOT be changed in ANY cases. - // So we have to inflate the stack-lock into an ObjectMonitor - // even if the current thread owns the lock. The BasicLock on - // a thread's stack can be asynchronously read by other threads - // during an inflate() call so any change to that stack memory - // may not propagate to other threads correctly. } - // Inflate the monitor to set the hash. - - // There's no need to inflate if the mark has already got a monitor. // NOTE: an async deflation can race after we get the monitor and // before we can update the ObjectMonitor's header with the hash // value below. - monitor = mark.has_monitor() ? mark.monitor() : inflate(current, obj, inflate_cause_hash_code); + assert(mark.has_monitor(), "must be"); + monitor = mark.monitor(); + // 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()); @@ -1115,19 +754,14 @@ bool ObjectSynchronizer::current_thread_holds_lock(JavaThread* current, assert(current == JavaThread::current(), "Can only be called on current thread"); oop obj = h_obj(); - markWord mark = read_stable_mark(obj); + markWord mark = obj->mark_acquire(); - if (LockingMode == LM_LEGACY && mark.has_locker()) { - // stack-locked case, header points into owner's stack - return current->is_lock_owned((address)mark.locker()); - } - - if (LockingMode == LM_LIGHTWEIGHT && mark.is_fast_locked()) { + if (mark.is_fast_locked()) { // fast-locking case, see if lock is in current's lock stack return current->lock_stack().contains(h_obj()); } - while (LockingMode == LM_LIGHTWEIGHT && mark.has_monitor()) { + while (mark.has_monitor()) { ObjectMonitor* monitor = read_monitor(current, obj, mark); if (monitor != nullptr) { return monitor->is_entered(current) != 0; @@ -1141,13 +775,6 @@ bool ObjectSynchronizer::current_thread_holds_lock(JavaThread* current, } } - if (LockingMode != LM_LIGHTWEIGHT && mark.has_monitor()) { - // Inflated monitor so header points to ObjectMonitor (tagged pointer). - // The first stage of async deflation does not affect any field - // used by this comparison so the ObjectMonitor* is usable here. - ObjectMonitor* monitor = read_monitor(mark); - return monitor->is_entered(current) != 0; - } // Unlocked case, header in place assert(mark.is_unlocked(), "sanity check"); return false; @@ -1155,21 +782,15 @@ bool ObjectSynchronizer::current_thread_holds_lock(JavaThread* current, JavaThread* ObjectSynchronizer::get_lock_owner(ThreadsList * t_list, Handle h_obj) { oop obj = h_obj(); - markWord mark = read_stable_mark(obj); + markWord mark = obj->mark_acquire(); - if (LockingMode == LM_LEGACY && mark.has_locker()) { - // stack-locked so header points into owner's stack. - // owning_thread_from_monitor_owner() may also return null here: - return Threads::owning_thread_from_stacklock(t_list, (address) mark.locker()); - } - - if (LockingMode == LM_LIGHTWEIGHT && mark.is_fast_locked()) { + if (mark.is_fast_locked()) { // fast-locked so get owner from the object. // owning_thread_from_object() may also return null here: return Threads::owning_thread_from_object(t_list, h_obj()); } - while (LockingMode == LM_LIGHTWEIGHT && mark.has_monitor()) { + while (mark.has_monitor()) { ObjectMonitor* monitor = read_monitor(Thread::current(), obj, mark); if (monitor != nullptr) { return Threads::owning_thread_from_monitor(t_list, monitor); @@ -1183,16 +804,6 @@ JavaThread* ObjectSynchronizer::get_lock_owner(ThreadsList * t_list, Handle h_ob } } - if (LockingMode != LM_LIGHTWEIGHT && mark.has_monitor()) { - // Inflated monitor so header points to ObjectMonitor (tagged pointer). - // The first stage of async deflation does not affect any field - // used by this comparison so the ObjectMonitor* is usable here. - ObjectMonitor* monitor = read_monitor(mark); - assert(monitor != nullptr, "monitor should be non-null"); - // owning_thread_from_monitor() may also return null here: - return Threads::owning_thread_from_monitor(t_list, monitor); - } - // Unlocked case, header in place // Cannot have assertion since this object may have been // locked by another thread when reaching here. @@ -1415,230 +1026,6 @@ jlong ObjectSynchronizer::time_since_last_async_deflation_ms() { return (os::javaTimeNanos() - last_async_deflation_time_ns()) / (NANOUNITS / MILLIUNITS); } -static void post_monitor_inflate_event(EventJavaMonitorInflate* event, - const oop obj, - ObjectSynchronizer::InflateCause cause) { - assert(event != nullptr, "invariant"); - const Klass* monitor_klass = obj->klass(); - if (ObjectMonitor::is_jfr_excluded(monitor_klass)) { - return; - } - event->set_monitorClass(monitor_klass); - event->set_address((uintptr_t)(void*)obj); - event->set_cause((u1)cause); - event->commit(); -} - -// Fast path code shared by multiple functions -void ObjectSynchronizer::inflate_helper(oop obj) { - assert(LockingMode != LM_LIGHTWEIGHT, "only inflate through enter"); - markWord mark = obj->mark_acquire(); - if (mark.has_monitor()) { - ObjectMonitor* monitor = read_monitor(mark); - markWord dmw = monitor->header(); - assert(dmw.is_neutral(), "sanity check: header=" INTPTR_FORMAT, dmw.value()); - return; - } - (void)inflate(Thread::current(), obj, inflate_cause_vm_internal); -} - -ObjectMonitor* ObjectSynchronizer::inflate(Thread* current, oop obj, const InflateCause cause) { - assert(current == Thread::current(), "must be"); - assert(LockingMode != LM_LIGHTWEIGHT, "only inflate through enter"); - return inflate_impl(current->is_Java_thread() ? JavaThread::cast(current) : nullptr, obj, cause); -} - -ObjectMonitor* ObjectSynchronizer::inflate_for(JavaThread* thread, oop obj, const InflateCause cause) { - assert(thread == Thread::current() || thread->is_obj_deopt_suspend(), "must be"); - assert(LockingMode != LM_LIGHTWEIGHT, "LM_LIGHTWEIGHT cannot use inflate_for"); - return inflate_impl(thread, obj, cause); -} - -ObjectMonitor* ObjectSynchronizer::inflate_impl(JavaThread* locking_thread, oop object, const InflateCause cause) { - // The JavaThread* locking_thread requires that the locking_thread == Thread::current() or - // is suspended throughout the call by some other mechanism. - // The thread might be nullptr when called from a non JavaThread. (As may still be - // the case from FastHashCode). However it is only important for correctness that the - // thread is set when called from ObjectSynchronizer::enter from the owning thread, - // ObjectSynchronizer::enter_for from any thread, or ObjectSynchronizer::exit. - assert(LockingMode != LM_LIGHTWEIGHT, "LM_LIGHTWEIGHT cannot use inflate_impl"); - EventJavaMonitorInflate event; - - for (;;) { - const markWord mark = object->mark_acquire(); - - // The mark can be in one of the following states: - // * inflated - If the ObjectMonitor owner is anonymous and the - // locking_thread owns the object lock, then we - // make the locking_thread the ObjectMonitor owner. - // * stack-locked - Coerce it to inflated from stack-locked. - // * INFLATING - Busy wait for conversion from stack-locked to - // inflated. - // * unlocked - Aggressively inflate the object. - - // CASE: inflated - if (mark.has_monitor()) { - ObjectMonitor* inf = mark.monitor(); - markWord dmw = inf->header(); - assert(dmw.is_neutral(), "invariant: header=" INTPTR_FORMAT, dmw.value()); - if (inf->has_anonymous_owner() && locking_thread != nullptr) { - assert(LockingMode == LM_LEGACY, "invariant"); - if (locking_thread->is_lock_owned((address)inf->stack_locker())) { - inf->set_stack_locker(nullptr); - inf->set_owner_from_anonymous(locking_thread); - } - } - return inf; - } - - // CASE: inflation in progress - inflating over a stack-lock. - // Some other thread is converting from stack-locked to inflated. - // Only that thread can complete inflation -- other threads must wait. - // The INFLATING value is transient. - // Currently, we spin/yield/park and poll the markword, waiting for inflation to finish. - // We could always eliminate polling by parking the thread on some auxiliary list. - if (mark == markWord::INFLATING()) { - read_stable_mark(object); - continue; - } - - // CASE: stack-locked - // Could be stack-locked either by current or by some other thread. - // - // Note that we allocate the ObjectMonitor speculatively, _before_ attempting - // to install INFLATING into the mark word. We originally installed INFLATING, - // allocated the ObjectMonitor, and then finally STed the address of the - // ObjectMonitor into the mark. This was correct, but artificially lengthened - // the interval in which INFLATING appeared in the mark, thus increasing - // the odds of inflation contention. If we lose the race to set INFLATING, - // then we just delete the ObjectMonitor and loop around again. - // - LogStreamHandle(Trace, monitorinflation) lsh; - if (LockingMode == LM_LEGACY && mark.has_locker()) { - ObjectMonitor* m = new ObjectMonitor(object); - // Optimistically prepare the ObjectMonitor - anticipate successful CAS - // We do this before the CAS in order to minimize the length of time - // in which INFLATING appears in the mark. - - markWord cmp = object->cas_set_mark(markWord::INFLATING(), mark); - if (cmp != mark) { - delete m; - continue; // Interference -- just retry - } - - // We've successfully installed INFLATING (0) into the mark-word. - // This is the only case where 0 will appear in a mark-word. - // Only the singular thread that successfully swings the mark-word - // to 0 can perform (or more precisely, complete) inflation. - // - // Why do we CAS a 0 into the mark-word instead of just CASing the - // mark-word from the stack-locked value directly to the new inflated state? - // Consider what happens when a thread unlocks a stack-locked object. - // It attempts to use CAS to swing the displaced header value from the - // on-stack BasicLock back into the object header. Recall also that the - // header value (hash code, etc) can reside in (a) the object header, or - // (b) a displaced header associated with the stack-lock, or (c) a displaced - // header in an ObjectMonitor. The inflate() routine must copy the header - // value from the BasicLock on the owner's stack to the ObjectMonitor, all - // the while preserving the hashCode stability invariants. If the owner - // decides to release the lock while the value is 0, the unlock will fail - // and control will eventually pass from slow_exit() to inflate. The owner - // will then spin, waiting for the 0 value to disappear. Put another way, - // the 0 causes the owner to stall if the owner happens to try to - // drop the lock (restoring the header from the BasicLock to the object) - // while inflation is in-progress. This protocol avoids races that might - // would otherwise permit hashCode values to change or "flicker" for an object. - // Critically, while object->mark is 0 mark.displaced_mark_helper() is stable. - // 0 serves as a "BUSY" inflate-in-progress indicator. - - - // fetch the displaced mark from the owner's stack. - // The owner can't die or unwind past the lock while our INFLATING - // object is in the mark. Furthermore the owner can't complete - // an unlock on the object, either. - 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). - assert(dmw.is_neutral(), "invariant: header=" INTPTR_FORMAT, dmw.value()); - - // Setup monitor fields to proper values -- prepare the monitor - m->set_header(dmw); - - // 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-nullptr .... ST idiom. - if (locking_thread != nullptr && locking_thread->is_lock_owned((address)mark.locker())) { - m->set_owner(locking_thread); - } else { - // Use ANONYMOUS_OWNER to indicate that the owner is the BasicLock on the stack, - // and set the stack locker field in the monitor. - m->set_stack_locker(mark.locker()); - m->set_anonymous_owner(); - } - // TODO-FIXME: assert BasicLock->dhw != 0. - - // Must preserve store ordering. The monitor state must - // be stable at the time of publishing the monitor address. - guarantee(object->mark() == markWord::INFLATING(), "invariant"); - // Release semantics so that above set_object() is seen first. - object->release_set_mark(markWord::encode(m)); - - // Once ObjectMonitor is configured and the object is associated - // with the ObjectMonitor, it is safe to allow async deflation: - _in_use_list.add(m); - - if (log_is_enabled(Trace, monitorinflation)) { - ResourceMark rm; - lsh.print_cr("inflate(has_locker): object=" INTPTR_FORMAT ", mark=" - INTPTR_FORMAT ", type='%s'", p2i(object), - object->mark().value(), object->klass()->external_name()); - } - if (event.should_commit()) { - post_monitor_inflate_event(&event, object, cause); - } - return m; - } - - // CASE: unlocked - // TODO-FIXME: for entry we currently inflate and then try to CAS _owner. - // If we know we're inflating for entry it's better to inflate by swinging a - // pre-locked ObjectMonitor pointer into the object header. A successful - // CAS inflates the object *and* confers ownership to the inflating thread. - // In the current implementation we use a 2-step mechanism where we CAS() - // to inflate and then CAS() again to try to swing _owner from null to current. - // An inflateTry() method that we could call from enter() would be useful. - - assert(mark.is_unlocked(), "invariant: header=" INTPTR_FORMAT, mark.value()); - ObjectMonitor* m = new ObjectMonitor(object); - // prepare m for installation - set monitor to initial state - m->set_header(mark); - - if (object->cas_set_mark(markWord::encode(m), mark) != mark) { - delete m; - m = nullptr; - continue; - // interference - the markword changed - just retry. - // The state-transitions are one-way, so there's no chance of - // live-lock -- "Inflated" is an absorbing state. - } - - // Once the ObjectMonitor is configured and object is associated - // with the ObjectMonitor, it is safe to allow async deflation: - _in_use_list.add(m); - - if (log_is_enabled(Trace, monitorinflation)) { - ResourceMark rm; - lsh.print_cr("inflate(unlocked): object=" INTPTR_FORMAT ", mark=" - INTPTR_FORMAT ", type='%s'", p2i(object), - object->mark().value(), object->klass()->external_name()); - } - if (event.should_commit()) { - post_monitor_inflate_event(&event, object, cause); - } - return m; - } -} - // Walk the in-use list and deflate (at most MonitorDeflationMax) idle // ObjectMonitors. Returns the number of deflated ObjectMonitors. // @@ -1914,7 +1301,6 @@ const char* ObjectSynchronizer::inflate_cause_name(const InflateCause cause) { case inflate_cause_monitor_enter: return "Monitor Enter"; case inflate_cause_wait: return "Monitor Wait"; case inflate_cause_notify: return "Monitor Notify"; - case inflate_cause_hash_code: return "Monitor Hash Code"; case inflate_cause_jni_enter: return "JNI Monitor Enter"; case inflate_cause_jni_exit: return "JNI Monitor Exit"; default: diff --git a/src/hotspot/share/runtime/synchronizer.hpp b/src/hotspot/share/runtime/synchronizer.hpp index e35c3651f5b..419cf2bf5bb 100644 --- a/src/hotspot/share/runtime/synchronizer.hpp +++ b/src/hotspot/share/runtime/synchronizer.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -73,16 +73,15 @@ class ObjectSynchronizer : AllStatic { friend class ObjectMonitorDeflationLogging; friend class WhiteBox; - public: +public: typedef enum { inflate_cause_vm_internal = 0, inflate_cause_monitor_enter = 1, inflate_cause_wait = 2, inflate_cause_notify = 3, - inflate_cause_hash_code = 4, - inflate_cause_jni_enter = 5, - inflate_cause_jni_exit = 6, - inflate_cause_nof = 7 // Number of causes + inflate_cause_jni_enter = 4, + inflate_cause_jni_exit = 5, + inflate_cause_nof = 6 // Number of causes } InflateCause; typedef enum { @@ -104,15 +103,7 @@ class ObjectSynchronizer : AllStatic { // locked on is either already locked by the locking_thread or cannot // escape the locking_thread. static void enter_for(Handle obj, BasicLock* lock, JavaThread* locking_thread); -private: - // Shared implementation for enter and enter_for. Performs all but - // inflated monitor enter. - static bool enter_fast_impl(Handle obj, BasicLock* lock, JavaThread* locking_thread); - static bool quick_enter_legacy(oop obj, BasicLock* Lock, JavaThread* current); - static void enter_legacy(Handle obj, BasicLock* Lock, JavaThread* current); - static void exit_legacy(oop obj, BasicLock* lock, JavaThread* current); -public: // Used only to handle jni locks or other unmatched monitor enter/exit // Internally they will use heavy weight monitor. static void jni_enter(Handle obj, JavaThread* current); @@ -131,18 +122,7 @@ public: // throwing unexpected InterruptedExecutionExceptions. static void waitUninterruptibly(Handle obj, jlong Millis, TRAPS); - // Inflate light weight monitor to heavy weight monitor - static ObjectMonitor* inflate(Thread* current, oop obj, const InflateCause cause); - // Used to inflate a monitor as if it was done from the thread JavaThread. - static ObjectMonitor* inflate_for(JavaThread* thread, oop obj, const InflateCause cause); - -private: - // Shared implementation between the different LockingMode. - static ObjectMonitor* inflate_impl(JavaThread* locking_thread, oop obj, const InflateCause cause); - public: - // This version is only for internal use - static void inflate_helper(oop obj); static const char* inflate_cause_name(const InflateCause cause); inline static ObjectMonitor* read_monitor(markWord mark); diff --git a/src/hotspot/share/runtime/synchronizer.inline.hpp b/src/hotspot/share/runtime/synchronizer.inline.hpp index ac9116088f7..a44fe817276 100644 --- a/src/hotspot/share/runtime/synchronizer.inline.hpp +++ b/src/hotspot/share/runtime/synchronizer.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,11 +45,7 @@ inline ObjectMonitor* ObjectSynchronizer::read_monitor(Thread* current, oop obj, inline void ObjectSynchronizer::enter(Handle obj, BasicLock* lock, JavaThread* current) { assert(current == Thread::current(), "must be"); - if (LockingMode == LM_LIGHTWEIGHT) { LightweightSynchronizer::enter(obj, lock, current); - } else { - enter_legacy(obj, lock, current); - } } inline bool ObjectSynchronizer::quick_enter(oop obj, BasicLock* lock, JavaThread* current) { @@ -61,21 +57,13 @@ inline bool ObjectSynchronizer::quick_enter(oop obj, BasicLock* lock, JavaThread return false; } - if (LockingMode == LM_LIGHTWEIGHT) { - return LightweightSynchronizer::quick_enter(obj, lock, current); - } else { - return quick_enter_legacy(obj, lock, current); - } + return LightweightSynchronizer::quick_enter(obj, lock, current); } inline void ObjectSynchronizer::exit(oop object, BasicLock* lock, JavaThread* current) { current->dec_held_monitor_count(); - if (LockingMode == LM_LIGHTWEIGHT) { - LightweightSynchronizer::exit(object, lock, current); - } else { - exit_legacy(object, lock, current); - } + LightweightSynchronizer::exit(object, lock, current); } #endif // SHARE_RUNTIME_SYNCHRONIZER_INLINE_HPP diff --git a/src/hotspot/share/runtime/threads.cpp b/src/hotspot/share/runtime/threads.cpp index 3cf1058b6f7..65eea9d5fb2 100644 --- a/src/hotspot/share/runtime/threads.cpp +++ b/src/hotspot/share/runtime/threads.cpp @@ -1294,21 +1294,7 @@ GrowableArray* Threads::get_pending_threads(ThreadsList * t_list, } #endif // INCLUDE_JVMTI -JavaThread *Threads::owning_thread_from_stacklock(ThreadsList * t_list, address basicLock) { - assert(LockingMode == LM_LEGACY, "Not with new lightweight locking"); - - JavaThread* the_owner = nullptr; - for (JavaThread* q : *t_list) { - if (q->is_lock_owned(basicLock)) { - the_owner = q; - break; - } - } - return the_owner; -} - JavaThread* Threads::owning_thread_from_object(ThreadsList * t_list, oop obj) { - assert(LockingMode == LM_LIGHTWEIGHT, "Only with new lightweight locking"); for (JavaThread* q : *t_list) { // Need to start processing before accessing oops in the thread. StackWatermark* watermark = StackWatermarkSet::get(q, StackWatermarkKind::gc); @@ -1325,12 +1311,7 @@ JavaThread* Threads::owning_thread_from_object(ThreadsList * t_list, oop obj) { JavaThread* Threads::owning_thread_from_monitor(ThreadsList* t_list, ObjectMonitor* monitor) { if (monitor->has_anonymous_owner()) { - if (LockingMode == LM_LIGHTWEIGHT) { - return owning_thread_from_object(t_list, monitor->object()); - } else { - assert(LockingMode == LM_LEGACY, "invariant"); - return owning_thread_from_stacklock(t_list, (address)monitor->stack_locker()); - } + return owning_thread_from_object(t_list, monitor->object()); } else { JavaThread* the_owner = nullptr; for (JavaThread* q : *t_list) { diff --git a/src/hotspot/share/runtime/threads.hpp b/src/hotspot/share/runtime/threads.hpp index 979b1dffe26..c6428c874f6 100644 --- a/src/hotspot/share/runtime/threads.hpp +++ b/src/hotspot/share/runtime/threads.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021, Azul Systems, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -134,9 +134,6 @@ public: static GrowableArray* get_pending_threads(ThreadsList * t_list, int count, address monitor); - // Get owning Java thread from the basicLock address. - static JavaThread *owning_thread_from_stacklock(ThreadsList * t_list, address basicLock); - static JavaThread* owning_thread_from_object(ThreadsList* t_list, oop obj); static JavaThread* owning_thread_from_monitor(ThreadsList* t_list, ObjectMonitor* owner); diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index 1fba55cde99..bc026887b84 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -673,7 +673,6 @@ volatile_nonstatic_field(ObjectMonitor, _metadata, uintptr_t) \ unchecked_nonstatic_field(ObjectMonitor, _object, sizeof(void *)) /* NOTE: no type */ \ volatile_nonstatic_field(ObjectMonitor, _owner, int64_t) \ - volatile_nonstatic_field(ObjectMonitor, _stack_locker, BasicLock*) \ volatile_nonstatic_field(ObjectMonitor, _next_om, ObjectMonitor*) \ volatile_nonstatic_field(BasicLock, _metadata, uintptr_t) \ nonstatic_field(ObjectMonitor, _contentions, int) \ @@ -1640,14 +1639,6 @@ declare_constant(T_NARROWKLASS_size) \ declare_constant(T_VOID_size) \ \ - /**********************************************/ \ - /* LockingMode enum (globalDefinitions.hpp) */ \ - /**********************************************/ \ - \ - declare_constant(LM_MONITOR) \ - declare_constant(LM_LEGACY) \ - declare_constant(LM_LIGHTWEIGHT) \ - \ /*********************************************/ \ /* MethodCompilation (globalDefinitions.hpp) */ \ /*********************************************/ \ diff --git a/src/hotspot/share/utilities/globalDefinitions.cpp b/src/hotspot/share/utilities/globalDefinitions.cpp index 84a0730212f..8a111a12607 100644 --- a/src/hotspot/share/utilities/globalDefinitions.cpp +++ b/src/hotspot/share/utilities/globalDefinitions.cpp @@ -56,8 +56,6 @@ int LogMinObjAlignmentInBytes = -1; // Oop encoding heap max uint64_t OopEncodingHeapMax = 0; -const int LockingMode = LM_LIGHTWEIGHT; - // Something to help porters sleep at night #ifdef ASSERT diff --git a/src/hotspot/share/utilities/globalDefinitions.hpp b/src/hotspot/share/utilities/globalDefinitions.hpp index 64ccae539a3..8217451a5c6 100644 --- a/src/hotspot/share/utilities/globalDefinitions.hpp +++ b/src/hotspot/share/utilities/globalDefinitions.hpp @@ -1004,17 +1004,6 @@ enum JavaThreadState { _thread_max_state = 12 // maximum thread state+1 - used for statistics allocation }; -enum LockingMode { - // Use only heavy monitors for locking - LM_MONITOR = 0, - // Legacy stack-locking, with monitors as 2nd tier - LM_LEGACY = 1, - // New lightweight locking, with monitors as 2nd tier - LM_LIGHTWEIGHT = 2 -}; - -extern const int LockingMode; - //---------------------------------------------------------------------------------------------------- // Special constants for debugging diff --git a/src/hotspot/share/utilities/vmError.cpp b/src/hotspot/share/utilities/vmError.cpp index a4d44a96878..81e357f1c4f 100644 --- a/src/hotspot/share/utilities/vmError.cpp +++ b/src/hotspot/share/utilities/vmError.cpp @@ -1078,7 +1078,7 @@ void VMError::report(outputStream* st, bool _verbose) { print_stack_location(st, _context, continuation); st->cr(); - STEP_IF("printing lock stack", _verbose && _thread != nullptr && _thread->is_Java_thread() && LockingMode == LM_LIGHTWEIGHT); + STEP_IF("printing lock stack", _verbose && _thread != nullptr && _thread->is_Java_thread()); st->print_cr("Lock stack of current Java thread (top to bottom):"); JavaThread::cast(_thread)->lock_stack().print_on(st); st->cr(); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ObjectMonitor.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ObjectMonitor.java index 25c5344506c..1bdbf8ce8a2 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ObjectMonitor.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ObjectMonitor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,8 +51,6 @@ public class ObjectMonitor extends VMObject { objectFieldOffset = f.getOffset(); f = type.getField("_owner"); ownerFieldOffset = f.getOffset(); - f = type.getField("_stack_locker"); - stackLockerFieldOffset = f.getOffset(); f = type.getField("_next_om"); nextOMFieldOffset = f.getOffset(); contentionsField = new CIntField(type.getCIntegerField("_contentions"), 0); @@ -89,7 +87,6 @@ public class ObjectMonitor extends VMObject { } public Address owner() { return addr.getAddressAt(ownerFieldOffset); } - public Address stackLocker() { return addr.getAddressAt(stackLockerFieldOffset); } // FIXME // void set_owner(void* owner); @@ -120,7 +117,6 @@ public class ObjectMonitor extends VMObject { private static long metadataFieldOffset; private static long objectFieldOffset; private static long ownerFieldOffset; - private static long stackLockerFieldOffset; private static long nextOMFieldOffset; private static CIntField contentionsField; private static CIntField waitersField; diff --git a/test/hotspot/gtest/runtime/test_lockStack.cpp b/test/hotspot/gtest/runtime/test_lockStack.cpp index 3163898e17d..6755541adb0 100644 --- a/test/hotspot/gtest/runtime/test_lockStack.cpp +++ b/test/hotspot/gtest/runtime/test_lockStack.cpp @@ -63,7 +63,7 @@ public: } while (false) TEST_VM_F(LockStackTest, is_recursive) { - if (LockingMode != LM_LIGHTWEIGHT || !VM_Version::supports_recursive_lightweight_locking()) { + if (!VM_Version::supports_recursive_lightweight_locking()) { return; } @@ -130,7 +130,7 @@ TEST_VM_F(LockStackTest, is_recursive) { } TEST_VM_F(LockStackTest, try_recursive_enter) { - if (LockingMode != LM_LIGHTWEIGHT || !VM_Version::supports_recursive_lightweight_locking()) { + if (!VM_Version::supports_recursive_lightweight_locking()) { return; } @@ -197,10 +197,6 @@ TEST_VM_F(LockStackTest, try_recursive_enter) { } TEST_VM_F(LockStackTest, contains) { - if (LockingMode != LM_LIGHTWEIGHT) { - return; - } - const bool test_recursive = VM_Version::supports_recursive_lightweight_locking(); JavaThread* THREAD = JavaThread::current(); @@ -263,10 +259,6 @@ TEST_VM_F(LockStackTest, contains) { } TEST_VM_F(LockStackTest, remove) { - if (LockingMode != LM_LIGHTWEIGHT) { - return; - } - const bool test_recursive = VM_Version::supports_recursive_lightweight_locking(); JavaThread* THREAD = JavaThread::current(); diff --git a/test/hotspot/jtreg/runtime/locking/TestRecursiveMonitorChurn.java b/test/hotspot/jtreg/runtime/locking/TestRecursiveMonitorChurn.java index e92e947ecfa..505d5cc7df7 100644 --- a/test/hotspot/jtreg/runtime/locking/TestRecursiveMonitorChurn.java +++ b/test/hotspot/jtreg/runtime/locking/TestRecursiveMonitorChurn.java @@ -53,9 +53,6 @@ public class TestRecursiveMonitorChurn { public static volatile Monitor monitor; public static void main(String[] args) { - if (WB.getBooleanVMFlag("VerifyHeavyMonitors")) { - throw new SkippedException("VerifyHeavyMonitors always inflates. Invalid test."); - } final long pre_monitor_count = WB.getInUseMonitorCount(); System.out.println(" Precount = " + pre_monitor_count); for (int i = 0; i < COUNT; i++) {