added GC_addCycleRoot

This commit is contained in:
Araq
2013-02-12 08:45:01 +01:00
parent 5e7dd69b00
commit 0f2aa053d9
3 changed files with 16 additions and 4 deletions

View File

@@ -520,7 +520,7 @@ type
TNodeSeq* = seq[PNode]
PType* = ref TType
PSym* = ref TSym
TNode*{.final.} = object # on a 32bit machine, this takes 32 bytes
TNode*{.final, acyclic.} = object # on a 32bit machine, this takes 32 bytes
typ*: PType
comment*: string
info*: TLineInfo
@@ -605,7 +605,7 @@ type
PInstantiation* = ref TInstantiation
PLib* = ref TLib
TSym* = object of TIdObj
TSym* {.acyclic.} = object of TIdObj
# proc and type instantiations are cached in the generic symbol
case kind*: TSymKind
of skType:
@@ -653,7 +653,8 @@ type
constraint*: PNode # additional constraints like 'lit|result'
TTypeSeq* = seq[PType]
TType* = object of TIdObj # types are identical iff they have the
TType* {.acyclic.} = object of TIdObj # \
# types are identical iff they have the
# same id; there may be multiple copies of a type
# in memory!
kind*: TTypeKind # kind of type

View File

@@ -26,7 +26,12 @@ The cycle collector can be en-/disabled independently from the other parts of
the GC with ``GC_enableMarkAndSweep`` and ``GC_disableMarkAndSweep``. The
compiler analyses the types for their possibility to build cycles, but often
it is necessary to help this analysis with the ``acyclic`` pragma (see
`acyclic <manual.html#acyclic-pragma>`_ for further information).
`acyclic <manual.html#acyclic-pragma>`_ for further information).
You can also use the ``acyclic`` pragma for data that is cyclic in reality and
then break up the cycles explicitly with ``GC_addCycleRoot``. This can be a
very good optimization; the Nimrod compiler itself relies on this optimization
trick to improve performance.
To force a full collection call ``GC_fullCollect``. Note that it is generally
better to let the GC do its work and not enforce a full collection.

View File

@@ -207,6 +207,12 @@ proc incRef(c: PCell) {.inline.} =
proc nimGCref(p: pointer) {.compilerProc, inline.} = incRef(usrToCell(p))
proc nimGCunref(p: pointer) {.compilerProc, inline.} = decRef(usrToCell(p))
proc GC_addCycleRoot*[T](p: ref T) {.inline.} =
## adds 'p' to the cycle candidate set for the cycle collector. It is
## necessary if you used the 'acyclic' pragma for optimization
## purposes and need to break cycles manually.
rtlAddCycleRoot(usrToCell(cast[pointer](p)))
proc nimGCunrefNoCycle(p: pointer) {.compilerProc, inline.} =
sysAssert(allocInv(gch.region), "begin nimGCunrefNoCycle")
var c = usrToCell(p)