Hi Eliot,
On 4 December 2017 at 23:44, Eliot Miranda <[email protected]> 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