summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2016-05-23 12:54:01 +0200
committerAndreas Rumpf <rumpf_a@web.de>2016-05-23 12:54:01 +0200
commit55ec99b70b56e7fb258e4ba2bccdea3767ff8a51 (patch)
treea872a620384a0e46b67da8f38b3715b531ab1772
parent9b609b26ca07ee78cb24e82fa89d31072f9f9133 (diff)
downloadNim-55ec99b70b56e7fb258e4ba2bccdea3767ff8a51.tar.gz
new GC listens to GC_ref/GC_unref
-rw-r--r--lib/system/gc.nim23
1 files changed, 21 insertions, 2 deletions
diff --git a/lib/system/gc.nim b/lib/system/gc.nim
index ed5b2d1e9..ee5eec30b 100644
--- a/lib/system/gc.nim
+++ b/lib/system/gc.nim
@@ -89,6 +89,7 @@ type
     stat: GcStat
     when useMarkForDebug or useBackupGc:
       marked: CellSet
+      additionalRoots: CellSeq # dummy roots for GC_ref/unref
     when hasThreadSupport:
       toDispose: SharedList[pointer]
 
@@ -223,8 +224,23 @@ proc incRef(c: PCell) {.inline.} =
   # and not colorMask
   #writeCell("incRef", c)
 
-proc nimGCref(p: pointer) {.compilerProc, inline.} = incRef(usrToCell(p))
-proc nimGCunref(p: pointer) {.compilerProc, inline.} = decRef(usrToCell(p))
+proc nimGCref(p: pointer) {.compilerProc.} =
+  # we keep it from being collected by pretending it's not even allocated:
+  add(gch.additionalRoots, usrToCell(p))
+  incRef(usrToCell(p))
+
+proc nimGCunref(p: pointer) {.compilerProc.} =
+  let cell = usrToCell(p)
+  var L = gch.additionalRoots.len-1
+  var i = L
+  let d = gch.additionalRoots.d
+  while i >= 0:
+    if d[i] == cell:
+      d[i] = d[L]
+      dec gch.additionalRoots.len
+      break
+    dec(i)
+  decRef(usrToCell(p))
 
 proc GC_addCycleRoot*[T](p: ref T) {.inline.} =
   ## adds 'p' to the cycle candidate set for the cycle collector. It is
@@ -294,6 +310,7 @@ proc initGC() =
     init(gch.decStack)
     when useMarkForDebug or useBackupGc:
       init(gch.marked)
+      init(gch.additionalRoots)
     when hasThreadSupport:
       gch.toDispose = initSharedList[pointer]()
 
@@ -608,6 +625,8 @@ when useMarkForDebug or useBackupGc:
 
   proc markGlobals(gch: var GcHeap) =
     for i in 0 .. < globalMarkersLen: globalMarkers[i]()
+    let d = gch.additionalRoots.d
+    for i in 0 .. < gch.additionalRoots.len: markS(gch, d[i])
 
 when logGC:
   var