On Tue, 13 Aug 2024 14:52:03 GMT, Axel Boldt-Christmas <abold...@openjdk.org> 
wrote:

>> When inflating a monitor the `ObjectMonitor*` is written directly over the 
>> `markWord` and any overwritten data is displaced into a displaced 
>> `markWord`. This is problematic for concurrent GCs which needs extra care or 
>> looser semantics to use this displaced data. In Lilliput this data also 
>> contains the klass forcing this to be something that the GC has to take into 
>> account everywhere.
>> 
>> This patch introduces an alternative solution where locking only uses the 
>> lock bits of the `markWord` and inflation does not override and displace the 
>> `markWord`. This is done by keeping associations between objects and 
>> `ObjectMonitor*` in an external hash table. Different caching techniques are 
>> used to speedup lookups from compiled code.
>> 
>> A diagnostic VM option is introduced called `UseObjectMonitorTable`. It is 
>> only supported in combination with the LM_LIGHTWEIGHT locking mode (the 
>> default). 
>> 
>> This patch has been evaluated to be performance neutral when 
>> `UseObjectMonitorTable` is turned off (the default). 
>> 
>> Below is a more detailed explanation of this change and how `LM_LIGHTWEIGHT` 
>> and `UseObjectMonitorTable` works.
>> 
>> # Cleanups
>> 
>> Cleaned up displaced header usage for:
>>   * BasicLock
>>     * Contains some Zero changes
>>     * Renames one exported JVMCI field
>>   * ObjectMonitor
>>     * Updates comments and tests consistencies
>> 
>> # Refactoring
>> 
>> `ObjectMonitor::enter` has been refactored an a 
>> `ObjectMonitorContentionMark` witness object has been introduced to the 
>> signatures. Which signals that the contentions reference counter is being 
>> held. More details are given below in the section about deflation.
>> 
>> The initial purpose of this was to allow `UseObjectMonitorTable` to interact 
>> more seamlessly with the `ObjectMonitor::enter` code. 
>> 
>> _There is even more `ObjectMonitor` refactoring which can be done here to 
>> create a more understandable and enforceable API. There are a handful of 
>> invariants / assumptions which are not always explicitly asserted which 
>> could be trivially abstracted and verified by the type system by using 
>> similar witness objects._
>> 
>> # LightweightSynchronizer
>> 
>> Working on adapting and incorporating the following section as a comment in 
>> the source code
>> 
>> ## Fast Locking
>> 
>>   CAS on locking bits in markWord. 
>>   0b00 (Fast Locked) <--> 0b01 (Unlocked)
>> 
>>   When locking and 0b00 (Fast Locked) is observed, it may be beneficial to 
>> avoid inflating by spinning a bit.
>> 
>>   If 0b10 (Inflated) is observed or there is to...
>
> Axel Boldt-Christmas has updated the pull request incrementally with two 
> additional commits since the last revision:
> 
>  - Remove the last OMWorld references
>  - Rename omworldtable_work to object_monitor_table_work

src/hotspot/share/runtime/basicLock.inline.hpp line 45:

> 43:   return reinterpret_cast<ObjectMonitor*>(get_metadata());
> 44: #else
> 45:   // Other platforms does not make use of the cache yet,

nit typo: s/does not/do not/

src/hotspot/share/runtime/basicLock.inline.hpp line 54:

> 52: inline void BasicLock::clear_object_monitor_cache() {
> 53:   assert(UseObjectMonitorTable, "must be");
> 54:   set_metadata(0);

Should this be a literal `0` or should it be `nullptr`?
Update: The metadata field is of type `unintptr_t`. Got it.

src/hotspot/share/runtime/deoptimization.cpp line 1650:

> 1648:                 mon_info->lock()->set_bad_metadata_deopt();
> 1649:               }
> 1650: #endif

I like this!

src/hotspot/share/runtime/globals.hpp line 1964:

