gc tweaking to gain a few percent of performance

This commit is contained in:
Araq
2011-05-07 22:13:24 +02:00
parent 7d2b3dd6db
commit 73c3551766
13 changed files with 183 additions and 153 deletions

View File

@@ -677,8 +677,8 @@ proc genProcAux(m: BModule, prc: PSym) =
if optStackTrace in prc.options: app(generatedProc, deinitFrame(p))
if (optProfiler in prc.options) and (gCmd != cmdCompileToLLVM):
appf(generatedProc,
"profileData[$1].total += elapsed(getticks(), NIM_profilingStart);$n",
[toRope(prc.loc.a)])
"profileData[$1].total += elapsed(getticks(), NIM_profilingStart);$n",
[toRope(prc.loc.a)])
app(generatedProc, returnStmt)
app(generatedProc, '}' & tnl)
app(m.s[cfsProcs], generatedProc)

View File

@@ -100,19 +100,16 @@ proc crcFromBuf(buf: Pointer, length: int): TCrc32 =
proc crcFromFile(filename: string): TCrc32 =
const
bufSize = 8 * 1024
bufSize = 8000 # don't use 8K for the memory allocator!
var
bin: tfile
buf: Pointer
readBytes: int
p: PByteArray
result = InitCrc32
if not open(bin, filename):
return # not equal if file does not exist
buf = alloc(BufSize)
p = cast[PByteArray](buf)
var buf = alloc(BufSize)
var p = cast[PByteArray](buf)
while true:
readBytes = readBuffer(bin, buf, bufSize)
var readBytes = readBuffer(bin, buf, bufSize)
for i in countup(0, readBytes - 1): result = updateCrc32(p[i], result)
if readBytes != bufSize: break
dealloc(buf)

View File

@@ -50,7 +50,7 @@ proc ProcessCmdLine(pass: TCmdLinePass, command, filename: var string) =
rawMessage(errArgsNeedRunOption, [])
proc HandleCmdLine() =
var start = getTime()
var start = epochTime()
if paramCount() == 0:
writeCommandLineUsage()
else:
@@ -73,7 +73,8 @@ proc HandleCmdLine() =
if gCmd == cmdRun:
tccgen.run()
if gCmd notin {cmdInterpret, cmdRun}:
rawMessage(hintSuccessX, [$gLinesCompiled, $(getTime() - start)])
rawMessage(hintSuccessX, [$gLinesCompiled,
formatFloat(epochTime() - start, ffDecimal, 3)])
if optRun in gGlobalOptions:
when defined(unix):
var prog = "./" & quoteIfContainsWhite(changeFileExt(filename, ""))
@@ -81,6 +82,7 @@ proc HandleCmdLine() =
var prog = quoteIfContainsWhite(changeFileExt(filename, ""))
execExternalProgram(prog & ' ' & arguments)
#GC_disableMarkAndSweep()
cmdLineInfo = newLineInfo("command line", -1, -1)
condsyms.InitDefines()
HandleCmdLine()

View File

