diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2020-05-29 12:08:17 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-29 12:08:17 +0200 |
commit | e31ac81899767e4cebb706ed473dae7ff6f0afd7 (patch) | |
tree | 07dc41f3d9b45216bafd5fc6ab18bb629f4dd050 /lib | |
parent | 4c08e64e9868dabca4a1a82979b74bda5c7d0329 (diff) | |
download | Nim-e31ac81899767e4cebb706ed473dae7ff6f0afd7.tar.gz |
more checking for --gc:arc, no need for valgrind (#14467)
* sigmatch: removed dead code
Diffstat (limited to 'lib')
-rw-r--r-- | lib/system/bitmasks.nim | 30 | ||||
-rw-r--r-- | lib/system/cellseqs_v1.nim | 43 | ||||
-rw-r--r-- | lib/system/cellsets.nim | 68 | ||||
-rw-r--r-- | lib/system/cyclebreaker.nim | 1 | ||||
-rw-r--r-- | lib/system/cyclicrefs_bacon.nim | 1 | ||||
-rw-r--r-- | lib/system/mmdisp.nim | 25 | ||||
-rw-r--r-- | lib/system/refs_v2.nim | 45 | ||||
-rw-r--r-- | lib/system/seqs_v2.nim | 1 |
8 files changed, 145 insertions, 69 deletions
diff --git a/lib/system/bitmasks.nim b/lib/system/bitmasks.nim new file mode 100644 index 000000000..922ad5fb7 --- /dev/null +++ b/lib/system/bitmasks.nim @@ -0,0 +1,30 @@ +# +# +# Nim's Runtime Library +# (c) Copyright 2015 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +# Page size of the system; in most cases 4096 bytes. For exotic OS or +# CPU this needs to be changed: +const + PageShift = when defined(cpu16): 8 else: 12 # \ + # my tests showed no improvements for using larger page sizes. + PageSize = 1 shl PageShift + PageMask = PageSize-1 + + MemAlign = 16 # also minimal allocatable memory block + + BitsPerPage = PageSize div MemAlign + UnitsPerPage = BitsPerPage div (sizeof(int)*8) + # how many ints do we need to describe a page: + # on 32 bit systems this is only 16 (!) + + TrunkShift = 9 + BitsPerTrunk = 1 shl TrunkShift # needs to be power of 2 and divisible by 64 + TrunkMask = BitsPerTrunk - 1 + IntsPerTrunk = BitsPerTrunk div (sizeof(int)*8) + IntShift = 5 + ord(sizeof(int) == 8) # 5 or 6, depending on int width + IntMask = 1 shl IntShift - 1 diff --git a/lib/system/cellseqs_v1.nim b/lib/system/cellseqs_v1.nim new file mode 100644 index 000000000..1952491b3 --- /dev/null +++ b/lib/system/cellseqs_v1.nim @@ -0,0 +1,43 @@ +# +# +# Nim's Runtime Library +# (c) Copyright 2019 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +# ------------------- cell seq handling --------------------------------------- + +type + PCellArray = ptr UncheckedArray[PCell] + CellSeq {.final, pure.} = object + len, cap: int + d: PCellArray + +proc contains(s: CellSeq, c: PCell): bool {.inline.} = + for i in 0 .. s.len-1: + if s.d[i] == c: return true + return false + +proc add(s: var CellSeq, c: PCell) {.inline.} = + if s.len >= s.cap: + s.cap = s.cap * 3 div 2 + var d = cast[PCellArray](alloc(s.cap * sizeof(PCell))) + copyMem(d, s.d, s.len * sizeof(PCell)) + dealloc(s.d) + s.d = d + # XXX: realloc? + s.d[s.len] = c + inc(s.len) + +proc init(s: var CellSeq, cap: int = 1024) = + s.len = 0 + s.cap = cap + s.d = cast[PCellArray](alloc0(cap * sizeof(PCell))) + +proc deinit(s: var CellSeq) = + dealloc(s.d) + s.d = nil + s.len = 0 + s.cap = 0 diff --git a/lib/system/cellsets.nim b/lib/system/cellsets.nim index c73c84f52..ea00176b5 100644 --- a/lib/system/cellsets.nim +++ b/lib/system/cellsets.nim @@ -9,20 +9,28 @@ # Efficient set of pointers for the GC (and repr) -type - RefCount = int +when defined(gcOrc) or defined(gcArc): + type + PCell = Cell - Cell {.pure.} = object - refcount: RefCount # the refcount and some flags - typ: PNimType - when trackAllocationSource: - filename: cstring - line: int - when useCellIds: - id: int + include bitmasks + +else: + type + RefCount = int - PCell = ptr Cell + Cell {.pure.} = object + refcount: RefCount # the refcount and some flags + typ: PNimType + when trackAllocationSource: + filename: cstring + line: int + when useCellIds: + id: int + PCell = ptr Cell + +type PPageDesc = ptr PageDesc BitIndex = range[0..UnitsPerPage-1] PageDesc {.final, pure.} = object @@ -35,39 +43,11 @@ type counter, max: int head: PPageDesc data: PPageDescArray - PCellArray = ptr UncheckedArray[PCell] - CellSeq {.final, pure.} = object - len, cap: int - d: PCellArray - -# ------------------- cell seq handling --------------------------------------- - -proc contains(s: CellSeq, c: PCell): bool {.inline.} = - for i in 0 .. s.len-1: - if s.d[i] == c: return true - return false - -proc add(s: var CellSeq, c: PCell) {.inline.} = - if s.len >= s.cap: - s.cap = s.cap * 3 div 2 - var d = cast[PCellArray](alloc(s.cap * sizeof(PCell))) - copyMem(d, s.d, s.len * sizeof(PCell)) - dealloc(s.d) - s.d = d - # XXX: realloc? - s.d[s.len] = c - inc(s.len) - -proc init(s: var CellSeq, cap: int = 1024) = - s.len = 0 - s.cap = cap - s.d = cast[PCellArray](alloc0(cap * sizeof(PCell))) - -proc deinit(s: var CellSeq) = - dealloc(s.d) - s.d = nil - s.len = 0 - s.cap = 0 + +when defined(gcOrc) or defined(gcArc): + discard +else: + include cellseqs_v1 # ------------------- cell set handling --------------------------------------- diff --git a/lib/system/cyclebreaker.nim b/lib/system/cyclebreaker.nim index 4b7f8db5a..3d01eeb9d 100644 --- a/lib/system/cyclebreaker.nim +++ b/lib/system/cyclebreaker.nim @@ -60,7 +60,6 @@ const colGreen = 0b000 colYellow = 0b001 colRed = 0b010 - rcShift = 3 # shift by rcShift to get the reference counter colorMask = 0b011 type diff --git a/lib/system/cyclicrefs_bacon.nim b/lib/system/cyclicrefs_bacon.nim index 5f0197384..b9c820e4a 100644 --- a/lib/system/cyclicrefs_bacon.nim +++ b/lib/system/cyclicrefs_bacon.nim @@ -24,7 +24,6 @@ const colPurple = 0b011 isCycleCandidate = 0b100 # cell is marked as a cycle candidate jumpStackFlag = 0b1000 - rcShift = 4 # shift by rcShift to get the reference counter colorMask = 0b011 type diff --git a/lib/system/mmdisp.nim b/lib/system/mmdisp.nim index 5cdac2991..5fe1960d1 100644 --- a/lib/system/mmdisp.nim +++ b/lib/system/mmdisp.nim @@ -38,27 +38,10 @@ type PByte = ptr ByteArray PString = ptr string -# Page size of the system; in most cases 4096 bytes. For exotic OS or -# CPU this needs to be changed: -const - PageShift = when defined(cpu16): 8 else: 12 # \ - # my tests showed no improvements for using larger page sizes. - PageSize = 1 shl PageShift - PageMask = PageSize-1 - - MemAlign = 16 # also minimal allocatable memory block - - BitsPerPage = PageSize div MemAlign - UnitsPerPage = BitsPerPage div (sizeof(int)*8) - # how many ints do we need to describe a page: - # on 32 bit systems this is only 16 (!) - - TrunkShift = 9 - BitsPerTrunk = 1 shl TrunkShift # needs to be power of 2 and divisible by 64 - TrunkMask = BitsPerTrunk - 1 - IntsPerTrunk = BitsPerTrunk div (sizeof(int)*8) - IntShift = 5 + ord(sizeof(int) == 8) # 5 or 6, depending on int width - IntMask = 1 shl IntShift - 1 +when declared(IntsPerTrunk): + discard +else: + include bitmasks proc raiseOutOfMem() {.noinline.} = if outOfMemHook != nil: outOfMemHook() diff --git a/lib/system/refs_v2.nim b/lib/system/refs_v2.nim index 8e5e03d3d..df1248586 100644 --- a/lib/system/refs_v2.nim +++ b/lib/system/refs_v2.nim @@ -38,11 +38,13 @@ when defined(gcOrc): const rcIncrement = 0b10000 # so that lowest 4 bits are not touched rcMask = 0b1111 + rcShift = 4 # shift by rcShift to get the reference counter else: const rcIncrement = 0b1000 # so that lowest 3 bits are not touched rcMask = 0b111 + rcShift = 3 # shift by rcShift to get the reference counter type RefHeader = object @@ -52,6 +54,8 @@ type when defined(gcOrc): rootIdx: int # thanks to this we can delete potential cycle roots # in O(1) without doubly linked lists + when defined(nimArcDebug): + refId: int Cell = ptr RefHeader @@ -67,6 +71,14 @@ template head(p: pointer): Cell = const traceCollector = defined(traceArc) +when defined(nimArcDebug): + include cellsets + + const traceId = 7739 # 1037 + + var gRefId: int + var freedCells: CellSet + proc nimNewObj(size: int): pointer {.compilerRtl.} = let s = size + sizeof(RefHeader) when defined(nimscript): @@ -79,6 +91,9 @@ proc nimNewObj(size: int): pointer {.compilerRtl.} = result = allocShared0(s) +! sizeof(RefHeader) else: result = alloc0(s) +! sizeof(RefHeader) + when defined(nimArcDebug): + head(result).refId = gRefId + atomicInc gRefId when traceCollector: cprintf("[Allocated] %p result: %p\n", result -! sizeof(RefHeader), result) @@ -98,6 +113,9 @@ proc nimNewObjUninit(size: int): pointer {.compilerRtl.} = when defined(gcOrc): orig.rootIdx = 0 result = orig +! sizeof(RefHeader) + when defined(nimArcDebug): + head(result).refId = gRefId + atomicInc gRefId when traceCollector: cprintf("[Allocated] %p result: %p\n", result -! sizeof(RefHeader), result) @@ -105,10 +123,25 @@ proc nimDecWeakRef(p: pointer) {.compilerRtl, inl.} = dec head(p).rc, rcIncrement proc nimIncRef(p: pointer) {.compilerRtl, inl.} = + when defined(nimArcDebug): + if head(p).refId == traceId: + writeStackTrace() + cfprintf(cstderr, "[IncRef] %p %ld\n", p, head(p).rc shr rcShift) + inc head(p).rc, rcIncrement when traceCollector: cprintf("[INCREF] %p\n", head(p)) +when not defined(nimscript) and defined(nimArcDebug): + proc deallocatedRefId*(p: pointer): int = + ## Returns the ref's ID if the ref was already deallocated. This + ## is a memory corruption check. Returns 0 if there is no error. + let c = head(p) + if freedCells.data != nil and freedCells.contains(c): + result = c.refId + else: + result = 0 + proc nimRawDispose(p: pointer) {.compilerRtl.} = when not defined(nimscript): when traceCollector: @@ -117,7 +150,11 @@ proc nimRawDispose(p: pointer) {.compilerRtl.} = if head(p).rc >= rcIncrement: cstderr.rawWrite "[FATAL] dangling references exist\n" quit 1 - when defined(useMalloc): + when defined(nimArcDebug): + # we do NOT really free the memory here in order to reliably detect use-after-frees + if freedCells.data == nil: init(freedCells) + freedCells.incl head(p) + elif defined(useMalloc): c_free(p -! sizeof(RefHeader)) elif compileOption("threads"): deallocShared(p -! sizeof(RefHeader)) @@ -150,6 +187,12 @@ when defined(gcOrc): proc nimDecRefIsLast(p: pointer): bool {.compilerRtl, inl.} = if p != nil: var cell = head(p) + + when defined(nimArcDebug): + if cell.refId == traceId: + writeStackTrace() + cfprintf(cstderr, "[DecRef] %p %ld\n", p, cell.rc shr rcShift) + if (cell.rc and not rcMask) == 0: result = true when traceCollector: diff --git a/lib/system/seqs_v2.nim b/lib/system/seqs_v2.nim index 175056f48..1b40c00ab 100644 --- a/lib/system/seqs_v2.nim +++ b/lib/system/seqs_v2.nim @@ -15,7 +15,6 @@ proc supportsCopyMem(t: typedesc): bool {.magic: "TypeTrait".} ## Default seq implementation used by Nim's core. type - NimSeqPayloadBase = object cap: int |