further memtracking improvements

This commit is contained in:
Andreas Rumpf 2016-11-24 08:27:09 +01:00
commit 249fd5e56b
5 changed files with 29 additions and 8 deletions

View file

@ -32,7 +32,7 @@ template sbind(x: int; value) =
quit "could not bind value" quit "could not bind value"
when defined(memTracker): when defined(memTracker):
proc logEntries(log: TrackLog) {.nimcall.} = proc logEntries(log: TrackLog) {.nimcall, locks: 0, tags: [].} =
for i in 0..log.count-1: for i in 0..log.count-1:
var success = false var success = false
let e = log.data[i] let e = log.data[i]

View file

@ -15,6 +15,10 @@
include osalloc 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. # 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 # 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 # 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 cast[ptr FreeCell](result).zeroField = 1 # mark it as used
sysAssert(not isAllocatedPtr(allocator, result), "alloc") sysAssert(not isAllocatedPtr(allocator, result), "alloc")
result = cast[pointer](cast[ByteAddress](result) +% sizeof(FreeCell)) result = cast[pointer](cast[ByteAddress](result) +% sizeof(FreeCell))
track("alloc", result, size)
proc alloc0(allocator: var MemRegion, size: Natural): pointer = proc alloc0(allocator: var MemRegion, size: Natural): pointer =
result = alloc(allocator, size) result = alloc(allocator, size)
@ -658,6 +663,7 @@ proc dealloc(allocator: var MemRegion, p: pointer) =
sysAssert(cast[ptr FreeCell](x).zeroField == 1, "dealloc 2") sysAssert(cast[ptr FreeCell](x).zeroField == 1, "dealloc 2")
rawDealloc(allocator, x) rawDealloc(allocator, x)
sysAssert(not isAllocatedPtr(allocator, x), "dealloc 3") sysAssert(not isAllocatedPtr(allocator, x), "dealloc 3")
track("dealloc", p, 0)
proc realloc(allocator: var MemRegion, p: pointer, newsize: Natural): pointer = proc realloc(allocator: var MemRegion, p: pointer, newsize: Natural): pointer =
if newsize > 0: if newsize > 0:

View file

@ -468,6 +468,7 @@ proc rawNewObj(typ: PNimType, size: int, gch: var GcHeap): pointer =
# its refcount is zero, so add it to the ZCT: # its refcount is zero, so add it to the ZCT:
addNewObjToZCT(res, gch) addNewObjToZCT(res, gch)
when logGC: writeCell("new cell", res) when logGC: writeCell("new cell", res)
track("rawNewObj", res, size)
gcTrace(res, csAllocated) gcTrace(res, csAllocated)
release(gch) release(gch)
when useCellIds: when useCellIds:
@ -519,6 +520,7 @@ proc newObjRC1(typ: PNimType, size: int): pointer {.compilerRtl.} =
res.refcount = rcIncrement # refcount is 1 res.refcount = rcIncrement # refcount is 1
sysAssert(isAllocatedPtr(gch.region, res), "newObj: 3") sysAssert(isAllocatedPtr(gch.region, res), "newObj: 3")
when logGC: writeCell("new cell", res) when logGC: writeCell("new cell", res)
track("newObjRC1", res, size)
gcTrace(res, csAllocated) gcTrace(res, csAllocated)
release(gch) release(gch)
when useCellIds: when useCellIds:
@ -561,6 +563,8 @@ proc growObj(old: pointer, newsize: int, gch: var GcHeap): pointer =
writeCell("growObj new cell", res) writeCell("growObj new cell", res)
gcTrace(ol, csZctFreed) gcTrace(ol, csZctFreed)
gcTrace(res, csAllocated) gcTrace(res, csAllocated)
track("growObj old", ol, 0)
track("growObj new", res, newsize)
when reallyDealloc: when reallyDealloc:
sysAssert(allocInv(gch.region), "growObj before dealloc") sysAssert(allocInv(gch.region), "growObj before dealloc")
if ol.refcount shr rcShift <=% 1: 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) = proc freeCyclicCell(gch: var GcHeap, c: PCell) =
prepareDealloc(c) prepareDealloc(c)
gcTrace(c, csCycFreed) gcTrace(c, csCycFreed)
track("cycle collector dealloc cell", c, 0)
when logGC: writeCell("cycle collector dealloc cell", c) when logGC: writeCell("cycle collector dealloc cell", c)
when reallyDealloc: when reallyDealloc:
sysAssert(allocInv(gch.region), "free cyclic cell") sysAssert(allocInv(gch.region), "free cyclic cell")
@ -673,6 +678,7 @@ proc doOperation(p: pointer, op: WalkOp) =
gcAssert(c.refcount >=% rcIncrement, "doOperation 2") gcAssert(c.refcount >=% rcIncrement, "doOperation 2")
#c.refcount = c.refcount -% rcIncrement #c.refcount = c.refcount -% rcIncrement
when logGC: writeCell("decref (from doOperation)", c) when logGC: writeCell("decref (from doOperation)", c)
track("waZctDecref", p, 0)
decRef(c) decRef(c)
#if c.refcount <% rcIncrement: addZCT(gch.zct, c) #if c.refcount <% rcIncrement: addZCT(gch.zct, c)
of waPush: of waPush:
@ -765,6 +771,7 @@ proc collectZCT(gch: var GcHeap): bool =
# In any case, it should be removed from the ZCT. But not # In any case, it should be removed from the ZCT. But not
# freed. **KEEP THIS IN MIND WHEN MAKING THIS INCREMENTAL!** # freed. **KEEP THIS IN MIND WHEN MAKING THIS INCREMENTAL!**
when logGC: writeCell("zct dealloc cell", c) when logGC: writeCell("zct dealloc cell", c)
track("zct dealloc cell", c, 0)
gcTrace(c, csZctFreed) gcTrace(c, csZctFreed)
# We are about to free the object, call the finalizer BEFORE its # We are about to free the object, call the finalizer BEFORE its
# children are deleted as well, because otherwise the finalizer may # children are deleted as well, because otherwise the finalizer may

