[External] : Re: Semantics of CollectedHeap::requires_barriers()
Roman Kennke
rkennke at redhat.com
Mon Feb 8 14:22:43 UTC 2021
Hi Ron,
>> Hi Ron,
>>
>> Thanks for the explanation!
>>
>> Does that mean that always returning true in requires_barriers() should be conservatively ok? If yes, why am I hitting this assert:
>
> No, you must not always return true. An that’s just been allocated since the last safepoint must return false.
> Otherwise, we’d never be able to freeze — we can only freeze frames into a chunk that doesn’t require barriers.
Ok.
>> Besides this, I think I know what to do for requires_barriers() in Shenandoah. In-fact (if I understand it corrcetly) I don't think Shenandoah needs any barriers at all there: this is about copying stack-frames (which might contain oops) *into* the StackChunk. It should be ok for SATB because there are no previous oop locations in a new StackChunk, and it should be ok for LRB because LRBs are only relevant when *loading* from oop locations, but here we're storing to oop locations.
>
> First, when storing frames, we already require that no barriers are needed. If they are we can’t freeze (i.e. we can never freeze into a chunk
> whose requires_barriers returns true).
Ok, makes sense.
> Now, we are reusing the same chunk for multiple freezes, as long as it doesn’t require barriers. That means we are overwriting oops,
> which is not okay for SATB. Unless you perform the writes in memory that has been allocated after marking started. Such memory does not
> need to be marked through by SATB marking.
Aha, ok! In this case we'll require-barriers for objects <
top-at-mark-start during SATB.
> We must not change the oop layout of something that is concurrently being traversed by the GC. Obviously if you allow to overwrite the chunk at
> any time, that implies it will get overwritten by a marking traversal operation that runs concurrently and inevitably crash. So it's not valid to mutate
> the layout or contents of a stack chunk that can be traversed concurrently by the GC, which again takes us back to allocating memory (allocated
> since the last marking phase started), which is not traversed by concurrent marking.
Right, that is very useful to know.
>> However, we might need barriers when copying frames out of the stack chunk (e.g. when thawing frames), because then we'd be loading from oop locations. Is this taken care of already somehow?
>
> If you need barriers when thawing, then requires_barriers must return false, and then it’s taken care of.
I assume you mean to return true when we require barriers when thawing?
>> Similar considerations should apply for ZGC. Or maybe I'm missing something?
>
> ZGC doesn’t require barriers iff the object is in an allocating region. Something similar would need to be done for Shenandoah, I assume.
Yes, with the above explanations in mind, I think we require barriers
when object is below update-watermark (aka top-at-evacuation-start)
during evac and update-refs phases, in addition to the SATB handling
during marking.
> If Shenandoah *always* requires barriers when reading, then we might need to split requires_barriers into two different methods.
No, I don't think this will be necessary.
I think it would be *very* useful to put all those explanations in
CollectedHeap::requires_barriers().
>> Do GCs need to treat StackChunk instances specially when marking or relocating?
>
> Absolutely, but I think that’s done automatically, as InstanceStackChunkKlass overrides oop_oop_iterate etc.
Ok, I see.
>> I am a bit skeptical about ContMirror::allocate_stack_chunk() (in continuation.cpp around line 5965), it looks to me like it's trying to second-guess GC allocation mechanics by going directly to the TLAB. I'm not sure if this is a good idea, but can't exactly point to what might go wrong (except a slight breach of GC interface). Can you say what is the reason behind this?
>
> I think this was supposed to be an optimisation. Not sure if it’s still required/effective.
It looks to me like something that GCs do anyway: try TLAB first,
failing that, fall back to allocate a new TLAB, try that again, and
failing that, try locked allocation. GCs may know better how to do that
fast ;-) (Plus, there might be special situations like -UseTLAB, etc)
Thanks for taking the time to explain all this, it's very useful!
Roman
More information about the loom-dev
mailing list