summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2012-01-13 12:49:06 +0100
committerAraq <rumpf_a@web.de>2012-01-13 12:49:06 +0100
commit76886432dad6df8e1a381286a918381554bab08b (patch)
tree35624eade34f07647bcf41cf456fa894ffe10662
parent2673d73366c6e0ff36b835c16fd97799c61530a0 (diff)
downloadNim-76886432dad6df8e1a381286a918381554bab08b.tar.gz
even more sys assertions
-rwxr-xr-xlib/pure/algorithm.nim3
-rwxr-xr-xlib/system.nim8
-rwxr-xr-xlib/system/alloc.nim24
-rwxr-xr-xlib/system/gc.nim25
-rwxr-xr-xtests/compile/tsortdev.nim39
-rwxr-xr-xtodo.txt2
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