RFC: Move forwarding ptr into the object

Aleksey Shipilev shade at redhat.com
Tue Sep 27 13:45:04 UTC 2016


On 09/27/2016 03:18 PM, Roman Kennke wrote:
>> *) The filler object mechanics is now gone, but we trade in the 
>> proper header initialization on all paths. Some code in VM
>> (JVM_Clone, looking at you!) actually copies the entire object with
>> header *after* we setup the forwarding ptrs.
>
> Is that a problem?

It is not a problem in theory. But in practice, I wasted 4 hours trying
to understand a subtle bug that crashed VM before even entering main(),
only to figure out that JVM_Clone thinks it is okay to allocate the
object in new place (where we intercept and put our forwarding ptr), but
then completely overwrite it with the source object, header included.
Development nuisance, certainly.

>> *) OOP definition in VM is static, and some artistry would be 
>> required to make sure the header has the forwarding ptr only for
>> Shenandoah.
> 
> The forwarding ptr must not be static in the sense that other GCs would
> get it too. But it should be possible to treat it as an extra slot only
> for Shenandoah. Kindof like the length field of arrays is handled now.

Yes, except that arrayOop is the special kind of oop that is also static
in itself. The trick here is to change the baseline oop layout based on
-XX:+UseShenandoahGC, i.e. at runtime. Doable, but may require some
creativity, which would certainly touch more shared VM parts.

Maybe we should refactor the oop/instanceOop/arrayOop relationship and
compressed klass handling to allow for extendable (slotted) object
headers, merge it into mainline, and then build forwarding ptr into the
header with one simple touch...

>> *) Forwarding ptr should probably be inlined between the mark word 
>> and class word: a) mark word is always HeapWord-sized, so
>> forwarding ptr is always HeapWord-aligned, regardless of class ptr
>> compression; b) some code in VM thinks the header size is the 
>> offset_of(class_ptr)+sizeof(class_ptr)...
>
> I was thinking that maybe it should be placed between the klass* and
> the actual fields:
> 1. we never need a read-barrier for reading the klass* and rarely (if
> ever) for the mark word, this would 'widen the window' for possible
> cache hit for subsequent field reads.
> 2. We may be able to squeeze the compressed forwarding ptr after the
> compressed klass* for non-arrays (assuming we can handle/compile
> different offsets for objects vs. arrays.

I haven't explored if we could add the injected field into the
java/lang/Object where to store the fwdptr, like some other system Java
classes do, then somehow manage to cram that into arrays. This should
keep oop hierarchy less abused, and still have the benefits of
observability and compressibility. If this works out, then the layout
would be similar to what you suggest, e.g.:

objects, 64-bit coops:
 0: [mark]
 8: [comp klass]
12: gap
16: [fwdptr]
24: ...other fields...

arrays, 64-bit coops:
 0: [mark]
 8: [comp klass]
12: [arraylength]
16: [fwdptr]
24: <array base>

There wouldn't be a benefit from compressing fwdptr for array case,
because the array base should be aligned. This probably also means that
fwdptr for objects should be at the same offset, negating the
compression benefits.


Thanks,
-Aleksey



More information about the shenandoah-dev mailing list