summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorIco Doornekamp <ico@pruts.nl>2020-01-25 17:14:31 +0100
committerAndreas Rumpf <rumpf_a@web.de>2020-01-25 17:14:31 +0100
commit4f3dd33509070f0f50bbe5bbb6cbfc8a12b47b49 (patch)
treeadfb765ed9ea91be1c5ae8510b143c3bea7fe0ec
parent5124b2e575a0293c665026dd766700c03bc6a04f (diff)
downloadNim-4f3dd33509070f0f50bbe5bbb6cbfc8a12b47b49.tar.gz
Cleaned up mmdisp.nim, moved implementations into lib/system/mm/ (#13254)
-rw-r--r--lib/system/mm/boehm.nim136
-rw-r--r--lib/system/mm/go.nim152
-rw-r--r--lib/system/mm/malloc.nim80
-rw-r--r--lib/system/mm/none.nim44
-rw-r--r--lib/system/mmdisp.nim396
5 files changed, 416 insertions, 392 deletions
diff --git a/lib/system/mm/boehm.nim b/lib/system/mm/boehm.nim
new file mode 100644
index 000000000..d02d52b52
--- /dev/null
+++ b/lib/system/mm/boehm.nim
@@ -0,0 +1,136 @@
+
+proc boehmGCinit {.importc: "GC_init", boehmGC.}
+proc boehmGC_disable {.importc: "GC_disable", boehmGC.}
+proc boehmGC_enable {.importc: "GC_enable", boehmGC.}
+proc boehmGCincremental {.
+  importc: "GC_enable_incremental", boehmGC.}
+proc boehmGCfullCollect {.importc: "GC_gcollect", boehmGC.}
+proc boehmGC_set_all_interior_pointers(flag: cint) {.
+  importc: "GC_set_all_interior_pointers", boehmGC.}
+proc boehmAlloc(size: int): pointer {.importc: "GC_malloc", boehmGC.}
+proc boehmAllocAtomic(size: int): pointer {.
+  importc: "GC_malloc_atomic", boehmGC.}
+proc boehmRealloc(p: pointer, size: int): pointer {.
+  importc: "GC_realloc", boehmGC.}
+proc boehmDealloc(p: pointer) {.importc: "GC_free", boehmGC.}
+when hasThreadSupport:
+  proc boehmGC_allow_register_threads {.
+    importc: "GC_allow_register_threads", boehmGC.}
+
+proc boehmGetHeapSize: int {.importc: "GC_get_heap_size", boehmGC.}
+  ## Return the number of bytes in the heap.  Excludes collector private
+  ## data structures. Includes empty blocks and fragmentation loss.
+  ## Includes some pages that were allocated but never written.
+
+proc boehmGetFreeBytes: int {.importc: "GC_get_free_bytes", boehmGC.}
+  ## Return a lower bound on the number of free bytes in the heap.
+
+proc boehmGetBytesSinceGC: int {.importc: "GC_get_bytes_since_gc", boehmGC.}
+  ## Return the number of bytes allocated since the last collection.
+
+proc boehmGetTotalBytes: int {.importc: "GC_get_total_bytes", boehmGC.}
+  ## Return the total number of bytes allocated in this process.
+  ## Never decreases.
+
+proc boehmRegisterFinalizer(obj, ff, cd, off, ocd: pointer) {.importc: "GC_register_finalizer", boehmGC.}
+
+proc allocAtomic(size: int): pointer =
+  result = boehmAllocAtomic(size)
+  zeroMem(result, size)
+
+when not defined(useNimRtl):
+
+  proc allocImpl(size: Natural): pointer =
+    result = boehmAlloc(size)
+    if result == nil: raiseOutOfMem()
+  proc alloc0Impl(size: Natural): pointer =
+    result = alloc(size)
+  proc reallocImpl(p: pointer, newSize: Natural): pointer =
+    result = boehmRealloc(p, newSize)
+    if result == nil: raiseOutOfMem()
+  proc realloc0Impl(p: pointer, oldSize, newSize: Natural): pointer =
+    result = boehmRealloc(p, newSize)
+    if result == nil: raiseOutOfMem()
+    if newsize > oldsize:
+      zeroMem(cast[pointer](cast[int](result) + oldsize), newsize - oldsize)
+  proc deallocImpl(p: pointer) = boehmDealloc(p)
+
+  proc allocSharedImpl(size: Natural): pointer = allocImpl(size)
+  proc allocShared0Impl(size: Natural): pointer = alloc0Impl(size)
+  proc reallocSharedImpl(p: pointer, newsize: Natural): pointer = reallocImpl(p, newsize)
+  proc reallocShared0Impl(p: pointer, oldsize, newsize: Natural): pointer = realloc0Impl(p, oldsize, newsize)
+  proc deallocSharedImpl(p: pointer) = deallocImpl(p)
+
+  when hasThreadSupport:
+    proc getFreeSharedMem(): int =
+      boehmGetFreeBytes()
+    proc getTotalSharedMem(): int =
+      boehmGetHeapSize()
+    proc getOccupiedSharedMem(): int =
+      getTotalSharedMem() - getFreeSharedMem()
+
+  #boehmGCincremental()
+
+  proc GC_disable() = boehmGC_disable()
+  proc GC_enable() = boehmGC_enable()
+  proc GC_fullCollect() = boehmGCfullCollect()
+  proc GC_setStrategy(strategy: GC_Strategy) = discard
+  proc GC_enableMarkAndSweep() = discard
+  proc GC_disableMarkAndSweep() = discard
+  proc GC_getStatistics(): string = return ""
+
+  proc getOccupiedMem(): int = return boehmGetHeapSize()-boehmGetFreeBytes()
+  proc getFreeMem(): int = return boehmGetFreeBytes()
+  proc getTotalMem(): int = return boehmGetHeapSize()
+
+  proc nimGC_setStackBottom(theStackBottom: pointer) = discard
+
+proc initGC() =
+  when defined(boehmNoIntPtr):
+    # See #12286
+    boehmGC_set_all_interior_pointers(0)
+  boehmGCinit()
+  when hasThreadSupport:
+    boehmGC_allow_register_threads()
+
+proc boehmgc_finalizer(obj: pointer, typedFinalizer: (proc(x: pointer) {.cdecl.})) =
+  typedFinalizer(obj)
+
+proc newObj(typ: PNimType, size: int): pointer {.compilerproc.} =
+  if ntfNoRefs in typ.flags: result = allocAtomic(size)
+  else: result = alloc(size)
+  if typ.finalizer != nil:
+    boehmRegisterFinalizer(result, boehmgc_finalizer, typ.finalizer, nil, nil)
+proc newSeq(typ: PNimType, len: int): pointer {.compilerproc.} =
+  result = newObj(typ, addInt(mulInt(len, typ.base.size), GenericSeqSize))
+  cast[PGenericSeq](result).len = len
+  cast[PGenericSeq](result).reserved = len
+
+proc growObj(old: pointer, newsize: int): pointer =
+  result = realloc(old, newsize)
+
+proc nimGCref(p: pointer) {.compilerproc, inline.} = discard
+proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard
+
+proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
+  dest[] = src
+proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
+  dest[] = src
+proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline,
+  deprecated: "old compiler compat".} = asgnRef(dest, src)
+
+type
+  MemRegion = object
+
+proc alloc(r: var MemRegion, size: int): pointer =
+  result = boehmAlloc(size)
+  if result == nil: raiseOutOfMem()
+proc alloc0(r: var MemRegion, size: int): pointer =
+  result = alloc(size)
+  zeroMem(result, size)
+proc dealloc(r: var MemRegion, p: pointer) = boehmDealloc(p)
+proc deallocOsPages(r: var MemRegion) {.inline.} = discard
+proc deallocOsPages() {.inline.} = discard
+
+include "system/cellsets"
+
diff --git a/lib/system/mm/go.nim b/lib/system/mm/go.nim
new file mode 100644
index 000000000..8e8558bea
--- /dev/null
+++ b/lib/system/mm/go.nim
@@ -0,0 +1,152 @@
+
+when defined(windows):
+  const goLib = "libgo.dll"
+elif defined(macosx):
+  const goLib = "libgo.dylib"
+else:
+  const goLib = "libgo.so"
+
+proc initGC() = discard
+proc GC_disable() = discard
+proc GC_enable() = discard
+proc go_gc() {.importc: "go_gc", dynlib: goLib.}
+proc GC_fullCollect() = go_gc()
+proc GC_setStrategy(strategy: GC_Strategy) = discard
+proc GC_enableMarkAndSweep() = discard
+proc GC_disableMarkAndSweep() = discard
+
+const
+  goNumSizeClasses = 67
+
+type
+  goMStats = object
+    alloc: uint64          # bytes allocated and still in use
+    total_alloc: uint64    # bytes allocated (even if freed)
+    sys: uint64            # bytes obtained from system
+    nlookup: uint64        # number of pointer lookups
+    nmalloc: uint64        # number of mallocs
+    nfree: uint64          # number of frees
+    heap_objects: uint64   # total number of allocated objects
+    pause_total_ns: uint64 # cumulative nanoseconds in GC stop-the-world pauses since the program started
+    numgc: uint32          # number of completed GC cycles
+
+proc goMemStats(): goMStats {.importc: "go_mem_stats", dynlib: goLib.}
+proc goMalloc(size: uint): pointer {.importc: "go_malloc", dynlib: goLib.}
+proc goSetFinalizer(obj: pointer, f: pointer) {.importc: "set_finalizer", codegenDecl:"$1 $2$3 __asm__ (\"main.Set_finalizer\");\n$1 $2$3", dynlib: goLib.}
+proc writebarrierptr(dest: PPointer, src: pointer) {.importc: "writebarrierptr", codegenDecl:"$1 $2$3 __asm__ (\"main.Atomic_store_pointer\");\n$1 $2$3", dynlib: goLib.}
+
+proc `$`*(x: uint64): string {.noSideEffect, raises: [].}
+
+proc GC_getStatistics(): string =
+  var mstats = goMemStats()
+  result = "[GC] total allocated memory: " & $(mstats.total_alloc) & "\n" &
+           "[GC] total memory obtained from system: " & $(mstats.sys) & "\n" &
+           "[GC] occupied memory: " & $(mstats.alloc) & "\n" &
+           "[GC] number of pointer lookups: " & $(mstats.nlookup) & "\n" &
+           "[GC] number of mallocs: " & $(mstats.nmalloc) & "\n" &
+           "[GC] number of frees: " & $(mstats.nfree) & "\n" &
+           "[GC] heap objects: " & $(mstats.heap_objects) & "\n" &
+           "[GC] number of completed GC cycles: " & $(mstats.numgc) & "\n" &
+           "[GC] total GC pause time [ms]: " & $(mstats.pause_total_ns div 1000_000)
+
+proc getOccupiedMem(): int =
+  var mstats = goMemStats()
+  result = int(mstats.alloc)
+
+proc getFreeMem(): int =
+  var mstats = goMemStats()
+  result = int(mstats.sys - mstats.alloc)
+
+proc getTotalMem(): int =
+  var mstats = goMemStats()
+  result = int(mstats.sys)
+
+proc nimGC_setStackBottom(theStackBottom: pointer) = discard
+
+proc allocImpl(size: Natural): pointer =
+  result = goMalloc(size.uint)
+
+proc alloc0Impl(size: Natural): pointer =
+  result = goMalloc(size.uint)
+
+proc reallocImpl(p: pointer, newsize: Natural): pointer =
+  doAssert false, "not implemented"
+
+proc realloc0Impl(p: pointer, oldsize, newsize: Natural): pointer =
+  doAssert false, "not implemented"
+
+proc deallocImpl(p: pointer) =
+  discard
+
+proc allocSharedImpl(size: Natural): pointer = allocImpl(size)
+proc allocShared0Impl(size: Natural): pointer = alloc0Impl(size)
+proc reallocSharedImpl(p: pointer, newsize: Natural): pointer = reallocImpl(p, newsize)
+proc reallocShared0Impl(p: pointer, oldsize, newsize: Natural): pointer = realloc0Impl(p, oldsize, newsize)
+proc deallocSharedImpl(p: pointer) = deallocImpl(p)
+
+when hasThreadSupport:
+  proc getFreeSharedMem(): int = discard
+  proc getTotalSharedMem(): int = discard
+  proc getOccupiedSharedMem(): int = discard
+
+proc newObj(typ: PNimType, size: int): pointer {.compilerproc.} =
+  writebarrierptr(addr(result), goMalloc(size.uint))
+  if typ.finalizer != nil:
+    goSetFinalizer(result, typ.finalizer)
+
+proc newObjRC1(typ: PNimType, size: int): pointer {.compilerRtl.} =
+  writebarrierptr(addr(result), newObj(typ, size))
+
+proc newObjNoInit(typ: PNimType, size: int): pointer =
+  writebarrierptr(addr(result), newObj(typ, size))
+
+proc newSeq(typ: PNimType, len: int): pointer {.compilerproc.} =
+  writebarrierptr(addr(result), newObj(typ, len * typ.base.size + GenericSeqSize))
+  cast[PGenericSeq](result).len = len
+  cast[PGenericSeq](result).reserved = len
+  cast[PGenericSeq](result).elemSize = typ.base.size
+
+proc newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl.} =
+  writebarrierptr(addr(result), newSeq(typ, len))
+
+proc nimNewSeqOfCap(typ: PNimType, cap: int): pointer {.compilerproc.} =
+  result = newObj(typ, cap * typ.base.size + GenericSeqSize)
+  cast[PGenericSeq](result).len = 0
+  cast[PGenericSeq](result).reserved = cap
+  cast[PGenericSeq](result).elemSize = typ.base.size
+
+proc typedMemMove(dest: pointer, src: pointer, size: uint) {.importc: "typedmemmove", dynlib: goLib.}
+
+proc growObj(old: pointer, newsize: int): pointer =
+  # the Go GC doesn't have a realloc
+  var metadataOld = cast[PGenericSeq](old)
+  if metadataOld.elemSize == 0:
+    metadataOld.elemSize = 1
+  let oldsize = cast[PGenericSeq](old).len * cast[PGenericSeq](old).elemSize + GenericSeqSize
+  writebarrierptr(addr(result), goMalloc(newsize.uint))
+  typedMemMove(result, old, oldsize.uint)
+
+proc nimGCref(p: pointer) {.compilerproc, inline.} = discard
+proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard
+proc nimGCunrefNoCycle(p: pointer) {.compilerProc, inline.} = discard
+proc nimGCunrefRC1(p: pointer) {.compilerProc, inline.} = discard
+proc nimGCvisit(d: pointer, op: int) {.compilerRtl.} = discard
+
+proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
+  writebarrierptr(dest, src)
+proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
+  writebarrierptr(dest, src)
+proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline,
+  deprecated: "old compiler compat".} = asgnRef(dest, src)
+
+type
+  MemRegion = object
+
+proc alloc(r: var MemRegion, size: int): pointer =
+  result = alloc(size)
+proc alloc0(r: var MemRegion, size: int): pointer =
+  result = alloc0Impl(size)
+proc dealloc(r: var MemRegion, p: pointer) = dealloc(p)
+proc deallocOsPages(r: var MemRegion) {.inline.} = discard
+proc deallocOsPages() {.inline.} = discard
+
diff --git a/lib/system/mm/malloc.nim b/lib/system/mm/malloc.nim
new file mode 100644
index 000000000..27e32f87d
--- /dev/null
+++ b/lib/system/mm/malloc.nim
@@ -0,0 +1,80 @@
+
+proc allocImpl(size: Natural): pointer =
+  c_malloc(size.csize_t)
+
+proc alloc0Impl(size: Natural): pointer =
+  c_calloc(size.csize_t, 1)
+
+proc reallocImpl(p: pointer, newsize: Natural): pointer =
+  c_realloc(p, newSize.csize_t)
+
+proc realloc0Impl(p: pointer, oldsize, newsize: Natural): pointer =
+  result = realloc(p, newsize.csize_t)
+  if newsize > oldsize:
+    zeroMem(cast[pointer](cast[int](result) + oldsize), newsize - oldsize)
+
+proc deallocImpl(p: pointer) =
+  c_free(p)
+
+
+# The shared allocators map on the regular ones
+
+proc allocSharedImpl(size: Natural): pointer =
+  allocImpl(size)
+
+proc allocShared0Impl(size: Natural): pointer =
+  alloc0Impl(size)
+
+proc reallocSharedImpl(p: pointer, newsize: Natural): pointer =
+  reallocImpl(p, newsize)
+
+proc reallocShared0Impl(p: pointer, oldsize, newsize: Natural): pointer =
+  realloc0Impl(p, oldsize, newsize)
+
+proc deallocSharedImpl(p: pointer) = deallocImpl(p)
+
+
+# Empty stubs for the GC
+
+proc GC_disable() = discard
+proc GC_enable() = discard
+proc GC_fullCollect() = discard
+proc GC_setStrategy(strategy: GC_Strategy) = discard
+proc GC_enableMarkAndSweep() = discard
+proc GC_disableMarkAndSweep() = discard
+
+proc getOccupiedMem(): int = discard
+proc getFreeMem(): int = discard
+proc getTotalMem(): int = discard
+
+proc nimGC_setStackBottom(theStackBottom: pointer) = discard
+
+proc initGC() = discard
+
+proc newObjNoInit(typ: PNimType, size: int): pointer =
+  result = alloc(size)
+
+proc growObj(old: pointer, newsize: int): pointer =
+  result = realloc(old, newsize)
+
+proc nimGCref(p: pointer) {.compilerproc, inline.} = discard
+proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard
+
+proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
+  dest[] = src
+proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
+  dest[] = src
+proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline,
+  deprecated: "old compiler compat".} = asgnRef(dest, src)
+
+type
+  MemRegion = object
+
+proc alloc(r: var MemRegion, size: int): pointer =
+  result = alloc(size)
+proc alloc0Impl(r: var MemRegion, size: int): pointer =
+  result = alloc0Impl(size)
+proc dealloc(r: var MemRegion, p: pointer) = dealloc(p)
+proc deallocOsPages(r: var MemRegion) {.inline.} = discard
+proc deallocOsPages() {.inline.} = discard
+
diff --git a/lib/system/mm/none.nim b/lib/system/mm/none.nim
new file mode 100644
index 000000000..3572b062c
--- /dev/null
+++ b/lib/system/mm/none.nim
@@ -0,0 +1,44 @@
+
+when appType == "lib":
+  {.warning: "nogc in a library context may not work".}
+
+include "system/alloc"
+
+proc initGC() = discard
+proc GC_disable() = discard
+proc GC_enable() = discard
+proc GC_fullCollect() = discard
+proc GC_setStrategy(strategy: GC_Strategy) = discard
+proc GC_enableMarkAndSweep() = discard
+proc GC_disableMarkAndSweep() = discard
+proc GC_getStatistics(): string = return ""
+
+proc newObj(typ: PNimType, size: int): pointer {.compilerproc.} =
+  result = alloc0Impl(size)
+
+proc newObjNoInit(typ: PNimType, size: int): pointer =
+  result = alloc(size)
+
+proc newSeq(typ: PNimType, len: int): pointer {.compilerproc.} =
+  result = newObj(typ, addInt(mulInt(len, typ.base.size), GenericSeqSize))
+  cast[PGenericSeq](result).len = len
+  cast[PGenericSeq](result).reserved = len
+
+proc growObj(old: pointer, newsize: int): pointer =
+  result = realloc(old, newsize)
+
+proc nimGC_setStackBottom(theStackBottom: pointer) = discard
+proc nimGCref(p: pointer) {.compilerproc, inline.} = discard
+proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard
+
+proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
+  dest[] = src
+proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
+  dest[] = src
+proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline,
+  deprecated: "old compiler compat".} = asgnRef(dest, src)
+
+var allocator {.rtlThreadVar.}: MemRegion
+instantiateForRegion(allocator)
+
+include "system/cellsets"
diff --git a/lib/system/mmdisp.nim b/lib/system/mmdisp.nim
index 1f42f1aa5..d2d0d576f 100644
--- a/lib/system/mmdisp.nim
+++ b/lib/system/mmdisp.nim
@@ -66,404 +66,16 @@ proc raiseOutOfMem() {.noinline.} =
   quit(1)
 
 when defined(boehmgc):
