ORC: critical bugfix for the cycle analyser, introduce -d:nimStressOrc for easier stress testing (#15572)
This commit is contained in:
parent
c2ba4ef979
commit
644eb4dd54
3 changed files with 33 additions and 20 deletions
|
|
@ -518,7 +518,7 @@ proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
addDestructorCall(c, elemType, newNodeI(nkStmtList, c.info), genDeref(x, nkDerefExpr))
|
addDestructorCall(c, elemType, newNodeI(nkStmtList, c.info), genDeref(x, nkDerefExpr))
|
||||||
actions.add callCodegenProc(c.g, "nimDestroyAndDispose", c.info, x)
|
actions.add callCodegenProc(c.g, "nimDestroyAndDispose", c.info, x)
|
||||||
|
|
||||||
let isCyclic = c.g.config.selectedGC == gcOrc and types.canFormAcycle(t)
|
let isCyclic = c.g.config.selectedGC == gcOrc and types.canFormAcycle(elemType)
|
||||||
|
|
||||||
var cond: PNode
|
var cond: PNode
|
||||||
if isCyclic:
|
if isCyclic:
|
||||||
|
|
|
||||||
|
|
@ -161,6 +161,12 @@ proc nimRawDispose(p: pointer) {.compilerRtl.} =
|
||||||
if head(p).rc >= rcIncrement:
|
if head(p).rc >= rcIncrement:
|
||||||
cstderr.rawWrite "[FATAL] dangling references exist\n"
|
cstderr.rawWrite "[FATAL] dangling references exist\n"
|
||||||
quit 1
|
quit 1
|
||||||
|
|
||||||
|
when defined(gcOrc) and defined(nimArcDebug):
|
||||||
|
if (head(p).rc and 0b100) != 0:
|
||||||
|
cstderr.rawWrite "[FATAL] cycle root freed\n"
|
||||||
|
quit 1
|
||||||
|
|
||||||
when defined(nimArcDebug):
|
when defined(nimArcDebug):
|
||||||
# we do NOT really free the memory here in order to reliably detect use-after-frees
|
# we do NOT really free the memory here in order to reliably detect use-after-frees
|
||||||
if freedCells.data == nil: init(freedCells)
|
if freedCells.data == nil: init(freedCells)
|
||||||
|
|
|
||||||
|
|
@ -297,8 +297,10 @@ proc collectCyclesBacon(j: var GcEnv) =
|
||||||
const
|
const
|
||||||
defaultThreshold = when defined(nimAdaptiveOrc): 128 else: 10_000
|
defaultThreshold = when defined(nimAdaptiveOrc): 128 else: 10_000
|
||||||
|
|
||||||
var
|
when defined(nimStressOrc):
|
||||||
rootsThreshold = defaultThreshold
|
const rootsThreshold = 10 # broken with -d:nimStressOrc: 10 and for havlak iterations 1..8
|
||||||
|
else:
|
||||||
|
var rootsThreshold = defaultThreshold
|
||||||
|
|
||||||
proc collectCycles() =
|
proc collectCycles() =
|
||||||
## Collect cycles.
|
## Collect cycles.
|
||||||
|
|
@ -320,28 +322,31 @@ proc collectCycles() =
|
||||||
|
|
||||||
deinit j.traceStack
|
deinit j.traceStack
|
||||||
deinit roots
|
deinit roots
|
||||||
# compute the threshold based on the previous history
|
|
||||||
# of the cycle collector's effectiveness:
|
when not defined(nimStressOrc):
|
||||||
# we're effective when we collected 50% or more of the nodes
|
# compute the threshold based on the previous history
|
||||||
# we touched. If we're effective, we can reset the threshold:
|
# of the cycle collector's effectiveness:
|
||||||
if j.freed * 2 >= j.touched:
|
# we're effective when we collected 50% or more of the nodes
|
||||||
when defined(nimAdaptiveOrc):
|
# we touched. If we're effective, we can reset the threshold:
|
||||||
rootsThreshold = max(rootsThreshold div 2, 16)
|
if j.freed * 2 >= j.touched:
|
||||||
else:
|
when defined(nimAdaptiveOrc):
|
||||||
rootsThreshold = defaultThreshold
|
rootsThreshold = max(rootsThreshold div 2, 16)
|
||||||
#cfprintf(cstderr, "[collectCycles] freed %ld, touched %ld new threshold %ld\n", j.freed, j.touched, rootsThreshold)
|
else:
|
||||||
elif rootsThreshold < high(int) div 4:
|
rootsThreshold = defaultThreshold
|
||||||
rootsThreshold = rootsThreshold * 3 div 2
|
#cfprintf(cstderr, "[collectCycles] freed %ld, touched %ld new threshold %ld\n", j.freed, j.touched, rootsThreshold)
|
||||||
|
elif rootsThreshold < high(int) div 4:
|
||||||
|
rootsThreshold = rootsThreshold * 3 div 2
|
||||||
when logOrc:
|
when logOrc:
|
||||||
cfprintf(cstderr, "[collectCycles] end; freed %ld new threshold %ld touched: %ld mem: %ld\n", j.freed, rootsThreshold, j.touched,
|
cfprintf(cstderr, "[collectCycles] end; freed %ld new threshold %ld touched: %ld mem: %ld\n", j.freed, rootsThreshold, j.touched,
|
||||||
getOccupiedMem())
|
getOccupiedMem())
|
||||||
|
|
||||||
proc registerCycle(s: Cell; desc: PNimTypeV2) =
|
proc registerCycle(s: Cell; desc: PNimTypeV2) =
|
||||||
|
s.rootIdx = roots.len
|
||||||
|
if roots.d == nil: init(roots)
|
||||||
|
add(roots, s, desc)
|
||||||
|
|
||||||
if roots.len >= rootsThreshold:
|
if roots.len >= rootsThreshold:
|
||||||
collectCycles()
|
collectCycles()
|
||||||
if roots.d == nil: init(roots)
|
|
||||||
s.rootIdx = roots.len
|
|
||||||
add(roots, s, desc)
|
|
||||||
#writeCell("[added root]", s)
|
#writeCell("[added root]", s)
|
||||||
|
|
||||||
proc GC_fullCollect* =
|
proc GC_fullCollect* =
|
||||||
|
|
@ -350,10 +355,12 @@ proc GC_fullCollect* =
|
||||||
collectCycles()
|
collectCycles()
|
||||||
|
|
||||||
proc GC_enableMarkAndSweep*() =
|
proc GC_enableMarkAndSweep*() =
|
||||||
rootsThreshold = defaultThreshold
|
when not defined(nimStressOrc):
|
||||||
|
rootsThreshold = defaultThreshold
|
||||||
|
|
||||||
proc GC_disableMarkAndSweep*() =
|
proc GC_disableMarkAndSweep*() =
|
||||||
rootsThreshold = high(int)
|
when not defined(nimStressOrc):
|
||||||
|
rootsThreshold = high(int)
|
||||||
|
|
||||||
proc rememberCycle(isDestroyAction: bool; s: Cell; desc: PNimTypeV2) {.noinline.} =
|
proc rememberCycle(isDestroyAction: bool; s: Cell; desc: PNimTypeV2) {.noinline.} =
|
||||||
if isDestroyAction:
|
if isDestroyAction:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue