[lworld] RFR: object methods in VM for lworld value type (locked mark word edition)

David Simms david.simms at oracle.com
Mon May 21 12:02:17 UTC 2018

So take 2, now with "markOopDesc::is_always_locked()".


Functionality is the same as previous patches, with John's comments 
applied (default VM hash is klass mirror hash code, not zero). I went to 
the trouble of encoding mark word as always locked. I realized it was 
not completely trivial, and requires some explanation as to why I went 
with the pattern I did...

Ideally, we want locking code to drop into slow path at no extra cost 
over the current implementation, and zero cost to fast path. So which 
state shall we abuse ?

Some ASCII art (hope this survives email), currently 6 possible mark 
word states:

| State       | Bits (MSB 
first)                                              |

| Thin locked |     Displaced Header 
Pointer                                00|
| Inflating   | NULL                                                    00|
| Hash code   |     <Unused>            |     Hashcode                C 
Age001|  C=CMS bit
| Biased      |     Thread Pointer                                  E C 
Age101| C=CMS bit E=2 Epoch bits
| Fat locked  |     Monitor 
Pointer                                         10|
| GC          |     <GC 
Things>                                             11|

* "GC" is reserved for GC and a black hole as far as we are concerned. 
Also isn't "locked" and won't get us to slow path.
* Hash code" isn't locked, current implementation will simply displace 
into the stack lock.
* "Inflating" state is always assumed by code to be a very temporary 
state, and GC doesn't expect to see this state, and the rest of the code 
would deadlock or need extra checks.
* Thin and fat locked states require a pointer to fixed write-able 
memory, i.e. displaced header, age bits still need somewhere to go, on a 
per object/value basis.

So we are left with "Biased", age bits are in place, no displacement 
needed, GC pointer forwarding doesn't need to preserve mark (re-init 
with klass prototype header will suffice).

Choosing a thread pointer with an illegal alignment should help with 
debugging (note "biased_lock_alignment" is "2" thread shifted, we use 
"1"). Although the patch tests by using mark exactly equal to 
"always_locked_pattern", it could be mask and test, then use the more 
significant bits for other purposes, e.g. "is_always_locked()" combined 
with other characteristics, like "is_value_type()", "is_frozen_array()".

What changes to locking code are required ?

* Biased enabled, no changes. We don't allow revoke/rebias, so the epoch 
always matches klass prototype header, so the "try_rebias" branch is 
never attempted.
* Without biased, there was an extra "andptr" op added to remove the the 
bias bit from the "swap_reg" so cmpxchg will fail with "always locked" 
pattern present.


     The klass ptr encoding trick is not used and could be dropped from 
the patch.
     Introduce "is_value_type()" characteristic bit, just above "always
     JIT: Minor lock change in expand lock node


More information about the valhalla-dev mailing list