diff options
Diffstat (limited to 'lib')
-rwxr-xr-x | lib/pure/algorithm.nim | 3 | ||||
-rwxr-xr-x | lib/system.nim | 8 | ||||
-rwxr-xr-x | lib/system/alloc.nim | 24 | ||||
-rwxr-xr-x | lib/system/gc.nim | 25 |
4 files changed, 53 insertions, 7 deletions
diff --git a/lib/pure/algorithm.nim b/lib/pure/algorithm.nim index f283b434c..0244c9fce 100755 --- a/lib/pure/algorithm.nim +++ b/lib/pure/algorithm.nim @@ -95,6 +95,9 @@ proc sort*[T](a: var openArray[T], ## .. code-block:: nimrod ## ## sort(myIntArray, system.cmp[int]) + ## + ## # do not use cmp[string] here as we want to use the specialized + ## # overload: ## sort(myStrArray, system.cmp) ## var n = a.len diff --git a/lib/system.nim b/lib/system.nim index c073bff92..334904056 100755 --- a/lib/system.nim +++ b/lib/system.nim @@ -832,10 +832,10 @@ proc quit*(errorcode: int = QuitSuccess) {. ## unless a quit procedure calls ``GC_collect``. template sysAssert(cond, msg: expr) = - # change this to activate system asserts - #if not cond: - # echo "[SYSASSERT] ", msg - # quit 1 + when defined(useSysAssert): + if not cond: + echo "[SYSASSERT] ", msg + quit 1 nil include "system/inclrtl" diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim index 6fd9efebd..f2603586e 100755 --- a/lib/system/alloc.nim +++ b/lib/system/alloc.nim @@ -480,7 +480,22 @@ proc getSmallChunk(a: var TMemRegion): PSmallChunk = # ----------------------------------------------------------------------------- proc isAllocatedPtr(a: TMemRegion, p: pointer): bool +proc allocInv(a: TMemRegion): bool = + ## checks some (not all yet) invariants of the allocator's data structures. + for s in low(a.freeSmallChunks)..high(a.freeSmallChunks): + var c = a.freeSmallChunks[s] + while c != nil: + if c.next == c: return false + if c.size != s * MemAlign: return false + var it = c.freeList + while it != nil: + if it.zeroField != 0: return false + it = it.next + c = c.next + result = true + proc rawAlloc(a: var TMemRegion, requestedSize: int): pointer = + sysAssert(allocInv(a), "rawAlloc: begin") sysAssert(roundup(65, 8) == 72, "rawAlloc 1") sysAssert requestedSize >= sizeof(TFreeCell), "rawAlloc 2" var size = roundup(requestedSize, MemAlign) @@ -502,6 +517,7 @@ proc rawAlloc(a: var TMemRegion, requestedSize: int): pointer = result = addr(c.data) sysAssert((cast[TAddress](result) and (MemAlign-1)) == 0, "rawAlloc 4") else: + sysAssert(allocInv(a), "rawAlloc: begin c != nil") sysAssert c.next != c, "rawAlloc 5" #if c.size != size: # c_fprintf(c_stdout, "csize: %lld; size %lld\n", c.size, size) @@ -517,10 +533,15 @@ proc rawAlloc(a: var TMemRegion, requestedSize: int): pointer = c.freeList = c.freeList.next dec(c.free, size) sysAssert((cast[TAddress](result) and (MemAlign-1)) == 0, "rawAlloc 9") + sysAssert(allocInv(a), "rawAlloc: end c != nil") + sysAssert(allocInv(a), "rawAlloc: before c.free < size") if c.free < size: + sysAssert(allocInv(a), "rawAlloc: before listRemove test") ListRemove(a.freeSmallChunks[s], c) + sysAssert(allocInv(a), "rawAlloc: end listRemove test") sysAssert(((cast[TAddress](result) and PageMask) -% smallChunkOverhead()) %% size == 0, "rawAlloc 21") + sysAssert(allocInv(a), "rawAlloc: end small size") else: size = roundup(requestedSize+bigChunkOverhead(), PageSize) # allocate a large block @@ -533,12 +554,14 @@ proc rawAlloc(a: var TMemRegion, requestedSize: int): pointer = if a.root == nil: a.root = bottom add(a, a.root, cast[TAddress](result), cast[TAddress](result)+%size) sysAssert(isAccessible(a, result), "rawAlloc 14") + sysAssert(allocInv(a), "rawAlloc: end") proc rawAlloc0(a: var TMemRegion, requestedSize: int): pointer = result = rawAlloc(a, requestedSize) zeroMem(result, requestedSize) proc rawDealloc(a: var TMemRegion, p: pointer) = + sysAssert(allocInv(a), "rawDealloc: begin") sysAssert(isAllocatedPtr(a, p), "rawDealloc: no allocated pointer!") var c = pageAddr(p) if isSmallChunk(c): @@ -578,6 +601,7 @@ proc rawDealloc(a: var TMemRegion, p: pointer) = a.deleted = bottom del(a, a.root, cast[int](addr(c.data))) freeBigChunk(a, c) + sysAssert(allocInv(a), "rawDealloc: end") proc isAllocatedPtr(a: TMemRegion, p: pointer): bool = if isAccessible(a, p): diff --git a/lib/system/gc.nim b/lib/system/gc.nim index 2ac61fca0..077f94905 100755 --- a/lib/system/gc.nim +++ b/lib/system/gc.nim @@ -241,9 +241,13 @@ proc nimGCref(p: pointer) {.compilerProc, inline.} = incRef(usrToCell(p)) proc nimGCunref(p: pointer) {.compilerProc, inline.} = decRef(usrToCell(p)) proc nimGCunrefNoCycle(p: pointer) {.compilerProc, inline.} = + sysAssert(allocInv(gch.region), "begin nimGCunrefNoCycle") var c = usrToCell(p) + sysAssert(isAllocatedPtr(gch.region, c), "nimGCunrefNoCycle: isAllocatedPtr") if --c.refcount: rtlAddZCT(c) + sysAssert(allocInv(gch.region), "end nimGCunrefNoCycle 2") + sysAssert(allocInv(gch.region), "end nimGCunrefNoCycle 5") proc asgnRef(dest: ppointer, src: pointer) {.compilerProc, inline.} = # the code generator calls this proc! @@ -393,6 +397,7 @@ proc rawNewObj(typ: PNimType, size: int, gch: var TGcHeap): pointer = acquire(gch) sysAssert(typ.kind in {tyRef, tyString, tySequence}, "newObj: 1") collectCT(gch) + sysAssert(allocInv(gch.region), "rawNewObj begin") var res = cast[PCell](rawAlloc(gch.region, size + sizeof(TCell))) sysAssert((cast[TAddress](res) and (MemAlign-1)) == 0, "newObj: 2") # now it is buffered in the ZCT @@ -409,6 +414,7 @@ proc rawNewObj(typ: PNimType, size: int, gch: var TGcHeap): pointer = gcTrace(res, csAllocated) release(gch) result = cellToUsr(res) + sysAssert(allocInv(gch.region), "rawNewObj end") proc newObj(typ: PNimType, size: int): pointer {.compilerRtl.} = result = rawNewObj(typ, size, gch) @@ -422,10 +428,14 @@ proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.} = proc newObjRC1(typ: PNimType, size: int): pointer {.compilerRtl.} = # generates a new object and sets its reference counter to 1 + sysAssert(allocInv(gch.region), "newObjRC1 begin") acquire(gch) sysAssert(typ.kind in {tyRef, tyString, tySequence}, "newObj: 1") collectCT(gch) + sysAssert(allocInv(gch.region), "newObjRC1 after collectCT") + var res = cast[PCell](rawAlloc(gch.region, size + sizeof(TCell))) + sysAssert(allocInv(gch.region), "newObjRC1 after rawAlloc") sysAssert((cast[TAddress](res) and (MemAlign-1)) == 0, "newObj: 2") # now it is buffered in the ZCT res.typ = typ @@ -440,6 +450,7 @@ proc newObjRC1(typ: PNimType, size: int): pointer {.compilerRtl.} = release(gch) result = cellToUsr(res) zeroMem(result, size) + sysAssert(allocInv(gch.region), "newObjRC1 end") proc newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl.} = result = newObjRC1(typ, addInt(mulInt(len, typ.base.size), GenericSeqSize)) @@ -452,14 +463,16 @@ proc growObj(old: pointer, newsize: int, gch: var TGcHeap): pointer = var ol = usrToCell(old) sysAssert(ol.typ != nil, "growObj: 1") sysAssert(ol.typ.kind in {tyString, tySequence}, "growObj: 2") - var res = cast[PCell](rawAlloc(gch.region, newsize + sizeof(TCell))) + sysAssert(allocInv(gch.region), "growObj begin") + + var res = cast[PCell](rawAlloc0(gch.region, newsize + sizeof(TCell))) var elemSize = 1 if ol.typ.kind != tyString: elemSize = ol.typ.base.size var oldsize = cast[PGenericSeq](old).len*elemSize + GenericSeqSize copyMem(res, ol, oldsize + sizeof(TCell)) - zeroMem(cast[pointer](cast[TAddress](res)+% oldsize +% sizeof(TCell)), - newsize-oldsize) + #zeroMem(cast[pointer](cast[TAddress](res)+% oldsize +% sizeof(TCell)), + # newsize-oldsize) sysAssert((cast[TAddress](res) and (MemAlign-1)) == 0, "growObj: 3") sysAssert(res.refcount shr rcShift <=% 1, "growObj: 4") #if res.refcount <% rcIncrement: @@ -486,6 +499,7 @@ proc growObj(old: pointer, newsize: int, gch: var TGcHeap): pointer = zeroMem(ol, sizeof(TCell)) release(gch) result = cellToUsr(res) + sysAssert(allocInv(gch.region), "growObj end") proc growObj(old: pointer, newsize: int): pointer {.rtl.} = result = growObj(old, newsize, gch) @@ -556,6 +570,7 @@ proc collectCycles(gch: var TGcHeap) = proc gcMark(gch: var TGcHeap, p: pointer) {.inline.} = # the addresses are not as cells on the stack, so turn them to cells: + sysAssert(allocInv(gch.region), "gcMark begin") var cell = usrToCell(p) var c = cast[TAddress](cell) if c >% PageSize: @@ -571,6 +586,7 @@ proc gcMark(gch: var TGcHeap, p: pointer) {.inline.} = # mark the cell: cell.refcount = cell.refcount +% rcIncrement add(gch.decStack, cell) + sysAssert(allocInv(gch.region), "gcMark end") proc nimKeepAlive(p: PGenericSeq) {.compilerRtl, noinline.} = var c = usrToCell(p) @@ -769,6 +785,8 @@ proc collectCT(gch: var TGcHeap) = if (gch.zct.len >= ZctThreshold or (cycleGC and getOccupiedMem(gch.region) >= gch.cycleThreshold) or stressGC) and gch.recGcLock == 0: + sysAssert(allocInv(gch.region), "collectCT: begin") + gch.stat.maxStackSize = max(gch.stat.maxStackSize, stackSize()) sysAssert(gch.decStack.len == 0, "collectCT") prepareForInteriorPointerChecking(gch.region) @@ -786,6 +804,7 @@ proc collectCT(gch: var TGcHeap) = cycleIncrease) gch.stat.maxThreshold = max(gch.stat.maxThreshold, gch.cycleThreshold) unmarkStackAndRegisters(gch) + sysAssert(allocInv(gch.region), "collectCT: end") when not defined(useNimRtl): proc GC_disable() = |