diff --git a/compiler/ast.nim b/compiler/ast.nim index 6943add46f..419c1f2d8f 100755 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -576,6 +576,9 @@ type flags*: TLocFlags # location's flags t*: PType # type of location r*: PRope # rope value of location (code generators) + heapRoot*: PRope # keeps track of the enclosing heap object that + # owns this location (required by GC algorithms + # employing heap snapshots or sliding views) a*: int # location's "address", i.e. slot for temporaries # ---------------- end of backend information ------------------------------ diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index ddc93d5a3d..67d7b1a38e 100755 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -165,7 +165,7 @@ proc getStorageLoc(n: PNode): TStorageLoc = proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = if dest.s == OnStack or optRefcGC notin gGlobalOptions: - lineF(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)]) + linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src)) if needToKeepAlive in flags: keepAlive(p, dest) elif dest.s == OnHeap: # location is on heap @@ -188,9 +188,19 @@ proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = linefmt(p, cpsStmts, "#asgnRef((void**) $1, $2);$n", addrLoc(dest), rdLoc(src)) else: + if cnimdbg: + echo "ASSIGN REF ", dest.k, " ", dest.s, " ", dest.r.ropeToStr + if dest.heapRoot != nil: + echo "ROOTED AT ", dest.heapRoot.ropeToStr + linefmt(p, cpsStmts, "#asgnRefNoCycle((void**) $1, $2);$n", addrLoc(dest), rdLoc(src)) else: + if cnimdbg: + echo "ASSIGN REF ", dest.k, " ", dest.s, " ", dest.r.ropeToStr + if dest.heapRoot != nil: + echo "ROOTED AT ", dest.heapRoot.ropeToStr + linefmt(p, cpsStmts, "#unsureAsgnRef((void**) $1, $2);$n", addrLoc(dest), rdLoc(src)) if needToKeepAlive in flags: keepAlive(p, dest) @@ -562,10 +572,15 @@ proc genAddr(p: BProc, e: PNode, d: var TLoc) = InitLocExpr(p, e.sons[0], a) putIntoDest(p, d, e.typ, addrLoc(a)) +template inheritLocation(d: var TLoc, a: TLoc) = + if d.k == locNone: d.s = a.s + if d.heapRoot == nil: + d.heapRoot = if a.heapRoot != nil: a.heapRoot else: a.r + proc genRecordFieldAux(p: BProc, e: PNode, d, a: var TLoc): PType = initLocExpr(p, e.sons[0], a) if e.sons[1].kind != nkSym: InternalError(e.info, "genRecordFieldAux") - if d.k == locNone: d.s = a.s + d.inheritLocation(a) discard getTypeDesc(p.module, a.t) # fill the record's fields.loc result = a.t @@ -598,7 +613,7 @@ proc genTupleElem(p: BProc, e: PNode, d: var TLoc) = a: TLoc i: int initLocExpr(p, e.sons[0], a) - if d.k == locNone: d.s = a.s + d.inheritLocation(a) discard getTypeDesc(p.module, a.t) # fill the record's fields.loc var ty = a.t var r = rdLoc(a) @@ -688,7 +703,7 @@ proc genArrayElem(p: BProc, e: PNode, d: var TLoc) = let idx = getOrdValue(e.sons[1]) if idx < firstOrd(ty) or idx > lastOrd(ty): localError(e.info, errIndexOutOfBounds) - if d.k == locNone: d.s = a.s + d.inheritLocation(a) putIntoDest(p, d, elemType(skipTypes(ty, abstractVar)), rfmt(nil, "$1[($2)- $3]", rdLoc(a), rdCharLoc(b), first)) @@ -729,6 +744,7 @@ proc genSeqElem(p: BPRoc, e: PNode, d: var TLoc) = "if ((NU)($1) >= (NU)($2->$3)) #raiseIndexError();$n", rdLoc(b), rdLoc(a), lenField()) if d.k == locNone: d.s = OnHeap + d.heapRoot = a.r if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}: a.r = rfmt(nil, "(*$1)", a.r) putIntoDest(p, d, elemType(skipTypes(a.t, abstractVar)), diff --git a/compiler/options.nim b/compiler/options.nim index a09384d33b..588d716c39 100755 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -233,7 +233,7 @@ proc binaryStrSearch*(x: openarray[string], y: string): int = result = - 1 # Can we keep this? I'm using it all the time -template nimdbg*: expr = c.filename.endsWith"hallo.nim" -template cnimdbg*: expr = p.module.filename.endsWith"hallo.nim" -template enimdbg*: expr = c.module.name.s == "hallo" -template pnimdbg*: expr = p.lex.fileIdx.ToFilename.endsWith"hallo.nim" +template nimdbg*: expr = c.module.fileIdx == gProjectMainIdx +template cnimdbg*: expr = p.module.module.fileIdx == gProjectMainIdx +template pnimdbg*: expr = p.lex.fileIdx == gProjectMainIdx + diff --git a/tests/compile/theaproots.nim b/tests/compile/theaproots.nim new file mode 100644 index 0000000000..aec140f421 --- /dev/null +++ b/tests/compile/theaproots.nim @@ -0,0 +1,71 @@ +type + Bar = object + x: int + + Foo = object + rheap: ref Bar + rmaybe: ref Bar + rstack: ref Bar + list: seq[ref Bar] + listarr: array[0..5, ref Bar] + nestedtup: Tup + inner: TInner + inref: ref TInner + + TInner = object + inref: ref Bar + + Tup = tuple + tupbar: ref Bar + inner: TInner + +proc acc(x: var Foo): var ref Bar = + result = x.rheap + +proc test(maybeFoo: var Foo, + maybeSeq: var seq[ref Bar], + bars: var openarray[ref Bar], + maybeTup: var Tup) = + var bb: ref Bar + maybeFoo.rmaybe = bb + maybeFoo.list[3] = bb + maybeFoo.listarr[3] = bb + acc(maybeFoo) = bb + + var localFoo: Foo + localFoo.rstack = bb + localFoo.list[3] = bb + localFoo.listarr[3] = bb + acc(localFoo) = bb + + var heapFoo: ref Foo + heapFoo.rheap = bb + heapFoo.list[3] = bb + heapFoo.listarr[3] = bb + acc(heapFoo[]) = bb + + heapFoo.nestedtup.tupbar = bb + heapFoo.nestedtup.inner.inref = bb + heapFoo.inner.inref = bb + heapFoo.inref.inref = bb + + var locseq: seq[ref Bar] + locseq[3] = bb + + var locarr: array[0..4, ref Bar] + locarr[3] = bb + + maybeSeq[3] = bb + + bars[3] = bb + + maybeTup[0] = bb + +var + ff: ref Foo + tt: Tup + gseq: seq[ref Bar] + +new(ff) + +test(ff[], gseq, gseq, tt)