-  proc boehmGCinit {.importc: "GC_init", boehmGC.}
-  proc boehmGC_disable {.importc: "GC_disable", boehmGC.}
-  proc boehmGC_enable {.importc: "GC_enable", boehmGC.}
-  proc boehmGCincremental {.
-    importc: "GC_enable_incremental", boehmGC.}
-  proc boehmGCfullCollect {.importc: "GC_gcollect", boehmGC.}
-  proc boehmGC_set_all_interior_pointers(flag: cint) {.
-    importc: "GC_set_all_interior_pointers", boehmGC.}
-  proc boehmAlloc(size: int): pointer {.importc: "GC_malloc", boehmGC.}
-  proc boehmAllocAtomic(size: int): pointer {.
-    importc: "GC_malloc_atomic", boehmGC.}
-  proc boehmRealloc(p: pointer, size: int): pointer {.
-    importc: "GC_realloc", boehmGC.}
-  proc boehmDealloc(p: pointer) {.importc: "GC_free", boehmGC.}
-  when hasThreadSupport:
-    proc boehmGC_allow_register_threads {.
-      importc: "GC_allow_register_threads", boehmGC.}
-
-  proc boehmGetHeapSize: int {.importc: "GC_get_heap_size", boehmGC.}
-    ## Return the number of bytes in the heap.  Excludes collector private
-    ## data structures. Includes empty blocks and fragmentation loss.
-    ## Includes some pages that were allocated but never written.
-
-  proc boehmGetFreeBytes: int {.importc: "GC_get_free_bytes", boehmGC.}
-    ## Return a lower bound on the number of free bytes in the heap.
-
-  proc boehmGetBytesSinceGC: int {.importc: "GC_get_bytes_since_gc", boehmGC.}
-    ## Return the number of bytes allocated since the last collection.
-
-  proc boehmGetTotalBytes: int {.importc: "GC_get_total_bytes", boehmGC.}
-    ## Return the total number of bytes allocated in this process.
-    ## Never decreases.
-
-  proc boehmRegisterFinalizer(obj, ff, cd, off, ocd: pointer) {.importc: "GC_register_finalizer", boehmGC.}
-
-  proc allocAtomic(size: int): pointer =
-    result = boehmAllocAtomic(size)
-    zeroMem(result, size)
-
-  when not defined(useNimRtl):
-
-    proc allocImpl(size: Natural): pointer =
-      result = boehmAlloc(size)
-      if result == nil: raiseOutOfMem()
-    proc alloc0Impl(size: Natural): pointer =
-      result = alloc(size)
-    proc reallocImpl(p: pointer, newSize: Natural): pointer =
-      result = boehmRealloc(p, newSize)
-      if result == nil: raiseOutOfMem()
-    proc realloc0Impl(p: pointer, oldSize, newSize: Natural): pointer =
-      result = boehmRealloc(p, newSize)
-      if result == nil: raiseOutOfMem()
-      if newsize > oldsize:
-        zeroMem(cast[pointer](cast[int](result) + oldsize), newsize - oldsize)
-    proc deallocImpl(p: pointer) = boehmDealloc(p)
-
-    proc allocSharedImpl(size: Natural): pointer = allocImpl(size)
-    proc allocShared0Impl(size: Natural): pointer = alloc0Impl(size)
-    proc reallocSharedImpl(p: pointer, newsize: Natural): pointer = reallocImpl(p, newsize)
-    proc reallocShared0Impl(p: pointer, oldsize, newsize: Natural): pointer = realloc0Impl(p, oldsize, newsize)
-    proc deallocSharedImpl(p: pointer) = deallocImpl(p)
-
-    when hasThreadSupport:
-      proc getFreeSharedMem(): int =
-        boehmGetFreeBytes()
-      proc getTotalSharedMem(): int =
-        boehmGetHeapSize()
-      proc getOccupiedSharedMem(): int =
-        getTotalSharedMem() - getFreeSharedMem()
-
-    #boehmGCincremental()
-
-    proc GC_disable() = boehmGC_disable()
-    proc GC_enable() = boehmGC_enable()
-    proc GC_fullCollect() = boehmGCfullCollect()
-    proc GC_setStrategy(strategy: GC_Strategy) = discard
-    proc GC_enableMarkAndSweep() = discard
-    proc GC_disableMarkAndSweep() = discard
-    proc GC_getStatistics(): string = return ""
-
-    proc getOccupiedMem(): int = return boehmGetHeapSize()-boehmGetFreeBytes()
-    proc getFreeMem(): int = return boehmGetFreeBytes()
-    proc getTotalMem(): int = return boehmGetHeapSize()
-
-    proc nimGC_setStackBottom(theStackBottom: pointer) = discard
-
-  proc initGC() =
-    when defined(boehmNoIntPtr):
-      # See #12286
-      boehmGC_set_all_interior_pointers(0)
-    boehmGCinit()
-    when hasThreadSupport:
-      boehmGC_allow_register_threads()
-
-  proc boehmgc_finalizer(obj: pointer, typedFinalizer: (proc(x: pointer) {.cdecl.})) =
-    typedFinalizer(obj)
-
-  proc newObj(typ: PNimType, size: int): pointer {.compilerproc.} =
-    if ntfNoRefs in typ.flags: result = allocAtomic(size)
-    else: result = alloc(size)
-    if typ.finalizer != nil:
-      boehmRegisterFinalizer(result, boehmgc_finalizer, typ.finalizer, nil, nil)
-  proc newSeq(typ: PNimType, len: int): pointer {.compilerproc.} =
-    result = newObj(typ, addInt(mulInt(len, typ.base.size), GenericSeqSize))
-    cast[PGenericSeq](result).len = len
-    cast[PGenericSeq](result).reserved = len
-
-  proc growObj(old: pointer, newsize: int): pointer =
-    result = realloc(old, newsize)
-
-  proc nimGCref(p: pointer) {.compilerproc, inline.} = discard
-  proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard
-
-  proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
-    dest[] = src
-  proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
-    dest[] = src
-  proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline,
-    deprecated: "old compiler compat".} = asgnRef(dest, src)
-
-  type
-    MemRegion = object
-
-  proc alloc(r: var MemRegion, size: int): pointer =
-    result = boehmAlloc(size)
-    if result == nil: raiseOutOfMem()
-  proc alloc0(r: var MemRegion, size: int): pointer =
-    result = alloc(size)
-    zeroMem(result, size)
-  proc dealloc(r: var MemRegion, p: pointer) = boehmDealloc(p)
-  proc deallocOsPages(r: var MemRegion) {.inline.} = discard
-  proc deallocOsPages() {.inline.} = discard
-
-  include "system/cellsets"
+  include system / mm / boehm
 
 elif defined(gogc):
