summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2020-05-29 12:08:17 +0200
committerGitHub <noreply@github.com>2020-05-29 12:08:17 +0200
commite31ac81899767e4cebb706ed473dae7ff6f0afd7 (patch)
tree07dc41f3d9b45216bafd5fc6ab18bb629f4dd050 /lib
parent4c08e64e9868dabca4a1a82979b74bda5c7d0329 (diff)
downloadNim-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.nim30
-rw-r--r--lib/system/cellseqs_v1.nim43
-rw-r--r--lib/system/cellsets.nim68
-rw-r--r--lib/system/cyclebreaker.nim1
-rw-r--r--lib/system/cyclicrefs_bacon.nim1
-rw-r--r--lib/system/mmdisp.nim25
-rw-r--r--lib/system/refs_v2.nim45
-rw-r--r--lib/system/seqs_v2.nim1
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