> 1962:                                                                         
>     \
> 1963:   product(int, LightweightFastLockingSpins, 13, DIAGNOSTIC,             
>     \
> 1964:           "Specifies the number of time lightweight fast locking will " 
>     \

nit typo: s/number of time/number of times/

src/hotspot/share/runtime/lightweightSynchronizer.cpp line 34:

> 32: #include "oops/oop.inline.hpp"
> 33: #include "runtime/atomic.hpp"
> 34: #include "memory/allStatic.hpp"

nit: this include is out of order.

src/hotspot/share/runtime/lightweightSynchronizer.cpp line 43:

> 41: #include "runtime/mutexLocker.hpp"
> 42: #include "runtime/objectMonitor.hpp"
> 43: #include "runtime/objectMonitor.inline.hpp"

Shouldn't have both includes here.

src/hotspot/share/runtime/lightweightSynchronizer.cpp line 81:

> 79:     oop _obj;
> 80: 
> 81:   public:

nit - please indent by one more space.

src/hotspot/share/runtime/lightweightSynchronizer.cpp line 86:

> 84:     uintx get_hash() const {
> 85:       uintx hash = _obj->mark().hash();
> 86:       assert(hash != 0, "should have a hash");

Hmmm... I can remember seeing hash values of zero in some
of my older legacy inflation stress runs. Is a hash value of zero
not a thing with lightweight locking?

src/hotspot/share/runtime/lightweightSynchronizer.cpp line 104:

> 102:     ObjectMonitor* _monitor;
> 103: 
> 104:   public:

nit - please indent by one more space.

src/hotspot/share/runtime/lightweightSynchronizer.cpp line 126:

> 124: 
> 125:   static void dec_items_count() {
> 126:     Atomic::inc(&_items_count);

Shouldn't this be `Atomic::dec`?

src/hotspot/share/runtime/lightweightSynchronizer.cpp line 130:

> 128: 
> 129:   static double get_load_factor() {
> 130:     return (double)_items_count/(double)_table_size;

nit - please add spaces around `/` operator.

src/hotspot/share/runtime/lightweightSynchronizer.cpp line 169:

> 167:   }
> 168: 
> 169: public:

nit - please indent by one space.

src/hotspot/share/runtime/lightweightSynchronizer.cpp line 184:

> 182:       bool has_monitor = obj->mark().has_monitor();
> 183:       assert(has_monitor == (monitor != nullptr),
> 184:           "Inconsistency between markWord and OMW table has_monitor: %s 
> monitor: " PTR_FORMAT,

Do you still want to use the name "OMW table"?

src/hotspot/share/runtime/lightweightSynchronizer.cpp line 213:

> 211: 
> 212:   static bool should_shrink() {
> 213:     // No implemented;

nit typo: s/No/Not/

src/hotspot/share/runtime/lightweightSynchronizer.cpp line 322:

> 320:        oop obj = om->object_peek();
> 321:        st->print("monitor " PTR_FORMAT " ", p2i(om));
> 322:        st->print("object " PTR_FORMAT, p2i(obj));

The monitor output style is to use `=` and commas, e.g.
`monitor=<value>, object=<value>`

src/hotspot/share/runtime/lightweightSynchronizer.cpp line 341:

> 339: 
> 340: ObjectMonitor* 
> LightweightSynchronizer::get_or_insert_monitor_from_table(oop object, 
> JavaThread* current, bool* inserted) {
> 341:   assert(LockingMode == LM_LIGHTWEIGHT, "must be");

Do you want to assert: `inserted != nullptr`?

src/hotspot/share/runtime/lightweightSynchronizer.cpp line 367:

> 365:     ResourceMark rm(current);
> 366:     log_trace(monitorinflation)("inflate: object=" INTPTR_FORMAT ", 
> mark="
> 367:                                 INTPTR_FORMAT ", type='%s' cause %s", 
> p2i(object),

nit typo: s/cause %s/cause=%s/

src/hotspot/share/runtime/lightweightSynchronizer.cpp line 414:

> 412: 
> 413:   intptr_t hash = obj->mark().hash();
> 414:   assert(hash != 0, "must be set when claiming the object monitor");

Hmmm... I can remember seeing hash values of zero in some
of my older legacy inflation stress runs. Is a hash value of zero
not a thing with lightweight locking?

src/hotspot/share/runtime/lightweightSynchronizer.cpp line 468:

> 466:     oop obj = *o;
> 467:     if (obj->mark_acquire().has_monitor()) {
> 468:       if (_length > 0 && _contended_oops[_length-1] == obj) {

nit - please add space around `-` operator.

src/hotspot/share/runtime/lightweightSynchronizer.cpp line 501:

> 499:   // Make room on lock_stack
> 500:   if (lock_stack.is_full()) {
> 501:     // Inflate contented objects

nit typo: s/contented/contended/

src/hotspot/share/runtime/lightweightSynchronizer.cpp line 545:

> 543:   bool _no_safepoint;
> 544: 
> 545: public:

nit - please indent by one space.

src/hotspot/share/runtime/lightweightSynchronizer.cpp line 664:

> 662: 
> 663:   // Used when deflation is observed. Progress here requires progress
> 664:   // from the deflator. After observing the that the deflator is not

nit typo: s/observing the that the deflator/observing that the deflator/

src/hotspot/share/runtime/lightweightSynchronizer.cpp line 760:

> 758: 
> 759: // LightweightSynchronizer::inflate_locked_or_imse is used to to get an 
> inflated
> 760: // ObjectMonitor* with LM_LIGHTWEIGHT. It is used from contexts which 
> requires

nit typo: s/used from contexts which requires/used from contexts which require/

src/hotspot/share/runtime/lightweightSynchronizer.cpp line 773:

> 771:   JavaThread* current = THREAD;
> 772: 
> 773:   for(;;) {

nit: please add space before `(`.

src/hotspot/share/runtime/lightweightSynchronizer.cpp line 778:

> 776:       // No lock, IMSE.
> 777:       THROW_MSG_(vmSymbols::java_lang_IllegalMonitorStateException(),
> 778:                 "current thread is not owner", nullptr);

nit - please indent by one more space.

src/hotspot/share/runtime/lightweightSynchronizer.cpp line 785:

> 783:         // Fast locked by other thread, IMSE.
> 784:         THROW_MSG_(vmSymbols::java_lang_IllegalMonitorStateException(),
> 785:                   "current thread is not owner", nullptr);

nit - please indent by one more space.

src/hotspot/share/runtime/lightweightSynchronizer.cpp line 799:

> 797:         if (lock_stack.contains(obj)) {
> 798:           // Current thread owns the lock but someone else inflated
> 799:           // fix owner and pop lock stack

Please consider:

          // Current thread owns the lock but someone else inflated it.
          // Fix owner and pop lock stack.

src/hotspot/share/runtime/lightweightSynchronizer.cpp line 805:

> 803:           // Fast locked (and inflated) by other thread, or deflation in 
> progress, IMSE.
> 804:           THROW_MSG_(vmSymbols::java_lang_IllegalMonitorStateException(),
> 805:                     "current thread is not owner", nullptr);

nit - please indent by one more space.

src/hotspot/share/runtime/lightweightSynchronizer.cpp line 1045:

> 1043:   if (monitor->is_being_async_deflated()) {
> 1044:     // The MonitorDeflation thread is deflating the monitor. The 
> locking thread
> 1045:     // must spin until further progress have been made.

nit typo: s/progress have been made./progress has been made./

src/hotspot/share/runtime/lightweightSynchronizer.cpp line 1075:

> 1073:     //                   lock, then we make the locking_thread thread
> 1074:     //                   the ObjectMonitor owner and remove the
> 1075:     //                   lock from the locking_thread thread's lock 
> stack.

nit typos: s/locking_thread thread/locking_thread/
in three places.

src/hotspot/share/runtime/lightweightSynchronizer.cpp line 1190:

> 1188: 
> 1189: #ifndef _LP64
> 1190:   // Only for 32bit which have limited support for fast locking outside 
> the runtime.

nit typo: s/which have limited support/which has limited support/

src/hotspot/share/runtime/lightweightSynchronizer.cpp line 1194:

> 1192:     // Recursive lock successful.
> 1193:     current->inc_held_monitor_count();
> 1194:     // Clears object monitor cache, because ?

What does this comment mean?

src/hotspot/share/runtime/lightweightSynchronizer.hpp line 36:

> 34: 
> 35: class LightweightSynchronizer : AllStatic {
> 36: private:

nit: please indent by 1 space.

src/hotspot/share/runtime/lightweightSynchronizer.hpp line 41:

> 39: 
> 40:   static ObjectMonitor* add_monitor(JavaThread* current, ObjectMonitor* 
> monitor, oop obj);
> 41:   static bool remove_monitor(Thread* current, oop obj, ObjectMonitor* 
> monitor);

Hmmm... `add_monitor` has `monitor` and then `obj` params.
`remove_monitor` has `obj` and then `monitor` params. Why
not use the same order?

src/hotspot/share/runtime/lightweightSynchronizer.hpp line 57:

> 55:   static bool resize_table(JavaThread* current);
> 56: 
> 57: private:

nit: please indent by 1 space.

src/hotspot/share/runtime/lightweightSynchronizer.hpp line 61:

> 59:   static bool fast_lock_spin_enter(oop obj, LockStack& lock_stack, 
> JavaThread* current, bool observed_deflation);
> 60: 
> 61: public:

nit: please indent by 1 space.

src/hotspot/share/runtime/lightweightSynchronizer.hpp line 69:

> 67:   static ObjectMonitor* inflate_locked_or_imse(oop object, 
> ObjectSynchronizer::InflateCause cause, TRAPS);
> 68:   static ObjectMonitor* inflate_fast_locked_object(oop object, 
> JavaThread* locking_thread, JavaThread* current, 
> ObjectSynchronizer::InflateCause cause);
> 69:   static ObjectMonitor* inflate_and_enter(oop object, JavaThread* 
> locking_thread, JavaThread* current, ObjectSynchronizer::InflateCause cause);

All of these are "inflate" functions, but:
- two of them have `object` parameter next to the `cause` parameter
-  two of them have `object` parameter first
- one of them has `current` parameter before the other thread parameter 
(`inflating_thread`)
- two of them have the `current` parameter after the other thread parameter 
(`locking_thread`)

Please consider making the parameter order consistent.

src/hotspot/share/runtime/lockStack.hpp line 130:

> 128: class OMCache {
> 129:   friend class VMStructs;
> 130: public:

Please indent by one space.

src/hotspot/share/runtime/lockStack.hpp line 133:

> 131:   static constexpr int CAPACITY = 8;
> 132: 
> 133: private:

Please indent by one space.

src/hotspot/share/runtime/lockStack.hpp line 140:

> 138:   const oop _null_sentinel = nullptr;
> 139: 
> 140: public:

Please indent by one space.

src/hotspot/share/runtime/objectMonitor.cpp line 669:

> 667:       install_displaced_markword_in_object(obj);
> 668:     }
> 669:   }

This can be cleaned up by putting L664 and L665 on the same line,
fixing the indents on L666-7 and deleting L668.

src/hotspot/share/runtime/objectMonitor.cpp line 682:

> 680: // deflation process.
> 681: void ObjectMonitor::install_displaced_markword_in_object(const oop obj) {
> 682:   assert(!UseObjectMonitorTable, "Lightweight has no dmw");

Perhaps:
`assert(!UseObjectMonitorTable, "ObjectMonitorTable has no dmw");`

src/hotspot/share/runtime/objectMonitor.hpp line 388:

> 386:   // Deflation support
> 387:   bool      deflate_monitor(Thread* current);
> 388: private:

nit - please indent by one space

src/hotspot/share/runtime/serviceThread.cpp line 44:

> 42: #include "runtime/jniHandles.hpp"
> 43: #include "runtime/serviceThread.hpp"
> 44: #include "runtime/lightweightSynchronizer.hpp"

Include is in the wrong place.

src/hotspot/share/runtime/synchronizer.cpp line 404:

> 402: 
> 403: bool ObjectSynchronizer::quick_enter_legacy(oop obj, JavaThread* current,
> 404:                                      BasicLock * lock) {

nit - please fix this indent.

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715569720
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715571831
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715582675
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715589490
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715617774
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715618379
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715621030
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715623399
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715640861
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715642307
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715643617
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715647133
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715649276
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715651080
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715661781
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715663965
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715662800
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715675411
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715678877
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715680995
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715682621
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715690997
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715696004
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715697549
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715698164
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715698568
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715700114
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715700801
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715716901
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715720857
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715724929
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715726115
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715603974
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715601643
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715604333
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715604553
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715614530
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715880925
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715881116
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715881379
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715922871
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715924876
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715900092
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715926418
PR Review Comment: https://git.openjdk.org/jdk/pull/20067#discussion_r1715940064

Reply via email to