GC: even more stress testing

This commit is contained in:
Araq 2013-10-31 22:32:27 +01:00
commit f73cec7f01
4 changed files with 30 additions and 9 deletions

View file

@ -13,7 +13,7 @@ Introduction
This document describes how the GC works and how to tune it for This document describes how the GC works and how to tune it for
(soft) `realtime systems`:idx:. (soft) `realtime systems`:idx:.
The basic algorithm is *Deferrent Reference Counting* with cycle detection. The basic algorithm is *Deferred Reference Counting* with cycle detection.
References on the stack are not counted for better performance (and easier C References on the stack are not counted for better performance (and easier C
code generation). The GC **never** scans the whole heap but it may scan the code generation). The GC **never** scans the whole heap but it may scan the
delta-subgraph of the heap that changed since its last run. delta-subgraph of the heap that changed since its last run.

View file

@ -520,11 +520,18 @@ proc allocInv(a: TMemRegion): bool =
for s in low(a.freeSmallChunks)..high(a.freeSmallChunks): for s in low(a.freeSmallChunks)..high(a.freeSmallChunks):
var c = a.freeSmallChunks[s] var c = a.freeSmallChunks[s]
while c != nil: while c != nil:
if c.next == c: return false if c.next == c:
if c.size != s * MemAlign: return false echo "[SYSASSERT] c.next == c"
return false
if c.size != s * MemAlign:
echo "[SYSASSERT] c.size != s * MemAlign"
return false
var it = c.freeList var it = c.freeList
while it != nil: while it != nil:
if it.zeroField != 0: return false if it.zeroField != 0:
echo "[SYSASSERT] it.zeroField != 0"
cprintf("%ld %p\n", it.zeroField, it)
return false
it = it.next it = it.next
c = c.next c = c.next
result = true result = true
@ -591,6 +598,7 @@ proc rawAlloc(a: var TMemRegion, requestedSize: int): pointer =
add(a, a.root, cast[TAddress](result), cast[TAddress](result)+%size) add(a, a.root, cast[TAddress](result), cast[TAddress](result)+%size)
sysAssert(isAccessible(a, result), "rawAlloc 14") sysAssert(isAccessible(a, result), "rawAlloc 14")
sysAssert(allocInv(a), "rawAlloc: end") sysAssert(allocInv(a), "rawAlloc: end")
when logAlloc: cprintf("rawAlloc: %ld %p\n", requestedSize, result)
proc rawAlloc0(a: var TMemRegion, requestedSize: int): pointer = proc rawAlloc0(a: var TMemRegion, requestedSize: int): pointer =
result = rawAlloc(a, requestedSize) result = rawAlloc(a, requestedSize)
@ -638,6 +646,7 @@ proc rawDealloc(a: var TMemRegion, p: pointer) =
del(a, a.root, cast[int](addr(c.data))) del(a, a.root, cast[int](addr(c.data)))
freeBigChunk(a, c) freeBigChunk(a, c)
sysAssert(allocInv(a), "rawDealloc: end") sysAssert(allocInv(a), "rawDealloc: end")
when logAlloc: cprintf("rawDealloc: %p\n", p)
proc isAllocatedPtr(a: TMemRegion, p: pointer): bool = proc isAllocatedPtr(a: TMemRegion, p: pointer): bool =
if isAccessible(a, p): if isAccessible(a, p):

View file

