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:
parent
c67520a7c5
commit
e9e22ccb2a
4 changed files with 98 additions and 8 deletions
|
|
@ -576,6 +576,9 @@ type
|
||||||
flags*: TLocFlags # location's flags
|
flags*: TLocFlags # location's flags
|
||||||
t*: PType # type of location
|
t*: PType # type of location
|
||||||
r*: PRope # rope value of location (code generators)
|
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
|
a*: int # location's "address", i.e. slot for temporaries
|
||||||
|
|
||||||
# ---------------- end of backend information ------------------------------
|
# ---------------- end of backend information ------------------------------
|
||||||
|
|
|
||||||
|
|
@ -165,7 +165,7 @@ proc getStorageLoc(n: PNode): TStorageLoc =
|
||||||
|
|
||||||
proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
if dest.s == OnStack or optRefcGC notin gGlobalOptions:
|
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)
|
if needToKeepAlive in flags: keepAlive(p, dest)
|
||||||
elif dest.s == OnHeap:
|
elif dest.s == OnHeap:
|
||||||
# location is on heap
|
# 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",
|
linefmt(p, cpsStmts, "#asgnRef((void**) $1, $2);$n",
|
||||||
addrLoc(dest), rdLoc(src))
|
addrLoc(dest), rdLoc(src))
|
||||||
else:
|
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",
|
linefmt(p, cpsStmts, "#asgnRefNoCycle((void**) $1, $2);$n",
|
||||||
addrLoc(dest), rdLoc(src))
|
addrLoc(dest), rdLoc(src))
|
||||||
else:
|
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",
|
linefmt(p, cpsStmts, "#unsureAsgnRef((void**) $1, $2);$n",
|
||||||
addrLoc(dest), rdLoc(src))
|
addrLoc(dest), rdLoc(src))
|
||||||
if needToKeepAlive in flags: keepAlive(p, dest)
|
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)
|
InitLocExpr(p, e.sons[0], a)
|
||||||
putIntoDest(p, d, e.typ, addrLoc(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 =
|
proc genRecordFieldAux(p: BProc, e: PNode, d, a: var TLoc): PType =
|
||||||
initLocExpr(p, e.sons[0], a)
|
initLocExpr(p, e.sons[0], a)
|
||||||
if e.sons[1].kind != nkSym: InternalError(e.info, "genRecordFieldAux")
|
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
|
discard getTypeDesc(p.module, a.t) # fill the record's fields.loc
|
||||||
result = a.t
|
result = a.t
|
||||||
|
|
||||||
|
|
@ -598,7 +613,7 @@ proc genTupleElem(p: BProc, e: PNode, d: var TLoc) =
|
||||||
a: TLoc
|
a: TLoc
|
||||||
i: int
|
i: int
|
||||||
initLocExpr(p, e.sons[0], a)
|
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
|
discard getTypeDesc(p.module, a.t) # fill the record's fields.loc
|
||||||
var ty = a.t
|
var ty = a.t
|
||||||
var r = rdLoc(a)
|
var r = rdLoc(a)
|
||||||
|
|
@ -688,7 +703,7 @@ proc genArrayElem(p: BProc, e: PNode, d: var TLoc) =
|
||||||
let idx = getOrdValue(e.sons[1])
|
let idx = getOrdValue(e.sons[1])
|
||||||
if idx < firstOrd(ty) or idx > lastOrd(ty):
|
if idx < firstOrd(ty) or idx > lastOrd(ty):
|
||||||
localError(e.info, errIndexOutOfBounds)
|
localError(e.info, errIndexOutOfBounds)
|
||||||
if d.k == locNone: d.s = a.s
|
d.inheritLocation(a)
|
||||||
putIntoDest(p, d, elemType(skipTypes(ty, abstractVar)),
|
putIntoDest(p, d, elemType(skipTypes(ty, abstractVar)),
|
||||||
rfmt(nil, "$1[($2)- $3]", rdLoc(a), rdCharLoc(b), first))
|
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",
|
"if ((NU)($1) >= (NU)($2->$3)) #raiseIndexError();$n",
|
||||||
rdLoc(b), rdLoc(a), lenField())
|
rdLoc(b), rdLoc(a), lenField())
|
||||||
if d.k == locNone: d.s = OnHeap
|
if d.k == locNone: d.s = OnHeap
|
||||||
|
d.heapRoot = a.r
|
||||||
if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}:
|
if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}:
|
||||||
a.r = rfmt(nil, "(*$1)", a.r)
|
a.r = rfmt(nil, "(*$1)", a.r)
|
||||||
putIntoDest(p, d, elemType(skipTypes(a.t, abstractVar)),
|
putIntoDest(p, d, elemType(skipTypes(a.t, abstractVar)),
|
||||||
|
|
|
||||||
|
|
@ -233,7 +233,7 @@ proc binaryStrSearch*(x: openarray[string], y: string): int =
|
||||||
result = - 1
|
result = - 1
|
||||||
|
|
||||||
# Can we keep this? I'm using it all the time
|
# Can we keep this? I'm using it all the time
|
||||||
template nimdbg*: expr = c.filename.endsWith"hallo.nim"
|
template nimdbg*: expr = c.module.fileIdx == gProjectMainIdx
|
||||||
template cnimdbg*: expr = p.module.filename.endsWith"hallo.nim"
|
template cnimdbg*: expr = p.module.module.fileIdx == gProjectMainIdx
|
||||||
template enimdbg*: expr = c.module.name.s == "hallo"
|
template pnimdbg*: expr = p.lex.fileIdx == gProjectMainIdx
|
||||||
template pnimdbg*: expr = p.lex.fileIdx.ToFilename.endsWith"hallo.nim"
|
|
||||||
|
|
|
||||||
71
tests/compile/theaproots.nim
Normal file
71
tests/compile/theaproots.nim
Normal 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)
|
||||||
Loading…
Add table
Add a link
Reference in a new issue