added GC_addCycleRoot

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

View file

@ -520,7 +520,7 @@ type
TNodeSeq* = seq[PNode] TNodeSeq* = seq[PNode]
PType* = ref TType PType* = ref TType
PSym* = ref TSym 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 typ*: PType
comment*: string comment*: string
info*: TLineInfo info*: TLineInfo
@ -605,7 +605,7 @@ type
PInstantiation* = ref TInstantiation PInstantiation* = ref TInstantiation
PLib* = ref TLib PLib* = ref TLib
TSym* = object of TIdObj TSym* {.acyclic.} = object of TIdObj
# proc and type instantiations are cached in the generic symbol # proc and type instantiations are cached in the generic symbol
case kind*: TSymKind case kind*: TSymKind
of skType: of skType:
@ -653,7 +653,8 @@ type
constraint*: PNode # additional constraints like 'lit|result' constraint*: PNode # additional constraints like 'lit|result'
TTypeSeq* = seq[PType] 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 # same id; there may be multiple copies of a type
# in memory! # in memory!
kind*: TTypeKind # kind of type 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 the GC with ``GC_enableMarkAndSweep`` and ``GC_disableMarkAndSweep``. The
compiler analyses the types for their possibility to build cycles, but often compiler analyses the types for their possibility to build cycles, but often
it is necessary to help this analysis with the ``acyclic`` pragma (see 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 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. 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 nimGCref(p: pointer) {.compilerProc, inline.} = incRef(usrToCell(p))
proc nimGCunref(p: pointer) {.compilerProc, inline.} = decRef(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.} = proc nimGCunrefNoCycle(p: pointer) {.compilerProc, inline.} =
sysAssert(allocInv(gch.region), "begin nimGCunrefNoCycle") sysAssert(allocInv(gch.region), "begin nimGCunrefNoCycle")
var c = usrToCell(p) var c = usrToCell(p)