summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/system/gc.nim15
-rw-r--r--lib/system/gc_common.nim32
-rw-r--r--lib/system/gc_ms.nim12
3 files changed, 32 insertions, 27 deletions
diff --git a/lib/system/gc.nim b/lib/system/gc.nim
index 2cef2b636..87a07fae9 100644
--- a/lib/system/gc.nim
+++ b/lib/system/gc.nim
@@ -238,21 +238,6 @@ proc nimGCunref(p: pointer) {.compilerProc.} =
 
 include gc_common
 
-proc prepareDealloc(cell: PCell) =
-  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)
-
 template beforeDealloc(gch: var GcHeap; c: PCell; msg: typed) =
   when false:
     for i in 0..gch.decStack.len-1:
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()
diff --git a/lib/system/gc_ms.nim b/lib/system/gc_ms.nim
index ba8c569f7..e03140d05 100644
--- a/lib/system/gc_ms.nim
+++ b/lib/system/gc_ms.nim
@@ -221,18 +221,6 @@ when defined(nimGcRefLeak):
 
 include gc_common
 
-proc prepareDealloc(cell: PCell) =
-  if cell.typ.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](cell.typ.finalizer))(cellToUsr(cell))
-    dec(gch.recGcLock)
-  decTypeSize cell, cell.typ
-
 proc initGC() =
   when not defined(useNimRtl):
     gch.cycleThreshold = InitialThreshold