even more sys assertions
This commit is contained in:
parent
2673d73366
commit
76886432da
6 changed files with 68 additions and 33 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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() =
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
2
todo.txt
2
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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue