Closed llbit closed 8 years ago
The Travis builds have problems using coalesced reference counting. I was not able to reproduce the build problems on my machine, so best guess is that the build failures are caused by the Travis builds running out of memory.
Every new object is inserted directly in the dirty list, thus requiring more memory for the dirty list, especially when very many objects are allocated.
Travis documentation: https://docs.travis-ci.com/user/common-build-problems/#My-build-script-is-killed-without-any-error
Merging into the branch for now.
This is an experimental implementation of coalesced reference counting. It is not fit for production yet, but could be polished up if it turns out to be worthwhile.
This implementation steals one bit from the reference count to use as a dirty bit.
Coalescing the reference count for a reference involves the following changes:
GCEdge<X>
toX*
attachReference(x, initialRef)
retargetReference(x, newTarget)
x.get()
by a regular access:x
x.detach()
bydetachReference(x)
applyToCoalescedReferences()
in the owner of the reference so that it calls the argument function on the coalesced reference.The attachReference(), retargetReference() and detachReference() functions are declared in GCNode, they are not static because they need the caller's this pointer to add the caller to the dirty list.
Coalescing a reference means that all outgoing references at the time the node is marked dirty are remembered. If outgoing references were not remembered then the reference counts for objects would be artificially inflated. On the next GC pass all reference counts for outgoing references are decreased, then the current outgoing references of all dirty nodes have their reference counts increased.
To make this work with the current eager reference counting I added a new virtual method in GCNode:
applyToCoalescedReferences(function<void(const GCNode*)>)
. This function is used to remember outgoing references and increase reference counts for current outgoing references (the steps described above).It would be an error ot not coalesce a reference but then treat it as a current outgoing reference during the GC pass, so I could not reuse GCNode::visitReferents() for coalesced ref. counting. If all references were coalesced, then GCNode::visitReferents() could be repurposed for that.