diff options
Diffstat (limited to 'lib/system/gc.nim')
-rw-r--r-- | lib/system/gc.nim | 92 |
1 files changed, 12 insertions, 80 deletions
diff --git a/lib/system/gc.nim b/lib/system/gc.nim index 74ac68eea..fb20edbbb 100644 --- a/lib/system/gc.nim +++ b/lib/system/gc.nim @@ -100,14 +100,6 @@ var when not defined(useNimRtl): instantiateForRegion(gch.region) -template acquire(gch: GcHeap) = - when hasThreadSupport and hasSharedHeap: - acquireSys(HeapLock) - -template release(gch: GcHeap) = - when hasThreadSupport and hasSharedHeap: - releaseSys(HeapLock) - template gcAssert(cond: bool, msg: string) = when defined(useGcAssert): if not cond: @@ -177,15 +169,6 @@ proc doOperation(p: pointer, op: WalkOp) {.benign.} proc forAllChildrenAux(dest: pointer, mt: PNimType, op: WalkOp) {.benign.} # we need the prototype here for debugging purposes -when hasThreadSupport and hasSharedHeap: - template `--`(x: untyped): untyped = atomicDec(x, rcIncrement) <% rcIncrement - template `++`(x: untyped) = discard atomicInc(x, rcIncrement) -else: - template `--`(x: untyped): untyped = - dec(x, rcIncrement) - x <% rcIncrement - template `++`(x: untyped) = inc(x, rcIncrement) - proc incRef(c: PCell) {.inline.} = gcAssert(isAllocatedPtr(gch.region, c), "incRef: interiorPtr") c.refcount = c.refcount +% rcIncrement @@ -194,28 +177,19 @@ proc incRef(c: PCell) {.inline.} = proc nimGCref(p: pointer) {.compilerProc.} = # we keep it from being collected by pretending it's not even allocated: - add(gch.additionalRoots, usrToCell(p)) - incRef(usrToCell(p)) - -proc rtlAddCycleRoot(c: PCell) {.rtl, inl.} = - # we MUST access gch as a global here, because this crosses DLL boundaries! - when hasThreadSupport and hasSharedHeap: - acquireSys(HeapLock) - when hasThreadSupport and hasSharedHeap: - releaseSys(HeapLock) + let c = usrToCell(p) + add(gch.additionalRoots, c) + incRef(c) proc rtlAddZCT(c: PCell) {.rtl, inl.} = # we MUST access gch as a global here, because this crosses DLL boundaries! - when hasThreadSupport and hasSharedHeap: - acquireSys(HeapLock) addZCT(gch.zct, c) - when hasThreadSupport and hasSharedHeap: - releaseSys(HeapLock) proc decRef(c: PCell) {.inline.} = gcAssert(isAllocatedPtr(gch.region, c), "decRef: interiorPtr") gcAssert(c.refcount >=% rcIncrement, "decRef") - if --c.refcount: + c.refcount = c.refcount -% rcIncrement + if c.refcount <% rcIncrement: rtlAddZCT(c) proc nimGCunref(p: pointer) {.compilerProc.} = @@ -239,19 +213,9 @@ template beforeDealloc(gch: var GcHeap; c: PCell; msg: typed) = if gch.decStack.d[i] == c: sysAssert(false, msg) -proc GC_addCycleRoot*[T](p: ref T) {.inline.} = - ## adds 'p' to the cycle candidate set for the cycle collector. It is - ## necessary if you used the 'acyclic' pragma for optimization - ## purposes and need to break cycles manually. - rtlAddCycleRoot(usrToCell(cast[pointer](p))) - proc nimGCunrefNoCycle(p: pointer) {.compilerProc, inline.} = sysAssert(allocInv(gch.region), "begin nimGCunrefNoCycle") - var c = usrToCell(p) - gcAssert(isAllocatedPtr(gch.region, c), "nimGCunrefNoCycle: isAllocatedPtr") - if --c.refcount: - rtlAddZCT(c) - sysAssert(allocInv(gch.region), "end nimGCunrefNoCycle 2") + decRef(usrToCell(p)) sysAssert(allocInv(gch.region), "end nimGCunrefNoCycle 5") proc nimGCunrefRC1(p: pointer) {.compilerProc, inline.} = @@ -265,17 +229,8 @@ proc asgnRef(dest: PPointer, src: pointer) {.compilerProc, inline.} = if dest[] != nil: decRef(usrToCell(dest[])) dest[] = src -proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerProc, inline.} = - # the code generator calls this proc if it is known at compile time that no - # cycle is possible. - if src != nil: - var c = usrToCell(src) - ++c.refcount - if dest[] != nil: - var c = usrToCell(dest[]) - if --c.refcount: - rtlAddZCT(c) - dest[] = src +proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline, + deprecated: "old compiler compat".} = asgnRef(dest, src) proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerProc.} = # unsureAsgnRef updates the reference counters only if dest is not on the @@ -440,7 +395,6 @@ proc rawNewObj(typ: PNimType, size: int, gch: var GcHeap): pointer = # generates a new object and sets its reference counter to 0 incTypeSize typ, size sysAssert(allocInv(gch.region), "rawNewObj begin") - acquire(gch) gcAssert(typ.kind in {tyRef, tyOptAsRef, tyString, tySequence}, "newObj: 1") collectCT(gch) var res = cast[PCell](rawAlloc(gch.region, size + sizeof(Cell))) @@ -457,7 +411,6 @@ proc rawNewObj(typ: PNimType, size: int, gch: var GcHeap): pointer = when logGC: writeCell("new cell", res) track("rawNewObj", res, size) gcTrace(res, csAllocated) - release(gch) when useCellIds: inc gch.idGenerator res.id = gch.idGenerator * 1000_000 + gch.gcThreadId @@ -488,7 +441,6 @@ proc newObjRC1(typ: PNimType, size: int): pointer {.compilerRtl.} = # generates a new object and sets its reference counter to 1 incTypeSize typ, size sysAssert(allocInv(gch.region), "newObjRC1 begin") - acquire(gch) gcAssert(typ.kind in {tyRef, tyOptAsRef, tyString, tySequence}, "newObj: 1") collectCT(gch) sysAssert(allocInv(gch.region), "newObjRC1 after collectCT") @@ -504,7 +456,6 @@ proc newObjRC1(typ: PNimType, size: int): pointer {.compilerRtl.} = when logGC: writeCell("new cell", res) track("newObjRC1", res, size) gcTrace(res, csAllocated) - release(gch) when useCellIds: inc gch.idGenerator res.id = gch.idGenerator * 1000_000 + gch.gcThreadId @@ -521,7 +472,6 @@ proc newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl.} = when defined(memProfiler): nimProfile(size) proc growObj(old: pointer, newsize: int, gch: var GcHeap): pointer = - acquire(gch) collectCT(gch) var ol = usrToCell(old) sysAssert(ol.typ != nil, "growObj: 1") @@ -577,7 +527,6 @@ proc growObj(old: pointer, newsize: int, gch: var GcHeap): pointer = else: sysAssert(ol.typ != nil, "growObj: 5") zeroMem(ol, sizeof(Cell)) - release(gch) when useCellIds: inc gch.idGenerator res.id = gch.idGenerator * 1000_000 + gch.gcThreadId @@ -665,11 +614,9 @@ proc doOperation(p: pointer, op: WalkOp) = # c_fprintf(stdout, "[GC] decref bug: %p", c) gcAssert(isAllocatedPtr(gch.region, c), "decRef: waZctDecRef") gcAssert(c.refcount >=% rcIncrement, "doOperation 2") - #c.refcount = c.refcount -% rcIncrement when logGC: writeCell("decref (from doOperation)", c) track("waZctDecref", p, 0) decRef(c) - #if c.refcount <% rcIncrement: addZCT(gch.zct, c) of waPush: add(gch.tempStack, c) of waMarkGlobal: @@ -707,13 +654,13 @@ proc gcMark(gch: var GcHeap, p: pointer) {.inline.} = var objStart = cast[PCell](interiorAllocatedPtr(gch.region, cell)) if objStart != nil: # mark the cell: - objStart.refcount = objStart.refcount +% rcIncrement + incRef(objStart) add(gch.decStack, objStart) when false: if isAllocatedPtr(gch.region, cell): sysAssert false, "allocated pointer but not interior?" # mark the cell: - cell.refcount = cell.refcount +% rcIncrement + incRef(cell) add(gch.decStack, cell) sysAssert(allocInv(gch.region), "gcMark end") @@ -787,11 +734,6 @@ proc unmarkStackAndRegisters(gch: var GcHeap) = for i in 0..gch.decStack.len-1: sysAssert isAllocatedPtr(gch.region, d[i]), "unmarkStackAndRegisters" decRef(d[i]) - #var c = d[i] - # XXX no need for an atomic dec here: - #if --c.refcount: - # addZCT(gch.zct, c) - #sysAssert c.typ != nil, "unmarkStackAndRegisters 2" gch.decStack.len = 0 proc collectCTBody(gch: var GcHeap) = @@ -850,13 +792,11 @@ when withRealTime: gch.maxPause = MaxPauseInUs.toNano proc GC_step(gch: var GcHeap, us: int, strongAdvice: bool) = - acquire(gch) gch.maxPause = us.toNano if (gch.zct.len >= ZctThreshold or (cycleGC and getOccupiedMem(gch.region)>=gch.cycleThreshold) or alwaysGC) or strongAdvice: collectCTBody(gch) - release(gch) proc GC_step*(us: int, strongAdvice = false, stackSize = -1) {.noinline.} = if stackSize >= 0: @@ -880,18 +820,12 @@ when withRealTime: when not defined(useNimRtl): proc GC_disable() = - when hasThreadSupport and hasSharedHeap: - discard atomicInc(gch.recGcLock, 1) - else: - inc(gch.recGcLock) + inc(gch.recGcLock) proc GC_enable() = if gch.recGcLock <= 0: raise newException(AssertionError, "API usage error: GC_enable called but GC is already enabled") - when hasThreadSupport and hasSharedHeap: - discard atomicDec(gch.recGcLock, 1) - else: - dec(gch.recGcLock) + dec(gch.recGcLock) proc GC_setStrategy(strategy: GC_Strategy) = discard @@ -904,12 +838,10 @@ when not defined(useNimRtl): # set to the max value to suppress the cycle detector proc GC_fullCollect() = - acquire(gch) var oldThreshold = gch.cycleThreshold gch.cycleThreshold = 0 # forces cycle collection collectCT(gch) gch.cycleThreshold = oldThreshold - release(gch) proc GC_getStatistics(): string = result = "[GC] total memory: " & $(getTotalMem()) & "\n" & |