@@ -1,7 +1,7 @@
#
#
# The Nimrod Compiler
# (c) Copyright 2008 Andreas Rumpf
# (c) Copyright 2011 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@@ -12,13 +12,7 @@
import
nhashes, ast, astalgo, types
proc NodeTableGet*(t: TNodeTable, key: PNode): int
proc NodeTablePut*(t: var TNodeTable, key: PNode, val: int)
proc NodeTableTestOrSet*(t: var TNodeTable, key: PNode, val: int): int
# implementation
proc hashTree(n: PNode): THash =
result = 0
if n == nil: return
result = ord(n.kind)
case n.kind
@@ -41,7 +35,6 @@ proc hashTree(n: PNode): THash =
result = concHash(result, hashTree(n.sons[i]))
proc TreesEquivalent(a, b: PNode): bool =
result = false
if a == b:
result = true
elif (a != nil) and (b != nil) and (a.kind == b.kind):
@@ -60,36 +53,31 @@ proc TreesEquivalent(a, b: PNode): bool =
if result: result = sameTypeOrNil(a.typ, b.typ)
proc NodeTableRawGet(t: TNodeTable, k: THash, key: PNode): int =
var h: THash
h = k and high(t.data)
var h: THash = k and high(t.data)
while t.data[h].key != nil:
if (t.data[h].h == k) and TreesEquivalent(t.data[h].key, key):
return h
h = nextTry(h, high(t.data))
result = - 1
result = -1
proc NodeTableGet(t: TNodeTable, key: PNode): int =
var index: int
index = NodeTableRawGet(t, hashTree(key), key)
proc NodeTableGet*(t: TNodeTable, key: PNode): int =
var index = NodeTableRawGet(t, hashTree(key), key)
if index >= 0: result = t.data[index].val
else: result = low(int)
proc NodeTableRawInsert(data: var TNodePairSeq, k: THash, key: PNode, val: int) =
var h: THash
h = k and high(data)
proc NodeTableRawInsert(data: var TNodePairSeq, k: THash, key: PNode,
val: int) =
var h: THash = k and high(data)
while data[h].key != nil: h = nextTry(h, high(data))
assert(data[h].key == nil)
data[h].h = k
data[h].key = key
data[h].val = val
proc NodeTablePut(t: var TNodeTable, key: PNode, val: int) =
var
index: int
n: TNodePairSeq
k: THash
k = hashTree(key)
index = NodeTableRawGet(t, k, key)
proc NodeTablePut*(t: var TNodeTable, key: PNode, val: int) =
var n: TNodePairSeq
var k: THash = hashTree(key)
var index = NodeTableRawGet(t, k, key)
if index >= 0:
assert(t.data[index].key != nil)
t.data[index].val = val
@@ -103,13 +91,10 @@ proc NodeTablePut(t: var TNodeTable, key: PNode, val: int) =
NodeTableRawInsert(t.data, k, key, val)
inc(t.counter)
proc NodeTableTestOrSet(t: var TNodeTable, key: PNode, val: int): int =
var
index: int
n: TNodePairSeq
k: THash
k = hashTree(key)
index = NodeTableRawGet(t, k, key)
proc NodeTableTestOrSet*(t: var TNodeTable, key: PNode, val: int): int =
var n: TNodePairSeq
var k: THash = hashTree(key)
var index = NodeTableRawGet(t, k, key)
if index >= 0:
assert(t.data[index].key != nil)
result = t.data[index].val

View File

@@ -157,10 +157,8 @@ proc cleanAux(dir: string) =
of "nimcache":
echo "removing dir: ", path
removeDir(path)
of "dist", ".git":
nil
else:
cleanAux(path)
of "dist", ".git": nil
else: cleanAux(path)
else: nil
proc removePattern(pattern: string) =

View File