View file

@ -27,8 +27,9 @@ type
line*: int line*: int
TrackLog* = object TrackLog* = object
count*: int count*: int
disabled: bool
data*: array[4000, LogEntry] data*: array[4000, LogEntry]
TrackLogger* = proc (log: TrackLog) {.nimcall.} TrackLogger* = proc (log: TrackLog) {.nimcall, tags: [], locks: 0.}
var var
gLog*: TrackLog gLog*: TrackLog
@ -38,6 +39,7 @@ proc setTrackLogger*(logger: TrackLogger) =
gLogger = logger gLogger = logger
proc addEntry(entry: LogEntry) = proc addEntry(entry: LogEntry) =
if not gLog.disabled:
if gLog.count > high(gLog.data): if gLog.count > high(gLog.data):
gLogger(gLog) gLogger(gLog)
gLog.count = 0 gLog.count = 0
@ -52,6 +54,12 @@ proc memTrackerOp*(op: cstring; address: pointer; size: int) =
addEntry LogEntry(op: op, address: address, size: size, addEntry LogEntry(op: op, address: address, size: size,
file: "", line: 0) file: "", line: 0)
proc memTrackerDisable*() =
gLog.disabled = true
proc memTrackerEnable*() =
gLog.disabled = false
proc logPendingOps() {.noconv.} = proc logPendingOps() {.noconv.} =
# forward declared and called from Nim's signal handler. # forward declared and called from Nim's signal handler.
gLogger(gLog) gLogger(gLog)

View file

@ -110,7 +110,7 @@ type
Callback* = proc (para1: pointer, para2: int32, para3, Callback* = proc (para1: pointer, para2: int32, para3,
para4: cstringArray): int32{.cdecl.} para4: cstringArray): int32{.cdecl.}
Tbind_destructor_func* = proc (para1: pointer){.cdecl.} Tbind_destructor_func* = proc (para1: pointer){.cdecl, locks: 0, tags: [].}
Create_function_step_func* = proc (para1: Pcontext, para2: int32, Create_function_step_func* = proc (para1: Pcontext, para2: int32,
para3: PValueArg){.cdecl.} para3: PValueArg){.cdecl.}
Create_function_func_func* = proc (para1: Pcontext, para2: int32, Create_function_func_func* = proc (para1: Pcontext, para2: int32,