summary refs log tree commit diff stats
path: root/lib/system
diff options
context:
space:
mode:
Diffstat (limited to 'lib/system')
-rw-r--r--lib/system/alloc.nim433
-rw-r--r--lib/system/ansi_c.nim22
-rw-r--r--lib/system/arithm.nim184
-rw-r--r--lib/system/assign.nim34
-rw-r--r--lib/system/atomics.nim49
-rw-r--r--lib/system/avltree.nim8
-rw-r--r--lib/system/cellsets.nim63
-rw-r--r--lib/system/cgprocs.nim16
-rw-r--r--lib/system/channels.nim528
-rw-r--r--lib/system/chcks.nim6
-rw-r--r--lib/system/debugger.nim62
-rw-r--r--lib/system/deepcopy.nim10
-rw-r--r--lib/system/dyncalls.nim41
-rw-r--r--lib/system/endb.nim98
-rw-r--r--lib/system/excpt.nim97
-rw-r--r--lib/system/gc.nim312
-rw-r--r--lib/system/gc2.nim283
-rw-r--r--lib/system/gc_common.nim277
-rw-r--r--lib/system/gc_ms.nim255
-rw-r--r--lib/system/hti.nim10
-rw-r--r--lib/system/inclrtl.nim10
-rw-r--r--lib/system/jssys.nim195
-rw-r--r--lib/system/mmdisp.nim299
-rw-r--r--lib/system/nimscript.nim277
-rw-r--r--lib/system/platforms.nim8
-rw-r--r--lib/system/profiler.nim24
-rw-r--r--lib/system/repr.nim86
-rw-r--r--lib/system/sets.nim9
-rw-r--r--lib/system/sysio.nim124
-rw-r--r--lib/system/syslocks.nim76
-rw-r--r--lib/system/sysspawn.nim6
-rw-r--r--lib/system/sysstr.nim14
-rw-r--r--lib/system/threads.nim333
-rw-r--r--lib/system/timers.nim73
-rw-r--r--lib/system/widestrs.nim65
35 files changed, 2629 insertions, 1758 deletions
diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim
index fd3ced832..3ebbc8c1e 100644
--- a/lib/system/alloc.nim
+++ b/lib/system/alloc.nim
@@ -8,50 +8,109 @@
 #
 
 # Low level allocator for Nim. Has been designed to support the GC.
-# TODO: 
+# TODO:
 # - eliminate "used" field
 # - make searching for block O(1)
 {.push profiler:off.}
 
+proc roundup(x, v: int): int {.inline.} =
+  result = (x + (v-1)) and not (v-1)
+  sysAssert(result >= x, "roundup: result < x")
+  #return ((-x) and (v-1)) +% x
+
+sysAssert(roundup(14, PageSize) == PageSize, "invalid PageSize")
+sysAssert(roundup(15, 8) == 16, "roundup broken")
+sysAssert(roundup(65, 8) == 72, "roundup broken 2")
+
 # ------------ platform specific chunk allocation code -----------------------
 
 # some platforms have really weird unmap behaviour: unmap(blockStart, PageSize)
 # really frees the whole block. Happens for Linux/PowerPC for example. Amd64
 # and x86 are safe though; Windows is special because MEM_RELEASE can only be
-# used with a size of 0:
-const weirdUnmap = not (defined(amd64) or defined(i386)) or defined(windows)
+# used with a size of 0. We also allow unmapping to be turned off with
+# -d:nimAllocNoUnmap:
+const doNotUnmap = not (defined(amd64) or defined(i386)) or
+                   defined(windows) or defined(nimAllocNoUnmap)
+
 
-when defined(posix): 
+when defined(emscripten):
   const
-    PROT_READ  = 1             # page can be read 
-    PROT_WRITE = 2             # page can be written 
-    MAP_PRIVATE = 2'i32        # Changes are private 
-  
+    PROT_READ  = 1             # page can be read
+    PROT_WRITE = 2             # page can be written
+    MAP_PRIVATE = 2'i32        # Changes are private
+
+  var MAP_ANONYMOUS {.importc: "MAP_ANONYMOUS", header: "<sys/mman.h>".}: cint
+  type 
+    PEmscriptenMMapBlock = ptr EmscriptenMMapBlock
+    EmscriptenMMapBlock {.pure, inheritable.} = object
+      realSize: int        # size of previous chunk; for coalescing
+      realPointer: pointer     # if < PageSize it is a small chunk
+
+  proc mmap(adr: pointer, len: int, prot, flags, fildes: cint,
+            off: int): pointer {.header: "<sys/mman.h>".}
+
+  proc munmap(adr: pointer, len: int) {.header: "<sys/mman.h>".}
+
+  proc osAllocPages(block_size: int): pointer {.inline.} =
+    let realSize = block_size + sizeof(EmscriptenMMapBlock) + PageSize + 1
+    result = mmap(nil, realSize, PROT_READ or PROT_WRITE,
+                             MAP_PRIVATE or MAP_ANONYMOUS, -1, 0)
+    if result == nil or result == cast[pointer](-1):
+      raiseOutOfMem()
+
+    let realPointer = result
+    let pos = cast[int](result)
+
+    # Convert pointer to PageSize correct one.
+    var new_pos = cast[ByteAddress](pos) +% (PageSize - (pos %% PageSize))
+    if (new_pos-pos)< sizeof(EmscriptenMMapBlock):
+      new_pos = new_pos +% PageSize
+    result = cast[pointer](new_pos)
+
+    var mmapDescrPos = cast[ByteAddress](result) -% sizeof(EmscriptenMMapBlock)
+
+    var mmapDescr = cast[EmscriptenMMapBlock](mmapDescrPos)
+    mmapDescr.realSize = realSize
+    mmapDescr.realPointer = realPointer
+
+    c_fprintf(c_stdout, "[Alloc] size %d %d realSize:%d realPos:%d\n", block_size, cast[int](result), realSize, cast[int](realPointer))
+
+  proc osDeallocPages(p: pointer, size: int) {.inline} =
+    var mmapDescrPos = cast[ByteAddress](p) -% sizeof(EmscriptenMMapBlock)
+    var mmapDescr = cast[EmscriptenMMapBlock](mmapDescrPos)
+    munmap(mmapDescr.realPointer, mmapDescr.realSize)
+
+elif defined(posix):
+  const
+    PROT_READ  = 1             # page can be read
+    PROT_WRITE = 2             # page can be written
+    MAP_PRIVATE = 2'i32        # Changes are private
+
   when defined(macosx) or defined(bsd):
     const MAP_ANONYMOUS = 0x1000
-  elif defined(solaris): 
+  elif defined(solaris):
     const MAP_ANONYMOUS = 0x100
   else:
     var
       MAP_ANONYMOUS {.importc: "MAP_ANONYMOUS", header: "<sys/mman.h>".}: cint
-    
+
   proc mmap(adr: pointer, len: int, prot, flags, fildes: cint,
             off: int): pointer {.header: "<sys/mman.h>".}
 
   proc munmap(adr: pointer, len: int) {.header: "<sys/mman.h>".}
-  
-  proc osAllocPages(size: int): pointer {.inline.} = 
-    result = mmap(nil, size, PROT_READ or PROT_WRITE, 
+
+  proc osAllocPages(size: int): pointer {.inline.} =
+    result = mmap(nil, size, PROT_READ or PROT_WRITE,
                              MAP_PRIVATE or MAP_ANONYMOUS, -1, 0)
     if result == nil or result == cast[pointer](-1):
       raiseOutOfMem()
-      
+
   proc osDeallocPages(p: pointer, size: int) {.inline} =
     when reallyOsDealloc: munmap(p, size)
-  
-elif defined(windows): 
+
+elif defined(windows):
   const
-    MEM_RESERVE = 0x2000 
+    MEM_RESERVE = 0x2000
     MEM_COMMIT = 0x1000
     MEM_TOP_DOWN = 0x100000
     PAGE_READWRITE = 0x04
@@ -62,12 +121,12 @@ elif defined(windows):
   proc virtualAlloc(lpAddress: pointer, dwSize: int, flAllocationType,
                     flProtect: int32): pointer {.
                     header: "<windows.h>", stdcall, importc: "VirtualAlloc".}
-  
-  proc virtualFree(lpAddress: pointer, dwSize: int, 
+
+  proc virtualFree(lpAddress: pointer, dwSize: int,
                    dwFreeType: int32) {.header: "<windows.h>", stdcall,
                    importc: "VirtualFree".}
-  
-  proc osAllocPages(size: int): pointer {.inline.} = 
+
+  proc osAllocPages(size: int): pointer {.inline.} =
     result = virtualAlloc(nil, size, MEM_RESERVE or MEM_COMMIT,
                           PAGE_READWRITE)
     if result == nil: raiseOutOfMem()
@@ -82,7 +141,22 @@ elif defined(windows):
     when reallyOsDealloc: virtualFree(p, 0, MEM_RELEASE)
     #VirtualFree(p, size, MEM_DECOMMIT)
 
-else: 
+elif hostOS == "standalone":
+  var
+    theHeap: array[1024*PageSize, float64] # 'float64' for alignment
+    bumpPointer = cast[int](addr theHeap)
+
+  proc osAllocPages(size: int): pointer {.inline.} =
+    if size+bumpPointer < cast[int](addr theHeap) + sizeof(theHeap):
+      result = cast[pointer](bumpPointer)
+      inc bumpPointer, size
+    else:
+      raiseOutOfMem()
+
+  proc osDeallocPages(p: pointer, size: int) {.inline.} =
+    if bumpPointer-size == cast[int](p):
+      dec bumpPointer, size
+else:
   {.error: "Port memory manager to your platform".}
 
 # --------------------- end of non-portable code -----------------------------
@@ -97,90 +171,85 @@ const
   InitialMemoryRequest = ChunkOsReturn div 2 # < ChunkOsReturn!
   SmallChunkSize = PageSize
 
-type 
-  PTrunk = ptr TTrunk
-  TTrunk {.final.} = object 
+type
+  PTrunk = ptr Trunk
+  Trunk {.final.} = object
     next: PTrunk         # all nodes are connected with this pointer
     key: int             # start address at bit 0
     bits: array[0..IntsPerTrunk-1, int] # a bit vector
-  
-  TTrunkBuckets = array[0..255, PTrunk]
-  TIntSet {.final.} = object 
-    data: TTrunkBuckets
-  
+
+  TrunkBuckets = array[0..255, PTrunk]
+  IntSet {.final.} = object
+    data: TrunkBuckets
+{.deprecated: [TIntSet: IntSet, TTrunk: Trunk, TTrunkBuckets: TrunkBuckets].}
+
 type
-  TAlignType = BiggestFloat
-  TFreeCell {.final, pure.} = object
-    next: ptr TFreeCell  # next free cell in chunk (overlaid with refcount)
+  AlignType = BiggestFloat
+  FreeCell {.final, pure.} = object
+    next: ptr FreeCell  # next free cell in chunk (overlaid with refcount)
     zeroField: int       # 0 means cell is not used (overlaid with typ field)
                          # 1 means cell is manually managed pointer
                          # otherwise a PNimType is stored in there
 
-  PChunk = ptr TBaseChunk
-  PBigChunk = ptr TBigChunk
-  PSmallChunk = ptr TSmallChunk
-  TBaseChunk {.pure, inheritable.} = object
+  PChunk = ptr BaseChunk
+  PBigChunk = ptr BigChunk
+  PSmallChunk = ptr SmallChunk
+  BaseChunk {.pure, inheritable.} = object
     prevSize: int        # size of previous chunk; for coalescing
     size: int            # if < PageSize it is a small chunk
     used: bool           # later will be optimized into prevSize...
-  
-  TSmallChunk = object of TBaseChunk
+
+  SmallChunk = object of BaseChunk
     next, prev: PSmallChunk  # chunks of the same size
-    freeList: ptr TFreeCell
-    free: int            # how many bytes remain    
+    freeList: ptr FreeCell
+    free: int            # how many bytes remain
     acc: int             # accumulator for small object allocation
-    data: TAlignType     # start of usable memory
-  
-  TBigChunk = object of TBaseChunk # not necessarily > PageSize!
+    data: AlignType      # start of usable memory
+
+  BigChunk = object of BaseChunk # not necessarily > PageSize!
     next, prev: PBigChunk    # chunks of the same (or bigger) size
     align: int
-    data: TAlignType     # start of usable memory
-
-template smallChunkOverhead(): expr = sizeof(TSmallChunk)-sizeof(TAlignType)
-template bigChunkOverhead(): expr = sizeof(TBigChunk)-sizeof(TAlignType)
+    data: AlignType      # start of usable memory
+{.deprecated: [TAlignType: AlignType, TFreeCell: FreeCell, TBaseChunk: BaseChunk,
+              TBigChunk: BigChunk, TSmallChunk: SmallChunk].}
 
-proc roundup(x, v: int): int {.inline.} = 
-  result = (x + (v-1)) and not (v-1)
-  sysAssert(result >= x, "roundup: result < x")
-  #return ((-x) and (v-1)) +% x
-
-sysAssert(roundup(14, PageSize) == PageSize, "invalid PageSize")
-sysAssert(roundup(15, 8) == 16, "roundup broken")
-sysAssert(roundup(65, 8) == 72, "roundup broken 2")
+template smallChunkOverhead(): expr = sizeof(SmallChunk)-sizeof(AlignType)
+template bigChunkOverhead(): expr = sizeof(BigChunk)-sizeof(AlignType)
 
 # ------------- chunk table ---------------------------------------------------
 # We use a PtrSet of chunk starts and a table[Page, chunksize] for chunk
 # endings of big chunks. This is needed by the merging operation. The only
 # remaining operation is best-fit for big chunks. Since there is a size-limit
 # for big chunks (because greater than the limit means they are returned back
-# to the OS), a fixed size array can be used. 
+# to the OS), a fixed size array can be used.
 
 type
-  PLLChunk = ptr TLLChunk
-  TLLChunk {.pure.} = object ## *low-level* chunk
+  PLLChunk = ptr LLChunk
+  LLChunk {.pure.} = object ## *low-level* chunk
     size: int                # remaining size
     acc: int                 # accumulator
     next: PLLChunk           # next low-level chunk; only needed for dealloc
 
-  PAvlNode = ptr TAvlNode
-  TAvlNode {.pure, final.} = object 
-    link: array[0..1, PAvlNode] # Left (0) and right (1) links 
+  PAvlNode = ptr AvlNode
+  AvlNode {.pure, final.} = object
+    link: array[0..1, PAvlNode] # Left (0) and right (1) links
     key, upperBound: int
     level: int
-    
-  TMemRegion {.final, pure.} = object
+
+  MemRegion {.final, pure.} = object
     minLargeObj, maxLargeObj: int
     freeSmallChunks: array[0..SmallChunkSize div MemAlign-1, PSmallChunk]
     llmem: PLLChunk
     currMem, maxMem, freeMem: int # memory sizes (allocated from OS)
-    lastSize: int # needed for the case that OS gives us pages linearly 
+    lastSize: int # needed for the case that OS gives us pages linearly
     freeChunksList: PBigChunk # XXX make this a datastructure with O(1) access
-    chunkStarts: TIntSet
+    chunkStarts: IntSet
     root, deleted, last, freeAvlNodes: PAvlNode
-  
+{.deprecated: [TLLChunk: LLChunk, TAvlNode: AvlNode, TMemRegion: MemRegion].}
+
 # shared:
 var
-  bottomData: TAvlNode
+  bottomData: AvlNode
   bottom: PAvlNode
 
 {.push stack_trace: off.}
@@ -191,44 +260,44 @@ proc initAllocator() =
     bottom.link[1] = bottom
 {.pop.}
 
-proc incCurrMem(a: var TMemRegion, bytes: int) {.inline.} = 
+proc incCurrMem(a: var MemRegion, bytes: int) {.inline.} =
   inc(a.currMem, bytes)
 
-proc decCurrMem(a: var TMemRegion, bytes: int) {.inline.} =
+proc decCurrMem(a: var MemRegion, bytes: int) {.inline.} =
   a.maxMem = max(a.maxMem, a.currMem)
   dec(a.currMem, bytes)
 
-proc getMaxMem(a: var TMemRegion): int =
-  # Since we update maxPagesCount only when freeing pages, 
+proc getMaxMem(a: var MemRegion): int =
+  # Since we update maxPagesCount only when freeing pages,
   # maxPagesCount may not be up to date. Thus we use the
   # maximum of these both values here:
   result = max(a.currMem, a.maxMem)
-  
-proc llAlloc(a: var TMemRegion, size: int): pointer =
+
+proc llAlloc(a: var MemRegion, size: int): pointer =
   # *low-level* alloc for the memory managers data structures. Deallocation
-  # is done at he end of the allocator's life time.
+  # is done at the end of the allocator's life time.
   if a.llmem == nil or size > a.llmem.size:
-    # the requested size is ``roundup(size+sizeof(TLLChunk), PageSize)``, but
+    # the requested size is ``roundup(size+sizeof(LLChunk), PageSize)``, but
     # since we know ``size`` is a (small) constant, we know the requested size
     # is one page:
-    sysAssert roundup(size+sizeof(TLLChunk), PageSize) == PageSize, "roundup 6"
+    sysAssert roundup(size+sizeof(LLChunk), PageSize) == PageSize, "roundup 6"
     var old = a.llmem # can be nil and is correct with nil
     a.llmem = cast[PLLChunk](osAllocPages(PageSize))
     incCurrMem(a, PageSize)
-    a.llmem.size = PageSize - sizeof(TLLChunk)
-    a.llmem.acc = sizeof(TLLChunk)
+    a.llmem.size = PageSize - sizeof(LLChunk)
+    a.llmem.acc = sizeof(LLChunk)
     a.llmem.next = old
   result = cast[pointer](cast[ByteAddress](a.llmem) + a.llmem.acc)
   dec(a.llmem.size, size)
   inc(a.llmem.acc, size)
   zeroMem(result, size)
 
-proc allocAvlNode(a: var TMemRegion, key, upperBound: int): PAvlNode =
+proc allocAvlNode(a: var MemRegion, key, upperBound: int): PAvlNode =
   if a.freeAvlNodes != nil:
     result = a.freeAvlNodes
     a.freeAvlNodes = a.freeAvlNodes.link[0]
   else:
-    result = cast[PAvlNode](llAlloc(a, sizeof(TAvlNode)))
+    result = cast[PAvlNode](llAlloc(a, sizeof(AvlNode)))
   result.key = key
   result.upperBound = upperBound
   result.link[0] = bottom
@@ -238,28 +307,28 @@ proc allocAvlNode(a: var TMemRegion, key, upperBound: int): PAvlNode =
   sysAssert(bottom.link[0] == bottom, "bottom link[0]")
   sysAssert(bottom.link[1] == bottom, "bottom link[1]")
 
-proc deallocAvlNode(a: var TMemRegion, n: PAvlNode) {.inline.} =
+proc deallocAvlNode(a: var MemRegion, n: PAvlNode) {.inline.} =
   n.link[0] = a.freeAvlNodes
   a.freeAvlNodes = n
 
 include "system/avltree"
 
-proc llDeallocAll(a: var TMemRegion) =
+proc llDeallocAll(a: var MemRegion) =
   var it = a.llmem
   while it != nil:
     # we know each block in the list has the size of 1 page:
     var next = it.next
     osDeallocPages(it, PageSize)
     it = next
-  
-proc intSetGet(t: TIntSet, key: int): PTrunk = 
+
+proc intSetGet(t: IntSet, key: int): PTrunk =
   var it = t.data[key and high(t.data)]
-  while it != nil: 
+  while it != nil:
     if it.key == key: return it
     it = it.next
   result = nil
 
-proc intSetPut(a: var TMemRegion, t: var TIntSet, key: int): PTrunk = 
+proc intSetPut(a: var MemRegion, t: var IntSet, key: int): PTrunk =
   result = intSetGet(t, key)
   if result == nil:
     result = cast[PTrunk](llAlloc(a, sizeof(result[])))
@@ -267,27 +336,27 @@ proc intSetPut(a: var TMemRegion, t: var TIntSet, key: int): PTrunk =
     t.data[key and high(t.data)] = result
     result.key = key
 
-proc contains(s: TIntSet, key: int): bool = 
+proc contains(s: IntSet, key: int): bool =
   var t = intSetGet(s, key shr TrunkShift)
-  if t != nil: 
+  if t != nil:
     var u = key and TrunkMask
     result = (t.bits[u shr IntShift] and (1 shl (u and IntMask))) != 0
-  else: 
+  else:
     result = false
-  
-proc incl(a: var TMemRegion, s: var TIntSet, key: int) = 
+
+proc incl(a: var MemRegion, s: var IntSet, key: int) =
   var t = intSetPut(a, s, key shr TrunkShift)
   var u = key and TrunkMask
   t.bits[u shr IntShift] = t.bits[u shr IntShift] or (1 shl (u and IntMask))
 
-proc excl(s: var TIntSet, key: int) = 
+proc excl(s: var IntSet, key: int) =
   var t = intSetGet(s, key shr TrunkShift)
   if t != nil:
     var u = key and TrunkMask
     t.bits[u shr IntShift] = t.bits[u shr IntShift] and not
         (1 shl (u and IntMask))
 
-iterator elements(t: TIntSet): int {.inline.} =
+iterator elements(t: IntSet): int {.inline.} =
   # while traversing it is forbidden to change the set!
   for h in 0..high(t.data):
     var r = t.data[h]
@@ -304,14 +373,14 @@ iterator elements(t: TIntSet): int {.inline.} =
           w = w shr 1
         inc(i)
       r = r.next
-  
-proc isSmallChunk(c: PChunk): bool {.inline.} = 
+
+proc isSmallChunk(c: PChunk): bool {.inline.} =
   return c.size <= SmallChunkSize-smallChunkOverhead()
-  
-proc chunkUnused(c: PChunk): bool {.inline.} = 
+
+proc chunkUnused(c: PChunk): bool {.inline.} =
   result = not c.used
 
-iterator allObjects(m: TMemRegion): pointer {.inline.} =
+iterator allObjects(m: MemRegion): pointer {.inline.} =
   for s in elements(m.chunkStarts):
     # we need to check here again as it could have been modified:
     if s in m.chunkStarts:
@@ -319,7 +388,7 @@ iterator allObjects(m: TMemRegion): pointer {.inline.} =
       if not chunkUnused(c):
         if isSmallChunk(c):
           var c = cast[PSmallChunk](c)
-          
+
           let size = c.size
           var a = cast[ByteAddress](addr(c.data))
           let limit = a + c.acc
@@ -331,20 +400,20 @@ iterator allObjects(m: TMemRegion): pointer {.inline.} =
           yield addr(c.data)
 
 proc isCell(p: pointer): bool {.inline.} =
-  result = cast[ptr TFreeCell](p).zeroField >% 1
+  result = cast[ptr FreeCell](p).zeroField >% 1
 
 # ------------- chunk management ----------------------------------------------
-proc pageIndex(c: PChunk): int {.inline.} = 
+proc pageIndex(c: PChunk): int {.inline.} =
   result = cast[ByteAddress](c) shr PageShift
 
-proc pageIndex(p: pointer): int {.inline.} = 
+proc pageIndex(p: pointer): int {.inline.} =
   result = cast[ByteAddress](p) shr PageShift
 
-proc pageAddr(p: pointer): PChunk {.inline.} = 
+proc pageAddr(p: pointer): PChunk {.inline.} =
   result = cast[PChunk](cast[ByteAddress](p) and not PageMask)
   #sysAssert(Contains(allocator.chunkStarts, pageIndex(result)))
 
-proc requestOsChunks(a: var TMemRegion, size: int): PBigChunk = 
+proc requestOsChunks(a: var MemRegion, size: int): PBigChunk =
   incCurrMem(a, size)
   inc(a.freeMem, size)
   result = cast[PBigChunk](osAllocPages(size))
@@ -373,7 +442,7 @@ proc requestOsChunks(a: var TMemRegion, size: int): PBigChunk =
     result.prevSize = 0 # unknown
   a.lastSize = size # for next request
 
-proc freeOsChunks(a: var TMemRegion, p: pointer, size: int) = 
+proc freeOsChunks(a: var MemRegion, p: pointer, size: int) =
   # update next.prevSize:
   var c = cast[PChunk](p)
   var nxt = cast[ByteAddress](p) +% c.size
@@ -387,36 +456,36 @@ proc freeOsChunks(a: var TMemRegion, p: pointer, size: int) =
   dec(a.freeMem, size)
   #c_fprintf(c_stdout, "[Alloc] back to OS: %ld\n", size)
 
-proc isAccessible(a: TMemRegion, p: pointer): bool {.inline.} = 
+proc isAccessible(a: MemRegion, p: pointer): bool {.inline.} =
   result = contains(a.chunkStarts, pageIndex(p))
 
-proc contains[T](list, x: T): bool = 
+proc contains[T](list, x: T): bool =
   var it = list
   while it != nil:
     if it == x: return true
     it = it.next
-    
-proc writeFreeList(a: TMemRegion) =
+
+proc writeFreeList(a: MemRegion) =
   var it = a.freeChunksList
   c_fprintf(c_stdout, "freeChunksList: %p\n", it)
-  while it != nil: 
-    c_fprintf(c_stdout, "it: %p, next: %p, prev: %p\n", 
+  while it != nil:
+    c_fprintf(c_stdout, "it: %p, next: %p, prev: %p\n",
               it, it.next, it.prev)
     it = it.next
 
-proc listAdd[T](head: var T, c: T) {.inline.} = 
+proc listAdd[T](head: var T, c: T) {.inline.} =
   sysAssert(c notin head, "listAdd 1")
   sysAssert c.prev == nil, "listAdd 2"
   sysAssert c.next == nil, "listAdd 3"
   c.next = head
-  if head != nil: 
+  if head != nil:
     sysAssert head.prev == nil, "listAdd 4"
     head.prev = c
   head = c
 
 proc listRemove[T](head: var T, c: T) {.inline.} =
   sysAssert(c in head, "listRemove")
-  if c == head: 
+  if c == head:
     head = c.next
     sysAssert c.prev == nil, "listRemove 2"
     if head != nil: head.prev = nil
@@ -426,15 +495,15 @@ proc listRemove[T](head: var T, c: T) {.inline.} =
     if c.next != nil: c.next.prev = c.prev
   c.next = nil
   c.prev = nil
-  
-proc updatePrevSize(a: var TMemRegion, c: PBigChunk, 
-                    prevSize: int) {.inline.} = 
+
+proc updatePrevSize(a: var MemRegion, c: PBigChunk,
+                    prevSize: int) {.inline.} =
   var ri = cast[PChunk](cast[ByteAddress](c) +% c.size)
   sysAssert((cast[ByteAddress](ri) and PageMask) == 0, "updatePrevSize")
   if isAccessible(a, ri):
     ri.prevSize = prevSize
-  
-proc freeBigChunk(a: var TMemRegion, c: PBigChunk) = 
+
+proc freeBigChunk(a: var MemRegion, c: PBigChunk) =
   var c = c
   sysAssert(c.size >= PageSize, "freeBigChunk")
   inc(a.freeMem, c.size)
@@ -448,7 +517,7 @@ proc freeBigChunk(a: var TMemRegion, c: PBigChunk) =
         inc(c.size, ri.size)
         excl(a.chunkStarts, pageIndex(ri))
   when coalescLeft:
-    if c.prevSize != 0: 
+    if c.prevSize != 0:
       var le = cast[PChunk](cast[ByteAddress](c) -% c.prevSize)
       sysAssert((cast[ByteAddress](le) and PageMask) == 0, "freeBigChunk 4")
       if isAccessible(a, le) and chunkUnused(le):
@@ -459,7 +528,7 @@ proc freeBigChunk(a: var TMemRegion, c: PBigChunk) =
           excl(a.chunkStarts, pageIndex(c))
           c = cast[PBigChunk](le)
 
-  if c.size < ChunkOsReturn or weirdUnmap:
+  if c.size < ChunkOsReturn or doNotUnmap:
     incl(a, a.chunkStarts, pageIndex(c))
     updatePrevSize(a, c, c.size)
     listAdd(a.freeChunksList, c)
@@ -467,7 +536,7 @@ proc freeBigChunk(a: var TMemRegion, c: PBigChunk) =
   else:
     freeOsChunks(a, c, c.size)
 
-proc splitChunk(a: var TMemRegion, c: PBigChunk, size: int) = 
+proc splitChunk(a: var MemRegion, c: PBigChunk, size: int) =
   var rest = cast[PBigChunk](cast[ByteAddress](c) +% size)
   sysAssert(rest notin a.freeChunksList, "splitChunk")
   rest.size = c.size - size
@@ -480,7 +549,7 @@ proc splitChunk(a: var TMemRegion, c: PBigChunk, size: int) =
   incl(a, a.chunkStarts, pageIndex(rest))
   listAdd(a.freeChunksList, rest)
 
-proc getBigChunk(a: var TMemRegion, size: int): PBigChunk = 
+proc getBigChunk(a: var MemRegion, size: int): PBigChunk =
   # use first fit for now:
   sysAssert((size and PageMask) == 0, "getBigChunk 1")
   sysAssert(size > 0, "getBigChunk 2")
@@ -488,7 +557,7 @@ proc getBigChunk(a: var TMemRegion, size: int): PBigChunk =
   block search:
     while result != nil:
       sysAssert chunkUnused(result), "getBigChunk 3"
-      if result.size == size: 
+      if result.size == size:
         listRemove(a.freeChunksList, result)
         break search
       elif result.size > size:
@@ -497,7 +566,7 @@ proc getBigChunk(a: var TMemRegion, size: int): PBigChunk =
         break search
       result = result.next
       sysAssert result != a.freeChunksList, "getBigChunk 4"
-    if size < InitialMemoryRequest: 
+    if size < InitialMemoryRequest:
       result = requestOsChunks(a, InitialMemoryRequest)
       splitChunk(a, result, size)
     else:
@@ -507,29 +576,29 @@ proc getBigChunk(a: var TMemRegion, size: int): PBigChunk =
   incl(a, a.chunkStarts, pageIndex(result))
   dec(a.freeMem, size)
 
-proc getSmallChunk(a: var TMemRegion): PSmallChunk = 
+proc getSmallChunk(a: var MemRegion): PSmallChunk =
   var res = getBigChunk(a, PageSize)
   sysAssert res.prev == nil, "getSmallChunk 1"
   sysAssert res.next == nil, "getSmallChunk 2"
   result = cast[PSmallChunk](res)
 
 # -----------------------------------------------------------------------------
-proc isAllocatedPtr(a: TMemRegion, p: pointer): bool {.benign.}
+proc isAllocatedPtr(a: MemRegion, p: pointer): bool {.benign.}
 
-proc allocInv(a: TMemRegion): bool =
+proc allocInv(a: MemRegion): bool =
   ## checks some (not all yet) invariants of the allocator's data structures.
   for s in low(a.freeSmallChunks)..high(a.freeSmallChunks):
     var c = a.freeSmallChunks[s]
     while c != nil:
-      if c.next == c: 
+      if c.next == c:
         echo "[SYSASSERT] c.next == c"
         return false
-      if c.size != s * MemAlign: 
+      if c.size != s * MemAlign:
         echo "[SYSASSERT] c.size != s * MemAlign"
         return false
       var it = c.freeList
       while it != nil:
-        if it.zeroField != 0: 
+        if it.zeroField != 0:
           echo "[SYSASSERT] it.zeroField != 0"
           c_printf("%ld %p\n", it.zeroField, it)
           return false
@@ -537,18 +606,18 @@ proc allocInv(a: TMemRegion): bool =
       c = c.next
   result = true
 
-proc rawAlloc(a: var TMemRegion, requestedSize: int): pointer =
+proc rawAlloc(a: var MemRegion, requestedSize: int): pointer =
   sysAssert(allocInv(a), "rawAlloc: begin")
-  sysAssert(roundup(65, 8) == 72, "rawAlloc 1")
-  sysAssert requestedSize >= sizeof(TFreeCell), "rawAlloc 2"
+  sysAssert(roundup(65, 8) == 72, "rawAlloc: roundup broken")
+  sysAssert(requestedSize >= sizeof(FreeCell), "rawAlloc: requested size too small")
   var size = roundup(requestedSize, MemAlign)
   sysAssert(size >= requestedSize, "insufficient allocated size!")
   #c_fprintf(c_stdout, "alloc; size: %ld; %ld\n", requestedSize, size)
-  if size <= SmallChunkSize-smallChunkOverhead(): 
+  if size <= SmallChunkSize-smallChunkOverhead():
     # allocate a small block: for small chunks, we use only its next pointer
     var s = size div MemAlign
     var c = a.freeSmallChunks[s]
-    if c == nil: 
+    if c == nil:
       c = getSmallChunk(a)
       c.freeList = nil
       sysAssert c.size == PageSize, "rawAlloc 3"
@@ -567,7 +636,7 @@ proc rawAlloc(a: var TMemRegion, requestedSize: int): pointer =
       #  c_fprintf(c_stdout, "csize: %lld; size %lld\n", c.size, size)
       sysAssert c.size == size, "rawAlloc 6"
       if c.freeList == nil:
-        sysAssert(c.acc + smallChunkOverhead() + size <= SmallChunkSize, 
+        sysAssert(c.acc + smallChunkOverhead() + size <= SmallChunkSize,
                   "rawAlloc 7")
         result = cast[pointer](cast[ByteAddress](addr(c.data)) +% c.acc)
         inc(c.acc, size)
@@ -601,11 +670,11 @@ proc rawAlloc(a: var TMemRegion, requestedSize: int): pointer =
   sysAssert(allocInv(a), "rawAlloc: end")
   when logAlloc: cprintf("rawAlloc: %ld %p\n", requestedSize, result)
 
-proc rawAlloc0(a: var TMemRegion, requestedSize: int): pointer =
+proc rawAlloc0(a: var MemRegion, requestedSize: int): pointer =
   result = rawAlloc(a, requestedSize)
   zeroMem(result, requestedSize)
 
-proc rawDealloc(a: var TMemRegion, p: pointer) =
+proc rawDealloc(a: var MemRegion, p: pointer) =
   #sysAssert(isAllocatedPtr(a, p), "rawDealloc: no allocated pointer")
   sysAssert(allocInv(a), "rawDealloc: begin")
   var c = pageAddr(p)
@@ -615,16 +684,16 @@ proc rawDealloc(a: var TMemRegion, p: pointer) =
     var s = c.size
     sysAssert(((cast[ByteAddress](p) and PageMask) - smallChunkOverhead()) %%
                s == 0, "rawDealloc 3")
-    var f = cast[ptr TFreeCell](p)
+    var f = cast[ptr FreeCell](p)
     #echo("setting to nil: ", $cast[TAddress](addr(f.zeroField)))
     sysAssert(f.zeroField != 0, "rawDealloc 1")
     f.zeroField = 0
     f.next = c.freeList
     c.freeList = f
-    when overwriteFree: 
+    when overwriteFree:
       # set to 0xff to check for usage after free bugs:
-      c_memset(cast[pointer](cast[int](p) +% sizeof(TFreeCell)), -1'i32, 
-               s -% sizeof(TFreeCell))
+      c_memset(cast[pointer](cast[int](p) +% sizeof(FreeCell)), -1'i32,
+               s -% sizeof(FreeCell))
     # check if it is not in the freeSmallChunks[s] list:
     if c.free < s:
       # add it to the freeSmallChunks[s] array:
@@ -649,36 +718,36 @@ proc rawDealloc(a: var TMemRegion, p: pointer) =
   sysAssert(allocInv(a), "rawDealloc: end")
   when logAlloc: cprintf("rawDealloc: %p\n", p)
 
-proc isAllocatedPtr(a: TMemRegion, p: pointer): bool = 
+proc isAllocatedPtr(a: MemRegion, p: pointer): bool =
   if isAccessible(a, p):
     var c = pageAddr(p)
     if not chunkUnused(c):
       if isSmallChunk(c):
         var c = cast[PSmallChunk](c)
-        var offset = (cast[ByteAddress](p) and (PageSize-1)) -% 
+        var offset = (cast[ByteAddress](p) and (PageSize-1)) -%
                      smallChunkOverhead()
         result = (c.acc >% offset) and (offset %% c.size == 0) and
-          (cast[ptr TFreeCell](p).zeroField >% 1)
+          (cast[ptr FreeCell](p).zeroField >% 1)
       else:
         var c = cast[PBigChunk](c)
-        result = p == addr(c.data) and cast[ptr TFreeCell](p).zeroField >% 1
+        result = p == addr(c.data) and cast[ptr FreeCell](p).zeroField >% 1
 
-proc prepareForInteriorPointerChecking(a: var TMemRegion) {.inline.} =
+proc prepareForInteriorPointerChecking(a: var MemRegion) {.inline.} =
   a.minLargeObj = lowGauge(a.root)
   a.maxLargeObj = highGauge(a.root)
 
-proc interiorAllocatedPtr(a: TMemRegion, p: pointer): pointer =
+proc interiorAllocatedPtr(a: MemRegion, p: pointer): pointer =
   if isAccessible(a, p):
     var c = pageAddr(p)
     if not chunkUnused(c):
       if isSmallChunk(c):
         var c = cast[PSmallChunk](c)
-        var offset = (cast[ByteAddress](p) and (PageSize-1)) -% 
+        var offset = (cast[ByteAddress](p) and (PageSize-1)) -%
                      smallChunkOverhead()
         if c.acc >% offset:
           sysAssert(cast[ByteAddress](addr(c.data)) +% offset ==
                     cast[ByteAddress](p), "offset is not what you think it is")
-          var d = cast[ptr TFreeCell](cast[ByteAddress](addr(c.data)) +% 
+          var d = cast[ptr FreeCell](cast[ByteAddress](addr(c.data)) +%
                     offset -% (offset %% c.size))
           if d.zeroField >% 1:
             result = d
@@ -686,7 +755,7 @@ proc interiorAllocatedPtr(a: TMemRegion, p: pointer): pointer =
       else:
         var c = cast[PBigChunk](c)
         var d = addr(c.data)
-        if p >= d and cast[ptr TFreeCell](d).zeroField >% 1:
+        if p >= d and cast[ptr FreeCell](d).zeroField >% 1:
           result = d
           sysAssert isAllocatedPtr(a, result), " result wrong pointer!"
   else:
@@ -699,38 +768,38 @@ proc interiorAllocatedPtr(a: TMemRegion, p: pointer): pointer =
         var k = cast[pointer](avlNode.key)
         var c = cast[PBigChunk](pageAddr(k))
         sysAssert(addr(c.data) == k, " k is not the same as addr(c.data)!")
-        if cast[ptr TFreeCell](k).zeroField >% 1:
+        if cast[ptr FreeCell](k).zeroField >% 1:
           result = k
           sysAssert isAllocatedPtr(a, result), " result wrong pointer!"
 
 proc ptrSize(p: pointer): int =
-  var x = cast[pointer](cast[ByteAddress](p) -% sizeof(TFreeCell))
+  var x = cast[pointer](cast[ByteAddress](p) -% sizeof(FreeCell))
   var c = pageAddr(p)
   sysAssert(not chunkUnused(c), "ptrSize")
-  result = c.size -% sizeof(TFreeCell)
+  result = c.size -% sizeof(FreeCell)
   if not isSmallChunk(c):
     dec result, bigChunkOverhead()
 
-proc alloc(allocator: var TMemRegion, size: int): pointer =
-  result = rawAlloc(allocator, size+sizeof(TFreeCell))
-  cast[ptr TFreeCell](result).zeroField = 1 # mark it as used
+proc alloc(allocator: var MemRegion, size: Natural): pointer =
+  result = rawAlloc(allocator, size+sizeof(FreeCell))
+  cast[ptr FreeCell](result).zeroField = 1 # mark it as used
   sysAssert(not isAllocatedPtr(allocator, result), "alloc")
-  result = cast[pointer](cast[ByteAddress](result) +% sizeof(TFreeCell))
+  result = cast[pointer](cast[ByteAddress](result) +% sizeof(FreeCell))
 
-proc alloc0(allocator: var TMemRegion, size: int): pointer =
+proc alloc0(allocator: var MemRegion, size: Natural): pointer =
   result = alloc(allocator, size)
   zeroMem(result, size)
 
-proc dealloc(allocator: var TMemRegion, p: pointer) =
+proc dealloc(allocator: var MemRegion, p: pointer) =
   sysAssert(p != nil, "dealloc 0")
-  var x = cast[pointer](cast[ByteAddress](p) -% sizeof(TFreeCell))
+  var x = cast[pointer](cast[ByteAddress](p) -% sizeof(FreeCell))
   sysAssert(x != nil, "dealloc 1")
   sysAssert(isAccessible(allocator, x), "is not accessible")
-  sysAssert(cast[ptr TFreeCell](x).zeroField == 1, "dealloc 2")
+  sysAssert(cast[ptr FreeCell](x).zeroField == 1, "dealloc 2")
   rawDealloc(allocator, x)
   sysAssert(not isAllocatedPtr(allocator, x), "dealloc 3")
 
-proc realloc(allocator: var TMemRegion, p: pointer, newsize: int): pointer =
+proc realloc(allocator: var MemRegion, p: pointer, newsize: Natural): pointer =
   if newsize > 0:
     result = alloc0(allocator, newsize)
     if p != nil:
@@ -739,11 +808,11 @@ proc realloc(allocator: var TMemRegion, p: pointer, newsize: int): pointer =
   elif p != nil:
     dealloc(allocator, p)
 
-proc deallocOsPages(a: var TMemRegion) =
+proc deallocOsPages(a: var MemRegion) =
   # we free every 'ordinarily' allocated page by iterating over the page bits:
   for p in elements(a.chunkStarts):
     var page = cast[PChunk](p shl PageShift)
-    when not weirdUnmap:
+    when not doNotUnmap:
       var size = if page.size < PageSize: PageSize else: page.size
       osDeallocPages(page, size)
     else:
@@ -756,9 +825,9 @@ proc deallocOsPages(a: var TMemRegion) =
   # And then we free the pages that are in use for the page bits:
   llDeallocAll(a)
 
-proc getFreeMem(a: TMemRegion): int {.inline.} = result = a.freeMem
-proc getTotalMem(a: TMemRegion): int {.inline.} = result = a.currMem
-proc getOccupiedMem(a: TMemRegion): int {.inline.} = 
+proc getFreeMem(a: MemRegion): int {.inline.} = result = a.freeMem
+proc getTotalMem(a: MemRegion): int {.inline.} = result = a.currMem
+proc getOccupiedMem(a: MemRegion): int {.inline.} =
   result = a.currMem - a.freeMem
 
 # ---------------------- thread memory region -------------------------------
@@ -769,21 +838,21 @@ template instantiateForRegion(allocator: expr) =
       result = interiorAllocatedPtr(allocator, p)
 
     proc isAllocatedPtr*(p: pointer): bool =
-      let p = cast[pointer](cast[ByteAddress](p)-%ByteAddress(sizeof(TCell)))
+      let p = cast[pointer](cast[ByteAddress](p)-%ByteAddress(sizeof(Cell)))
       result = isAllocatedPtr(allocator, p)
 
   proc deallocOsPages = deallocOsPages(allocator)
 
-  proc alloc(size: int): pointer =
+  proc alloc(size: Natural): pointer =
     result = alloc(allocator, size)
 
-  proc alloc0(size: int): pointer =
+  proc alloc0(size: Natural): pointer =
     result = alloc0(allocator, size)
 
   proc dealloc(p: pointer) =
     dealloc(allocator, p)
 
-  proc realloc(p: pointer, newsize: int): pointer =
+  proc realloc(p: pointer, newsize: Natural): pointer =
     result = realloc(allocator, p, newSize)
 
   when false:
@@ -794,7 +863,7 @@ template instantiateForRegion(allocator: expr) =
         inc(result, it.size)
         it = it.next
 
-  proc getFreeMem(): int = 
+  proc getFreeMem(): int =
     result = allocator.freeMem
     #sysAssert(result == countFreeMem())
 
@@ -803,11 +872,11 @@ template instantiateForRegion(allocator: expr) =
 
   # -------------------- shared heap region ----------------------------------
   when hasThreadSupport:
-    var sharedHeap: TMemRegion
-    var heapLock: TSysLock
+    var sharedHeap: MemRegion
+    var heapLock: SysLock
     initSysLock(heapLock)
 
-  proc allocShared(size: int): pointer =
+  proc allocShared(size: Natural): pointer =
     when hasThreadSupport:
       acquireSys(heapLock)
       result = alloc(sharedHeap, size)
@@ -815,20 +884,20 @@ template instantiateForRegion(allocator: expr) =
     else:
       result = alloc(size)
 
-  proc allocShared0(size: int): pointer =
+  proc allocShared0(size: Natural): pointer =
     result = allocShared(size)
     zeroMem(result, size)
 
   proc deallocShared(p: pointer) =
-    when hasThreadSupport: 
+    when hasThreadSupport:
       acquireSys(heapLock)
       dealloc(sharedHeap, p)
       releaseSys(heapLock)
     else:
       dealloc(p)
 
-  proc reallocShared(p: pointer, newsize: int): pointer =
-    when hasThreadSupport: 
+  proc reallocShared(p: pointer, newsize: Natural): pointer =
+    when hasThreadSupport:
       acquireSys(heapLock)
       result = realloc(sharedHeap, p, newsize)
       releaseSys(heapLock)
diff --git a/lib/system/ansi_c.nim b/lib/system/ansi_c.nim
index 9406f26c9..702559034 100644
--- a/lib/system/ansi_c.nim
+++ b/lib/system/ansi_c.nim
@@ -13,20 +13,20 @@
 
 {.push hints:off}
 
-proc c_strcmp(a, b: cstring): cint {.header: "<string.h>", 
+proc c_strcmp(a, b: cstring): cint {.header: "<string.h>",
   noSideEffect, importc: "strcmp".}
-proc c_memcmp(a, b: cstring, size: int): cint {.header: "<string.h>", 
+proc c_memcmp(a, b: cstring, size: int): cint {.header: "<string.h>",
   noSideEffect, importc: "memcmp".}
 proc c_memcpy(a, b: cstring, size: int) {.header: "<string.h>", importc: "memcpy".}
-proc c_strlen(a: cstring): int {.header: "<string.h>", 
+proc c_strlen(a: cstring): int {.header: "<string.h>",
   noSideEffect, importc: "strlen".}
 proc c_memset(p: pointer, value: cint, size: int) {.
   header: "<string.h>", importc: "memset".}
 
 type
-  C_TextFile {.importc: "FILE", header: "<stdio.h>", 
+  C_TextFile {.importc: "FILE", header: "<stdio.h>",
                final, incompleteStruct.} = object
-  C_BinaryFile {.importc: "FILE", header: "<stdio.h>", 
+  C_BinaryFile {.importc: "FILE", header: "<stdio.h>",
                  final, incompleteStruct.} = object
   C_TextFileStar = ptr C_TextFile
   C_BinaryFileStar = ptr C_BinaryFile
@@ -101,15 +101,15 @@ proc c_signal(sig: cint, handler: proc (a: cint) {.noconv.}) {.
   importc: "signal", header: "<signal.h>".}
 proc c_raise(sig: cint) {.importc: "raise", header: "<signal.h>".}
 
-proc c_fputs(c: cstring, f: C_TextFileStar) {.importc: "fputs", 
+proc c_fputs(c: cstring, f: C_TextFileStar) {.importc: "fputs",
   header: "<stdio.h>".}
 proc c_fgets(c: cstring, n: int, f: C_TextFileStar): cstring  {.
   importc: "fgets", header: "<stdio.h>".}
-proc c_fgetc(stream: C_TextFileStar): int {.importc: "fgetc", 
+proc c_fgetc(stream: C_TextFileStar): int {.importc: "fgetc",
   header: "<stdio.h>".}
-proc c_ungetc(c: int, f: C_TextFileStar) {.importc: "ungetc", 
+proc c_ungetc(c: int, f: C_TextFileStar) {.importc: "ungetc",
   header: "<stdio.h>".}
-proc c_putc(c: char, stream: C_TextFileStar) {.importc: "putc", 
+proc c_putc(c: char, stream: C_TextFileStar) {.importc: "putc",
   header: "<stdio.h>".}
 proc c_fprintf(f: C_TextFileStar, frmt: cstring) {.
   importc: "fprintf", header: "<stdio.h>", varargs.}
@@ -120,7 +120,7 @@ proc c_fopen(filename, mode: cstring): C_TextFileStar {.
   importc: "fopen", header: "<stdio.h>".}
 proc c_fclose(f: C_TextFileStar) {.importc: "fclose", header: "<stdio.h>".}
 
-proc c_sprintf(buf, frmt: cstring): cint {.header: "<stdio.h>", 
+proc c_sprintf(buf, frmt: cstring): cint {.header: "<stdio.h>",
   importc: "sprintf", varargs, noSideEffect.}
   # we use it only in a way that cannot lead to security issues
 
@@ -149,7 +149,7 @@ when hostOS != "standalone":
   when not declared(errno):
     when defined(NimrodVM):
       var vmErrnoWrapper {.importc.}: ptr cint
-      template errno: expr = 
+      template errno: expr =
         bind vmErrnoWrapper
         vmErrnoWrapper[]
     else:
diff --git a/lib/system/arithm.nim b/lib/system/arithm.nim
index f68e2dcd9..69c558799 100644
--- a/lib/system/arithm.nim
+++ b/lib/system/arithm.nim
@@ -10,24 +10,121 @@
 
 # simple integer arithmetic with overflow checking
 
-proc raiseOverflow {.compilerproc, noinline, noreturn.} =
+proc raiseOverflow {.compilerproc, noinline.} =
   # a single proc to reduce code size to a minimum
   sysFatal(OverflowError, "over- or underflow")
 
-proc raiseDivByZero {.compilerproc, noinline, noreturn.} =
+proc raiseDivByZero {.compilerproc, noinline.} =
   sysFatal(DivByZeroError, "division by zero")
 
-proc addInt64(a, b: int64): int64 {.compilerProc, inline.} =
-  result = a +% b
-  if (result xor a) >= int64(0) or (result xor b) >= int64(0):
-    return result
-  raiseOverflow()
+when defined(builtinOverflow):
+  # Builtin compiler functions for improved performance
+  when sizeof(clong) == 8:
+    proc addInt64Overflow[T: int64|int](a, b: T, c: var T): bool {.
+      importc: "__builtin_saddl_overflow", nodecl, nosideeffect.}
 
-proc subInt64(a, b: int64): int64 {.compilerProc, inline.} =
-  result = a -% b
-  if (result xor a) >= int64(0) or (result xor not b) >= int64(0):
-    return result
-  raiseOverflow()
+    proc subInt64Overflow[T: int64|int](a, b: T, c: var T): bool {.
+      importc: "__builtin_ssubl_overflow", nodecl, nosideeffect.}
+
+    proc mulInt64Overflow[T: int64|int](a, b: T, c: var T): bool {.
+      importc: "__builtin_smull_overflow", nodecl, nosideeffect.}
+
+  elif sizeof(clonglong) == 8:
+    proc addInt64Overflow[T: int64|int](a, b: T, c: var T): bool {.
+      importc: "__builtin_saddll_overflow", nodecl, nosideeffect.}
+
+    proc subInt64Overflow[T: int64|int](a, b: T, c: var T): bool {.
+      importc: "__builtin_ssubll_overflow", nodecl, nosideeffect.}
+
+    proc mulInt64Overflow[T: int64|int](a, b: T, c: var T): bool {.
+      importc: "__builtin_smulll_overflow", nodecl, nosideeffect.}
+
+  when sizeof(int) == 8:
+    proc addIntOverflow(a, b: int, c: var int): bool {.inline.} =
+      addInt64Overflow(a, b, c)
+
+    proc subIntOverflow(a, b: int, c: var int): bool {.inline.} =
+      subInt64Overflow(a, b, c)
+
+    proc mulIntOverflow(a, b: int, c: var int): bool {.inline.} =
+      mulInt64Overflow(a, b, c)
+
+  elif sizeof(int) == 4 and sizeof(cint) == 4:
+    proc addIntOverflow(a, b: int, c: var int): bool {.
+      importc: "__builtin_sadd_overflow", nodecl, nosideeffect.}
+
+    proc subIntOverflow(a, b: int, c: var int): bool {.
+      importc: "__builtin_ssub_overflow", nodecl, nosideeffect.}
+
+    proc mulIntOverflow(a, b: int, c: var int): bool {.
+      importc: "__builtin_smul_overflow", nodecl, nosideeffect.}
+
+  proc addInt64(a, b: int64): int64 {.compilerProc, inline.} =
+    if addInt64Overflow(a, b, result):
+      raiseOverflow()
+
+  proc subInt64(a, b: int64): int64 {.compilerProc, inline.} =
+    if subInt64Overflow(a, b, result):
+      raiseOverflow()
+
+  proc mulInt64(a, b: int64): int64 {.compilerproc, inline.} =
+    if mulInt64Overflow(a, b, result):
+      raiseOverflow()
+else:
+  proc addInt64(a, b: int64): int64 {.compilerProc, inline.} =
+    result = a +% b
+    if (result xor a) >= int64(0) or (result xor b) >= int64(0):
+      return result
+    raiseOverflow()
+
+  proc subInt64(a, b: int64): int64 {.compilerProc, inline.} =
+    result = a -% b
+    if (result xor a) >= int64(0) or (result xor not b) >= int64(0):
+      return result
+    raiseOverflow()
+
+  #
+  # This code has been inspired by Python's source code.
+  # The native int product x*y is either exactly right or *way* off, being
+  # just the last n bits of the true product, where n is the number of bits
+  # in an int (the delivered product is the true product plus i*2**n for
+  # some integer i).
+  #
+  # The native float64 product x*y is subject to three
+  # rounding errors: on a sizeof(int)==8 box, each cast to double can lose
+  # info, and even on a sizeof(int)==4 box, the multiplication can lose info.
+  # But, unlike the native int product, it's not in *range* trouble:  even
+  # if sizeof(int)==32 (256-bit ints), the product easily fits in the
+  # dynamic range of a float64. So the leading 50 (or so) bits of the float64
+  # product are correct.
+  #
+  # We check these two ways against each other, and declare victory if they're
+  # approximately the same. Else, because the native int product is the only
+  # one that can lose catastrophic amounts of information, it's the native int
+  # product that must have overflowed.
+  #
+  proc mulInt64(a, b: int64): int64 {.compilerproc.} =
+    var
+      resAsFloat, floatProd: float64
+    result = a *% b
+    floatProd = toBiggestFloat(a) # conversion
+    floatProd = floatProd * toBiggestFloat(b)
+    resAsFloat = toBiggestFloat(result)
+
+    # Fast path for normal case: small multiplicands, and no info
+    # is lost in either method.
+    if resAsFloat == floatProd: return result
+
+    # Somebody somewhere lost info. Close enough, or way off? Note
+    # that a != 0 and b != 0 (else resAsFloat == floatProd == 0).
+    # The difference either is or isn't significant compared to the
+    # true value (of which floatProd is a good approximation).
+
+    # abs(diff)/abs(prod) <= 1/32 iff
+    #   32 * abs(diff) <= abs(prod) -- 5 good bits is "close enough"
+    if 32.0 * abs(resAsFloat - floatProd) <= abs(floatProd):
+      return result
+    raiseOverflow()
 
 proc negInt64(a: int64): int64 {.compilerProc, inline.} =
   if a != low(int64): return -a
@@ -51,50 +148,6 @@ proc modInt64(a, b: int64): int64 {.compilerProc, inline.} =
     raiseDivByZero()
   return a mod b
 
-#
-# This code has been inspired by Python's source code.
-# The native int product x*y is either exactly right or *way* off, being
-# just the last n bits of the true product, where n is the number of bits
-# in an int (the delivered product is the true product plus i*2**n for
-# some integer i).
-#
-# The native float64 product x*y is subject to three
-# rounding errors: on a sizeof(int)==8 box, each cast to double can lose
-# info, and even on a sizeof(int)==4 box, the multiplication can lose info.
-# But, unlike the native int product, it's not in *range* trouble:  even
-# if sizeof(int)==32 (256-bit ints), the product easily fits in the
-# dynamic range of a float64. So the leading 50 (or so) bits of the float64
-# product are correct.
-#
-# We check these two ways against each other, and declare victory if they're
-# approximately the same. Else, because the native int product is the only
-# one that can lose catastrophic amounts of information, it's the native int
-# product that must have overflowed.
-#
-proc mulInt64(a, b: int64): int64 {.compilerproc.} =
-  var
-    resAsFloat, floatProd: float64
-  result = a *% b
-  floatProd = toBiggestFloat(a) # conversion
-  floatProd = floatProd * toBiggestFloat(b)
-  resAsFloat = toBiggestFloat(result)
-
-  # Fast path for normal case: small multiplicands, and no info
-  # is lost in either method.
-  if resAsFloat == floatProd: return result
-
-  # Somebody somewhere lost info. Close enough, or way off? Note
-  # that a != 0 and b != 0 (else resAsFloat == floatProd == 0).
-  # The difference either is or isn't significant compared to the
-  # true value (of which floatProd is a good approximation).
-
-  # abs(diff)/abs(prod) <= 1/32 iff
-  #   32 * abs(diff) <= abs(prod) -- 5 good bits is "close enough"
-  if 32.0 * abs(resAsFloat - floatProd) <= abs(floatProd):
-    return result
-  raiseOverflow()
-
-
 proc absInt(a: int): int {.compilerProc, inline.} =
   if a != low(int):
     if a >= 0: return a
@@ -246,6 +299,21 @@ elif false: # asmVersion and (defined(gcc) or defined(llvm_gcc)):
             :"%edx"
     """
 
+when not declared(addInt) and defined(builtinOverflow):
+  proc addInt(a, b: int): int {.compilerProc, inline.} =
+    if addIntOverflow(a, b, result):
+      raiseOverflow()
+
+when not declared(subInt) and defined(builtinOverflow):
+  proc subInt(a, b: int): int {.compilerProc, inline.} =
+    if subIntOverflow(a, b, result):
+      raiseOverflow()
+
+when not declared(mulInt) and defined(builtinOverflow):
+  proc mulInt(a, b: int): int {.compilerProc, inline.} =
+    if mulIntOverflow(a, b, result):
+      raiseOverflow()
+
 # Platform independent versions of the above (slower!)
 when not declared(addInt):
   proc addInt(a, b: int): int {.compilerProc, inline.} =
@@ -327,13 +395,13 @@ when not declared(mulInt):
 # We avoid setting the FPU control word here for compatibility with libraries
 # written in other languages.
 
-proc raiseFloatInvalidOp {.noinline, noreturn.} =
+proc raiseFloatInvalidOp {.noinline.} =
   sysFatal(FloatInvalidOpError, "FPU operation caused a NaN result")
 
 proc nanCheck(x: float64) {.compilerProc, inline.} =
   if x != x: raiseFloatInvalidOp()
 
-proc raiseFloatOverflow(x: float64) {.noinline, noreturn.} =
+proc raiseFloatOverflow(x: float64) {.noinline.} =
   if x > 0.0:
     sysFatal(FloatOverflowError, "FPU operation caused an overflow")
   else:
diff --git a/lib/system/assign.nim b/lib/system/assign.nim
index 78995954f..55d7572e2 100644
--- a/lib/system/assign.nim
+++ b/lib/system/assign.nim
@@ -17,7 +17,7 @@ proc genericAssignAux(dest, src: pointer, n: ptr TNimNode,
     s = cast[ByteAddress](src)
   case n.kind
   of nkSlot:
-    genericAssignAux(cast[pointer](d +% n.offset), 
+    genericAssignAux(cast[pointer](d +% n.offset),
                      cast[pointer](s +% n.offset), n.typ, shallow)
   of nkList:
     for i in 0..n.len-1:
@@ -54,7 +54,7 @@ proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) =
       unsureAsgnRef(x, copyString(cast[NimString](s2)))
   of tySequence:
     var s2 = cast[PPointer](src)[]
-    var seq = cast[PGenericSeq](s2)      
+    var seq = cast[PGenericSeq](s2)
     var x = cast[PPointer](dest)
     if s2 == nil or shallow or (seq.reserved and seqShallowFlag) != 0:
       # this can happen! nil sequences are allowed
@@ -100,7 +100,7 @@ proc genericShallowAssign(dest, src: pointer, mt: PNimType) {.compilerProc.} =
 
 when false:
   proc debugNimType(t: PNimType) =
-    if t.isNil: 
+    if t.isNil:
       cprintf("nil!")
       return
     var k: cstring
@@ -170,21 +170,13 @@ proc objectInit(dest: pointer, typ: PNimType) =
     for i in 0..(typ.size div typ.base.size)-1:
       objectInit(cast[pointer](d +% i * typ.base.size), typ.base)
   else: discard # nothing to do
-  
+
 # ---------------------- assign zero -----------------------------------------
 
-when not defined(nimmixin):
-  proc destroy(x: int) = discard
-  proc nimDestroyRange*[T](r: T) =
-    # internal proc used for destroying sequences and arrays
-    for i in countup(0, r.len - 1): destroy(r[i])
-else:
-  # XXX Why is this exported and no compilerproc? -> compilerprocs cannot be
-  # generic for now
-  proc nimDestroyRange*[T](r: T) =
-    # internal proc used for destroying sequences and arrays
-    mixin destroy
-    for i in countup(0, r.len - 1): destroy(r[i])
+proc nimDestroyRange[T](r: T) {.compilerProc.} =
+  # internal proc used for destroying sequences and arrays
+  mixin `=destroy`
+  for i in countup(0, r.len - 1): `=destroy`(r[i])
 
 proc genericReset(dest: pointer, mt: PNimType) {.compilerProc, benign.}
 proc genericResetAux(dest: pointer, n: ptr TNimNode) =
@@ -198,7 +190,7 @@ proc genericResetAux(dest: pointer, n: ptr TNimNode) =
     var m = selectBranch(dest, n)
     if m != nil: genericResetAux(dest, m)
     zeroMem(cast[pointer](d +% n.offset), n.typ.size)
-  
+
 proc genericReset(dest: pointer, mt: PNimType) =
   var d = cast[ByteAddress](dest)
   sysAssert(mt != nil, "genericReset 2")
@@ -218,15 +210,15 @@ proc genericReset(dest: pointer, mt: PNimType) =
   else:
     zeroMem(dest, mt.size) # set raw bits to zero
 
-proc selectBranch(discVal, L: int, 
+proc selectBranch(discVal, L: int,
                   a: ptr array [0..0x7fff, ptr TNimNode]): ptr TNimNode =
   result = a[L] # a[L] contains the ``else`` part (but may be nil)
   if discVal <% L:
     var x = a[discVal]
     if x != nil: result = x
-  
-proc FieldDiscriminantCheck(oldDiscVal, newDiscVal: int, 
-                            a: ptr array [0..0x7fff, ptr TNimNode], 
+
+proc FieldDiscriminantCheck(oldDiscVal, newDiscVal: int,
+                            a: ptr array [0..0x7fff, ptr TNimNode],
                             L: int) {.compilerProc.} =
   var oldBranch = selectBranch(oldDiscVal, L, a)
   var newBranch = selectBranch(newDiscVal, L, a)
diff --git a/lib/system/atomics.nim b/lib/system/atomics.nim
index 300fa85f3..158fe91bc 100644
--- a/lib/system/atomics.nim
+++ b/lib/system/atomics.nim
@@ -37,39 +37,40 @@ when someGcc and hasThreadSupport:
     ## and release stores in all threads.
 
   type
-    TAtomType* = SomeNumber|pointer|ptr|char|bool
+    AtomType* = SomeNumber|pointer|ptr|char|bool
       ## Type Class representing valid types for use with atomic procs
+  {.deprecated: [TAtomType: AtomType].}
 
-  proc atomicLoadN*[T: TAtomType](p: ptr T, mem: AtomMemModel): T {.
+  proc atomicLoadN*[T: AtomType](p: ptr T, mem: AtomMemModel): T {.
     importc: "__atomic_load_n", nodecl.}
     ## This proc implements an atomic load operation. It returns the contents at p.
     ## ATOMIC_RELAXED, ATOMIC_SEQ_CST, ATOMIC_ACQUIRE, ATOMIC_CONSUME.
 
-  proc atomicLoad*[T: TAtomType](p, ret: ptr T, mem: AtomMemModel) {.
+  proc atomicLoad*[T: AtomType](p, ret: ptr T, mem: AtomMemModel) {.
     importc: "__atomic_load", nodecl.}
     ## This is the generic version of an atomic load. It returns the contents at p in ret.
 
-  proc atomicStoreN*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel) {.
+  proc atomicStoreN*[T: AtomType](p: ptr T, val: T, mem: AtomMemModel) {.
     importc: "__atomic_store_n", nodecl.}
     ## This proc implements an atomic store operation. It writes val at p.
     ## ATOMIC_RELAXED, ATOMIC_SEQ_CST, and ATOMIC_RELEASE.
 
-  proc atomicStore*[T: TAtomType](p, val: ptr T, mem: AtomMemModel) {.
+  proc atomicStore*[T: AtomType](p, val: ptr T, mem: AtomMemModel) {.
     importc: "__atomic_store", nodecl.}
     ## This is the generic version of an atomic store. It stores the value of val at p
 
-  proc atomicExchangeN*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
+  proc atomicExchangeN*[T: AtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
     importc: "__atomic_exchange_n", nodecl.}
     ## This proc implements an atomic exchange operation. It writes val at p,
     ## and returns the previous contents at p.
     ## ATOMIC_RELAXED, ATOMIC_SEQ_CST, ATOMIC_ACQUIRE, ATOMIC_RELEASE, ATOMIC_ACQ_REL
 
-  proc atomicExchange*[T: TAtomType](p, val, ret: ptr T, mem: AtomMemModel) {.
+  proc atomicExchange*[T: AtomType](p, val, ret: ptr T, mem: AtomMemModel) {.
     importc: "__atomic_exchange", nodecl.}
     ## This is the generic version of an atomic exchange. It stores the contents at val at p.
     ## The original value at p is copied into ret.
 
-  proc atomicCompareExchangeN*[T: TAtomType](p, expected: ptr T, desired: T,
+  proc atomicCompareExchangeN*[T: AtomType](p, expected: ptr T, desired: T,
     weak: bool, success_memmodel: AtomMemModel, failure_memmodel: AtomMemModel): bool {.
     importc: "__atomic_compare_exchange_n ", nodecl.}
     ## This proc implements an atomic compare and exchange operation. This compares the
@@ -85,39 +86,39 @@ when someGcc and hasThreadSupport:
     ## cannot be __ATOMIC_RELEASE nor __ATOMIC_ACQ_REL. It also cannot be a stronger model
     ## than that specified by success_memmodel.
 
-  proc atomicCompareExchange*[T: TAtomType](p, expected, desired: ptr T,
+  proc atomicCompareExchange*[T: AtomType](p, expected, desired: ptr T,
     weak: bool, success_memmodel: AtomMemModel, failure_memmodel: AtomMemModel): bool {.
-    importc: "__atomic_compare_exchange_n ", nodecl.}
+    importc: "__atomic_compare_exchange", nodecl.}
     ## This proc implements the generic version of atomic_compare_exchange.
     ## The proc is virtually identical to atomic_compare_exchange_n, except the desired
     ## value is also a pointer.
 
   ## Perform the operation return the new value, all memory models are valid
-  proc atomicAddFetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
+  proc atomicAddFetch*[T: AtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
     importc: "__atomic_add_fetch", nodecl.}
-  proc atomicSubFetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
+  proc atomicSubFetch*[T: AtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
     importc: "__atomic_sub_fetch", nodecl.}
-  proc atomicOrFetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
+  proc atomicOrFetch*[T: AtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
     importc: "__atomic_or_fetch ", nodecl.}
-  proc atomicAndFetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
+  proc atomicAndFetch*[T: AtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
     importc: "__atomic_and_fetch", nodecl.}
-  proc atomicXorFetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
+  proc atomicXorFetch*[T: AtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
     importc: "__atomic_xor_fetch", nodecl.}
-  proc atomicNandFetch*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
+  proc atomicNandFetch*[T: AtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
     importc: "__atomic_nand_fetch ", nodecl.}
 
   ## Perform the operation return the old value, all memory models are valid
-  proc atomicFetchAdd*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
+  proc atomicFetchAdd*[T: AtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
     importc: "__atomic_fetch_add", nodecl.}
-  proc atomicFetchSub*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
+  proc atomicFetchSub*[T: AtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
     importc: "__atomic_fetch_sub", nodecl.}
-  proc atomicFetchOr*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
+  proc atomicFetchOr*[T: AtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
     importc: "__atomic_fetch_or", nodecl.}
-  proc atomicFetchAnd*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
+  proc atomicFetchAnd*[T: AtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
     importc: "__atomic_fetch_and", nodecl.}
-  proc atomicFetchXor*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
+  proc atomicFetchXor*[T: AtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
     importc: "__atomic_fetch_xor", nodecl.}
-  proc atomicFetchNand*[T: TAtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
+  proc atomicFetchNand*[T: AtomType](p: ptr T, val: T, mem: AtomMemModel): T {.
     importc: "__atomic_fetch_nand", nodecl.}
 
   proc atomicTestAndSet*(p: pointer, mem: AtomMemModel): bool {.
@@ -190,11 +191,11 @@ proc atomicDec*(memLoc: var int, x: int = 1): int =
     result = memLoc
 
 when defined(windows) and not someGcc:
-  proc interlockedCompareExchange(p: pointer; exchange, comparand: int32): int32
+  proc interlockedCompareExchange(p: pointer; exchange, comparand: int): int
     {.importc: "InterlockedCompareExchange", header: "<windows.h>", cdecl.}
 
   proc cas*[T: bool|int|ptr](p: ptr T; oldValue, newValue: T): bool =
-    interlockedCompareExchange(p, newValue.int32, oldValue.int32) != 0
+    interlockedCompareExchange(p, cast[int](newValue), cast[int](oldValue)) != 0
   # XXX fix for 64 bit build
 else:
   # this is valid for GCC and Intel C++
diff --git a/lib/system/avltree.nim b/lib/system/avltree.nim
index 292097062..d5c901542 100644
--- a/lib/system/avltree.nim
+++ b/lib/system/avltree.nim
@@ -16,7 +16,7 @@ proc lowGauge(n: PAvlNode): int =
   while not isBottom(it):
     result = it.key
     it = it.link[0]
-  
+
 proc highGauge(n: PAvlNode): int =
   result = -1
   var it = n
@@ -24,7 +24,7 @@ proc highGauge(n: PAvlNode): int =
     result = it.upperBound
     it = it.link[1]
 
-proc find(root: PAvlNode, key: int): PAvlNode = 
+proc find(root: PAvlNode, key: int): PAvlNode =
   var it = root
   while not isBottom(it):
     if it.key == key: return it
@@ -51,7 +51,7 @@ proc split(t: var PAvlNode) =
     t.link[0] = temp
     inc t.level
 
-proc add(a: var TMemRegion, t: var PAvlNode, key, upperBound: int) {.benign.} =
+proc add(a: var MemRegion, t: var PAvlNode, key, upperBound: int) {.benign.} =
   if t == bottom:
     t = allocAvlNode(a, key, upperBound)
   else:
@@ -64,7 +64,7 @@ proc add(a: var TMemRegion, t: var PAvlNode, key, upperBound: int) {.benign.} =
     skew(t)
     split(t)
 
-proc del(a: var TMemRegion, t: var PAvlNode, x: int) {.benign.} =
+proc del(a: var MemRegion, t: var PAvlNode, x: int) {.benign.} =
   if t == bottom: return
   a.last = t
   if x <% t.key:
diff --git a/lib/system/cellsets.nim b/lib/system/cellsets.nim
index 0e3a01eba..bb5de6f42 100644
--- a/lib/system/cellsets.nim
+++ b/lib/system/cellsets.nim
@@ -10,10 +10,10 @@
 # Efficient set of pointers for the GC (and repr)
 
 type
-  TRefCount = int
+  RefCount = int
 
-  TCell {.pure.} = object
-    refcount: TRefCount  # the refcount and some flags
+  Cell {.pure.} = object
+    refcount: RefCount  # the refcount and some flags
     typ: PNimType
     when trackAllocationSource:
       filename: cstring
@@ -21,34 +21,35 @@ type
     when useCellIds:
       id: int
 
-  PCell = ptr TCell
+  PCell = ptr Cell
 
-  PPageDesc = ptr TPageDesc
-  TBitIndex = range[0..UnitsPerPage-1]
-  TPageDesc {.final, pure.} = object
+  PPageDesc = ptr PageDesc
+  BitIndex = range[0..UnitsPerPage-1]
+  PageDesc {.final, pure.} = object
     next: PPageDesc # all nodes are connected with this pointer
     key: ByteAddress   # start address at bit 0
-    bits: array[TBitIndex, int] # a bit vector
+    bits: array[BitIndex, int] # a bit vector
 
   PPageDescArray = ptr array[0..1000_000, PPageDesc]
-  TCellSet {.final, pure.} = object
+  CellSet {.final, pure.} = object
     counter, max: int
     head: PPageDesc
     data: PPageDescArray
 
   PCellArray = ptr array[0..100_000_000, PCell]
-  TCellSeq {.final, pure.} = object
+  CellSeq {.final, pure.} = object
     len, cap: int
     d: PCellArray
-
+{.deprecated: [TCell: Cell, TBitIndex: BitIndex, TPageDesc: PageDesc,
+              TRefCount: RefCount, TCellSet: CellSet, TCellSeq: CellSeq].}
 # ------------------- cell seq handling ---------------------------------------
 
-proc contains(s: TCellSeq, c: PCell): bool {.inline.} =
+proc contains(s: CellSeq, c: PCell): bool {.inline.} =
   for i in 0 .. s.len-1:
     if s.d[i] == c: return true
   return false
 
-proc add(s: var TCellSeq, c: PCell) {.inline.} =
+proc add(s: var CellSeq, c: PCell) {.inline.} =
   if s.len >= s.cap:
     s.cap = s.cap * 3 div 2
     var d = cast[PCellArray](alloc(s.cap * sizeof(PCell)))
@@ -59,12 +60,12 @@ proc add(s: var TCellSeq, c: PCell) {.inline.} =
   s.d[s.len] = c
   inc(s.len)
 
-proc init(s: var TCellSeq, cap: int = 1024) =
+proc init(s: var CellSeq, cap: int = 1024) =
   s.len = 0
   s.cap = cap
   s.d = cast[PCellArray](alloc0(cap * sizeof(PCell)))
 
-proc deinit(s: var TCellSeq) = 
+proc deinit(s: var CellSeq) =
   dealloc(s.d)
   s.d = nil
   s.len = 0
@@ -75,13 +76,13 @@ proc deinit(s: var TCellSeq) =
 const
   InitCellSetSize = 1024 # must be a power of two!
 
-proc init(s: var TCellSet) =
+proc init(s: var CellSet) =
   s.data = cast[PPageDescArray](alloc0(InitCellSetSize * sizeof(PPageDesc)))
   s.max = InitCellSetSize-1
   s.counter = 0
   s.head = nil
 
-proc deinit(s: var TCellSet) =
+proc deinit(s: var CellSet) =
   var it = s.head
   while it != nil:
     var n = it.next
@@ -97,15 +98,15 @@ proc nextTry(h, maxHash: int): int {.inline.} =
   # For any initial h in range(maxHash), repeating that maxHash times
   # generates each int in range(maxHash) exactly once (see any text on
   # random-number generation for proof).
-  
-proc cellSetGet(t: TCellSet, key: ByteAddress): PPageDesc =
+
+proc cellSetGet(t: CellSet, key: ByteAddress): PPageDesc =
   var h = cast[int](key) and t.max
   while t.data[h] != nil:
     if t.data[h].key == key: return t.data[h]
     h = nextTry(h, t.max)
   return nil
 
-proc cellSetRawInsert(t: TCellSet, data: PPageDescArray, desc: PPageDesc) =
+proc cellSetRawInsert(t: CellSet, data: PPageDescArray, desc: PPageDesc) =
   var h = cast[int](desc.key) and t.max
   while data[h] != nil:
     sysAssert(data[h] != desc, "CellSetRawInsert 1")
@@ -113,7 +114,7 @@ proc cellSetRawInsert(t: TCellSet, data: PPageDescArray, desc: PPageDesc) =
   sysAssert(data[h] == nil, "CellSetRawInsert 2")
   data[h] = desc
 
-proc cellSetEnlarge(t: var TCellSet) =
+proc cellSetEnlarge(t: var CellSet) =
   var oldMax = t.max
   t.max = ((t.max+1)*2)-1
   var n = cast[PPageDescArray](alloc0((t.max + 1) * sizeof(PPageDesc)))
@@ -123,7 +124,7 @@ proc cellSetEnlarge(t: var TCellSet) =
   dealloc(t.data)
   t.data = n
 
-proc cellSetPut(t: var TCellSet, key: ByteAddress): PPageDesc =
+proc cellSetPut(t: var CellSet, key: ByteAddress): PPageDesc =
   var h = cast[int](key) and t.max
   while true:
     var x = t.data[h]
@@ -138,7 +139,7 @@ proc cellSetPut(t: var TCellSet, key: ByteAddress): PPageDesc =
   while t.data[h] != nil: h = nextTry(h, t.max)
   sysAssert(t.data[h] == nil, "CellSetPut")
   # the new page descriptor goes into result
-  result = cast[PPageDesc](alloc0(sizeof(TPageDesc)))
+  result = cast[PPageDesc](alloc0(sizeof(PageDesc)))
   result.next = t.head
   result.key = key
   t.head = result
@@ -146,7 +147,7 @@ proc cellSetPut(t: var TCellSet, key: ByteAddress): PPageDesc =
 
 # ---------- slightly higher level procs --------------------------------------
 
-proc contains(s: TCellSet, cell: PCell): bool =
+proc contains(s: CellSet, cell: PCell): bool =
   var u = cast[ByteAddress](cell)
   var t = cellSetGet(s, u shr PageShift)
   if t != nil:
@@ -155,13 +156,13 @@ proc contains(s: TCellSet, cell: PCell): bool =
   else:
     result = false
 
-proc incl(s: var TCellSet, cell: PCell) {.noinline.} =
+proc incl(s: var CellSet, cell: PCell) {.noinline.} =
   var u = cast[ByteAddress](cell)
   var t = cellSetPut(s, u shr PageShift)
   u = (u %% PageSize) /% MemAlign
   t.bits[u shr IntShift] = t.bits[u shr IntShift] or (1 shl (u and IntMask))
 
-proc excl(s: var TCellSet, cell: PCell) =
+proc excl(s: var CellSet, cell: PCell) =
   var u = cast[ByteAddress](cell)
   var t = cellSetGet(s, u shr PageShift)
   if t != nil:
@@ -169,20 +170,20 @@ proc excl(s: var TCellSet, cell: PCell) =
     t.bits[u shr IntShift] = (t.bits[u shr IntShift] and
                               not (1 shl (u and IntMask)))
 
-proc containsOrIncl(s: var TCellSet, cell: PCell): bool = 
+proc containsOrIncl(s: var CellSet, cell: PCell): bool =
   var u = cast[ByteAddress](cell)
   var t = cellSetGet(s, u shr PageShift)
   if t != nil:
     u = (u %% PageSize) /% MemAlign
     result = (t.bits[u shr IntShift] and (1 shl (u and IntMask))) != 0
-    if not result: 
+    if not result:
       t.bits[u shr IntShift] = t.bits[u shr IntShift] or
           (1 shl (u and IntMask))
-  else: 
+  else:
     incl(s, cell)
     result = false
 
-iterator elements(t: TCellSet): PCell {.inline.} =
+iterator elements(t: CellSet): PCell {.inline.} =
   # while traversing it is forbidden to add pointers to the tree!
   var r = t.head
   while r != nil:
@@ -200,7 +201,7 @@ iterator elements(t: TCellSet): PCell {.inline.} =
       inc(i)
     r = r.next
 
-iterator elementsExcept(t, s: TCellSet): PCell {.inline.} =
+iterator elementsExcept(t, s: CellSet): PCell {.inline.} =
   var r = t.head
   while r != nil:
     let ss = cellSetGet(s, r.key)
diff --git a/lib/system/cgprocs.nim b/lib/system/cgprocs.nim
index f3acc81f2..660c68116 100644
--- a/lib/system/cgprocs.nim
+++ b/lib/system/cgprocs.nim
@@ -9,17 +9,13 @@
 
 # Headers for procs that the code generator depends on ("compilerprocs")
 
-proc addChar(s: NimString, c: char): NimString {.compilerProc, benign.}
-
 type
-  TLibHandle = pointer       # private type
-  TProcAddr = pointer        # library loading and loading of procs:
+  LibHandle = pointer       # private type
+  ProcAddr = pointer        # library loading and loading of procs:
+{.deprecated: [TLibHandle: LibHandle, TProcAddr: ProcAddr].}
 
-proc nimLoadLibrary(path: string): TLibHandle {.compilerproc.}
-proc nimUnloadLibrary(lib: TLibHandle) {.compilerproc.}
-proc nimGetProcAddr(lib: TLibHandle, name: cstring): TProcAddr {.compilerproc.}
+proc nimLoadLibrary(path: string): LibHandle {.compilerproc.}
+proc nimUnloadLibrary(lib: LibHandle) {.compilerproc.}
+proc nimGetProcAddr(lib: LibHandle, name: cstring): ProcAddr {.compilerproc.}
 
 proc nimLoadLibraryError(path: string) {.compilerproc, noinline.}
-
-proc setStackBottom(theStackBottom: pointer) {.compilerRtl, noinline, benign.}
-
diff --git a/lib/system/channels.nim b/lib/system/channels.nim
index ebd30c353..68c0e32d2 100644
--- a/lib/system/channels.nim
+++ b/lib/system/channels.nim
@@ -1,265 +1,267 @@
-#

-#

-#            Nim's Runtime Library

+#
+#
+#            Nim's Runtime Library
 #        (c) Copyright 2015 Andreas Rumpf
-#

-#    See the file "copying.txt", included in this

-#    distribution, for details about the copyright.

-#

-

-## Channel support for threads. **Note**: This is part of the system module.

-## Do not import it directly. To activate thread support you need to compile

-## with the ``--threads:on`` command line switch.

-##

-## **Note:** The current implementation of message passing is slow and does

-## not work with cyclic data structures.

-  

-when not declared(NimString):

-  {.error: "You must not import this module explicitly".}

-

-type

-  pbytes = ptr array[0.. 0xffff, byte]

-  TRawChannel {.pure, final.} = object ## msg queue for a thread

-    rd, wr, count, mask: int

-    data: pbytes

-    lock: TSysLock

-    cond: TSysCond

-    elemType: PNimType

-    ready: bool

-    region: TMemRegion

-  PRawChannel = ptr TRawChannel

-  TLoadStoreMode = enum mStore, mLoad

-  TChannel* {.gcsafe.}[TMsg] = TRawChannel ## a channel for thread communication

-

-const ChannelDeadMask = -2

-

-proc initRawChannel(p: pointer) =

-  var c = cast[PRawChannel](p)

-  initSysLock(c.lock)

-  initSysCond(c.cond)

-  c.mask = -1

-

-proc deinitRawChannel(p: pointer) =

-  var c = cast[PRawChannel](p)

-  # we need to grab the lock to be safe against sending threads!

-  acquireSys(c.lock)

-  c.mask = ChannelDeadMask

-  deallocOsPages(c.region)

-  deinitSys(c.lock)

-  deinitSysCond(c.cond)

-

-proc storeAux(dest, src: pointer, mt: PNimType, t: PRawChannel, 

-              mode: TLoadStoreMode) {.benign.}

-proc storeAux(dest, src: pointer, n: ptr TNimNode, t: PRawChannel,

-              mode: TLoadStoreMode) {.benign.} =

-  var

-    d = cast[ByteAddress](dest)

-    s = cast[ByteAddress](src)

-  case n.kind

-  of nkSlot: storeAux(cast[pointer](d +% n.offset), 

-                      cast[pointer](s +% n.offset), n.typ, t, mode)

-  of nkList:

-    for i in 0..n.len-1: storeAux(dest, src, n.sons[i], t, mode)

-  of nkCase:

-    copyMem(cast[pointer](d +% n.offset), cast[pointer](s +% n.offset),

-            n.typ.size)

-    var m = selectBranch(src, n)

-    if m != nil: storeAux(dest, src, m, t, mode)

-  of nkNone: sysAssert(false, "storeAux")

-

-proc storeAux(dest, src: pointer, mt: PNimType, t: PRawChannel, 

-              mode: TLoadStoreMode) =

-  var

-    d = cast[ByteAddress](dest)

-    s = cast[ByteAddress](src)

-  sysAssert(mt != nil, "mt == nil")

-  case mt.kind

-  of tyString:

-    if mode == mStore:

-      var x = cast[PPointer](dest)

-      var s2 = cast[PPointer](s)[]

-      if s2 == nil: 

-        x[] = nil

-      else:

-        var ss = cast[NimString](s2)

-        var ns = cast[NimString](alloc(t.region, ss.len+1 + GenericSeqSize))

-        copyMem(ns, ss, ss.len+1 + GenericSeqSize)

-        x[] = ns

-    else:

-      var x = cast[PPointer](dest)

-      var s2 = cast[PPointer](s)[]

-      if s2 == nil:

-        unsureAsgnRef(x, s2)

-      else:

-        unsureAsgnRef(x, copyString(cast[NimString](s2)))

-        dealloc(t.region, s2)

-  of tySequence:

-    var s2 = cast[PPointer](src)[]

-    var seq = cast[PGenericSeq](s2)

-    var x = cast[PPointer](dest)

-    if s2 == nil:

-      if mode == mStore:

-        x[] = nil

-      else:

-        unsureAsgnRef(x, nil)

-    else:

-      sysAssert(dest != nil, "dest == nil")

-      if mode == mStore:

-        x[] = alloc(t.region, seq.len *% mt.base.size +% GenericSeqSize)

-      else:

-        unsureAsgnRef(x, newObj(mt, seq.len * mt.base.size + GenericSeqSize))

-      var dst = cast[ByteAddress](cast[PPointer](dest)[])

-      for i in 0..seq.len-1:

-        storeAux(

-          cast[pointer](dst +% i*% mt.base.size +% GenericSeqSize),

-          cast[pointer](cast[ByteAddress](s2) +% i *% mt.base.size +%

-                        GenericSeqSize),

-          mt.base, t, mode)

-      var dstseq = cast[PGenericSeq](dst)

-      dstseq.len = seq.len

-      dstseq.reserved = seq.len

-      if mode != mStore: dealloc(t.region, s2)

-  of tyObject:

-    # copy type field:

-    var pint = cast[ptr PNimType](dest)

-    # XXX use dynamic type here!

-    pint[] = mt

-    if mt.base != nil:

-      storeAux(dest, src, mt.base, t, mode)

-    storeAux(dest, src, mt.node, t, mode)

-  of tyTuple:

-    storeAux(dest, src, mt.node, t, mode)

-  of tyArray, tyArrayConstr:

-    for i in 0..(mt.size div mt.base.size)-1:

-      storeAux(cast[pointer](d +% i*% mt.base.size),

-               cast[pointer](s +% i*% mt.base.size), mt.base, t, mode)

-  of tyRef:

-    var s = cast[PPointer](src)[]

-    var x = cast[PPointer](dest)

-    if s == nil:

-      if mode == mStore:

-        x[] = nil

-      else:

-        unsureAsgnRef(x, nil)

-    else:

-      if mode == mStore:

-        x[] = alloc(t.region, mt.base.size)

-      else:

-        # XXX we should use the dynamic type here too, but that is not stored

-        # in the inbox at all --> use source[]'s object type? but how? we need

-        # a tyRef to the object!

-        var obj = newObj(mt, mt.base.size)

-        unsureAsgnRef(x, obj)

-      storeAux(x[], s, mt.base, t, mode)

-      if mode != mStore: dealloc(t.region, s)

-  else:

-    copyMem(dest, src, mt.size) # copy raw bits

-

-proc rawSend(q: PRawChannel, data: pointer, typ: PNimType) =

-  ## adds an `item` to the end of the queue `q`.

-  var cap = q.mask+1

-  if q.count >= cap:

-    # start with capacity for 2 entries in the queue:

-    if cap == 0: cap = 1

-    var n = cast[pbytes](alloc0(q.region, cap*2*typ.size))

-    var z = 0

-    var i = q.rd

-    var c = q.count

-    while c > 0:

-      dec c

-      copyMem(addr(n[z*typ.size]), addr(q.data[i*typ.size]), typ.size)

-      i = (i + 1) and q.mask

-      inc z

-    if q.data != nil: dealloc(q.region, q.data)

-    q.data = n

-    q.mask = cap*2 - 1

-    q.wr = q.count

-    q.rd = 0

-  storeAux(addr(q.data[q.wr * typ.size]), data, typ, q, mStore)

-  inc q.count

-  q.wr = (q.wr + 1) and q.mask

-

-proc rawRecv(q: PRawChannel, data: pointer, typ: PNimType) =

-  sysAssert q.count > 0, "rawRecv"

-  dec q.count

-  storeAux(data, addr(q.data[q.rd * typ.size]), typ, q, mLoad)

-  q.rd = (q.rd + 1) and q.mask

-

-template lockChannel(q: expr, action: stmt) {.immediate.} =

-  acquireSys(q.lock)

-  action

-  releaseSys(q.lock)

-

-template sendImpl(q: expr) {.immediate.} =  

-  if q.mask == ChannelDeadMask:

-    sysFatal(DeadThreadError, "cannot send message; thread died")

-  acquireSys(q.lock)

-  var m: TMsg

-  shallowCopy(m, msg)

-  var typ = cast[PNimType](getTypeInfo(msg))

-  rawSend(q, addr(m), typ)

-  q.elemType = typ

-  releaseSys(q.lock)

-  signalSysCond(q.cond)

-

-proc send*[TMsg](c: var TChannel[TMsg], msg: TMsg) =

-  ## sends a message to a thread. `msg` is deeply copied.

-  var q = cast[PRawChannel](addr(c))

-  sendImpl(q)

-

-proc llRecv(q: PRawChannel, res: pointer, typ: PNimType) =

-  # to save space, the generic is as small as possible

-  q.ready = true

-  while q.count <= 0:

-    waitSysCond(q.cond, q.lock)

-  q.ready = false

-  if typ != q.elemType:

-    releaseSys(q.lock)

-    sysFatal(ValueError, "cannot receive message of wrong type")

-  rawRecv(q, res, typ)

-

-proc recv*[TMsg](c: var TChannel[TMsg]): TMsg =

-  ## receives a message from the channel `c`. This blocks until

-  ## a message has arrived! You may use ``peek`` to avoid the blocking.

-  var q = cast[PRawChannel](addr(c))

-  acquireSys(q.lock)

-  llRecv(q, addr(result), cast[PNimType](getTypeInfo(result)))

-  releaseSys(q.lock)

-

-proc tryRecv*[TMsg](c: var TChannel[TMsg]): tuple[dataAvailable: bool,

-                                                  msg: TMsg] =

-  ## try to receives a message from the channel `c` if available. Otherwise

-  ## it returns ``(false, default(msg))``.

-  var q = cast[PRawChannel](addr(c))

-  if q.mask != ChannelDeadMask:

+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## Channel support for threads. **Note**: This is part of the system module.
+## Do not import it directly. To activate thread support you need to compile
+## with the ``--threads:on`` command line switch.
+##
+## **Note:** The current implementation of message passing is slow and does
+## not work with cyclic data structures.
+
+when not declared(NimString):
+  {.error: "You must not import this module explicitly".}
+
+type
+  pbytes = ptr array[0.. 0xffff, byte]
+  RawChannel {.pure, final.} = object ## msg queue for a thread
+    rd, wr, count, mask: int
+    data: pbytes
+    lock: SysLock
+    cond: SysCond
+    elemType: PNimType
+    ready: bool
+    region: MemRegion
+  PRawChannel = ptr RawChannel
+  LoadStoreMode = enum mStore, mLoad
+  Channel* {.gcsafe.}[TMsg] = RawChannel ## a channel for thread communication
+{.deprecated: [TRawChannel: RawChannel, TLoadStoreMode: LoadStoreMode,
+              TChannel: Channel].}
+
+const ChannelDeadMask = -2
+
+proc initRawChannel(p: pointer) =
+  var c = cast[PRawChannel](p)
+  initSysLock(c.lock)
+  initSysCond(c.cond)
+  c.mask = -1
+
+proc deinitRawChannel(p: pointer) =
+  var c = cast[PRawChannel](p)
+  # we need to grab the lock to be safe against sending threads!
+  acquireSys(c.lock)
+  c.mask = ChannelDeadMask
+  deallocOsPages(c.region)
+  deinitSys(c.lock)
+  deinitSysCond(c.cond)
+
+proc storeAux(dest, src: pointer, mt: PNimType, t: PRawChannel,
+              mode: LoadStoreMode) {.benign.}
+proc storeAux(dest, src: pointer, n: ptr TNimNode, t: PRawChannel,
+              mode: LoadStoreMode) {.benign.} =
+  var
+    d = cast[ByteAddress](dest)
+    s = cast[ByteAddress](src)
+  case n.kind
+  of nkSlot: storeAux(cast[pointer](d +% n.offset),
+                      cast[pointer](s +% n.offset), n.typ, t, mode)
+  of nkList:
+    for i in 0..n.len-1: storeAux(dest, src, n.sons[i], t, mode)
+  of nkCase:
+    copyMem(cast[pointer](d +% n.offset), cast[pointer](s +% n.offset),
+            n.typ.size)
+    var m = selectBranch(src, n)
+    if m != nil: storeAux(dest, src, m, t, mode)
+  of nkNone: sysAssert(false, "storeAux")
+
+proc storeAux(dest, src: pointer, mt: PNimType, t: PRawChannel,
+              mode: LoadStoreMode) =
+  var
+    d = cast[ByteAddress](dest)
+    s = cast[ByteAddress](src)
+  sysAssert(mt != nil, "mt == nil")
+  case mt.kind
+  of tyString:
+    if mode == mStore:
+      var x = cast[PPointer](dest)
+      var s2 = cast[PPointer](s)[]
+      if s2 == nil:
+        x[] = nil
+      else:
+        var ss = cast[NimString](s2)
+        var ns = cast[NimString](alloc(t.region, ss.len+1 + GenericSeqSize))
+        copyMem(ns, ss, ss.len+1 + GenericSeqSize)
+        x[] = ns
+    else:
+      var x = cast[PPointer](dest)
+      var s2 = cast[PPointer](s)[]
+      if s2 == nil:
+        unsureAsgnRef(x, s2)
+      else:
+        unsureAsgnRef(x, copyString(cast[NimString](s2)))
+        dealloc(t.region, s2)
+  of tySequence:
+    var s2 = cast[PPointer](src)[]
+    var seq = cast[PGenericSeq](s2)
+    var x = cast[PPointer](dest)
+    if s2 == nil:
+      if mode == mStore:
+        x[] = nil
+      else:
+        unsureAsgnRef(x, nil)
+    else:
+      sysAssert(dest != nil, "dest == nil")
+      if mode == mStore:
+        x[] = alloc(t.region, seq.len *% mt.base.size +% GenericSeqSize)
+      else:
+        unsureAsgnRef(x, newObj(mt, seq.len * mt.base.size + GenericSeqSize))
+      var dst = cast[ByteAddress](cast[PPointer](dest)[])
+      for i in 0..seq.len-1:
+        storeAux(
+          cast[pointer](dst +% i*% mt.base.size +% GenericSeqSize),
+          cast[pointer](cast[ByteAddress](s2) +% i *% mt.base.size +%
+                        GenericSeqSize),
+          mt.base, t, mode)
+      var dstseq = cast[PGenericSeq](dst)
+      dstseq.len = seq.len
+      dstseq.reserved = seq.len
+      if mode != mStore: dealloc(t.region, s2)
+  of tyObject:
+    # copy type field:
+    var pint = cast[ptr PNimType](dest)
+    # XXX use dynamic type here!
+    pint[] = mt
+    if mt.base != nil:
+      storeAux(dest, src, mt.base, t, mode)
+    storeAux(dest, src, mt.node, t, mode)
+  of tyTuple:
+    storeAux(dest, src, mt.node, t, mode)
+  of tyArray, tyArrayConstr:
+    for i in 0..(mt.size div mt.base.size)-1:
+      storeAux(cast[pointer](d +% i*% mt.base.size),
+               cast[pointer](s +% i*% mt.base.size), mt.base, t, mode)
+  of tyRef:
+    var s = cast[PPointer](src)[]
+    var x = cast[PPointer](dest)
+    if s == nil:
+      if mode == mStore:
+        x[] = nil
+      else:
+        unsureAsgnRef(x, nil)
+    else:
+      if mode == mStore:
+        x[] = alloc(t.region, mt.base.size)
+      else:
+        # XXX we should use the dynamic type here too, but that is not stored
+        # in the inbox at all --> use source[]'s object type? but how? we need
+        # a tyRef to the object!
+        var obj = newObj(mt, mt.base.size)
+        unsureAsgnRef(x, obj)
+      storeAux(x[], s, mt.base, t, mode)
+      if mode != mStore: dealloc(t.region, s)
+  else:
+    copyMem(dest, src, mt.size) # copy raw bits
+
+proc rawSend(q: PRawChannel, data: pointer, typ: PNimType) =
+  ## adds an `item` to the end of the queue `q`.
+  var cap = q.mask+1
+  if q.count >= cap:
+    # start with capacity for 2 entries in the queue:
+    if cap == 0: cap = 1
+    var n = cast[pbytes](alloc0(q.region, cap*2*typ.size))
+    var z = 0
+    var i = q.rd
+    var c = q.count
+    while c > 0:
+      dec c
+      copyMem(addr(n[z*typ.size]), addr(q.data[i*typ.size]), typ.size)
+      i = (i + 1) and q.mask
+      inc z
+    if q.data != nil: dealloc(q.region, q.data)
+    q.data = n
+    q.mask = cap*2 - 1
+    q.wr = q.count
+    q.rd = 0
+  storeAux(addr(q.data[q.wr * typ.size]), data, typ, q, mStore)
+  inc q.count
+  q.wr = (q.wr + 1) and q.mask
+
+proc rawRecv(q: PRawChannel, data: pointer, typ: PNimType) =
+  sysAssert q.count > 0, "rawRecv"
+  dec q.count
+  storeAux(data, addr(q.data[q.rd * typ.size]), typ, q, mLoad)
+  q.rd = (q.rd + 1) and q.mask
+
+template lockChannel(q: expr, action: stmt) {.immediate.} =
+  acquireSys(q.lock)
+  action
+  releaseSys(q.lock)
+
+template sendImpl(q: expr) {.immediate.} =
+  if q.mask == ChannelDeadMask:
+    sysFatal(DeadThreadError, "cannot send message; thread died")
+  acquireSys(q.lock)
+  var m: TMsg
+  shallowCopy(m, msg)
+  var typ = cast[PNimType](getTypeInfo(msg))
+  rawSend(q, addr(m), typ)
+  q.elemType = typ
+  releaseSys(q.lock)
+  signalSysCond(q.cond)
+
+proc send*[TMsg](c: var Channel[TMsg], msg: TMsg) =
+  ## sends a message to a thread. `msg` is deeply copied.
+  var q = cast[PRawChannel](addr(c))
+  sendImpl(q)
+
+proc llRecv(q: PRawChannel, res: pointer, typ: PNimType) =
+  # to save space, the generic is as small as possible
+  q.ready = true
+  while q.count <= 0:
+    waitSysCond(q.cond, q.lock)
+  q.ready = false
+  if typ != q.elemType:
+    releaseSys(q.lock)
+    sysFatal(ValueError, "cannot receive message of wrong type")
+  rawRecv(q, res, typ)
+
+proc recv*[TMsg](c: var Channel[TMsg]): TMsg =
+  ## receives a message from the channel `c`. This blocks until
+  ## a message has arrived! You may use ``peek`` to avoid the blocking.
+  var q = cast[PRawChannel](addr(c))
+  acquireSys(q.lock)
+  llRecv(q, addr(result), cast[PNimType](getTypeInfo(result)))
+  releaseSys(q.lock)
+
+proc tryRecv*[TMsg](c: var Channel[TMsg]): tuple[dataAvailable: bool,
+                                                  msg: TMsg] =
+  ## try to receives a message from the channel `c` if available. Otherwise
+  ## it returns ``(false, default(msg))``.
+  var q = cast[PRawChannel](addr(c))
+  if q.mask != ChannelDeadMask:
     if tryAcquireSys(q.lock):
-      if q.count > 0:

-        llRecv(q, addr(result.msg), cast[PNimType](getTypeInfo(result.msg)))

-        result.dataAvailable = true

-      releaseSys(q.lock)

-

-proc peek*[TMsg](c: var TChannel[TMsg]): int =

-  ## returns the current number of messages in the channel `c`. Returns -1

-  ## if the channel has been closed. **Note**: This is dangerous to use

-  ## as it encourages races. It's much better to use ``tryRecv`` instead.

-  var q = cast[PRawChannel](addr(c))

-  if q.mask != ChannelDeadMask:

-    lockChannel(q):

-      result = q.count

-  else:

-    result = -1

-

-proc open*[TMsg](c: var TChannel[TMsg]) =

-  ## opens a channel `c` for inter thread communication.

-  initRawChannel(addr(c))

-

-proc close*[TMsg](c: var TChannel[TMsg]) =

-  ## closes a channel `c` and frees its associated resources.

-  deinitRawChannel(addr(c))

-

-proc ready*[TMsg](c: var TChannel[TMsg]): bool =

-  ## returns true iff some thread is waiting on the channel `c` for

-  ## new messages.

-  var q = cast[PRawChannel](addr(c))

-  result = q.ready

-

+      if q.count > 0:
+        llRecv(q, addr(result.msg), cast[PNimType](getTypeInfo(result.msg)))
+        result.dataAvailable = true
+      releaseSys(q.lock)
+
+proc peek*[TMsg](c: var Channel[TMsg]): int =
+  ## returns the current number of messages in the channel `c`. Returns -1
+  ## if the channel has been closed. **Note**: This is dangerous to use
+  ## as it encourages races. It's much better to use ``tryRecv`` instead.
+  var q = cast[PRawChannel](addr(c))
+  if q.mask != ChannelDeadMask:
+    lockChannel(q):
+      result = q.count
+  else:
+    result = -1
+
+proc open*[TMsg](c: var Channel[TMsg]) =
+  ## opens a channel `c` for inter thread communication.
+  initRawChannel(addr(c))
+
+proc close*[TMsg](c: var Channel[TMsg]) =
+  ## closes a channel `c` and frees its associated resources.
+  deinitRawChannel(addr(c))
+
+proc ready*[TMsg](c: var Channel[TMsg]): bool =
+  ## returns true iff some thread is waiting on the channel `c` for
+  ## new messages.
+  var q = cast[PRawChannel](addr(c))
+  result = q.ready
+
diff --git a/lib/system/chcks.nim b/lib/system/chcks.nim
index 2f6d25a12..6caf99d27 100644
--- a/lib/system/chcks.nim
+++ b/lib/system/chcks.nim
@@ -9,16 +9,16 @@
 
 # Implementation of some runtime checks.
 
-proc raiseRangeError(val: BiggestInt) {.compilerproc, noreturn, noinline.} =
+proc raiseRangeError(val: BiggestInt) {.compilerproc, noinline.} =
   when hostOS == "standalone":
     sysFatal(RangeError, "value out of range")
   else:
     sysFatal(RangeError, "value out of range: ", $val)
 
-proc raiseIndexError() {.compilerproc, noreturn, noinline.} =
+proc raiseIndexError() {.compilerproc, noinline.} =
   sysFatal(IndexError, "index out of bounds")
 
-proc raiseFieldError(f: string) {.compilerproc, noreturn, noinline.} =
+proc raiseFieldError(f: string) {.compilerproc, noinline.} =
   sysFatal(FieldError, f, " is not accessible")
 
 proc chckIndx(i, a, b: int): int =
diff --git a/lib/system/debugger.nim b/lib/system/debugger.nim
index 7b5169344..b18c61755 100644
--- a/lib/system/debugger.nim
+++ b/lib/system/debugger.nim
@@ -10,22 +10,23 @@
 ## This file implements basic features for any debugger.
 
 type
-  TVarSlot* {.compilerproc, final.} = object ## a slot in a frame
+  VarSlot* {.compilerproc, final.} = object ## a slot in a frame
     address*: pointer ## the variable's address
     typ*: PNimType    ## the variable's type
     name*: cstring    ## the variable's name; for globals this is "module.name"
 
-  PExtendedFrame = ptr TExtendedFrame
-  TExtendedFrame = object  # If the debugger is enabled the compiler
+  PExtendedFrame = ptr ExtendedFrame
+  ExtendedFrame = object  # If the debugger is enabled the compiler
                            # provides an extended frame. Of course
                            # only slots that are
                            # needed are allocated and not 10_000,
                            # except for the global data description.
     f: TFrame
-    slots: array[0..10_000, TVarSlot]
+    slots: array[0..10_000, VarSlot]
+{.deprecated: [TVarSlot: VarSlot, TExtendedFrame: ExtendedFrame].}
 
 var
-  dbgGlobalData: TExtendedFrame # this reserves much space, but
+  dbgGlobalData: ExtendedFrame  # this reserves much space, but
                                 # for now it is the most practical way
 
 proc dbgRegisterGlobal(name: cstring, address: pointer,
@@ -39,7 +40,7 @@ proc dbgRegisterGlobal(name: cstring, address: pointer,
   dbgGlobalData.slots[i].address = address
   inc(dbgGlobalData.f.len)
 
-proc getLocal*(frame: PFrame; slot: int): TVarSlot {.inline.} =
+proc getLocal*(frame: PFrame; slot: int): VarSlot {.inline.} =
   ## retrieves the meta data for the local variable at `slot`. CAUTION: An
   ## invalid `slot` value causes a corruption!
   result = cast[PExtendedFrame](frame).slots[slot]
@@ -48,7 +49,7 @@ proc getGlobalLen*(): int {.inline.} =
   ## gets the number of registered globals.
   result = dbgGlobalData.f.len
 
-proc getGlobal*(slot: int): TVarSlot {.inline.} =
+proc getGlobal*(slot: int): VarSlot {.inline.} =
   ## retrieves the meta data for the global variable at `slot`. CAUTION: An
   ## invalid `slot` value causes a corruption!
   result = dbgGlobalData.slots[slot]
@@ -56,16 +57,16 @@ proc getGlobal*(slot: int): TVarSlot {.inline.} =
 # ------------------- breakpoint support ------------------------------------
 
 type
-  TBreakpoint* = object  ## represents a break point
+  Breakpoint* = object   ## represents a break point
     low*, high*: int     ## range from low to high; if disabled
                          ## both low and high are set to their negative values
     filename*: cstring   ## the filename of the breakpoint
 
 var
-  dbgBP: array[0..127, TBreakpoint] # breakpoints
+  dbgBP: array[0..127, Breakpoint] # breakpoints
   dbgBPlen: int
   dbgBPbloom: int64  # we use a bloom filter to speed up breakpoint checking
-  
+
   dbgFilenames*: array[0..300, cstring] ## registered filenames;
                                         ## 'nil' terminated
   dbgFilenameLen: int
@@ -131,16 +132,16 @@ proc canonFilename*(filename: cstring): cstring =
     if fileMatches(result, filename): return result
   result = nil
 
-iterator listBreakpoints*(): ptr TBreakpoint =
+iterator listBreakpoints*(): ptr Breakpoint =
   ## lists all breakpoints.
   for i in 0..dbgBPlen-1: yield addr(dbgBP[i])
 
-proc isActive*(b: ptr TBreakpoint): bool = b.low > 0
-proc flip*(b: ptr TBreakpoint) =
+proc isActive*(b: ptr Breakpoint): bool = b.low > 0
+proc flip*(b: ptr Breakpoint) =
   ## enables or disables 'b' depending on its current state.
   b.low = -b.low; b.high = -b.high
 
-proc checkBreakpoints*(filename: cstring, line: int): ptr TBreakpoint =
+proc checkBreakpoints*(filename: cstring, line: int): ptr Breakpoint =
   ## in which breakpoint (if any) we are.
   if (dbgBPbloom and line) != line: return nil
   for b in listBreakpoints():
@@ -149,29 +150,30 @@ proc checkBreakpoints*(filename: cstring, line: int): ptr TBreakpoint =
 # ------------------- watchpoint support ------------------------------------
 
 type
-  THash = int
-  TWatchpoint {.pure, final.} = object
+  Hash = int
+  Watchpoint {.pure, final.} = object
     name: cstring
     address: pointer
     typ: PNimType
-    oldValue: THash
+    oldValue: Hash
+{.deprecated: [THash: Hash, TWatchpoint: Watchpoint].}
 
 var
-  watchpoints: array [0..99, TWatchpoint]
+  watchpoints: array [0..99, Watchpoint]
   watchpointsLen: int
 
-proc `!&`(h: THash, val: int): THash {.inline.} =
+proc `!&`(h: Hash, val: int): Hash {.inline.} =
   result = h +% val
   result = result +% result shl 10
   result = result xor (result shr 6)
 
-proc `!$`(h: THash): THash {.inline.} =
+proc `!$`(h: Hash): Hash {.inline.} =
   result = h +% h shl 3
   result = result xor (result shr 11)
   result = result +% result shl 15
 
-proc hash(data: pointer, size: int): THash =
-  var h: THash = 0
+proc hash(data: pointer, size: int): Hash =
+  var h: Hash = 0
   var p = cast[cstring](data)
   var i = 0
   var s = size
@@ -181,21 +183,21 @@ proc hash(data: pointer, size: int): THash =
     dec(s)
   result = !$h
 
-proc hashGcHeader(data: pointer): THash =
+proc hashGcHeader(data: pointer): Hash =
   const headerSize = sizeof(int)*2
   result = hash(cast[pointer](cast[int](data) -% headerSize), headerSize)
 
 proc genericHashAux(dest: pointer, mt: PNimType, shallow: bool,
-                    h: THash): THash
+                    h: Hash): Hash
 proc genericHashAux(dest: pointer, n: ptr TNimNode, shallow: bool,
-                    h: THash): THash =
+                    h: Hash): Hash =
   var d = cast[ByteAddress](dest)
   case n.kind
   of nkSlot:
     result = genericHashAux(cast[pointer](d +% n.offset), n.typ, shallow, h)
   of nkList:
     result = h
-    for i in 0..n.len-1: 
+    for i in 0..n.len-1:
       result = result !& genericHashAux(dest, n.sons[i], shallow, result)
   of nkCase:
     result = h !& hash(cast[pointer](d +% n.offset), n.typ.size)
@@ -203,8 +205,8 @@ proc genericHashAux(dest: pointer, n: ptr TNimNode, shallow: bool,
     if m != nil: result = genericHashAux(dest, m, shallow, result)
   of nkNone: sysAssert(false, "genericHashAux")
 
-proc genericHashAux(dest: pointer, mt: PNimType, shallow: bool, 
-                    h: THash): THash =
+proc genericHashAux(dest: pointer, mt: PNimType, shallow: bool,
+                    h: Hash): Hash =
   sysAssert(mt != nil, "genericHashAux 2")
   case mt.kind
   of tyString:
@@ -255,7 +257,7 @@ proc genericHashAux(dest: pointer, mt: PNimType, shallow: bool,
 
 proc genericHash(dest: pointer, mt: PNimType): int =
   result = genericHashAux(dest, mt, false, 0)
-  
+
 proc dbgRegisterWatchpoint(address: pointer, name: cstring,
                            typ: PNimType) {.compilerproc.} =
   let L = watchPointsLen
@@ -283,7 +285,7 @@ var
     ## Only code compiled with the ``debugger:on`` switch calls this hook.
 
   dbgWatchpointHook*: proc (watchpointName: cstring) {.nimcall.}
-  
+
 proc checkWatchpoints =
   let L = watchPointsLen
   for i in 0.. <L:
diff --git a/lib/system/deepcopy.nim b/lib/system/deepcopy.nim
index 093c0f3a7..03230e541 100644
--- a/lib/system/deepcopy.nim
+++ b/lib/system/deepcopy.nim
@@ -14,7 +14,7 @@ proc genericDeepCopyAux(dest, src: pointer, n: ptr TNimNode) {.benign.} =
     s = cast[ByteAddress](src)
   case n.kind
   of nkSlot:
-    genericDeepCopyAux(cast[pointer](d +% n.offset), 
+    genericDeepCopyAux(cast[pointer](d +% n.offset),
                        cast[pointer](s +% n.offset), n.typ)
   of nkList:
     for i in 0..n.len-1:
@@ -24,7 +24,7 @@ proc genericDeepCopyAux(dest, src: pointer, n: ptr TNimNode) {.benign.} =
     var m = selectBranch(src, n)
     # reset if different branches are in use; note different branches also
     # imply that's not self-assignment (``x = x``)!
-    if m != dd and dd != nil: 
+    if m != dd and dd != nil:
       genericResetAux(dest, dd)
     copyMem(cast[pointer](d +% n.offset), cast[pointer](s +% n.offset),
             n.typ.size)
@@ -103,16 +103,16 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) =
         else:
           let realType = x.typ
           let z = newObj(realType, realType.base.size)
-          
+
           unsureAsgnRef(cast[PPointer](dest), z)
           x.typ = cast[PNimType](cast[int](z) or 1)
           genericDeepCopyAux(z, s2, realType.base)
           x.typ = realType
       else:
         let realType = mt
-        let z = newObj(realType, realType.base.size)        
+        let z = newObj(realType, realType.base.size)
         unsureAsgnRef(cast[PPointer](dest), z)
-        genericDeepCopyAux(z, s2, realType.base)        
+        genericDeepCopyAux(z, s2, realType.base)
   of tyPtr:
     # no cycle check here, but also not really required
     let s2 = cast[PPointer](src)[]
diff --git a/lib/system/dyncalls.nim b/lib/system/dyncalls.nim
index 44f7b67c3..fe98b1e6f 100644
--- a/lib/system/dyncalls.nim
+++ b/lib/system/dyncalls.nim
@@ -15,9 +15,9 @@
 {.push stack_trace: off.}
 
 const
-  NilLibHandle: TLibHandle = nil
+  NilLibHandle: LibHandle = nil
 
-proc rawWrite(f: File, s: string) = 
+proc rawWrite(f: File, s: string) =
   # we cannot throw an exception here!
   discard writeBuffer(f, cstring(s), s.len)
 
@@ -55,22 +55,22 @@ when defined(posix):
   var
     RTLD_NOW {.importc: "RTLD_NOW", header: "<dlfcn.h>".}: int
 
-  proc dlclose(lib: TLibHandle) {.importc, header: "<dlfcn.h>".}
-  proc dlopen(path: cstring, mode: int): TLibHandle {.
+  proc dlclose(lib: LibHandle) {.importc, header: "<dlfcn.h>".}
+  proc dlopen(path: cstring, mode: int): LibHandle {.
       importc, header: "<dlfcn.h>".}
-  proc dlsym(lib: TLibHandle, name: cstring): TProcAddr {.
+  proc dlsym(lib: LibHandle, name: cstring): ProcAddr {.
       importc, header: "<dlfcn.h>".}
 
   proc dlerror(): cstring {.importc, header: "<dlfcn.h>".}
 
-  proc nimUnloadLibrary(lib: TLibHandle) =
+  proc nimUnloadLibrary(lib: LibHandle) =
     dlclose(lib)
 
-  proc nimLoadLibrary(path: string): TLibHandle =
+  proc nimLoadLibrary(path: string): LibHandle =
     result = dlopen(path, RTLD_NOW)
     #c_fprintf(c_stdout, "%s\n", dlerror())
 
-  proc nimGetProcAddr(lib: TLibHandle, name: cstring): TProcAddr =
+  proc nimGetProcAddr(lib: LibHandle, name: cstring): ProcAddr =
     result = dlsym(lib, name)
     if result == nil: procAddrError(name)
 
@@ -84,12 +84,12 @@ elif defined(windows) or defined(dos):
     type
       THINSTANCE {.importc: "HINSTANCE".} = object
         x: pointer
-    proc getProcAddress(lib: THINSTANCE, name: cstring): TProcAddr {.
+    proc getProcAddress(lib: THINSTANCE, name: cstring): ProcAddr {.
         importcpp: "(void*)GetProcAddress(@)", header: "<windows.h>", stdcall.}
   else:
     type
       THINSTANCE {.importc: "HINSTANCE".} = pointer
-    proc getProcAddress(lib: THINSTANCE, name: cstring): TProcAddr {.
+    proc getProcAddress(lib: THINSTANCE, name: cstring): ProcAddr {.
         importc: "GetProcAddress", header: "<windows.h>", stdcall.}
 
   proc freeLibrary(lib: THINSTANCE) {.
@@ -97,13 +97,13 @@ elif defined(windows) or defined(dos):
   proc winLoadLibrary(path: cstring): THINSTANCE {.
       importc: "LoadLibraryA", header: "<windows.h>", stdcall.}
 
-  proc nimUnloadLibrary(lib: TLibHandle) =
+  proc nimUnloadLibrary(lib: LibHandle) =
     freeLibrary(cast[THINSTANCE](lib))
 
-  proc nimLoadLibrary(path: string): TLibHandle =
-    result = cast[TLibHandle](winLoadLibrary(path))
+  proc nimLoadLibrary(path: string): LibHandle =
+    result = cast[LibHandle](winLoadLibrary(path))
 
-  proc nimGetProcAddr(lib: TLibHandle, name: cstring): TProcAddr =
+  proc nimGetProcAddr(lib: LibHandle, name: cstring): ProcAddr =
     result = getProcAddress(cast[THINSTANCE](lib), name)
     if result == nil: procAddrError(name)
 
@@ -115,13 +115,13 @@ elif defined(mac):
   #
   {.error: "no implementation for dyncalls yet".}
 
-  proc nimUnloadLibrary(lib: TLibHandle) =
+  proc nimUnloadLibrary(lib: LibHandle) =
     NSUnLinkModule(NSModule(lib), NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES)
 
   var
     dyld_present {.importc: "_dyld_present", header: "<dyld.h>".}: int
 
-  proc nimLoadLibrary(path: string): TLibHandle =
+  proc nimLoadLibrary(path: string): LibHandle =
     var
       img: NSObjectFileImage
       ret: NSObjectFileImageReturnCode
@@ -134,17 +134,16 @@ elif defined(mac):
         modul = NSLinkModule(img, path, NSLINKMODULE_OPTION_PRIVATE or
                                         NSLINKMODULE_OPTION_RETURN_ON_ERROR)
         NSDestroyObjectFileImage(img)
-        result = TLibHandle(modul)
+        result = LibHandle(modul)
 
-  proc nimGetProcAddr(lib: TLibHandle, name: cstring): TProcAddr =
+  proc nimGetProcAddr(lib: LibHandle, name: cstring): ProcAddr =
     var
       nss: NSSymbol
     nss = NSLookupSymbolInModule(NSModule(lib), name)
-    result = TProcAddr(NSAddressOfSymbol(nss))
+    result = ProcAddr(NSAddressOfSymbol(nss))
     if result == nil: ProcAddrError(name)
 
 else:
   {.error: "no implementation for dyncalls".}
-  
-{.pop.}
 
+{.pop.}
diff --git a/lib/system/endb.nim b/lib/system/endb.nim
index 003698421..b2cc5624b 100644
--- a/lib/system/endb.nim
+++ b/lib/system/endb.nim
@@ -20,63 +20,65 @@ const
   EndbEnd = "***\n"
 
 type
-  TStaticStr = object
+  StaticStr = object
     len: int
     data: array[0..100, char]
 
-  TBreakpointFilename = object
-    b: ptr TBreakpoint
-    filename: TStaticStr
+  BreakpointFilename = object
+    b: ptr Breakpoint
+    filename: StaticStr
 
-  TDbgState = enum
+  DbgState = enum
     dbOff,        # debugger is turned off
     dbStepInto,   # debugger is in tracing mode
     dbStepOver,
     dbSkipCurrent,
     dbQuiting,    # debugger wants to quit
     dbBreakpoints # debugger is only interested in breakpoints
+{.deprecated: [TStaticStr: StaticStr, TBreakpointFilename: BreakpointFilename,
+              TDbgState: DbgState].}
 
 var
-  dbgUser: TStaticStr   # buffer for user input; first command is ``step_into``
+  dbgUser: StaticStr    # buffer for user input; first command is ``step_into``
                         # needs to be global cause we store the last command
                         # in it
-  dbgState: TDbgState   # state of debugger
+  dbgState: DbgState    # state of debugger
   dbgSkipToFrame: PFrame # frame to be skipped to
 
   maxDisplayRecDepth: int = 5 # do not display too much data!
 
-  brkPoints: array[0..127, TBreakpointFilename]
+  brkPoints: array[0..127, BreakpointFilename]
 
-proc setLen(s: var TStaticStr, newLen=0) =
+proc setLen(s: var StaticStr, newLen=0) =
   s.len = newLen
   s.data[newLen] = '\0'
 
-proc add(s: var TStaticStr, c: char) =
+proc add(s: var StaticStr, c: char) =
   if s.len < high(s.data)-1:
     s.data[s.len] = c
     s.data[s.len+1] = '\0'
     inc s.len
 
-proc add(s: var TStaticStr, c: cstring) =
+proc add(s: var StaticStr, c: cstring) =
   var i = 0
   while c[i] != '\0':
     add s, c[i]
     inc i
 
-proc assign(s: var TStaticStr, c: cstring) =
+proc assign(s: var StaticStr, c: cstring) =
   setLen(s)
   add s, c
 
-proc `==`(a, b: TStaticStr): bool =
+proc `==`(a, b: StaticStr): bool =
   if a.len == b.len:
     for i in 0 .. a.len-1:
       if a.data[i] != b.data[i]: return false
     return true
 
-proc `==`(a: TStaticStr, b: cstring): bool =
+proc `==`(a: StaticStr, b: cstring): bool =
   result = c_strcmp(a.data, b) == 0
 
-proc write(f: TFile, s: TStaticStr) =
+proc write(f: File, s: StaticStr) =
   write(f, cstring(s.data))
 
 proc listBreakPoints() =
@@ -95,14 +97,14 @@ proc listBreakPoints() =
       write(stdout, "\n")
   write(stdout, EndbEnd)
 
-proc openAppend(filename: cstring): TFile =
+proc openAppend(filename: cstring): File =
   var p: pointer = fopen(filename, "ab")
   if p != nil:
-    result = cast[TFile](p)
+    result = cast[File](p)
     write(result, "----------------------------------------\n")
 
 proc dbgRepr(p: pointer, typ: PNimType): string =
-  var cl: TReprClosure
+  var cl: ReprClosure
   initReprClosure(cl)
   cl.recDepth = maxDisplayRecDepth
   # locks for the GC turned out to be a bad idea...
@@ -112,21 +114,21 @@ proc dbgRepr(p: pointer, typ: PNimType): string =
   # dec(recGcLock)
   deinitReprClosure(cl)
 
-proc writeVariable(stream: TFile, slot: TVarSlot) =
+proc writeVariable(stream: File, slot: VarSlot) =
   write(stream, slot.name)
   write(stream, " = ")
-  writeln(stream, dbgRepr(slot.address, slot.typ))
+  writeLine(stream, dbgRepr(slot.address, slot.typ))
 
-proc listFrame(stream: TFile, f: PFrame) =
+proc listFrame(stream: File, f: PFrame) =
   write(stream, EndbBeg)
   write(stream, "| Frame (")
   write(stream, f.len)
   write(stream, " slots):\n")
   for i in 0 .. f.len-1:
-    writeln(stream, getLocal(f, i).name)
+    writeLine(stream, getLocal(f, i).name)
   write(stream, EndbEnd)
 
-proc listLocals(stream: TFile, f: PFrame) =
+proc listLocals(stream: File, f: PFrame) =
   write(stream, EndbBeg)
   write(stream, "| Frame (")
   write(stream, f.len)
@@ -135,11 +137,11 @@ proc listLocals(stream: TFile, f: PFrame) =
     writeVariable(stream, getLocal(f, i))
   write(stream, EndbEnd)
 
-proc listGlobals(stream: TFile) =
+proc listGlobals(stream: File) =
   write(stream, EndbBeg)
   write(stream, "| Globals:\n")
   for i in 0 .. getGlobalLen()-1:
-    writeln(stream, getGlobal(i).name)
+    writeLine(stream, getGlobal(i).name)
   write(stream, EndbEnd)
 
 proc debugOut(msg: cstring) =
@@ -172,7 +174,7 @@ proc dbgShowExecutionPoint() =
   write(stdout, framePtr.procname)
   write(stdout, " ***\n")
 
-proc scanAndAppendWord(src: cstring, a: var TStaticStr, start: int): int =
+proc scanAndAppendWord(src: cstring, a: var StaticStr, start: int): int =
   result = start
   # skip whitespace:
   while src[result] in {'\t', ' '}: inc(result)
@@ -184,11 +186,11 @@ proc scanAndAppendWord(src: cstring, a: var TStaticStr, start: int): int =
     else: break
     inc(result)
 
-proc scanWord(src: cstring, a: var TStaticStr, start: int): int =
+proc scanWord(src: cstring, a: var StaticStr, start: int): int =
   setlen(a)
   result = scanAndAppendWord(src, a, start)
 
-proc scanFilename(src: cstring, a: var TStaticStr, start: int): int =
+proc scanFilename(src: cstring, a: var StaticStr, start: int): int =
   result = start
   setLen a
   while src[result] in {'\t', ' '}: inc(result)
@@ -250,8 +252,8 @@ proc hasExt(s: cstring): bool =
     if s[i] == '.': return true
     inc i
 
-proc parseBreakpoint(s: cstring, start: int): TBreakpoint =
-  var dbgTemp: TStaticStr
+proc parseBreakpoint(s: cstring, start: int): Breakpoint =
+  var dbgTemp: StaticStr
   var i = scanNumber(s, result.low, start)
   if result.low == 0: result.low = framePtr.line
   i = scanNumber(s, result.high, i)
@@ -279,11 +281,11 @@ proc breakpointToggle(s: cstring, start: int) =
     if not b.isNil: b.flip
     else: debugOut("[Warning] unknown breakpoint ")
 
-proc dbgEvaluate(stream: TFile, s: cstring, start: int, f: PFrame) =
-  var dbgTemp: TStaticStr
+proc dbgEvaluate(stream: File, s: cstring, start: int, f: PFrame) =
+  var dbgTemp: StaticStr
   var i = scanWord(s, dbgTemp, start)
   while s[i] in {' ', '\t'}: inc(i)
-  var v: TVarSlot
+  var v: VarSlot
   if s[i] == '.':
     inc(i)
     add(dbgTemp, '.')
@@ -296,10 +298,10 @@ proc dbgEvaluate(stream: TFile, s: cstring, start: int, f: PFrame) =
     for i in 0 .. f.len-1:
       let v = getLocal(f, i)
       if c_strcmp(v.name, dbgTemp.data) == 0:
-        writeVariable(stream, v)  
+        writeVariable(stream, v)
 
 proc dbgOut(s: cstring, start: int, currFrame: PFrame) =
-  var dbgTemp: TStaticStr
+  var dbgTemp: StaticStr
   var i = scanFilename(s, dbgTemp, start)
   if dbgTemp.len == 0:
     invalidCommand()
@@ -312,7 +314,7 @@ proc dbgOut(s: cstring, start: int, currFrame: PFrame) =
   close(stream)
 
 proc dbgStackFrame(s: cstring, start: int, currFrame: PFrame) =
-  var dbgTemp: TStaticStr
+  var dbgTemp: StaticStr
   var i = scanFilename(s, dbgTemp, start)
   if dbgTemp.len == 0:
     # just write it to stdout:
@@ -325,7 +327,7 @@ proc dbgStackFrame(s: cstring, start: int, currFrame: PFrame) =
     listFrame(stream, currFrame)
     close(stream)
 
-proc readLine(f: TFile, line: var TStaticStr): bool =
+proc readLine(f: File, line: var StaticStr): bool =
   while true:
     var c = fgetc(f)
     if c < 0'i32:
@@ -358,7 +360,7 @@ proc commandPrompt() =
     again = true
     dbgFramePtr = framePtr # for going down and up the stack
     dbgDown = 0 # how often we did go down
-    dbgTemp: TStaticStr
+    dbgTemp: StaticStr
 
   while again:
     write(stdout, "*** endb| >>")
@@ -394,7 +396,13 @@ proc commandPrompt() =
       again = false
       quit(1) # BUGFIX: quit with error code > 0
     elif ?"e" or ?"eval":
+      var
+        prevState = dbgState
+        prevSkipFrame = dbgSkipToFrame
+      dbgState = dbSkipCurrent
       dbgEvaluate(stdout, dbgUser.data, i, dbgFramePtr)
+      dbgState = prevState
+      dbgSkipToFrame = prevSkipFrame
     elif ?"o" or ?"out":
       dbgOut(dbgUser.data, i, dbgFramePtr)
     elif ?"stackframe":
@@ -402,9 +410,21 @@ proc commandPrompt() =
     elif ?"w" or ?"where":
       dbgShowExecutionPoint()
     elif ?"l" or ?"locals":
+      var
+        prevState = dbgState
+        prevSkipFrame = dbgSkipToFrame
+      dbgState = dbSkipCurrent
       listLocals(stdout, dbgFramePtr)
+      dbgState = prevState
+      dbgSkipToFrame = prevSkipFrame
     elif ?"g" or ?"globals":
+      var
+        prevState = dbgState
+        prevSkipFrame = dbgSkipToFrame
+      dbgState = dbSkipCurrent
       listGlobals(stdout)
+      dbgState = prevState
+      dbgSkipToFrame = prevSkipFrame
     elif ?"u" or ?"up":
       if dbgDown <= 0:
         debugOut("[Warning] cannot go up any further ")
@@ -482,7 +502,7 @@ proc dbgWriteStackTrace(f: PFrame) =
     inc(i)
     b = b.prev
   for j in countdown(i-1, 0):
-    if tempFrames[j] == nil: 
+    if tempFrames[j] == nil:
       write(stdout, "(")
       write(stdout, skipped)
       write(stdout, " calls omitted) ...")
diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim
index 1b3471978..df28c1493 100644
--- a/lib/system/excpt.nim
+++ b/lib/system/excpt.nim
@@ -44,10 +44,12 @@ var
     # a global variable for the root of all try blocks
   currException {.threadvar.}: ref Exception
 
+proc getFrame*(): PFrame {.compilerRtl, inl.} = framePtr
+
 proc popFrame {.compilerRtl, inl.} =
   framePtr = framePtr.prev
 
-proc setFrame(s: PFrame) {.compilerRtl, inl.} =
+proc setFrame*(s: PFrame) {.compilerRtl, inl.} =
   framePtr = s
 
 proc pushSafePoint(s: PSafePoint) {.compilerRtl, inl.} =
@@ -58,23 +60,23 @@ proc pushSafePoint(s: PSafePoint) {.compilerRtl, inl.} =
 proc popSafePoint {.compilerRtl, inl.} =
   excHandler = excHandler.prev
 
-proc pushCurrentException(e: ref Exception) {.compilerRtl, inl.} = 
+proc pushCurrentException(e: ref Exception) {.compilerRtl, inl.} =
   e.parent = currException
   currException = e
 
 proc popCurrentException {.compilerRtl, inl.} =
-  currException = currException.parent
+  currException = nil # currException.parent
 
 # some platforms have native support for stack traces:
 const
   nativeStackTraceSupported* = (defined(macosx) or defined(linux)) and
                               not NimStackTrace
-  hasSomeStackTrace = NimStackTrace or 
+  hasSomeStackTrace = NimStackTrace or
     defined(nativeStackTrace) and nativeStackTraceSupported
 
 when defined(nativeStacktrace) and nativeStackTraceSupported:
   type
-    TDl_info {.importc: "Dl_info", header: "<dlfcn.h>", 
+    TDl_info {.importc: "Dl_info", header: "<dlfcn.h>",
                final, pure.} = object
       dli_fname: cstring
       dli_fbase: pointer
@@ -98,7 +100,7 @@ when defined(nativeStacktrace) and nativeStackTraceSupported:
         tempDlInfo: TDl_info
     # This is allowed to be expensive since it only happens during crashes
     # (but this way you don't need manual stack tracing)
-    var size = backtrace(cast[ptr pointer](addr(tempAddresses)), 
+    var size = backtrace(cast[ptr pointer](addr(tempAddresses)),
                          len(tempAddresses))
     var enabled = false
     for i in 0..size-1:
@@ -123,7 +125,7 @@ when defined(nativeStacktrace) and nativeStackTraceSupported:
 when not hasThreadSupport:
   var
     tempFrames: array [0..127, PFrame] # should not be alloc'd on stack
-  
+
 proc auxWriteStackTrace(f: PFrame, s: var string) =
   when hasThreadSupport:
     var
@@ -160,7 +162,7 @@ proc auxWriteStackTrace(f: PFrame, s: var string) =
     inc(i)
     b = b.prev
   for j in countdown(i-1, 0):
-    if tempFrames[j] == nil: 
+    if tempFrames[j] == nil:
       add(s, "(")
       add(s, $skipped)
       add(s, " calls omitted) ...")
@@ -214,41 +216,49 @@ proc raiseExceptionAux(e: ref Exception) =
     if not localRaiseHook(e): return
   if globalRaiseHook != nil:
     if not globalRaiseHook(e): return
-  if excHandler != nil:
-    if not excHandler.hasRaiseAction or excHandler.raiseAction(e):
+  when defined(cpp):
+    if e[] of OutOfMemError:
+      showErrorMessage(e.name)
+      quitOrDebug()
+    else:
       pushCurrentException(e)
-      c_longjmp(excHandler.context, 1)
-  elif e[] of OutOfMemError:
-    showErrorMessage(e.name)
-    quitOrDebug()
+      {.emit: "throw NimException(`e`, `e`->name);".}
   else:
-    when hasSomeStackTrace:
-      var buf = newStringOfCap(2000)
-      if isNil(e.trace): rawWriteStackTrace(buf)
-      else: add(buf, e.trace)
-      add(buf, "Error: unhandled exception: ")
-      if not isNil(e.msg): add(buf, e.msg)
-      add(buf, " [")
-      add(buf, $e.name)
-      add(buf, "]\n")
-      showErrorMessage(buf)
+    if excHandler != nil:
+      if not excHandler.hasRaiseAction or excHandler.raiseAction(e):
+        pushCurrentException(e)
+        c_longjmp(excHandler.context, 1)
+    elif e[] of OutOfMemError:
+      showErrorMessage(e.name)
+      quitOrDebug()
     else:
-      # ugly, but avoids heap allocations :-)
-      template xadd(buf, s, slen: expr) =
-        if L + slen < high(buf):
-          copyMem(addr(buf[L]), cstring(s), slen)
-          inc L, slen
-      template add(buf, s: expr) =
-        xadd(buf, s, s.len)
-      var buf: array [0..2000, char]
-      var L = 0
-      add(buf, "Error: unhandled exception: ")
-      if not isNil(e.msg): add(buf, e.msg)
-      add(buf, " [")
-      xadd(buf, e.name, c_strlen(e.name))
-      add(buf, "]\n")
-      showErrorMessage(buf)
-    quitOrDebug()
+      when hasSomeStackTrace:
+        var buf = newStringOfCap(2000)
+        if isNil(e.trace): rawWriteStackTrace(buf)
+        else: add(buf, e.trace)
+        add(buf, "Error: unhandled exception: ")
+        if not isNil(e.msg): add(buf, e.msg)
+        add(buf, " [")
+        add(buf, $e.name)
+        add(buf, "]\n")
+        showErrorMessage(buf)
+      else:
+        # ugly, but avoids heap allocations :-)
+        template xadd(buf, s, slen: expr) =
+          if L + slen < high(buf):
+            copyMem(addr(buf[L]), cstring(s), slen)
+            inc L, slen
+        template add(buf, s: expr) =
+          xadd(buf, s, s.len)
+        var buf: array [0..2000, char]
+        var L = 0
+        add(buf, "Error: unhandled exception: ")
+        if not isNil(e.msg): add(buf, e.msg)
+        add(buf, " [")
+        xadd(buf, e.name, c_strlen(e.name))
+        add(buf, "]\n")
+        showErrorMessage(buf)
+      quitOrDebug()
 
 proc raiseException(e: ref Exception, ename: cstring) {.compilerRtl.} =
   e.name = ename
@@ -309,7 +319,7 @@ when not defined(noSignalHandler):
   proc signalHandler(sig: cint) {.exportc: "signalHandler", noconv.} =
     template processSignal(s, action: expr) {.immediate,  dirty.} =
       if s == SIGINT: action("SIGINT: Interrupted by Ctrl-C.\n")
-      elif s == SIGSEGV: 
+      elif s == SIGSEGV:
         action("SIGSEGV: Illegal storage access. (Attempt to read from nil?)\n")
       elif s == SIGABRT:
         when defined(endb):
@@ -357,5 +367,6 @@ when not defined(noSignalHandler):
 
 proc setControlCHook(hook: proc () {.noconv.} not nil) =
   # ugly cast, but should work on all architectures:
-  type TSignalHandler = proc (sig: cint) {.noconv, benign.}
-  c_signal(SIGINT, cast[TSignalHandler](hook))
+  type SignalHandler = proc (sig: cint) {.noconv, benign.}
+  {.deprecated: [TSignalHandler: SignalHandler].}
+  c_signal(SIGINT, cast[SignalHandler](hook))
diff --git a/lib/system/gc.nim b/lib/system/gc.nim
index c4374d00c..0c632aeb1 100644
--- a/lib/system/gc.nim
+++ b/lib/system/gc.nim
@@ -16,6 +16,10 @@
 # Special care has been taken to avoid recursion as far as possible to avoid
 # stack overflows when traversing deep datastructures. It is well-suited
 # for soft real time applications (like games).
+
+when defined(nimCoroutines):
+  import arch
+
 {.push profiler:off.}
 
 const
@@ -45,17 +49,17 @@ const
   rcShift = 3      # shift by rcShift to get the reference counter
   colorMask = 0b011
 type
-  TWalkOp = enum
+  WalkOp = enum
     waMarkGlobal,    # part of the backup/debug mark&sweep
     waMarkPrecise,   # part of the backup/debug mark&sweep
     waZctDecRef, waPush, waCycleDecRef, waMarkGray, waScan, waScanBlack,
     waCollectWhite #, waDebug
 
-  TFinalizer {.compilerproc.} = proc (self: pointer) {.nimcall, benign.}
+  Finalizer {.compilerproc.} = proc (self: pointer) {.nimcall, benign.}
     # A ref type can have a finalizer that is called before the object's
     # storage is freed.
 
-  TGcStat {.final, pure.} = object
+  GcStat {.final, pure.} = object
     stackScans: int          # number of performed stack scans (for statistics)
     cycleCollections: int    # number of performed full collections
     maxThreshold: int        # max threshold that has been set
@@ -64,35 +68,44 @@ type
     cycleTableSize: int      # max entries in cycle table
     maxPause: int64          # max measured GC pause in nanoseconds
 
-  TGcHeap {.final, pure.} = object # this contains the zero count and
+  GcStack {.final.} = object
+    prev: ptr GcStack
+    next: ptr GcStack
+    starts: pointer
+    pos: pointer
+    maxStackSize: int
+
+  GcHeap {.final, pure.} = object # this contains the zero count and
                                    # non-zero count table
+    stack: ptr GcStack
     stackBottom: pointer
     cycleThreshold: int
     when useCellIds:
       idGenerator: int
-    zct: TCellSeq            # the zero count table
-    decStack: TCellSeq       # cells in the stack that are to decref again
-    cycleRoots: TCellSet
-    tempStack: TCellSeq      # temporary stack for recursion elimination
+    zct: CellSeq             # the zero count table
+    decStack: CellSeq        # cells in the stack that are to decref again
+    cycleRoots: CellSet
+    tempStack: CellSeq       # temporary stack for recursion elimination
     recGcLock: int           # prevent recursion via finalizers; no thread lock
     when withRealTime:
-      maxPause: TNanos       # max allowed pause in nanoseconds; active if > 0
-    region: TMemRegion       # garbage collected region
-    stat: TGcStat
+      maxPause: Nanos        # max allowed pause in nanoseconds; active if > 0
+    region: MemRegion        # garbage collected region
+    stat: GcStat
     when useMarkForDebug or useBackupGc:
-      marked: TCellSet
-
+      marked: CellSet
+{.deprecated: [TWalkOp: WalkOp, TFinalizer: Finalizer, TGcHeap: GcHeap,
+              TGcStat: GcStat].}
 var
-  gch {.rtlThreadVar.}: TGcHeap
+  gch {.rtlThreadVar.}: GcHeap
 
 when not defined(useNimRtl):
   instantiateForRegion(gch.region)
 
-template acquire(gch: TGcHeap) =
+template acquire(gch: GcHeap) =
   when hasThreadSupport and hasSharedHeap:
     acquireSys(HeapLock)
 
-template release(gch: TGcHeap) =
+template release(gch: GcHeap) =
   when hasThreadSupport and hasSharedHeap:
     releaseSys(HeapLock)
 
@@ -104,18 +117,18 @@ template gcAssert(cond: bool, msg: string) =
       writeStackTrace()
       quit 1
 
-proc addZCT(s: var TCellSeq, c: PCell) {.noinline.} =
+proc addZCT(s: var CellSeq, c: PCell) {.noinline.} =
   if (c.refcount and ZctFlag) == 0:
     c.refcount = c.refcount or ZctFlag
     add(s, c)
 
 proc cellToUsr(cell: PCell): pointer {.inline.} =
   # convert object (=pointer to refcount) to pointer to userdata
-  result = cast[pointer](cast[ByteAddress](cell)+%ByteAddress(sizeof(TCell)))
+  result = cast[pointer](cast[ByteAddress](cell)+%ByteAddress(sizeof(Cell)))
 
 proc usrToCell(usr: pointer): PCell {.inline.} =
   # convert pointer to userdata to object (=pointer to refcount)
-  result = cast[PCell](cast[ByteAddress](usr)-%ByteAddress(sizeof(TCell)))
+  result = cast[PCell](cast[ByteAddress](usr)-%ByteAddress(sizeof(Cell)))
 
 proc canBeCycleRoot(c: PCell): bool {.inline.} =
   result = ntfAcyclic notin c.typ.flags
@@ -152,11 +165,11 @@ template gcTrace(cell, state: expr): stmt {.immediate.} =
   when traceGC: traceCell(cell, state)
 
 # forward declarations:
-proc collectCT(gch: var TGcHeap) {.benign.}
-proc isOnStack*(p: pointer): bool {.noinline, benign.}
-proc forAllChildren(cell: PCell, op: TWalkOp) {.benign.}
-proc doOperation(p: pointer, op: TWalkOp) {.benign.}
-proc forAllChildrenAux(dest: pointer, mt: PNimType, op: TWalkOp) {.benign.}
+proc collectCT(gch: var GcHeap) {.benign.}
+proc isOnStack(p: pointer): bool {.noinline, benign.}
+proc forAllChildren(cell: PCell, op: WalkOp) {.benign.}
+proc doOperation(p: pointer, op: WalkOp) {.benign.}
+proc forAllChildrenAux(dest: pointer, mt: PNimType, op: WalkOp) {.benign.}
 # we need the prototype here for debugging purposes
 
 when hasThreadSupport and hasSharedHeap:
@@ -178,7 +191,7 @@ proc prepareDealloc(cell: PCell) =
     # prevend recursive entering here by a lock.
     # XXX: we should set the cell's children to nil!
     inc(gch.recGcLock)
-    (cast[TFinalizer](cell.typ.finalizer))(cellToUsr(cell))
+    (cast[Finalizer](cell.typ.finalizer))(cellToUsr(cell))
     dec(gch.recGcLock)
 
 proc rtlAddCycleRoot(c: PCell) {.rtl, inl.} =
@@ -276,7 +289,7 @@ proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerProc.} =
 proc initGC() =
   when not defined(useNimRtl):
     when traceGC:
-      for i in low(TCellState)..high(TCellState): init(states[i])
+      for i in low(CellState)..high(CellState): init(states[i])
     gch.cycleThreshold = InitialCycleThreshold
     gch.stat.stackScans = 0
     gch.stat.cycleCollections = 0
@@ -292,28 +305,15 @@ proc initGC() =
     when useMarkForDebug or useBackupGc:
       init(gch.marked)
 
-var
-  localGcInitialized {.rtlThreadVar.}: bool
-
-proc setupForeignThreadGc*() =
-  ## call this if you registered a callback that will be run from a thread not
-  ## under your control. This has a cheap thread-local guard, so the GC for
-  ## this thread will only be initialized once per thread, no matter how often
-  ## it is called.
-  if not localGcInitialized:
-    localGcInitialized = true
-    var stackTop {.volatile.}: pointer
-    setStackBottom(addr(stackTop))
-    initGC()
-
 when useMarkForDebug or useBackupGc:
   type
-    TGlobalMarkerProc = proc () {.nimcall, benign.}
+    GlobalMarkerProc = proc () {.nimcall, benign.}
+  {.deprecated: [TGlobalMarkerProc: GlobalMarkerProc].}
   var
     globalMarkersLen: int
-    globalMarkers: array[0.. 7_000, TGlobalMarkerProc]
+    globalMarkers: array[0.. 7_000, GlobalMarkerProc]
 
-  proc nimRegisterGlobalMarker(markerProc: TGlobalMarkerProc) {.compilerProc.} =
+  proc nimRegisterGlobalMarker(markerProc: GlobalMarkerProc) {.compilerProc.} =
     if globalMarkersLen <= high(globalMarkers):
       globalMarkers[globalMarkersLen] = markerProc
       inc globalMarkersLen
@@ -321,11 +321,11 @@ when useMarkForDebug or useBackupGc:
       echo "[GC] cannot register global variable; too many global variables"
       quit 1
 
-proc cellsetReset(s: var TCellSet) =
+proc cellsetReset(s: var CellSet) =
   deinit(s)
   init(s)
 
-proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) {.benign.} =
+proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: WalkOp) {.benign.} =
   var d = cast[ByteAddress](dest)
   case n.kind
   of nkSlot: forAllChildrenAux(cast[pointer](d +% n.offset), n.typ, op)
@@ -345,7 +345,7 @@ proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) {.benign.} =
     if m != nil: forAllSlotsAux(dest, m, op)
   of nkNone: sysAssert(false, "forAllSlotsAux")
 
-proc forAllChildrenAux(dest: pointer, mt: PNimType, op: TWalkOp) =
+proc forAllChildrenAux(dest: pointer, mt: PNimType, op: WalkOp) =
   var d = cast[ByteAddress](dest)
   if dest == nil: return # nothing to do
   if ntfNoRefs notin mt.flags:
@@ -359,7 +359,7 @@ proc forAllChildrenAux(dest: pointer, mt: PNimType, op: TWalkOp) =
         forAllChildrenAux(cast[pointer](d +% i *% mt.base.size), mt.base, op)
     else: discard
 
-proc forAllChildren(cell: PCell, op: TWalkOp) =
+proc forAllChildren(cell: PCell, op: WalkOp) =
   gcAssert(cell != nil, "forAllChildren: 1")
   gcAssert(isAllocatedPtr(gch.region, cell), "forAllChildren: 2")
   gcAssert(cell.typ != nil, "forAllChildren: 3")
@@ -380,7 +380,7 @@ proc forAllChildren(cell: PCell, op: TWalkOp) =
             GenericSeqSize), cell.typ.base, op)
     else: discard
 
-proc addNewObjToZCT(res: PCell, gch: var TGcHeap) {.inline.} =
+proc addNewObjToZCT(res: PCell, gch: var GcHeap) {.inline.} =
   # we check the last 8 entries (cache line) for a slot that could be reused.
   # In 63% of all cases we succeed here! But we have to optimize the heck
   # out of this small linear search so that ``newObj`` is not slowed down.
@@ -431,13 +431,13 @@ proc gcInvariant*() =
     markForDebug(gch)
 {.pop.}
 
-proc rawNewObj(typ: PNimType, size: int, gch: var TGcHeap): pointer =
+proc rawNewObj(typ: PNimType, size: int, gch: var GcHeap): pointer =
   # generates a new object and sets its reference counter to 0
   sysAssert(allocInv(gch.region), "rawNewObj begin")
   acquire(gch)
   gcAssert(typ.kind in {tyRef, tyString, tySequence}, "newObj: 1")
   collectCT(gch)
-  var res = cast[PCell](rawAlloc(gch.region, size + sizeof(TCell)))
+  var res = cast[PCell](rawAlloc(gch.region, size + sizeof(Cell)))
   gcAssert((cast[ByteAddress](res) and (MemAlign-1)) == 0, "newObj: 2")
   # now it is buffered in the ZCT
   res.typ = typ
@@ -486,7 +486,7 @@ proc newObjRC1(typ: PNimType, size: int): pointer {.compilerRtl.} =
   collectCT(gch)
   sysAssert(allocInv(gch.region), "newObjRC1 after collectCT")
 
-  var res = cast[PCell](rawAlloc(gch.region, size + sizeof(TCell)))
+  var res = cast[PCell](rawAlloc(gch.region, size + sizeof(Cell)))
   sysAssert(allocInv(gch.region), "newObjRC1 after rawAlloc")
   sysAssert((cast[ByteAddress](res) and (MemAlign-1)) == 0, "newObj: 2")
   # now it is buffered in the ZCT
@@ -515,7 +515,7 @@ proc newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl.} =
   cast[PGenericSeq](result).reserved = len
   when defined(memProfiler): nimProfile(size)
 
-proc growObj(old: pointer, newsize: int, gch: var TGcHeap): pointer =
+proc growObj(old: pointer, newsize: int, gch: var GcHeap): pointer =
   acquire(gch)
   collectCT(gch)
   var ol = usrToCell(old)
@@ -523,13 +523,13 @@ proc growObj(old: pointer, newsize: int, gch: var TGcHeap): pointer =
   gcAssert(ol.typ.kind in {tyString, tySequence}, "growObj: 2")
   sysAssert(allocInv(gch.region), "growObj begin")
 
-  var res = cast[PCell](rawAlloc(gch.region, newsize + sizeof(TCell)))
+  var res = cast[PCell](rawAlloc(gch.region, newsize + sizeof(Cell)))
   var elemSize = 1
   if ol.typ.kind != tyString: elemSize = ol.typ.base.size
 
   var oldsize = cast[PGenericSeq](old).len*elemSize + GenericSeqSize
-  copyMem(res, ol, oldsize + sizeof(TCell))
-  zeroMem(cast[pointer](cast[ByteAddress](res)+% oldsize +% sizeof(TCell)),
+  copyMem(res, ol, oldsize + sizeof(Cell))
+  zeroMem(cast[pointer](cast[ByteAddress](res)+% oldsize +% sizeof(Cell)),
           newsize-oldsize)
   sysAssert((cast[ByteAddress](res) and (MemAlign-1)) == 0, "growObj: 3")
   # This can be wrong for intermediate temps that are nevertheless on the
@@ -564,7 +564,7 @@ proc growObj(old: pointer, newsize: int, gch: var TGcHeap): pointer =
       decRef(ol)
   else:
     sysAssert(ol.typ != nil, "growObj: 5")
-    zeroMem(ol, sizeof(TCell))
+    zeroMem(ol, sizeof(Cell))
   release(gch)
   when useCellIds:
     inc gch.idGenerator
@@ -580,7 +580,7 @@ proc growObj(old: pointer, newsize: int): pointer {.rtl.} =
 
 # ---------------- cycle collector -------------------------------------------
 
-proc freeCyclicCell(gch: var TGcHeap, c: PCell) =
+proc freeCyclicCell(gch: var GcHeap, c: PCell) =
   prepareDealloc(c)
   gcTrace(c, csCycFreed)
   when logGC: writeCell("cycle collector dealloc cell", c)
@@ -589,7 +589,7 @@ proc freeCyclicCell(gch: var TGcHeap, c: PCell) =
     rawDealloc(gch.region, c)
   else:
     gcAssert(c.typ != nil, "freeCyclicCell")
-    zeroMem(c, sizeof(TCell))
+    zeroMem(c, sizeof(Cell))
 
 proc markGray(s: PCell) =
   if s.color != rcGray:
@@ -620,7 +620,7 @@ proc collectWhite(s: PCell) =
     forAllChildren(s, waCollectWhite)
     freeCyclicCell(gch, s)
 
-proc markRoots(gch: var TGcHeap) =
+proc markRoots(gch: var GcHeap) =
   var tabSize = 0
   for s in elements(gch.cycleRoots):
     #writeCell("markRoot", s)
@@ -635,7 +635,7 @@ proc markRoots(gch: var TGcHeap) =
   gch.stat.cycleTableSize = max(gch.stat.cycleTableSize, tabSize)
 
 when useBackupGc:
-  proc sweep(gch: var TGcHeap) =
+  proc sweep(gch: var GcHeap) =
     for x in allObjects(gch.region):
       if isCell(x):
         # cast to PCell is correct here:
@@ -643,7 +643,7 @@ when useBackupGc:
         if c notin gch.marked: freeCyclicCell(gch, c)
 
 when useMarkForDebug or useBackupGc:
-  proc markS(gch: var TGcHeap, c: PCell) =
+  proc markS(gch: var GcHeap, c: PCell) =
     incl(gch.marked, c)
     gcAssert gch.tempStack.len == 0, "stack not empty!"
     forAllChildren(c, waMarkPrecise)
@@ -653,10 +653,10 @@ when useMarkForDebug or useBackupGc:
       if not containsOrIncl(gch.marked, d):
         forAllChildren(d, waMarkPrecise)
 
-  proc markGlobals(gch: var TGcHeap) =
+  proc markGlobals(gch: var GcHeap) =
     for i in 0 .. < globalMarkersLen: globalMarkers[i]()
 
-  proc stackMarkS(gch: var TGcHeap, p: pointer) {.inline.} =
+  proc stackMarkS(gch: var GcHeap, p: pointer) {.inline.} =
     # the addresses are not as cells on the stack, so turn them to cells:
     var cell = usrToCell(p)
     var c = cast[TAddress](cell)
@@ -688,7 +688,7 @@ when logGC:
       forAllChildren(s, waDebug)
       c_fprintf(c_stdout, "}\n")
 
-proc doOperation(p: pointer, op: TWalkOp) =
+proc doOperation(p: pointer, op: WalkOp) =
   if p == nil: return
   var c: PCell = usrToCell(p)
   gcAssert(c != nil, "doOperation: 1")
@@ -733,19 +733,19 @@ proc doOperation(p: pointer, op: TWalkOp) =
   #of waDebug: debugGraph(c)
 
 proc nimGCvisit(d: pointer, op: int) {.compilerRtl.} =
-  doOperation(d, TWalkOp(op))
+  doOperation(d, WalkOp(op))
 
-proc collectZCT(gch: var TGcHeap): bool {.benign.}
+proc collectZCT(gch: var GcHeap): bool {.benign.}
 
 when useMarkForDebug or useBackupGc:
-  proc markStackAndRegistersForSweep(gch: var TGcHeap) {.noinline, cdecl,
+  proc markStackAndRegistersForSweep(gch: var GcHeap) {.noinline, cdecl,
                                                          benign.}
 
-proc collectRoots(gch: var TGcHeap) =
+proc collectRoots(gch: var GcHeap) =
   for s in elements(gch.cycleRoots):
     collectWhite(s)
 
-proc collectCycles(gch: var TGcHeap) =
+proc collectCycles(gch: var GcHeap) =
   # ensure the ZCT 'color' is not used:
   while gch.zct.len > 0: discard collectZCT(gch)
   when useBackupGc:
@@ -778,7 +778,7 @@ proc collectCycles(gch: var TGcHeap) =
     if cycleRootsLen != 0:
       cfprintf(cstdout, "cycle roots: %ld\n", cycleRootsLen)
 
-proc gcMark(gch: var TGcHeap, p: pointer) {.inline.} =
+proc gcMark(gch: var GcHeap, p: pointer) {.inline.} =
   # the addresses are not as cells on the stack, so turn them to cells:
   sysAssert(allocInv(gch.region), "gcMark begin")
   var cell = usrToCell(p)
@@ -798,7 +798,7 @@ proc gcMark(gch: var TGcHeap, p: pointer) {.inline.} =
         add(gch.decStack, cell)
   sysAssert(allocInv(gch.region), "gcMark end")
 
-proc markThreadStacks(gch: var TGcHeap) =
+proc markThreadStacks(gch: var GcHeap) =
   when hasThreadSupport and hasSharedHeap:
     {.error: "not fully implemented".}
     var it = threadList
@@ -814,142 +814,16 @@ proc markThreadStacks(gch: var TGcHeap) =
         sp = sp +% sizeof(pointer)
       it = it.next
 
-# ----------------- stack management --------------------------------------
-#  inspired from Smart Eiffel
-
-when defined(sparc):
-  const stackIncreases = false
-elif defined(hppa) or defined(hp9000) or defined(hp9000s300) or
-     defined(hp9000s700) or defined(hp9000s800) or defined(hp9000s820):
-  const stackIncreases = true
-else:
-  const stackIncreases = false
-
-when not defined(useNimRtl):
-  {.push stack_trace: off.}
-  proc setStackBottom(theStackBottom: pointer) =
-    #c_fprintf(c_stdout, "stack bottom: %p;\n", theStackBottom)
-    # the first init must be the one that defines the stack bottom:
-    if gch.stackBottom == nil: gch.stackBottom = theStackBottom
-    else:
-      var a = cast[ByteAddress](theStackBottom) # and not PageMask - PageSize*2
-      var b = cast[ByteAddress](gch.stackBottom)
-      #c_fprintf(c_stdout, "old: %p new: %p;\n",gch.stackBottom,theStackBottom)
-      when stackIncreases:
-        gch.stackBottom = cast[pointer](min(a, b))
-      else:
-        gch.stackBottom = cast[pointer](max(a, b))
-  {.pop.}
-
-proc stackSize(): int {.noinline.} =
-  var stackTop {.volatile.}: pointer
-  result = abs(cast[int](addr(stackTop)) - cast[int](gch.stackBottom))
-
-when defined(sparc): # For SPARC architecture.
-  proc isOnStack(p: pointer): bool =
-    var stackTop {.volatile.}: pointer
-    stackTop = addr(stackTop)
-    var b = cast[TAddress](gch.stackBottom)
-    var a = cast[TAddress](stackTop)
-    var x = cast[TAddress](p)
-    result = a <=% x and x <=% b
-
-  template forEachStackSlot(gch, gcMark: expr) {.immediate, dirty.} =
-    when defined(sparcv9):
-      asm  """"flushw \n" """
-    else:
-      asm  """"ta      0x3   ! ST_FLUSH_WINDOWS\n" """
-
-    var
-      max = gch.stackBottom
-      sp: PPointer
-      stackTop: array[0..1, pointer]
-    sp = addr(stackTop[0])
-    # Addresses decrease as the stack grows.
-    while sp <= max:
-      gcMark(gch, sp[])
-      sp = cast[PPointer](cast[TAddress](sp) +% sizeof(pointer))
-
-elif defined(ELATE):
-  {.error: "stack marking code is to be written for this architecture".}
-
-elif stackIncreases:
-  # ---------------------------------------------------------------------------
-  # Generic code for architectures where addresses increase as the stack grows.
-  # ---------------------------------------------------------------------------
-  proc isOnStack(p: pointer): bool =
-    var stackTop {.volatile.}: pointer
-    stackTop = addr(stackTop)
-    var a = cast[TAddress](gch.stackBottom)
-    var b = cast[TAddress](stackTop)
-    var x = cast[TAddress](p)
-    result = a <=% x and x <=% b
-
-  var
-    jmpbufSize {.importc: "sizeof(jmp_buf)", nodecl.}: int
-      # a little hack to get the size of a TJmpBuf in the generated C code
-      # in a platform independent way
-
-  template forEachStackSlot(gch, gcMark: expr) {.immediate, dirty.} =
-    var registers: C_JmpBuf
-    if c_setjmp(registers) == 0'i32: # To fill the C stack with registers.
-      var max = cast[TAddress](gch.stackBottom)
-      var sp = cast[TAddress](addr(registers)) +% jmpbufSize -% sizeof(pointer)
-      # sp will traverse the JMP_BUF as well (jmp_buf size is added,
-      # otherwise sp would be below the registers structure).
-      while sp >=% max:
-        gcMark(gch, cast[ppointer](sp)[])
-        sp = sp -% sizeof(pointer)
-
-else:
-  # ---------------------------------------------------------------------------
-  # Generic code for architectures where addresses decrease as the stack grows.
-  # ---------------------------------------------------------------------------
-  proc isOnStack(p: pointer): bool =
-    var stackTop {.volatile.}: pointer
-    stackTop = addr(stackTop)
-    var b = cast[ByteAddress](gch.stackBottom)
-    var a = cast[ByteAddress](stackTop)
-    var x = cast[ByteAddress](p)
-    result = a <=% x and x <=% b
-
-  template forEachStackSlot(gch, gcMark: expr) {.immediate, dirty.} =
-    # We use a jmp_buf buffer that is in the C stack.
-    # Used to traverse the stack and registers assuming
-    # that 'setjmp' will save registers in the C stack.
-    type PStackSlice = ptr array [0..7, pointer]
-    var registers {.noinit.}: C_JmpBuf
-    if c_setjmp(registers) == 0'i32: # To fill the C stack with registers.
-      var max = cast[ByteAddress](gch.stackBottom)
-      var sp = cast[ByteAddress](addr(registers))
-      # loop unrolled:
-      while sp <% max - 8*sizeof(pointer):
-        gcMark(gch, cast[PStackSlice](sp)[0])
-        gcMark(gch, cast[PStackSlice](sp)[1])
-        gcMark(gch, cast[PStackSlice](sp)[2])
-        gcMark(gch, cast[PStackSlice](sp)[3])
-        gcMark(gch, cast[PStackSlice](sp)[4])
-        gcMark(gch, cast[PStackSlice](sp)[5])
-        gcMark(gch, cast[PStackSlice](sp)[6])
-        gcMark(gch, cast[PStackSlice](sp)[7])
-        sp = sp +% sizeof(pointer)*8
-      # last few entries:
-      while sp <=% max:
-        gcMark(gch, cast[PPointer](sp)[])
-        sp = sp +% sizeof(pointer)
+include gc_common
 
-proc markStackAndRegisters(gch: var TGcHeap) {.noinline, cdecl.} =
+proc markStackAndRegisters(gch: var GcHeap) {.noinline, cdecl.} =
   forEachStackSlot(gch, gcMark)
 
 when useMarkForDebug or useBackupGc:
-  proc markStackAndRegistersForSweep(gch: var TGcHeap) =
+  proc markStackAndRegistersForSweep(gch: var GcHeap) =
     forEachStackSlot(gch, stackMarkS)
 
-# ----------------------------------------------------------------------------
-# end of non-portable code
-# ----------------------------------------------------------------------------
-
-proc collectZCT(gch: var TGcHeap): bool =
+proc collectZCT(gch: var GcHeap): bool =
   # Note: Freeing may add child objects to the ZCT! So essentially we do
   # deep freeing, which is bad for incremental operation. In order to
   # avoid a deep stack, we move objects to keep the ZCT small.
@@ -959,7 +833,7 @@ proc collectZCT(gch: var TGcHeap): bool =
 
   when withRealTime:
     var steps = workPackage
-    var t0: TTicks
+    var t0: Ticks
     if gch.maxPause > 0: t0 = getticks()
   while L[] > 0:
     var c = gch.zct.d[0]
@@ -992,7 +866,7 @@ proc collectZCT(gch: var TGcHeap): bool =
         rawDealloc(gch.region, c)
       else:
         sysAssert(c.typ != nil, "collectZCT 2")
-        zeroMem(c, sizeof(TCell))
+        zeroMem(c, sizeof(Cell))
     when withRealTime:
       if steps == 0:
         steps = workPackage
@@ -1005,7 +879,7 @@ proc collectZCT(gch: var TGcHeap): bool =
             return false
   result = true
 
-proc unmarkStackAndRegisters(gch: var TGcHeap) =
+proc unmarkStackAndRegisters(gch: var GcHeap) =
   var d = gch.decStack.d
   for i in 0..gch.decStack.len-1:
     sysAssert isAllocatedPtr(gch.region, d[i]), "unmarkStackAndRegisters"
@@ -1017,12 +891,13 @@ proc unmarkStackAndRegisters(gch: var TGcHeap) =
     #sysAssert c.typ != nil, "unmarkStackAndRegisters 2"
   gch.decStack.len = 0
 
-proc collectCTBody(gch: var TGcHeap) =
+proc collectCTBody(gch: var GcHeap) =
   when withRealTime:
     let t0 = getticks()
   sysAssert(allocInv(gch.region), "collectCT: begin")
 
-  gch.stat.maxStackSize = max(gch.stat.maxStackSize, stackSize())
+  when not defined(nimCoroutines):
+    gch.stat.maxStackSize = max(gch.stat.maxStackSize, stackSize())
   sysAssert(gch.decStack.len == 0, "collectCT")
   prepareForInteriorPointerChecking(gch.region)
   markStackAndRegisters(gch)
@@ -1049,15 +924,23 @@ proc collectCTBody(gch: var TGcHeap) =
         c_fprintf(c_stdout, "[GC] missed deadline: %ld\n", duration)
 
 when useMarkForDebug or useBackupGc:
-  proc markForDebug(gch: var TGcHeap) =
+  proc markForDebug(gch: var GcHeap) =
     markStackAndRegistersForSweep(gch)
     markGlobals(gch)
 
-proc collectCT(gch: var TGcHeap) =
+when defined(nimCoroutines):
+  proc currentStackSizes(): int =
+    for stack in items(gch.stack):
+      result = result + stackSize(stack.starts, stack.pos)
+
+proc collectCT(gch: var GcHeap) =
   # stackMarkCosts prevents some pathological behaviour: Stack marking
   # becomes more expensive with large stacks and large stacks mean that
   # cells with RC=0 are more likely to be kept alive by the stack.
-  let stackMarkCosts = max(stackSize() div (16*sizeof(int)), ZctThreshold)
+  when defined(nimCoroutines):
+    let stackMarkCosts = max(currentStackSizes() div (16*sizeof(int)), ZctThreshold)
+  else:
+    let stackMarkCosts = max(stackSize() div (16*sizeof(int)), ZctThreshold)
   if (gch.zct.len >= stackMarkCosts or (cycleGC and
       getOccupiedMem(gch.region)>=gch.cycleThreshold) or alwaysGC) and
       gch.recGcLock == 0:
@@ -1068,13 +951,13 @@ proc collectCT(gch: var TGcHeap) =
     collectCTBody(gch)
 
 when withRealTime:
-  proc toNano(x: int): TNanos {.inline.} =
+  proc toNano(x: int): Nanos {.inline.} =
     result = x * 1000
 
   proc GC_setMaxPause*(MaxPauseInUs: int) =
     gch.maxPause = MaxPauseInUs.toNano
 
-  proc GC_step(gch: var TGcHeap, us: int, strongAdvice: bool) =
+  proc GC_step(gch: var GcHeap, us: int, strongAdvice: bool) =
     acquire(gch)
     gch.maxPause = us.toNano
     if (gch.zct.len >= ZctThreshold or (cycleGC and
@@ -1126,8 +1009,13 @@ when not defined(useNimRtl):
              "[GC] max threshold: " & $gch.stat.maxThreshold & "\n" &
              "[GC] zct capacity: " & $gch.zct.cap & "\n" &
              "[GC] max cycle table size: " & $gch.stat.cycleTableSize & "\n" &
-             "[GC] max stack size: " & $gch.stat.maxStackSize & "\n" &
              "[GC] max pause time [ms]: " & $(gch.stat.maxPause div 1000_000)
+    when defined(nimCoroutines):
+      result = result & "[GC] number of stacks: " & $gch.stack.len & "\n"
+      for stack in items(gch.stack):
+        result = result & "[GC]   stack " & stack.starts.repr & "[GC]     max stack size " & $stack.maxStackSize & "\n"
+    else:
+      result = result & "[GC] max stack size: " & $gch.stat.maxStackSize & "\n"
     GC_enable()
 
 {.pop.}
diff --git a/lib/system/gc2.nim b/lib/system/gc2.nim
index 4e3dee51c..4ca0d144f 100644
--- a/lib/system/gc2.nim
+++ b/lib/system/gc2.nim
@@ -37,24 +37,24 @@ const
 
   rcAlive = 0b00000           # object is reachable.
                               # color *black* in the original paper
-                              
+
   rcCycleCandidate = 0b00001  # possible root of a cycle. *purple*
 
   rcDecRefApplied = 0b00010   # the first dec-ref phase of the
                               # collector was already applied to this
                               # object. *gray*
-                              
+
   rcMaybeDead = 0b00011       # this object is a candidate for deletion
                               # during the collect cycles algorithm.
                               # *white*.
-                              
+
   rcReallyDead = 0b00100      # this is proved to be garbage
-  
+
   rcRetiredBuffer = 0b00101   # this is a seq or string buffer that
                               # was replaced by a resize operation.
                               # see growObj for details
 
-  rcColorMask = TRefCount(0b00111)
+  rcColorMask = RefCount(0b00111)
 
   rcZct = 0b01000             # already added to ZCT
   rcInCycleRoots = 0b10000    # already buffered as cycle candidate
@@ -80,14 +80,14 @@ const
     # The bit must also be set for new objects that are not rc1 and it must be
     # examined in the decref loop in collectCycles.
     # XXX: not implemented yet as tests didn't show any improvement from this
-   
+
   MarkingSkipsAcyclicObjects = true
-    # Acyclic objects can be safely ignored in the mark and scan phases, 
+    # Acyclic objects can be safely ignored in the mark and scan phases,
     # because they cannot contribute to the internal count.
     # XXX: if we generate specialized `markCyclic` and `markAcyclic`
     # procs we can further optimize this as there won't be need for any
     # checks in the code
-  
+
   MinimumStackMarking = false
     # Try to scan only the user stack and ignore the part of the stack
     # belonging to the GC itself. see setStackTop for further info.
@@ -97,34 +97,34 @@ const
   CollectCyclesStats = false
 
 type
-  TWalkOp = enum
+  WalkOp = enum
     waPush
 
-  TFinalizer {.compilerproc.} = proc (self: pointer) {.nimcall.}
+  Finalizer {.compilerproc.} = proc (self: pointer) {.nimcall.}
     # A ref type can have a finalizer that is called before the object's
     # storage is freed.
 
-  TGcStat {.final, pure.} = object
+  GcStat {.final, pure.} = object
     stackScans: int          # number of performed stack scans (for statistics)
     cycleCollections: int    # number of performed full collections
     maxThreshold: int        # max threshold that has been set
     maxStackSize: int        # max stack size
     maxStackCells: int       # max stack cells in ``decStack``
-    cycleTableSize: int      # max entries in cycle table  
+    cycleTableSize: int      # max entries in cycle table
     maxPause: int64          # max measured GC pause in nanoseconds
-  
-  TGcHeap {.final, pure.} = object # this contains the zero count and
+
+  GcHeap {.final, pure.} = object # this contains the zero count and
                                    # non-zero count table
     stackBottom: pointer
     stackTop: pointer
     cycleThreshold: int
-    zct: TCellSeq            # the zero count table
-    decStack: TCellSeq       # cells in the stack that are to decref again
-    cycleRoots: TCellSeq
-    tempStack: TCellSeq      # temporary stack for recursion elimination
-    freeStack: TCellSeq      # objects ready to be freed
+    zct: CellSeq             # the zero count table
+    decStack: CellSeq        # cells in the stack that are to decref again
+    cycleRoots: CellSeq
+    tempStack: CellSeq       # temporary stack for recursion elimination
+    freeStack: CellSeq       # objects ready to be freed
     recGcLock: int           # prevent recursion via finalizers; no thread lock
-    cycleRootsTrimIdx: int   # Trimming is a light-weight collection of the 
+    cycleRootsTrimIdx: int   # Trimming is a light-weight collection of the
                              # cycle roots table that uses a cheap linear scan
                              # to find only possitively dead objects.
                              # One strategy is to perform it only for new objects
@@ -132,21 +132,22 @@ type
                              # This index indicates the start of the range of
                              # such new objects within the table.
     when withRealTime:
-      maxPause: TNanos       # max allowed pause in nanoseconds; active if > 0
-    region: TMemRegion       # garbage collected region
-    stat: TGcStat
-
+      maxPause: Nanos        # max allowed pause in nanoseconds; active if > 0
+    region: MemRegion        # garbage collected region
+    stat: GcStat
+{.deprecated: [TWalkOp: WalkOp, TFinalizer: Finalizer, TGcStat: GcStat,
+              TGcHeap: GcHeap].}
 var
-  gch* {.rtlThreadVar.}: TGcHeap
+  gch* {.rtlThreadVar.}: GcHeap
 
 when not defined(useNimRtl):
   instantiateForRegion(gch.region)
 
-template acquire(gch: TGcHeap) = 
+template acquire(gch: GcHeap) =
   when hasThreadSupport and hasSharedHeap:
     AcquireSys(HeapLock)
 
-template release(gch: TGcHeap) = 
+template release(gch: GcHeap) =
   when hasThreadSupport and hasSharedHeap:
     releaseSys(HeapLock)
 
@@ -169,7 +170,7 @@ template isDead(c: Pcell): expr =
   c.isBitUp(rcReallyDead) # also covers rcRetiredBuffer
 
 template clearBit(c: PCell, bit): expr =
-  c.refcount = c.refcount and (not TRefCount(bit))
+  c.refcount = c.refcount and (not RefCount(bit))
 
 when debugGC:
   var gcCollectionIdx = 0
@@ -184,7 +185,7 @@ when debugGC:
     of rcRetiredBuffer: return "retired"
     of rcReallyDead: return "dead"
     else: return "unknown?"
-  
+
   proc inCycleRootsStr(c: PCell): cstring =
     if c.isBitUp(rcInCycleRoots): result = "cycleroot"
     else: result = ""
@@ -206,7 +207,7 @@ when debugGC:
       c_fprintf(c_stdout, "[GC] %s: %p %d rc=%ld\n",
                 msg, c, kind, c.refcount shr rcShift)
 
-proc addZCT(zct: var TCellSeq, c: PCell) {.noinline.} =
+proc addZCT(zct: var CellSeq, c: PCell) {.noinline.} =
   if c.isBitDown(rcZct):
     c.setBit rcZct
     zct.add c
@@ -221,10 +222,10 @@ template setStackTop(gch) =
     var stackTop {.volatile.}: pointer
     gch.stackTop = addr(stackTop)
 
-template addCycleRoot(cycleRoots: var TCellSeq, c: PCell) =
+template addCycleRoot(cycleRoots: var CellSeq, c: PCell) =
   if c.color != rcCycleCandidate:
     c.setColor rcCycleCandidate
-    
+
     # the object may be buffered already. for example, consider:
     # decref; incref; decref
     if c.isBitDown(rcInCycleRoots):
@@ -233,11 +234,11 @@ template addCycleRoot(cycleRoots: var TCellSeq, c: PCell) =
 
 proc cellToUsr(cell: PCell): pointer {.inline.} =
   # convert object (=pointer to refcount) to pointer to userdata
-  result = cast[pointer](cast[ByteAddress](cell)+%ByteAddress(sizeof(TCell)))
+  result = cast[pointer](cast[ByteAddress](cell)+%ByteAddress(sizeof(Cell)))
 
 proc usrToCell*(usr: pointer): PCell {.inline.} =
   # convert pointer to userdata to object (=pointer to refcount)
-  result = cast[PCell](cast[ByteAddress](usr)-%ByteAddress(sizeof(TCell)))
+  result = cast[PCell](cast[ByteAddress](usr)-%ByteAddress(sizeof(Cell)))
 
 proc canbeCycleRoot(c: PCell): bool {.inline.} =
   result = ntfAcyclic notin c.typ.flags
@@ -254,11 +255,11 @@ when BitsPerPage mod (sizeof(int)*8) != 0:
   {.error: "(BitsPerPage mod BitsPerUnit) should be zero!".}
 
 # forward declarations:
-proc collectCT(gch: var TGcHeap)
+proc collectCT(gch: var GcHeap)
 proc isOnStack*(p: pointer): bool {.noinline.}
-proc forAllChildren(cell: PCell, op: TWalkOp)
-proc doOperation(p: pointer, op: TWalkOp)
-proc forAllChildrenAux(dest: pointer, mt: PNimType, op: TWalkOp)
+proc forAllChildren(cell: PCell, op: WalkOp)
+proc doOperation(p: pointer, op: WalkOp)
+proc forAllChildrenAux(dest: pointer, mt: PNimType, op: WalkOp)
 # we need the prototype here for debugging purposes
 
 proc prepareDealloc(cell: PCell) =
@@ -269,18 +270,19 @@ proc prepareDealloc(cell: PCell) =
     # prevend recursive entering here by a lock.
     # XXX: we should set the cell's children to nil!
     inc(gch.recGcLock)
-    (cast[TFinalizer](cell.typ.finalizer))(cellToUsr(cell))
+    (cast[Finalizer](cell.typ.finalizer))(cellToUsr(cell))
     dec(gch.recGcLock)
 
 when traceGC:
   # traceGC is a special switch to enable extensive debugging
   type
-    TCellState = enum
+    CellState = enum
       csAllocated, csFreed
+  {.deprecated: [TCellState: CellState].}
   var
-    states: array[TCellState, TCellSet]
+    states: array[CellState, CellSet]
 
-  proc traceCell(c: PCell, state: TCellState) =
+  proc traceCell(c: PCell, state: CellState) =
     case state
     of csAllocated:
       if c in states[csAllocated]:
@@ -300,12 +302,12 @@ when traceGC:
     incl(states[state], c)
 
   proc computeCellWeight(c: PCell): int =
-    var x: TCellSet
+    var x: CellSet
     x.init
 
     let startLen = gch.tempStack.len
     c.forAllChildren waPush
-    
+
     while startLen != gch.tempStack.len:
       dec gch.tempStack.len
       var c = gch.tempStack.d[gch.tempStack.len]
@@ -329,7 +331,7 @@ when traceGC:
     if c.isBitUp(rcMarkBit) and not isMarked:
       writecell("cyclic cell", cell)
       cprintf "Weight %d\n", cell.computeCellWeight
-      
+
   proc writeLeakage(onlyRoots: bool) =
     if onlyRoots:
       for c in elements(states[csAllocated]):
@@ -354,7 +356,7 @@ template WithHeapLock(blk: stmt): stmt =
   blk
   when hasThreadSupport and hasSharedHeap: ReleaseSys(HeapLock)
 
-proc rtlAddCycleRoot(c: PCell) {.rtl, inl.} = 
+proc rtlAddCycleRoot(c: PCell) {.rtl, inl.} =
   # we MUST access gch as a global here, because this crosses DLL boundaries!
   WithHeapLock: addCycleRoot(gch.cycleRoots, c)
 
@@ -363,30 +365,32 @@ proc rtlAddZCT(c: PCell) {.rtl, inl.} =
   WithHeapLock: addZCT(gch.zct, c)
 
 type
-  TCyclicMode = enum
+  CyclicMode = enum
     Cyclic,
     Acyclic,
     MaybeCyclic
 
-  TReleaseType = enum
+  ReleaseType = enum
     AddToZTC
     FreeImmediately
 
-  THeapType = enum
+  HeapType = enum
     LocalHeap
     SharedHeap
+{.deprecated: [TCyclicMode: CyclicMode, TReleaseType: ReleaseType,
+              THeapType: HeapType].}
 
-template `++` (rc: TRefCount, heapType: THeapType): stmt =
+template `++` (rc: RefCount, heapType: HeapType): stmt =
   when heapType == SharedHeap:
     discard atomicInc(rc, rcIncrement)
   else:
     inc rc, rcIncrement
 
-template `--`(rc: TRefCount): expr =
+template `--`(rc: RefCount): expr =
   dec rc, rcIncrement
   rc <% rcIncrement
 
-template `--` (rc: TRefCount, heapType: THeapType): expr =
+template `--` (rc: RefCount, heapType: HeapType): expr =
   (when heapType == SharedHeap: atomicDec(rc, rcIncrement) <% rcIncrement else: --rc)
 
 template doDecRef(cc: PCell,
@@ -419,7 +423,7 @@ template doIncRef(cc: PCell,
     elif IncRefRemovesCandidates:
       c.setColor rcAlive
   # XXX: this is not really atomic enough!
-  
+
 proc nimGCref(p: pointer) {.compilerProc, inline.} = doIncRef(usrToCell(p))
 proc nimGCunref(p: pointer) {.compilerProc, inline.} = doDecRef(usrToCell(p))
 
@@ -445,7 +449,7 @@ proc asgnRef(dest: PPointer, src: pointer) {.compilerProc, inline.} =
   doAsgnRef(dest, src, LocalHeap, MaybeCyclic)
 
 proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerProc, inline.} =
-  # the code generator calls this proc if it is known at compile time that no 
+  # the code generator calls this proc if it is known at compile time that no
   # cycle is possible.
   doAsgnRef(dest, src, LocalHeap, Acyclic)
 
@@ -479,7 +483,7 @@ when hasThreadSupport and hasSharedHeap:
 proc initGC() =
   when not defined(useNimRtl):
     when traceGC:
-      for i in low(TCellState)..high(TCellState): init(states[i])
+      for i in low(CellState)..high(CellState): init(states[i])
     gch.cycleThreshold = InitialCycleThreshold
     gch.stat.stackScans = 0
     gch.stat.cycleCollections = 0
@@ -494,7 +498,7 @@ proc initGC() =
     init(gch.cycleRoots)
     init(gch.decStack)
 
-proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) =
+proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: WalkOp) =
   var d = cast[ByteAddress](dest)
   case n.kind
   of nkSlot: forAllChildrenAux(cast[pointer](d +% n.offset), n.typ, op)
@@ -505,7 +509,7 @@ proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) =
         if n.sons[i].typ.kind in {tyRef, tyString, tySequence}:
           doOperation(cast[PPointer](d +% n.sons[i].offset)[], op)
         else:
-          forAllChildrenAux(cast[pointer](d +% n.sons[i].offset), 
+          forAllChildrenAux(cast[pointer](d +% n.sons[i].offset),
                             n.sons[i].typ, op)
       else:
         forAllSlotsAux(dest, n.sons[i], op)
@@ -514,7 +518,7 @@ proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) =
     if m != nil: forAllSlotsAux(dest, m, op)
   of nkNone: sysAssert(false, "forAllSlotsAux")
 
-proc forAllChildrenAux(dest: pointer, mt: PNimType, op: TWalkOp) =
+proc forAllChildrenAux(dest: pointer, mt: PNimType, op: WalkOp) =
   var d = cast[ByteAddress](dest)
   if dest == nil: return # nothing to do
   if ntfNoRefs notin mt.flags:
@@ -528,7 +532,7 @@ proc forAllChildrenAux(dest: pointer, mt: PNimType, op: TWalkOp) =
         forAllChildrenAux(cast[pointer](d +% i *% mt.base.size), mt.base, op)
     else: discard
 
-proc forAllChildren(cell: PCell, op: TWalkOp) =
+proc forAllChildren(cell: PCell, op: WalkOp) =
   sysAssert(cell != nil, "forAllChildren: 1")
   sysAssert(cell.typ != nil, "forAllChildren: 2")
   sysAssert cell.typ.kind in {tyRef, tySequence, tyString}, "forAllChildren: 3"
@@ -549,11 +553,11 @@ proc forAllChildren(cell: PCell, op: TWalkOp) =
                             cell.typ.base, op)
     else: discard
 
-proc addNewObjToZCT(res: PCell, gch: var TGcHeap) {.inline.} =
+proc addNewObjToZCT(res: PCell, gch: var GcHeap) {.inline.} =
   # we check the last 8 entries (cache line) for a slot that could be reused.
   # In 63% of all cases we succeed here! But we have to optimize the heck
   # out of this small linear search so that ``newObj`` is not slowed down.
-  # 
+  #
   # Slots to try          cache hit
   # 1                     32%
   # 4                     59%
@@ -593,29 +597,29 @@ proc addNewObjToZCT(res: PCell, gch: var TGcHeap) {.inline.} =
         return
     add(gch.zct, res)
 
-proc rawNewObj(typ: PNimType, size: int, gch: var TGcHeap, rc1 = false): pointer =
+proc rawNewObj(typ: PNimType, size: int, gch: var GcHeap, rc1 = false): pointer =
   # generates a new object and sets its reference counter to 0
   acquire(gch)
   sysAssert(allocInv(gch.region), "rawNewObj begin")
   sysAssert(typ.kind in {tyRef, tyString, tySequence}, "newObj: 1")
-  
+
   collectCT(gch)
   sysAssert(allocInv(gch.region), "rawNewObj after collect")
 
-  var res = cast[PCell](rawAlloc(gch.region, size + sizeof(TCell)))
+  var res = cast[PCell](rawAlloc(gch.region, size + sizeof(Cell)))
   sysAssert(allocInv(gch.region), "rawNewObj after rawAlloc")
 
   sysAssert((cast[ByteAddress](res) and (MemAlign-1)) == 0, "newObj: 2")
-  
+
   res.typ = typ
-  
+
   when trackAllocationSource and not hasThreadSupport:
     if framePtr != nil and framePtr.prev != nil and framePtr.prev.prev != nil:
       res.filename = framePtr.prev.prev.filename
       res.line = framePtr.prev.prev.line
     else:
       res.filename = "nofile"
-  
+
   if rc1:
     res.refcount = rcIncrement # refcount is 1
   else:
@@ -627,9 +631,9 @@ proc rawNewObj(typ: PNimType, size: int, gch: var TGcHeap, rc1 = false): pointer
       res.setBit(rcInCycleRoots)
       res.setColor rcCycleCandidate
       gch.cycleRoots.add res
-    
+
   sysAssert(isAllocatedPtr(gch.region, res), "newObj: 3")
-  
+
   when logGC: writeCell("new cell", res)
   gcTrace(res, csAllocated)
   release(gch)
@@ -638,20 +642,20 @@ proc rawNewObj(typ: PNimType, size: int, gch: var TGcHeap, rc1 = false): pointer
 
 {.pop.}
 
-proc freeCell(gch: var TGcHeap, c: PCell) =
+proc freeCell(gch: var GcHeap, c: PCell) =
   # prepareDealloc(c)
   gcTrace(c, csFreed)
 
   when reallyDealloc: rawDealloc(gch.region, c)
   else:
     sysAssert(c.typ != nil, "collectCycles")
-    zeroMem(c, sizeof(TCell))
+    zeroMem(c, sizeof(Cell))
 
-template eraseAt(cells: var TCellSeq, at: int): stmt =
+template eraseAt(cells: var CellSeq, at: int): stmt =
   cells.d[at] = cells.d[cells.len - 1]
   dec cells.len
 
-template trimAt(roots: var TCellSeq, at: int): stmt =
+template trimAt(roots: var CellSeq, at: int): stmt =
   # This will remove a cycle root candidate during trimming.
   # a candidate is removed either because it received a refup and
   # it's no longer a candidate or because it received further refdowns
@@ -696,7 +700,7 @@ proc newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl.} =
   cast[PGenericSeq](result).len = len
   cast[PGenericSeq](result).reserved = len
 
-proc growObj(old: pointer, newsize: int, gch: var TGcHeap): pointer =
+proc growObj(old: pointer, newsize: int, gch: var GcHeap): pointer =
   acquire(gch)
   collectCT(gch)
   var ol = usrToCell(old)
@@ -704,39 +708,39 @@ proc growObj(old: pointer, newsize: int, gch: var TGcHeap): pointer =
   sysAssert(ol.typ.kind in {tyString, tySequence}, "growObj: 2")
   sysAssert(allocInv(gch.region), "growObj begin")
 
-  var res = cast[PCell](rawAlloc(gch.region, newsize + sizeof(TCell)))
+  var res = cast[PCell](rawAlloc(gch.region, newsize + sizeof(Cell)))
   var elemSize = if ol.typ.kind != tyString: ol.typ.base.size
                  else: 1
-  
+
   var oldsize = cast[PGenericSeq](old).len*elemSize + GenericSeqSize
-  
+
   # XXX: This should happen outside
   # call user-defined move code
   # call user-defined default constructor
-  copyMem(res, ol, oldsize + sizeof(TCell))
-  zeroMem(cast[pointer](cast[ByteAddress](res)+% oldsize +% sizeof(TCell)),
+  copyMem(res, ol, oldsize + sizeof(Cell))
+  zeroMem(cast[pointer](cast[ByteAddress](res)+% oldsize +% sizeof(Cell)),
           newsize-oldsize)
 
   sysAssert((cast[ByteAddress](res) and (MemAlign-1)) == 0, "growObj: 3")
   sysAssert(res.refcount shr rcShift <=% 1, "growObj: 4")
-  
+
   when false:
     if ol.isBitUp(rcZct):
       var j = gch.zct.len-1
       var d = gch.zct.d
-      while j >= 0: 
+      while j >= 0:
         if d[j] == ol:
           d[j] = res
           break
         dec(j)
-    
+
     if ol.isBitUp(rcInCycleRoots):
       for i in 0 .. <gch.cycleRoots.len:
         if gch.cycleRoots.d[i] == ol:
           eraseAt(gch.cycleRoots, i)
 
     freeCell(gch, ol)
-  
+
   else:
     # the new buffer inherits the GC state of the old one
     if res.isBitUp(rcZct): gch.zct.add res
@@ -778,26 +782,27 @@ proc growObj(old: pointer, newsize: int): pointer {.rtl.} =
 
 # ---------------- cycle collector -------------------------------------------
 
-proc doOperation(p: pointer, op: TWalkOp) =
+proc doOperation(p: pointer, op: WalkOp) =
   if p == nil: return
   var c: PCell = usrToCell(p)
   sysAssert(c != nil, "doOperation: 1")
   gch.tempStack.add c
-  
+
 proc nimGCvisit(d: pointer, op: int) {.compilerRtl.} =
-  doOperation(d, TWalkOp(op))
+  doOperation(d, WalkOp(op))
 
 type
-  TRecursionType = enum 
+  RecursionType = enum
     FromChildren,
     FromRoot
+{.deprecated: [TRecursionType: RecursionType].}
 
-proc collectZCT(gch: var TGcHeap): bool
+proc collectZCT(gch: var GcHeap): bool
 
-template pseudoRecursion(typ: TRecursionType, body: stmt): stmt =
+template pseudoRecursion(typ: RecursionType, body: stmt): stmt =
   discard
 
-proc trimCycleRoots(gch: var TGcHeap, startIdx = gch.cycleRootsTrimIdx) =
+proc trimCycleRoots(gch: var GcHeap, startIdx = gch.cycleRootsTrimIdx) =
   var i = startIdx
   while i < gch.cycleRoots.len:
     if gch.cycleRoots.d[i].color != rcCycleCandidate:
@@ -808,7 +813,7 @@ proc trimCycleRoots(gch: var TGcHeap, startIdx = gch.cycleRootsTrimIdx) =
   gch.cycleRootsTrimIdx = gch.cycleRoots.len
 
 # we now use a much simpler and non-recursive algorithm for cycle removal
-proc collectCycles(gch: var TGcHeap) =
+proc collectCycles(gch: var GcHeap) =
   if gch.cycleRoots.len == 0: return
   gch.stat.cycleTableSize = max(gch.stat.cycleTableSize, gch.cycleRoots.len)
 
@@ -833,14 +838,14 @@ proc collectCycles(gch: var TGcHeap) =
     let startLen = gch.tempStack.len
     cell.setColor rcAlive
     cell.forAllChildren waPush
-    
+
     while startLen != gch.tempStack.len:
       dec gch.tempStack.len
       var c = gch.tempStack.d[gch.tempStack.len]
       if c.color != rcAlive:
         c.setColor rcAlive
         c.forAllChildren waPush
-  
+
   template earlyMarkAlive(stackRoots) =
     # This marks all objects reachable from the stack as alive before any
     # of the other stages is executed. Such objects cannot be garbage and
@@ -851,7 +856,7 @@ proc collectCycles(gch: var TGcHeap) =
       earlyMarkAliveRec(c)
 
   earlyMarkAlive(gch.decStack)
-  
+
   when CollectCyclesStats:
     let tAfterEarlyMarkAlive = getTicks()
 
@@ -859,7 +864,7 @@ proc collectCycles(gch: var TGcHeap) =
     let startLen = gch.tempStack.len
     cell.setColor rcDecRefApplied
     cell.forAllChildren waPush
-    
+
     while startLen != gch.tempStack.len:
       dec gch.tempStack.len
       var c = gch.tempStack.d[gch.tempStack.len]
@@ -871,7 +876,7 @@ proc collectCycles(gch: var TGcHeap) =
       if c.color != rcDecRefApplied:
         c.setColor rcDecRefApplied
         c.forAllChildren waPush
- 
+
   template markRoots(roots) =
     var i = 0
     while i < roots.len:
@@ -880,34 +885,34 @@ proc collectCycles(gch: var TGcHeap) =
         inc i
       else:
         roots.trimAt i
-  
+
   markRoots(gch.cycleRoots)
-  
+
   when CollectCyclesStats:
     let tAfterMark = getTicks()
     c_printf "COLLECT CYCLES %d: %d/%d\n", gcCollectionIdx, gch.cycleRoots.len, l0
-  
+
   template recursiveMarkAlive(cell) =
     let startLen = gch.tempStack.len
     cell.setColor rcAlive
     cell.forAllChildren waPush
-    
+
     while startLen != gch.tempStack.len:
       dec gch.tempStack.len
       var c = gch.tempStack.d[gch.tempStack.len]
       if ignoreObject(c): continue
       inc c.refcount, rcIncrement
       inc increfs
-      
+
       if c.color != rcAlive:
         c.setColor rcAlive
         c.forAllChildren waPush
- 
+
   template scanRoots(roots) =
     for i in 0 .. <roots.len:
       let startLen = gch.tempStack.len
       gch.tempStack.add roots.d[i]
-      
+
       while startLen != gch.tempStack.len:
         dec gch.tempStack.len
         var c = gch.tempStack.d[gch.tempStack.len]
@@ -923,9 +928,9 @@ proc collectCycles(gch: var TGcHeap) =
             c.setColor rcMaybeDead
             inc maybedeads
             c.forAllChildren waPush
-  
+
   scanRoots(gch.cycleRoots)
-  
+
   when CollectCyclesStats:
     let tAfterScan = getTicks()
 
@@ -936,7 +941,7 @@ proc collectCycles(gch: var TGcHeap) =
 
       let startLen = gch.tempStack.len
       gch.tempStack.add c
-      
+
       while startLen != gch.tempStack.len:
         dec gch.tempStack.len
         var c = gch.tempStack.d[gch.tempStack.len]
@@ -960,7 +965,7 @@ proc collectCycles(gch: var TGcHeap) =
       freeCell(gch, gch.freeStack.d[i])
 
   collectDead(gch.cycleRoots)
-  
+
   when CollectCyclesStats:
     let tFinal = getTicks()
     cprintf "times:\n  early mark alive: %d ms\n  mark: %d ms\n  scan: %d ms\n  collect: %d ms\n  decrefs: %d\n  increfs: %d\n  marked dead: %d\n  collected: %d\n",
@@ -981,7 +986,7 @@ proc collectCycles(gch: var TGcHeap) =
 
   when MarkingSkipsAcyclicObjects:
     # Collect the acyclic objects that became unreachable due to collected
-    # cyclic objects. 
+    # cyclic objects.
     discard collectZCT(gch)
     # collectZCT may add new cycle candidates and we may decide to loop here
     # if gch.cycleRoots.len > 0: repeat
@@ -990,7 +995,7 @@ var gcDebugging* = false
 
 var seqdbg* : proc (s: PGenericSeq) {.cdecl.}
 
-proc gcMark(gch: var TGcHeap, p: pointer) {.inline.} =
+proc gcMark(gch: var GcHeap, p: pointer) {.inline.} =
   # the addresses are not as cells on the stack, so turn them to cells:
   sysAssert(allocInv(gch.region), "gcMark begin")
   var cell = usrToCell(p)
@@ -1025,12 +1030,12 @@ proc gcMark(gch: var TGcHeap, p: pointer) {.inline.} =
         add(gch.decStack, cell)
   sysAssert(allocInv(gch.region), "gcMark end")
 
-proc markThreadStacks(gch: var TGcHeap) = 
+proc markThreadStacks(gch: var GcHeap) =
   when hasThreadSupport and hasSharedHeap:
     {.error: "not fully implemented".}
     var it = threadList
     while it != nil:
-      # mark registers: 
+      # mark registers:
       for i in 0 .. high(it.registers): gcMark(gch, it.registers[i])
       var sp = cast[ByteAddress](it.stackBottom)
       var max = cast[ByteAddress](it.stackTop)
@@ -1074,7 +1079,7 @@ proc stackSize(): int {.noinline.} =
 
 var
   jmpbufSize {.importc: "sizeof(jmp_buf)", nodecl.}: int
-    # a little hack to get the size of a TJmpBuf in the generated C code
+    # a little hack to get the size of a JmpBuf in the generated C code
     # in a platform independent way
 
 when defined(sparc): # For SPARC architecture.
@@ -1086,7 +1091,7 @@ when defined(sparc): # For SPARC architecture.
     var x = cast[ByteAddress](p)
     result = a <=% x and x <=% b
 
-  proc markStackAndRegisters(gch: var TGcHeap) {.noinline, cdecl.} =
+  proc markStackAndRegisters(gch: var GcHeap) {.noinline, cdecl.} =
     when defined(sparcv9):
       asm  """"flushw \n" """
     else:
@@ -1116,8 +1121,8 @@ elif stackIncreases:
     var b = cast[ByteAddress](stackTop)
     var x = cast[ByteAddress](p)
     result = a <=% x and x <=% b
-  
-  proc markStackAndRegisters(gch: var TGcHeap) {.noinline, cdecl.} =
+
+  proc markStackAndRegisters(gch: var GcHeap) {.noinline, cdecl.} =
     var registers: C_JmpBuf
     if c_setjmp(registers) == 0'i32: # To fill the C stack with registers.
       var max = cast[ByteAddress](gch.stackBottom)
@@ -1140,7 +1145,7 @@ else:
     var x = cast[ByteAddress](p)
     result = a <=% x and x <=% b
 
-  proc markStackAndRegisters(gch: var TGcHeap) {.noinline, cdecl.} =
+  proc markStackAndRegisters(gch: var GcHeap) {.noinline, cdecl.} =
     # We use a jmp_buf buffer that is in the C stack.
     # Used to traverse the stack and registers assuming
     # that 'setjmp' will save registers in the C stack.
@@ -1151,7 +1156,7 @@ else:
         # mark the registers
         var jmpbufPtr = cast[ByteAddress](addr(registers))
         var jmpbufEnd = jmpbufPtr +% jmpbufSize
-      
+
         while jmpbufPtr <=% jmpbufEnd:
           gcMark(gch, cast[PPointer](jmpbufPtr)[])
           jmpbufPtr = jmpbufPtr +% sizeof(pointer)
@@ -1181,7 +1186,7 @@ else:
 # end of non-portable code
 # ----------------------------------------------------------------------------
 
-proc releaseCell(gch: var TGcHeap, cell: PCell) =
+proc releaseCell(gch: var GcHeap, cell: PCell) =
   if cell.color != rcReallyDead:
     prepareDealloc(cell)
     cell.setColor rcReallyDead
@@ -1210,21 +1215,21 @@ proc releaseCell(gch: var TGcHeap, cell: PCell) =
   #  recursion).
   # We can ignore it now as the ZCT cleaner will reach it soon.
 
-proc collectZCT(gch: var TGcHeap): bool =
+proc collectZCT(gch: var GcHeap): bool =
   const workPackage = 100
   var L = addr(gch.zct.len)
-  
+
   when withRealtime:
     var steps = workPackage
-    var t0: TTicks
+    var t0: Ticks
     if gch.maxPause > 0: t0 = getticks()
-  
+
   while L[] > 0:
     var c = gch.zct.d[0]
     sysAssert c.isBitUp(rcZct), "collectZCT: rcZct missing!"
     sysAssert(isAllocatedPtr(gch.region, c), "collectZCT: isAllocatedPtr")
-    
-    # remove from ZCT:    
+
+    # remove from ZCT:
     c.clearBit(rcZct)
     gch.zct.d[0] = gch.zct.d[L[] - 1]
     dec(L[])
@@ -1232,7 +1237,7 @@ proc collectZCT(gch: var TGcHeap): bool =
     if c.refcount <% rcIncrement:
       # It may have a RC > 0, if it is in the hardware stack or
       # it has not been removed yet from the ZCT. This is because
-      # ``incref`` does not bother to remove the cell from the ZCT 
+      # ``incref`` does not bother to remove the cell from the ZCT
       # as this might be too slow.
       # In any case, it should be removed from the ZCT. But not
       # freed. **KEEP THIS IN MIND WHEN MAKING THIS INCREMENTAL!**
@@ -1247,7 +1252,7 @@ proc collectZCT(gch: var TGcHeap): bool =
         steps = workPackage
         if gch.maxPause > 0:
           let duration = getticks() - t0
-          # the GC's measuring is not accurate and needs some cleanup actions 
+          # the GC's measuring is not accurate and needs some cleanup actions
           # (stack unmarking), so subtract some short amount of time in to
           # order to miss deadlines less often:
           if duration >= gch.maxPause - 50_000:
@@ -1257,14 +1262,14 @@ proc collectZCT(gch: var TGcHeap): bool =
   #deInit(gch.zct)
   #init(gch.zct)
 
-proc unmarkStackAndRegisters(gch: var TGcHeap) =
+proc unmarkStackAndRegisters(gch: var GcHeap) =
   var d = gch.decStack.d
   for i in 0 .. <gch.decStack.len:
     sysAssert isAllocatedPtr(gch.region, d[i]), "unmarkStackAndRegisters"
     # XXX: just call doDecRef?
     var c = d[i]
     sysAssert c.typ != nil, "unmarkStackAndRegisters 2"
-    
+
     if c.color == rcRetiredBuffer:
       continue
 
@@ -1273,7 +1278,7 @@ proc unmarkStackAndRegisters(gch: var TGcHeap) =
       # the object survived only because of a stack reference
       # it still doesn't have heap references
       addZCT(gch.zct, c)
-    
+
     if canbeCycleRoot(c):
       # any cyclic object reachable from the stack can be turned into
       # a leak if it's orphaned through the stack reference
@@ -1283,12 +1288,12 @@ proc unmarkStackAndRegisters(gch: var TGcHeap) =
 
   gch.decStack.len = 0
 
-proc collectCTBody(gch: var TGcHeap) =
+proc collectCTBody(gch: var GcHeap) =
   when withRealtime:
     let t0 = getticks()
   when debugGC: inc gcCollectionIdx
   sysAssert(allocInv(gch.region), "collectCT: begin")
-  
+
   gch.stat.maxStackSize = max(gch.stat.maxStackSize, stackSize())
   sysAssert(gch.decStack.len == 0, "collectCT")
   prepareForInteriorPointerChecking(gch.region)
@@ -1307,7 +1312,7 @@ proc collectCTBody(gch: var TGcHeap) =
         gch.stat.maxThreshold = max(gch.stat.maxThreshold, gch.cycleThreshold)
   unmarkStackAndRegisters(gch)
   sysAssert(allocInv(gch.region), "collectCT: end")
-  
+
   when withRealtime:
     let duration = getticks() - t0
     gch.stat.maxPause = max(gch.stat.maxPause, duration)
@@ -1315,24 +1320,24 @@ proc collectCTBody(gch: var TGcHeap) =
       if gch.maxPause > 0 and duration > gch.maxPause:
         c_fprintf(c_stdout, "[GC] missed deadline: %ld\n", duration)
 
-proc collectCT(gch: var TGcHeap) =
+proc collectCT(gch: var GcHeap) =
   if (gch.zct.len >= ZctThreshold or (cycleGC and
-      getOccupiedMem(gch.region)>=gch.cycleThreshold) or alwaysGC) and 
+      getOccupiedMem(gch.region)>=gch.cycleThreshold) or alwaysGC) and
       gch.recGcLock == 0:
     collectCTBody(gch)
 
 when withRealtime:
-  proc toNano(x: int): TNanos {.inline.} =
+  proc toNano(x: int): Nanos {.inline.} =
     result = x * 1000
 
   proc GC_setMaxPause*(MaxPauseInUs: int) =
     gch.maxPause = MaxPauseInUs.toNano
 
-  proc GC_step(gch: var TGcHeap, us: int, strongAdvice: bool) =
+  proc GC_step(gch: var GcHeap, us: int, strongAdvice: bool) =
     acquire(gch)
     gch.maxPause = us.toNano
     if (gch.zct.len >= ZctThreshold or (cycleGC and
-        getOccupiedMem(gch.region)>=gch.cycleThreshold) or alwaysGC) or 
+        getOccupiedMem(gch.region)>=gch.cycleThreshold) or alwaysGC) or
         strongAdvice:
       collectCTBody(gch)
     release(gch)
@@ -1340,13 +1345,13 @@ when withRealtime:
   proc GC_step*(us: int, strongAdvice = false) = GC_step(gch, us, strongAdvice)
 
 when not defined(useNimRtl):
-  proc GC_disable() = 
+  proc GC_disable() =
     when hasThreadSupport and hasSharedHeap:
       discard atomicInc(gch.recGcLock, 1)
     else:
       inc(gch.recGcLock)
   proc GC_enable() =
-    if gch.recGcLock > 0: 
+    if gch.recGcLock > 0:
       when hasThreadSupport and hasSharedHeap:
         discard atomicDec(gch.recGcLock, 1)
       else:
diff --git a/lib/system/gc_common.nim b/lib/system/gc_common.nim
new file mode 100644
index 000000000..47e8b4b1f
--- /dev/null
+++ b/lib/system/gc_common.nim
@@ -0,0 +1,277 @@
+#
+#
+#            Nim's Runtime Library
+#        (c) Copyright 2015 Rokas Kupstys
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+proc len(stack: ptr GcStack): int =
+  if stack == nil:
+    return 0
+
+  var s = stack
+  result = 1
+  while s.next != nil:
+    inc(result)
+    s = s.next
+
+when defined(nimCoroutines):
+  proc stackSize(stackBottom: pointer, pos: pointer=nil): int {.noinline.} =
+    var sp: pointer
+    if pos == nil:
+      var stackTop {.volatile.}: pointer
+      sp = addr(stackTop)
+    else:
+      sp = pos
+    result = abs(cast[int](sp) - cast[int](stackBottom))
+
+  proc GC_addStack*(starts: pointer) {.cdecl, exportc.} =
+    var sp {.volatile.}: pointer
+    var stack = cast[ptr GcStack](alloc0(sizeof(GcStack)))
+    stack.starts = starts
+    stack.pos = addr sp
+    if gch.stack == nil:
+      gch.stack = stack
+    else:
+      stack.next = gch.stack
+      gch.stack.prev = stack
+      gch.stack = stack
+    # c_fprintf(c_stdout, "[GC] added stack 0x%016X\n", starts)
+
+  proc GC_removeStack*(starts: pointer) {.cdecl, exportc.} =
+    var stack = gch.stack
+    while stack != nil:
+      if stack.starts == starts:
+        if stack.prev == nil:
+          if stack.next != nil:
+            stack.next.prev = nil
+          gch.stack = stack.next
+        else:
+          stack.prev.next = stack.next
+          if stack.next != nil:
+              stack.next.prev = stack.prev
+        dealloc(stack)
+        # echo "[GC] removed stack ", starts.repr
+        break
+      else:
+        stack = stack.next
+
+  proc GC_setCurrentStack*(starts, pos: pointer) {.cdecl, exportc.} =
+    var stack = gch.stack
+    while stack != nil:
+      if stack.starts == starts:
+        stack.pos = pos
+        stack.maxStackSize = max(stack.maxStackSize, stackSize(stack.starts, pos))
+        return
+      stack = stack.next
+    gcAssert(false, "Current stack position does not belong to registered stack")
+else:
+  proc stackSize(): int {.noinline.} =
+    var stackTop {.volatile.}: pointer
+    result = abs(cast[int](addr(stackTop)) - cast[int](gch.stackBottom))
+
+iterator items(stack: ptr GcStack): ptr GcStack =
+  var s = stack
+  while not isNil(s):
+    yield s
+    s = s.next
+
+var
+  localGcInitialized {.rtlThreadVar.}: bool
+
+proc setupForeignThreadGc*() =
+  ## call this if you registered a callback that will be run from a thread not
+  ## under your control. This has a cheap thread-local guard, so the GC for
+  ## this thread will only be initialized once per thread, no matter how often
+  ## it is called.
+  if not localGcInitialized:
+    localGcInitialized = true
+    var stackTop {.volatile.}: pointer
+    setStackBottom(addr(stackTop))
+    initGC()
+
+# ----------------- stack management --------------------------------------
+#  inspired from Smart Eiffel
+
+when defined(emscripten):
+  const stackIncreases = true
+elif defined(sparc):
+  const stackIncreases = false
+elif defined(hppa) or defined(hp9000) or defined(hp9000s300) or
+     defined(hp9000s700) or defined(hp9000s800) or defined(hp9000s820):
+  const stackIncreases = true
+else:
+  const stackIncreases = false
+
+when not defined(useNimRtl):
+  {.push stack_trace: off.}
+  proc setStackBottom(theStackBottom: pointer) =
+    #c_fprintf(c_stdout, "stack bottom: %p;\n", theStackBottom)
+    # the first init must be the one that defines the stack bottom:
+    when defined(nimCoroutines):
+      GC_addStack(theStackBottom)
+    else:
+      if gch.stackBottom == nil: gch.stackBottom = theStackBottom
+      else:
+        var a = cast[ByteAddress](theStackBottom) # and not PageMask - PageSize*2
+        var b = cast[ByteAddress](gch.stackBottom)
+        #c_fprintf(c_stdout, "old: %p new: %p;\n",gch.stackBottom,theStackBottom)
+        when stackIncreases:
+          gch.stackBottom = cast[pointer](min(a, b))
+        else:
+          gch.stackBottom = cast[pointer](max(a, b))
+  {.pop.}
+
+when defined(sparc): # For SPARC architecture.
+  when defined(nimCoroutines):
+    {.error: "Nim coroutines are not supported on this platform."}
+
+  proc isOnStack(p: pointer): bool =
+    var stackTop {.volatile.}: pointer
+    stackTop = addr(stackTop)
+    var b = cast[TAddress](gch.stackBottom)
+    var a = cast[TAddress](stackTop)
+    var x = cast[TAddress](p)
+    result = a <=% x and x <=% b
+
+  template forEachStackSlot(gch, gcMark: expr) {.immediate, dirty.} =
+    when defined(sparcv9):
+      asm  """"flushw \n" """
+    else:
+      asm  """"ta      0x3   ! ST_FLUSH_WINDOWS\n" """
+
+    var
+      max = gch.stackBottom
+      sp: PPointer
+      stackTop: array[0..1, pointer]
+    sp = addr(stackTop[0])
+    # Addresses decrease as the stack grows.
+    while sp <= max:
+      gcMark(gch, sp[])
+      sp = cast[PPointer](cast[TAddress](sp) +% sizeof(pointer))
+
+elif defined(ELATE):
+  {.error: "stack marking code is to be written for this architecture".}
+
+elif stackIncreases:
+  # ---------------------------------------------------------------------------
+  # Generic code for architectures where addresses increase as the stack grows.
+  # ---------------------------------------------------------------------------
+  when defined(nimCoroutines):
+    {.error: "Nim coroutines are not supported on this platform."}
+  proc isOnStack(p: pointer): bool =
+    var stackTop {.volatile.}: pointer
+    stackTop = addr(stackTop)
+    var a = cast[ByteAddress](gch.stackBottom)
+    var b = cast[ByteAddress](stackTop)
+    var x = cast[ByteAddress](p)
+    result = a <=% x and x <=% b
+
+  var
+    jmpbufSize {.importc: "sizeof(jmp_buf)", nodecl.}: int
+      # a little hack to get the size of a JmpBuf in the generated C code
+      # in a platform independent way
+
+  template forEachStackSlot(gch, gcMark: expr) {.immediate, dirty.} =
+    var registers {.noinit.}: C_JmpBuf
+    if c_setjmp(registers) == 0'i32: # To fill the C stack with registers.
+      var max = cast[ByteAddress](gch.stackBottom)
+      var sp = cast[ByteAddress](addr(registers)) +% jmpbufSize -% sizeof(pointer)
+      # sp will traverse the JMP_BUF as well (jmp_buf size is added,
+      # otherwise sp would be below the registers structure).
+      while sp >=% max:
+        gcMark(gch, cast[PPointer](sp)[])
+        sp = sp -% sizeof(pointer)
+
+else:
+  # ---------------------------------------------------------------------------
+  # Generic code for architectures where addresses decrease as the stack grows.
+  # ---------------------------------------------------------------------------
+  when defined(nimCoroutines):
+    proc isOnStack(p: pointer): bool =
+      var stackTop {.volatile.}: pointer
+      stackTop = addr(stackTop)
+      for stack in items(gch.stack):
+        var b = cast[ByteAddress](stack.starts)
+        var a = cast[ByteAddress](stack.starts) - stack.maxStackSize
+        var x = cast[ByteAddress](p)
+        if a <=% x and x <=% b:
+          return true
+
+    template forEachStackSlot(gch, gcMark: expr) {.immediate, dirty.} =
+      # We use a jmp_buf buffer that is in the C stack.
+      # Used to traverse the stack and registers assuming
+      # that 'setjmp' will save registers in the C stack.
+      type PStackSlice = ptr array [0..7, pointer]
+      var registers {.noinit.}: Registers
+      getRegisters(registers)
+      for i in registers.low .. registers.high:
+        gcMark(gch, cast[PPointer](registers[i]))
+
+      for stack in items(gch.stack):
+        stack.maxStackSize = max(stack.maxStackSize, stackSize(stack.starts))
+        var max = cast[ByteAddress](stack.starts)
+        var sp = cast[ByteAddress](stack.pos)
+        # loop unrolled:
+        while sp <% max - 8*sizeof(pointer):
+          gcMark(gch, cast[PStackSlice](sp)[0])
+          gcMark(gch, cast[PStackSlice](sp)[1])
+          gcMark(gch, cast[PStackSlice](sp)[2])
+          gcMark(gch, cast[PStackSlice](sp)[3])
+          gcMark(gch, cast[PStackSlice](sp)[4])
+          gcMark(gch, cast[PStackSlice](sp)[5])
+          gcMark(gch, cast[PStackSlice](sp)[6])
+          gcMark(gch, cast[PStackSlice](sp)[7])
+          sp = sp +% sizeof(pointer)*8
+        # last few entries:
+        while sp <=% max:
+          gcMark(gch, cast[PPointer](sp)[])
+          sp = sp +% sizeof(pointer)
+  else:
+    proc isOnStack(p: pointer): bool =
+      var stackTop {.volatile.}: pointer
+      stackTop = addr(stackTop)
+      var b = cast[ByteAddress](gch.stackBottom)
+      var a = cast[ByteAddress](stackTop)
+      var x = cast[ByteAddress](p)
+      result = a <=% x and x <=% b
+
+    template forEachStackSlot(gch, gcMark: expr) {.immediate, dirty.} =
+      # We use a jmp_buf buffer that is in the C stack.
+      # Used to traverse the stack and registers assuming
+      # that 'setjmp' will save registers in the C stack.
+      type PStackSlice = ptr array [0..7, pointer]
+      var registers {.noinit.}: C_JmpBuf
+      if c_setjmp(registers) == 0'i32: # To fill the C stack with registers.
+        var max = cast[ByteAddress](gch.stackBottom)
+        var sp = cast[ByteAddress](addr(registers))
+        when defined(amd64):
+          # words within the jmp_buf structure may not be properly aligned.
+          let regEnd = sp +% sizeof(registers)
+          while sp <% regEnd:
+            gcMark(gch, cast[PPointer](sp)[])
+            gcMark(gch, cast[PPointer](sp +% sizeof(pointer) div 2)[])
+            sp = sp +% sizeof(pointer)
+        # Make sure sp is word-aligned
+        sp = sp and not (sizeof(pointer) - 1)
+        # loop unrolled:
+        while sp <% max - 8*sizeof(pointer):
+          gcMark(gch, cast[PStackSlice](sp)[0])
+          gcMark(gch, cast[PStackSlice](sp)[1])
+          gcMark(gch, cast[PStackSlice](sp)[2])
+          gcMark(gch, cast[PStackSlice](sp)[3])
+          gcMark(gch, cast[PStackSlice](sp)[4])
+          gcMark(gch, cast[PStackSlice](sp)[5])
+          gcMark(gch, cast[PStackSlice](sp)[6])
+          gcMark(gch, cast[PStackSlice](sp)[7])
+          sp = sp +% sizeof(pointer)*8
+        # last few entries:
+        while sp <=% max:
+          gcMark(gch, cast[PPointer](sp)[])
+          sp = sp +% sizeof(pointer)
+
+# ----------------------------------------------------------------------------
+# end of non-portable code
+# ----------------------------------------------------------------------------
diff --git a/lib/system/gc_ms.nim b/lib/system/gc_ms.nim
index e287bf5d9..d1aecb7a2 100644
--- a/lib/system/gc_ms.nim
+++ b/lib/system/gc_ms.nim
@@ -9,6 +9,10 @@
 
 # A simple mark&sweep garbage collector for Nim. Define the
 # symbol ``gcUseBitvectors`` to generate a variant of this GC.
+
+when defined(nimCoroutines):
+  import arch
+
 {.push profiler:off.}
 
 const
@@ -26,49 +30,58 @@ when defined(memProfiler):
   proc nimProfile(requestedSize: int)
 
 type
-  TWalkOp = enum
+  WalkOp = enum
     waMarkGlobal,  # we need to mark conservatively for global marker procs
                    # as these may refer to a global var and not to a thread
                    # local
     waMarkPrecise  # fast precise marking
 
-  TFinalizer {.compilerproc.} = proc (self: pointer) {.nimcall, benign.}
+  Finalizer {.compilerproc.} = proc (self: pointer) {.nimcall, benign.}
     # A ref type can have a finalizer that is called before the object's
     # storage is freed.
 
-  TGlobalMarkerProc = proc () {.nimcall, benign.}
+  GlobalMarkerProc = proc () {.nimcall, benign.}
 
-  TGcStat = object
+  GcStat = object
     collections: int         # number of performed full collections
     maxThreshold: int        # max threshold that has been set
     maxStackSize: int        # max stack size
     freedObjects: int        # max entries in cycle table
 
-  TGcHeap = object           # this contains the zero count and
+  GcStack {.final.} = object
+    prev: ptr GcStack
+    next: ptr GcStack
+    starts: pointer
+    pos: pointer
+    maxStackSize: int
+
+  GcHeap = object            # this contains the zero count and
                              # non-zero count table
+    stack: ptr GcStack
     stackBottom: pointer
     cycleThreshold: int
     when useCellIds:
       idGenerator: int
     when withBitvectors:
-      allocated, marked: TCellSet
-    tempStack: TCellSeq      # temporary stack for recursion elimination
+      allocated, marked: CellSet
+    tempStack: CellSeq       # temporary stack for recursion elimination
     recGcLock: int           # prevent recursion via finalizers; no thread lock
-    region: TMemRegion       # garbage collected region
-    stat: TGcStat
-    additionalRoots: TCellSeq # dummy roots for GC_ref/unref
-
+    region: MemRegion        # garbage collected region
+    stat: GcStat
+    additionalRoots: CellSeq # dummy roots for GC_ref/unref
+{.deprecated: [TWalkOp: WalkOp, TFinalizer: Finalizer, TGcStat: GcStat,
+              TGlobalMarkerProc: GlobalMarkerProc, TGcHeap: GcHeap].}
 var
-  gch {.rtlThreadVar.}: TGcHeap
+  gch {.rtlThreadVar.}: GcHeap
 
 when not defined(useNimRtl):
   instantiateForRegion(gch.region)
 
-template acquire(gch: TGcHeap) =
+template acquire(gch: GcHeap) =
   when hasThreadSupport and hasSharedHeap:
     acquireSys(HeapLock)
 
-template release(gch: TGcHeap) =
+template release(gch: GcHeap) =
   when hasThreadSupport and hasSharedHeap:
     releaseSys(HeapLock)
 
@@ -80,11 +93,11 @@ template gcAssert(cond: bool, msg: string) =
 
 proc cellToUsr(cell: PCell): pointer {.inline.} =
   # convert object (=pointer to refcount) to pointer to userdata
-  result = cast[pointer](cast[ByteAddress](cell)+%ByteAddress(sizeof(TCell)))
+  result = cast[pointer](cast[ByteAddress](cell)+%ByteAddress(sizeof(Cell)))
 
 proc usrToCell(usr: pointer): PCell {.inline.} =
   # convert pointer to userdata to object (=pointer to refcount)
-  result = cast[PCell](cast[ByteAddress](usr)-%ByteAddress(sizeof(TCell)))
+  result = cast[PCell](cast[ByteAddress](usr)-%ByteAddress(sizeof(Cell)))
 
 proc canbeCycleRoot(c: PCell): bool {.inline.} =
   result = ntfAcyclic notin c.typ.flags
@@ -101,9 +114,9 @@ proc internRefcount(p: pointer): int {.exportc: "getRefcount".} =
 
 var
   globalMarkersLen: int
-  globalMarkers: array[0.. 7_000, TGlobalMarkerProc]
+  globalMarkers: array[0.. 7_000, GlobalMarkerProc]
 
-proc nimRegisterGlobalMarker(markerProc: TGlobalMarkerProc) {.compilerProc.} =
+proc nimRegisterGlobalMarker(markerProc: GlobalMarkerProc) {.compilerProc.} =
   if globalMarkersLen <= high(globalMarkers):
     globalMarkers[globalMarkersLen] = markerProc
     inc globalMarkersLen
@@ -116,11 +129,10 @@ when BitsPerPage mod (sizeof(int)*8) != 0:
   {.error: "(BitsPerPage mod BitsPerUnit) should be zero!".}
 
 # forward declarations:
-proc collectCT(gch: var TGcHeap) {.benign.}
-proc isOnStack*(p: pointer): bool {.noinline, benign.}
-proc forAllChildren(cell: PCell, op: TWalkOp) {.benign.}
-proc doOperation(p: pointer, op: TWalkOp) {.benign.}
-proc forAllChildrenAux(dest: pointer, mt: PNimType, op: TWalkOp) {.benign.}
+proc collectCT(gch: var GcHeap) {.benign.}
+proc forAllChildren(cell: PCell, op: WalkOp) {.benign.}
+proc doOperation(p: pointer, op: WalkOp) {.benign.}
+proc forAllChildrenAux(dest: pointer, mt: PNimType, op: WalkOp) {.benign.}
 # we need the prototype here for debugging purposes
 
 proc prepareDealloc(cell: PCell) =
@@ -131,7 +143,7 @@ proc prepareDealloc(cell: PCell) =
     # prevend recursive entering here by a lock.
     # XXX: we should set the cell's children to nil!
     inc(gch.recGcLock)
-    (cast[TFinalizer](cell.typ.finalizer))(cellToUsr(cell))
+    (cast[Finalizer](cell.typ.finalizer))(cellToUsr(cell))
     dec(gch.recGcLock)
 
 proc nimGCref(p: pointer) {.compilerProc.} =
@@ -168,21 +180,7 @@ proc initGC() =
       init(gch.allocated)
       init(gch.marked)
 
-var
-  localGcInitialized {.rtlThreadVar.}: bool
-
-proc setupForeignThreadGc*() =
-  ## call this if you registered a callback that will be run from a thread not
-  ## under your control. This has a cheap thread-local guard, so the GC for
-  ## this thread will only be initialized once per thread, no matter how often
-  ## it is called.
-  if not localGcInitialized:
-    localGcInitialized = true
-    var stackTop {.volatile.}: pointer
-    setStackBottom(addr(stackTop))
-    initGC()
-
-proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) {.benign.} =
+proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: WalkOp) {.benign.} =
   var d = cast[ByteAddress](dest)
   case n.kind
   of nkSlot: forAllChildrenAux(cast[pointer](d +% n.offset), n.typ, op)
@@ -194,7 +192,7 @@ proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) {.benign.} =
     if m != nil: forAllSlotsAux(dest, m, op)
   of nkNone: sysAssert(false, "forAllSlotsAux")
 
-proc forAllChildrenAux(dest: pointer, mt: PNimType, op: TWalkOp) =
+proc forAllChildrenAux(dest: pointer, mt: PNimType, op: WalkOp) =
   var d = cast[ByteAddress](dest)
   if dest == nil: return # nothing to do
   if ntfNoRefs notin mt.flags:
@@ -208,7 +206,7 @@ proc forAllChildrenAux(dest: pointer, mt: PNimType, op: TWalkOp) =
         forAllChildrenAux(cast[pointer](d +% i *% mt.base.size), mt.base, op)
     else: discard
 
-proc forAllChildren(cell: PCell, op: TWalkOp) =
+proc forAllChildren(cell: PCell, op: WalkOp) =
   gcAssert(cell != nil, "forAllChildren: 1")
   gcAssert(cell.typ != nil, "forAllChildren: 2")
   gcAssert cell.typ.kind in {tyRef, tySequence, tyString}, "forAllChildren: 3"
@@ -228,12 +226,12 @@ proc forAllChildren(cell: PCell, op: TWalkOp) =
             GenericSeqSize), cell.typ.base, op)
     else: discard
 
-proc rawNewObj(typ: PNimType, size: int, gch: var TGcHeap): pointer =
+proc rawNewObj(typ: PNimType, size: int, gch: var GcHeap): pointer =
   # generates a new object and sets its reference counter to 0
   acquire(gch)
   gcAssert(typ.kind in {tyRef, tyString, tySequence}, "newObj: 1")
   collectCT(gch)
-  var res = cast[PCell](rawAlloc(gch.region, size + sizeof(TCell)))
+  var res = cast[PCell](rawAlloc(gch.region, size + sizeof(Cell)))
   gcAssert((cast[ByteAddress](res) and (MemAlign-1)) == 0, "newObj: 2")
   # now it is buffered in the ZCT
   res.typ = typ
@@ -285,20 +283,20 @@ proc newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl.} =
   cast[PGenericSeq](result).reserved = len
   when defined(memProfiler): nimProfile(size)
 
-proc growObj(old: pointer, newsize: int, gch: var TGcHeap): pointer =
+proc growObj(old: pointer, newsize: int, gch: var GcHeap): pointer =
   acquire(gch)
   collectCT(gch)
   var ol = usrToCell(old)
   sysAssert(ol.typ != nil, "growObj: 1")
   gcAssert(ol.typ.kind in {tyString, tySequence}, "growObj: 2")
 
-  var res = cast[PCell](rawAlloc(gch.region, newsize + sizeof(TCell)))
+  var res = cast[PCell](rawAlloc(gch.region, newsize + sizeof(Cell)))
   var elemSize = 1
   if ol.typ.kind != tyString: elemSize = ol.typ.base.size
 
   var oldsize = cast[PGenericSeq](old).len*elemSize + GenericSeqSize
-  copyMem(res, ol, oldsize + sizeof(TCell))
-  zeroMem(cast[pointer](cast[ByteAddress](res)+% oldsize +% sizeof(TCell)),
+  copyMem(res, ol, oldsize + sizeof(Cell))
+  zeroMem(cast[pointer](cast[ByteAddress](res)+% oldsize +% sizeof(Cell)),
           newsize-oldsize)
   sysAssert((cast[ByteAddress](res) and (MemAlign-1)) == 0, "growObj: 3")
   when false:
@@ -306,7 +304,7 @@ proc growObj(old: pointer, newsize: int, gch: var TGcHeap): pointer =
     when withBitvectors: excl(gch.allocated, ol)
     when reallyDealloc: rawDealloc(gch.region, ol)
     else:
-      zeroMem(ol, sizeof(TCell))
+      zeroMem(ol, sizeof(Cell))
   when withBitvectors: incl(gch.allocated, res)
   when useCellIds:
     inc gch.idGenerator
@@ -322,7 +320,7 @@ proc growObj(old: pointer, newsize: int): pointer {.rtl.} =
 
 # ----------------- collector -----------------------------------------------
 
-proc mark(gch: var TGcHeap, c: PCell) =
+proc mark(gch: var GcHeap, c: PCell) =
   when withBitvectors:
     incl(gch.marked, c)
     gcAssert gch.tempStack.len == 0, "stack not empty!"
@@ -344,7 +342,7 @@ proc mark(gch: var TGcHeap, c: PCell) =
         d.refCount = rcBlack
         forAllChildren(d, waMarkPrecise)
 
-proc doOperation(p: pointer, op: TWalkOp) =
+proc doOperation(p: pointer, op: WalkOp) =
   if p == nil: return
   var c: PCell = usrToCell(p)
   gcAssert(c != nil, "doOperation: 1")
@@ -359,17 +357,17 @@ proc doOperation(p: pointer, op: TWalkOp) =
   of waMarkPrecise: add(gch.tempStack, c)
 
 proc nimGCvisit(d: pointer, op: int) {.compilerRtl.} =
-  doOperation(d, TWalkOp(op))
+  doOperation(d, WalkOp(op))
 
-proc freeCyclicCell(gch: var TGcHeap, c: PCell) =
+proc freeCyclicCell(gch: var GcHeap, c: PCell) =
   inc gch.stat.freedObjects
   prepareDealloc(c)
   when reallyDealloc: rawDealloc(gch.region, c)
   else:
     gcAssert(c.typ != nil, "freeCyclicCell")
-    zeroMem(c, sizeof(TCell))
+    zeroMem(c, sizeof(Cell))
 
-proc sweep(gch: var TGcHeap) =
+proc sweep(gch: var GcHeap) =
   when withBitvectors:
     for c in gch.allocated.elementsExcept(gch.marked):
       gch.allocated.excl(c)
@@ -391,12 +389,12 @@ when false:
           writeStackTrace()
           quit 1
 
-proc markGlobals(gch: var TGcHeap) =
+proc markGlobals(gch: var GcHeap) =
   for i in 0 .. < globalMarkersLen: globalMarkers[i]()
   let d = gch.additionalRoots.d
   for i in 0 .. < gch.additionalRoots.len: mark(gch, d[i])
 
-proc gcMark(gch: var TGcHeap, p: pointer) {.inline.} =
+proc gcMark(gch: var GcHeap, p: pointer) {.inline.} =
   # the addresses are not as cells on the stack, so turn them to cells:
   var cell = usrToCell(p)
   var c = cast[ByteAddress](cell)
@@ -406,136 +404,14 @@ proc gcMark(gch: var TGcHeap, p: pointer) {.inline.} =
     if objStart != nil:
       mark(gch, objStart)
 
-# ----------------- stack management --------------------------------------
-#  inspired from Smart Eiffel
+include gc_common
 
-when defined(sparc):
-  const stackIncreases = false
-elif defined(hppa) or defined(hp9000) or defined(hp9000s300) or
-     defined(hp9000s700) or defined(hp9000s800) or defined(hp9000s820):
-  const stackIncreases = true
-else:
-  const stackIncreases = false
+proc markStackAndRegisters(gch: var GcHeap) {.noinline, cdecl.} =
+  forEachStackSlot(gch, gcMark)
 
-when not defined(useNimRtl):
-  {.push stack_trace: off.}
-  proc setStackBottom(theStackBottom: pointer) =
-    #c_fprintf(c_stdout, "stack bottom: %p;\n", theStackBottom)
-    # the first init must be the one that defines the stack bottom:
-    if gch.stackBottom == nil: gch.stackBottom = theStackBottom
-    else:
-      var a = cast[ByteAddress](theStackBottom) # and not PageMask - PageSize*2
-      var b = cast[ByteAddress](gch.stackBottom)
-      #c_fprintf(c_stdout, "old: %p new: %p;\n",gch.stackBottom,theStackBottom)
-      when stackIncreases:
-        gch.stackBottom = cast[pointer](min(a, b))
-      else:
-        gch.stackBottom = cast[pointer](max(a, b))
-  {.pop.}
-
-proc stackSize(): int {.noinline.} =
-  var stackTop {.volatile.}: pointer
-  result = abs(cast[int](addr(stackTop)) - cast[int](gch.stackBottom))
-
-when defined(sparc): # For SPARC architecture.
-  proc isOnStack(p: pointer): bool =
-    var stackTop {.volatile.}: pointer
-    stackTop = addr(stackTop)
-    var b = cast[ByteAddress](gch.stackBottom)
-    var a = cast[ByteAddress](stackTop)
-    var x = cast[ByteAddress](p)
-    result = a <=% x and x <=% b
-
-  proc markStackAndRegisters(gch: var TGcHeap) {.noinline, cdecl.} =
-    when defined(sparcv9):
-      asm  """"flushw \n" """
-    else:
-      asm  """"ta      0x3   ! ST_FLUSH_WINDOWS\n" """
-
-    var
-      max = gch.stackBottom
-      sp: PPointer
-      stackTop: array[0..1, pointer]
-    sp = addr(stackTop[0])
-    # Addresses decrease as the stack grows.
-    while sp <= max:
-      gcMark(gch, sp[])
-      sp = cast[ppointer](cast[ByteAddress](sp) +% sizeof(pointer))
-
-elif defined(ELATE):
-  {.error: "stack marking code is to be written for this architecture".}
-
-elif stackIncreases:
-  # ---------------------------------------------------------------------------
-  # Generic code for architectures where addresses increase as the stack grows.
-  # ---------------------------------------------------------------------------
-  proc isOnStack(p: pointer): bool =
-    var stackTop {.volatile.}: pointer
-    stackTop = addr(stackTop)
-    var a = cast[ByteAddress](gch.stackBottom)
-    var b = cast[ByteAddress](stackTop)
-    var x = cast[ByteAddress](p)
-    result = a <=% x and x <=% b
-
-  var
-    jmpbufSize {.importc: "sizeof(jmp_buf)", nodecl.}: int
-      # a little hack to get the size of a TJmpBuf in the generated C code
-      # in a platform independent way
-
-  proc markStackAndRegisters(gch: var TGcHeap) {.noinline, cdecl.} =
-    var registers: C_JmpBuf
-    if c_setjmp(registers) == 0'i32: # To fill the C stack with registers.
-      var max = cast[ByteAddress](gch.stackBottom)
-      var sp = cast[ByteAddress](addr(registers)) +% jmpbufSize -% sizeof(pointer)
-      # sp will traverse the JMP_BUF as well (jmp_buf size is added,
-      # otherwise sp would be below the registers structure).
-      while sp >=% max:
-        gcMark(gch, cast[ppointer](sp)[])
-        sp = sp -% sizeof(pointer)
-
-else:
-  # ---------------------------------------------------------------------------
-  # Generic code for architectures where addresses decrease as the stack grows.
-  # ---------------------------------------------------------------------------
-  proc isOnStack(p: pointer): bool =
-    var stackTop {.volatile.}: pointer
-    stackTop = addr(stackTop)
-    var b = cast[ByteAddress](gch.stackBottom)
-    var a = cast[ByteAddress](stackTop)
-    var x = cast[ByteAddress](p)
-    result = a <=% x and x <=% b
-
-  proc markStackAndRegisters(gch: var TGcHeap) {.noinline, cdecl.} =
-    # We use a jmp_buf buffer that is in the C stack.
-    # Used to traverse the stack and registers assuming
-    # that 'setjmp' will save registers in the C stack.
-    type PStackSlice = ptr array [0..7, pointer]
-    var registers {.noinit.}: C_JmpBuf
-    if c_setjmp(registers) == 0'i32: # To fill the C stack with registers.
-      var max = cast[ByteAddress](gch.stackBottom)
-      var sp = cast[ByteAddress](addr(registers))
-      # loop unrolled:
-      while sp <% max - 8*sizeof(pointer):
-        gcMark(gch, cast[PStackSlice](sp)[0])
-        gcMark(gch, cast[PStackSlice](sp)[1])
-        gcMark(gch, cast[PStackSlice](sp)[2])
-        gcMark(gch, cast[PStackSlice](sp)[3])
-        gcMark(gch, cast[PStackSlice](sp)[4])
-        gcMark(gch, cast[PStackSlice](sp)[5])
-        gcMark(gch, cast[PStackSlice](sp)[6])
-        gcMark(gch, cast[PStackSlice](sp)[7])
-        sp = sp +% sizeof(pointer)*8
-      # last few entries:
-      while sp <=% max:
-        gcMark(gch, cast[PPointer](sp)[])
-        sp = sp +% sizeof(pointer)
-
-# ----------------------------------------------------------------------------
-# end of non-portable code
-# ----------------------------------------------------------------------------
-
-proc collectCTBody(gch: var TGcHeap) =
-  gch.stat.maxStackSize = max(gch.stat.maxStackSize, stackSize())
+proc collectCTBody(gch: var GcHeap) =
+  when not defined(nimCoroutines):
+    gch.stat.maxStackSize = max(gch.stat.maxStackSize, stackSize())
   prepareForInteriorPointerChecking(gch.region)
   markStackAndRegisters(gch)
   markGlobals(gch)
@@ -549,7 +425,7 @@ proc collectCTBody(gch: var TGcHeap) =
   gch.stat.maxThreshold = max(gch.stat.maxThreshold, gch.cycleThreshold)
   sysAssert(allocInv(gch.region), "collectCT: end")
 
-proc collectCT(gch: var TGcHeap) =
+proc collectCT(gch: var GcHeap) =
   if getOccupiedMem(gch.region) >= gch.cycleThreshold and gch.recGcLock == 0:
     collectCTBody(gch)
 
@@ -589,8 +465,13 @@ when not defined(useNimRtl):
              "[GC] occupied memory: " & $getOccupiedMem() & "\n" &
              "[GC] collections: " & $gch.stat.collections & "\n" &
              "[GC] max threshold: " & $gch.stat.maxThreshold & "\n" &
-             "[GC] freed objects: " & $gch.stat.freedObjects & "\n" &
-             "[GC] max stack size: " & $gch.stat.maxStackSize & "\n"
+             "[GC] freed objects: " & $gch.stat.freedObjects & "\n"
+    when defined(nimCoroutines):
+      result = result & "[GC] number of stacks: " & $gch.stack.len & "\n"
+      for stack in items(gch.stack):
+        result = result & "[GC]   stack " & stack.starts.repr & "[GC]     max stack size " & $stack.maxStackSize & "\n"
+    else:
+      result = result & "[GC] max stack size: " & $gch.stat.maxStackSize & "\n"
     GC_enable()
 
 {.pop.}
diff --git a/lib/system/hti.nim b/lib/system/hti.nim
index aff0c0e6f..bfb13059e 100644
--- a/lib/system/hti.nim
+++ b/lib/system/hti.nim
@@ -7,14 +7,14 @@
 #    distribution, for details about the copyright.
 #
 
-when declared(NimString): 
+when declared(NimString):
   # we are in system module:
   {.pragma: codegenType, compilerproc.}
 else:
   {.pragma: codegenType, importc.}
 
-type 
-  # This should be he same as ast.TTypeKind
+type
+  # This should be the same as ast.TTypeKind
   # many enum fields are not used at runtime
   TNimKind = enum
     tyNone,
@@ -73,7 +73,7 @@ type
     len: int
     sons: ptr array [0..0x7fff, ptr TNimNode]
 
-  TNimTypeFlag = enum 
+  TNimTypeFlag = enum
     ntfNoRefs = 0,     # type contains no tyRef, tySequence, tyString
     ntfAcyclic = 1,    # type cannot form a cycle
     ntfEnumHole = 2    # enum has holes and thus `$` for them needs the slow
@@ -88,5 +88,5 @@ type
     marker: proc (p: pointer, op: int) {.nimcall, benign.} # marker proc for GC
     deepcopy: proc (p: pointer): pointer {.nimcall, benign.}
   PNimType = ptr TNimType
-  
+
 # node.len may be the ``first`` element of a set
diff --git a/lib/system/inclrtl.nim b/lib/system/inclrtl.nim
index dbc961402..201a99ca7 100644
--- a/lib/system/inclrtl.nim
+++ b/lib/system/inclrtl.nim
@@ -20,21 +20,21 @@ when not defined(nimNewShared):
   {.pragma: gcsafe.}
 
 when defined(createNimRtl):
-  when defined(useNimRtl): 
+  when defined(useNimRtl):
     {.error: "Cannot create and use nimrtl at the same time!".}
   elif appType != "lib":
     {.error: "nimrtl must be built as a library!".}
 
-when defined(createNimRtl): 
+when defined(createNimRtl):
   {.pragma: rtl, exportc: "nimrtl_$1", dynlib, gcsafe.}
   {.pragma: inl.}
   {.pragma: compilerRtl, compilerproc, exportc: "nimrtl_$1", dynlib.}
 elif defined(useNimRtl):
-  when defined(windows): 
+  when defined(windows):
     const nimrtl* = "nimrtl.dll"
   elif defined(macosx):
-    const nimrtl* = "nimrtl.dylib"
-  else: 
+    const nimrtl* = "libnimrtl.dylib"
+  else:
     const nimrtl* = "libnimrtl.so"
   {.pragma: rtl, importc: "nimrtl_$1", dynlib: nimrtl, gcsafe.}
   {.pragma: inl.}
diff --git a/lib/system/jssys.nim b/lib/system/jssys.nim
index 3b55f62ca..eb6080d38 100644
--- a/lib/system/jssys.nim
+++ b/lib/system/jssys.nim
@@ -15,13 +15,13 @@ else:
 proc log*(s: cstring) {.importc: "console.log", varargs, nodecl.}
 
 type
-  PSafePoint = ptr TSafePoint
-  TSafePoint {.compilerproc, final.} = object
+  PSafePoint = ptr SafePoint
+  SafePoint {.compilerproc, final.} = object
     prev: PSafePoint # points to next safe point
     exc: ref Exception
 
-  PCallFrame = ptr TCallFrame
-  TCallFrame {.importc, nodecl, final.} = object
+  PCallFrame = ptr CallFrame
+  CallFrame {.importc, nodecl, final.} = object
     prev: PCallFrame
     procname: cstring
     line: int # current line number
@@ -33,12 +33,11 @@ type
     lineNumber {.importc.}: int
     message {.importc.}: cstring
     stack {.importc.}: cstring
+{.deprecated: [TSafePoint: SafePoint, TCallFrame: CallFrame].}
 
 var
   framePtr {.importc, nodecl, volatile.}: PCallFrame
-  excHandler {.importc, nodecl, volatile.}: PSafePoint = nil
-    # list of exception handlers
-    # a global variable for the root of all try blocks
+  excHandler {.importc, nodecl, volatile.}: int = 0
   lastJSError {.importc, nodecl, volatile.}: PJSError = nil
 
 {.push stacktrace: off, profiler:off.}
@@ -51,21 +50,20 @@ proc nimCharToStr(x: char): string {.compilerproc.} =
   result[0] = x
 
 proc getCurrentExceptionMsg*(): string =
-  if excHandler != nil and excHandler.exc != nil:
-    return $excHandler.exc.msg
-  elif lastJSError != nil:
+  if lastJSError != nil:
     return $lastJSError.message
   else:
     return ""
 
 proc auxWriteStackTrace(f: PCallFrame): string =
   type
-    TTempFrame = tuple[procname: cstring, line: int]
+    TempFrame = tuple[procname: cstring, line: int]
+  {.deprecated: [TTempFrame: TempFrame].}
   var
     it = f
     i = 0
     total = 0
-    tempFrames: array [0..63, TTempFrame]
+    tempFrames: array [0..63, TempFrame]
   while it != nil and i <= high(tempFrames):
     tempFrames[i].procname = it.procname
     tempFrames[i].line = it.line
@@ -97,32 +95,41 @@ proc rawWriteStackTrace(): string =
   else:
     result = "No stack traceback available\n"
 
-proc raiseException(e: ref Exception, ename: cstring) {.
+proc unhandledException(e: ref Exception) {.
     compilerproc, asmNoStackFrame.} =
-  e.name = ename
-  if excHandler != nil:
-    excHandler.exc = e
+  when NimStackTrace:
+    var buf = rawWriteStackTrace()
   else:
-    when NimStackTrace:
-      var buf = rawWriteStackTrace()
-    else:
-      var buf = ""
+    var buf = ""
     if e.msg != nil and e.msg[0] != '\0':
       add(buf, "Error: unhandled exception: ")
       add(buf, e.msg)
     else:
       add(buf, "Error: unhandled exception")
     add(buf, " [")
-    add(buf, ename)
+    add(buf, e.name)
     add(buf, "]\n")
     alert(buf)
-  asm """throw `e`;"""
+
+proc raiseException(e: ref Exception, ename: cstring) {.
+    compilerproc, asmNoStackFrame.} =
+  e.name = ename
+  when not defined(noUnhandledHandler):
+    if excHandler == 0:
+      unhandledException(e)
+  asm "throw `e`;"
 
 proc reraiseException() {.compilerproc, asmNoStackFrame.} =
-  if excHandler == nil:
+  if lastJSError == nil:
     raise newException(ReraiseError, "no exception to reraise")
   else:
-    asm """throw excHandler.exc;"""
+    when not defined(noUnhandledHandler):
+      if excHandler == 0:
+        var isNimException : bool
+        asm "`isNimException` = lastJSError.m_type;"
+        if isNimException:
+          unhandledException(cast[ref Exception](lastJSError))
+    asm "throw lastJSError;"
 
 proc raiseOverflow {.exportc: "raiseOverflow", noreturn.} =
   raise newException(OverflowError, "over- or underflow")
@@ -168,12 +175,28 @@ proc cstrToNimstr(c: cstring): string {.asmNoStackFrame, compilerproc.} =
 proc toJSStr(s: string): cstring {.asmNoStackFrame, compilerproc.} =
   asm """
     var len = `s`.length-1;
-    var result = new Array(len);
+    var asciiPart = new Array(len);
     var fcc = String.fromCharCode;
+    var nonAsciiPart = null;
+    var nonAsciiOffset = 0;
     for (var i = 0; i < len; ++i) {
-      result[i] = fcc(`s`[i]);
+      if (nonAsciiPart !== null) {
+        var offset = (i - nonAsciiOffset) * 2;
+        nonAsciiPart[offset] = "%";
+        nonAsciiPart[offset + 1] = `s`[i].toString(16);
+      }
+      else if (`s`[i] < 128)
+        asciiPart[i] = fcc(`s`[i]);
+      else {
+        asciiPart.length = i;
+        nonAsciiOffset = i;
+        nonAsciiPart = new Array((len - i) * 2);
+        --i;
+      }
     }
-    return result.join("");
+    asciiPart = asciiPart.join("");
+    return (nonAsciiPart === null) ?
+        asciiPart : asciiPart + decodeURIComponent(nonAsciiPart.join(""));
   """
 
 proc mnewString(len: int): string {.asmNoStackFrame, compilerproc.} =
@@ -260,17 +283,17 @@ proc eqStrings(a, b: string): bool {.asmNoStackFrame, compilerProc.} =
   """
 
 type
-  TDocument {.importc.} = object of RootObj
+  Document {.importc.} = object of RootObj
     write: proc (text: cstring) {.nimcall.}
     writeln: proc (text: cstring) {.nimcall.}
-    createAttribute: proc (identifier: cstring): ref TNode {.nimcall.}
-    createElement: proc (identifier: cstring): ref TNode {.nimcall.}
-    createTextNode: proc (identifier: cstring): ref TNode {.nimcall.}
-    getElementById: proc (id: cstring): ref TNode {.nimcall.}
-    getElementsByName: proc (name: cstring): seq[ref TNode] {.nimcall.}
-    getElementsByTagName: proc (name: cstring): seq[ref TNode] {.nimcall.}
-
-  TNodeType* = enum
+    createAttribute: proc (identifier: cstring): ref Node {.nimcall.}
+    createElement: proc (identifier: cstring): ref Node {.nimcall.}
+    createTextNode: proc (identifier: cstring): ref Node {.nimcall.}
+    getElementById: proc (id: cstring): ref Node {.nimcall.}
+    getElementsByName: proc (name: cstring): seq[ref Node] {.nimcall.}
+    getElementsByTagName: proc (name: cstring): seq[ref Node] {.nimcall.}
+
+  NodeType* = enum
     ElementNode = 1,
     AttributeNode,
     TextNode,
@@ -283,35 +306,36 @@ type
     DocumentTypeNode,
     DocumentFragmentNode,
     NotationNode
-  TNode* {.importc.} = object of RootObj
-    attributes*: seq[ref TNode]
-    childNodes*: seq[ref TNode]
+  Node* {.importc.} = object of RootObj
+    attributes*: seq[ref Node]
+    childNodes*: seq[ref Node]
     data*: cstring
-    firstChild*: ref TNode
-    lastChild*: ref TNode
-    nextSibling*: ref TNode
+    firstChild*: ref Node
+    lastChild*: ref Node
+    nextSibling*: ref Node
     nodeName*: cstring
-    nodeType*: TNodeType
+    nodeType*: NodeType
     nodeValue*: cstring
-    parentNode*: ref TNode
-    previousSibling*: ref TNode
-    appendChild*: proc (child: ref TNode) {.nimcall.}
+    parentNode*: ref Node
+    previousSibling*: ref Node
+    appendChild*: proc (child: ref Node) {.nimcall.}
     appendData*: proc (data: cstring) {.nimcall.}
     cloneNode*: proc (copyContent: bool) {.nimcall.}
     deleteData*: proc (start, len: int) {.nimcall.}
     getAttribute*: proc (attr: cstring): cstring {.nimcall.}
-    getAttributeNode*: proc (attr: cstring): ref TNode {.nimcall.}
-    getElementsByTagName*: proc (): seq[ref TNode] {.nimcall.}
+    getAttributeNode*: proc (attr: cstring): ref Node {.nimcall.}
+    getElementsByTagName*: proc (): seq[ref Node] {.nimcall.}
     hasChildNodes*: proc (): bool {.nimcall.}
-    insertBefore*: proc (newNode, before: ref TNode) {.nimcall.}
+    insertBefore*: proc (newNode, before: ref Node) {.nimcall.}
     insertData*: proc (position: int, data: cstring) {.nimcall.}
     removeAttribute*: proc (attr: cstring) {.nimcall.}
-    removeAttributeNode*: proc (attr: ref TNode) {.nimcall.}
-    removeChild*: proc (child: ref TNode) {.nimcall.}
-    replaceChild*: proc (newNode, oldNode: ref TNode) {.nimcall.}
+    removeAttributeNode*: proc (attr: ref Node) {.nimcall.}
+    removeChild*: proc (child: ref Node) {.nimcall.}
+    replaceChild*: proc (newNode, oldNode: ref Node) {.nimcall.}
     replaceData*: proc (start, len: int, text: cstring) {.nimcall.}
     setAttribute*: proc (name, value: cstring) {.nimcall.}
-    setAttributeNode*: proc (attr: ref TNode) {.nimcall.}
+    setAttributeNode*: proc (attr: ref Node) {.nimcall.}
+{.deprecated: [TNode: Node, TNodeType: NodeType, TDocument: Document].}
 
 when defined(kwin):
   proc rawEcho {.compilerproc, asmNoStackFrame.} =
@@ -337,7 +361,7 @@ elif defined(nodejs):
 
 else:
   var
-    document {.importc, nodecl.}: ref TDocument
+    document {.importc, nodecl.}: ref Document
 
   proc ewriteln(x: cstring) =
     var node = document.getElementsByTagName("body")[0]
@@ -508,75 +532,80 @@ proc nimMax(a, b: int): int {.compilerproc.} = return if a >= b: a else: b
 type NimString = string # hack for hti.nim
 include "system/hti"
 
+type JSRef = int # Fake type.
+
 proc isFatPointer(ti: PNimType): bool =
   # This has to be consistent with the code generator!
   return ti.base.kind notin {tyObject,
     tyArray, tyArrayConstr, tyTuple,
     tyOpenArray, tySet, tyVar, tyRef, tyPtr}
 
-proc nimCopy(x: pointer, ti: PNimType): pointer {.compilerproc.}
+proc nimCopy(dest, src: JSRef, ti: PNimType): JSRef {.compilerproc.}
 
-proc nimCopyAux(dest, src: pointer, n: ptr TNimNode) {.compilerproc.} =
+proc nimCopyAux(dest, src: JSRef, n: ptr TNimNode) {.compilerproc.} =
   case n.kind
   of nkNone: sysAssert(false, "nimCopyAux")
   of nkSlot:
-    asm "`dest`[`n`.offset] = nimCopy(`src`[`n`.offset], `n`.typ);"
+    asm """
+      `dest`[`n`.offset] = nimCopy(`dest`[`n`.offset], `src`[`n`.offset], `n`.typ);
+    """
   of nkList:
     for i in 0..n.len-1:
       nimCopyAux(dest, src, n.sons[i])
   of nkCase:
     asm """
-      `dest`[`n`.offset] = nimCopy(`src`[`n`.offset], `n`.typ);
+      `dest`[`n`.offset] = nimCopy(`dest`[`n`.offset], `src`[`n`.offset], `n`.typ);
       for (var i = 0; i < `n`.sons.length; ++i) {
         nimCopyAux(`dest`, `src`, `n`.sons[i][1]);
       }
     """
 
-proc nimCopy(x: pointer, ti: PNimType): pointer =
+proc nimCopy(dest, src: JSRef, ti: PNimType): JSRef =
   case ti.kind
   of tyPtr, tyRef, tyVar, tyNil:
     if not isFatPointer(ti):
-      result = x
+      result = src
     else:
-      asm """
-        `result` = [null, 0];
-        `result`[0] = `x`[0];
-        `result`[1] = `x`[1];
-      """
+      asm "`result` = [`src`[0], `src`[1]];"
   of tySet:
     asm """
       `result` = {};
-      for (var key in `x`) { `result`[key] = `x`[key]; }
+      for (var key in `src`) { `result`[key] = `src`[key]; }
     """
   of tyTuple, tyObject:
-    if ti.base != nil: result = nimCopy(x, ti.base)
+    if ti.base != nil: result = nimCopy(dest, src, ti.base)
     elif ti.kind == tyObject:
-      asm "`result` = {m_type: `ti`};"
+      asm "`result` = (`dest` === null || `dest` === undefined) ? {m_type: `ti`} : `dest`;"
     else:
-      asm "`result` = {};"
-    nimCopyAux(result, x, ti.node)
+      asm "`result` = (`dest` === null || `dest` === undefined) ? {} : `dest`;"
+    nimCopyAux(result, src, ti.node)
   of tySequence, tyArrayConstr, tyOpenArray, tyArray:
     asm """
-      `result` = new Array(`x`.length);
-      for (var i = 0; i < `x`.length; ++i) {
-        `result`[i] = nimCopy(`x`[i], `ti`.base);
+      if (`dest` === null || `dest` === undefined) {
+        `dest` = new Array(`src`.length);
+      }
+      else {
+        `dest`.length = `src`.length;
+      }
+      `result` = `dest`;
+      for (var i = 0; i < `src`.length; ++i) {
+        `result`[i] = nimCopy(`result`[i], `src`[i], `ti`.base);
       }
     """
   of tyString:
     asm """
-      if (`x` !== null) {
-        `result` = `x`.slice(0);
+      if (`src` !== null) {
+        `result` = `src`.slice(0);
       }
     """
   else:
-    result = x
+    result = src
 
-proc genericReset(x: pointer, ti: PNimType): pointer {.compilerproc.} =
+proc genericReset(x: JSRef, ti: PNimType): JSRef {.compilerproc.} =
+  asm "`result` = null;"
   case ti.kind
   of tyPtr, tyRef, tyVar, tyNil:
-    if not isFatPointer(ti):
-      result = nil
-    else:
+    if isFatPointer(ti):
       asm """
         `result` = [null, 0];
       """
@@ -601,14 +630,14 @@ proc genericReset(x: pointer, ti: PNimType): pointer {.compilerproc.} =
       }
     """
   else:
-    result = nil
+    discard
 
-proc arrayConstr(len: int, value: pointer, typ: PNimType): pointer {.
+proc arrayConstr(len: int, value: JSRef, typ: PNimType): JSRef {.
                  asmNoStackFrame, compilerproc.} =
   # types are fake
   asm """
     var result = new Array(`len`);
-    for (var i = 0; i < `len`; ++i) result[i] = nimCopy(`value`, `typ`);
+    for (var i = 0; i < `len`; ++i) result[i] = nimCopy(null, `value`, `typ`);
     return result;
   """
 
diff --git a/lib/system/mmdisp.nim b/lib/system/mmdisp.nim
index 84e532049..1c13f3ff8 100644
--- a/lib/system/mmdisp.nim
+++ b/lib/system/mmdisp.nim
@@ -7,7 +7,7 @@
 #    distribution, for details about the copyright.
 #
 
-# Nim high-level memory manager: It supports Boehm's GC, no GC and the
+# Nim high-level memory manager: It supports Boehm's GC, Go's GC, no GC and the
 # native Nim GC. The native Nim GC is the default.
 
 #{.push checks:on, assertions:on.}
@@ -34,14 +34,15 @@ const
 
 type
   PPointer = ptr pointer
-  TByteArray = array[0..1000_0000, byte]
-  PByte = ptr TByteArray
+  ByteArray = array[0..ArrayDummySize, byte]
+  PByte = ptr ByteArray
   PString = ptr string
+{.deprecated: [TByteArray: ByteArray].}
 
 # Page size of the system; in most cases 4096 bytes. For exotic OS or
 # CPU this needs to be changed:
 const
-  PageShift = 12
+  PageShift = when defined(cpu16): 8 else: 12
   PageSize = 1 shl PageShift
   PageMask = PageSize-1
 
@@ -65,41 +66,34 @@ proc raiseOutOfMem() {.noinline.} =
   quit(1)
 
 when defined(boehmgc):
-  when defined(windows):
-    const boehmLib = "boehmgc.dll"
-  elif defined(macosx):
-    const boehmLib = "libgc.dylib"
-  else:
-    const boehmLib = "/usr/lib/libgc.so.1"
-
-  proc boehmGCinit {.importc: "GC_init", dynlib: boehmLib.}
-  proc boehmGC_disable {.importc: "GC_disable", dynlib: boehmLib.}
-  proc boehmGC_enable {.importc: "GC_enable", dynlib: boehmLib.}
+  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", dynlib: boehmLib.}
-  proc boehmGCfullCollect {.importc: "GC_gcollect", dynlib: boehmLib.}
-  proc boehmAlloc(size: int): pointer {.
-    importc: "GC_malloc", dynlib: boehmLib.}
+    importc: "GC_enable_incremental", boehmGC.}
+  proc boehmGCfullCollect {.importc: "GC_gcollect", boehmGC.}
+  proc boehmAlloc(size: int): pointer {.importc: "GC_malloc", boehmGC.}
   proc boehmAllocAtomic(size: int): pointer {.
-    importc: "GC_malloc_atomic", dynlib: boehmLib.}
+    importc: "GC_malloc_atomic", boehmGC.}
   proc boehmRealloc(p: pointer, size: int): pointer {.
-    importc: "GC_realloc", dynlib: boehmLib.}
-  proc boehmDealloc(p: pointer) {.importc: "GC_free", dynlib: boehmLib.}
+    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", dynlib: boehmLib.}
+  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", dynlib: boehmLib.}
+  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",
-    dynlib: boehmLib.}
+  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",
-    dynlib: boehmLib.}
+  proc boehmGetTotalBytes: int {.importc: "GC_get_total_bytes", boehmGC.}
     ## Return the total number of bytes allocated in this process.
     ## Never decreases.
 
@@ -109,24 +103,24 @@ when defined(boehmgc):
 
   when not defined(useNimRtl):
 
-    proc alloc(size: int): pointer =
+    proc alloc(size: Natural): pointer =
       result = boehmAlloc(size)
       if result == nil: raiseOutOfMem()
-    proc alloc0(size: int): pointer =
+    proc alloc0(size: Natural): pointer =
       result = alloc(size)
       zeroMem(result, size)
-    proc realloc(p: pointer, newsize: int): pointer =
+    proc realloc(p: pointer, newsize: Natural): pointer =
       result = boehmRealloc(p, newsize)
       if result == nil: raiseOutOfMem()
     proc dealloc(p: pointer) = boehmDealloc(p)
 
-    proc allocShared(size: int): pointer =
+    proc allocShared(size: Natural): pointer =
       result = boehmAlloc(size)
       if result == nil: raiseOutOfMem()
-    proc allocShared0(size: int): pointer =
+    proc allocShared0(size: Natural): pointer =
       result = alloc(size)
       zeroMem(result, size)
-    proc reallocShared(p: pointer, newsize: int): pointer =
+    proc reallocShared(p: pointer, newsize: Natural): pointer =
       result = boehmRealloc(p, newsize)
       if result == nil: raiseOutOfMem()
     proc deallocShared(p: pointer) = boehmDealloc(p)
@@ -156,7 +150,9 @@ when defined(boehmgc):
     proc setStackBottom(theStackBottom: pointer) = discard
 
   proc initGC() =
-    when defined(macosx): boehmGCinit()
+    boehmGCinit()
+    when hasThreadSupport:
+      boehmGC_allow_register_threads()
 
   proc newObj(typ: PNimType, size: int): pointer {.compilerproc.} =
     if ntfNoRefs in typ.flags: result = allocAtomic(size)
@@ -180,40 +176,236 @@ when defined(boehmgc):
     dest[] = src
 
   type
-    TMemRegion = object {.final, pure.}
+    MemRegion = object {.final, pure.}
+  {.deprecated: [TMemRegion: MemRegion].}
 
-  proc alloc(r: var TMemRegion, size: int): pointer =
+  proc alloc(r: var MemRegion, size: int): pointer =
     result = boehmAlloc(size)
     if result == nil: raiseOutOfMem()
-  proc alloc0(r: var TMemRegion, size: int): pointer =
+  proc alloc0(r: var MemRegion, size: int): pointer =
     result = alloc(size)
     zeroMem(result, size)
-  proc dealloc(r: var TMemRegion, p: pointer) = boehmDealloc(p)
-  proc deallocOsPages(r: var TMemRegion) {.inline.} = discard
+  proc dealloc(r: var MemRegion, p: pointer) = boehmDealloc(p)
+  proc deallocOsPages(r: var MemRegion) {.inline.} = discard
   proc deallocOsPages() {.inline.} = discard
 
   include "system/cellsets"
+
+elif defined(gogc):
+  when defined(windows):
+    const goLib = "libgo.dll"
+  elif defined(macosx):
+    const goLib = "libgo.dylib"
+  else:
+    const goLib = "libgo.so"
+
+  proc roundup(x, v: int): int {.inline.} =
+    result = (x + (v-1)) and not (v-1)
+
+  proc initGC() = discard
+  # runtime_setgcpercent is only available in GCC 5
+  proc GC_disable() = discard
+  proc GC_enable() = discard
+  proc goRuntimeGC(force: int32) {.importc: "runtime_gc", dynlib: goLib.}
+  proc GC_fullCollect() = goRuntimeGC(2)
+  proc GC_setStrategy(strategy: GC_Strategy) = discard
+  proc GC_enableMarkAndSweep() = discard
+  proc GC_disableMarkAndSweep() = discard
+
+  const
+    goNumSizeClasses = 67
+
+  type
+    cbool {.importc: "_Bool", nodecl.} = bool
+
+    goMStats_inner_struct = object
+        size: uint32
+        nmalloc: uint64
+        nfree: uint64
+
+    goMStats = object
+        # General statistics.
+        alloc: uint64            # bytes allocated and still in use
+        total_alloc: uint64      # bytes allocated (even if freed)
+        sys: uint64              # bytes obtained from system (should be sum of xxx_sys below, no locking, approximate)
+        nlookup: uint64          # number of pointer lookups
+        nmalloc: uint64          # number of mallocs
+        nfree: uint64            # number of frees
+        # Statistics about malloc heap.
+        # protected by mheap.Lock
+        heap_alloc: uint64       # bytes allocated and still in use
+        heap_sys: uint64         # bytes obtained from system
+        heap_idle: uint64        # bytes in idle spans
+        heap_inuse: uint64       # bytes in non-idle spans
+        heap_released: uint64    # bytes released to the OS
+        heap_objects: uint64 # total number of allocated objects
+        # Statistics about allocation of low-level fixed-size structures.
+        # Protected by FixAlloc locks.
+        stacks_inuse: uint64     # bootstrap stacks
+        stacks_sys: uint64
+        mspan_inuse: uint64      # MSpan structures
+        mspan_sys: uint64
+        mcache_inuse: uint64     # MCache structures
+        mcache_sys: uint64
+        buckhash_sys: uint64     # profiling bucket hash table
+        gc_sys: uint64
+        other_sys: uint64
+        # Statistics about garbage collector.
+        # Protected by mheap or stopping the world during GC.
+        next_gc: uint64          # next GC (in heap_alloc time)
+        last_gc: uint64          # last GC (in absolute time)
+        pause_total_ns: uint64
+        pause_ns: array[256, uint64]
+        numgc: uint32
+        enablegc: cbool
+        debuggc: cbool
+        # Statistics about allocation size classes.
+        by_size: array[goNumSizeClasses, goMStats_inner_struct]
+
+  proc goRuntime_ReadMemStats(a2: ptr goMStats) {.cdecl,
+    importc: "runtime_ReadMemStats",
+    codegenDecl: "$1 $2$3 __asm__ (\"runtime.ReadMemStats\");\n$1 $2$3",
+    dynlib: goLib.}
+
+  proc GC_getStatistics(): string =
+    var mstats: goMStats
+    goRuntime_ReadMemStats(addr mstats)
+    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] numgc: " & $(mstats.numgc) & "\n" &
+             "[GC] enablegc: " & $(mstats.enablegc) & "\n" &
+             "[GC] debuggc: " & $(mstats.debuggc) & "\n" &
+             "[GC] total pause time [ms]: " & $(mstats.pause_total_ns div 1000_000)
+
+  proc getOccupiedMem(): int =
+    var mstats: goMStats
+    goRuntime_ReadMemStats(addr mstats)
+    result = int(mstats.alloc)
+
+  proc getFreeMem(): int =
+    var mstats: goMStats
+    goRuntime_ReadMemStats(addr mstats)
+    result = int(mstats.sys - mstats.alloc)
+
+  proc getTotalMem(): int =
+    var mstats: goMStats
+    goRuntime_ReadMemStats(addr mstats)
+    result = int(mstats.sys)
+
+  proc setStackBottom(theStackBottom: pointer) = discard
+
+  proc alloc(size: Natural): pointer =
+    result = cmalloc(size)
+    if result == nil: raiseOutOfMem()
+
+  proc alloc0(size: Natural): pointer =
+    result = alloc(size)
+    zeroMem(result, size)
+
+  proc realloc(p: pointer, newsize: Natural): pointer =
+    result = crealloc(p, newsize)
+    if result == nil: raiseOutOfMem()
+
+  proc dealloc(p: pointer) = cfree(p)
+
+  proc allocShared(size: Natural): pointer =
+    result = cmalloc(size)
+    if result == nil: raiseOutOfMem()
+
+  proc allocShared0(size: Natural): pointer =
+    result = alloc(size)
+    zeroMem(result, size)
+
+  proc reallocShared(p: pointer, newsize: Natural): pointer =
+    result = crealloc(p, newsize)
+    if result == nil: raiseOutOfMem()
+
+  proc deallocShared(p: pointer) = cfree(p)
+
+  when hasThreadSupport:
+    proc getFreeSharedMem(): int = discard
+    proc getTotalSharedMem(): int = discard
+    proc getOccupiedSharedMem(): int = discard
+
+  const goFlagNoZero: uint32 = 1 shl 3
+  proc goRuntimeMallocGC(size: uint, typ: uint, flag: uint32): pointer {.importc: "runtime_mallocgc", dynlib: goLib.}
+  proc goFree(v: pointer) {.importc: "__go_free", 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 newObj(typ: PNimType, size: int): pointer {.compilerproc.} =
+    result = goRuntimeMallocGC(roundup(size, sizeof(pointer)).uint, 0.uint, 0.uint32)
+    if typ.finalizer != nil:
+      goSetFinalizer(result, typ.finalizer)
+
+  proc newObjNoInit(typ: PNimType, size: int): pointer =
+    result = goRuntimeMallocGC(roundup(size, sizeof(pointer)).uint, 0.uint, goFlagNoZero)
+    if typ.finalizer != nil:
+      goSetFinalizer(result, typ.finalizer)
+
+  proc newSeq(typ: PNimType, len: int): pointer {.compilerproc.} =
+    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 growObj(old: pointer, newsize: int): pointer =
+    # the Go GC doesn't have a realloc
+    var
+      oldsize = cast[PGenericSeq](old).len * cast[PGenericSeq](old).elemSize + GenericSeqSize
+    result = goRuntimeMallocGC(roundup(newsize, sizeof(pointer)).uint, 0.uint, goFlagNoZero)
+    copyMem(result, old, oldsize)
+    zeroMem(cast[pointer](cast[ByteAddress](result) +% oldsize), newsize - oldsize)
+    goFree(old)
+
+  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.} =
+    dest[] = src
+
+  type
+    MemRegion = object {.final, pure.}
+  {.deprecated: [TMemRegion: MemRegion].}
+
+  proc alloc(r: var MemRegion, size: int): pointer =
+    result = alloc(size)
+  proc alloc0(r: var MemRegion, size: int): pointer =
+    result = alloc0(size)
+  proc dealloc(r: var MemRegion, p: pointer) = dealloc(p)
+  proc deallocOsPages(r: var MemRegion) {.inline.} = discard
+  proc deallocOsPages() {.inline.} = discard
+
 elif defined(nogc) and defined(useMalloc):
 
   when not defined(useNimRtl):
-    proc alloc(size: int): pointer =
+    proc alloc(size: Natural): pointer =
       result = cmalloc(size)
       if result == nil: raiseOutOfMem()
-    proc alloc0(size: int): pointer =
+    proc alloc0(size: Natural): pointer =
       result = alloc(size)
       zeroMem(result, size)
-    proc realloc(p: pointer, newsize: int): pointer =
+    proc realloc(p: pointer, newsize: Natural): pointer =
       result = crealloc(p, newsize)
       if result == nil: raiseOutOfMem()
     proc dealloc(p: pointer) = cfree(p)
 
-    proc allocShared(size: int): pointer =
+    proc allocShared(size: Natural): pointer =
       result = cmalloc(size)
       if result == nil: raiseOutOfMem()
-    proc allocShared0(size: int): pointer =
+    proc allocShared0(size: Natural): pointer =
       result = alloc(size)
       zeroMem(result, size)
-    proc reallocShared(p: pointer, newsize: int): pointer =
+    proc reallocShared(p: pointer, newsize: Natural): pointer =
       result = crealloc(p, newsize)
       if result == nil: raiseOutOfMem()
     proc deallocShared(p: pointer) = cfree(p)
@@ -257,14 +449,15 @@ elif defined(nogc) and defined(useMalloc):
     dest[] = src
 
   type
-    TMemRegion = object {.final, pure.}
+    MemRegion = object {.final, pure.}
+  {.deprecated: [TMemRegion: MemRegion].}
 
-  proc alloc(r: var TMemRegion, size: int): pointer =
+  proc alloc(r: var MemRegion, size: int): pointer =
     result = alloc(size)
-  proc alloc0(r: var TMemRegion, size: int): pointer =
+  proc alloc0(r: var MemRegion, size: int): pointer =
     result = alloc0(size)
-  proc dealloc(r: var TMemRegion, p: pointer) = dealloc(p)
-  proc deallocOsPages(r: var TMemRegion) {.inline.} = discard
+  proc dealloc(r: var MemRegion, p: pointer) = dealloc(p)
+  proc deallocOsPages(r: var MemRegion) {.inline.} = discard
   proc deallocOsPages() {.inline.} = discard
 
 elif defined(nogc):
@@ -288,7 +481,6 @@ elif defined(nogc):
   proc GC_disableMarkAndSweep() = discard
   proc GC_getStatistics(): string = return ""
 
-
   proc newObj(typ: PNimType, size: int): pointer {.compilerproc.} =
     result = alloc0(size)
 
@@ -313,7 +505,7 @@ elif defined(nogc):
   proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline.} =
     dest[] = src
 
-  var allocator {.rtlThreadVar.}: TMemRegion
+  var allocator {.rtlThreadVar.}: MemRegion
   instantiateForRegion(allocator)
 
   include "system/cellsets"
@@ -323,7 +515,7 @@ else:
 
   include "system/cellsets"
   when not leakDetector:
-    sysAssert(sizeof(TCell) == sizeof(TFreeCell), "sizeof TFreeCell")
+    sysAssert(sizeof(Cell) == sizeof(FreeCell), "sizeof FreeCell")
   when compileOption("gc", "v2"):
     include "system/gc2"
   elif defined(gcMarkAndSweep):
@@ -335,4 +527,3 @@ else:
     include "system/gc"
 
 {.pop.}
-
diff --git a/lib/system/nimscript.nim b/lib/system/nimscript.nim
new file mode 100644
index 000000000..22430348c
--- /dev/null
+++ b/lib/system/nimscript.nim
@@ -0,0 +1,277 @@
+#
+#
+#            Nim's Runtime Library
+#        (c) Copyright 2015 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+
+# Nim's configuration system now uses Nim for scripting. This module provides
+# a few things that are required for this to work.
+
+template builtin = discard
+
+# We know the effects better than the compiler:
+{.push hint[XDeclaredButNotUsed]: off.}
+
+proc listDirs*(dir: string): seq[string] =
+  ## Lists all the subdirectories (non-recursively) in the directory `dir`.
+  builtin
+proc listFiles*(dir: string): seq[string] =
+  ## Lists all the files (non-recursively) in the directory `dir`.
+  builtin
+
+proc removeDir(dir: string){.
+  tags: [ReadIOEffect, WriteIOEffect], raises: [OSError].} = builtin
+proc removeFile(dir: string) {.
+  tags: [ReadIOEffect, WriteIOEffect], raises: [OSError].} = builtin
+proc moveFile(src, dest: string) {.
+  tags: [ReadIOEffect, WriteIOEffect], raises: [OSError].} = builtin
+proc copyFile(src, dest: string) {.
+  tags: [ReadIOEffect, WriteIOEffect], raises: [OSError].} = builtin
+proc createDir(dir: string) {.tags: [WriteIOEffect], raises: [OSError].} =
+  builtin
+proc getOsError: string = builtin
+proc setCurrentDir(dir: string) = builtin
+proc getCurrentDir(): string = builtin
+proc rawExec(cmd: string): int {.tags: [ExecIOEffect], raises: [OSError].} =
+  builtin
+
+proc paramStr*(i: int): string =
+  ## Retrieves the ``i``'th command line parameter.
+  builtin
+
+proc paramCount*(): int =
+  ## Retrieves the number of command line parameters.
+  builtin
+
+proc switch*(key: string, val="") =
+  ## Sets a Nim compiler command line switch, for
+  ## example ``switch("checks", "on")``.
+  builtin
+
+proc getCommand*(): string =
+  ## Gets the Nim command that the compiler has been invoked with, for example
+  ## "c", "js", "build", "help".
+  builtin
+
+proc setCommand*(cmd: string; project="") =
+  ## Sets the Nim command that should be continued with after this Nimscript
+  ## has finished.
+  builtin
+
+proc cmpIgnoreStyle(a, b: string): int = builtin
+proc cmpIgnoreCase(a, b: string): int = builtin
+
+proc cmpic*(a, b: string): int =
+  ## Compares `a` and `b` ignoring case.
+  cmpIgnoreCase(a, b)
+
+proc getEnv*(key: string): string {.tags: [ReadIOEffect].} =
+  ## Retrieves the environment variable of name `key`.
+  builtin
+
+proc existsEnv*(key: string): bool {.tags: [ReadIOEffect].} =
+  ## Checks for the existance of an environment variable named `key`.
+  builtin
+
+proc fileExists*(filename: string): bool {.tags: [ReadIOEffect].} =
+  ## Checks if the file exists.
+  builtin
+
+proc dirExists*(dir: string): bool {.
+  tags: [ReadIOEffect].} =
+  ## Checks if the directory `dir` exists.
+  builtin
+
+proc existsFile*(filename: string): bool =
+  ## An alias for ``fileExists``.
+  fileExists(filename)
+
+proc existsDir*(dir: string): bool =
+  ## An alias for ``dirExists``.
+  dirExists(dir)
+
+proc toExe*(filename: string): string =
+  ## On Windows adds ".exe" to `filename`, else returns `filename` unmodified.
+  (when defined(windows): filename & ".exe" else: filename)
+
+proc toDll*(filename: string): string =
+  ## On Windows adds ".dll" to `filename`, on Posix produces "lib$filename.so".
+  (when defined(windows): filename & ".dll" else: "lib" & filename & ".so")
+
+proc strip(s: string): string =
+  var i = 0
+  while s[i] in {' ', '\c', '\L'}: inc i
+  result = s.substr(i)
+
+template `--`*(key, val: untyped) =
+  ## A shortcut for ``switch(astToStr(key), astToStr(val))``.
+  switch(astToStr(key), strip astToStr(val))
+
+template `--`*(key: untyped) =
+  ## A shortcut for ``switch(astToStr(key)``.
+  switch(astToStr(key), "")
+
+type
+  ScriptMode* {.pure.} = enum ## Controls the behaviour of the script.
+    Silent,                   ## Be silent.
+    Verbose,                  ## Be verbose.
+    Whatif                    ## Do not run commands, instead just echo what
+                              ## would have been done.
+
+var
+  mode*: ScriptMode ## Set this to influence how mkDir, rmDir, rmFile etc.
+                    ## behave
+
+template checkOsError =
+  let err = getOsError()
+  if err.len > 0: raise newException(OSError, err)
+
+template log(msg: string, body: untyped) =
+  if mode == ScriptMode.Verbose or mode == ScriptMode.Whatif:
+    echo "[NimScript] ", msg
+  if mode != ScriptMode.WhatIf:
+    body
+
+proc rmDir*(dir: string) {.raises: [OSError].} =
+  ## Removes the directory `dir`.
+  log "rmDir: " & dir:
+    removeDir dir
+    checkOsError()
+
+proc rmFile*(file: string) {.raises: [OSError].} =
+  ## Removes the `file`.
+  log "rmFile: " & file:
+    removeFile file
+    checkOsError()
+
+proc mkDir*(dir: string) {.raises: [OSError].} =
+  ## Creates the directory `dir` including all necessary subdirectories. If
+  ## the directory already exists, no error is raised.
+  log "mkDir: " & dir:
+    createDir dir
+    checkOsError()
+
+proc mvFile*(`from`, to: string) {.raises: [OSError].} =
+  ## Moves the file `from` to `to`.
+  log "mvFile: " & `from` & ", " & to:
+    moveFile `from`, to
+    checkOsError()
+
+proc cpFile*(`from`, to: string) {.raises: [OSError].} =
+  ## Copies the file `from` to `to`.
+  log "mvFile: " & `from` & ", " & to:
+    copyFile `from`, to
+    checkOsError()
+
+proc exec*(command: string) =
+  ## Executes an external process.
+  log "exec: " & command:
+    if rawExec(command) != 0:
+      raise newException(OSError, "FAILED: " & command)
+    checkOsError()
+
+proc exec*(command: string, input: string, cache = "") {.
+  raises: [OSError], tags: [ExecIOEffect].} =
+  ## Executes an external process.
+  log "exec: " & command:
+    echo staticExec(command, input, cache)
+
+proc put*(key, value: string) =
+  ## Sets a configuration 'key' like 'gcc.options.always' to its value.
+  builtin
+
+proc get*(key: string): string =
+  ## Retrieves a configuration 'key' like 'gcc.options.always'.
+  builtin
+
+proc exists*(key: string): bool =
+  ## Checks for the existance of a configuration 'key'
+  ## like 'gcc.options.always'.
+  builtin
+
+proc nimcacheDir*(): string =
+  ## Retrieves the location of 'nimcache'.
+  builtin
+
+proc thisDir*(): string =
+  ## Retrieves the location of the current ``nims`` script file.
+  builtin
+
+proc cd*(dir: string) {.raises: [OSError].} =
+  ## Changes the current directory.
+  ##
+  ## The change is permanent for the rest of the execution, since this is just
+  ## a shortcut for `os.setCurrentDir()
+  ## <http://nim-lang.org/os.html#setCurrentDir,string>`_ . Use the `withDir()
+  ## <#withDir>`_ template if you want to perform a temporary change only.
+  setCurrentDir(dir)
+  checkOsError()
+
+template withDir*(dir: string; body: untyped): untyped =
+  ## Changes the current directory temporarily.
+  ##
+  ## If you need a permanent change, use the `cd() <#cd>`_ proc. Usage example:
+  ##
+  ## .. code-block:: nim
+  ##   withDir "foo":
+  ##     # inside foo
+  ##   #back to last dir
+  var curDir = getCurrentDir()
+  try:
+    cd(dir)
+    body
+  finally:
+    cd(curDir)
+
+template `==?`(a, b: string): bool = cmpIgnoreStyle(a, b) == 0
+
+proc writeTask(name, desc: string) =
+  if desc.len > 0:
+    var spaces = " "
+    for i in 0 ..< 20 - name.len: spaces.add ' '
+    echo name, spaces, desc
+
+template task*(name: untyped; description: string; body: untyped): untyped =
+  ## Defines a task. Hidden tasks are supported via an empty description.
+  ## Example:
+  ##
+  ## .. code-block:: nim
+  ##  task build, "default build is via the C backend":
+  ##    setCommand "c"
+  proc `name Task`() = body
+
+  let cmd = getCommand()
+  if cmd.len == 0 or cmd ==? "help":
+    setCommand "help"
+    writeTask(astToStr(name), description)
+  elif cmd ==? astToStr(name):
+    setCommand "nop"
+    `name Task`()
+
+var
+  packageName* = ""    ## Nimble support: Set this to the package name. It
+                       ## is usually not required to do that, nims' filename is
+                       ## the default.
+  version*: string     ## Nimble support: The package's version.
+  author*: string      ## Nimble support: The package's author.
+  description*: string ## Nimble support: The package's description.
+  license*: string     ## Nimble support: The package's license.
+  srcdir*: string      ## Nimble support: The package's source directory.
+  binDir*: string      ## Nimble support: The package's binary directory.
+  backend*: string     ## Nimble support: The package's backend.
+
+  skipDirs*, skipFiles*, skipExt*, installDirs*, installFiles*,
+    installExt*, bin*: seq[string] = @[] ## Nimble metadata.
+  requiresData*: seq[string] = @[] ## Exposes the list of requirements for read
+                                   ## and write accesses.
+
+proc requires*(deps: varargs[string]) =
+  ## Nimble support: Call this to set the list of requirements of your Nimble
+  ## package.
+  for d in deps: requiresData.add(d)
+
+{.pop.}
diff --git a/lib/system/platforms.nim b/lib/system/platforms.nim
index 47a01d5fe..eeada5c51 100644
--- a/lib/system/platforms.nim
+++ b/lib/system/platforms.nim
@@ -18,13 +18,17 @@ type
     alpha,                     ## Alpha processor
     powerpc,                   ## 32 bit PowerPC
     powerpc64,                 ## 64 bit PowerPC
+    powerpc64el,               ## Little Endian 64 bit PowerPC
     sparc,                     ## Sparc based processor
     ia64,                      ## Intel Itanium
     amd64,                     ## x86_64 (AMD64); 64 bit x86 compatible CPU
     mips,                      ## Mips based processor
+    mipsel,                    ## Little Endian Mips based processor
     arm,                       ## ARM based processor
+    arm64,                     ## ARM64 based processor
     vm,                        ## Some Virtual machine: Nim's VM or JavaScript
     avr                        ## AVR based processor
+    msp430                     ## TI MSP430 microcontroller
 
   OsPlatform* {.pure.} = enum ## the OS this program will run on.
     none, dos, windows, os2, linux, morphos, skyos, solaris,
@@ -63,12 +67,16 @@ const
                elif defined(alpha): CpuPlatform.alpha
                elif defined(powerpc): CpuPlatform.powerpc
                elif defined(powerpc64): CpuPlatform.powerpc64
+               elif defined(powerpc64el): CpuPlatform.powerpc64el
                elif defined(sparc): CpuPlatform.sparc
                elif defined(ia64): CpuPlatform.ia64
                elif defined(amd64): CpuPlatform.amd64
                elif defined(mips): CpuPlatform.mips
+               elif defined(mipsel): CpuPlatform.mipsel
                elif defined(arm): CpuPlatform.arm
+               elif defined(arm64): CpuPlatform.arm64
                elif defined(vm): CpuPlatform.vm
                elif defined(avr): CpuPlatform.avr
+               elif defined(msp430): CpuPlatform.msp430
                else: CpuPlatform.none
     ## the CPU this program will run on.
diff --git a/lib/system/profiler.nim b/lib/system/profiler.nim
index 6d6863caa..4f600417e 100644
--- a/lib/system/profiler.nim
+++ b/lib/system/profiler.nim
@@ -19,10 +19,11 @@ const
   MaxTraceLen = 20 # tracking the last 20 calls is enough
 
 type
-  TStackTrace* = array [0..MaxTraceLen-1, cstring]
-  TProfilerHook* = proc (st: TStackTrace) {.nimcall.}
+  StackTrace* = array [0..MaxTraceLen-1, cstring]
+  ProfilerHook* = proc (st: StackTrace) {.nimcall.}
+{.deprecated: [TStackTrace: StackTrace, TProfilerHook: ProfilerHook].}
 
-proc captureStackTrace(f: PFrame, st: var TStackTrace) =
+proc captureStackTrace(f: PFrame, st: var StackTrace) =
   const
     firstCalls = 5
   var
@@ -39,7 +40,7 @@ proc captureStackTrace(f: PFrame, st: var TStackTrace) =
   while it != nil:
     inc(total)
     it = it.prev
-  for j in 1..total-i-(firstCalls-1): 
+  for j in 1..total-i-(firstCalls-1):
     if b != nil: b = b.prev
   if total != i:
     st[i] = "..."
@@ -51,14 +52,15 @@ proc captureStackTrace(f: PFrame, st: var TStackTrace) =
 
 when defined(memProfiler):
   type
-    TMemProfilerHook* = proc (st: TStackTrace, requestedSize: int) {.nimcall, benign.}
+    MemProfilerHook* = proc (st: StackTrace, requestedSize: int) {.nimcall, benign.}
+  {.deprecated: [TMemProfilerHook: MemProfilerHook].}
   var
-    profilerHook*: TMemProfilerHook
+    profilerHook*: MemProfilerHook
       ## set this variable to provide a procedure that implements a profiler in
       ## user space. See the `nimprof` module for a reference implementation.
 
-  proc callProfilerHook(hook: TMemProfilerHook, requestedSize: int) =
-    var st: TStackTrace
+  proc callProfilerHook(hook: MemProfilerHook, requestedSize: int) =
+    var st: StackTrace
     captureStackTrace(framePtr, st)
     hook(st, requestedSize)
 
@@ -70,15 +72,15 @@ else:
     SamplingInterval = 50_000
       # set this to change the default sampling interval
   var
-    profilerHook*: TProfilerHook
+    profilerHook*: ProfilerHook
       ## set this variable to provide a procedure that implements a profiler in
       ## user space. See the `nimprof` module for a reference implementation.
     gTicker {.threadvar.}: int
 
-  proc callProfilerHook(hook: TProfilerHook) {.noinline.} =
+  proc callProfilerHook(hook: ProfilerHook) {.noinline.} =
     # 'noinline' so that 'nimProfile' does not perform the stack allocation
     # in the common case.
-    var st: TStackTrace
+    var st: StackTrace
     captureStackTrace(framePtr, st)
     hook(st)
 
diff --git a/lib/system/repr.nim b/lib/system/repr.nim
index f1029ff6a..1f81a0813 100644
--- a/lib/system/repr.nim
+++ b/lib/system/repr.nim
@@ -21,9 +21,22 @@ proc reprPointer(x: pointer): string {.compilerproc.} =
   return $buf
 
 proc `$`(x: uint64): string =
-  var buf: array [0..59, char]
-  discard c_sprintf(buf, "%llu", x)
-  return $buf
+  if x == 0:
+    result = "0"
+  else:
+    var buf: array [60, char]
+    var i = 0
+    var n = x
+    while n != 0:
+      let nn = n div 10'u64
+      buf[i] = char(n - 10'u64 * nn + ord('0'))
+      inc i
+      n = nn
+
+    let half = i div 2
+    # Reverse
+    for t in 0 .. < half: swap(buf[t], buf[i-t-1])
+    result = $buf
 
 proc reprStrAux(result: var string, s: string) =
   if cast[pointer](s) == nil:
@@ -121,38 +134,39 @@ proc reprSet(p: pointer, typ: PNimType): string {.compilerRtl.} =
   reprSetAux(result, p, typ)
 
 type
-  TReprClosure {.final.} = object # we cannot use a global variable here
+  ReprClosure {.final.} = object # we cannot use a global variable here
                                   # as this wouldn't be thread-safe
-    when declared(TCellSet):
-      marked: TCellSet
+    when declared(CellSet):
+      marked: CellSet
     recdepth: int       # do not recurse endlessly
     indent: int         # indentation
+{.deprecated: [TReprClosure: ReprClosure].}
 
 when not defined(useNimRtl):
-  proc initReprClosure(cl: var TReprClosure) =
+  proc initReprClosure(cl: var ReprClosure) =
     # Important: cellsets does not lock the heap when doing allocations! We
     # have to do it here ...
     when hasThreadSupport and hasSharedHeap and declared(heapLock):
       AcquireSys(HeapLock)
-    when declared(TCellSet):
+    when declared(CellSet):
       init(cl.marked)
     cl.recdepth = -1      # default is to display everything!
     cl.indent = 0
 
-  proc deinitReprClosure(cl: var TReprClosure) =
-    when declared(TCellSet): deinit(cl.marked)
-    when hasThreadSupport and hasSharedHeap and declared(heapLock): 
+  proc deinitReprClosure(cl: var ReprClosure) =
+    when declared(CellSet): deinit(cl.marked)
+    when hasThreadSupport and hasSharedHeap and declared(heapLock):
       ReleaseSys(HeapLock)
 
-  proc reprBreak(result: var string, cl: TReprClosure) =
+  proc reprBreak(result: var string, cl: ReprClosure) =
     add result, "\n"
     for i in 0..cl.indent-1: add result, ' '
 
   proc reprAux(result: var string, p: pointer, typ: PNimType,
-               cl: var TReprClosure) {.benign.}
+               cl: var ReprClosure) {.benign.}
 
   proc reprArray(result: var string, p: pointer, typ: PNimType,
-                 cl: var TReprClosure) =
+                 cl: var ReprClosure) =
     add result, "["
     var bs = typ.base.size
     for i in 0..typ.size div bs - 1:
@@ -161,7 +175,7 @@ when not defined(useNimRtl):
     add result, "]"
 
   proc reprSequence(result: var string, p: pointer, typ: PNimType,
-                    cl: var TReprClosure) =
+                    cl: var ReprClosure) =
     if p == nil:
       add result, "nil"
       return
@@ -174,7 +188,7 @@ when not defined(useNimRtl):
     add result, "]"
 
   proc reprRecordAux(result: var string, p: pointer, n: ptr TNimNode,
-                     cl: var TReprClosure) {.benign.} =
+                     cl: var ReprClosure) {.benign.} =
     case n.kind
     of nkNone: sysAssert(false, "reprRecordAux")
     of nkSlot:
@@ -191,20 +205,26 @@ when not defined(useNimRtl):
       if m != nil: reprRecordAux(result, p, m, cl)
 
   proc reprRecord(result: var string, p: pointer, typ: PNimType,
-                  cl: var TReprClosure) =
+                  cl: var ReprClosure) =
     add result, "["
-    let oldLen = result.len
-    reprRecordAux(result, p, typ.node, cl)
-    if typ.base != nil: 
-      if oldLen != result.len: add result, ",\n"
-      reprRecordAux(result, p, typ.base.node, cl)
+    var curTyp = typ
+    var first = true
+    while curTyp != nil:
+      var part = ""
+      reprRecordAux(part, p, curTyp.node, cl)
+      if part.len > 0:
+        if not first:
+          add result, ",\n"
+        add result, part
+        first = false
+      curTyp = curTyp.base
     add result, "]"
 
   proc reprRef(result: var string, p: pointer, typ: PNimType,
-               cl: var TReprClosure) =
+               cl: var ReprClosure) =
     # we know that p is not nil here:
-    when declared(TCellSet):
-      when defined(boehmGC) or defined(nogc):
+    when declared(CellSet):
+      when defined(boehmGC) or defined(gogc) or defined(nogc):
         var cell = cast[PCell](p)
       else:
         var cell = usrToCell(p)
@@ -216,7 +236,7 @@ when not defined(useNimRtl):
         reprAux(result, p, typ.base, cl)
 
   proc reprAux(result: var string, p: pointer, typ: PNimType,
-               cl: var TReprClosure) =
+               cl: var ReprClosure) =
     if cl.recdepth == 0:
       add result, "..."
       return
@@ -225,7 +245,7 @@ when not defined(useNimRtl):
     of tySet: reprSetAux(result, p, typ)
     of tyArray, tyArrayConstr: reprArray(result, p, typ, cl)
     of tyTuple: reprRecord(result, p, typ, cl)
-    of tyObject: 
+    of tyObject:
       var t = cast[ptr PNimType](p)[]
       reprRecord(result, p, t, cl)
     of tyRef, tyPtr:
@@ -241,7 +261,7 @@ when not defined(useNimRtl):
     of tyInt64: add result, $(cast[ptr int64](p)[])
     of tyUInt8: add result, $ze(cast[ptr int8](p)[])
     of tyUInt16: add result, $ze(cast[ptr int16](p)[])
-    
+
     of tyFloat: add result, $(cast[ptr float](p)[])
     of tyFloat32: add result, $(cast[ptr float32](p)[])
     of tyFloat64: add result, $(cast[ptr float64](p)[])
@@ -249,7 +269,10 @@ when not defined(useNimRtl):
     of tyBool: add result, reprBool(cast[ptr bool](p)[])
     of tyChar: add result, reprChar(cast[ptr char](p)[])
     of tyString: reprStrAux(result, cast[ptr string](p)[])
-    of tyCString: reprStrAux(result, $(cast[ptr cstring](p)[]))
+    of tyCString:
+      let cs = cast[ptr cstring](p)[]
+      if cs.isNil: add result, "nil"
+      else: reprStrAux(result, $cs)
     of tyRange: reprAux(result, p, typ.base, cl)
     of tyProc, tyPointer:
       if cast[PPointer](p)[] == nil: add result, "nil"
@@ -261,7 +284,7 @@ when not defined(useNimRtl):
 proc reprOpenArray(p: pointer, length: int, elemtyp: PNimType): string {.
                    compilerRtl.} =
   var
-    cl: TReprClosure
+    cl: ReprClosure
   initReprClosure(cl)
   result = "["
   var bs = elemtyp.size
@@ -274,7 +297,7 @@ proc reprOpenArray(p: pointer, length: int, elemtyp: PNimType): string {.
 when not defined(useNimRtl):
   proc reprAny(p: pointer, typ: PNimType): string =
     var
-      cl: TReprClosure
+      cl: ReprClosure
     initReprClosure(cl)
     result = ""
     if typ.kind in {tyObject, tyTuple, tyArray, tyArrayConstr, tySet}:
@@ -284,4 +307,3 @@ when not defined(useNimRtl):
       reprAux(result, addr(p), typ, cl)
     add result, "\n"
     deinitReprClosure(cl)
-
diff --git a/lib/system/sets.nim b/lib/system/sets.nim
index 7826fd4b7..66877de30 100644
--- a/lib/system/sets.nim
+++ b/lib/system/sets.nim
@@ -10,7 +10,8 @@
 # set handling
 
 type
-  TNimSet = array [0..4*2048-1, uint8]
+  NimSet = array [0..4*2048-1, uint8]
+{.deprecated: [TNimSet: NimSet].}
 
 proc countBits32(n: int32): int {.compilerproc.} =
   var v = n
@@ -19,10 +20,10 @@ proc countBits32(n: int32): int {.compilerproc.} =
   result = ((v +% (v shr 4'i32) and 0xF0F0F0F'i32) *% 0x1010101'i32) shr 24'i32
 
 proc countBits64(n: int64): int {.compilerproc.} =
-  result = countBits32(toU32(n and 0xffff'i64)) +
-           countBits32(toU32(n shr 16'i64))
+  result = countBits32(toU32(n and 0xffffffff'i64)) +
+           countBits32(toU32(n shr 32'i64))
 
-proc cardSet(s: TNimSet, len: int): int {.compilerproc.} =
+proc cardSet(s: NimSet, len: int): int {.compilerproc.} =
   result = 0
   for i in countup(0, len-1):
     inc(result, countBits32(int32(s[i])))
diff --git a/lib/system/sysio.nim b/lib/system/sysio.nim
index 468af1713..3d0b2aa8a 100644
--- a/lib/system/sysio.nim
+++ b/lib/system/sysio.nim
@@ -16,7 +16,7 @@
                        # of the standard library!
 
 
-proc fputs(c: cstring, f: File) {.importc: "fputs", header: "<stdio.h>", 
+proc fputs(c: cstring, f: File) {.importc: "fputs", header: "<stdio.h>",
   tags: [WriteIOEffect].}
 proc fgets(c: cstring, n: int, f: File): cstring {.
   importc: "fgets", header: "<stdio.h>", tags: [ReadIOEffect].}
@@ -26,20 +26,24 @@ proc ungetc(c: cint, f: File) {.importc: "ungetc", header: "<stdio.h>",
   tags: [].}
 proc putc(c: char, stream: File) {.importc: "putc", header: "<stdio.h>",
   tags: [WriteIOEffect].}
-proc fprintf(f: File, frmt: cstring) {.importc: "fprintf", 
+proc fprintf(f: File, frmt: cstring) {.importc: "fprintf",
   header: "<stdio.h>", varargs, tags: [WriteIOEffect].}
 proc strlen(c: cstring): int {.
   importc: "strlen", header: "<string.h>", tags: [].}
 
-
 # C routine that is used here:
 proc fread(buf: pointer, size, n: int, f: File): int {.
   importc: "fread", header: "<stdio.h>", tags: [ReadIOEffect].}
 proc fseek(f: File, offset: clong, whence: int): int {.
   importc: "fseek", header: "<stdio.h>", tags: [].}
 proc ftell(f: File): int {.importc: "ftell", header: "<stdio.h>", tags: [].}
+proc ferror(f: File): int {.importc: "ferror", header: "<stdio.h>", tags: [].}
 proc setvbuf(stream: File, buf: pointer, typ, size: cint): cint {.
   importc, header: "<stdio.h>", tags: [].}
+proc memchr(s: pointer, c: cint, n: csize): pointer {.
+  importc: "memchr", header: "<string.h>", tags: [].}
+proc memset(s: pointer, c: cint, n: csize) {.
+  header: "<string.h>", importc: "memset", tags: [].}
 
 {.push stackTrace:off, profiler:off.}
 proc write(f: File, c: cstring) = fputs(c, f)
@@ -68,38 +72,60 @@ proc raiseEIO(msg: string) {.noinline, noreturn.} =
   sysFatal(IOError, msg)
 
 proc readLine(f: File, line: var TaintedString): bool =
-  # of course this could be optimized a bit; but IO is slow anyway...
-  # and it was difficult to get this CORRECT with Ansi C's methods
-  setLen(line.string, 0) # reuse the buffer!
+  var pos = 0
+  # Use the currently reserved space for a first try
+  when defined(nimscript):
+    var space = 80
+  else:
+    var space = cast[PGenericSeq](line.string).space
+  line.string.setLen(space)
+
   while true:
-    var c = fgetc(f)
-    if c < 0'i32:
-      if line.len > 0: break
-      else: return false
-    if c == 10'i32: break # LF
-    if c == 13'i32:  # CR
-      c = fgetc(f) # is the next char LF?
-      if c != 10'i32: ungetc(c, f) # no, put the character back
-      break
-    add line.string, chr(int(c))
-  result = true
+    # memset to \l so that we can tell how far fgets wrote, even on EOF, where
+    # fgets doesn't append an \l
+    memset(addr line.string[pos], '\l'.ord, space)
+    if fgets(addr line.string[pos], space, f) == nil:
+      line.string.setLen(0)
+      return false
+    let m = memchr(addr line.string[pos], '\l'.ord, space)
+    if m != nil:
+      # \l found: Could be our own or the one by fgets, in any case, we're done
+      var last = cast[ByteAddress](m) - cast[ByteAddress](addr line.string[0])
+      if last > 0 and line.string[last-1] == '\c':
+        line.string.setLen(last-1)
+        return true
+        # We have to distinguish between two possible cases:
+        # \0\l\0 => line ending in a null character.
+        # \0\l\l => last line without newline, null was put there by fgets.
+      elif last > 0 and line.string[last-1] == '\0':
+        if last < pos + space - 1 and line.string[last+1] != '\0':
+          dec last
+      line.string.setLen(last)
+      return true
+    else:
+      # fgets will have inserted a null byte at the end of the string.
+      dec space
+    # No \l found: Increase buffer and read more
+    inc pos, space
+    space = 128 # read in 128 bytes at a time
+    line.string.setLen(pos+space)
 
 proc readLine(f: File): TaintedString =
   result = TaintedString(newStringOfCap(80))
   if not readLine(f, result): raiseEIO("EOF reached")
 
-proc write(f: File, i: int) = 
+proc write(f: File, i: int) =
   when sizeof(int) == 8:
     fprintf(f, "%lld", i)
   else:
     fprintf(f, "%ld", i)
 
-proc write(f: File, i: BiggestInt) = 
+proc write(f: File, i: BiggestInt) =
   when sizeof(BiggestInt) == 8:
     fprintf(f, "%lld", i)
   else:
     fprintf(f, "%ld", i)
-    
+
 proc write(f: File, b: bool) =
   if b: write(f, "true")
   else: write(f, "false")
@@ -110,7 +136,7 @@ proc write(f: File, c: char) = putc(c, f)
 proc write(f: File, a: varargs[string, `$`]) =
   for x in items(a): write(f, x)
 
-proc readAllBuffer(file: File): string = 
+proc readAllBuffer(file: File): string =
   # This proc is for File we want to read but don't know how many
   # bytes we need to read before the buffer is empty.
   result = ""
@@ -123,8 +149,8 @@ proc readAllBuffer(file: File): string =
       buffer.setLen(bytesRead)
       result.add(buffer)
       break
-  
-proc rawFileSize(file: File): int = 
+
+proc rawFileSize(file: File): int =
   # this does not raise an error opposed to `getFileSize`
   var oldPos = ftell(file)
   discard fseek(file, 0, 2) # seek the end of the file
@@ -134,23 +160,34 @@ proc rawFileSize(file: File): int =
 proc readAllFile(file: File, len: int): string =
   # We acquire the filesize beforehand and hope it doesn't change.
   # Speeds things up.
-  result = newString(int(len))
-  if readBuffer(file, addr(result[0]), int(len)) != len:
+  result = newString(len)
+  let bytes = readBuffer(file, addr(result[0]), len)
+  if endOfFile(file):
+    if bytes < len:
+      result.setLen(bytes)
+  elif ferror(file) != 0:
     raiseEIO("error while reading from file")
+  else:
+    # We read all the bytes but did not reach the EOF
+    # Try to read it as a buffer
+    result.add(readAllBuffer(file))
 
 proc readAllFile(file: File): string =
   var len = rawFileSize(file)
   result = readAllFile(file, len)
-  
-proc readAll(file: File): TaintedString = 
+
+proc readAll(file: File): TaintedString =
   # Separate handling needed because we need to buffer when we
   # don't know the overall length of the File.
-  let len = if file != stdin: rawFileSize(file) else: -1
+  when declared(stdin):
+    let len = if file != stdin: rawFileSize(file) else: -1
+  else:
+    let len = rawFileSize(file)
   if len > 0:
     result = readAllFile(file, len).TaintedString
   else:
     result = readAllBuffer(file).TaintedString
-  
+
 proc readFile(filename: string): TaintedString =
   var f = open(filename)
   try:
@@ -171,12 +208,19 @@ proc endOfFile(f: File): bool =
   ungetc(c, f)
   return c < 0'i32
 
-proc writeln[Ty](f: File, x: varargs[Ty, `$`]) =
-  for i in items(x): write(f, i)
+proc writeLn[Ty](f: File, x: varargs[Ty, `$`]) =
+  for i in items(x):
+    write(f, i)
+  write(f, "\n")
+
+proc writeLine[Ty](f: File, x: varargs[Ty, `$`]) =
+  for i in items(x):
+    write(f, i)
   write(f, "\n")
 
-proc rawEcho(x: string) {.inline, compilerproc.} = write(stdout, x)
-proc rawEchoNL() {.inline, compilerproc.} = write(stdout, "\n")
+when declared(stdout):
+  proc rawEcho(x: string) {.inline, compilerproc.} = write(stdout, x)
+  proc rawEchoNL() {.inline, compilerproc.} = write(stdout, "\n")
 
 # interface to the C procs:
 
@@ -229,7 +273,7 @@ proc open(f: var File, filename: string,
     elif bufSize == 0:
       discard setvbuf(f, nil, IONBF, 0)
 
-proc reopen(f: File, filename: string, mode: FileMode = fmRead): bool = 
+proc reopen(f: File, filename: string, mode: FileMode = fmRead): bool =
   var p: pointer = freopen(filename, FormatOpen[mode], f)
   result = p != nil
 
@@ -243,23 +287,23 @@ proc open(f: var File, filehandle: FileHandle, mode: FileMode): bool =
 proc fwrite(buf: pointer, size, n: int, f: File): int {.
   importc: "fwrite", noDecl.}
 
-proc readBuffer(f: File, buffer: pointer, len: int): int =
+proc readBuffer(f: File, buffer: pointer, len: Natural): int =
   result = fread(buffer, 1, len, f)
 
-proc readBytes(f: File, a: var openArray[int8|uint8], start, len: int): int =
+proc readBytes(f: File, a: var openArray[int8|uint8], start, len: Natural): int =
   result = readBuffer(f, addr(a[start]), len)
 
-proc readChars(f: File, a: var openArray[char], start, len: int): int =
+proc readChars(f: File, a: var openArray[char], start, len: Natural): int =
   result = readBuffer(f, addr(a[start]), len)
 
 {.push stackTrace:off, profiler:off.}
-proc writeBytes(f: File, a: openArray[int8|uint8], start, len: int): int =
+proc writeBytes(f: File, a: openArray[int8|uint8], start, len: Natural): int =
   var x = cast[ptr array[0..1000_000_000, int8]](a)
   result = writeBuffer(f, addr(x[start]), len)
-proc writeChars(f: File, a: openArray[char], start, len: int): int =
+proc writeChars(f: File, a: openArray[char], start, len: Natural): int =
   var x = cast[ptr array[0..1000_000_000, int8]](a)
   result = writeBuffer(f, addr(x[start]), len)
-proc writeBuffer(f: File, buffer: pointer, len: int): int =
+proc writeBuffer(f: File, buffer: pointer, len: Natural): int =
   result = fwrite(buffer, 1, len, f)
 
 proc write(f: File, s: string) =
diff --git a/lib/system/syslocks.nim b/lib/system/syslocks.nim
index 8b38f34f3..7a113b9d4 100644
--- a/lib/system/syslocks.nim
+++ b/lib/system/syslocks.nim
@@ -11,8 +11,8 @@
 
 when defined(Windows):
   type
-    THandle = int
-    TSysLock {.final, pure.} = object # CRITICAL_SECTION in WinApi
+    Handle = int
+    SysLock {.final, pure.} = object # CRITICAL_SECTION in WinApi
       DebugInfo: pointer
       LockCount: int32
       RecursionCount: int32
@@ -20,85 +20,87 @@ when defined(Windows):
       LockSemaphore: int
       Reserved: int32
 
-    TSysCond = THandle
-          
-  proc initSysLock(L: var TSysLock) {.stdcall, noSideEffect,
+    SysCond = Handle
+
+  {.deprecated: [THandle: Handle, TSysLock: SysLock, TSysCond: SysCond].}
+
+  proc initSysLock(L: var SysLock) {.stdcall, noSideEffect,
     dynlib: "kernel32", importc: "InitializeCriticalSection".}
     ## Initializes the lock `L`.
 
-  proc tryAcquireSysAux(L: var TSysLock): int32 {.stdcall, noSideEffect,
+  proc tryAcquireSysAux(L: var SysLock): int32 {.stdcall, noSideEffect,
     dynlib: "kernel32", importc: "TryEnterCriticalSection".}
     ## Tries to acquire the lock `L`.
-    
-  proc tryAcquireSys(L: var TSysLock): bool {.inline.} = 
+
+  proc tryAcquireSys(L: var SysLock): bool {.inline.} =
     result = tryAcquireSysAux(L) != 0'i32
 
-  proc acquireSys(L: var TSysLock) {.stdcall, noSideEffect,
+  proc acquireSys(L: var SysLock) {.stdcall, noSideEffect,
     dynlib: "kernel32", importc: "EnterCriticalSection".}
     ## Acquires the lock `L`.
-    
-  proc releaseSys(L: var TSysLock) {.stdcall, noSideEffect,
+
+  proc releaseSys(L: var SysLock) {.stdcall, noSideEffect,
     dynlib: "kernel32", importc: "LeaveCriticalSection".}
     ## Releases the lock `L`.
 
-  proc deinitSys(L: var TSysLock) {.stdcall, noSideEffect,
+  proc deinitSys(L: var SysLock) {.stdcall, noSideEffect,
     dynlib: "kernel32", importc: "DeleteCriticalSection".}
 
-  proc createEvent(lpEventAttributes: pointer, 
+  proc createEvent(lpEventAttributes: pointer,
                    bManualReset, bInitialState: int32,
-                   lpName: cstring): TSysCond {.stdcall, noSideEffect,
+                   lpName: cstring): SysCond {.stdcall, noSideEffect,
     dynlib: "kernel32", importc: "CreateEventA".}
-  
-  proc closeHandle(hObject: THandle) {.stdcall, noSideEffect,
+
+  proc closeHandle(hObject: Handle) {.stdcall, noSideEffect,
     dynlib: "kernel32", importc: "CloseHandle".}
-  proc waitForSingleObject(hHandle: THandle, dwMilliseconds: int32): int32 {.
+  proc waitForSingleObject(hHandle: Handle, dwMilliseconds: int32): int32 {.
     stdcall, dynlib: "kernel32", importc: "WaitForSingleObject", noSideEffect.}
 
-  proc signalSysCond(hEvent: TSysCond) {.stdcall, noSideEffect,
+  proc signalSysCond(hEvent: SysCond) {.stdcall, noSideEffect,
     dynlib: "kernel32", importc: "SetEvent".}
-  
-  proc initSysCond(cond: var TSysCond) {.inline.} =
+
+  proc initSysCond(cond: var SysCond) {.inline.} =
     cond = createEvent(nil, 0'i32, 0'i32, nil)
-  proc deinitSysCond(cond: var TSysCond) {.inline.} =
+  proc deinitSysCond(cond: var SysCond) {.inline.} =
     closeHandle(cond)
-  proc waitSysCond(cond: var TSysCond, lock: var TSysLock) =
+  proc waitSysCond(cond: var SysCond, lock: var SysLock) =
     releaseSys(lock)
     discard waitForSingleObject(cond, -1'i32)
     acquireSys(lock)
 
-  proc waitSysCondWindows(cond: var TSysCond) =
+  proc waitSysCondWindows(cond: var SysCond) =
     discard waitForSingleObject(cond, -1'i32)
 
 else:
   type
-    TSysLock {.importc: "pthread_mutex_t", pure, final,
+    SysLock {.importc: "pthread_mutex_t", pure, final,
                header: "<sys/types.h>".} = object
-    TSysCond {.importc: "pthread_cond_t", pure, final,
+    SysCond {.importc: "pthread_cond_t", pure, final,
                header: "<sys/types.h>".} = object
 
-  proc initSysLock(L: var TSysLock, attr: pointer = nil) {.
+  proc initSysLock(L: var SysLock, attr: pointer = nil) {.
     importc: "pthread_mutex_init", header: "<pthread.h>", noSideEffect.}
 
-  proc acquireSys(L: var TSysLock) {.noSideEffect,
+  proc acquireSys(L: var SysLock) {.noSideEffect,
     importc: "pthread_mutex_lock", header: "<pthread.h>".}
-  proc tryAcquireSysAux(L: var TSysLock): cint {.noSideEffect,
+  proc tryAcquireSysAux(L: var SysLock): cint {.noSideEffect,
     importc: "pthread_mutex_trylock", header: "<pthread.h>".}
 
-  proc tryAcquireSys(L: var TSysLock): bool {.inline.} = 
+  proc tryAcquireSys(L: var SysLock): bool {.inline.} =
     result = tryAcquireSysAux(L) == 0'i32
 
-  proc releaseSys(L: var TSysLock) {.noSideEffect,
+  proc releaseSys(L: var SysLock) {.noSideEffect,
     importc: "pthread_mutex_unlock", header: "<pthread.h>".}
-  proc deinitSys(L: var TSysLock) {.noSideEffect,
+  proc deinitSys(L: var SysLock) {.noSideEffect,
     importc: "pthread_mutex_destroy", header: "<pthread.h>".}
 
-  proc initSysCond(cond: var TSysCond, cond_attr: pointer = nil) {.
+  proc initSysCond(cond: var SysCond, cond_attr: pointer = nil) {.
     importc: "pthread_cond_init", header: "<pthread.h>", noSideEffect.}
-  proc waitSysCond(cond: var TSysCond, lock: var TSysLock) {.
+  proc waitSysCond(cond: var SysCond, lock: var SysLock) {.
     importc: "pthread_cond_wait", header: "<pthread.h>", noSideEffect.}
-  proc signalSysCond(cond: var TSysCond) {.
+  proc signalSysCond(cond: var SysCond) {.
     importc: "pthread_cond_signal", header: "<pthread.h>", noSideEffect.}
-  
-  proc deinitSysCond(cond: var TSysCond) {.noSideEffect,
+
+  proc deinitSysCond(cond: var SysCond) {.noSideEffect,
     importc: "pthread_cond_destroy", header: "<pthread.h>".}
-  
+
diff --git a/lib/system/sysspawn.nim b/lib/system/sysspawn.nim
index 6f45f1509..7aef86df9 100644
--- a/lib/system/sysspawn.nim
+++ b/lib/system/sysspawn.nim
@@ -9,7 +9,7 @@
 
 ## Implements Nim's 'spawn'.
 
-when not declared(NimString): 
+when not declared(NimString):
   {.error: "You must not import this module explicitly".}
 
 {.push stackTrace:off.}
@@ -19,9 +19,9 @@ when not declared(NimString):
 
 type
   CondVar = object
-    c: TSysCond
+    c: SysCond
     when defined(posix):
-      stupidLock: TSysLock
+      stupidLock: SysLock
       counter: int
 
 proc createCondVar(): CondVar =
diff --git a/lib/system/sysstr.nim b/lib/system/sysstr.nim
index 5b4020c8c..326c601bd 100644
--- a/lib/system/sysstr.nim
+++ b/lib/system/sysstr.nim
@@ -50,12 +50,16 @@ proc rawNewStringNoInit(space: int): NimString {.compilerProc.} =
   if s < 7: s = 7
   result = allocStrNoInit(sizeof(TGenericSeq) + s + 1)
   result.reserved = s
+  when defined(gogc):
+    result.elemSize = 1
 
 proc rawNewString(space: int): NimString {.compilerProc.} =
   var s = space
   if s < 7: s = 7
   result = allocStr(sizeof(TGenericSeq) + s + 1)
   result.reserved = s
+  when defined(gogc):
+    result.elemSize = 1
 
 proc mnewString(len: int): NimString {.compilerProc.} =
   result = rawNewString(len)
@@ -206,6 +210,14 @@ proc incrSeq(seq: PGenericSeq, elemSize: int): PGenericSeq {.compilerProc.} =
                                GenericSeqSize))
   inc(result.len)
 
+proc incrSeqV2(seq: PGenericSeq, elemSize: int): PGenericSeq {.compilerProc.} =
+  # incrSeq version 2
+  result = seq
+  if result.len >= result.space:
+    result.reserved = resize(result.space)
+    result = cast[PGenericSeq](growObj(result, elemSize * result.reserved +
+                               GenericSeqSize))
+
 proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
     compilerRtl.} =
   result = seq
@@ -216,7 +228,7 @@ proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
   elif newLen < result.len:
     # we need to decref here, otherwise the GC leaks!
     when not defined(boehmGC) and not defined(nogc) and
-         not defined(gcMarkAndSweep):
+         not defined(gcMarkAndSweep) and not defined(gogc):
       when compileOption("gc", "v2"):
         for i in newLen..result.len-1:
           let len0 = gch.tempStack.len
diff --git a/lib/system/threads.nim b/lib/system/threads.nim
index d8e011ecb..c5de841f8 100644
--- a/lib/system/threads.nim
+++ b/lib/system/threads.nim
@@ -11,7 +11,7 @@
 ## Do not import it directly. To activate thread support you need to compile
 ## with the ``--threads:on`` command line switch.
 ##
-## Nim's memory model for threads is quite different from other common 
+## Nim's memory model for threads is quite different from other common
 ## programming languages (C, Pascal): Each thread has its own
 ## (garbage collected) heap and sharing of memory is restricted. This helps
 ## to prevent race conditions and improves efficiency. See `the manual for
@@ -24,9 +24,9 @@
 ##  import locks
 ##
 ##  var
-##    thr: array [0..4, TThread[tuple[a,b: int]]]
-##    L: TLock
-##  
+##    thr: array [0..4, Thread[tuple[a,b: int]]]
+##    L: Lock
+##
 ##  proc threadFunc(interval: tuple[a,b: int]) {.thread.} =
 ##    for i in interval.a..interval.b:
 ##      acquire(L) # lock stdout
@@ -38,8 +38,8 @@
 ##  for i in 0..high(thr):
 ##    createThread(thr[i], threadFunc, (i*10, i*10+5))
 ##  joinThreads(thr)
-  
-when not declared(NimString): 
+
+when not declared(NimString):
   {.error: "You must not import this module explicitly".}
 
 const
@@ -51,40 +51,41 @@ const
 
 when defined(windows):
   type
-    TSysThread = THandle
-    TWinThreadProc = proc (x: pointer): int32 {.stdcall.}
+    SysThread = Handle
+    WinThreadProc = proc (x: pointer): int32 {.stdcall.}
+  {.deprecated: [TSysThread: SysThread, TWinThreadProc: WinThreadProc].}
 
   proc createThread(lpThreadAttributes: pointer, dwStackSize: int32,
-                     lpStartAddress: TWinThreadProc, 
+                     lpStartAddress: WinThreadProc,
                      lpParameter: pointer,
-                     dwCreationFlags: int32, 
-                     lpThreadId: var int32): TSysThread {.
+                     dwCreationFlags: int32,
+                     lpThreadId: var int32): SysThread {.
     stdcall, dynlib: "kernel32", importc: "CreateThread".}
 
-  proc winSuspendThread(hThread: TSysThread): int32 {.
+  proc winSuspendThread(hThread: SysThread): int32 {.
     stdcall, dynlib: "kernel32", importc: "SuspendThread".}
-      
-  proc winResumeThread(hThread: TSysThread): int32 {.
+
+  proc winResumeThread(hThread: SysThread): int32 {.
     stdcall, dynlib: "kernel32", importc: "ResumeThread".}
 
   proc waitForMultipleObjects(nCount: int32,
-                              lpHandles: ptr TSysThread,
+                              lpHandles: ptr SysThread,
                               bWaitAll: int32,
                               dwMilliseconds: int32): int32 {.
     stdcall, dynlib: "kernel32", importc: "WaitForMultipleObjects".}
 
-  proc terminateThread(hThread: TSysThread, dwExitCode: int32): int32 {.
+  proc terminateThread(hThread: SysThread, dwExitCode: int32): int32 {.
     stdcall, dynlib: "kernel32", importc: "TerminateThread".}
-    
+
   type
-    TThreadVarSlot = distinct int32
+    ThreadVarSlot = distinct int32
 
   when true:
-    proc threadVarAlloc(): TThreadVarSlot {.
+    proc threadVarAlloc(): ThreadVarSlot {.
       importc: "TlsAlloc", stdcall, header: "<windows.h>".}
-    proc threadVarSetValue(dwTlsIndex: TThreadVarSlot, lpTlsValue: pointer) {.
+    proc threadVarSetValue(dwTlsIndex: ThreadVarSlot, lpTlsValue: pointer) {.
       importc: "TlsSetValue", stdcall, header: "<windows.h>".}
-    proc tlsGetValue(dwTlsIndex: TThreadVarSlot): pointer {.
+    proc tlsGetValue(dwTlsIndex: ThreadVarSlot): pointer {.
       importc: "TlsGetValue", stdcall, header: "<windows.h>".}
 
     proc getLastError(): uint32 {.
@@ -92,76 +93,93 @@ when defined(windows):
     proc setLastError(x: uint32) {.
       importc: "SetLastError", stdcall, header: "<windows.h>".}
 
-    proc threadVarGetValue(dwTlsIndex: TThreadVarSlot): pointer =
+    proc threadVarGetValue(dwTlsIndex: ThreadVarSlot): pointer =
       let realLastError = getLastError()
       result = tlsGetValue(dwTlsIndex)
       setLastError(realLastError)
   else:
-    proc threadVarAlloc(): TThreadVarSlot {.
+    proc threadVarAlloc(): ThreadVarSlot {.
       importc: "TlsAlloc", stdcall, dynlib: "kernel32".}
-    proc threadVarSetValue(dwTlsIndex: TThreadVarSlot, lpTlsValue: pointer) {.
+    proc threadVarSetValue(dwTlsIndex: ThreadVarSlot, lpTlsValue: pointer) {.
       importc: "TlsSetValue", stdcall, dynlib: "kernel32".}
-    proc threadVarGetValue(dwTlsIndex: TThreadVarSlot): pointer {.
+    proc threadVarGetValue(dwTlsIndex: ThreadVarSlot): pointer {.
       importc: "TlsGetValue", stdcall, dynlib: "kernel32".}
-  
+
+  proc setThreadAffinityMask(hThread: SysThread, dwThreadAffinityMask: uint) {.
+    importc: "SetThreadAffinityMask", stdcall, header: "<windows.h>".}
+
 else:
   when not defined(macosx):
     {.passL: "-pthread".}
 
   {.passC: "-pthread".}
+  const
+    schedh = "#define _GNU_SOURCE\n#include <sched.h>"
+    pthreadh = "#define _GNU_SOURCE\n#include <pthread.h>"
 
   type
-    TSysThread {.importc: "pthread_t", header: "<sys/types.h>",
+    SysThread {.importc: "pthread_t", header: "<sys/types.h>",
                  final, pure.} = object
-    Tpthread_attr {.importc: "pthread_attr_t",
+    Pthread_attr {.importc: "pthread_attr_t",
                      header: "<sys/types.h>", final, pure.} = object
-                 
-    Ttimespec {.importc: "struct timespec",
+
+    Timespec {.importc: "struct timespec",
                 header: "<time.h>", final, pure.} = object
       tv_sec: int
       tv_nsec: int
+  {.deprecated: [TSysThread: SysThread, Tpthread_attr: PThreadAttr,
+                Ttimespec: Timespec].}
 
-  proc pthread_attr_init(a1: var TPthread_attr) {.
-    importc, header: "<pthread.h>".}
-  proc pthread_attr_setstacksize(a1: var TPthread_attr, a2: int) {.
-    importc, header: "<pthread.h>".}
+  proc pthread_attr_init(a1: var PthreadAttr) {.
+    importc, header: pthreadh.}
+  proc pthread_attr_setstacksize(a1: var PthreadAttr, a2: int) {.
+    importc, header: pthreadh.}
 
-  proc pthread_create(a1: var TSysThread, a2: var TPthread_attr,
-            a3: proc (x: pointer): pointer {.noconv.}, 
-            a4: pointer): cint {.importc: "pthread_create", 
-            header: "<pthread.h>".}
-  proc pthread_join(a1: TSysThread, a2: ptr pointer): cint {.
-    importc, header: "<pthread.h>".}
+  proc pthread_create(a1: var SysThread, a2: var PthreadAttr,
+            a3: proc (x: pointer): pointer {.noconv.},
+            a4: pointer): cint {.importc: "pthread_create",
+            header: pthreadh.}
+  proc pthread_join(a1: SysThread, a2: ptr pointer): cint {.
+    importc, header: pthreadh.}
 
-  proc pthread_cancel(a1: TSysThread): cint {.
-    importc: "pthread_cancel", header: "<pthread.h>".}
+  proc pthread_cancel(a1: SysThread): cint {.
+    importc: "pthread_cancel", header: pthreadh.}
 
   type
-    TThreadVarSlot {.importc: "pthread_key_t", pure, final,
+    ThreadVarSlot {.importc: "pthread_key_t", pure, final,
                    header: "<sys/types.h>".} = object
+  {.deprecated: [TThreadVarSlot: ThreadVarSlot].}
 
-  proc pthread_getspecific(a1: TThreadVarSlot): pointer {.
-    importc: "pthread_getspecific", header: "<pthread.h>".}
-  proc pthread_key_create(a1: ptr TThreadVarSlot, 
+  proc pthread_getspecific(a1: ThreadVarSlot): pointer {.
+    importc: "pthread_getspecific", header: pthreadh.}
+  proc pthread_key_create(a1: ptr ThreadVarSlot,
                           destruct: proc (x: pointer) {.noconv.}): int32 {.
-    importc: "pthread_key_create", header: "<pthread.h>".}
-  proc pthread_key_delete(a1: TThreadVarSlot): int32 {.
-    importc: "pthread_key_delete", header: "<pthread.h>".}
-
-  proc pthread_setspecific(a1: TThreadVarSlot, a2: pointer): int32 {.
-    importc: "pthread_setspecific", header: "<pthread.h>".}
-  
-  proc threadVarAlloc(): TThreadVarSlot {.inline.} =
+    importc: "pthread_key_create", header: pthreadh.}
+  proc pthread_key_delete(a1: ThreadVarSlot): int32 {.
+    importc: "pthread_key_delete", header: pthreadh.}
+
+  proc pthread_setspecific(a1: ThreadVarSlot, a2: pointer): int32 {.
+    importc: "pthread_setspecific", header: pthreadh.}
+
+  proc threadVarAlloc(): ThreadVarSlot {.inline.} =
     discard pthread_key_create(addr(result), nil)
-  proc threadVarSetValue(s: TThreadVarSlot, value: pointer) {.inline.} =
+  proc threadVarSetValue(s: ThreadVarSlot, value: pointer) {.inline.} =
     discard pthread_setspecific(s, value)
-  proc threadVarGetValue(s: TThreadVarSlot): pointer {.inline.} =
+  proc threadVarGetValue(s: ThreadVarSlot): pointer {.inline.} =
     result = pthread_getspecific(s)
 
   when useStackMaskHack:
-    proc pthread_attr_setstack(attr: var TPthread_attr, stackaddr: pointer,
+    proc pthread_attr_setstack(attr: var PthreadAttr, stackaddr: pointer,
                                size: int): cint {.
-      importc: "pthread_attr_setstack", header: "<pthread.h>".}
+      importc: "pthread_attr_setstack", header: pthreadh.}
+
+  type CpuSet {.importc: "cpu_set_t", header: schedh.} = object
+  proc cpusetZero(s: var CpuSet) {.importc: "CPU_ZERO", header: schedh.}
+  proc cpusetIncl(cpu: cint; s: var CpuSet) {.
+    importc: "CPU_SET", header: schedh.}
+
+  proc setAffinity(thread: SysThread; setsize: csize; s: var CpuSet) {.
+    importc: "pthread_setaffinity_np", header: pthreadh.}
 
 const
   emulatedThreadVars = compileOption("tlsEmulation")
@@ -175,13 +193,13 @@ when emulatedThreadVars:
 # allocations are needed. Currently less than 7K are used on a 64bit machine.
 # We use ``float`` for proper alignment:
 type
-  TThreadLocalStorage = array [0..1_000, float]
+  ThreadLocalStorage = array [0..1_000, float]
 
-  PGcThread = ptr TGcThread
-  TGcThread {.pure, inheritable.} = object
-    sys: TSysThread
+  PGcThread = ptr GcThread
+  GcThread {.pure, inheritable.} = object
+    sys: SysThread
     when emulatedThreadVars and not useStackMaskHack:
-      tls: TThreadLocalStorage
+      tls: ThreadLocalStorage
     else:
       nil
     when hasSharedHeap:
@@ -190,34 +208,35 @@ type
       stackSize: int
     else:
       nil
-
-# XXX it'd be more efficient to not use a global variable for the 
-# thread storage slot, but to rely on the implementation to assign slot X
-# for us... ;-)
-var globalsSlot: TThreadVarSlot
+{.deprecated: [TThreadLocalStorage: ThreadLocalStorage, TGcThread: GcThread].}
 
 when not defined(useNimRtl):
   when not useStackMaskHack:
-    var mainThread: TGcThread
+    var mainThread: GcThread
 
-proc initThreadVarsEmulation() {.compilerProc, inline.} =
-  when not defined(useNimRtl):
-    globalsSlot = threadVarAlloc()
-    when declared(mainThread):
-      threadVarSetValue(globalsSlot, addr(mainThread))
-
-#const globalsSlot = TThreadVarSlot(0)
+#const globalsSlot = ThreadVarSlot(0)
 #sysAssert checkSlot.int == globalsSlot.int
 
 when emulatedThreadVars:
+  # XXX it'd be more efficient to not use a global variable for the
+  # thread storage slot, but to rely on the implementation to assign slot X
+  # for us... ;-)
+  var globalsSlot: ThreadVarSlot
+
   proc GetThreadLocalVars(): pointer {.compilerRtl, inl.} =
     result = addr(cast[PGcThread](threadVarGetValue(globalsSlot)).tls)
 
+  proc initThreadVarsEmulation() {.compilerProc, inline.} =
+    when not defined(useNimRtl):
+      globalsSlot = threadVarAlloc()
+      when declared(mainThread):
+        threadVarSetValue(globalsSlot, addr(mainThread))
+
 when useStackMaskHack:
   proc maskStackPointer(offset: int): pointer {.compilerRtl, inl.} =
     var x {.volatile.}: pointer
     x = addr(x)
-    result = cast[pointer]((cast[int](x) and not ThreadStackMask) +% 
+    result = cast[pointer]((cast[int](x) and not ThreadStackMask) +%
       (0) +% offset)
 
 # create for the main thread. Note: do not insert this data into the list
@@ -225,28 +244,28 @@ when useStackMaskHack:
 when not defined(useNimRtl):
   when not useStackMaskHack:
     #when not defined(createNimRtl): initStackBottom()
-    initGC()
-    
+    when declared(initGC): initGC()
+
   when emulatedThreadVars:
-    if nimThreadVarsSize() > sizeof(TThreadLocalStorage):
+    if nimThreadVarsSize() > sizeof(ThreadLocalStorage):
       echo "too large thread local storage size requested"
       quit 1
-  
-  when hasSharedHeap and not defined(boehmgc) and not defined(nogc):
+
+  when hasSharedHeap and not defined(boehmgc) and not defined(gogc) and not defined(nogc):
     var
       threadList: PGcThread
-      
-    proc registerThread(t: PGcThread) = 
+
+    proc registerThread(t: PGcThread) =
       # we need to use the GC global lock here!
       acquireSys(HeapLock)
       t.prev = nil
       t.next = threadList
-      if threadList != nil: 
+      if threadList != nil:
         sysAssert(threadList.prev == nil, "threadList.prev == nil")
         threadList.prev = t
       threadList = t
       releaseSys(HeapLock)
-    
+
     proc unregisterThread(t: PGcThread) =
       # we need to use the GC global lock here!
       acquireSys(HeapLock)
@@ -258,96 +277,128 @@ when not defined(useNimRtl):
       t.next = nil
       t.prev = nil
       releaseSys(HeapLock)
-      
+
     # on UNIX, the GC uses ``SIGFREEZE`` to tell every thread to stop so that
     # the GC can examine the stacks?
     proc stopTheWord() = discard
-    
+
 # We jump through some hops here to ensure that Nim thread procs can have
-# the Nim calling convention. This is needed because thread procs are 
+# the Nim calling convention. This is needed because thread procs are
 # ``stdcall`` on Windows and ``noconv`` on UNIX. Alternative would be to just
 # use ``stdcall`` since it is mapped to ``noconv`` on UNIX anyway.
 
 type
-  TThread* {.pure, final.}[TArg] =
-      object of TGcThread ## Nim thread. A thread is a heavy object (~14K)
+  Thread* {.pure, final.}[TArg] =
+      object of GcThread  ## Nim thread. A thread is a heavy object (~14K)
                           ## that **must not** be part of a message! Use
-                          ## a ``TThreadId`` for that.
+                          ## a ``ThreadId`` for that.
     when TArg is void:
       dataFn: proc () {.nimcall, gcsafe.}
     else:
       dataFn: proc (m: TArg) {.nimcall, gcsafe.}
       data: TArg
-  TThreadId*[TArg] = ptr TThread[TArg] ## the current implementation uses
+  ThreadId*[TArg] = ptr Thread[TArg]  ## the current implementation uses
                                        ## a pointer as a thread ID.
+{.deprecated: [TThread: Thread, TThreadId: ThreadId].}
 
-when not defined(boehmgc) and not hasSharedHeap:
+when not defined(boehmgc) and not hasSharedHeap and not defined(gogc):
   proc deallocOsPages()
 
+when defined(boehmgc):
+  type GCStackBaseProc = proc(sb: pointer, t: pointer) {.noconv.}
+  proc boehmGC_call_with_stack_base(sbp: GCStackBaseProc, p: pointer)
+    {.importc: "GC_call_with_stack_base", boehmGC.}
+  proc boehmGC_register_my_thread(sb: pointer)
+    {.importc: "GC_register_my_thread", boehmGC.}
+  proc boehmGC_unregister_my_thread()
+    {.importc: "GC_unregister_my_thread", boehmGC.}
+
+  proc threadProcWrapDispatch[TArg](sb: pointer, thrd: pointer) {.noconv.} =
+    boehmGC_register_my_thread(sb)
+    let thrd = cast[ptr Thread[TArg]](thrd)
+    when TArg is void:
+      thrd.dataFn()
+    else:
+      thrd.dataFn(thrd.data)
+    boehmGC_unregister_my_thread()
+else:
+  proc threadProcWrapDispatch[TArg](thrd: ptr Thread[TArg]) =
+    when TArg is void:
+      thrd.dataFn()
+    else:
+      thrd.dataFn(thrd.data)
+
+proc threadProcWrapStackFrame[TArg](thrd: ptr Thread[TArg]) =
+  when defined(boehmgc):
+    boehmGC_call_with_stack_base(threadProcWrapDispatch[TArg], thrd)
+  elif not defined(nogc) and not defined(gogc):
+    var p {.volatile.}: proc(a: ptr Thread[TArg]) {.nimcall.} =
+      threadProcWrapDispatch[TArg]
+    when not hasSharedHeap:
+      # init the GC for refc/markandsweep
+      setStackBottom(addr(p))
+      initGC()
+    when declared(registerThread):
+      thrd.stackBottom = addr(thrd)
+      registerThread(thrd)
+    p(thrd)
+    when declared(registerThread): unregisterThread(thrd)
+    when declared(deallocOsPages): deallocOsPages()
+  else:
+    threadProcWrapDispatch(thrd)
+
 template threadProcWrapperBody(closure: expr) {.immediate.} =
   when declared(globalsSlot): threadVarSetValue(globalsSlot, closure)
-  var t = cast[ptr TThread[TArg]](closure)
-  when useStackMaskHack:
-    var tls: TThreadLocalStorage
-  when not defined(boehmgc) and not defined(nogc) and not hasSharedHeap:
-    # init the GC for this thread:
-    setStackBottom(addr(t))
-    initGC()
-  when declared(registerThread):
-    t.stackBottom = addr(t)
-    registerThread(t)
-  when TArg is void: t.dataFn()
-  else: t.dataFn(t.data)
-  when declared(registerThread): unregisterThread(t)
-  when declared(deallocOsPages): deallocOsPages()
+  var thrd = cast[ptr Thread[TArg]](closure)
+  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
   # exception is tried to be re-raised by the code-gen after the ``finally``!
   # However this is doomed to fail, because we already unmapped every heap
   # page!
-  
+
   # mark as not running anymore:
-  t.dataFn = nil
-  
+  thrd.dataFn = nil
+
 {.push stack_trace:off.}
 when defined(windows):
-  proc threadProcWrapper[TArg](closure: pointer): int32 {.stdcall.} = 
+  proc threadProcWrapper[TArg](closure: pointer): int32 {.stdcall.} =
     threadProcWrapperBody(closure)
     # implicitly return 0
 else:
-  proc threadProcWrapper[TArg](closure: pointer): pointer {.noconv.} = 
+  proc threadProcWrapper[TArg](closure: pointer): pointer {.noconv.} =
     threadProcWrapperBody(closure)
 {.pop.}
 
-proc running*[TArg](t: TThread[TArg]): bool {.inline.} = 
+proc running*[TArg](t: Thread[TArg]): bool {.inline.} =
   ## returns true if `t` is running.
   result = t.dataFn != nil
 
 when hostOS == "windows":
-  proc joinThread*[TArg](t: TThread[TArg]) {.inline.} = 
+  proc joinThread*[TArg](t: Thread[TArg]) {.inline.} =
     ## waits for the thread `t` to finish.
     discard waitForSingleObject(t.sys, -1'i32)
 
-  proc joinThreads*[TArg](t: varargs[TThread[TArg]]) = 
+  proc joinThreads*[TArg](t: varargs[Thread[TArg]]) =
     ## waits for every thread in `t` to finish.
-    var a: array[0..255, TSysThread]
+    var a: array[0..255, SysThread]
     sysAssert a.len >= t.len, "a.len >= t.len"
     for i in 0..t.high: a[i] = t[i].sys
     discard waitForMultipleObjects(t.len.int32,
-                                   cast[ptr TSysThread](addr(a)), 1, -1)
+                                   cast[ptr SysThread](addr(a)), 1, -1)
 
 else:
-  proc joinThread*[TArg](t: TThread[TArg]) {.inline.} =
+  proc joinThread*[TArg](t: Thread[TArg]) {.inline.} =
     ## waits for the thread `t` to finish.
     discard pthread_join(t.sys, nil)
 
-  proc joinThreads*[TArg](t: varargs[TThread[TArg]]) =
+  proc joinThreads*[TArg](t: varargs[Thread[TArg]]) =
     ## waits for every thread in `t` to finish.
     for i in 0..t.high: joinThread(t[i])
 
 when false:
   # XXX a thread should really release its heap here somehow:
-  proc destroyThread*[TArg](t: var TThread[TArg]) =
+  proc destroyThread*[TArg](t: var Thread[TArg]) =
     ## forces the thread `t` to terminate. This is potentially dangerous if
     ## you don't have full control over `t` and its acquired resources.
     when hostOS == "windows":
@@ -358,8 +409,8 @@ when false:
     t.dataFn = nil
 
 when hostOS == "windows":
-  proc createThread*[TArg](t: var TThread[TArg],
-                           tp: proc (arg: TArg) {.thread.}, 
+  proc createThread*[TArg](t: var Thread[TArg],
+                           tp: proc (arg: TArg) {.thread.},
                            param: TArg) =
     ## creates a new thread `t` and starts its execution. Entry point is the
     ## proc `tp`. `param` is passed to `tp`. `TArg` can be ``void`` if you
@@ -372,9 +423,16 @@ when hostOS == "windows":
                          addr(t), 0'i32, dummyThreadId)
     if t.sys <= 0:
       raise newException(ResourceExhaustedError, "cannot create thread")
+
+  proc pinToCpu*[Arg](t: var Thread[Arg]; cpu: Natural) =
+    ## pins a thread to a `CPU`:idx:. In other words sets a
+    ## thread's `affinity`:idx:. If you don't know what this means, you
+    ## shouldn't use this proc.
+    setThreadAffinityMask(t.sys, uint(1 shl cpu))
+
 else:
-  proc createThread*[TArg](t: var TThread[TArg], 
-                           tp: proc (arg: TArg) {.thread.}, 
+  proc createThread*[TArg](t: var Thread[TArg],
+                           tp: proc (arg: TArg) {.thread.},
                            param: TArg) =
     ## creates a new thread `t` and starts its execution. Entry point is the
     ## proc `tp`. `param` is passed to `tp`. `TArg` can be ``void`` if you
@@ -382,29 +440,32 @@ else:
     when TArg isnot void: t.data = param
     t.dataFn = tp
     when hasSharedHeap: t.stackSize = ThreadStackSize
-    var a {.noinit.}: Tpthread_attr
+    var a {.noinit.}: PthreadAttr
     pthread_attr_init(a)
     pthread_attr_setstacksize(a, ThreadStackSize)
     if pthread_create(t.sys, a, threadProcWrapper[TArg], addr(t)) != 0:
       raise newException(ResourceExhaustedError, "cannot create thread")
 
-proc threadId*[TArg](t: var TThread[TArg]): TThreadId[TArg] {.inline.} =
+  proc pinToCpu*[Arg](t: var Thread[Arg]; cpu: Natural) =
+    ## pins a thread to a `CPU`:idx:. In other words sets a
+    ## thread's `affinity`:idx:. If you don't know what this means, you
+    ## shouldn't use this proc.
+    var s {.noinit.}: CpuSet
+    cpusetZero(s)
+    cpusetIncl(cpu.cint, s)
+    setAffinity(t.sys, sizeof(s), s)
+
+proc threadId*[TArg](t: var Thread[TArg]): ThreadId[TArg] {.inline.} =
   ## returns the thread ID of `t`.
   result = addr(t)
 
-proc myThreadId*[TArg](): TThreadId[TArg] =
-  ## returns the thread ID of the thread that calls this proc. This is unsafe
-  ## because the type ``TArg`` is not checked for consistency!
-  result = cast[TThreadId[TArg]](threadVarGetValue(globalsSlot))
-
 when false:
-  proc mainThreadId*[TArg](): TThreadId[TArg] =
+  proc mainThreadId*[TArg](): ThreadId[TArg] =
     ## returns the thread ID of the main thread.
-    result = cast[TThreadId[TArg]](addr(mainThread))
+    result = cast[ThreadId[TArg]](addr(mainThread))
 
 when useStackMaskHack:
   proc runMain(tp: proc () {.thread.}) {.compilerproc.} =
-    var mainThread: TThread[pointer]
+    var mainThread: Thread[pointer]
     createThread(mainThread, tp)
     joinThread(mainThread)
-
diff --git a/lib/system/timers.nim b/lib/system/timers.nim
index e5de791ac..ac8418824 100644
--- a/lib/system/timers.nim
+++ b/lib/system/timers.nim
@@ -11,83 +11,86 @@
 ## `<https://github.com/jckarter/clay/blob/master/compiler/src/hirestimer.cpp>`_
 
 type
-  TTicks = distinct int64
-  TNanos = int64
+  Ticks = distinct int64
+  Nanos = int64
+{.deprecated: [TTicks: Ticks, TNanos: Nanos].}
 
 when defined(windows):
 
-  proc QueryPerformanceCounter(res: var TTicks) {.
+  proc QueryPerformanceCounter(res: var Ticks) {.
     importc: "QueryPerformanceCounter", stdcall, dynlib: "kernel32".}
   proc QueryPerformanceFrequency(res: var int64) {.
     importc: "QueryPerformanceFrequency", stdcall, dynlib: "kernel32".}
 
-  proc getTicks(): TTicks {.inline.} =
+  proc getTicks(): Ticks {.inline.} =
     QueryPerformanceCounter(result)
 
-  proc `-`(a, b: TTicks): TNanos =
+  proc `-`(a, b: Ticks): Nanos =
     var frequency: int64
     QueryPerformanceFrequency(frequency)
     var performanceCounterRate = 1e+9'f64 / float64(frequency)
 
-    result = TNanos(float64(a.int64 - b.int64) * performanceCounterRate)
+    result = Nanos(float64(a.int64 - b.int64) * performanceCounterRate)
 
 elif defined(macosx):
   type
-    TMachTimebaseInfoData {.pure, final, 
-        importc: "mach_timebase_info_data_t", 
+    MachTimebaseInfoData {.pure, final,
+        importc: "mach_timebase_info_data_t",
         header: "<mach/mach_time.h>".} = object
       numer, denom: int32
+  {.deprecated: [TMachTimebaseInfoData: MachTimebaseInfoData].}
 
   proc mach_absolute_time(): int64 {.importc, header: "<mach/mach.h>".}
-  proc mach_timebase_info(info: var TMachTimebaseInfoData) {.importc,
+  proc mach_timebase_info(info: var MachTimebaseInfoData) {.importc,
     header: "<mach/mach_time.h>".}
 
-  proc getTicks(): TTicks {.inline.} =
-    result = TTicks(mach_absolute_time())
-  
-  var timeBaseInfo: TMachTimebaseInfoData
+  proc getTicks(): Ticks {.inline.} =
+    result = Ticks(mach_absolute_time())
+
+  var timeBaseInfo: MachTimebaseInfoData
   mach_timebase_info(timeBaseInfo)
-    
-  proc `-`(a, b: TTicks): TNanos =
+
+  proc `-`(a, b: Ticks): Nanos =
     result = (a.int64 - b.int64)  * timeBaseInfo.numer div timeBaseInfo.denom
 
 elif defined(posixRealtime):
   type
-    TClockid {.importc: "clockid_t", header: "<time.h>", final.} = object
+    Clockid {.importc: "clockid_t", header: "<time.h>", final.} = object
 
-    TTimeSpec {.importc: "struct timespec", header: "<time.h>", 
+    TimeSpec {.importc: "struct timespec", header: "<time.h>",
                final, pure.} = object ## struct timespec
-      tv_sec: int  ## Seconds. 
-      tv_nsec: int ## Nanoseconds. 
+      tv_sec: int  ## Seconds.
+      tv_nsec: int ## Nanoseconds.
+  {.deprecated: [TClockid: Clickid, TTimeSpec: TimeSpec].}
 
   var
-    CLOCK_REALTIME {.importc: "CLOCK_REALTIME", header: "<time.h>".}: TClockid
+    CLOCK_REALTIME {.importc: "CLOCK_REALTIME", header: "<time.h>".}: Clockid
 
-  proc clock_gettime(clkId: TClockid, tp: var TTimespec) {.
+  proc clock_gettime(clkId: Clockid, tp: var Timespec) {.
     importc: "clock_gettime", header: "<time.h>".}
 
-  proc getTicks(): TTicks =
-    var t: TTimespec
+  proc getTicks(): Ticks =
+    var t: Timespec
     clock_gettime(CLOCK_REALTIME, t)
-    result = TTicks(int64(t.tv_sec) * 1000000000'i64 + int64(t.tv_nsec))
+    result = Ticks(int64(t.tv_sec) * 1000000000'i64 + int64(t.tv_nsec))
 
-  proc `-`(a, b: TTicks): TNanos {.borrow.}
+  proc `-`(a, b: Ticks): Nanos {.borrow.}
 
 else:
-  # fallback Posix implementation:  
+  # fallback Posix implementation:
   type
-    Ttimeval {.importc: "struct timeval", header: "<sys/select.h>", 
+    Timeval {.importc: "struct timeval", header: "<sys/select.h>",
                final, pure.} = object ## struct timeval
-      tv_sec: int  ## Seconds. 
-      tv_usec: int ## Microseconds. 
-        
-  proc posix_gettimeofday(tp: var Ttimeval, unused: pointer = nil) {.
+      tv_sec: int  ## Seconds.
+      tv_usec: int ## Microseconds.
+  {.deprecated: [Ttimeval: Timeval].}
+  proc posix_gettimeofday(tp: var Timeval, unused: pointer = nil) {.
     importc: "gettimeofday", header: "<sys/time.h>".}
 
-  proc getTicks(): TTicks =
-    var t: Ttimeval
+  proc getTicks(): Ticks =
+    var t: Timeval
     posix_gettimeofday(t)
-    result = TTicks(int64(t.tv_sec) * 1000_000_000'i64 + 
+    result = Ticks(int64(t.tv_sec) * 1000_000_000'i64 +
                     int64(t.tv_usec) * 1000'i64)
 
-  proc `-`(a, b: TTicks): TNanos {.borrow.}
+  proc `-`(a, b: Ticks): Nanos {.borrow.}
diff --git a/lib/system/widestrs.nim b/lib/system/widestrs.nim
index 1e8bc6791..5a30a7c0f 100644
--- a/lib/system/widestrs.nim
+++ b/lib/system/widestrs.nim
@@ -14,8 +14,9 @@ when not declared(NimString):
   {.error: "You must not import this module explicitly".}
 
 type
-  TUtf16Char* = distinct int16
-  WideCString* = ref array[0.. 1_000_000, TUtf16Char]
+  Utf16Char* = distinct int16
+  WideCString* = ref array[0.. 1_000_000, Utf16Char]
+{.deprecated: [TUtf16Char: Utf16Char].}
 
 proc len*(w: WideCString): int =
   ## returns the length of a widestring. This traverses the whole string to
@@ -23,7 +24,7 @@ proc len*(w: WideCString): int =
   while int16(w[result]) != 0'i16: inc result
 
 const
-  UNI_REPLACEMENT_CHAR = TUtf16Char(0xFFFD'i16)
+  UNI_REPLACEMENT_CHAR = Utf16Char(0xFFFD'i16)
   UNI_MAX_BMP = 0x0000FFFF
   UNI_MAX_UTF16 = 0x0010FFFF
   UNI_MAX_UTF32 = 0x7FFFFFFF
@@ -89,16 +90,16 @@ proc newWideCString*(source: cstring, L: int): WideCString =
       if ch >=% UNI_SUR_HIGH_START and ch <=% UNI_SUR_LOW_END:
         result[d] = UNI_REPLACEMENT_CHAR
       else:
-        result[d] = TUtf16Char(toU16(ch))
+        result[d] = Utf16Char(toU16(ch))
     elif ch >% UNI_MAX_UTF16:
       result[d] = UNI_REPLACEMENT_CHAR
     else:
       let ch = ch -% halfBase
-      result[d] = TUtf16Char(toU16((ch shr halfShift) +% UNI_SUR_HIGH_START))
+      result[d] = Utf16Char(toU16((ch shr halfShift) +% UNI_SUR_HIGH_START))
       inc d
-      result[d] = TUtf16Char(toU16((ch and halfMask) +% UNI_SUR_LOW_START))
+      result[d] = Utf16Char(toU16((ch and halfMask) +% UNI_SUR_LOW_START))
     inc d
-  result[d] = TUtf16Char(0'i16)
+  result[d] = Utf16Char(0'i16)
 
 proc newWideCString*(s: cstring): WideCString =
   if s.isNil: return nil
@@ -113,38 +114,44 @@ proc newWideCString*(s: cstring): WideCString =
 proc newWideCString*(s: string): WideCString =
   result = newWideCString(s, s.len)
 
-proc `$`*(w: WideCString, estimate: int): string =
+proc `$`*(w: WideCString, estimate: int, replacement: int = 0xFFFD): string =
   result = newStringOfCap(estimate + estimate shr 2)
 
   var i = 0
   while w[i].int16 != 0'i16:
-    var ch = w[i].int
+    var ch = int(cast[uint16](w[i]))
     inc i
-    if ch >=% UNI_SUR_HIGH_START and ch <=% UNI_SUR_HIGH_END:
+    if ch >= UNI_SUR_HIGH_START and ch <= UNI_SUR_HIGH_END:
       # If the 16 bits following the high surrogate are in the source buffer...
-      let ch2 = w[i].int
+      let ch2 = int(cast[uint16](w[i]))
+
       # If it's a low surrogate, convert to UTF32:
-      if ch2 >=% UNI_SUR_LOW_START and ch2 <=% UNI_SUR_LOW_END:
-        ch = ((ch -% UNI_SUR_HIGH_START) shr halfShift) +%
-              (ch2 -% UNI_SUR_LOW_START) +% halfBase
+      if ch2 >= UNI_SUR_LOW_START and ch2 <= UNI_SUR_LOW_END:
+        ch = (((ch and halfMask) shl halfShift) + (ch2 and halfMask)) + halfBase
         inc i
-        
-    if ch <=% 127:
+      else:
+        #invalid UTF-16
+        ch = replacement
+    elif ch >= UNI_SUR_LOW_START and ch <= UNI_SUR_LOW_END:
+      #invalid UTF-16
+      ch = replacement
+
+    if ch < 0x80:
       result.add chr(ch)
-    elif ch <=% 0x07FF:
-      result.add chr((ch shr 6) or 0b110_00000)
-      result.add chr((ch and ones(6)) or 0b10_000000)
-    elif ch <=% 0xFFFF:
-      result.add chr(ch shr 12 or 0b1110_0000)
-      result.add chr(ch shr 6 and ones(6) or 0b10_0000_00)
-      result.add chr(ch and ones(6) or 0b10_0000_00)
-    elif ch <=% 0x0010FFFF:
-      result.add chr(ch shr 18 or 0b1111_0000)
-      result.add chr(ch shr 12 and ones(6) or 0b10_0000_00)
-      result.add chr(ch shr 6 and ones(6) or 0b10_0000_00)
-      result.add chr(ch and ones(6) or 0b10_0000_00)
+    elif ch < 0x800:
+      result.add chr((ch shr 6) or 0xc0)
+      result.add chr((ch and 0x3f) or 0x80)
+    elif ch < 0x10000:
+      result.add chr((ch shr 12) or 0xe0)
+      result.add chr(((ch shr 6) and 0x3f) or 0x80)
+      result.add chr((ch and 0x3f) or 0x80)
+    elif ch <= 0x10FFFF:
+      result.add chr((ch shr 18) or 0xf0)
+      result.add chr(((ch shr 12) and 0x3f) or 0x80)
+      result.add chr(((ch shr 6) and 0x3f) or 0x80)
+      result.add chr((ch and 0x3f) or 0x80)
     else:
-      # replacement char:
+      # replacement char(in case user give very large number):
       result.add chr(0xFFFD shr 12 or 0b1110_0000)
       result.add chr(0xFFFD shr 6 and ones(6) or 0b10_0000_00)
       result.add chr(0xFFFD and ones(6) or 0b10_0000_00)