RFR: Eliminate extra forwarding pointer per object

Roman Kennke rkennke at redhat.com
Tue May 7 19:49:19 UTC 2019


Hi Aleksey,

>> I propose to push it to shenandoah/jdk and bake it there a little before upstreaming it into jdk/jdk.
> 
> This plan is fine with me; but let's review it first.
> 
>> Webrev:
>> http://cr.openjdk.java.net/~rkennke/eliminate-fwdptr/webrev.00/
> 
> Brief look:
> 
> *) In shenandoahBarrierSetAssembler_aarch64.cpp there is comment about temp registers in
> SBSA::resolve_forward_pointer_not_null. Yet, new code does clobber them? Maybe the comment is
> obsolete now?

I changed the comment to allow using explicitely passed in tmp 
registers. :-)

> *) Maybe we should fork introducing new tmp to CAS? That would make the patch easier to backport, I
> think.

Not sure. The change would make the register allocators free one more 
register but then not use it. I left it out of this iteration for now.

> *) Is there a compelling reason why we drop the midpath in SBSA::load_reference_barrier_not_null and
> call into slowpath? I.e. is it required, or is it opportunistic optimization? Maybe it just works
> around the complexity of parsing out the fwdptr?

It works around the complexity of getting an extra register for 
decoding. This is much easier in the stub.

> *) In shenandoahAsserts, we deliberately not going via resolves, instead doing
> SBP::get_raw_unchecked. Just replacing them with SBS::resolve_forwarded_not_null does not feel
> sufficient. Instead, asserts/verifier needs to be adjusted to decode the fwdptrs properly (if present).

I re-instated the utility class as ShenandoahForwarding and this updated 
change keeps those utilities.

> *) It seems in SH::evacuate_object, this needs to call some utility method?
> 
>   236   markOop old_mark = p->mark_raw();
>   237   if (old_mark->is_marked()) {
>   238     return (oop) old_mark->clear_lock_bits();
>   239   }
> 
> ...and here?
> 
>   281   markOop new_mark = markOopDesc::encode_pointer_as_mark(copy_val);
>   282   markOop prev_mark = p->cas_set_mark_raw(new_mark, old_mark);
>   283   if (prev_mark == old_mark) {


> I actually think that we can keep ShenandoahBrooksPointer and put all that util code there. It would
> still be doing its job: abstracting away the forwarding data handling.


I reinstated the ShenandoahForwarding utility class. However, it is hard 
to abstract the protocol because the two parts strictly belong together. 
However, this seems all the more reason to abstract it properly. The 
only thing that happens in between the two blocks is actually allocating 
and copying the object. So we could call into, say, 
ShenandoahForwarding::evacuate() which would do the prefix and suffix, 
and call back to say copy = ShHeap::allocate_and_copy(obj); or such for 
the payload. What do you think?

> *) In ShenandoahMarkCompact, do these need to be public?
> 
>    76 public:
>    77   void preserve_mark(oop obj);
>    78   void restore_marks();
>    79   void adjust_marks();

I forgot to mention ShenandoahMarkCompact. This completely overhauls how 
ShMarkCompact stores forwarding information. It's changed to basically 
work like other GCs and stores the forwarding in the mark-word. However, 
the mark word must sometimes be preserved. Therefore we store it to the 
side. The 3 methods above handle that. They are public because they are 
called from closures. Alternatively, we could make the closures friends 
of ShMarkCompact. ?

Updated patch:
http://cr.openjdk.java.net/~rkennke/eliminate-fwdptr/webrev.01/

It's based on:
http://cr.openjdk.java.net/~rkennke/renamebrooksptr/webrev.00/

Still passes all tests.

Roman


More information about the shenandoah-dev mailing list