diff --git a/lib/system/yrc.nim b/lib/system/yrc.nim index 9a9920cee8..a681917de2 100644 --- a/lib/system/yrc.nim +++ b/lib/system/yrc.nim @@ -217,6 +217,9 @@ proc nimIncRefCyclic(p: pointer; cyclic: bool) {.compilerRtl, inl.} = break proc mergePendingRoots() = + # Merge buffered RC operations. Note: Unlike truly concurrent collectors, + # we don't need to set color to black on incRef because collection runs + # under the global lock, so no concurrent mutations happen during collection. for i in 0.. 0) for cycle detection - # Only process roots from lowMark to immediateFreeStart (cycleStart == immediateFreeStart after swap loop) - for i in lowMark.. 0: - let (entry, childDesc) = j.traceStack.pop() - let t = head entry[] - entry[] = nil - # Recursively trace children to nil their descendants too - trace(t, childDesc, j) - - # Clear roots before freeing to prevent nested collectCycles() from accessing freed cells roots.len = 0 - # Free all roots (both immediate-free and cycle-detected) together + # Free all collected objects # Destructors must not call nimDecRefIsLastCyclicStatic (add to toDec) during this phase for i in 0 ..< j.toFree.len: let s = j.toFree.d[i][0] - s.rc = s.rc and not inRootsFlag when orcLeakDetector: writeCell("CYCLIC OBJECT FREED", s, j.toFree.d[i][1]) free(s, j.toFree.d[i][1]) when not defined(nimStressOrc): rootsThreshold = oldThreshold - j.freed = j.freed +% j.toFree.len +% immediateFreeCount + j.freed = j.freed +% j.toFree.len deinit j.toFree when defined(nimOrcStats):