diff options
-rwxr-xr-x | compiler/ast.nim | 7 | ||||
-rw-r--r-- | doc/gc.txt | 7 | ||||
-rw-r--r-- | lib/system/gc.nim | 6 |
3 files changed, 16 insertions, 4 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index 0e4700065..107489094 100755 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -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 diff --git a/doc/gc.txt b/doc/gc.txt index dfcfa07f3..975a89308 100644 --- a/doc/gc.txt +++ b/doc/gc.txt @@ -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. diff --git a/lib/system/gc.nim b/lib/system/gc.nim index 33b82686f..0ab5f4d94 100644 --- a/lib/system/gc.nim +++ b/lib/system/gc.nim @@ -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) |