diff options
author | Zahary Karadjov <zahary@gmail.com> | 2012-12-01 15:24:32 +0200 |
---|---|---|
committer | Zahary Karadjov <zahary@gmail.com> | 2012-12-01 15:37:13 +0200 |
commit | e9e22ccb2adfe1a44e998405b2dfed9b46ddcb95 (patch) | |
tree | f157d6c1bc8e3b908c8175a3729ce2f8e7bc48f4 | |
parent | c67520a7c5d474be409bee98d9b258030115c259 (diff) | |
download | Nim-e9e22ccb2adfe1a44e998405b2dfed9b46ddcb95.tar.gz |
track the "owner" heap object in the ref write barrier
See the papers for reference counting with heap sliding views for details:
-rwxr-xr-x | compiler/ast.nim | 3 | ||||
-rwxr-xr-x | compiler/ccgexprs.nim | 24 | ||||
-rwxr-xr-x | compiler/options.nim | 8 | ||||
-rw-r--r-- | tests/compile/theaproots.nim | 71 |
4 files changed, 98 insertions, 8 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index 6943add46..419c1f2d8 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 ddc93d5a3..67d7b1a38 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 a09384d33..588d716c3 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 000000000..aec140f42 --- /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) |