summary refs log tree commit diff stats
path: root/lib/system/gc_common.nim
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2017-09-15 09:27:51 +0200
committerAndreas Rumpf <rumpf_a@web.de>2017-09-15 09:27:51 +0200
commit39f0195ebf30cc9f4b96953423298d7a2130eac8 (patch)
treebb4daf580c239b59d232e186814b69fc642ce6d5 /lib/system/gc_common.nim
parentbc738d63a728ee6030cc224c8808990a6f641feb (diff)
parent2ef65d5cdf3d65cbfab4c39796ddb4e70e9ebb37 (diff)
downloadNim-39f0195ebf30cc9f4b96953423298d7a2130eac8.tar.gz
Merge branch 'devel' into araq
Diffstat (limited to 'lib/system/gc_common.nim')
-rw-r--r--lib/system/gc_common.nim32
1 files changed, 32 insertions, 0 deletions
diff --git a/lib/system/gc_common.nim b/lib/system/gc_common.nim
index cd03d2a54..220331e96 100644
--- a/lib/system/gc_common.nim
+++ b/lib/system/gc_common.nim
@@ -351,3 +351,35 @@ else:
 # ----------------------------------------------------------------------------
 # end of non-portable code
 # ----------------------------------------------------------------------------
+
+proc prepareDealloc(cell: PCell) =
+  when declared(useMarkForDebug):
+    when useMarkForDebug:
+      gcAssert(cell notin gch.marked, "Cell still alive!")
+  let t = cell.typ
+  if t.finalizer != nil:
+    # the finalizer could invoke something that
+    # allocates memory; this could trigger a garbage
+    # collection. Since we are already collecting we
+    # prevend recursive entering here by a lock.
+    # XXX: we should set the cell's children to nil!
+    inc(gch.recGcLock)
+    (cast[Finalizer](t.finalizer))(cellToUsr(cell))
+    dec(gch.recGcLock)
+  decTypeSize(cell, t)
+
+proc deallocHeap*(runFinalizers = true; allowGcAfterwards = true) =
+  ## Frees the thread local heap. Runs every finalizer if ``runFinalizers```
+  ## is true. If ``allowGcAfterwards`` is true, a minimal amount of allocation
+  ## happens to ensure the GC can continue to work after the call
+  ## to ``deallocHeap``.
+  if runFinalizers:
+    for x in allObjects(gch.region):
+      if isCell(x):
+        # cast to PCell is correct here:
+        var c = cast[PCell](x)
+        prepareDealloc(c)
+  deallocOsPages(gch.region)
+  zeroMem(addr gch.region, sizeof(gch.region))
+  if allowGcAfterwards:
+    initGC()