@@ -13,60 +13,60 @@
## .. include:: ../doc/astspec.txt
type
TNimrodNodeKind* = enum
nnkNone, nnkEmpty, nnkIdent, nnkSym,
nnkType, nnkCharLit, nnkIntLit, nnkInt8Lit,
nnkInt16Lit, nnkInt32Lit, nnkInt64Lit, nnkFloatLit,
nnkFloat32Lit, nnkFloat64Lit, nnkStrLit, nnkRStrLit,
nnkTripleStrLit, nnkMetaNode, nnkNilLit, nnkDotCall,
nnkCommand, nnkCall, nnkCallStrLit, nnkExprEqExpr,
nnkExprColonExpr, nnkIdentDefs, nnkVarTuple, nnkInfix,
nnkPrefix, nnkPostfix, nnkPar, nnkCurly,
nnkBracket, nnkBracketExpr, nnkPragmaExpr, nnkRange,
nnkDotExpr, nnkCheckedFieldExpr, nnkDerefExpr, nnkIfExpr,
nnkElifExpr, nnkElseExpr, nnkLambda, nnkAccQuoted,
nnkTableConstr, nnkBind, nnkSymChoice, nnkHiddenStdConv,
nnkHiddenSubConv, nnkHiddenCallConv, nnkConv, nnkCast,
nnkAddr, nnkHiddenAddr, nnkHiddenDeref, nnkObjDownConv,
nnkObjUpConv, nnkChckRangeF, nnkChckRange64, nnkChckRange,
nnkStringToCString, nnkCStringToString, nnkPassAsOpenArray, nnkAsgn,
nnkFastAsgn, nnkGenericParams, nnkFormalParams, nnkOfInherit,
nnkModule, nnkProcDef, nnkMethodDef, nnkConverterDef,
nnkMacroDef, nnkTemplateDef, nnkIteratorDef, nnkOfBranch,
nnkElifBranch, nnkExceptBranch, nnkElse, nnkMacroStmt,
nnkAsmStmt, nnkPragma, nnkIfStmt, nnkWhenStmt,
nnkForStmt, nnkWhileStmt, nnkCaseStmt, nnkVarSection,
nnkConstSection, nnkConstDef, nnkTypeSection, nnkTypeDef,
nnkYieldStmt, nnkTryStmt, nnkFinally, nnkRaiseStmt,
nnkReturnStmt, nnkBreakStmt, nnkContinueStmt, nnkBlockStmt,
nnkDiscardStmt, nnkStmtList, nnkImportStmt, nnkFromStmt,
nnkIncludeStmt, nnkCommentStmt, nnkStmtListExpr, nnkBlockExpr,
nnkStmtListType, nnkBlockType, nnkTypeOfExpr, nnkObjectTy,
nnkTupleTy, nnkRecList, nnkRecCase, nnkRecWhen,
nnkRefTy, nnkPtrTy, nnkVarTy, nnkDistinctTy,
nnkProcTy, nnkEnumTy, nnkEnumFieldDef, nnkReturnToken
TNimNodeKinds* = set[TNimrodNodeKind]
TNimrodTypeKind* = enum
ntyNone, ntyBool, ntyChar, ntyEmpty,
ntyArrayConstr, ntyNil, ntyExpr, ntyStmt,
ntyTypeDesc, ntyGenericInvokation, ntyGenericBody, ntyGenericInst,
ntyGenericParam, ntyDistinct, ntyEnum, ntyOrdinal,
ntyArray, ntyObject, ntyTuple, ntySet,
ntyRange, ntyPtr, ntyRef, ntyVar,
ntySequence, ntyProc, ntyPointer, ntyOpenArray,
ntyString, ntyCString, ntyForward, ntyInt,
ntyInt8, ntyInt16, ntyInt32, ntyInt64,
ntyFloat, ntyFloat32, ntyFloat64, ntyFloat128
TNimTypeKinds* = set[TNimrodTypeKind]
TNimrodSymKind* = enum
nskUnknown, nskConditional, nskDynLib, nskParam,
nskGenericParam, nskTemp, nskType, nskConst,
nskVar, nskProc, nskMethod, nskIterator,
nskConverter, nskMacro, nskTemplate, nskField,
nskEnumField, nskForVar, nskModule, nskLabel,
nskStub
TNimSymKinds* = set[TNimrodSymKind]
type
TNimrodNodeKind* = enum
nnkNone, nnkEmpty, nnkIdent, nnkSym,
nnkType, nnkCharLit, nnkIntLit, nnkInt8Lit,
nnkInt16Lit, nnkInt32Lit, nnkInt64Lit, nnkFloatLit,
nnkFloat32Lit, nnkFloat64Lit, nnkStrLit, nnkRStrLit,
nnkTripleStrLit, nnkMetaNode, nnkNilLit, nnkDotCall,
nnkCommand, nnkCall, nnkCallStrLit, nnkExprEqExpr,
nnkExprColonExpr, nnkIdentDefs, nnkVarTuple, nnkInfix,
nnkPrefix, nnkPostfix, nnkPar, nnkCurly,
nnkBracket, nnkBracketExpr, nnkPragmaExpr, nnkRange,
nnkDotExpr, nnkCheckedFieldExpr, nnkDerefExpr, nnkIfExpr,
nnkElifExpr, nnkElseExpr, nnkLambda, nnkAccQuoted,
nnkTableConstr, nnkBind, nnkSymChoice, nnkHiddenStdConv,
nnkHiddenSubConv, nnkHiddenCallConv, nnkConv, nnkCast,
nnkAddr, nnkHiddenAddr, nnkHiddenDeref, nnkObjDownConv,
nnkObjUpConv, nnkChckRangeF, nnkChckRange64, nnkChckRange,
nnkStringToCString, nnkCStringToString, nnkPassAsOpenArray, nnkAsgn,
nnkFastAsgn, nnkGenericParams, nnkFormalParams, nnkOfInherit,
nnkModule, nnkProcDef, nnkMethodDef, nnkConverterDef,
nnkMacroDef, nnkTemplateDef, nnkIteratorDef, nnkOfBranch,
nnkElifBranch, nnkExceptBranch, nnkElse, nnkMacroStmt,
nnkAsmStmt, nnkPragma, nnkIfStmt, nnkWhenStmt,
nnkForStmt, nnkWhileStmt, nnkCaseStmt, nnkVarSection,
nnkConstSection, nnkConstDef, nnkTypeSection, nnkTypeDef,
nnkYieldStmt, nnkTryStmt, nnkFinally, nnkRaiseStmt,
nnkReturnStmt, nnkBreakStmt, nnkContinueStmt, nnkBlockStmt,
nnkDiscardStmt, nnkStmtList, nnkImportStmt, nnkFromStmt,
nnkIncludeStmt, nnkCommentStmt, nnkStmtListExpr, nnkBlockExpr,
nnkStmtListType, nnkBlockType, nnkTypeOfExpr, nnkObjectTy,
nnkTupleTy, nnkRecList, nnkRecCase, nnkRecWhen,
nnkRefTy, nnkPtrTy, nnkVarTy, nnkDistinctTy,
nnkProcTy, nnkEnumTy, nnkEnumFieldDef, nnkReturnToken
TNimNodeKinds* = set[TNimrodNodeKind]
TNimrodTypeKind* = enum
ntyNone, ntyBool, ntyChar, ntyEmpty,
ntyArrayConstr, ntyNil, ntyExpr, ntyStmt,
ntyTypeDesc, ntyGenericInvokation, ntyGenericBody, ntyGenericInst,
ntyGenericParam, ntyDistinct, ntyEnum, ntyOrdinal,
ntyArray, ntyObject, ntyTuple, ntySet,
ntyRange, ntyPtr, ntyRef, ntyVar,
ntySequence, ntyProc, ntyPointer, ntyOpenArray,
ntyString, ntyCString, ntyForward, ntyInt,
ntyInt8, ntyInt16, ntyInt32, ntyInt64,
ntyFloat, ntyFloat32, ntyFloat64, ntyFloat128
TNimTypeKinds* = set[TNimrodTypeKind]
TNimrodSymKind* = enum
nskUnknown, nskConditional, nskDynLib, nskParam,
nskGenericParam, nskTemp, nskType, nskConst,
nskVar, nskProc, nskMethod, nskIterator,
nskConverter, nskMacro, nskTemplate, nskField,
nskEnumField, nskForVar, nskModule, nskLabel,
nskStub
TNimSymKinds* = set[TNimrodSymKind]
type
TNimrodIdent* = object of TObject
@@ -88,7 +88,7 @@ type
# Nodes should be reference counted to make the `copy` operation very fast!
# However, this is difficult to achieve: modify(n[0][1]) should propagate to
# its father. How to do this without back references? Hm, BS, it works without
# its father. How to do this without back references? Hm, BS, it works without
# them.
proc `[]`* (n: PNimrodNode, i: int): PNimrodNode {.magic: "NChild".}
@@ -105,7 +105,7 @@ proc `$`*(i: TNimrodIdent): string {.magic: "IdentToStr".}
proc `==`* (a, b: TNimrodIdent): bool {.magic: "EqIdent", noSideEffect.}
## compares two Nimrod identifiers
proc `==`* (a, b: PNimrodNode): bool {.magic: "EqNimrodNode", noSideEffect.}
## compares two Nimrod nodes

