more sysasserts for allocator/gc

This commit is contained in:
Araq 2012-01-12 19:44:57 +01:00
commit e6b3f50c7f
8 changed files with 38 additions and 24 deletions

View file

@ -16,7 +16,8 @@ type
proc `*`*(x: int, order: TSortOrder): int {.inline.} = proc `*`*(x: int, order: TSortOrder): int {.inline.} =
## flips `x` if ``order == Descending``; ## flips `x` if ``order == Descending``;
## if ``order == Ascending`` then `x` is returned. ## if ``order == Ascending`` then `x` is returned.
## `x` is supposed to be the result of a comparator. ## `x` is supposed to be the result of a comparator, ie ``< 0`` for
## *less than*, ``== 0`` for *equal*, ``> 0`` for *greater than*.
var y = order.ord - 1 var y = order.ord - 1
result = (x xor y) - y result = (x xor y) - y
@ -81,13 +82,21 @@ proc merge[T](a, b: var openArray[T], lo, m, hi: int,
if k < j: copyMem(addr(a[k]), addr(b[i]), sizeof(T)*(j-k)) if k < j: copyMem(addr(a[k]), addr(b[i]), sizeof(T)*(j-k))
proc sort*[T](a: var openArray[T], proc sort*[T](a: var openArray[T],
cmp: proc (x, y: T): int = cmp, cmp: proc (x, y: T): int,
order = TSortOrder.Ascending) = order = TSortOrder.Ascending) =
## Default Nimrod sort. The sorting is guaranteed to be stable and ## Default Nimrod sort. The sorting is guaranteed to be stable and
## the worst case is guaranteed to be O(n log n). ## the worst case is guaranteed to be O(n log n).
## The current implementation uses an iterative ## The current implementation uses an iterative
## mergesort to achieve this. It uses a temporary sequence of ## mergesort to achieve this. It uses a temporary sequence of
## length ``a.len div 2``. ## length ``a.len div 2``. Currently Nimrod does not support a
## sensible default argument for ``cmp``, so you have to provide one
## of your own. However, the ``system.cmp`` procs can be used:
##
## .. code-block:: nimrod
##
## sort(myIntArray, system.cmp[int])
## sort(myStrArray, system.cmp)
##
var n = a.len var n = a.len
var b: seq[T] var b: seq[T]
newSeq(b, n div 2) newSeq(b, n div 2)

View file

@ -478,6 +478,7 @@ proc getSmallChunk(a: var TMemRegion): PSmallChunk =
result = cast[PSmallChunk](res) result = cast[PSmallChunk](res)
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
proc isAllocatedPtr(a: TMemRegion, p: pointer): bool
proc rawAlloc(a: var TMemRegion, requestedSize: int): pointer = proc rawAlloc(a: var TMemRegion, requestedSize: int): pointer =
sysAssert(roundup(65, 8) == 72, "rawAlloc 1") sysAssert(roundup(65, 8) == 72, "rawAlloc 1")
@ -538,6 +539,7 @@ proc rawAlloc0(a: var TMemRegion, requestedSize: int): pointer =
zeroMem(result, requestedSize) zeroMem(result, requestedSize)
proc rawDealloc(a: var TMemRegion, p: pointer) = proc rawDealloc(a: var TMemRegion, p: pointer) =
sysAssert(isAllocatedPtr(a, p), "rawDealloc: no allocated pointer!")
var c = pageAddr(p) var c = pageAddr(p)
if isSmallChunk(c): if isSmallChunk(c):
# `p` is within a small chunk: # `p` is within a small chunk:

View file

@ -222,11 +222,8 @@ proc rtlAddZCT(c: PCell) {.rtl, inl.} =
ReleaseSys(HeapLock) ReleaseSys(HeapLock)
proc decRef(c: PCell) {.inline.} = proc decRef(c: PCell) {.inline.} =
when stressGC: sysAssert(isAllocatedPtr(gch.region, c), "decRef: interiorPtr")
if c.refcount <% rcIncrement:
writeCell("broken cell", c)
sysAssert(c.refcount >=% rcIncrement, "decRef") sysAssert(c.refcount >=% rcIncrement, "decRef")
#if c.refcount <% rcIncrement: quit("leck mich")
if --c.refcount: if --c.refcount:
rtlAddZCT(c) rtlAddZCT(c)
elif canBeCycleRoot(c): elif canBeCycleRoot(c):
@ -235,6 +232,7 @@ proc decRef(c: PCell) {.inline.} =
rtlAddCycleRoot(c) rtlAddCycleRoot(c)
proc incRef(c: PCell) {.inline.} = proc incRef(c: PCell) {.inline.} =
sysAssert(isAllocatedPtr(gch.region, c), "incRef: interiorPtr")
++c.refcount ++c.refcount
if canBeCycleRoot(c): if canBeCycleRoot(c):
rtlAddCycleRoot(c) rtlAddCycleRoot(c)
@ -500,6 +498,7 @@ proc doOperation(p: pointer, op: TWalkOp) =
sysAssert(c != nil, "doOperation: 1") sysAssert(c != nil, "doOperation: 1")
case op # faster than function pointers because of easy prediction case op # faster than function pointers because of easy prediction
of waZctDecRef: of waZctDecRef:
sysAssert(isAllocatedPtr(gch.region, c), "decRef: waZctDecRef")
sysAssert(c.refcount >=% rcIncrement, "doOperation 2") sysAssert(c.refcount >=% rcIncrement, "doOperation 2")
c.refcount = c.refcount -% rcIncrement c.refcount = c.refcount -% rcIncrement
when logGC: writeCell("decref (from doOperation)", c) when logGC: writeCell("decref (from doOperation)", c)
@ -727,8 +726,10 @@ proc CollectZCT(gch: var TGcHeap) =
var L = addr(gch.zct.len) var L = addr(gch.zct.len)
while L[] > 0: while L[] > 0:
var c = gch.zct.d[0] var c = gch.zct.d[0]
sysAssert(isAllocatedPtr(gch.region, c), "CollectZCT: isAllocatedPtr")
# remove from ZCT: # remove from ZCT:
sysAssert((c.refcount and rcZct) == rcZct, "collectZCT") sysAssert((c.refcount and rcZct) == rcZct, "collectZCT")
c.refcount = c.refcount and not colorMask c.refcount = c.refcount and not colorMask
gch.zct.d[0] = gch.zct.d[L[] - 1] gch.zct.d[0] = gch.zct.d[L[] - 1]
dec(L[]) dec(L[])

View file

@ -1,5 +1,5 @@
discard """ discard """
disabled: true disabled: false
""" """
import math, algorithm import math, algorithm
@ -12,7 +12,7 @@ proc sorted[T](a: openArray[T], order: TSortOrder): bool =
result = false result = false
proc bubbleSort[T](a: var openArray[T], proc bubbleSort[T](a: var openArray[T],
cmp: proc (x, y: T): int = cmp, cmp: proc (x, y: T): int,
order = TSortOrder.Ascending) = order = TSortOrder.Ascending) =
while true: while true:
var sorted = true var sorted = true
@ -28,12 +28,16 @@ when isMainModule:
var data: seq[string] = @[] var data: seq[string] = @[]
for i in 0..10_000: for i in 0..10_000:
var L = random(59) var L = 59 #random(59)
setLen(data, L) setLen(data, L)
for j in 0 .. L-1: for j in 0 .. L-1:
data[j] = $(math.random(90) - 10) data[j] = "" #$(math.random(90) - 10)
var copy = data when false:
sort(data, cmp, order) #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)
if not sorted(data, order): if not sorted(data, order):
#for x in items(data): echo x #for x in items(data): echo x
break break
@ -46,6 +50,7 @@ when isMainModule:
if copy[i] != data[i]: if copy[i] != data[i]:
quit "algorithms differ!" quit "algorithms differ!"
when false:
for i in 0..10_000: for i in 0..10_000:
var data: seq[int] = @[] var data: seq[int] = @[]
var L = random(59) var L = random(59)
@ -59,7 +64,7 @@ when isMainModule:
break break
else: else:
echo "SUCCESS!" echo "SUCCESS!"
bubblesort(copy) bubblesort(copy, cmp[int])
if copy.len != data.len: if copy.len != data.len:
quit "lengths differ!" quit "lengths differ!"
for i in 0 .. copy.high: for i in 0 .. copy.high:

View file

@ -1,21 +1,17 @@
version 0.8.14 version 0.8.14
============== ==============
- fix memory corruption bug triggered by visual c++ in release mode: - fix tsortdev bugs
* sysasserts in incref
* force full collection in ccgstmts.nim
- fix line info in assertions - fix line info in assertions
- fix remaining generics bugs
version 0.9.0 version 0.9.0
============= =============
- fix remaining generics bugs
- GC: marker procs for native Nimrod GC and Boehm GC; precise stack marking; - GC: marker procs for native Nimrod GC and Boehm GC; precise stack marking;
escape analysis for string/seq seems to be easy to do too; escape analysis for string/seq seems to be easy to do too;
even further write barrier specialization even further write barrier specialization
- dead code elim for JS backend; 'of' operator for JS backend - dead code elim for JS backend; 'of' operator for JS backend
- test the sort implementation again
- const ptr/ref - const ptr/ref
- unsigned ints and bignums; requires abstract integer literal type: - unsigned ints and bignums; requires abstract integer literal type:
use tyInt+node for that use tyInt+node for that

View file

@ -146,6 +146,7 @@ Library Additions
- Added ``memfiles`` module. - Added ``memfiles`` module.
- Added ``subexes`` module. - Added ``subexes`` module.
- Added ``critbits`` module. - Added ``critbits`` module.
- Added ``algorithm`` module for generic ``sort``, ``reverse`` etc. operations.
- Added ``osproc.startCmd``, ``osproc.execCmdEx``. - Added ``osproc.startCmd``, ``osproc.execCmdEx``.
- The ``osproc`` module now uses ``posix_spawn`` instead of ``fork`` - The ``osproc`` module now uses ``posix_spawn`` instead of ``fork``
and ``exec`` on Posix systems. Define the symbol ``useFork`` to revert to and ``exec`` on Posix systems. Define the symbol ``useFork`` to revert to

View file

@ -27,7 +27,7 @@ pdf: "manual;lib;tut1;tut2;nimrodc;c2nim;niminst"
srcdoc: "core/macros;pure/marshal;core/typeinfo" srcdoc: "core/macros;pure/marshal;core/typeinfo"
srcdoc: "impure/graphics;impure/re;pure/sockets" srcdoc: "impure/graphics;impure/re;pure/sockets"
srcdoc: "system.nim;system/threads.nim;system/channels.nim" srcdoc: "system.nim;system/threads.nim;system/channels.nim"
srcdoc: "pure/os;pure/strutils;pure/math;pure/matchers" srcdoc: "pure/os;pure/strutils;pure/math;pure/matchers;pure/algorithm"
srcdoc: "pure/complex;pure/times;pure/osproc;pure/pegs;pure/dynlib" srcdoc: "pure/complex;pure/times;pure/osproc;pure/pegs;pure/dynlib"
srcdoc: "pure/parseopt;pure/hashes;pure/strtabs;pure/lexbase" srcdoc: "pure/parseopt;pure/hashes;pure/strtabs;pure/lexbase"
srcdoc: "pure/parsecfg;pure/parsexml;pure/parsecsv;pure/parsesql" srcdoc: "pure/parsecfg;pure/parsexml;pure/parsecsv;pure/parsesql"