diff options
author | Araq <rumpf_a@web.de> | 2015-11-30 00:23:23 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2015-12-01 00:53:30 +0100 |
commit | 070403ca5eb9e7c1c9cdea5f930022408fca5000 (patch) | |
tree | cedbbcd44e64dd45018b0a975bd9fba345e12f7c | |
parent | 0d8c7624521207449f1b9194ed00084ebcb1c5f2 (diff) | |
download | Nim-070403ca5eb9e7c1c9cdea5f930022408fca5000.tar.gz |
first compiling version of the new GC
-rw-r--r-- | lib/system/gc2.nim | 63 | ||||
-rw-r--r-- | lib/system/sysstr.nim | 2 |
2 files changed, 46 insertions, 19 deletions
diff --git a/lib/system/gc2.nim b/lib/system/gc2.nim index 78901b1dc..89f299436 100644 --- a/lib/system/gc2.nim +++ b/lib/system/gc2.nim @@ -31,6 +31,12 @@ when withRealTime and not declared(getTicks): when defined(memProfiler): proc nimProfile(requestedSize: int) {.benign.} +type + ObjectSpaceIter = object + state: range[-1..0] + +iterToProc(allObjects, ptr ObjectSpaceIter, allObjectsAsProc) + const rcIncrement = 0b1000 # so that lowest 3 bits are not touched rcWhite = 0b000 # cell is colored white @@ -85,6 +91,7 @@ type region: MemRegion # garbage collected region stat: GcStat additionalRoots: CellSeq # dummy roots for GC_ref/unref + spaceIter: ObjectSpaceIter var gch {.rtlThreadVar.}: GcHeap @@ -487,6 +494,8 @@ proc newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl.} = proc growObj(old: pointer, newsize: int, gch: var GcHeap): pointer = collectCT(gch) var ol = usrToCell(old) + gcAssert(isAllocatedPtr(gch.region, ol), "growObj: freed pointer?") + sysAssert(ol.typ != nil, "growObj: 1") gcAssert(ol.typ.kind in {tyString, tySequence}, "growObj: 2") sysAssert(allocInv(gch.region), "growObj begin") @@ -547,6 +556,7 @@ proc growObj(old: pointer, newsize: int): pointer {.rtl.} = template takeStartTime(workPackageSize) {.dirty.} = const workPackage = workPackageSize + var debugticker = 1000 when withRealTime: var steps = workPackage var t0: Ticks @@ -554,8 +564,12 @@ template takeStartTime(workPackageSize) {.dirty.} = template takeTime {.dirty.} = when withRealTime: dec steps + dec debugticker template checkTime {.dirty.} = + if debugticker <= 0: + echo "in loop" + debugticker = 1000 when withRealTime: if steps == 0: steps = workPackage @@ -580,35 +594,45 @@ proc freeCyclicCell(gch: var GcHeap, c: PCell) = gcAssert(c.typ != nil, "freeCyclicCell") zeroMem(c, sizeof(Cell)) -proc sweep(gch: var GcHeap) = - # XXX make this incremental! - for x in allObjects(gch.region): +proc sweep(gch: var GcHeap): bool = + takeStartTime(100) + echo "loop start" + while true: + let x = allObjectsAsProc(gch.region, addr gch.spaceIter) + if gch.spaceIter.state < 0: break + takeTime() if isCell(x): # cast to PCell is correct here: var c = cast[PCell](x) if c.color == rcWhite: freeCyclicCell(gch, c) else: c.setColor(rcWhite) + checkTime() + # prepare for next iteration: + echo "loop end" + gch.spaceIter = ObjectSpaceIter() + result = true proc markS(gch: var GcHeap, c: PCell) = - if x.color != rcGrey: - x.setColor(rcGrey) - add(gch.greyStack, x) + if c.color != rcGrey: + c.setColor(rcGrey) + add(gch.greyStack, c) #forAllChildren(c, waMarkGrey) #x.setColor(rcBlack) -proc markIncrementally(gch: var GcHeap): bool = +proc markIncremental(gch: var GcHeap): bool = var L = addr(gch.greyStack.len) takeStartTime(100) while L[] > 0: var c = gch.greyStack.d[0] - sysAssert(isAllocatedPtr(gch.region, c), "CollectZCT: isAllocatedPtr") + sysAssert(isAllocatedPtr(gch.region, c), "markIncremental: isAllocatedPtr") gch.greyStack.d[0] = gch.greyStack.d[L[] - 1] dec(L[]) takeTime() - if c.color == clGrey: + if c.color == rcGrey: + c.setColor(rcBlack) forAllChildren(c, waMarkGrey) - c.setColor(clBlack) checkTime() + gcAssert gch.greyStack.len == 0, "markIncremental: greystack not empty " result = true proc markGlobals(gch: var GcHeap) = @@ -616,7 +640,7 @@ proc markGlobals(gch: var GcHeap) = proc markLocals(gch: var GcHeap) = var d = gch.decStack.d - for i in 0..<gch.decStack.len: + for i in 0 .. < gch.decStack.len: sysAssert isAllocatedPtr(gch.region, d[i]), "markLocals" markS(gch, d[i]) @@ -666,7 +690,7 @@ proc doOperation(p: pointer, op: WalkOp) = else: markS(gch, c) of waMarkGrey: - if x.color != rcGrey: + if c.color != rcBlack: c.setColor(rcGrey) add(gch.greyStack, c) #of waDebug: debugGraph(c) @@ -681,13 +705,16 @@ proc collectCycles(gch: var GcHeap): bool = while gch.zct.len > 0: discard collectZCT(gch) markGlobals(gch) markLocals(gch) - if markIncrementally(gch): - gch.phase = Phase.Sweeping - sweep(gch) - gch.phase = Phase.None - result = true - else: + case gch.phase + of Phase.None, Phase.Marking: gch.phase = Phase.Marking + if markIncremental(gch): + gch.phase = Phase.Sweeping + of Phase.Sweeping: + gcAssert gch.greyStack.len == 0, "greystack not empty" + if sweep(gch): + gch.phase = Phase.None + result = true proc gcMark(gch: var GcHeap, p: pointer) {.inline.} = # the addresses are not as cells on the stack, so turn them to cells: diff --git a/lib/system/sysstr.nim b/lib/system/sysstr.nim index 326c601bd..e2137e8f4 100644 --- a/lib/system/sysstr.nim +++ b/lib/system/sysstr.nim @@ -229,7 +229,7 @@ proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {. # we need to decref here, otherwise the GC leaks! when not defined(boehmGC) and not defined(nogc) and not defined(gcMarkAndSweep) and not defined(gogc): - when compileOption("gc", "v2"): + when false: # compileOption("gc", "v2"): for i in newLen..result.len-1: let len0 = gch.tempStack.len forAllChildrenAux(cast[pointer](cast[ByteAddress](result) +% |