summary refs log tree commit diff stats
path: root/lib/system
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2016-11-24 08:27:09 +0100
committerAndreas Rumpf <rumpf_a@web.de>2016-11-24 08:27:19 +0100
commit249fd5e56b60899b7ee2a7551f643307796247bc (patch)
tree36df2341786bd0a73afe2586fbac70432540d3f6 /lib/system
parent074f276c8a753bbb85788777b7c58a074f41329f (diff)
downloadNim-249fd5e56b60899b7ee2a7551f643307796247bc.tar.gz
further memtracking improvements
Diffstat (limited to 'lib/system')
-rw-r--r--lib/system/alloc.nim6
-rw-r--r--lib/system/gc.nim7
-rw-r--r--lib/system/memtracker.nim20
3 files changed, 27 insertions, 6 deletions
diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim
index 745bbbf62..3a8e8a1b6 100644
--- a/lib/system/alloc.nim
+++ b/lib/system/alloc.nim
@@ -15,6 +15,10 @@
 
 include osalloc
 
+template track(op, address, size) =
+  when defined(memTracker):
+    memTrackerOp(op, address, size)
+
 # We manage *chunks* of memory. Each chunk is a multiple of the page size.
 # Each chunk starts at an address that is divisible by the page size. Chunks
 # that are bigger than ``ChunkOsReturn`` are returned back to the operating
@@ -645,6 +649,7 @@ proc alloc(allocator: var MemRegion, size: Natural): pointer =
   cast[ptr FreeCell](result).zeroField = 1 # mark it as used
   sysAssert(not isAllocatedPtr(allocator, result), "alloc")
   result = cast[pointer](cast[ByteAddress](result) +% sizeof(FreeCell))
+  track("alloc", result, size)
 
 proc alloc0(allocator: var MemRegion, size: Natural): pointer =
   result = alloc(allocator, size)
@@ -658,6 +663,7 @@ proc dealloc(allocator: var MemRegion, p: pointer) =
   sysAssert(cast[ptr FreeCell](x).zeroField == 1, "dealloc 2")
   rawDealloc(allocator, x)
   sysAssert(not isAllocatedPtr(allocator, x), "dealloc 3")
+  track("dealloc", p, 0)
 
 proc realloc(allocator: var MemRegion, p: pointer, newsize: Natural): pointer =
   if newsize > 0:
diff --git a/lib/system/gc.nim b/lib/system/gc.nim
index 11897ce80..3bb0f62ff 100644
--- a/lib/system/gc.nim
+++ b/lib/system/gc.nim
@@ -468,6 +468,7 @@ proc rawNewObj(typ: PNimType, size: int, gch: var GcHeap): pointer =
   # its refcount is zero, so add it to the ZCT:
   addNewObjToZCT(res, gch)
   when logGC: writeCell("new cell", res)
+  track("rawNewObj", res, size)
   gcTrace(res, csAllocated)
   release(gch)
   when useCellIds:
@@ -519,6 +520,7 @@ proc newObjRC1(typ: PNimType, size: int): pointer {.compilerRtl.} =
   res.refcount = rcIncrement # refcount is 1
   sysAssert(isAllocatedPtr(gch.region, res), "newObj: 3")
   when logGC: writeCell("new cell", res)
+  track("newObjRC1", res, size)
   gcTrace(res, csAllocated)
   release(gch)
   when useCellIds:
@@ -561,6 +563,8 @@ proc growObj(old: pointer, newsize: int, gch: var GcHeap): pointer =
     writeCell("growObj new cell", res)
   gcTrace(ol, csZctFreed)
   gcTrace(res, csAllocated)
+  track("growObj old", ol, 0)
+  track("growObj new", res, newsize)
   when reallyDealloc:
     sysAssert(allocInv(gch.region), "growObj before dealloc")
     if ol.refcount shr rcShift <=% 1:
@@ -604,6 +608,7 @@ proc growObj(old: pointer, newsize: int): pointer {.rtl.} =
 proc freeCyclicCell(gch: var GcHeap, c: PCell) =
   prepareDealloc(c)
   gcTrace(c, csCycFreed)
+  track("cycle collector dealloc cell", c, 0)
   when logGC: writeCell("cycle collector dealloc cell", c)
   when reallyDealloc:
     sysAssert(allocInv(gch.region), "free cyclic cell")
@@ -673,6 +678,7 @@ proc doOperation(p: pointer, op: WalkOp) =
     gcAssert(c.refcount >=% rcIncrement, "doOperation 2")
     #c.refcount = c.refcount -% rcIncrement
     when logGC: writeCell("decref (from doOperation)", c)
+    track("waZctDecref", p, 0)
     decRef(c)
     #if c.refcount <% rcIncrement: addZCT(gch.zct, c)
   of waPush:
@@ -765,6 +771,7 @@ proc collectZCT(gch: var GcHeap): bool =
       # In any case, it should be removed from the ZCT. But not
       # freed. **KEEP THIS IN MIND WHEN MAKING THIS INCREMENTAL!**
       when logGC: writeCell("zct dealloc cell", c)
+      track("zct dealloc cell", c, 0)
       gcTrace(c, csZctFreed)
       # We are about to free the object, call the finalizer BEFORE its
       # children are deleted as well, because otherwise the finalizer may
diff --git a/lib/system/memtracker.nim b/lib/system/memtracker.nim
index b4a5460fa..a9767bbca 100644
--- a/lib/system/memtracker.nim
+++ b/lib/system/memtracker.nim
@@ -27,8 +27,9 @@ type
     line*: int
   TrackLog* = object
     count*: int
+    disabled: bool
     data*: array[4000, LogEntry]
-  TrackLogger* = proc (log: TrackLog) {.nimcall.}
+  TrackLogger* = proc (log: TrackLog) {.nimcall, tags: [], locks: 0.}
 
 var
   gLog*: TrackLog
@@ -38,11 +39,12 @@ proc setTrackLogger*(logger: TrackLogger) =
   gLogger = logger
 
 proc addEntry(entry: LogEntry) =
-  if gLog.count > high(gLog.data):
-    gLogger(gLog)
-    gLog.count = 0
-  gLog.data[gLog.count] = entry
-  inc gLog.count
+  if not gLog.disabled:
+    if gLog.count > high(gLog.data):
+      gLogger(gLog)
+      gLog.count = 0
+    gLog.data[gLog.count] = entry
+    inc gLog.count
 
 proc memTrackerWrite(address: pointer; size: int; file: cstring; line: int) {.compilerProc.} =
   addEntry LogEntry(op: "write", address: address,
@@ -52,6 +54,12 @@ proc memTrackerOp*(op: cstring; address: pointer; size: int) =
   addEntry LogEntry(op: op, address: address, size: size,
       file: "", line: 0)
 
+proc memTrackerDisable*() =
+  gLog.disabled = true
+
+proc memTrackerEnable*() =
+  gLog.disabled = false
+
 proc logPendingOps() {.noconv.} =
   # forward declared and called from Nim's signal handler.
   gLogger(gLog)