summary refs log tree commit diff stats
path: root/lib/system/gc_common.nim
diff options
context:
space:
mode:
Diffstat (limited to 'lib/system/gc_common.nim')
-rw-r--r--lib/system/gc_common.nim74
1 files changed, 66 insertions, 8 deletions
diff --git a/lib/system/gc_common.nim b/lib/system/gc_common.nim
index 484a4db9a..939776a58 100644
--- a/lib/system/gc_common.nim
+++ b/lib/system/gc_common.nim
@@ -18,12 +18,45 @@ proc protect*(x: pointer): ForeignCell =
   result.owner = addr(gch)
 
 when defined(nimTypeNames):
+  type InstancesInfo = array[400, (cstring, int, int)]
+  proc sortInstances(a: var InstancesInfo; n: int) =
+    # we use shellsort here; fast and simple
+    var h = 1
+    while true:
+      h = 3 * h + 1
+      if h > n: break
+    while true:
+      h = h div 3
+      for i in countup(h, n - 1):
+        var v = a[i]
+        var j = i
+        while a[j - h][2] < v[2]:
+          a[j] = a[j - h]
+          j = j - h
+          if j < h: break
+        a[j] = v
+      if h == 1: break
+
   proc dumpNumberOfInstances* =
+    # also add the allocated strings to the list of known types:
+    if strDesc.nextType == nil:
+      strDesc.nextType = nimTypeRoot
+      strDesc.name = "string"
+      nimTypeRoot = addr strDesc
+    var a: InstancesInfo
+    var n = 0
     var it = nimTypeRoot
+    var totalAllocated = 0
     while it != nil:
-      if it.instances > 0:
-        c_fprintf(stdout, "[Heap] %s: #%ld; bytes: %ld\n", it.name, it.instances, it.sizes)
+      if (it.instances > 0 or it.sizes != 0) and n < a.len:
+        a[n] = (it.name, it.instances, it.sizes)
+        inc n
+      inc totalAllocated, it.sizes
       it = it.nextType
+    sortInstances(a, n)
+    for i in 0 .. n-1:
+      c_fprintf(stdout, "[Heap] %s: #%ld; bytes: %ld\n", a[i][0], a[i][1], a[i][2])
+    c_fprintf(stdout, "[Heap] total number of bytes: %ld\n", totalAllocated)
 
   when defined(nimGcRefLeak):
     proc oomhandler() =
@@ -36,12 +69,12 @@ template decTypeSize(cell, t) =
   # XXX this needs to use atomics for multithreaded apps!
   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)
+      let cap = cast[PGenericSeq](cellToUsr(cell)).space
+      let size = if t.kind == tyString: cap+1+GenericSeqSize
+                 else: addInt(mulInt(cap, t.base.size), GenericSeqSize)
       dec t.sizes, size+sizeof(Cell)
     else:
-      dec t.sizes, t.size+sizeof(Cell)
+      dec t.sizes, t.base.size+sizeof(Cell)
     dec t.instances
 
 template incTypeSize(typ, size) =
@@ -167,7 +200,7 @@ when declared(threadType):
     if threadType == ThreadType.None:
       initAllocator()
       var stackTop {.volatile.}: pointer
-      setStackBottom(addr(stackTop))
+      nimGC_setStackBottom(addr(stackTop))
       initGC()
       threadType = ThreadType.ForeignThread
 
@@ -224,7 +257,7 @@ when nimCoroutines:
     gch.activeStack.setPosition(addr(sp))
 
 when not defined(useNimRtl):
-  proc setStackBottom(theStackBottom: pointer) =
+  proc nimGC_setStackBottom(theStackBottom: pointer) =
     # Initializes main stack of the thread.
     when nimCoroutines:
       if gch.stack.next == nil:
@@ -393,3 +426,28 @@ proc deallocHeap*(runFinalizers = true; allowGcAfterwards = true) =
   zeroMem(addr gch.region, sizeof(gch.region))
   if allowGcAfterwards:
     initGC()
+
+type
+  GlobalMarkerProc = proc () {.nimcall, benign.}
+var
+  globalMarkersLen: int
+  globalMarkers: array[0.. 3499, GlobalMarkerProc]
+  threadLocalMarkersLen: int
+  threadLocalMarkers: array[0.. 3499, GlobalMarkerProc]
+  gHeapidGenerator: int
+
+proc nimRegisterGlobalMarker(markerProc: GlobalMarkerProc) {.compilerProc.} =
+  if globalMarkersLen <= high(globalMarkers):
+    globalMarkers[globalMarkersLen] = markerProc
+    inc globalMarkersLen
+  else:
+    echo "[GC] cannot register global variable; too many global variables"
+    quit 1
+
+proc nimRegisterThreadLocalMarker(markerProc: GlobalMarkerProc) {.compilerProc.} =
+  if threadLocalMarkersLen <= high(threadLocalMarkers):
+    threadLocalMarkers[threadLocalMarkersLen] = markerProc
+    inc threadLocalMarkersLen
+  else:
+    echo "[GC] cannot register thread local variable; too many thread local variables"
+    quit 1