the Go GC - initial implementation
This commit is contained in:
parent
6820b2fea9
commit
50e96ad939
10 changed files with 213 additions and 16 deletions
|
|
@ -22,6 +22,7 @@ bootSwitch(usedNoCaas, defined(noCaas), "-d:noCaas")
|
||||||
bootSwitch(usedBoehm, defined(boehmgc), "--gc:boehm")
|
bootSwitch(usedBoehm, defined(boehmgc), "--gc:boehm")
|
||||||
bootSwitch(usedMarkAndSweep, defined(gcmarkandsweep), "--gc:markAndSweep")
|
bootSwitch(usedMarkAndSweep, defined(gcmarkandsweep), "--gc:markAndSweep")
|
||||||
bootSwitch(usedGenerational, defined(gcgenerational), "--gc:generational")
|
bootSwitch(usedGenerational, defined(gcgenerational), "--gc:generational")
|
||||||
|
bootSwitch(usedGoGC, defined(gogc), "--gc:go")
|
||||||
bootSwitch(usedNoGC, defined(nogc), "--gc:none")
|
bootSwitch(usedNoGC, defined(nogc), "--gc:none")
|
||||||
|
|
||||||
import
|
import
|
||||||
|
|
@ -86,7 +87,7 @@ proc writeVersionInfo(pass: TCmdLinePass) =
|
||||||
|
|
||||||
msgWriteln("active boot switches:" & usedRelease & usedAvoidTimeMachine &
|
msgWriteln("active boot switches:" & usedRelease & usedAvoidTimeMachine &
|
||||||
usedTinyC & usedGnuReadline & usedNativeStacktrace & usedNoCaas &
|
usedTinyC & usedGnuReadline & usedNativeStacktrace & usedNoCaas &
|
||||||
usedFFI & usedBoehm & usedMarkAndSweep & usedGenerational & usedNoGC)
|
usedFFI & usedBoehm & usedMarkAndSweep & usedGenerational & usedGoGC & usedNoGC)
|
||||||
msgQuit(0)
|
msgQuit(0)
|
||||||
|
|
||||||
var
|
var
|
||||||
|
|
@ -181,6 +182,7 @@ proc testCompileOptionArg*(switch, arg: string, info: TLineInfo): bool =
|
||||||
of "v2": result = gSelectedGC == gcV2
|
of "v2": result = gSelectedGC == gcV2
|
||||||
of "markandsweep": result = gSelectedGC == gcMarkAndSweep
|
of "markandsweep": result = gSelectedGC == gcMarkAndSweep
|
||||||
of "generational": result = gSelectedGC == gcGenerational
|
of "generational": result = gSelectedGC == gcGenerational
|
||||||
|
of "go": result = gSelectedGC == gcGo
|
||||||
of "none": result = gSelectedGC == gcNone
|
of "none": result = gSelectedGC == gcNone
|
||||||
else: localError(info, errNoneBoehmRefcExpectedButXFound, arg)
|
else: localError(info, errNoneBoehmRefcExpectedButXFound, arg)
|
||||||
of "opt":
|
of "opt":
|
||||||
|
|
@ -365,6 +367,9 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
|
||||||
of "generational":
|
of "generational":
|
||||||
gSelectedGC = gcGenerational
|
gSelectedGC = gcGenerational
|
||||||
defineSymbol("gcgenerational")
|
defineSymbol("gcgenerational")
|
||||||
|
of "go":
|
||||||
|
gSelectedGC = gcGo
|
||||||
|
defineSymbol("gogc")
|
||||||
of "none":
|
of "none":
|
||||||
gSelectedGC = gcNone
|
gSelectedGC = gcNone
|
||||||
defineSymbol("nogc")
|
defineSymbol("nogc")
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ type # please make sure we have under 32 options
|
||||||
cmdRun # run the project via TCC backend
|
cmdRun # run the project via TCC backend
|
||||||
TStringSeq* = seq[string]
|
TStringSeq* = seq[string]
|
||||||
TGCMode* = enum # the selected GC
|
TGCMode* = enum # the selected GC
|
||||||
gcNone, gcBoehm, gcMarkAndSweep, gcRefc, gcV2, gcGenerational
|
gcNone, gcBoehm, gcGo, gcMarkAndSweep, gcRefc, gcV2, gcGenerational
|
||||||
|
|
||||||
IdeCmd* = enum
|
IdeCmd* = enum
|
||||||
ideNone, ideSug, ideCon, ideDef, ideUse
|
ideNone, ideSug, ideCon, ideDef, ideUse
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ Advanced options:
|
||||||
--skipUserCfg do not read the user's configuration file
|
--skipUserCfg do not read the user's configuration file
|
||||||
--skipParentCfg do not read the parent dirs' configuration files
|
--skipParentCfg do not read the parent dirs' configuration files
|
||||||
--skipProjCfg do not read the project's configuration file
|
--skipProjCfg do not read the project's configuration file
|
||||||
--gc:refc|v2|markAndSweep|boehm|none
|
--gc:refc|v2|markAndSweep|boehm|go|none
|
||||||
select the GC to use; default is 'refc'
|
select the GC to use; default is 'refc'
|
||||||
--index:on|off turn index file generation on|off
|
--index:on|off turn index file generation on|off
|
||||||
--putenv:key=value set an environment variable
|
--putenv:key=value set an environment variable
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ options:
|
||||||
are limited to pure Nim code at compilation time. Enabling
|
are limited to pure Nim code at compilation time. Enabling
|
||||||
this switch will allow macros to execute non-nim code at
|
this switch will allow macros to execute non-nim code at
|
||||||
compilation time (eg. open a file and write to it).
|
compilation time (eg. open a file and write to it).
|
||||||
--gc:refc|v2|markAndSweep|boehm|none
|
--gc:refc|v2|markAndSweep|boehm|go|none
|
||||||
Selects which garbage collection strategy to use for the compiler
|
Selects which garbage collection strategy to use for the compiler
|
||||||
and generated code. See the `Nim's Garbage Collector <gc.html>`_
|
and generated code. See the `Nim's Garbage Collector <gc.html>`_
|
||||||
documentation for more information.
|
documentation for more information.
|
||||||
|
|
|
||||||
|
|
@ -67,11 +67,11 @@ type
|
||||||
pbyteArray = ptr array[0.. 0xffff, int8]
|
pbyteArray = ptr array[0.. 0xffff, int8]
|
||||||
|
|
||||||
TGenericSeq {.importc.} = object
|
TGenericSeq {.importc.} = object
|
||||||
len, space: int
|
len, space, elemSize: int
|
||||||
PGenSeq = ptr TGenericSeq
|
PGenSeq = ptr TGenericSeq
|
||||||
|
|
||||||
const
|
const
|
||||||
GenericSeqSize = (2 * sizeof(int))
|
GenericSeqSize = (3 * sizeof(int))
|
||||||
|
|
||||||
proc genericAssign(dest, src: pointer, mt: PNimType) {.importCompilerProc.}
|
proc genericAssign(dest, src: pointer, mt: PNimType) {.importCompilerProc.}
|
||||||
proc genericShallowAssign(dest, src: pointer, mt: PNimType) {.
|
proc genericShallowAssign(dest, src: pointer, mt: PNimType) {.
|
||||||
|
|
|
||||||
|
|
@ -304,7 +304,7 @@ const ArrayDummySize = when defined(cpu16): 10_000 else: 100_000_000
|
||||||
when not defined(JS):
|
when not defined(JS):
|
||||||
type
|
type
|
||||||
TGenericSeq {.compilerproc, pure, inheritable.} = object
|
TGenericSeq {.compilerproc, pure, inheritable.} = object
|
||||||
len, reserved: int
|
len, reserved, elemSize: int
|
||||||
PGenericSeq {.exportc.} = ptr TGenericSeq
|
PGenericSeq {.exportc.} = ptr TGenericSeq
|
||||||
UncheckedCharArray {.unchecked.} = array[0..ArrayDummySize, char]
|
UncheckedCharArray {.unchecked.} = array[0..ArrayDummySize, char]
|
||||||
# len and space without counting the terminating zero:
|
# len and space without counting the terminating zero:
|
||||||
|
|
@ -1068,7 +1068,7 @@ proc compileOption*(option, arg: string): bool {.
|
||||||
|
|
||||||
const
|
const
|
||||||
hasThreadSupport = compileOption("threads")
|
hasThreadSupport = compileOption("threads")
|
||||||
hasSharedHeap = defined(boehmgc) # don't share heaps; every thread has its own
|
hasSharedHeap = defined(boehmgc) or defined(gogc) # don't share heaps; every thread has its own
|
||||||
taintMode = compileOption("taintmode")
|
taintMode = compileOption("taintmode")
|
||||||
|
|
||||||
when taintMode:
|
when taintMode:
|
||||||
|
|
@ -2315,7 +2315,7 @@ when not defined(JS): #and not defined(NimrodVM):
|
||||||
|
|
||||||
when not defined(NimrodVM) and hostOS != "standalone":
|
when not defined(NimrodVM) and hostOS != "standalone":
|
||||||
proc initGC()
|
proc initGC()
|
||||||
when not defined(boehmgc) and not defined(useMalloc):
|
when not defined(boehmgc) and not defined(useMalloc) and not defined(gogc):
|
||||||
proc initAllocator() {.inline.}
|
proc initAllocator() {.inline.}
|
||||||
|
|
||||||
proc initStackBottom() {.inline, compilerproc.} =
|
proc initStackBottom() {.inline, compilerproc.} =
|
||||||
|
|
@ -2649,7 +2649,7 @@ when not defined(JS): #and not defined(NimrodVM):
|
||||||
include "system/sets"
|
include "system/sets"
|
||||||
|
|
||||||
const
|
const
|
||||||
GenericSeqSize = (2 * sizeof(int))
|
GenericSeqSize = (3 * sizeof(int))
|
||||||
|
|
||||||
proc getDiscriminant(aa: pointer, n: ptr TNimNode): int =
|
proc getDiscriminant(aa: pointer, n: ptr TNimNode): int =
|
||||||
sysAssert(n.kind == nkCase, "getDiscriminant: node != nkCase")
|
sysAssert(n.kind == nkCase, "getDiscriminant: node != nkCase")
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
# Nim high-level memory manager: It supports Boehm's GC, no GC and the
|
# Nim high-level memory manager: It supports Boehm's GC, Go's GC, no GC and the
|
||||||
# native Nim GC. The native Nim GC is the default.
|
# native Nim GC. The native Nim GC is the default.
|
||||||
|
|
||||||
#{.push checks:on, assertions:on.}
|
#{.push checks:on, assertions:on.}
|
||||||
|
|
@ -148,6 +148,7 @@ when defined(boehmgc):
|
||||||
proc GC_enableMarkAndSweep() = discard
|
proc GC_enableMarkAndSweep() = discard
|
||||||
proc GC_disableMarkAndSweep() = discard
|
proc GC_disableMarkAndSweep() = discard
|
||||||
proc GC_getStatistics(): string = return ""
|
proc GC_getStatistics(): string = return ""
|
||||||
|
proc setupForeignThreadGc*() = discard
|
||||||
|
|
||||||
proc getOccupiedMem(): int = return boehmGetHeapSize()-boehmGetFreeBytes()
|
proc getOccupiedMem(): int = return boehmGetHeapSize()-boehmGetFreeBytes()
|
||||||
proc getFreeMem(): int = return boehmGetFreeBytes()
|
proc getFreeMem(): int = return boehmGetFreeBytes()
|
||||||
|
|
@ -193,6 +194,195 @@ when defined(boehmgc):
|
||||||
proc deallocOsPages() {.inline.} = discard
|
proc deallocOsPages() {.inline.} = discard
|
||||||
|
|
||||||
include "system/cellsets"
|
include "system/cellsets"
|
||||||
|
|
||||||
|
elif defined(gogc):
|
||||||
|
when defined(windows):
|
||||||
|
const goLib = "libgo.dll"
|
||||||
|
elif defined(macosx):
|
||||||
|
const goLib = "libgo.dylib"
|
||||||
|
else:
|
||||||
|
const goLib = "libgo.so"
|
||||||
|
|
||||||
|
proc `div`[T: SomeUnsignedInt](x, y: T): T {.magic: "DivU", noSideEffect.}
|
||||||
|
proc `-`[T: SomeUnsignedInt](x, y: T): T {.magic: "SubU", noSideEffect.}
|
||||||
|
|
||||||
|
proc roundup(x, v: int): int {.inline.} =
|
||||||
|
result = (x + (v-1)) and not (v-1)
|
||||||
|
|
||||||
|
proc initGC() = discard
|
||||||
|
# runtime_setgcpercent is only available in GCC 5
|
||||||
|
proc GC_disable() = discard
|
||||||
|
proc GC_enable() = discard
|
||||||
|
proc goRuntimeGC(force: int32) {.importc: "runtime_gc", dynlib: goLib.}
|
||||||
|
proc GC_fullCollect() = goRuntimeGC(2)
|
||||||
|
proc GC_setStrategy(strategy: GC_Strategy) = discard
|
||||||
|
proc GC_enableMarkAndSweep() = discard
|
||||||
|
proc GC_disableMarkAndSweep() = discard
|
||||||
|
|
||||||
|
const
|
||||||
|
goNumSizeClasses = 67
|
||||||
|
|
||||||
|
type
|
||||||
|
cbool {.importc: "_Bool", nodecl.} = bool
|
||||||
|
|
||||||
|
goMStats_inner_struct = object
|
||||||
|
size: uint32
|
||||||
|
nmalloc: uint64
|
||||||
|
nfree: uint64
|
||||||
|
|
||||||
|
goMStats = object
|
||||||
|
# General statistics.
|
||||||
|
alloc: uint64 # bytes allocated and still in use
|
||||||
|
total_alloc: uint64 # bytes allocated (even if freed)
|
||||||
|
sys: uint64 # bytes obtained from system (should be sum of xxx_sys below, no locking, approximate)
|
||||||
|
nlookup: uint64 # number of pointer lookups
|
||||||
|
nmalloc: uint64 # number of mallocs
|
||||||
|
nfree: uint64 # number of frees
|
||||||
|
# Statistics about malloc heap.
|
||||||
|
# protected by mheap.Lock
|
||||||
|
heap_alloc: uint64 # bytes allocated and still in use
|
||||||
|
heap_sys: uint64 # bytes obtained from system
|
||||||
|
heap_idle: uint64 # bytes in idle spans
|
||||||
|
heap_inuse: uint64 # bytes in non-idle spans
|
||||||
|
heap_released: uint64 # bytes released to the OS
|
||||||
|
heap_objects: uint64 # total number of allocated objects
|
||||||
|
# Statistics about allocation of low-level fixed-size structures.
|
||||||
|
# Protected by FixAlloc locks.
|
||||||
|
stacks_inuse: uint64 # bootstrap stacks
|
||||||
|
stacks_sys: uint64
|
||||||
|
mspan_inuse: uint64 # MSpan structures
|
||||||
|
mspan_sys: uint64
|
||||||
|
mcache_inuse: uint64 # MCache structures
|
||||||
|
mcache_sys: uint64
|
||||||
|
buckhash_sys: uint64 # profiling bucket hash table
|
||||||
|
gc_sys: uint64
|
||||||
|
other_sys: uint64
|
||||||
|
# Statistics about garbage collector.
|
||||||
|
# Protected by mheap or stopping the world during GC.
|
||||||
|
next_gc: uint64 # next GC (in heap_alloc time)
|
||||||
|
last_gc: uint64 # last GC (in absolute time)
|
||||||
|
pause_total_ns: uint64
|
||||||
|
pause_ns: array[256, uint64]
|
||||||
|
numgc: uint32
|
||||||
|
enablegc: cbool
|
||||||
|
debuggc: cbool
|
||||||
|
# Statistics about allocation size classes.
|
||||||
|
by_size: array[goNumSizeClasses, goMStats_inner_struct]
|
||||||
|
|
||||||
|
proc goRuntime_ReadMemStats(a2: ptr goMStats) {.cdecl, importc: "runtime_ReadMemStats", codegenDecl: "$1 $2$3 __asm__ (\"runtime.ReadMemStats\");\n$1 $2$3", dynlib: goLib.}
|
||||||
|
|
||||||
|
proc GC_getStatistics(): string =
|
||||||
|
var mstats: goMStats
|
||||||
|
goRuntime_ReadMemStats(addr mstats)
|
||||||
|
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] numgc: " & $(mstats.numgc) & "\n" &
|
||||||
|
"[GC] enablegc: " & $(mstats.enablegc) & "\n" &
|
||||||
|
"[GC] debuggc: " & $(mstats.debuggc) & "\n" &
|
||||||
|
"[GC] total pause time [ms]: " & $(mstats.pause_total_ns div 1000_000)
|
||||||
|
proc setupForeignThreadGc*() = discard
|
||||||
|
|
||||||
|
proc getOccupiedMem(): int =
|
||||||
|
var mstats: goMStats
|
||||||
|
goRuntime_ReadMemStats(addr mstats)
|
||||||
|
result = int(mstats.alloc)
|
||||||
|
|
||||||
|
proc getFreeMem(): int =
|
||||||
|
var mstats: goMStats
|
||||||
|
goRuntime_ReadMemStats(addr mstats)
|
||||||
|
result = int(mstats.sys - mstats.alloc)
|
||||||
|
|
||||||
|
proc getTotalMem(): int =
|
||||||
|
var mstats: goMStats
|
||||||
|
goRuntime_ReadMemStats(addr mstats)
|
||||||
|
result = int(mstats.sys)
|
||||||
|
|
||||||
|
proc setStackBottom(theStackBottom: pointer) = discard
|
||||||
|
|
||||||
|
proc alloc(size: Natural): pointer =
|
||||||
|
result = cmalloc(size)
|
||||||
|
if result == nil: raiseOutOfMem()
|
||||||
|
|
||||||
|
proc alloc0(size: Natural): pointer =
|
||||||
|
result = alloc(size)
|
||||||
|
zeroMem(result, size)
|
||||||
|
|
||||||
|
proc realloc(p: pointer, newsize: Natural): pointer =
|
||||||
|
result = crealloc(p, newsize)
|
||||||
|
if result == nil: raiseOutOfMem()
|
||||||
|
|
||||||
|
proc dealloc(p: pointer) = cfree(p)
|
||||||
|
|
||||||
|
proc allocShared(size: Natural): pointer =
|
||||||
|
result = cmalloc(size)
|
||||||
|
if result == nil: raiseOutOfMem()
|
||||||
|
|
||||||
|
proc allocShared0(size: Natural): pointer =
|
||||||
|
result = alloc(size)
|
||||||
|
zeroMem(result, size)
|
||||||
|
|
||||||
|
proc reallocShared(p: pointer, newsize: Natural): pointer =
|
||||||
|
result = crealloc(p, newsize)
|
||||||
|
if result == nil: raiseOutOfMem()
|
||||||
|
|
||||||
|
proc deallocShared(p: pointer) = cfree(p)
|
||||||
|
|
||||||
|
when hasThreadSupport:
|
||||||
|
proc getFreeSharedMem(): int = discard
|
||||||
|
proc getTotalSharedMem(): int = discard
|
||||||
|
proc getOccupiedSharedMem(): int = discard
|
||||||
|
|
||||||
|
const goFlagNoZero: uint32 = 1 shl 3
|
||||||
|
proc goRuntimeMallocGC(size: uint, typ: uint, flag: uint32): pointer {.importc: "runtime_mallocgc", dynlib: goLib.}
|
||||||
|
proc goFree(v: pointer) {.importc: "__go_free", dynlib: goLib.}
|
||||||
|
|
||||||
|
proc newObj(typ: PNimType, size: int): pointer {.compilerproc.} =
|
||||||
|
result = goRuntimeMallocGC(roundup(size, sizeof(pointer)).uint, 0.uint, 0.uint32)
|
||||||
|
|
||||||
|
proc newObjNoInit(typ: PNimType, size: int): pointer =
|
||||||
|
result = goRuntimeMallocGC(roundup(size, sizeof(pointer)).uint, 0.uint, goFlagNoZero)
|
||||||
|
|
||||||
|
proc newSeq(typ: PNimType, len: int): pointer {.compilerproc.} =
|
||||||
|
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 growObj(old: pointer, newsize: int): pointer =
|
||||||
|
# the Go GC doesn't have a realloc
|
||||||
|
var
|
||||||
|
oldsize = cast[PGenericSeq](old).len * cast[PGenericSeq](old).elemSize + GenericSeqSize
|
||||||
|
result = goRuntimeMallocGC(roundup(newsize, sizeof(pointer)).uint, 0.uint, goFlagNoZero)
|
||||||
|
copyMem(result, old, oldsize)
|
||||||
|
zeroMem(cast[pointer](cast[ByteAddress](result) +% oldsize), newsize - oldsize)
|
||||||
|
goFree(old)
|
||||||
|
|
||||||
|
proc nimGCref(p: pointer) {.compilerproc, inline.} = discard
|
||||||
|
proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard
|
||||||
|
|
||||||
|
proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
|
||||||
|
dest[] = src
|
||||||
|
proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
|
||||||
|
dest[] = src
|
||||||
|
proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline.} =
|
||||||
|
dest[] = src
|
||||||
|
|
||||||
|
type
|
||||||
|
TMemRegion = object {.final, pure.}
|
||||||
|
|
||||||
|
proc alloc(r: var TMemRegion, size: int): pointer =
|
||||||
|
result = alloc(size)
|
||||||
|
proc alloc0(r: var TMemRegion, size: int): pointer =
|
||||||
|
result = alloc0(size)
|
||||||
|
proc dealloc(r: var TMemRegion, p: pointer) = dealloc(p)
|
||||||
|
proc deallocOsPages(r: var TMemRegion) {.inline.} = discard
|
||||||
|
proc deallocOsPages() {.inline.} = discard
|
||||||
|
|
||||||
elif defined(nogc) and defined(useMalloc):
|
elif defined(nogc) and defined(useMalloc):
|
||||||
|
|
||||||
when not defined(useNimRtl):
|
when not defined(useNimRtl):
|
||||||
|
|
@ -225,6 +415,7 @@ elif defined(nogc) and defined(useMalloc):
|
||||||
proc GC_enableMarkAndSweep() = discard
|
proc GC_enableMarkAndSweep() = discard
|
||||||
proc GC_disableMarkAndSweep() = discard
|
proc GC_disableMarkAndSweep() = discard
|
||||||
proc GC_getStatistics(): string = return ""
|
proc GC_getStatistics(): string = return ""
|
||||||
|
proc setupForeignThreadGc*() = discard
|
||||||
|
|
||||||
proc getOccupiedMem(): int = discard
|
proc getOccupiedMem(): int = discard
|
||||||
proc getFreeMem(): int = discard
|
proc getFreeMem(): int = discard
|
||||||
|
|
@ -287,6 +478,7 @@ elif defined(nogc):
|
||||||
proc GC_enableMarkAndSweep() = discard
|
proc GC_enableMarkAndSweep() = discard
|
||||||
proc GC_disableMarkAndSweep() = discard
|
proc GC_disableMarkAndSweep() = discard
|
||||||
proc GC_getStatistics(): string = return ""
|
proc GC_getStatistics(): string = return ""
|
||||||
|
proc setupForeignThreadGc*() = discard
|
||||||
|
|
||||||
|
|
||||||
proc newObj(typ: PNimType, size: int): pointer {.compilerproc.} =
|
proc newObj(typ: PNimType, size: int): pointer {.compilerproc.} =
|
||||||
|
|
|
||||||
|
|
@ -204,7 +204,7 @@ when not defined(useNimRtl):
|
||||||
cl: var TReprClosure) =
|
cl: var TReprClosure) =
|
||||||
# we know that p is not nil here:
|
# we know that p is not nil here:
|
||||||
when declared(TCellSet):
|
when declared(TCellSet):
|
||||||
when defined(boehmGC) or defined(nogc):
|
when defined(boehmGC) or defined(gogc) or defined(nogc):
|
||||||
var cell = cast[PCell](p)
|
var cell = cast[PCell](p)
|
||||||
else:
|
else:
|
||||||
var cell = usrToCell(p)
|
var cell = usrToCell(p)
|
||||||
|
|
|
||||||
|
|
@ -216,7 +216,7 @@ proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
|
||||||
elif newLen < result.len:
|
elif newLen < result.len:
|
||||||
# we need to decref here, otherwise the GC leaks!
|
# we need to decref here, otherwise the GC leaks!
|
||||||
when not defined(boehmGC) and not defined(nogc) and
|
when not defined(boehmGC) and not defined(nogc) and
|
||||||
not defined(gcMarkAndSweep):
|
not defined(gcMarkAndSweep) and not defined(gogc):
|
||||||
when compileOption("gc", "v2"):
|
when compileOption("gc", "v2"):
|
||||||
for i in newLen..result.len-1:
|
for i in newLen..result.len-1:
|
||||||
let len0 = gch.tempStack.len
|
let len0 = gch.tempStack.len
|
||||||
|
|
|
||||||
|
|
@ -232,7 +232,7 @@ when not defined(useNimRtl):
|
||||||
echo "too large thread local storage size requested"
|
echo "too large thread local storage size requested"
|
||||||
quit 1
|
quit 1
|
||||||
|
|
||||||
when hasSharedHeap and not defined(boehmgc) and not defined(nogc):
|
when hasSharedHeap and not defined(boehmgc) and not defined(gogc) and not defined(nogc):
|
||||||
var
|
var
|
||||||
threadList: PGcThread
|
threadList: PGcThread
|
||||||
|
|
||||||
|
|
@ -281,7 +281,7 @@ type
|
||||||
TThreadId*[TArg] = ptr TThread[TArg] ## the current implementation uses
|
TThreadId*[TArg] = ptr TThread[TArg] ## the current implementation uses
|
||||||
## a pointer as a thread ID.
|
## a pointer as a thread ID.
|
||||||
|
|
||||||
when not defined(boehmgc) and not hasSharedHeap:
|
when not defined(boehmgc) and not hasSharedHeap and not defined(gogc):
|
||||||
proc deallocOsPages()
|
proc deallocOsPages()
|
||||||
|
|
||||||
template threadProcWrapperBody(closure: expr) {.immediate.} =
|
template threadProcWrapperBody(closure: expr) {.immediate.} =
|
||||||
|
|
@ -289,7 +289,7 @@ template threadProcWrapperBody(closure: expr) {.immediate.} =
|
||||||
var t = cast[ptr TThread[TArg]](closure)
|
var t = cast[ptr TThread[TArg]](closure)
|
||||||
when useStackMaskHack:
|
when useStackMaskHack:
|
||||||
var tls: TThreadLocalStorage
|
var tls: TThreadLocalStorage
|
||||||
when not defined(boehmgc) and not defined(nogc) and not hasSharedHeap:
|
when not defined(boehmgc) and not defined(gogc) and not defined(nogc) and not hasSharedHeap:
|
||||||
# init the GC for this thread:
|
# init the GC for this thread:
|
||||||
setStackBottom(addr(t))
|
setStackBottom(addr(t))
|
||||||
initGC()
|
initGC()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue