1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
when defined(windows):
const goLib = "libgo.dll"
elif defined(macosx):
const goLib = "libgo.dylib"
else:
const goLib = "libgo.so"
proc initGC() = discard
proc GC_disable() = discard
proc GC_enable() = discard
proc go_gc() {.importc: "go_gc", dynlib: goLib.}
proc GC_fullCollect() = go_gc()
proc GC_setStrategy(strategy: GC_Strategy) = discard
proc GC_enableMarkAndSweep() = discard
proc GC_disableMarkAndSweep() = discard
const
goNumSizeClasses = 67
type
goMStats = object
alloc: uint64 # bytes allocated and still in use
total_alloc: uint64 # bytes allocated (even if freed)
sys: uint64 # bytes obtained from system
nlookup: uint64 # number of pointer lookups
nmalloc: uint64 # number of mallocs
nfree: uint64 # number of frees
heap_objects: uint64 # total number of allocated objects
pause_total_ns: uint64 # cumulative nanoseconds in GC stop-the-world pauses since the program started
numgc: uint32 # number of completed GC cycles
proc goMemStats(): goMStats {.importc: "go_mem_stats", dynlib: goLib.}
proc goMalloc(size: uint): pointer {.importc: "go_malloc", 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 writebarrierptr(dest: PPointer, src: pointer) {.importc: "writebarrierptr", codegenDecl:"$1 $2$3 __asm__ (\"main.Atomic_store_pointer\");\n$1 $2$3", dynlib: goLib.}
proc `$`*(x: uint64): string {.noSideEffect, raises: [].}
proc GC_getStatistics(): string =
var mstats = goMemStats()
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] number of completed GC cycles: " & $(mstats.numgc) & "\n" &
"[GC] total GC pause time [ms]: " & $(mstats.pause_total_ns div 1000_000)
proc getOccupiedMem(): int =
var mstats = goMemStats()
result = int(mstats.alloc)
proc getFreeMem(): int =
var mstats = goMemStats()
result = int(mstats.sys - mstats.alloc)
proc getTotalMem(): int =
var mstats = goMemStats()
result = int(mstats.sys)
proc nimGC_setStackBottom(theStackBottom: pointer) = discard
proc allocImpl(size: Natural): pointer =
result = goMalloc(size.uint)
proc alloc0Impl(size: Natural): pointer =
result = goMalloc(size.uint)
proc reallocImpl(p: pointer, newsize: Natural): pointer =
doAssert false, "not implemented"
proc realloc0Impl(p: pointer, oldsize, newsize: Natural): pointer =
doAssert false, "not implemented"
proc deallocImpl(p: pointer) =
discard
proc allocSharedImpl(size: Natural): pointer = allocImpl(size)
proc allocShared0Impl(size: Natural): pointer = alloc0Impl(size)
proc reallocSharedImpl(p: pointer, newsize: Natural): pointer = reallocImpl(p, newsize)
proc reallocShared0Impl(p: pointer, oldsize, newsize: Natural): pointer = realloc0Impl(p, oldsize, newsize)
proc deallocSharedImpl(p: pointer) = deallocImpl(p)
when hasThreadSupport:
proc getFreeSharedMem(): int = discard
proc getTotalSharedMem(): int = discard
proc getOccupiedSharedMem(): int = discard
proc newObj(typ: PNimType, size: int): pointer {.compilerproc.} =
writebarrierptr(addr(result), goMalloc(size.uint))
if typ.finalizer != nil:
goSetFinalizer(result, typ.finalizer)
proc newObjRC1(typ: PNimType, size: int): pointer {.compilerRtl.} =
writebarrierptr(addr(result), newObj(typ, size))
proc newObjNoInit(typ: PNimType, size: int): pointer =
writebarrierptr(addr(result), newObj(typ, size))
proc newSeq(typ: PNimType, len: int): pointer {.compilerproc.} =
writebarrierptr(addr(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 newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl.} =
writebarrierptr(addr(result), newSeq(typ, len))
proc nimNewSeqOfCap(typ: PNimType, cap: int): pointer {.compilerproc.} =
result = newObj(typ, cap * typ.base.size + GenericSeqSize)
cast[PGenericSeq](result).len = 0
cast[PGenericSeq](result).reserved = cap
cast[PGenericSeq](result).elemSize = typ.base.size
proc typedMemMove(dest: pointer, src: pointer, size: uint) {.importc: "typedmemmove", dynlib: goLib.}
proc growObj(old: pointer, newsize: int): pointer =
# the Go GC doesn't have a realloc
var metadataOld = cast[PGenericSeq](old)
if metadataOld.elemSize == 0:
metadataOld.elemSize = 1
let oldsize = cast[PGenericSeq](old).len * cast[PGenericSeq](old).elemSize + GenericSeqSize
writebarrierptr(addr(result), goMalloc(newsize.uint))
typedMemMove(result, old, oldsize.uint)
proc nimGCref(p: pointer) {.compilerproc, inline.} = discard
proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard
proc nimGCunrefNoCycle(p: pointer) {.compilerProc, inline.} = discard
proc nimGCunrefRC1(p: pointer) {.compilerProc, inline.} = discard
proc nimGCvisit(d: pointer, op: int) {.compilerRtl.} = discard
proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
writebarrierptr(dest, src)
proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
writebarrierptr(dest, src)
proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline,
deprecated: "old compiler compat".} = asgnRef(dest, src)
type
MemRegion = object
proc alloc(r: var MemRegion, size: int): pointer =
result = alloc(size)
proc alloc0(r: var MemRegion, size: int): pointer =
result = alloc0Impl(size)
proc dealloc(r: var MemRegion, p: pointer) = dealloc(p)
proc deallocOsPages(r: var MemRegion) {.inline.} = discard
proc deallocOsPages() {.inline.} = discard
|