summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2013-02-12 08:45:01 +0100
committerAraq <rumpf_a@web.de>2013-02-12 08:45:01 +0100
commit0f2aa053d9e9bcbe67238c498ed96f27c8d737db (patch)
treed61a7b65ef2d9e1249a2bd16c5274e79e9b07b99
parent5e7dd69b000f762ce3659e5c615a648ede44bb52 (diff)
downloadNim-0f2aa053d9e9bcbe67238c498ed96f27c8d737db.tar.gz
added GC_addCycleRoot
-rwxr-xr-xcompiler/ast.nim7
-rw-r--r--doc/gc.txt7
-rw-r--r--lib/system/gc.nim6
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)