summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorZahary Karadjov <zahary@gmail.com>2012-12-01 15:24:32 +0200
committerZahary Karadjov <zahary@gmail.com>2012-12-01 15:37:13 +0200
commite9e22ccb2adfe1a44e998405b2dfed9b46ddcb95 (patch)
treef157d6c1bc8e3b908c8175a3729ce2f8e7bc48f4
parentc67520a7c5d474be409bee98d9b258030115c259 (diff)
downloadNim-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-xcompiler/ast.nim3
-rwxr-xr-xcompiler/ccgexprs.nim24
-rwxr-xr-xcompiler/options.nim8
-rw-r--r--tests/compile/theaproots.nim71
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)