-  when defined(windows):
-    const goLib = "libgo.dll"
-  elif defined(macosx):
-    const goLib = "libgo.dylib"
-  else:
-    const goLib = "libgo.so"
-
-  proc initGC() = discard
-  proc GC_disable() = discard
-  proc GC_enable() = discard
-  proc go_gc() {.importc: "go_gc", dynlib: goLib.}
-  proc GC_fullCollect() = go_gc()
-  proc GC_setStrategy(strategy: GC_Strategy) = discard
-  proc GC_enableMarkAndSweep() = discard
-  proc GC_disableMarkAndSweep() = discard
-
-  const
-    goNumSizeClasses = 67
-
-  type
-    goMStats = object
-      alloc: uint64          # bytes allocated and still in use
-      total_alloc: uint64    # bytes allocated (even if freed)
-      sys: uint64            # bytes obtained from system
-      nlookup: uint64        # number of pointer lookups
-      nmalloc: uint64        # number of mallocs
-      nfree: uint64          # number of frees
-      heap_objects: uint64   # total number of allocated objects
-      pause_total_ns: uint64 # cumulative nanoseconds in GC stop-the-world pauses since the program started
-      numgc: uint32          # number of completed GC cycles
-
-  proc goMemStats(): goMStats {.importc: "go_mem_stats", dynlib: goLib.}
-  proc goMalloc(size: uint): pointer {.importc: "go_malloc", dynlib: goLib.}
-  proc goSetFinalizer(obj: pointer, f: pointer) {.importc: "set_finalizer", codegenDecl:"$1 $2$3 __asm__ (\"main.Set_finalizer\");\n$1 $2$3", dynlib: goLib.}
-  proc writebarrierptr(dest: PPointer, src: pointer) {.importc: "writebarrierptr", codegenDecl:"$1 $2$3 __asm__ (\"main.Atomic_store_pointer\");\n$1 $2$3", dynlib: goLib.}
-
-  proc `$`*(x: uint64): string {.noSideEffect, raises: [].}
-
-  proc GC_getStatistics(): string =
-    var mstats = goMemStats()
-    result = "[GC] total allocated memory: " & $(mstats.total_alloc) & "\n" &
-             "[GC] total memory obtained from system: " & $(mstats.sys) & "\n" &
-             "[GC] occupied memory: " & $(mstats.alloc) & "\n" &
-             "[GC] number of pointer lookups: " & $(mstats.nlookup) & "\n" &
-             "[GC] number of mallocs: " & $(mstats.nmalloc) & "\n" &
-             "[GC] number of frees: " & $(mstats.nfree) & "\n" &
-             "[GC] heap objects: " & $(mstats.heap_objects) & "\n" &
-             "[GC] number of completed GC cycles: " & $(mstats.numgc) & "\n" &
-             "[GC] total GC pause time [ms]: " & $(mstats.pause_total_ns div 1000_000)
-
-  proc getOccupiedMem(): int =
-    var mstats = goMemStats()
-    result = int(mstats.alloc)
-
-  proc getFreeMem(): int =
-    var mstats = goMemStats()
-    result = int(mstats.sys - mstats.alloc)
-
-  proc getTotalMem(): int =
-    var mstats = goMemStats()
-    result = int(mstats.sys)
-
-  proc nimGC_setStackBottom(theStackBottom: pointer) = discard
-
-  proc allocImpl(size: Natural): pointer =
-    result = goMalloc(size.uint)
-
-  proc alloc0Impl(size: Natural): pointer =
-    result = goMalloc(size.uint)
-
-  proc reallocImpl(p: pointer, newsize: Natural): pointer =
-    doAssert false, "not implemented"
-
-  proc realloc0Impl(p: pointer, oldsize, newsize: Natural): pointer =
-    doAssert false, "not implemented"
-
-  proc deallocImpl(p: pointer) =
-    discard
-
-  proc allocSharedImpl(size: Natural): pointer = allocImpl(size)
-  proc allocShared0Impl(size: Natural): pointer = alloc0Impl(size)
-  proc reallocSharedImpl(p: pointer, newsize: Natural): pointer = reallocImpl(p, newsize)
-  proc reallocShared0Impl(p: pointer, oldsize, newsize: Natural): pointer = realloc0Impl(p, oldsize, newsize)
-  proc deallocSharedImpl(p: pointer) = deallocImpl(p)
-
-  when hasThreadSupport:
-    proc getFreeSharedMem(): int = discard
-    proc getTotalSharedMem(): int = discard
-    proc getOccupiedSharedMem(): int = discard
-
-  proc newObj(typ: PNimType, size: int): pointer {.compilerproc.} =
-    writebarrierptr(addr(result), goMalloc(size.uint))
-    if typ.finalizer != nil:
-      goSetFinalizer(result, typ.finalizer)
-
-  proc newObjRC1(typ: PNimType, size: int): pointer {.compilerRtl.} =
-    writebarrierptr(addr(result), newObj(typ, size))
-
-  proc newObjNoInit(typ: PNimType, size: int): pointer =
-    writebarrierptr(addr(result), newObj(typ, size))
-
-  proc newSeq(typ: PNimType, len: int): pointer {.compilerproc.} =
-    writebarrierptr(addr(result), newObj(typ, len * typ.base.size + GenericSeqSize))
-    cast[PGenericSeq](result).len = len
-    cast[PGenericSeq](result).reserved = len
-    cast[PGenericSeq](result).elemSize = typ.base.size
-
-  proc newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl.} =
-    writebarrierptr(addr(result), newSeq(typ, len))
-
-  proc nimNewSeqOfCap(typ: PNimType, cap: int): pointer {.compilerproc.} =
-    result = newObj(typ, cap * typ.base.size + GenericSeqSize)
-    cast[PGenericSeq](result).len = 0
-    cast[PGenericSeq](result).reserved = cap
-    cast[PGenericSeq](result).elemSize = typ.base.size
-
-  proc typedMemMove(dest: pointer, src: pointer, size: uint) {.importc: "typedmemmove", dynlib: goLib.}
-
-  proc growObj(old: pointer, newsize: int): pointer =
-    # the Go GC doesn't have a realloc
-    var metadataOld = cast[PGenericSeq](old)
-    if metadataOld.elemSize == 0:
-      metadataOld.elemSize = 1
-    let oldsize = cast[PGenericSeq](old).len * cast[PGenericSeq](old).elemSize + GenericSeqSize
-    writebarrierptr(addr(result), goMalloc(newsize.uint))
-    typedMemMove(result, old, oldsize.uint)
-
-  proc nimGCref(p: pointer) {.compilerproc, inline.} = discard
-  proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard
-  proc nimGCunrefNoCycle(p: pointer) {.compilerProc, inline.} = discard
-  proc nimGCunrefRC1(p: pointer) {.compilerProc, inline.} = discard
-  proc nimGCvisit(d: pointer, op: int) {.compilerRtl.} = discard
-
-  proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
-    writebarrierptr(dest, src)
-  proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
-    writebarrierptr(dest, src)
-  proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline,
-    deprecated: "old compiler compat".} = asgnRef(dest, src)
-
-  type
-    MemRegion = object
-
-  proc alloc(r: var MemRegion, size: int): pointer =
-    result = alloc(size)
-  proc alloc0(r: var MemRegion, size: int): pointer =
-    result = alloc0Impl(size)
-  proc dealloc(r: var MemRegion, p: pointer) = dealloc(p)
-  proc deallocOsPages(r: var MemRegion) {.inline.} = discard
-  proc deallocOsPages() {.inline.} = discard
+  include system / mm / go
 
 elif (defined(nogc) or defined(gcDestructors)) and defined(useMalloc):
