Disabled mark-and-sweep in the compiler itself
This also adds "cycle roots trimming": a light-weight collection of the cycle roots performed in CollectZCT for candidates that are recently allocated and provably dead.
This commit is contained in:
parent
41cbd1c980
commit
31134a6bae
2 changed files with 34 additions and 8 deletions
|
|
@ -73,6 +73,7 @@ proc HandleCmdLine() =
|
||||||
|
|
||||||
when defined(GC_setMaxPause):
|
when defined(GC_setMaxPause):
|
||||||
GC_setMaxPause 2_000
|
GC_setMaxPause 2_000
|
||||||
|
GC_disableMarkAndSweep()
|
||||||
condsyms.InitDefines()
|
condsyms.InitDefines()
|
||||||
HandleCmdLine()
|
HandleCmdLine()
|
||||||
quit(options.gExitcode)
|
quit(options.gExitcode)
|
||||||
|
|
|
||||||
|
|
@ -124,6 +124,13 @@ type
|
||||||
tempStack: TCellSeq # temporary stack for recursion elimination
|
tempStack: TCellSeq # temporary stack for recursion elimination
|
||||||
freeStack: TCellSeq # objects ready to be freed
|
freeStack: TCellSeq # objects ready to be freed
|
||||||
recGcLock: int # prevent recursion via finalizers; no thread lock
|
recGcLock: int # prevent recursion via finalizers; no thread lock
|
||||||
|
cycleRootsTrimIdx: int # Trimming is a light-weight collection of the
|
||||||
|
# cycle roots table that uses a cheap linear scan
|
||||||
|
# to find only possitively dead objects.
|
||||||
|
# One strategy is to perform it only for new objects
|
||||||
|
# allocated between the invocations of CollectZCT.
|
||||||
|
# This index indicates the start of the range of
|
||||||
|
# such new objects within the table.
|
||||||
when withRealTime:
|
when withRealTime:
|
||||||
maxPause: TNanos # max allowed pause in nanoseconds; active if > 0
|
maxPause: TNanos # max allowed pause in nanoseconds; active if > 0
|
||||||
region: TMemRegion # garbage collected region
|
region: TMemRegion # garbage collected region
|
||||||
|
|
@ -646,6 +653,20 @@ template eraseAt(cells: var TCellSeq, at: int): stmt =
|
||||||
cells.d[at] = cells.d[cells.len - 1]
|
cells.d[at] = cells.d[cells.len - 1]
|
||||||
dec cells.len
|
dec cells.len
|
||||||
|
|
||||||
|
template trimAt(roots: var TCellSeq, at: int): stmt =
|
||||||
|
# This will remove a cycle root candidate during trimming.
|
||||||
|
# a candidate is removed either because it received a refup and
|
||||||
|
# it's no longer a candidate or because it received further refdowns
|
||||||
|
# and now it's dead for sure.
|
||||||
|
let c = roots.d[at]
|
||||||
|
c.clearBit(rcInCycleRoots)
|
||||||
|
roots.eraseAt(at)
|
||||||
|
if c.isBitUp(rcReallyDead) and c.refcount <% rcIncrement:
|
||||||
|
# This case covers both dead objects and retired buffers
|
||||||
|
# That's why we must also check the refcount (it may be
|
||||||
|
# kept possitive by stack references).
|
||||||
|
freeCell(gch, c)
|
||||||
|
|
||||||
proc newObj(typ: PNimType, size: int): pointer {.compilerRtl.} =
|
proc newObj(typ: PNimType, size: int): pointer {.compilerRtl.} =
|
||||||
setStackTop(gch)
|
setStackTop(gch)
|
||||||
result = rawNewObj(typ, size, gch, false)
|
result = rawNewObj(typ, size, gch, false)
|
||||||
|
|
@ -770,6 +791,16 @@ proc CollectZCT(gch: var TGcHeap): bool
|
||||||
template pseudoRecursion(typ: TRecursionType, body: stmt): stmt =
|
template pseudoRecursion(typ: TRecursionType, body: stmt): stmt =
|
||||||
#
|
#
|
||||||
|
|
||||||
|
proc trimCycleRoots(gch: var TGcHeap, startIdx = gch.cycleRootsTrimIdx) =
|
||||||
|
var i = startIdx
|
||||||
|
while i < gch.cycleRoots.len:
|
||||||
|
if gch.cycleRoots.d[i].color != rcCycleCandidate:
|
||||||
|
gch.cycleRoots.trimAt i
|
||||||
|
else:
|
||||||
|
inc i
|
||||||
|
|
||||||
|
gch.cycleRootsTrimIdx = gch.cycleRoots.len
|
||||||
|
|
||||||
# we now use a much simpler and non-recursive algorithm for cycle removal
|
# we now use a much simpler and non-recursive algorithm for cycle removal
|
||||||
proc collectCycles(gch: var TGcHeap) =
|
proc collectCycles(gch: var TGcHeap) =
|
||||||
if gch.cycleRoots.len == 0: return
|
if gch.cycleRoots.len == 0: return
|
||||||
|
|
@ -842,13 +873,7 @@ proc collectCycles(gch: var TGcHeap) =
|
||||||
recursiveDecRef(roots.d[i])
|
recursiveDecRef(roots.d[i])
|
||||||
inc i
|
inc i
|
||||||
else:
|
else:
|
||||||
let c = roots.d[i]
|
roots.trimAt i
|
||||||
c.clearBit(rcInCycleRoots)
|
|
||||||
roots.eraseAt(i)
|
|
||||||
if c.isBitUp(rcReallyDead):
|
|
||||||
freeCell(gch, c)
|
|
||||||
elif c.color == rcRetiredBuffer and c.refcount <% rcIncrement:
|
|
||||||
freeCell(gch, c)
|
|
||||||
|
|
||||||
markRoots(gch.cycleRoots)
|
markRoots(gch.cycleRoots)
|
||||||
|
|
||||||
|
|
@ -1220,7 +1245,7 @@ proc CollectZCT(gch: var TGcHeap): bool =
|
||||||
if duration >= gch.maxPause - 50_000:
|
if duration >= gch.maxPause - 50_000:
|
||||||
return false
|
return false
|
||||||
result = true
|
result = true
|
||||||
|
gch.trimCycleRoots
|
||||||
#deInit(gch.zct)
|
#deInit(gch.zct)
|
||||||
#init(gch.zct)
|
#init(gch.zct)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue