summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2018-01-04 15:59:03 +0100
committerAndreas Rumpf <rumpf_a@web.de>2018-01-04 15:59:03 +0100
commit2e635ab28cb60be5e63e01ecf074596ccc385696 (patch)
tree9f500368898e755323aa08c0b8959c4eab08f9fc /lib
parent80fef7c8182f8b1427697ef923266094bb49abb2 (diff)
downloadNim-2e635ab28cb60be5e63e01ecf074596ccc385696.tar.gz
new runtime: added typelayouts.nim
Diffstat (limited to 'lib')
-rw-r--r--lib/core/allocators.nim14
-rw-r--r--lib/core/refs.nim48
-rw-r--r--lib/core/typelayouts.nim19
3 files changed, 64 insertions, 17 deletions
diff --git a/lib/core/allocators.nim b/lib/core/allocators.nim
index 093da296a..d6608a203 100644
--- a/lib/core/allocators.nim
+++ b/lib/core/allocators.nim
@@ -8,24 +8,10 @@
 #
 
 type
-  TypeLayout* = object
-    size*, alignment*: int
-    destructor*: proc (self: pointer; a: Allocator) {.nimcall.}
-    trace*: proc (self: pointer; a: Allocator) {.nimcall.}
-    when false:
-      construct*: proc (self: pointer; a: Allocator) {.nimcall.}
-      copy*, deepcopy*, sink*: proc (self, other: pointer; a: Allocator) {.nimcall.}
-
   Allocator* {.inheritable.} = ptr object
     alloc*: proc (a: Allocator; size: int; alignment = 8): pointer {.nimcall.}
     dealloc*: proc (a: Allocator; p: pointer; size: int) {.nimcall.}
     realloc*: proc (a: Allocator; p: pointer; oldSize, newSize: int): pointer {.nimcall.}
-    visit*: proc (fieldAddr: ptr pointer; a: Allocator) {.nimcall.}
-
-#proc allocArray(a: Allocator; L, elem: TypeLayout; n: int): pointer
-#proc deallocArray(a: Allocator; p: pointer; L, elem: TypeLayout; n: int)
-
-proc getTypeLayout*(t: typedesc): ptr TypeLayout {.magic: "getTypeLayout".}
 
 var
   currentAllocator {.threadvar.}: Allocator
diff --git a/lib/core/refs.nim b/lib/core/refs.nim
index 71c999a74..e1575b68c 100644
--- a/lib/core/refs.nim
+++ b/lib/core/refs.nim
@@ -9,23 +9,66 @@
 
 ## Default ref implementation used by Nim's core.
 
-import allocators
+# We cannot use the allocator interface here as we require a heap walker to
+# exist. Thus we import 'alloc' directly here to get our own heap that is
+# all under the GC's control and can use the ``allObjects`` iterator which
+# is crucial for the "sweep" phase.
+import typelayouts, alloc
 
 type
   TracingGc = ptr object of Allocator
+    visit*: proc (fieldAddr: ptr pointer; a: Allocator) {.nimcall.}
+
+  GcColor = enum
+    white = 0, black = 1, grey = 2 ## to flip the meaning of white/black
+                                   ## perform (1 - col)
 
   GcHeader = object
     t: ptr TypeLayout
+    color: GcColor
+  Cell = ptr GcHeader
 
   GcFrame {.core.} = object
     prev: ptr GcFrame
     marker: proc (self: GcFrame; a: Allocator)
 
+  Phase = enum
+    None, Marking, Sweeping
+
+  GcHeap = object
+    r: MemRegion
+    phase: Phase
+    currBlack, currWhite: GcColor
+    greyStack: seq[Cell]
+
+var
+  gch {.threadvar.}: GcHeap
+
 proc `=trace`[T](a: ref T) =
   if not marked(a):
     mark(a)
     `=trace`(a[])
 
+template usrToCell(p: pointer): Cell =
+
+template cellToUsr(cell: Cell): pointer =
+  cast[pointer](cast[ByteAddress](cell)+%ByteAddress(sizeof(GcHeader)))
+
+template usrToCell(usr: pointer): Cell =
+  cast[Cell](cast[ByteAddress](usr)-%ByteAddress(sizeof(GcHeader)))
+
+template markGrey(x: Cell) =
+  if x.color == gch.currWhite and phase == Marking:
+    x.color = grey
+    add(gch.greyStack, x)
+
+proc `=`[T](dest: var ref T; src: ref T) =
+  ## full write barrier implementation.
+  if src != nil:
+    let s = usrToCell(src)
+    markGrey(s)
+  system.`=`(dest, src)
+
 proc linkGcFrame(f: ptr GcFrame) {.core.}
 proc unlinkGcFrame() {.core.}
 
@@ -38,8 +81,7 @@ proc registerThreadvar(p: pointer; t: ptr TypeLayout) {.core.}
 proc unregisterThreadvar(p: pointer; t: ptr TypeLayout) {.core.}
 
 proc newImpl(t: ptr TypeLayout): pointer =
-  let a = getCurrentAllocator()
-  let r = cast[ptr GcHeader](a.alloc(a, t.size + sizeof(GcHeader), t.alignment))
+  let r = cast[Cell](rawAlloc(t.size + sizeof(GcHeader)))
   r.typ = t
   result = r +! sizeof(GcHeader)
 
diff --git a/lib/core/typelayouts.nim b/lib/core/typelayouts.nim
new file mode 100644
index 000000000..445ce77c4
--- /dev/null
+++ b/lib/core/typelayouts.nim
@@ -0,0 +1,19 @@
+#
+#
+#            Nim's Runtime Library
+#        (c) Copyright 2017 Nim contributors
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+type
+  TypeLayout* = object
+    size*, alignment*: int
+    destructor*: proc (self: pointer; a: Allocator) {.nimcall.}
+    trace*: proc (self: pointer; a: Allocator) {.nimcall.}
+    when false:
+      construct*: proc (self: pointer; a: Allocator) {.nimcall.}
+      copy*, deepcopy*, sink*: proc (self, other: pointer; a: Allocator) {.nimcall.}
+
+proc getTypeLayout(t: typedesc): ptr TypeLayout {.magic: "getTypeLayout".}