refs.nim 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. #
  2. #
  3. # Nim's Runtime Library
  4. # (c) Copyright 2017 Nim contributors
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. ## Default ref implementation used by Nim's core.
  10. # We cannot use the allocator interface here as we require a heap walker to
  11. # exist. Thus we import 'alloc' directly here to get our own heap that is
  12. # all under the GC's control and can use the ``allObjects`` iterator which
  13. # is crucial for the "sweep" phase.
  14. import typelayouts, alloc
  15. type
  16. TracingGc = ptr object of Allocator
  17. visit*: proc (fieldAddr: ptr pointer; a: Allocator) {.nimcall.}
  18. GcColor = enum
  19. white = 0, black = 1, grey = 2 ## to flip the meaning of white/black
  20. ## perform (1 - col)
  21. GcHeader = object
  22. t: ptr TypeLayout
  23. color: GcColor
  24. Cell = ptr GcHeader
  25. GcFrame {.core.} = object
  26. prev: ptr GcFrame
  27. marker: proc (self: GcFrame; a: Allocator)
  28. Phase = enum
  29. None, Marking, Sweeping
  30. GcHeap = object
  31. r: MemRegion
  32. phase: Phase
  33. currBlack, currWhite: GcColor
  34. greyStack: seq[Cell]
  35. var
  36. gch {.threadvar.}: GcHeap
  37. proc `=trace`[T](a: ref T) =
  38. if not marked(a):
  39. mark(a)
  40. `=trace`(a[])
  41. template usrToCell(p: pointer): Cell =
  42. template cellToUsr(cell: Cell): pointer =
  43. cast[pointer](cast[ByteAddress](cell)+%ByteAddress(sizeof(GcHeader)))
  44. template usrToCell(usr: pointer): Cell =
  45. cast[Cell](cast[ByteAddress](usr)-%ByteAddress(sizeof(GcHeader)))
  46. template markGrey(x: Cell) =
  47. if x.color == gch.currWhite and phase == Marking:
  48. x.color = grey
  49. add(gch.greyStack, x)
  50. proc `=`[T](dest: var ref T; src: ref T) =
  51. ## full write barrier implementation.
  52. if src != nil:
  53. let s = usrToCell(src)
  54. markGrey(s)
  55. system.`=`(dest, src)
  56. proc linkGcFrame(f: ptr GcFrame) {.core.}
  57. proc unlinkGcFrame() {.core.}
  58. proc setGcFrame(f: ptr GcFrame) {.core.}
  59. proc registerGlobal(p: pointer; t: ptr TypeLayout) {.core.}
  60. proc unregisterGlobal(p: pointer; t: ptr TypeLayout) {.core.}
  61. proc registerThreadvar(p: pointer; t: ptr TypeLayout) {.core.}
  62. proc unregisterThreadvar(p: pointer; t: ptr TypeLayout) {.core.}
  63. proc newImpl(t: ptr TypeLayout): pointer =
  64. let r = cast[Cell](rawAlloc(t.size + sizeof(GcHeader)))
  65. r.typ = t
  66. result = r +! sizeof(GcHeader)
  67. template new*[T](x: var ref T) =
  68. x = newImpl(getTypeLayout(x))
  69. when false:
  70. # implement these if your GC requires them:
  71. proc writeBarrierLocal() {.core.}
  72. proc writeBarrierGlobal() {.core.}
  73. proc writeBarrierGeneric() {.core.}