diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2017-01-15 10:12:18 +0100 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2017-01-15 10:12:28 +0100 |
commit | 03916fa3b1a07eb4cbd88cf3afe359695caf5446 (patch) | |
tree | 18785dd1ae6e70c2479843a865dddf3a197d62d8 /lib | |
parent | e216e0debda7efcaf9681a1233a38414c690e54f (diff) | |
download | Nim-03916fa3b1a07eb4cbd88cf3afe359695caf5446.tar.gz |
M&S GC gets the heap dump feature
Diffstat (limited to 'lib')
-rw-r--r-- | lib/system/gc.nim | 90 | ||||
-rw-r--r-- | lib/system/gc_common.nim | 24 | ||||
-rw-r--r-- | lib/system/gc_ms.nim | 31 |
3 files changed, 76 insertions, 69 deletions
diff --git a/lib/system/gc.nim b/lib/system/gc.nim index 2c971b35d..18d41219d 100644 --- a/lib/system/gc.nim +++ b/lib/system/gc.nim @@ -167,15 +167,6 @@ 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) @@ -196,34 +187,16 @@ else: x <% rcIncrement template `++`(x: expr): stmt = inc(x, rcIncrement) -proc prepareDealloc(cell: PCell) = - when useMarkForDebug: - gcAssert(cell notin gch.marked, "Cell still alive!") - 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](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 +proc incRef(c: PCell) {.inline.} = + gcAssert(isAllocatedPtr(gch.region, c), "incRef: interiorPtr") + c.refcount = c.refcount +% rcIncrement + # and not colorMask + #writeCell("incRef", c) -template beforeDealloc(gch: var GcHeap; c: PCell; msg: typed) = - when false: - for i in 0..gch.decStack.len-1: - if gch.decStack.d[i] == c: - sysAssert(false, msg) +proc nimGCref(p: pointer) {.compilerProc.} = + # we keep it from being collected by pretending it's not even allocated: + add(gch.additionalRoots, usrToCell(p)) + incRef(usrToCell(p)) proc rtlAddCycleRoot(c: PCell) {.rtl, inl.} = # we MUST access gch as a global here, because this crosses DLL boundaries! @@ -246,17 +219,6 @@ proc decRef(c: PCell) {.inline.} = if --c.refcount: rtlAddZCT(c) -proc incRef(c: PCell) {.inline.} = - gcAssert(isAllocatedPtr(gch.region, c), "incRef: interiorPtr") - c.refcount = c.refcount +% rcIncrement - # and not colorMask - #writeCell("incRef", c) - -proc nimGCref(p: pointer) {.compilerProc.} = - # we keep it from being collected by pretending it's not even allocated: - add(gch.additionalRoots, usrToCell(p)) - incRef(usrToCell(p)) - proc nimGCunref(p: pointer) {.compilerProc.} = let cell = usrToCell(p) var L = gch.additionalRoots.len-1 @@ -270,6 +232,29 @@ proc nimGCunref(p: pointer) {.compilerProc.} = dec(i) decRef(usrToCell(p)) +include gc_common + +proc prepareDealloc(cell: PCell) = + when useMarkForDebug: + gcAssert(cell notin gch.marked, "Cell still alive!") + 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](t.finalizer))(cellToUsr(cell)) + dec(gch.recGcLock) + decTypeSize(cell, t) + +template beforeDealloc(gch: var GcHeap; c: PCell; msg: typed) = + when false: + for i in 0..gch.decStack.len-1: + if gch.decStack.d[i] == c: + sysAssert(false, msg) + proc GC_addCycleRoot*[T](p: ref T) {.inline.} = ## adds 'p' to the cycle candidate set for the cycle collector. It is ## necessary if you used the 'acyclic' pragma for optimization @@ -481,9 +466,7 @@ 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) + incTypeSize typ, size sysAssert(allocInv(gch.region), "rawNewObj begin") acquire(gch) gcAssert(typ.kind in {tyRef, tyString, tySequence}, "newObj: 1") @@ -531,9 +514,7 @@ 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) + incTypeSize typ, size sysAssert(allocInv(gch.region), "newObjRC1 begin") acquire(gch) gcAssert(typ.kind in {tyRef, tyString, tySequence}, "newObj: 1") @@ -578,6 +559,7 @@ proc growObj(old: pointer, newsize: int, gch: var GcHeap): pointer = var res = cast[PCell](rawAlloc(gch.region, newsize + sizeof(Cell))) var elemSize = 1 if ol.typ.kind != tyString: elemSize = ol.typ.base.size + incTypeSize ol.typ, newsize var oldsize = cast[PGenericSeq](old).len*elemSize + GenericSeqSize copyMem(res, ol, oldsize + sizeof(Cell)) @@ -765,8 +747,6 @@ proc gcMark(gch: var GcHeap, p: pointer) {.inline.} = add(gch.decStack, cell) sysAssert(allocInv(gch.region), "gcMark end") -include gc_common - proc markStackAndRegisters(gch: var GcHeap) {.noinline, cdecl.} = forEachStackSlot(gch, gcMark) diff --git a/lib/system/gc_common.nim b/lib/system/gc_common.nim index 513ede173..64acb7b24 100644 --- a/lib/system/gc_common.nim +++ b/lib/system/gc_common.nim @@ -17,6 +17,30 @@ proc protect*(x: pointer): ForeignCell = result.data = x result.owner = addr(gch) +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 decTypeSize(cell, t) = + 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 incTypeSize(typ, size) = + when defined(nimTypeNames): + inc typ.instances + inc typ.sizes, size+sizeof(Cell) + proc dispose*(x: ForeignCell) = when hasThreadSupport: # if we own it we can free it directly: diff --git a/lib/system/gc_ms.nim b/lib/system/gc_ms.nim index ec69f6e5f..63ca94698 100644 --- a/lib/system/gc_ms.nim +++ b/lib/system/gc_ms.nim @@ -28,7 +28,7 @@ template mulThreshold(x): expr {.immediate.} = x * 2 when defined(memProfiler): proc nimProfile(requestedSize: int) - + when hasThreadSupport: import sharedlist @@ -140,17 +140,6 @@ proc doOperation(p: pointer, op: WalkOp) {.benign.} proc forAllChildrenAux(dest: pointer, mt: PNimType, op: WalkOp) {.benign.} # we need the prototype here for debugging purposes -proc prepareDealloc(cell: PCell) = - if cell.typ.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)) - dec(gch.recGcLock) - proc nimGCref(p: pointer) {.compilerProc.} = # we keep it from being collected by pretending it's not even allocated: when false: @@ -173,6 +162,20 @@ proc nimGCunref(p: pointer) {.compilerProc.} = when withBitvectors: incl(gch.allocated, usrToCell(p)) else: usrToCell(p).refcount = rcWhite +include gc_common + +proc prepareDealloc(cell: PCell) = + if cell.typ.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)) + dec(gch.recGcLock) + decTypeSize cell, cell.typ + proc initGC() = when not defined(useNimRtl): gch.cycleThreshold = InitialThreshold @@ -235,6 +238,7 @@ proc forAllChildren(cell: PCell, op: WalkOp) = proc rawNewObj(typ: PNimType, size: int, gch: var GcHeap): pointer = # generates a new object and sets its reference counter to 0 + incTypeSize typ, size acquire(gch) gcAssert(typ.kind in {tyRef, tyString, tySequence}, "newObj: 1") collectCT(gch) @@ -300,6 +304,7 @@ proc growObj(old: pointer, newsize: int, gch: var GcHeap): pointer = var res = cast[PCell](rawAlloc(gch.region, newsize + sizeof(Cell))) var elemSize = 1 if ol.typ.kind != tyString: elemSize = ol.typ.base.size + incTypeSize ol.typ, newsize var oldsize = cast[PGenericSeq](old).len*elemSize + GenericSeqSize copyMem(res, ol, oldsize + sizeof(Cell)) @@ -414,8 +419,6 @@ proc gcMark(gch: var GcHeap, p: pointer) {.inline.} = if objStart != nil: mark(gch, objStart) -include gc_common - proc markStackAndRegisters(gch: var GcHeap) {.noinline, cdecl.} = forEachStackSlot(gch, gcMark) |