diff options
author | Araq <rumpf_a@web.de> | 2012-01-13 12:49:06 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2012-01-13 12:49:06 +0100 |
commit | 76886432dad6df8e1a381286a918381554bab08b (patch) | |
tree | 35624eade34f07647bcf41cf456fa894ffe10662 | |
parent | 2673d73366c6e0ff36b835c16fd97799c61530a0 (diff) | |
download | Nim-76886432dad6df8e1a381286a918381554bab08b.tar.gz |
even more sys assertions
-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 | ||||
-rwxr-xr-x | tests/compile/tsortdev.nim | 39 | ||||
-rwxr-xr-x | todo.txt | 2 |
6 files changed, 68 insertions, 33 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() = diff --git a/tests/compile/tsortdev.nim b/tests/compile/tsortdev.nim index 479b8ffc0..ecfab260d 100755 --- a/tests/compile/tsortdev.nim +++ b/tests/compile/tsortdev.nim @@ -25,46 +25,35 @@ proc bubbleSort[T](a: var openArray[T], when isMainModule: proc main() = const order = Ascending - var data: seq[string] = @[] + var data: seq[string] for i in 0..10_000: - var L = 59 #random(59) - setLen(data, L) - for j in 0 .. L-1: - data[j] = "" #$(math.random(90) - 10) - when false: - #var copy = data - var copy: seq[string] - newSeq(copy, data.len) - for i in 0..data.high: copy[i] = data[i] - bubblesort(data, cmp, order) + var L = random(59) + newSeq(data, L) + for j in 0 .. L-1: + data[j] = $(math.random(90) - 10) + var copy = data + bubblesort(data, system.cmp, order) if not sorted(data, order): - #for x in items(data): echo x - break - else: - echo "SUCCESS!" - bubblesort(copy, cmp, order) + quit "bubblesort failed" + sort(copy, cmp, order) if copy.len != data.len: quit "lengths differ!" for i in 0 .. copy.high: if copy[i] != data[i]: quit "algorithms differ!" - when false: - for i in 0..10_000: - var data: seq[int] = @[] + for i in 0..10_000: + var data: seq[int] var L = random(59) - setLen(data, L) + newSeq(data, L) for j in 0 .. L-1: data[j] = (math.random(90) - 10) var copy = data sort(data, cmp[int], order) if not sorted(data, order): - #for x in items(data): echo x - break - else: - echo "SUCCESS!" - bubblesort(copy, cmp[int]) + quit "sort for seq[int] failed" + bubblesort(copy, system.cmp[int], order) if copy.len != data.len: quit "lengths differ!" for i in 0 .. copy.high: diff --git a/todo.txt b/todo.txt index 2132cc825..29aff15b0 100755 --- a/todo.txt +++ b/todo.txt @@ -1,7 +1,6 @@ version 0.8.14 ============== -- fix tsortdev bugs - fix line info in assertions version 0.9.0 @@ -46,6 +45,7 @@ Bugs without ``-d:release`` leaks memory; good way to figure out how a fixed amount of stack can hold an arbitrary number of GC roots! - BUG: temp2.nim triggers weird compiler and except.nim bug +- bug: tsortdev does not run version 0.9.XX |