summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ccgexprs.nim8
-rw-r--r--compiler/ccgstmts.nim1
-rw-r--r--compiler/ccgtypes.nim4
-rw-r--r--compiler/liftdestructors.nim39
-rw-r--r--lib/core/allocators.nim2
-rw-r--r--lib/core/runtime_v2.nim18
-rw-r--r--lib/core/seqs.nim20
-rw-r--r--lib/core/strs.nim38
-rw-r--r--lib/system.nim68
-rw-r--r--lib/system/alloc.nim4
-rw-r--r--lib/system/ansi_c.nim7
-rw-r--r--lib/system/excpt.nim7
-rw-r--r--lib/system/gc_common.nim1
-rw-r--r--lib/system/mmdisp.nim3
-rw-r--r--lib/system/threads.nim2
15 files changed, 112 insertions, 110 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index e080ca746..7de5e5606 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -1956,14 +1956,14 @@ proc genDestroy(p: BProc; n: PNode) =
     of tyString:
       var a: TLoc
       initLocExpr(p, n[1].skipAddr, a)
-      linefmt(p, cpsStmts, "if ($1.len && $1.region) {$n" &
-        " $1.region->dealloc($1.region, $1.p, $1.p->cap + 1 + sizeof(NI) + sizeof(void*)); }$n",
+      linefmt(p, cpsStmts, "if ($1.len && $1.p->allocator) {$n" &
+        " $1.p->allocator->dealloc($1.p->allocator, $1.p, $1.p->cap + 1 + sizeof(NI) + sizeof(void*)); }$n",
         [rdLoc(a)])
     of tySequence:
       var a: TLoc
       initLocExpr(p, n[1].skipAddr, a)
-      linefmt(p, cpsStmts, "if ($1.len && $1.region) {$n" &
-        " $1.region->dealloc($1.region, $1.p, ($1.p->cap * sizeof($2)) + sizeof(NI) + sizeof(void*)); }$n",
+      linefmt(p, cpsStmts, "if ($1.len && $1.p->allocator) {$n" &
+        " $1.p->allocator->dealloc($1.p->allocator, $1.p, ($1.p->cap * sizeof($2)) + sizeof(NI) + sizeof(void*)); }$n",
         [rdLoc(a), getTypeDesc(p.module, t.lastSon)])
     else: discard "nothing to do"
   else:
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim
index e2790f4f6..1e6e04458 100644
--- a/compiler/ccgstmts.nim
+++ b/compiler/ccgstmts.nim
@@ -17,6 +17,7 @@ const
 
 proc getTraverseProc(p: BProc, v: Psym): Rope =
   if p.config.selectedGC in {gcMarkAndSweep, gcDestructors, gcV2, gcRefc} and
+      optNimV2 notin p.config.globalOptions and
       containsGarbageCollectedRef(v.loc.t):
     # we register a specialized marked proc here; this has the advantage
     # that it works out of the box for thread local storage then :-)
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index ed051170f..6b4e9602b 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -740,7 +740,7 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
                  "  #TGenericSeq Sup;$n"
         if m.config.selectedGC == gcDestructors:
           appcg(m, m.s[cfsTypes],
-            "typedef struct{ NI cap;void* allocator;$1 data[SEQ_DECL_SIZE];}$2_Content;$n" &
+            "typedef struct{ NI cap;#AllocatorObj* allocator;$1 data[SEQ_DECL_SIZE];}$2_Content;$n" &
             "struct $2 {$n" &
             "  NI len; $2_Content* p;$n" &
             "};$n", [getTypeDescAux(m, t.sons[0], check), result])
@@ -1254,7 +1254,7 @@ proc genObjectInfoV2(m: BModule, t, origType: PType, name: Rope; info: TLineInfo
     d = t.destructor.loc.r
   else:
     d = rope("NIM_NIL")
-
+  addf(m.s[cfsVars], "TNimType $1;$n", [name])
   addf(m.s[cfsTypeInit3], "$1.destructor = $2; $1.size = sizeof($3); $1.name = $4;$n", [
     name, d, getTypeDesc(m, t), genTypeInfo2Name(m, t)])
 
diff --git a/compiler/liftdestructors.nim b/compiler/liftdestructors.nim
index aea244a78..046428795 100644
--- a/compiler/liftdestructors.nim
+++ b/compiler/liftdestructors.nim
@@ -141,22 +141,19 @@ proc considerAsgnOrSink(c: var TLiftCtx; t: PType; body, x, y: PNode;
     result = true
 
 proc addDestructorCall(c: var TLiftCtx; t: PType; body, x: PNode): bool =
-  let op = t.destructor
+  var op = t.destructor
+  if op == nil and useNoGc(c, t):
+    op = liftBody(c.graph, t, attachedDestructor, c.info)
+    doAssert op != nil
+
   if op != nil:
     markUsed(c.graph.config, c.info, op, c.graph.usageSym)
     onUse(c.info, op)
     body.add destructorCall(c.graph, op, x)
     result = true
   elif useNoGc(c, t):
-    if sameType(t, c.asgnForType) and c.kind == attachedDestructor:
-      let op = c.fn
-      markUsed(c.graph.config, c.info, op, c.graph.usageSym)
-      onUse(c.info, op)
-      body.add destructorCall(c.graph, op, x)
-      result = true
-    else:
-      internalError(c.graph.config, c.info,
-        "type-bound operator could not be resolved")
+    internalError(c.graph.config, c.info,
+      "type-bound operator could not be resolved")
 
 proc considerOverloadedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
   case c.kind
@@ -479,19 +476,27 @@ proc liftBody(g: ModuleGraph; typ: PType; kind: TTypeAttachedOp;
   if kind != attachedDestructor:
     result.typ.addParam src
 
-  liftBodyAux(a, typ, body, newSymNode(dest).newDeref, newSymNode(src))
-  # recursion is handled explicitly, do not register the type based operation
-  # before 'liftBodyAux':
-  if g.config.selectedGC == gcDestructors and
-      typ.kind in {tySequence, tyString} and body.len == 0:
-    discard "do not cache it yet"
-  else:
+  if optNimV2 in g.config.globalOptions:
     case kind
     of attachedAsgn: typ.assignment = result
     of attachedSink: typ.sink = result
     of attachedDeepCopy: typ.deepCopy = result
     of attachedDestructor: typ.destructor = result
 
+  liftBodyAux(a, typ, body, newSymNode(dest).newDeref, newSymNode(src))
+  if optNimV2 notin g.config.globalOptions:
+    # recursion is handled explicitly, do not register the type based operation
+    # before 'liftBodyAux':
+    if g.config.selectedGC == gcDestructors and
+        typ.kind in {tySequence, tyString} and body.len == 0:
+      discard "do not cache it yet"
+    else:
+      case kind
+      of attachedAsgn: typ.assignment = result
+      of attachedSink: typ.sink = result
+      of attachedDeepCopy: typ.deepCopy = result
+      of attachedDestructor: typ.destructor = result
+
   var n = newNodeI(nkProcDef, info, bodyPos+1)
   for i in 0 ..< n.len: n.sons[i] = newNodeI(nkEmpty, info)
   n.sons[namePos] = newSymNode(result)
diff --git a/lib/core/allocators.nim b/lib/core/allocators.nim
index 001caac05..984e83690 100644
--- a/lib/core/allocators.nim
+++ b/lib/core/allocators.nim
@@ -12,7 +12,7 @@ type
     ThreadLocal ## the allocator is thread local only.
     ZerosMem    ## the allocator always zeros the memory on an allocation
   Allocator* = ptr AllocatorObj
-  AllocatorObj* {.inheritable.} = object
+  AllocatorObj* {.inheritable, compilerproc.} = object
     alloc*: proc (a: Allocator; size: int; alignment: int = 8): pointer {.nimcall, raises: [], tags: [].}
     dealloc*: proc (a: Allocator; p: pointer; size: int) {.nimcall, raises: [], tags: [].}
     realloc*: proc (a: Allocator; p: pointer; oldSize, newSize: int): pointer {.nimcall, raises: [], tags: [].}
diff --git a/lib/core/runtime_v2.nim b/lib/core/runtime_v2.nim
index 8a9068c37..4367954d1 100644
--- a/lib/core/runtime_v2.nim
+++ b/lib/core/runtime_v2.nim
@@ -38,15 +38,6 @@ type
             # we could remove it in non-debug builds but this seems
             # unwise.
 
-proc isObj(obj: PNimType, subclass: cstring): bool {.compilerproc.} =
-  proc strstr(s, sub: cstring): cstring {.header: "<string.h>", importc.}
-
-  result = strstr(obj.name, subclass) != nil
-
-proc chckObj(obj: PNimType, subclass: cstring) {.compilerproc.} =
-  # checks if obj is of type subclass:
-  if not isObj(obj, subclass): sysFatal(ObjectConversionError, "invalid object conversion")
-
 template `+!`(p: pointer, s: int): pointer =
   cast[pointer](cast[int](p) +% s)
 
@@ -76,3 +67,12 @@ proc nimDestroyAndDispose(p: pointer) {.compilerRtl.} =
   let d = cast[ptr PNimType](p)[].destructor
   if d != nil: d(p)
   nimRawDispose(p)
+
+proc isObj(obj: PNimType, subclass: cstring): bool {.compilerproc.} =
+  proc strstr(s, sub: cstring): cstring {.header: "<string.h>", importc.}
+
+  result = strstr(obj.name, subclass) != nil
+
+proc chckObj(obj: PNimType, subclass: cstring) {.compilerproc.} =
+  # checks if obj is of type subclass:
+  if not isObj(obj, subclass): sysFatal(ObjectConversionError, "invalid object conversion")
diff --git a/lib/core/seqs.nim b/lib/core/seqs.nim
index 08c10962b..4a21515b7 100644
--- a/lib/core/seqs.nim
+++ b/lib/core/seqs.nim
@@ -17,7 +17,7 @@ proc supportsCopyMem(t: typedesc): bool {.magic: "TypeTrait".}
 type
   NimSeqPayload[T] = object
     cap: int
-    region: Allocator
+    allocator: Allocator
     data: UncheckedArray[T]
 
   NimSeqV2*[T] = object
@@ -52,8 +52,8 @@ when not defined(nimV2):
       mixin `=destroy`
       when not supportsCopyMem(T):
         for i in 0..<x.len: `=destroy`(p.data[i])
-      if p.region != nil:
-        p.region.dealloc(p.region, p, payloadSize(p.cap))
+      if p.allocator != nil:
+        p.allocator.dealloc(p.allocator, p, payloadSize(p.cap))
       x.p = nil
       x.len = 0
 
@@ -87,15 +87,15 @@ when not defined(nimV2):
 type
   PayloadBase = object
     cap: int
-    region: Allocator
+    allocator: Allocator
 
 proc newSeqPayload(cap, elemSize: int): pointer {.compilerRtl, raises: [].} =
   # we have to use type erasure here as Nim does not support generic
   # compilerProcs. Oh well, this will all be inlined anyway.
   if cap > 0:
-    let region = getLocalAllocator()
-    var p = cast[ptr PayloadBase](region.alloc(region, cap * elemSize + sizeof(int) + sizeof(Allocator)))
-    p.region = region
+    let allocator = getLocalAllocator()
+    var p = cast[ptr PayloadBase](allocator.alloc(allocator, cap * elemSize + sizeof(int) + sizeof(Allocator)))
+    p.allocator = allocator
     p.cap = cap
     result = p
   else:
@@ -112,12 +112,12 @@ proc prepareSeqAdd(len: int; p: pointer; addlen, elemSize: int): pointer {.
       # Note: this means we cannot support things that have internal pointers as
       # they get reallocated here. This needs to be documented clearly.
       var p = cast[ptr PayloadBase](p)
-      let region = if p.region == nil: getLocalAllocator() else: p.region
+      let allocator = if p.allocator == nil: getLocalAllocator() else: p.allocator
       let cap = max(resize(p.cap), len+addlen)
-      var q = cast[ptr PayloadBase](region.realloc(region, p,
+      var q = cast[ptr PayloadBase](allocator.realloc(allocator, p,
         sizeof(int) + sizeof(Allocator) + elemSize * p.cap,
         sizeof(int) + sizeof(Allocator) + elemSize * cap))
-      q.region = region
+      q.allocator = allocator
       q.cap = cap
       result = q
 
diff --git a/lib/core/strs.nim b/lib/core/strs.nim
index 540765de3..5c291e411 100644
--- a/lib/core/strs.nim
+++ b/lib/core/strs.nim
@@ -28,7 +28,7 @@ import allocators
 type
   NimStrPayload {.core.} = object
     cap: int
-    region: Allocator
+    allocator: Allocator
     data: UncheckedArray[char]
 
   NimStringV2 {.core.} = object
@@ -37,7 +37,7 @@ type
 
 const nimStrVersion {.core.} = 2
 
-template isLiteral(s): bool = s.p == nil or s.p.region == nil
+template isLiteral(s): bool = s.p == nil or s.p.allocator == nil
 
 template contentSize(cap): int = cap + 1 + sizeof(int) + sizeof(Allocator)
 
@@ -45,7 +45,7 @@ when not defined(nimV2):
 
   template frees(s) =
     if not isLiteral(s):
-      s.p.region.dealloc(s.p.region, s.p, contentSize(s.p.cap))
+      s.p.allocator.dealloc(s.p.allocator, s.p, contentSize(s.p.cap))
 
   proc `=destroy`(s: var string) =
     var a = cast[ptr NimStringV2](addr s)
@@ -72,12 +72,12 @@ when not defined(nimV2):
       # we can shallow copy literals:
       a.p = b.p
     else:
-      let region = if a.p != nil and a.p.region != nil: a.p.region else: getLocalAllocator()
+      let allocator = if a.p != nil and a.p.allocator != nil: a.p.allocator else: getLocalAllocator()
       # we have to allocate the 'cap' here, consider
       # 'let y = newStringOfCap(); var x = y'
       # on the other hand... These get turned into moves now.
-      a.p = cast[ptr NimStrPayload](region.alloc(region, contentSize(b.len)))
-      a.p.region = region
+      a.p = cast[ptr NimStrPayload](allocator.alloc(allocator, contentSize(b.len)))
+      a.p.allocator = allocator
       a.p.cap = b.len
       copyMem(unsafeAddr a.p.data[0], unsafeAddr b.p.data[0], b.len+1)
 
@@ -90,16 +90,16 @@ proc prepareAdd(s: var NimStringV2; addlen: int) {.compilerRtl.} =
   if isLiteral(s):
     let oldP = s.p
     # can't mutate a literal, so we need a fresh copy here:
-    let region = getLocalAllocator()
-    s.p = cast[ptr NimStrPayload](region.alloc(region, contentSize(s.len + addlen)))
-    s.p.region = region
+    let allocator = getLocalAllocator()
+    s.p = cast[ptr NimStrPayload](allocator.alloc(allocator, contentSize(s.len + addlen)))
+    s.p.allocator = allocator
     s.p.cap = s.len + addlen
     if s.len > 0:
       # we are about to append, so there is no need to copy the \0 terminator:
       copyMem(unsafeAddr s.p.data[0], unsafeAddr oldP.data[0], s.len)
   elif s.len + addlen > s.p.cap:
     let cap = max(s.len + addlen, resize(s.p.cap))
-    s.p = cast[ptr NimStrPayload](s.p.region.realloc(s.p.region, s.p,
+    s.p = cast[ptr NimStrPayload](s.p.allocator.realloc(s.p.allocator, s.p,
       oldSize = contentSize(s.p.cap),
       newSize = contentSize(cap)))
     s.p.cap = cap
@@ -114,9 +114,9 @@ proc toNimStr(str: cstring, len: int): NimStringV2 {.compilerProc.} =
   if len <= 0:
     result = NimStringV2(len: 0, p: nil)
   else:
-    let region = getLocalAllocator()
-    var p = cast[ptr NimStrPayload](region.alloc(region, contentSize(len)))
-    p.region = region
+    let allocator = getLocalAllocator()
+    var p = cast[ptr NimStrPayload](allocator.alloc(allocator, contentSize(len)))
+    p.allocator = allocator
     p.cap = len
     if len > 0:
       # we are about to append, so there is no need to copy the \0 terminator:
@@ -147,9 +147,9 @@ proc rawNewString(space: int): NimStringV2 {.compilerProc.} =
   if space <= 0:
     result = NimStringV2(len: 0, p: nil)
   else:
-    let region = getLocalAllocator()
-    var p = cast[ptr NimStrPayload](region.alloc(region, contentSize(space)))
-    p.region = region
+    let allocator = getLocalAllocator()
+    var p = cast[ptr NimStrPayload](allocator.alloc(allocator, contentSize(space)))
+    p.allocator = allocator
     p.cap = space
     result = NimStringV2(len: 0, p: p)
 
@@ -157,9 +157,9 @@ proc mnewString(len: int): NimStringV2 {.compilerProc.} =
   if len <= 0:
     result = NimStringV2(len: 0, p: nil)
   else:
-    let region = getLocalAllocator()
-    var p = cast[ptr NimStrPayload](region.alloc(region, contentSize(len)))
-    p.region = region
+    let allocator = getLocalAllocator()
+    var p = cast[ptr NimStrPayload](allocator.alloc(allocator, contentSize(len)))
+    p.allocator = allocator
     p.cap = len
     result = NimStringV2(len: len, p: p)
 
diff --git a/lib/system.nim b/lib/system.nim
index 9e32cc971..090c6359c 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -679,7 +679,8 @@ when not defined(JS) and not defined(nimscript):
   when not defined(gcDestructors):
     template space(s: PGenericSeq): int {.dirty.} =
       s.reserved and not (seqShallowFlag or strlitFlag)
-  include "system/hti"
+  when not defined(nimV2):
+    include "system/hti"
 
 type
   byte* = uint8 ## This is an alias for ``uint8``, that is an unsigned
@@ -2925,6 +2926,14 @@ proc compiles*(x: untyped): bool {.magic: "Compiles", noSideEffect, compileTime.
   ##     echo "'+' for integers is available"
   discard
 
+when not defined(js) and not defined(nimscript):
+  include "system/ansi_c"
+
+when not declared(sysFatal):
+  include "system/fatal"
+
+when defined(nimV2) and not defined(nimscript):
+  include core/runtime_v2
 
 import system/assertions
 export assertions
@@ -2995,7 +3004,7 @@ when not defined(nimscript) and hasAlloc:
       gcOptimizeTime,    ## optimize for speed
       gcOptimizeSpace    ## optimize for memory footprint
 
-  when not defined(JS):
+  when not defined(JS) and not defined(nimV2):
     proc GC_disable*() {.rtl, inl, benign.}
       ## Disables the GC. If called `n` times, `n` calls to `GC_enable`
       ## are needed to reactivate the GC.
@@ -3242,12 +3251,6 @@ when hostOS == "standalone":
     if s == nil or s.len == 0: result = cstring""
     else: result = cstring(addr s.data)
 
-when not defined(js) and not defined(nimscript):
-  include "system/ansi_c"
-
-when not declared(sysFatal):
-  include "system/fatal"
-
 proc getTypeInfo*[T](x: T): pointer {.magic: "GetTypeInfo", benign.}
   ## Get type information for `x`.
   ##
@@ -3364,11 +3367,8 @@ when not defined(JS): #and not defined(nimscript):
   {.push stack_trace: off, profiler:off.}
 
   when hasAlloc:
-    when not defined(gcRegions):
+    when not defined(gcRegions) and not defined(nimV2):
       proc initGC() {.gcsafe.}
-    when not defined(boehmgc) and not defined(useMalloc) and
-        not defined(gogc) and not defined(gcRegions):
-      proc initAllocator() {.inline.}
 
     proc initStackBottom() {.inline, compilerproc.} =
       # WARNING: This is very fragile! An array size of 8 does not work on my
@@ -3547,26 +3547,27 @@ when not defined(JS): #and not defined(nimscript):
     else:
       const GenericSeqSize = (2 * sizeof(int))
 
-    proc getDiscriminant(aa: pointer, n: ptr TNimNode): int =
-      sysAssert(n.kind == nkCase, "getDiscriminant: node != nkCase")
-      var d: int
-      var a = cast[ByteAddress](aa)
-      case n.typ.size
-      of 1: d = ze(cast[ptr int8](a +% n.offset)[])
-      of 2: d = ze(cast[ptr int16](a +% n.offset)[])
-      of 4: d = int(cast[ptr int32](a +% n.offset)[])
-      of 8: d = int(cast[ptr int64](a +% n.offset)[])
-      else: sysAssert(false, "getDiscriminant: invalid n.typ.size")
-      return d
-
-    proc selectBranch(aa: pointer, n: ptr TNimNode): ptr TNimNode =
-      var discr = getDiscriminant(aa, n)
-      if discr <% n.len:
-        result = n.sons[discr]
-        if result == nil: result = n.sons[n.len]
-        # n.sons[n.len] contains the ``else`` part (but may be nil)
-      else:
-        result = n.sons[n.len]
+    when not defined(nimV2):
+      proc getDiscriminant(aa: pointer, n: ptr TNimNode): int =
+        sysAssert(n.kind == nkCase, "getDiscriminant: node != nkCase")
+        var d: int
+        var a = cast[ByteAddress](aa)
+        case n.typ.size
+        of 1: d = ze(cast[ptr int8](a +% n.offset)[])
+        of 2: d = ze(cast[ptr int16](a +% n.offset)[])
+        of 4: d = int(cast[ptr int32](a +% n.offset)[])
+        of 8: d = int(cast[ptr int64](a +% n.offset)[])
+        else: sysAssert(false, "getDiscriminant: invalid n.typ.size")
+        return d
+
+      proc selectBranch(aa: pointer, n: ptr TNimNode): ptr TNimNode =
+        var discr = getDiscriminant(aa, n)
+        if discr <% n.len:
+          result = n.sons[discr]
+          if result == nil: result = n.sons[n.len]
+          # n.sons[n.len] contains the ``else`` part (but may be nil)
+        else:
+          result = n.sons[n.len]
 
     {.push profiler:off.}
     when hasAlloc: include "system/mmdisp"
@@ -3584,7 +3585,8 @@ when not defined(JS): #and not defined(nimscript):
   when not defined(nimscript) and hasAlloc:
     when not defined(gcDestructors):
       include "system/assign"
-    include "system/repr"
+    when not defined(nimV2):
+      include "system/repr"
 
   when hostOS != "standalone" and not defined(nimscript):
     proc getCurrentException*(): ref Exception {.compilerRtl, inl, benign.} =
diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim
index e938dc475..d4c686869 100644
--- a/lib/system/alloc.nim
+++ b/lib/system/alloc.nim
@@ -224,10 +224,6 @@ proc addChunkToMatrix(a: var MemRegion; b: PBigChunk) =
   setBit(sl, a.slBitmap[fl])
   setBit(fl, a.flBitmap)
 
-{.push stack_trace: off.}
-proc initAllocator() = discard "nothing to do anymore"
-{.pop.}
-
 proc incCurrMem(a: var MemRegion, bytes: int) {.inline.} =
   inc(a.currMem, bytes)
 
diff --git a/lib/system/ansi_c.nim b/lib/system/ansi_c.nim
index 552962775..47d30886c 100644
--- a/lib/system/ansi_c.nim
+++ b/lib/system/ansi_c.nim
@@ -139,4 +139,11 @@ proc c_free(p: pointer) {.
 proc c_realloc(p: pointer, newsize: csize): pointer {.
   importc: "realloc", header: "<stdlib.h>".}
 
+proc c_fwrite(buf: pointer, size, n: csize, f: CFilePtr): cint {.
+  importc: "fwrite", header: "<stdio.h>".}
+
+proc rawWrite(f: CFilePtr, s: cstring) {.compilerproc, nonreloadable, inline.} =
+  # we cannot throw an exception here!
+  discard c_fwrite(s, 1, s.len, f)
+
 {.pop}
diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim
index 551e54fae..8849caee5 100644
--- a/lib/system/excpt.nim
+++ b/lib/system/excpt.nim
@@ -17,13 +17,6 @@ var
     ## instead of `stdmsg.write` when printing stacktrace.
     ## Unstable API.
 
-proc c_fwrite(buf: pointer, size, n: csize, f: CFilePtr): cint {.
-  importc: "fwrite", header: "<stdio.h>".}
-
-proc rawWrite(f: CFilePtr, s: cstring) {.compilerproc, nonreloadable, hcrInline.} =
-  # we cannot throw an exception here!
-  discard c_fwrite(s, 1, s.len, f)
-
 when not defined(windows) or not defined(guiapp):
   proc writeToStdErr(msg: cstring) = rawWrite(cstderr, msg)
 
diff --git a/lib/system/gc_common.nim b/lib/system/gc_common.nim
index 91c0244ea..b86ef84f0 100644
--- a/lib/system/gc_common.nim
+++ b/lib/system/gc_common.nim
@@ -167,7 +167,6 @@ when declared(threadType):
     ## This function is available only when ``--threads:on`` and ``--tlsEmulation:off``
     ## switches are used
     if threadType == ThreadType.None:
-      initAllocator()
       var stackTop {.volatile.}: pointer
       nimGC_setStackBottom(addr(stackTop))
       initGC()
diff --git a/lib/system/mmdisp.nim b/lib/system/mmdisp.nim
index a2cddc472..905fdcc94 100644
--- a/lib/system/mmdisp.nim
+++ b/lib/system/mmdisp.nim
@@ -497,7 +497,8 @@ else:
     # XXX due to bootstrapping reasons, we cannot use  compileOption("gc", "stack") here
     include "system/gc_regions"
   elif defined(nimV2):
-    include "core/runtime_v2"
+    var allocator {.rtlThreadVar.}: MemRegion
+    instantiateForRegion(allocator)
   elif defined(gcMarkAndSweep) or defined(gcDestructors):
     # XXX use 'compileOption' here
     include "system/gc_ms"
diff --git a/lib/system/threads.nim b/lib/system/threads.nim
index 7a988db46..ec22a2b12 100644
--- a/lib/system/threads.nim
+++ b/lib/system/threads.nim
@@ -456,8 +456,6 @@ template threadProcWrapperBody(closure: untyped): untyped =
   var thrd = cast[ptr Thread[TArg]](closure)
   var core = thrd.core
   when declared(globalsSlot): threadVarSetValue(globalsSlot, thrd.core)
-  when declared(initAllocator):
-    initAllocator()
   threadProcWrapStackFrame(thrd)
   # Since an unhandled exception terminates the whole process (!), there is
   # no need for a ``try finally`` here, nor would it be correct: The current