summary refs log tree commit diff stats
path: root/lib/system/gc_ms.nim
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2014-04-30 00:22:45 +0200
committerAraq <rumpf_a@web.de>2014-04-30 00:22:45 +0200
commited1927e0013a72b1e33086b674d8546de4641a9b (patch)
tree58b188d3c3154cb1a8bb4c9a11ca1c1c3fa29c8c /lib/system/gc_ms.nim
parent5bbb09acf8b3efdc2440df356167f9fb413335ea (diff)
downloadNim-ed1927e0013a72b1e33086b674d8546de4641a9b.tar.gz
bugfix: MS GC acknowledges GC_ref/unref properly
Diffstat (limited to 'lib/system/gc_ms.nim')
-rw-r--r--lib/system/gc_ms.nim51
1 files changed, 45 insertions, 6 deletions
diff --git a/lib/system/gc_ms.nim b/lib/system/gc_ms.nim
index 3c99a57e1..db437b8d0 100644
--- a/lib/system/gc_ms.nim
+++ b/lib/system/gc_ms.nim
@@ -48,12 +48,15 @@ type
                              # non-zero count table
     stackBottom: pointer
     cycleThreshold: int
+    when useCellIds:
+      idGenerator: int
     when withBitvectors:
       allocated, marked: TCellSet
     tempStack: TCellSeq      # temporary stack for recursion elimination
     recGcLock: int           # prevent recursion via finalizers; no thread lock
     region: TMemRegion       # garbage collected region
     stat: TGcStat
+    additionalRoots: TCellSeq # dummy roots for GC_ref/unref
 
 var
   gch {.rtlThreadVar.}: TGcHeap
@@ -131,13 +134,26 @@ proc prepareDealloc(cell: PCell) =
     (cast[TFinalizer](cell.typ.finalizer))(cellToUsr(cell))
     dec(gch.recGcLock)
 
-proc nimGCref(p: pointer) {.compilerProc, inline.} = 
+proc nimGCref(p: pointer) {.compilerProc.} = 
   # we keep it from being collected by pretending it's not even allocated:
-  when withBitvectors: excl(gch.allocated, usrToCell(p))
-  else: usrToCell(p).refcount = rcBlack
-proc nimGCunref(p: pointer) {.compilerProc, inline.} = 
-  when withBitvectors: incl(gch.allocated, usrToCell(p))
-  else: usrToCell(p).refcount = rcWhite
+  when false:
+    when withBitvectors: excl(gch.allocated, usrToCell(p))
+    else: usrToCell(p).refcount = rcBlack
+  add(gch.additionalRoots, usrToCell(p))
+
+proc nimGCunref(p: pointer) {.compilerProc.} =
+  let cell = usrToCell(p)
+  var L = gch.additionalRoots.len
+  var i = L
+  let d = gch.additionalRoots.d
+  while i >= 0:
+    if d[i] == cell:
+      d[i] = d[L]
+      dec gch.additionalRoots.len
+      break
+  when false:
+    when withBitvectors: incl(gch.allocated, usrToCell(p))
+    else: usrToCell(p).refcount = rcWhite
 
 proc initGC() =
   when not defined(useNimRtl):
@@ -146,6 +162,7 @@ proc initGC() =
     gch.stat.maxThreshold = 0
     gch.stat.maxStackSize = 0
     init(gch.tempStack)
+    init(gch.additionalRoots)
     when withBitvectors:
       Init(gch.allocated)
       init(gch.marked)
@@ -212,8 +229,16 @@ proc rawNewObj(typ: PNimType, size: int, gch: var TGcHeap): pointer =
   res.refcount = 0
   release(gch)
   when withBitvectors: incl(gch.allocated, res)
+  when useCellIds:
+    inc gch.idGenerator
+    res.id = gch.idGenerator
   result = cellToUsr(res)
 
+when useCellIds:
+  proc getCellId*[T](x: ref T): int =
+    let p = usrToCell(cast[pointer](x))
+    result = p.id
+
 {.pop.}
 
 proc newObj(typ: PNimType, size: int): pointer {.compilerRtl.} =
@@ -262,6 +287,9 @@ proc growObj(old: pointer, newsize: int, gch: var TGcHeap): pointer =
   else:
     zeroMem(ol, sizeof(TCell))
   when withBitvectors: incl(gch.allocated, res)
+  when useCellIds:
+    inc gch.idGenerator
+    res.id = gch.idGenerator
   release(gch)
   result = cellToUsr(res)
   when defined(memProfiler): nimProfile(newsize-oldsize)
@@ -332,8 +360,19 @@ proc sweep(gch: var TGcHeap) =
         if c.refcount == rcBlack: c.refcount = rcWhite
         else: freeCyclicCell(gch, c)
 
+when false:
+  proc newGcInvariant*() =
+    for x in allObjects(gch.region):
+      if isCell(x):
+        var c = cast[PCell](x)
+        if c.typ == nil:
+          writeStackTrace()
+          quit 1
+
 proc markGlobals(gch: var TGcHeap) =
   for i in 0 .. < globalMarkersLen: globalMarkers[i]()
+  let d = gch.additionalRoots.d
+  for i in 0 .. < gch.additionalRoots.len: mark(gch, d[i])
 
 proc gcMark(gch: var TGcHeap, p: pointer) {.inline.} =
   # the addresses are not as cells on the stack, so turn them to cells: