diff --git a/lib/system/gc.nim b/lib/system/gc.nim index 2cef2b636a..87a07fae98 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 cd03d2a546..220331e964 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 ba8c569f79..e03140d05f 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