ORC: critical bugfix for the cycle analyser, introduce -d:nimStressOrc for easier stress testing (#15572)

This commit is contained in:
Andreas Rumpf 2020-10-14 22:26:21 +02:00 • committed by GitHub
commit 644eb4dd54
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 33 additions and 20 deletions

View file

@ -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:

View file

@ -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)

View file

@ -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,6 +322,8 @@ proc collectCycles() =
deinit j.traceStack deinit j.traceStack
deinit roots deinit roots
when not defined(nimStressOrc):
# compute the threshold based on the previous history # compute the threshold based on the previous history
# of the cycle collector's effectiveness: # of the cycle collector's effectiveness:
# we're effective when we collected 50% or more of the nodes # we're effective when we collected 50% or more of the nodes
@ -337,11 +341,12 @@ proc collectCycles() =
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,9 +355,11 @@ proc GC_fullCollect* =
collectCycles() collectCycles()
proc GC_enableMarkAndSweep*() = proc GC_enableMarkAndSweep*() =
when not defined(nimStressOrc):
rootsThreshold = defaultThreshold rootsThreshold = defaultThreshold
proc GC_disableMarkAndSweep*() = proc GC_disableMarkAndSweep*() =
when not defined(nimStressOrc):
rootsThreshold = high(int) rootsThreshold = high(int)
proc rememberCycle(isDestroyAction: bool; s: Cell; desc: PNimTypeV2) {.noinline.} = proc rememberCycle(isDestroyAction: bool; s: Cell; desc: PNimTypeV2) {.noinline.} =