View File

@@ -100,7 +100,7 @@ when defined(Windows):
stdcall, dynlib: "kernel32", importc: "WaitForMultipleObjects".}
proc WaitForSingleObject(hHandle: THANDLE, dwMilliseconds: int32): int32 {.
stdcall, dynlib: "kernel32", importc: "WaitForSingleObject".}
stdcall, dynlib: "kernel32", importc: "WaitForSingleObject".}
proc TerminateThread(hThread: THandle, dwExitCode: int32): int32 {.
stdcall, dynlib: "kernel32", importc: "TerminateThread".}

View File

@@ -216,9 +216,16 @@ proc `[]=`*[A, B](t: TOrderedHashTable[A, B], key: A, val: B) =
inc(t.counter)
proc del*[A, B](t: TOrderedHashTable[A, B], key: A) =
## deletes `key` from hash table `t`.
## deletes `key` from hash table `t`. Warning: It's inefficient for ordered
## tables: O(n).
var index = RawGet(t, key)
if index >= 0:
var i = t.first
while i >= 0:
var nxt = t.data[i].next
if nxt == index: XXX
i = nxt
t.data[index].slot = seDeleted
dec(t.counter)

View File

@@ -23,28 +23,39 @@ proc nimLoadLibraryError(path: string) {.compilerproc, noinline.}
proc setStackBottom(theStackBottom: pointer) {.compilerRtl, noinline.}
# Support for thread local storage:
when false:
when defined(windows):
proc TlsAlloc(): int32 {.importc: "TlsAlloc", stdcall, dynlib: "kernel32".}
proc TlsSetValue(dwTlsIndex: int32, lpTlsValue: pointer) {.
importc: "TlsSetValue", stdcall, dynlib: "kernel32".}
proc TlsGetValue(dwTlsIndex: int32): pointer {.
importc: "TlsGetValue", stdcall, dynlib: "kernel32".}
else:
type
Tpthread_key {.importc: "pthread_key_t", header: "<sys/types.h>".} = int
when defined(windows):
type
TThreadVarSlot {.compilerproc.} = distinct int32
proc pthread_getspecific(a1: Tpthread_key): pointer {.
importc: "pthread_getspecific", header: "<pthread.h>".}
proc pthread_key_create(a1: ptr Tpthread_key,
a2: proc (x: pointer) {.noconv.}): int32 {.
importc: "pthread_key_create", header: "<pthread.h>".}
proc pthread_key_delete(a1: Tpthread_key): int32 {.
importc: "pthread_key_delete", header: "<pthread.h>".}
proc TlsAlloc(): TThreadVarSlot {.
importc: "TlsAlloc", stdcall, dynlib: "kernel32".}
proc TlsSetValue(dwTlsIndex: TThreadVarSlot, lpTlsValue: pointer) {.
importc: "TlsSetValue", stdcall, dynlib: "kernel32".}
proc TlsGetValue(dwTlsIndex: TThreadVarSlot): pointer {.
importc: "TlsGetValue", stdcall, dynlib: "kernel32".}
proc ThreadVarAlloc(): TThreadVarSlot {.compilerproc, inline.} =
result = TlsAlloc()
proc ThreadVarSetValue(s: TThreadVarSlot, value: pointer) {.compilerproc.} =
TlsSetValue(s, value)
proc ThreadVarGetValue(s: TThreadVarSlot): pointer {.compilerproc.} =
result = TlsGetValue(s)
else:
type
Tpthread_key {.importc: "pthread_key_t",
header: "<sys/types.h>".} = distinct int
TThreadVarSlot {.compilerproc.} = Tpthread_key
proc pthread_setspecific(a1: Tpthread_key, a2: pointer): int32 {.
importc: "pthread_setspecific", header: "<pthread.h>".}
proc pthread_getspecific(a1: Tpthread_key): pointer {.
importc: "pthread_getspecific", header: "<pthread.h>".}
proc pthread_key_create(a1: ptr Tpthread_key,
destruct: proc (x: pointer) {.noconv.}): int32 {.
importc: "pthread_key_create", header: "<pthread.h>".}
proc pthread_key_delete(a1: Tpthread_key): int32 {.
importc: "pthread_key_delete", header: "<pthread.h>".}
proc pthread_setspecific(a1: Tpthread_key, a2: pointer): int32 {.
importc: "pthread_setspecific", header: "<pthread.h>".}

