diff options
Diffstat (limited to 'lib/system/gc_common.nim')
-rw-r--r-- | lib/system/gc_common.nim | 74 |
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 |