track the "owner" heap object in the ref write barrier

See the papers for reference counting with heap sliding views for details:
This commit is contained in:
Zahary Karadjov
2012-12-01 15:24:32 +02:00
parent c67520a7c5
commit e9e22ccb2a
4 changed files with 98 additions and 8 deletions

View File

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

View File

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

View File

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

View File

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