Sharing the markword (aka Valhalla's markword use)

Kennke, Roman rkennke at amazon.de
Mon Mar 11 12:41:16 UTC 2024


Hi John,

> The larval state of a value object can be viewed as an analog of the locked state of an identity object.  In both cases, one specific thread is doing something exclusive to the object.  For values, this larval state is indeed highly exclusive:  The thread that made the value object is also filling in its fields, protected either by the verifier (if it is constructor code) or by some other means (if the fields are being set by privileged non-constructor code).  Unlike a locked identity object, once a value exits the larval state, it is forever an adult; an identity object can be relocked many times.
> 
> All that said, the lifecycles are different, but they are similar enough that we can envision using some of the same bit-patterns in parallel.  I am pretty sure that whatever locked state indicator (a bit pattern) that we invent for the object header of an identity object is more than adequate for a value object in its larval state.
> 
> So, just have each GC process larvae very much like locked objects, and arrange the header bit patterns to make this easy, by making them be similar.

Can value objects be locked? If not, could value objects use the same bits that are used for locking of identity objects?
Other than that, it should be easy to preserve larvae bit across GC, pretty much like lock-bits.

> And, as an aside, in the future the GC or JIT may perform deduplication (or, say, NUMA-sensitive duplication) of values, or any other reorganization that reassigns varying pointers which alias equivalent copies of the same value state.  In such a case, please be sure to treat every larval value object as unique and never aliased to any other value object, however similar.  A larval value is likely to be side-effected to a new state before it becomes adult, which would cause bad failures if it were accidentally treated as aliased to some unrelated value.  Only adult values are legitimate subjects for alias-based optimizations, whether in the JIT or GC.

Ok, that is good to know.

> Regarding the other bits (is-value, is-flat-array, is-null-free-array), those can all be re-hoisted from the Klass object, if for some reason the header needs  to be restored or reset.  After all, those bits are just optimized copies (hoisted into a convenient place in the header), copied from the original information in the Klass object itself.  This hoisting is a performance hack.  We are discussing it at length here because the Valhalla team has determined, at least provisionally, that acceptable product performance requires such a “hoisting hack”.

That is also very good to know. It means we don’t have to preserve those bits across GCs or other destructive ops, and can always restore them. Makes life easier.

> I suggest adding, to Klass itself, a field which is a prototype header for the object, with all the right bits in place.

In Lilliput we already have that field, for the Klass-pointer (pretty much restored from the earlier prototype for biased locking). We can add more info bits to that prototype header.

>  The GC can use that as a starting point when repairing headers that it had to reset.  (I thought we already had something like this somewhere, but a quick check came up empty…)  Currently, it appears we reset object headers from markWord::prototype which is an absolute constant.  Perhaps this function should be refactored to a query to non-static Klass::prototype_mark_word.  That’s just my $0.02; probably stuff like this has been discussed several times.

Yup, no problem with that.

> A final suggestion, which I’ve mentioned elsewhere, but it’s worth repeating:  If we don’t choose to burn whole a bit on the is-value test, we can use a joint bit encoding.  (Similar point for an is-array test, in fact, or for particular subkinds of arrays.)  In either the klass or IHC subfield of the header, we might be able to get away with stating something like, “if there 10 or more zeroes at the high end of the subfield, then the object is a value, and otherwise it’s not”.  That would steal dynamic range from the subfield for values, but would leave the non-values unscathed (except for the responsibility to avoid that 1/1024 fraction of reserved encodings).  For more details, please see: https://cr.openjdk.org/~jrose/jvm/joint-bit-encodings.html

Nice, that might be useful.

Thanks!

Roman



Amazon Development Center Germany GmbH
Krausenstr. 38
10117 Berlin
Geschaeftsfuehrung: Christian Schlaeger, Jonathan Weiss
Eingetragen am Amtsgericht Charlottenburg unter HRB 149173 B
Sitz: Berlin
Ust-ID: DE 289 237 879




More information about the valhalla-dev mailing list