1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 |
- #
- #
- # 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.}
|