summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2017-01-14 04:00:06 +0100
committerAndreas Rumpf <rumpf_a@web.de>2017-01-14 04:00:06 +0100
commit823fbd4e40fa19aca1eab1a425f668463d654f3c (patch)
tree9ba118d6a4f1f97c4cca5e982d22757e6cd2fffc /lib
parent9753782f96bcd9b35a4c45d6cb20de2a85c33e55 (diff)
downloadNim-823fbd4e40fa19aca1eab1a425f668463d654f3c.tar.gz
default GC can do a sort of heap dump via -d:nimTypeNames and dumpNumberOfInstances()
Diffstat (limited to 'lib')
-rw-r--r--lib/system/gc.nim29
-rw-r--r--lib/system/hti.nim6
2 files changed, 33 insertions, 2 deletions
diff --git a/lib/system/gc.nim b/lib/system/gc.nim
index 8d9dc9025..2c971b35d 100644
--- a/lib/system/gc.nim
+++ b/lib/system/gc.nim
@@ -167,6 +167,15 @@ proc writeCell(msg: cstring, c: PCell) =
     c_fprintf(stdout, "[GC] %s: %p %d %s rc=%ld; color=%ld\n",
               msg, c, kind, typName, c.refcount shr rcShift, c.color)
 
+
+when defined(nimTypeNames):
+  proc dumpNumberOfInstances* =
+    var it = nimTypeRoot
+    while it != nil:
+      if it.instances > 0:
+        c_fprintf(stdout, "[Heap] %s: #%ld; bytes: %ld\n", it.name, it.instances, it.sizes)
+      it = it.nextType
+
 template gcTrace(cell, state: expr): stmt {.immediate.} =
   when traceGC: traceCell(cell, state)
 
@@ -190,15 +199,25 @@ else:
 proc prepareDealloc(cell: PCell) =
   when useMarkForDebug:
     gcAssert(cell notin gch.marked, "Cell still alive!")
-  if cell.typ.finalizer != nil:
+  let t = cell.typ
+  if t.finalizer != nil:
     # the finalizer could invoke something that
     # allocates memory; this could trigger a garbage
     # collection. Since we are already collecting we
     # prevend recursive entering here by a lock.
     # XXX: we should set the cell's children to nil!
     inc(gch.recGcLock)
-    (cast[Finalizer](cell.typ.finalizer))(cellToUsr(cell))
+    (cast[Finalizer](t.finalizer))(cellToUsr(cell))
     dec(gch.recGcLock)
+  when defined(nimTypeNames):
+    if t.kind in {tyString, tySequence}:
+      let len = cast[PGenericSeq](cellToUsr(cell)).len
+      let base = if t.kind == tyString: 1 else: t.base.size
+      let size = addInt(mulInt(len, base), GenericSeqSize)
+      dec t.sizes, size+sizeof(Cell)
+    else:
+      dec t.sizes, t.size+sizeof(Cell)
+    dec t.instances
 
 template beforeDealloc(gch: var GcHeap; c: PCell; msg: typed) =
   when false:
@@ -462,6 +481,9 @@ template setFrameInfo(c: PCell) =
 
 proc rawNewObj(typ: PNimType, size: int, gch: var GcHeap): pointer =
   # generates a new object and sets its reference counter to 0
+  when defined(nimTypeNames):
+    inc typ.instances
+    inc typ.sizes, size+sizeof(Cell)
   sysAssert(allocInv(gch.region), "rawNewObj begin")
   acquire(gch)
   gcAssert(typ.kind in {tyRef, tyString, tySequence}, "newObj: 1")
@@ -509,6 +531,9 @@ proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.} =
 
 proc newObjRC1(typ: PNimType, size: int): pointer {.compilerRtl.} =
   # generates a new object and sets its reference counter to 1
+  when defined(nimTypeNames):
+    inc typ.instances
+    inc typ.sizes, size+sizeof(Cell)
   sysAssert(allocInv(gch.region), "newObjRC1 begin")
   acquire(gch)
   gcAssert(typ.kind in {tyRef, tyString, tySequence}, "newObj: 1")
diff --git a/lib/system/hti.nim b/lib/system/hti.nim
index d5cca7c1c..6ac976cb4 100644
--- a/lib/system/hti.nim
+++ b/lib/system/hti.nim
@@ -88,6 +88,12 @@ type
     deepcopy: proc (p: pointer): pointer {.nimcall, benign.}
     when defined(nimTypeNames):
       name: cstring
+      nextType: ptr TNimType
+      instances: int # count the number of instances
+      sizes: int # sizes of all instances in bytes
   PNimType = ptr TNimType
 
+when defined(nimTypeNames):
+  var nimTypeRoot {.codegenType.}: PNimType
+
 # node.len may be the ``first`` element of a set