View File

@@ -1,7 +1,7 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2010 Andreas Rumpf
# (c) Copyright 2011 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@@ -21,8 +21,6 @@ proc rawWrite(f: TFile, s: string) =
proc nimLoadLibraryError(path: string) =
# carefully written to avoid memory allocation:
#stdout.write("could not load: ")
#quit(path)
stdout.rawWrite("could not load: ")
stdout.rawWrite(path)
stdout.rawWrite("\n")

View File

@@ -23,7 +23,7 @@
const
CycleIncrease = 2 # is a multiplicative increase
InitialCycleThreshold = 4*1024*1024 # X MB because cycle checking is slow
ZctThreshold = 256 # we collect garbage if the ZCT's size
ZctThreshold = 500 # we collect garbage if the ZCT's size
# reaches this threshold
# this seems to be a good value
@@ -294,31 +294,32 @@ proc initGC() =
proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) =
var d = cast[TAddress](dest)
case n.kind
of nkNone: assert(false)
of nkSlot: forAllChildrenAux(cast[pointer](d +% n.offset), n.typ, op)
of nkList:
for i in 0..n.len-1: forAllSlotsAux(dest, n.sons[i], op)
of nkCase:
var m = selectBranch(dest, n)
if m != nil: forAllSlotsAux(dest, m, op)
of nkNone: assert(false)
proc forAllChildrenAux(dest: Pointer, mt: PNimType, op: TWalkOp) =
var d = cast[TAddress](dest)
if dest == nil: return # nothing to do
if ntfNoRefs notin mt.flags:
case mt.Kind
of tyArray, tyArrayConstr, tyOpenArray:
for i in 0..(mt.size div mt.base.size)-1:
forAllChildrenAux(cast[pointer](d +% i *% mt.base.size), mt.base, op)
of tyRef, tyString, tySequence: # leaf:
doOperation(cast[ppointer](d)[], op)
of tyObject, tyTuple, tyPureObject:
forAllSlotsAux(dest, mt.node, op)
of tyArray, tyArrayConstr, tyOpenArray:
for i in 0..(mt.size div mt.base.size)-1:
forAllChildrenAux(cast[pointer](d +% i *% mt.base.size), mt.base, op)
else: nil
proc forAllChildren(cell: PCell, op: TWalkOp) =
assert(cell != nil)
assert(cell.typ != nil)
assert cell.typ.kind in {tyRef, tySequence, tyString}
case cell.typ.Kind
of tyRef: # common case
forAllChildrenAux(cellToUsr(cell), cell.typ.base, op)
@@ -329,14 +330,57 @@ proc forAllChildren(cell: PCell, op: TWalkOp) =
for i in 0..s.len-1:
forAllChildrenAux(cast[pointer](d +% i *% cell.typ.base.size +%
GenericSeqSize), cell.typ.base, op)
of tyString: nil
else: assert(false)
else: nil
proc checkCollection {.inline.} =
# checks if a collection should be done
if recGcLock == 0:
collectCT(gch)
proc addNewObjToZCT(res: PCell) {.inline.} =
# we check the last 8 entries (cache line) for a slot that could be reused.
# In 63% of all cases we succeed here! But we have to optimize the heck
# out of this small linear search so that ``newObj`` is not slowed down.
#
# Slots to try cache hit
# 1 32%
# 4 59%
# 8 63%
# 16 66%
# all slots 68%
var L = gch.zct.len
var d = gch.zct.d
when true:
# loop unrolled for performance:
template replaceZctEntry(i: expr) =
c = d[i]
if c.refcount >=% rcIncrement:
c.refcount = c.refcount and not colorMask
d[i] = res
return
if L > 8:
var c: PCell
replaceZctEntry(L-1)
replaceZctEntry(L-2)
replaceZctEntry(L-3)
replaceZctEntry(L-4)
replaceZctEntry(L-5)
replaceZctEntry(L-6)
replaceZctEntry(L-7)
replaceZctEntry(L-8)
add(gch.zct, res)
else:
d[L] = res
inc(gch.zct.len)
else:
for i in countdown(L-1, max(0, L-8)):
var c = d[i]
if c.refcount >=% rcIncrement:
c.refcount = c.refcount and not colorMask
d[i] = res
return
add(gch.zct, res)
proc newObj(typ: PNimType, size: int): pointer {.compilerRtl.} =
# generates a new object and sets its reference counter to 0
aquire(gch)
@@ -354,18 +398,7 @@ proc newObj(typ: PNimType, size: int): pointer {.compilerRtl.} =
res.refcount = rcZct # refcount is zero, but mark it to be in the ZCT
assert(isAllocatedPtr(allocator, res))
# its refcount is zero, so add it to the ZCT:
block addToZCT:
# we check the last 8 entries (cache line) for a slot
# that could be reused
var L = gch.zct.len
var d = gch.zct.d
for i in countdown(L-1, max(0, L-8)):
var c = d[i]
if c.refcount >=% rcIncrement:
c.refcount = c.refcount and not colorMask
d[i] = res
break addToZCT
add(gch.zct, res)
addNewObjToZCT(res)
when logGC: writeCell("new cell", res)
gcTrace(res, csAllocated)
release(gch)

View File

@@ -1,7 +1,7 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2010 Andreas Rumpf
# (c) Copyright 2011 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.

View File

@@ -1,11 +1,13 @@
* thread support: threadvar on Windows seems broken;
add --deadlock_prevention:on|off switch
- implicit ref/ptr->var conversion
- warning for implicit openArray -> varargs convention
- implement explicit varargs
High priority (version 0.9.0)
=============================
- warning for implicit openArray -> varargs convention
- implement explicit varargs
- tests: run modules that contain "#RUN_ME", compile the other
modules; run the GC tests
- fix implicit generic routines
@@ -32,11 +34,8 @@ To implement
* hash tables and sets; count tables; ordered dicts
* distinct types for array/seq indexes
* implement closures for the C code generator
* GC: marker procs for native Nimrod GC and Boehm GC
* thread support: threadvar on Windows seems broken;
add --deadlock_prevention:on|off switch
* built-in serialization