@ -9,7 +9,7 @@
# Garbage Collector # Garbage Collector
# #
# The basic algorithm is *Deferrent Reference Counting* with cycle detection. # The basic algorithm is *Deferred Reference Counting* with cycle detection.
# This is achieved by combining a Deutsch-Bobrow garbage collector # This is achieved by combining a Deutsch-Bobrow garbage collector
# together with Christoper's partial mark-sweep garbage collector. # together with Christoper's partial mark-sweep garbage collector.
# #
@ -407,12 +407,17 @@ proc addNewObjToZCT(res: PCell, gch: var TGcHeap) {.inline.} =
return return
add(gch.zct, res) add(gch.zct, res)
{.push stackTrace: off, profiler:off.}
proc gcInvariant*(msg: string) =
sysAssert(allocInv(gch.region), msg)
{.pop.}
proc rawNewObj(typ: PNimType, size: int, gch: var TGcHeap): pointer = proc rawNewObj(typ: PNimType, size: int, gch: var TGcHeap): pointer =
# generates a new object and sets its reference counter to 0 # generates a new object and sets its reference counter to 0
sysAssert(allocInv(gch.region), "rawNewObj begin")
acquire(gch) acquire(gch)
gcAssert(typ.kind in {tyRef, tyString, tySequence}, "newObj: 1") gcAssert(typ.kind in {tyRef, tyString, tySequence}, "newObj: 1")
collectCT(gch) collectCT(gch)
sysAssert(allocInv(gch.region), "rawNewObj begin")
var res = cast[PCell](rawAlloc(gch.region, size + sizeof(TCell))) var res = cast[PCell](rawAlloc(gch.region, size + sizeof(TCell)))
gcAssert((cast[TAddress](res) and (MemAlign-1)) == 0, "newObj: 2") gcAssert((cast[TAddress](res) and (MemAlign-1)) == 0, "newObj: 2")
# now it is buffered in the ZCT # now it is buffered in the ZCT
@ -517,7 +522,9 @@ proc growObj(old: pointer, newsize: int, gch: var TGcHeap): pointer =
writeCell("growObj new cell", res) writeCell("growObj new cell", res)
gcTrace(ol, csZctFreed) gcTrace(ol, csZctFreed)
gcTrace(res, csAllocated) gcTrace(res, csAllocated)
when reallyDealloc: rawDealloc(gch.region, ol) when reallyDealloc:
sysAssert(allocInv(gch.region), "growObj before dealloc")
rawDealloc(gch.region, ol)
else: else:
sysAssert(ol.typ != nil, "growObj: 5") sysAssert(ol.typ != nil, "growObj: 5")
zeroMem(ol, sizeof(TCell)) zeroMem(ol, sizeof(TCell))
@ -537,7 +544,9 @@ proc freeCyclicCell(gch: var TGcHeap, c: PCell) =
prepareDealloc(c) prepareDealloc(c)
gcTrace(c, csCycFreed) gcTrace(c, csCycFreed)
when logGC: writeCell("cycle collector dealloc cell", c) when logGC: writeCell("cycle collector dealloc cell", c)
when reallyDealloc: rawDealloc(gch.region, c) when reallyDealloc:
sysAssert(allocInv(gch.region), "free cyclic cell")
rawDealloc(gch.region, c)
else: else:
gcAssert(c.typ != nil, "freeCyclicCell") gcAssert(c.typ != nil, "freeCyclicCell")
zeroMem(c, sizeof(TCell)) zeroMem(c, sizeof(TCell))
@ -910,7 +919,9 @@ proc collectZCT(gch: var TGcHeap): bool =
# access invalid memory. This is done by prepareDealloc(): # access invalid memory. This is done by prepareDealloc():
prepareDealloc(c) prepareDealloc(c)
forAllChildren(c, waZctDecRef) forAllChildren(c, waZctDecRef)
when reallyDealloc: rawDealloc(gch.region, c) when reallyDealloc:
sysAssert(allocInv(gch.region), "collectZCT: rawDealloc")
rawDealloc(gch.region, c)
else: else:
sysAssert(c.typ != nil, "collectZCT 2") sysAssert(c.typ != nil, "collectZCT 2")
zeroMem(c, sizeof(TCell)) zeroMem(c, sizeof(TCell))

View file

@ -28,6 +28,7 @@ const
reallyOsDealloc = true reallyOsDealloc = true
coalescRight = true coalescRight = true
coalescLeft = true coalescLeft = true
logAlloc = false
type type
PPointer = ptr pointer PPointer = ptr pointer