[master] RFR: Store (narrow) klass in object header

Roman Kennke rkennke at openjdk.java.net
Fri May 21 18:23:19 UTC 2021

On Fri, 21 May 2021 15:04:57 GMT, Aleksey Shipilev <shade at openjdk.org> wrote:

>> This change stores compressed Klass* in the upper 32bits of the object header. It doesn't really use it, yet. But I added some code in heap-object-stats to verify that all objects receive it.
>> It is implemented by storing the compressed Klass* into the prototype-header for each Klass, and use that to initialize objects, pretty much like we used to do for +BiasedLocking.
>> It will take some serious effort to change all code to use this new location to find the Klass*:
>> - We need to change all generated code (intepreter, c1, c2) to load Klass* from the header, and call to runtime when it encounters a displaced header word.
>> - We need to change (sliding-compacting) GCs to be able to iterate heap while objects are forwarded. Most likely by using a forwarding table, but I'm not quite sure yet.
>> - We need to change rest of runtime to load Klass* from header.
>> In this change, I modified some code in G1 that deals with checking consistent header, the same asserts that we have seen in #6. This is rather ugly, but I actually expect those asserts to go away or be rewritten in a more useful way.
>> CDS support is noteworthy because we need to ensure that we propagate the actual narrowKlass whenever we (re-)initialize object headers, because that may be encoded with a different base address for archived Klass instances than other Klass instances, and would create a mess if we would re-encode the Klass*.
>> Testing
>>  - [x] tier1
>>  - [x] tier2
> src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp line 162:
>> 160:   assert_different_registers(obj, klass, len);
>> 161:   Register tmp_encode_klass = LP64_ONLY(rscratch1) NOT_LP64(noreg);
>> 162:   assert_different_registers(obj, klass, len, t1, t2);
> Looks to me this subsumes the assert two lines before.

Right. Both were pre-existing, but folding brought them close together.

> src/hotspot/share/cds/archiveBuilder.cpp line 785:
>> 783: #ifdef _LP64
>> 784:   o->set_mark(o->mark().set_narrow_klass(nk));
>> 785: #endif
> So... is `o->set_narrow_klass(nk)` the line below doing the same? Also, why only `_LP64`?

No, o->set_narrow_klass(nk) sets the field in the Klass* slot, while the other sets the field in the header slot. The Klass* slot will eventually go away - but not now.

> src/hotspot/share/oops/markWord.cpp line 122:
>> 120:     return set_narrow_klass(nklass);
>> 121:   } else {
>> 122:     return markWord(value());
> So this `else` path does not use `klass`? Is that because `UseCompressedClassPointers` is always `true`? Is it, though, on x86_32? It would be cleaner to put `ShouldNotReachHere()` if that path should not be taken.

In 32bit, we should not call this (the whole block is _LP64). In 64bit, UseCompressedClassPointers is forced and the else-branch should not be used/eventually go away. Yes, we can do ShouldNotReachHere() there.


PR: https://git.openjdk.java.net/lilliput/pull/7

More information about the lilliput-dev mailing list