diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/system/gc.nim | 15 | ||||
-rw-r--r-- | lib/system/gc_common.nim | 32 | ||||
-rw-r--r-- | lib/system/gc_ms.nim | 12 |
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 |