-
-  when not defined(useNimRtl):
-
-    proc allocImpl(size: Natural): pointer = c_malloc(size.csize_t)
-    proc alloc0Impl(size: Natural): pointer = c_calloc(size.csize_t, 1)
-    proc reallocImpl(p: pointer, newsize: Natural): pointer = c_realloc(p, newSize.csize_t)
-    proc realloc0Impl(p: pointer, oldsize, newsize: Natural): pointer =
-      result = realloc(p, newsize.csize_t)
-      if newsize > oldsize:
-        zeroMem(cast[pointer](cast[int](result) + oldsize), newsize - oldsize)
-    proc deallocImpl(p: pointer) = c_free(p)
-
-    proc allocSharedImpl(size: Natural): pointer = allocImpl(size)
-    proc allocShared0Impl(size: Natural): pointer = alloc0Impl(size)
-    proc reallocSharedImpl(p: pointer, newsize: Natural): pointer = reallocImpl(p, newsize)
-    proc reallocShared0Impl(p: pointer, oldsize, newsize: Natural): pointer = realloc0Impl(p, oldsize, newsize)
-    proc deallocSharedImpl(p: pointer) = deallocImpl(p)
-
-    proc GC_disable() = discard
-    proc GC_enable() = discard
-    proc GC_fullCollect() = discard
-    proc GC_setStrategy(strategy: GC_Strategy) = discard
-    proc GC_enableMarkAndSweep() = discard
-    proc GC_disableMarkAndSweep() = discard
-
-    proc getOccupiedMem(): int = discard
-    proc getFreeMem(): int = discard
-    proc getTotalMem(): int = discard
-
-    proc nimGC_setStackBottom(theStackBottom: pointer) = discard
-
-  proc initGC() = discard
-
-  proc newObjNoInit(typ: PNimType, size: int): pointer =
-    result = alloc(size)
-
-  proc growObj(old: pointer, newsize: int): pointer =
-    result = realloc(old, newsize)
-
-  proc nimGCref(p: pointer) {.compilerproc, inline.} = discard
-  proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard
-
-  proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
-    dest[] = src
-  proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
-    dest[] = src
-  proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline,
-    deprecated: "old compiler compat".} = asgnRef(dest, src)
-
-  type
-    MemRegion = object
-
-  proc alloc(r: var MemRegion, size: int): pointer =
-    result = alloc(size)
-  proc alloc0Impl(r: var MemRegion, size: int): pointer =
-    result = alloc0Impl(size)
-  proc dealloc(r: var MemRegion, p: pointer) = dealloc(p)
-  proc deallocOsPages(r: var MemRegion) {.inline.} = discard
-  proc deallocOsPages() {.inline.} = discard
+  include system / mm / malloc
 
 elif defined(nogc):
