mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-30 09:54:49 +00:00
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:
@@ -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 ------------------------------
|
||||
|
||||
@@ -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)),
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
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)
|
||||
Reference in New Issue
Block a user