Hi Eliot,

On 4 December 2017 at 23:44, Eliot Miranda <eliot.mira...@gmail.com> wrote:
>
> Alas a forwarding object has two fields that need to be set in separate
words.
> The class index in the header must be the forwarder class index,
> and the first word of the object body must point to the forwarder.

Good to better understand that.
Just restating after condensing most of the thread, only the Main-thread
would convert objects to forwarders.


> Reverting obviously requires two writes too. So atomic (un)forwarding is
not possible.

sorry, just double-checking since I realised I erred in my example below,
which may have mislead your response.

IIUC(now)... while "creating" a forwarder involves writing separately to
object-header and object-body.
wouldn't "reverting" only involve updating an object-pointer in a slot to
the real-object's new location?
And that would be a single word operation on both 32bit and 64bit platforms?


> >> - Currently the marking phase removes all forwarders and I would like
incremental marking to maintain the same invariant (forwarders are always
white).
> >
> > A concurrent-marking thread could essentially do the same.
> >         i. From shared memory load forward header Fh from object-slot
> >                    Fheader <== object-slot
> >         ii. Follow forwarder to real-object, store into local temporary
> >                    Rheader <== flattened/followed pointer
> >
> >         iii. Atomic compare-and-swap R back into object-slot,
> >                    object-slot <== if Fheader then Rheader

whoops, corrected...

    i. From shared memory, concurrent marking-scan has loaded an
object-pointer from object-slot.  If it points to a forwarding object ...
              Opointer <== object-slot (as part of normal marking scan)
              if *Opointer isForwardingObject {
                    Fpointer <== Opointer (redundant, just for clarity)

    ii. Follow that to real-object, store into local temporary
              Rpointer <== followed Fpointer forwarding chain to real
object.

    iii. Atomic compare-and-swap Rpointer back into object-slot
              object-slot <== if still Fpointer then Rpointer



When (iii.) fails
* If I'm the Main-thread, I'm in the middle of handling a failed
forwarder-check
  and can infer the GC-thread already did what I was going to do.
  I can be certain that...    "object-slot == Rpointer" (since thats the
only object-slot mutation GC-threads can do)
  so its fine to continue to my usual post-flattening retry

* If I'm a GC-thread, either:
     * the Main-thread flattened the forwarder, or
     * the Main-thread changed which object the slot holds
   In either case, just re-read the slot

A race scenario to consider is where the Main-thread converts an object
to a forwarder simultaneous with a GC-thread flattening one of its slots.
The object copy in its new location may miss that update.
But in terms of the object graph that seems not a problem, since the copy
without that update is still consistent.
Infrequently just a little bit of work is lost.

I'm contemplating other race scenarios around marking, but won't distract
with them for now.

cheers -ben

Reply via email to