GCs support ForeignCells
This commit is contained in:
parent
b02e31e409
commit
ad7e219117
4 changed files with 47 additions and 0 deletions
|
|
@ -39,6 +39,9 @@ when withRealTime and not declared(getTicks):
|
||||||
when defined(memProfiler):
|
when defined(memProfiler):
|
||||||
proc nimProfile(requestedSize: int) {.benign.}
|
proc nimProfile(requestedSize: int) {.benign.}
|
||||||
|
|
||||||
|
when hasThreadSupport:
|
||||||
|
import sharedlist
|
||||||
|
|
||||||
const
|
const
|
||||||
rcIncrement = 0b1000 # so that lowest 3 bits are not touched
|
rcIncrement = 0b1000 # so that lowest 3 bits are not touched
|
||||||
rcBlack = 0b000 # cell is colored black; in use or free
|
rcBlack = 0b000 # cell is colored black; in use or free
|
||||||
|
|
@ -93,6 +96,9 @@ type
|
||||||
stat: GcStat
|
stat: GcStat
|
||||||
when useMarkForDebug or useBackupGc:
|
when useMarkForDebug or useBackupGc:
|
||||||
marked: CellSet
|
marked: CellSet
|
||||||
|
when hasThreadSupport:
|
||||||
|
toDispose: SharedList[pointer]
|
||||||
|
|
||||||
{.deprecated: [TWalkOp: WalkOp, TFinalizer: Finalizer, TGcHeap: GcHeap,
|
{.deprecated: [TWalkOp: WalkOp, TFinalizer: Finalizer, TGcHeap: GcHeap,
|
||||||
TGcStat: GcStat].}
|
TGcStat: GcStat].}
|
||||||
var
|
var
|
||||||
|
|
@ -304,6 +310,8 @@ proc initGC() =
|
||||||
init(gch.decStack)
|
init(gch.decStack)
|
||||||
when useMarkForDebug or useBackupGc:
|
when useMarkForDebug or useBackupGc:
|
||||||
init(gch.marked)
|
init(gch.marked)
|
||||||
|
when hasThreadSupport:
|
||||||
|
gch.toDispose = initSharedList[pointer]()
|
||||||
|
|
||||||
when useMarkForDebug or useBackupGc:
|
when useMarkForDebug or useBackupGc:
|
||||||
type
|
type
|
||||||
|
|
@ -749,6 +757,9 @@ proc collectRoots(gch: var GcHeap) =
|
||||||
collectWhite(s)
|
collectWhite(s)
|
||||||
|
|
||||||
proc collectCycles(gch: var GcHeap) =
|
proc collectCycles(gch: var GcHeap) =
|
||||||
|
when hasThreadSupport:
|
||||||
|
for c in gch.toDispose:
|
||||||
|
nimGCunref(c)
|
||||||
# ensure the ZCT 'color' is not used:
|
# ensure the ZCT 'color' is not used:
|
||||||
while gch.zct.len > 0: discard collectZCT(gch)
|
while gch.zct.len > 0: discard collectZCT(gch)
|
||||||
when useBackupGc:
|
when useBackupGc:
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,31 @@
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
type
|
||||||
|
ForeignCell* = object
|
||||||
|
data*: pointer
|
||||||
|
owner: ptr GcHeap
|
||||||
|
|
||||||
|
proc protect*(x: pointer): ForeignCell =
|
||||||
|
nimGCref(x)
|
||||||
|
result.data = x
|
||||||
|
result.owner = addr(gch)
|
||||||
|
|
||||||
|
proc dispose*(x: ForeignCell) =
|
||||||
|
when hasThreadSupport:
|
||||||
|
# if we own it we can free it directly:
|
||||||
|
if x.owner == addr(gch):
|
||||||
|
nimGCunref(x.data)
|
||||||
|
else:
|
||||||
|
x.owner.toDispose.add(x.data)
|
||||||
|
else:
|
||||||
|
nimGCunref(x.data)
|
||||||
|
|
||||||
|
proc isNotForeign*(x: ForeignCell): bool =
|
||||||
|
## returns true if 'x' belongs to the calling thread.
|
||||||
|
## No deep copy has to be performed then.
|
||||||
|
x.owner == addr(gch)
|
||||||
|
|
||||||
proc len(stack: ptr GcStack): int =
|
proc len(stack: ptr GcStack): int =
|
||||||
if stack == nil:
|
if stack == nil:
|
||||||
return 0
|
return 0
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,8 @@ type
|
||||||
recGcLock: int # prevent recursion via finalizers; no thread lock
|
recGcLock: int # prevent recursion via finalizers; no thread lock
|
||||||
region: MemRegion # garbage collected region
|
region: MemRegion # garbage collected region
|
||||||
stat: GcStat
|
stat: GcStat
|
||||||
|
when hasThreadSupport:
|
||||||
|
toDispose: SharedList[pointer]
|
||||||
additionalRoots: CellSeq # dummy roots for GC_ref/unref
|
additionalRoots: CellSeq # dummy roots for GC_ref/unref
|
||||||
{.deprecated: [TWalkOp: WalkOp, TFinalizer: Finalizer, TGcStat: GcStat,
|
{.deprecated: [TWalkOp: WalkOp, TFinalizer: Finalizer, TGcStat: GcStat,
|
||||||
TGlobalMarkerProc: GlobalMarkerProc, TGcHeap: GcHeap].}
|
TGlobalMarkerProc: GlobalMarkerProc, TGcHeap: GcHeap].}
|
||||||
|
|
@ -179,6 +181,8 @@ proc initGC() =
|
||||||
when withBitvectors:
|
when withBitvectors:
|
||||||
init(gch.allocated)
|
init(gch.allocated)
|
||||||
init(gch.marked)
|
init(gch.marked)
|
||||||
|
when hasThreadSupport:
|
||||||
|
gch.toDispose = initSharedList[pointer]()
|
||||||
|
|
||||||
proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: WalkOp) {.benign.} =
|
proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: WalkOp) {.benign.} =
|
||||||
var d = cast[ByteAddress](dest)
|
var d = cast[ByteAddress](dest)
|
||||||
|
|
@ -321,6 +325,9 @@ proc growObj(old: pointer, newsize: int): pointer {.rtl.} =
|
||||||
# ----------------- collector -----------------------------------------------
|
# ----------------- collector -----------------------------------------------
|
||||||
|
|
||||||
proc mark(gch: var GcHeap, c: PCell) =
|
proc mark(gch: var GcHeap, c: PCell) =
|
||||||
|
when hasThreadSupport:
|
||||||
|
for c in gch.toDispose:
|
||||||
|
nimGCunref(c)
|
||||||
when withBitvectors:
|
when withBitvectors:
|
||||||
incl(gch.marked, c)
|
incl(gch.marked, c)
|
||||||
gcAssert gch.tempStack.len == 0, "stack not empty!"
|
gcAssert gch.tempStack.len == 0, "stack not empty!"
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@
|
||||||
|
|
||||||
# Low level system locks and condition vars.
|
# Low level system locks and condition vars.
|
||||||
|
|
||||||
|
{.push stackTrace: off.}
|
||||||
|
|
||||||
when defined(Windows):
|
when defined(Windows):
|
||||||
type
|
type
|
||||||
Handle = int
|
Handle = int
|
||||||
|
|
@ -118,3 +120,5 @@ else:
|
||||||
|
|
||||||
proc deinitSysCond(cond: var SysCond) {.noSideEffect,
|
proc deinitSysCond(cond: var SysCond) {.noSideEffect,
|
||||||
importc: "pthread_cond_destroy", header: "<pthread.h>".}
|
importc: "pthread_cond_destroy", header: "<pthread.h>".}
|
||||||
|
|
||||||
|
{.pop.}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue