# # # Nim's Runtime Library # (c) Copyright 2017 Nim contributors # # See the file "copying.txt", included in this # distribution, for details about the copyright. # ## Default ref implementation used by Nim's core. # 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.} proc setGcFrame(f: ptr GcFrame) {.core.} proc registerGlobal(p: pointer; t: ptr TypeLayout) {.core.} proc unregisterGlobal(p: pointer; t: ptr TypeLayout) {.core.} proc registerThreadvar(p: pointer; t: ptr TypeLayout) {.core.} proc unregisterThreadvar(p: pointer; t: ptr TypeLayout) {.core.} proc newImpl(t: ptr TypeLayout): pointer = let r = cast[Cell](rawAlloc(t.size + sizeof(GcHeader))) r.typ = t result = r +! sizeof(GcHeader) template new*[T](x: var ref T) = x = newImpl(getTypeLayout(x)) when false: # implement these if your GC requires them: proc writeBarrierLocal() {.core.} proc writeBarrierGlobal() {.core.} proc writeBarrierGeneric() {.core.}