-  # Even though we don't want the GC, we cannot simply use C's memory manager
-  # because Nim's runtime wants ``realloc`` to zero out the additional
-  # space which C's ``realloc`` does not. And we cannot get the old size of an
-  # object, because C does not support this operation... Even though every
-  # possible implementation has to have a way to determine the object's size.
-  # C just sucks.
-  when appType == "lib":
-    {.warning: "nogc in a library context may not work".}
-
-  include "system/alloc"
-
-  proc initGC() = discard
-  proc GC_disable() = discard
-  proc GC_enable() = discard
-  proc GC_fullCollect() = discard
-  proc GC_setStrategy(strategy: GC_Strategy) = discard
-  proc GC_enableMarkAndSweep() = discard
-  proc GC_disableMarkAndSweep() = discard
-  proc GC_getStatistics(): string = return ""
-
-  proc newObj(typ: PNimType, size: int): pointer {.compilerproc.} =
-    result = alloc0Impl(size)
-
-  proc newObjNoInit(typ: PNimType, size: int): pointer =
-    result = alloc(size)
-
-  proc newSeq(typ: PNimType, len: int): pointer {.compilerproc.} =
-    result = newObj(typ, addInt(mulInt(len, typ.base.size), GenericSeqSize))
-    cast[PGenericSeq](result).len = len
-    cast[PGenericSeq](result).reserved = len
-
-  proc growObj(old: pointer, newsize: int): pointer =
-    result = realloc(old, newsize)
-
-  proc nimGC_setStackBottom(theStackBottom: pointer) = discard
-  proc nimGCref(p: pointer) {.compilerproc, inline.} = discard
-  proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard
-
-  proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
-    dest[] = src
-  proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
-    dest[] = src
-  proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline,
-    deprecated: "old compiler compat".} = asgnRef(dest, src)
-
-  var allocator {.rtlThreadVar.}: MemRegion
-  instantiateForRegion(allocator)
-
-  include "system/cellsets"
+  include system / mm / none
 
 else:
   when not defined(gcRegions):