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