From 88b65ea957b286bf7225c63e38b6d83632ee6cce Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Fri, 11 Aug 2017 20:14:35 +0200 Subject: [PATCH] fixes #6234 --- compiler/ccgexprs.nim | 8 ++++---- lib/system/gc.nim | 3 +++ lib/system/mmdisp.nim | 2 +- tests/ccgbugs/twrongrefcounting.nim | 22 ++++++++++++++++++++++ 4 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 tests/ccgbugs/twrongrefcounting.nim diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index de784acf9c..fbdd5f3182 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -1100,9 +1100,9 @@ proc rawGenNew(p: BProc, a: TLoc, sizeExpr: Rope) = if a.s == OnHeap and usesNativeGC(): # use newObjRC1 as an optimization if canFormAcycle(a.t): - linefmt(p, cpsStmts, "if ($1) #nimGCunref($1);$n", a.rdLoc) + linefmt(p, cpsStmts, "if ($1) { #nimGCunrefRC1($1); $1 = NIM_NIL; }$n", a.rdLoc) else: - linefmt(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", a.rdLoc) + linefmt(p, cpsStmts, "if ($1) { #nimGCunrefNoCycle($1); $1 = NIM_NIL; }$n", a.rdLoc) b.r = ropecg(p.module, "($1) #newObjRC1($2, $3)", args) linefmt(p, cpsStmts, "$1 = $2;$n", a.rdLoc, b.rdLoc) else: @@ -1130,9 +1130,9 @@ proc genNewSeqAux(p: BProc, dest: TLoc, length: Rope) = initLoc(call, locExpr, dest.t, OnHeap) if dest.s == OnHeap and usesNativeGC(): if canFormAcycle(dest.t): - linefmt(p, cpsStmts, "if ($1) #nimGCunref($1);$n", dest.rdLoc) + linefmt(p, cpsStmts, "if ($1) { #nimGCunrefRC1($1); $1 = NIM_NIL; }$n", dest.rdLoc) else: - linefmt(p, cpsStmts, "if ($1) #nimGCunrefNoCycle($1);$n", dest.rdLoc) + linefmt(p, cpsStmts, "if ($1) { #nimGCunrefNoCycle($1); $1 = NIM_NIL; }$n", dest.rdLoc) call.r = ropecg(p.module, "($1) #newSeqRC1($2, $3)", args) linefmt(p, cpsStmts, "$1 = $2;$n", dest.rdLoc, call.rdLoc) else: diff --git a/lib/system/gc.nim b/lib/system/gc.nim index 87a07fae98..80aa5cf1be 100644 --- a/lib/system/gc.nim +++ b/lib/system/gc.nim @@ -259,6 +259,9 @@ proc nimGCunrefNoCycle(p: pointer) {.compilerProc, inline.} = sysAssert(allocInv(gch.region), "end nimGCunrefNoCycle 2") sysAssert(allocInv(gch.region), "end nimGCunrefNoCycle 5") +proc nimGCunrefRC1(p: pointer) {.compilerProc, inline.} = + decRef(usrToCell(p)) + proc asgnRef(dest: PPointer, src: pointer) {.compilerProc, inline.} = # the code generator calls this proc! gcAssert(not isOnStack(dest), "asgnRef") diff --git a/lib/system/mmdisp.nim b/lib/system/mmdisp.nim index 5b5ba94908..35fa0ce9a4 100644 --- a/lib/system/mmdisp.nim +++ b/lib/system/mmdisp.nim @@ -16,7 +16,7 @@ const debugGC = false # we wish to debug the GC... logGC = false - traceGC = defined(smokeCycles) # extensive debugging + traceGC = false # extensive debugging alwaysCycleGC = defined(smokeCycles) alwaysGC = defined(fulldebug) # collect after every memory # allocation (for debugging) diff --git a/tests/ccgbugs/twrongrefcounting.nim b/tests/ccgbugs/twrongrefcounting.nim new file mode 100644 index 0000000000..c0c3e0fc24 --- /dev/null +++ b/tests/ccgbugs/twrongrefcounting.nim @@ -0,0 +1,22 @@ +discard """ + output: '''ok''' + cmd: "nim c -r --gc:refc -d:useGcAssert -d:useSysAssert -d:fulldebug -d:smokeCycles $file" +""" +# bug #6234 +type + Foo = ref object + s: seq[Bar] + Bar = ref object + f: Foo + +proc test() = + var f = Foo.new() + for i in 0 .. 5: + f.s = @[] + for j in 0 .. 5: + var b = Bar.new() + b.f = f + f.s.add(b) + +test() +echo "ok"