gc tweaking to gain a few percent of performance
This commit is contained in:
parent
7d2b3dd6db
commit
73c3551766
13 changed files with 183 additions and 153 deletions
|
|
@ -100,19 +100,16 @@ proc crcFromBuf(buf: Pointer, length: int): TCrc32 =
|
||||||
|
|
||||||
proc crcFromFile(filename: string): TCrc32 =
|
proc crcFromFile(filename: string): TCrc32 =
|
||||||
const
|
const
|
||||||
bufSize = 8 * 1024
|
bufSize = 8000 # don't use 8K for the memory allocator!
|
||||||
var
|
var
|
||||||
bin: tfile
|
bin: tfile
|
||||||
buf: Pointer
|
|
||||||
readBytes: int
|
|
||||||
p: PByteArray
|
|
||||||
result = InitCrc32
|
result = InitCrc32
|
||||||
if not open(bin, filename):
|
if not open(bin, filename):
|
||||||
return # not equal if file does not exist
|
return # not equal if file does not exist
|
||||||
buf = alloc(BufSize)
|
var buf = alloc(BufSize)
|
||||||
p = cast[PByteArray](buf)
|
var p = cast[PByteArray](buf)
|
||||||
while true:
|
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)
|
for i in countup(0, readBytes - 1): result = updateCrc32(p[i], result)
|
||||||
if readBytes != bufSize: break
|
if readBytes != bufSize: break
|
||||||
dealloc(buf)
|
dealloc(buf)
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ proc ProcessCmdLine(pass: TCmdLinePass, command, filename: var string) =
|
||||||
rawMessage(errArgsNeedRunOption, [])
|
rawMessage(errArgsNeedRunOption, [])
|
||||||
|
|
||||||
proc HandleCmdLine() =
|
proc HandleCmdLine() =
|
||||||
var start = getTime()
|
var start = epochTime()
|
||||||
if paramCount() == 0:
|
if paramCount() == 0:
|
||||||
writeCommandLineUsage()
|
writeCommandLineUsage()
|
||||||
else:
|
else:
|
||||||
|
|
@ -73,7 +73,8 @@ proc HandleCmdLine() =
|
||||||
if gCmd == cmdRun:
|
if gCmd == cmdRun:
|
||||||
tccgen.run()
|
tccgen.run()
|
||||||
if gCmd notin {cmdInterpret, cmdRun}:
|
if gCmd notin {cmdInterpret, cmdRun}:
|
||||||
rawMessage(hintSuccessX, [$gLinesCompiled, $(getTime() - start)])
|
rawMessage(hintSuccessX, [$gLinesCompiled,
|
||||||
|
formatFloat(epochTime() - start, ffDecimal, 3)])
|
||||||
if optRun in gGlobalOptions:
|
if optRun in gGlobalOptions:
|
||||||
when defined(unix):
|
when defined(unix):
|
||||||
var prog = "./" & quoteIfContainsWhite(changeFileExt(filename, ""))
|
var prog = "./" & quoteIfContainsWhite(changeFileExt(filename, ""))
|
||||||
|
|
@ -81,6 +82,7 @@ proc HandleCmdLine() =
|
||||||
var prog = quoteIfContainsWhite(changeFileExt(filename, ""))
|
var prog = quoteIfContainsWhite(changeFileExt(filename, ""))
|
||||||
execExternalProgram(prog & ' ' & arguments)
|
execExternalProgram(prog & ' ' & arguments)
|
||||||
|
|
||||||
|
#GC_disableMarkAndSweep()
|
||||||
cmdLineInfo = newLineInfo("command line", -1, -1)
|
cmdLineInfo = newLineInfo("command line", -1, -1)
|
||||||
condsyms.InitDefines()
|
condsyms.InitDefines()
|
||||||
HandleCmdLine()
|
HandleCmdLine()
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# The Nimrod Compiler
|
# The Nimrod Compiler
|
||||||
# (c) Copyright 2008 Andreas Rumpf
|
# (c) Copyright 2011 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
@ -12,13 +12,7 @@
|
||||||
import
|
import
|
||||||
nhashes, ast, astalgo, types
|
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 =
|
proc hashTree(n: PNode): THash =
|
||||||
result = 0
|
|
||||||
if n == nil: return
|
if n == nil: return
|
||||||
result = ord(n.kind)
|
result = ord(n.kind)
|
||||||
case n.kind
|
case n.kind
|
||||||
|
|
@ -41,7 +35,6 @@ proc hashTree(n: PNode): THash =
|
||||||
result = concHash(result, hashTree(n.sons[i]))
|
result = concHash(result, hashTree(n.sons[i]))
|
||||||
|
|
||||||
proc TreesEquivalent(a, b: PNode): bool =
|
proc TreesEquivalent(a, b: PNode): bool =
|
||||||
result = false
|
|
||||||
if a == b:
|
if a == b:
|
||||||
result = true
|
result = true
|
||||||
elif (a != nil) and (b != nil) and (a.kind == b.kind):
|
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)
|
if result: result = sameTypeOrNil(a.typ, b.typ)
|
||||||
|
|
||||||
proc NodeTableRawGet(t: TNodeTable, k: THash, key: PNode): int =
|
proc NodeTableRawGet(t: TNodeTable, k: THash, key: PNode): int =
|
||||||
var h: THash
|
var h: THash = k and high(t.data)
|
||||||
h = k and high(t.data)
|
|
||||||
while t.data[h].key != nil:
|
while t.data[h].key != nil:
|
||||||
if (t.data[h].h == k) and TreesEquivalent(t.data[h].key, key):
|
if (t.data[h].h == k) and TreesEquivalent(t.data[h].key, key):
|
||||||
return h
|
return h
|
||||||
h = nextTry(h, high(t.data))
|
h = nextTry(h, high(t.data))
|
||||||
result = - 1
|
result = -1
|
||||||
|
|
||||||
proc NodeTableGet(t: TNodeTable, key: PNode): int =
|
proc NodeTableGet*(t: TNodeTable, key: PNode): int =
|
||||||
var index: int
|
var index = NodeTableRawGet(t, hashTree(key), key)
|
||||||
index = NodeTableRawGet(t, hashTree(key), key)
|
|
||||||
if index >= 0: result = t.data[index].val
|
if index >= 0: result = t.data[index].val
|
||||||
else: result = low(int)
|
else: result = low(int)
|
||||||
|
|
||||||
proc NodeTableRawInsert(data: var TNodePairSeq, k: THash, key: PNode, val: int) =
|
proc NodeTableRawInsert(data: var TNodePairSeq, k: THash, key: PNode,
|
||||||
var h: THash
|
val: int) =
|
||||||
h = k and high(data)
|
var h: THash = k and high(data)
|
||||||
while data[h].key != nil: h = nextTry(h, high(data))
|
while data[h].key != nil: h = nextTry(h, high(data))
|
||||||
assert(data[h].key == nil)
|
assert(data[h].key == nil)
|
||||||
data[h].h = k
|
data[h].h = k
|
||||||
data[h].key = key
|
data[h].key = key
|
||||||
data[h].val = val
|
data[h].val = val
|
||||||
|
|
||||||
proc NodeTablePut(t: var TNodeTable, key: PNode, val: int) =
|
proc NodeTablePut*(t: var TNodeTable, key: PNode, val: int) =
|
||||||
var
|
var n: TNodePairSeq
|
||||||
index: int
|
var k: THash = hashTree(key)
|
||||||
n: TNodePairSeq
|
var index = NodeTableRawGet(t, k, key)
|
||||||
k: THash
|
|
||||||
k = hashTree(key)
|
|
||||||
index = NodeTableRawGet(t, k, key)
|
|
||||||
if index >= 0:
|
if index >= 0:
|
||||||
assert(t.data[index].key != nil)
|
assert(t.data[index].key != nil)
|
||||||
t.data[index].val = val
|
t.data[index].val = val
|
||||||
|
|
@ -103,13 +91,10 @@ proc NodeTablePut(t: var TNodeTable, key: PNode, val: int) =
|
||||||
NodeTableRawInsert(t.data, k, key, val)
|
NodeTableRawInsert(t.data, k, key, val)
|
||||||
inc(t.counter)
|
inc(t.counter)
|
||||||
|
|
||||||
proc NodeTableTestOrSet(t: var TNodeTable, key: PNode, val: int): int =
|
proc NodeTableTestOrSet*(t: var TNodeTable, key: PNode, val: int): int =
|
||||||
var
|
var n: TNodePairSeq
|
||||||
index: int
|
var k: THash = hashTree(key)
|
||||||
n: TNodePairSeq
|
var index = NodeTableRawGet(t, k, key)
|
||||||
k: THash
|
|
||||||
k = hashTree(key)
|
|
||||||
index = NodeTableRawGet(t, k, key)
|
|
||||||
if index >= 0:
|
if index >= 0:
|
||||||
assert(t.data[index].key != nil)
|
assert(t.data[index].key != nil)
|
||||||
result = t.data[index].val
|
result = t.data[index].val
|
||||||
|
|
|
||||||
6
koch.nim
6
koch.nim
|
|
@ -157,10 +157,8 @@ proc cleanAux(dir: string) =
|
||||||
of "nimcache":
|
of "nimcache":
|
||||||
echo "removing dir: ", path
|
echo "removing dir: ", path
|
||||||
removeDir(path)
|
removeDir(path)
|
||||||
of "dist", ".git":
|
of "dist", ".git": nil
|
||||||
nil
|
else: cleanAux(path)
|
||||||
else:
|
|
||||||
cleanAux(path)
|
|
||||||
else: nil
|
else: nil
|
||||||
|
|
||||||
proc removePattern(pattern: string) =
|
proc removePattern(pattern: string) =
|
||||||
|
|
|
||||||
|
|
@ -216,9 +216,16 @@ proc `[]=`*[A, B](t: TOrderedHashTable[A, B], key: A, val: B) =
|
||||||
inc(t.counter)
|
inc(t.counter)
|
||||||
|
|
||||||
proc del*[A, B](t: TOrderedHashTable[A, B], key: A) =
|
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)
|
var index = RawGet(t, key)
|
||||||
if index >= 0:
|
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
|
t.data[index].slot = seDeleted
|
||||||
dec(t.counter)
|
dec(t.counter)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,24 +23,35 @@ proc nimLoadLibraryError(path: string) {.compilerproc, noinline.}
|
||||||
|
|
||||||
proc setStackBottom(theStackBottom: pointer) {.compilerRtl, noinline.}
|
proc setStackBottom(theStackBottom: pointer) {.compilerRtl, noinline.}
|
||||||
|
|
||||||
|
|
||||||
# Support for thread local storage:
|
# Support for thread local storage:
|
||||||
when false:
|
when defined(windows):
|
||||||
when defined(windows):
|
type
|
||||||
proc TlsAlloc(): int32 {.importc: "TlsAlloc", stdcall, dynlib: "kernel32".}
|
TThreadVarSlot {.compilerproc.} = distinct int32
|
||||||
proc TlsSetValue(dwTlsIndex: int32, lpTlsValue: pointer) {.
|
|
||||||
|
proc TlsAlloc(): TThreadVarSlot {.
|
||||||
|
importc: "TlsAlloc", stdcall, dynlib: "kernel32".}
|
||||||
|
proc TlsSetValue(dwTlsIndex: TThreadVarSlot, lpTlsValue: pointer) {.
|
||||||
importc: "TlsSetValue", stdcall, dynlib: "kernel32".}
|
importc: "TlsSetValue", stdcall, dynlib: "kernel32".}
|
||||||
proc TlsGetValue(dwTlsIndex: int32): pointer {.
|
proc TlsGetValue(dwTlsIndex: TThreadVarSlot): pointer {.
|
||||||
importc: "TlsGetValue", stdcall, dynlib: "kernel32".}
|
importc: "TlsGetValue", stdcall, dynlib: "kernel32".}
|
||||||
|
|
||||||
else:
|
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
|
type
|
||||||
Tpthread_key {.importc: "pthread_key_t", header: "<sys/types.h>".} = int
|
Tpthread_key {.importc: "pthread_key_t",
|
||||||
|
header: "<sys/types.h>".} = distinct int
|
||||||
|
TThreadVarSlot {.compilerproc.} = Tpthread_key
|
||||||
|
|
||||||
proc pthread_getspecific(a1: Tpthread_key): pointer {.
|
proc pthread_getspecific(a1: Tpthread_key): pointer {.
|
||||||
importc: "pthread_getspecific", header: "<pthread.h>".}
|
importc: "pthread_getspecific", header: "<pthread.h>".}
|
||||||
proc pthread_key_create(a1: ptr Tpthread_key,
|
proc pthread_key_create(a1: ptr Tpthread_key,
|
||||||
a2: proc (x: pointer) {.noconv.}): int32 {.
|
destruct: proc (x: pointer) {.noconv.}): int32 {.
|
||||||
importc: "pthread_key_create", header: "<pthread.h>".}
|
importc: "pthread_key_create", header: "<pthread.h>".}
|
||||||
proc pthread_key_delete(a1: Tpthread_key): int32 {.
|
proc pthread_key_delete(a1: Tpthread_key): int32 {.
|
||||||
importc: "pthread_key_delete", header: "<pthread.h>".}
|
importc: "pthread_key_delete", header: "<pthread.h>".}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Nimrod's Runtime Library
|
# Nimrod's Runtime Library
|
||||||
# (c) Copyright 2010 Andreas Rumpf
|
# (c) Copyright 2011 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
@ -21,8 +21,6 @@ proc rawWrite(f: TFile, s: string) =
|
||||||
|
|
||||||
proc nimLoadLibraryError(path: string) =
|
proc nimLoadLibraryError(path: string) =
|
||||||
# carefully written to avoid memory allocation:
|
# carefully written to avoid memory allocation:
|
||||||
#stdout.write("could not load: ")
|
|
||||||
#quit(path)
|
|
||||||
stdout.rawWrite("could not load: ")
|
stdout.rawWrite("could not load: ")
|
||||||
stdout.rawWrite(path)
|
stdout.rawWrite(path)
|
||||||
stdout.rawWrite("\n")
|
stdout.rawWrite("\n")
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@
|
||||||
const
|
const
|
||||||
CycleIncrease = 2 # is a multiplicative increase
|
CycleIncrease = 2 # is a multiplicative increase
|
||||||
InitialCycleThreshold = 4*1024*1024 # X MB because cycle checking is slow
|
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
|
# reaches this threshold
|
||||||
# this seems to be a good value
|
# this seems to be a good value
|
||||||
|
|
||||||
|
|
@ -294,31 +294,32 @@ proc initGC() =
|
||||||
proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) =
|
proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: TWalkOp) =
|
||||||
var d = cast[TAddress](dest)
|
var d = cast[TAddress](dest)
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkNone: assert(false)
|
|
||||||
of nkSlot: forAllChildrenAux(cast[pointer](d +% n.offset), n.typ, op)
|
of nkSlot: forAllChildrenAux(cast[pointer](d +% n.offset), n.typ, op)
|
||||||
of nkList:
|
of nkList:
|
||||||
for i in 0..n.len-1: forAllSlotsAux(dest, n.sons[i], op)
|
for i in 0..n.len-1: forAllSlotsAux(dest, n.sons[i], op)
|
||||||
of nkCase:
|
of nkCase:
|
||||||
var m = selectBranch(dest, n)
|
var m = selectBranch(dest, n)
|
||||||
if m != nil: forAllSlotsAux(dest, m, op)
|
if m != nil: forAllSlotsAux(dest, m, op)
|
||||||
|
of nkNone: assert(false)
|
||||||
|
|
||||||
proc forAllChildrenAux(dest: Pointer, mt: PNimType, op: TWalkOp) =
|
proc forAllChildrenAux(dest: Pointer, mt: PNimType, op: TWalkOp) =
|
||||||
var d = cast[TAddress](dest)
|
var d = cast[TAddress](dest)
|
||||||
if dest == nil: return # nothing to do
|
if dest == nil: return # nothing to do
|
||||||
if ntfNoRefs notin mt.flags:
|
if ntfNoRefs notin mt.flags:
|
||||||
case mt.Kind
|
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:
|
of tyRef, tyString, tySequence: # leaf:
|
||||||
doOperation(cast[ppointer](d)[], op)
|
doOperation(cast[ppointer](d)[], op)
|
||||||
of tyObject, tyTuple, tyPureObject:
|
of tyObject, tyTuple, tyPureObject:
|
||||||
forAllSlotsAux(dest, mt.node, op)
|
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
|
else: nil
|
||||||
|
|
||||||
proc forAllChildren(cell: PCell, op: TWalkOp) =
|
proc forAllChildren(cell: PCell, op: TWalkOp) =
|
||||||
assert(cell != nil)
|
assert(cell != nil)
|
||||||
assert(cell.typ != nil)
|
assert(cell.typ != nil)
|
||||||
|
assert cell.typ.kind in {tyRef, tySequence, tyString}
|
||||||
case cell.typ.Kind
|
case cell.typ.Kind
|
||||||
of tyRef: # common case
|
of tyRef: # common case
|
||||||
forAllChildrenAux(cellToUsr(cell), cell.typ.base, op)
|
forAllChildrenAux(cellToUsr(cell), cell.typ.base, op)
|
||||||
|
|
@ -329,14 +330,57 @@ proc forAllChildren(cell: PCell, op: TWalkOp) =
|
||||||
for i in 0..s.len-1:
|
for i in 0..s.len-1:
|
||||||
forAllChildrenAux(cast[pointer](d +% i *% cell.typ.base.size +%
|
forAllChildrenAux(cast[pointer](d +% i *% cell.typ.base.size +%
|
||||||
GenericSeqSize), cell.typ.base, op)
|
GenericSeqSize), cell.typ.base, op)
|
||||||
of tyString: nil
|
else: nil
|
||||||
else: assert(false)
|
|
||||||
|
|
||||||
proc checkCollection {.inline.} =
|
proc checkCollection {.inline.} =
|
||||||
# checks if a collection should be done
|
# checks if a collection should be done
|
||||||
if recGcLock == 0:
|
if recGcLock == 0:
|
||||||
collectCT(gch)
|
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.} =
|
proc newObj(typ: PNimType, size: int): pointer {.compilerRtl.} =
|
||||||
# generates a new object and sets its reference counter to 0
|
# generates a new object and sets its reference counter to 0
|
||||||
aquire(gch)
|
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
|
res.refcount = rcZct # refcount is zero, but mark it to be in the ZCT
|
||||||
assert(isAllocatedPtr(allocator, res))
|
assert(isAllocatedPtr(allocator, res))
|
||||||
# its refcount is zero, so add it to the ZCT:
|
# its refcount is zero, so add it to the ZCT:
|
||||||
block addToZCT:
|
addNewObjToZCT(res)
|
||||||
# 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)
|
|
||||||
when logGC: writeCell("new cell", res)
|
when logGC: writeCell("new cell", res)
|
||||||
gcTrace(res, csAllocated)
|
gcTrace(res, csAllocated)
|
||||||
release(gch)
|
release(gch)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Nimrod's Runtime Library
|
# Nimrod's Runtime Library
|
||||||
# (c) Copyright 2010 Andreas Rumpf
|
# (c) Copyright 2011 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
|
||||||
9
todo.txt
9
todo.txt
|
|
@ -1,11 +1,13 @@
|
||||||
|
* thread support: threadvar on Windows seems broken;
|
||||||
|
add --deadlock_prevention:on|off switch
|
||||||
- implicit ref/ptr->var conversion
|
- implicit ref/ptr->var conversion
|
||||||
- warning for implicit openArray -> varargs convention
|
|
||||||
- implement explicit varargs
|
|
||||||
|
|
||||||
|
|
||||||
High priority (version 0.9.0)
|
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
|
- tests: run modules that contain "#RUN_ME", compile the other
|
||||||
modules; run the GC tests
|
modules; run the GC tests
|
||||||
- fix implicit generic routines
|
- fix implicit generic routines
|
||||||
|
|
@ -32,11 +34,8 @@ To implement
|
||||||
|
|
||||||
* hash tables and sets; count tables; ordered dicts
|
* hash tables and sets; count tables; ordered dicts
|
||||||
* distinct types for array/seq indexes
|
* distinct types for array/seq indexes
|
||||||
|
|
||||||
* implement closures for the C code generator
|
* implement closures for the C code generator
|
||||||
* GC: marker procs for native Nimrod GC and Boehm GC
|
* 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
|
* built-in serialization
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue