more checking for --gc:arc, no need for valgrind (#14467)

* sigmatch: removed dead code
This commit is contained in:
Andreas Rumpf
2020-05-29 12:08:17 +02:00
committed by GitHub
parent 4c08e64e98
commit e31ac81899
12 changed files with 159 additions and 73 deletions

View File

@@ -2067,7 +2067,8 @@ proc myClose(graph: ModuleGraph; b: PPassContext, n: PNode): PNode =
let disp = generateMethodDispatchers(graph)
for x in disp: genProcAux(m, x.sym)
m.g.modulesClosed.add m
let mm = m
m.g.modulesClosed.add mm
proc genForwardedProcs(g: BModuleList) =
# Forward declared proc:s lack bodies when first encountered, so they're given

View File

@@ -809,4 +809,7 @@ proc constructCfg*(s: PSym; body: PNode): ControlFlowGraph =
withBlock(s):
gen(c, body)
genImplicitReturn(c)
shallowCopy(result, c.code)
when defined(gcArc) or defined(gcOrc):
result = c.code # will move
else:
shallowCopy(result, c.code)

View File

@@ -354,6 +354,8 @@ proc genWasMoved(n: PNode; c: var Con): PNode =
result = newNodeI(nkCall, n.info)
result.add(newSymNode(createMagic(c.graph, "wasMoved", mWasMoved)))
result.add copyTree(n) #mWasMoved does not take the address
#if n.kind != nkSym:
# message(c.graph.config, n.info, warnUser, "wasMoved(" & $n & ")")
proc genDefaultCall(t: PType; c: Con; info: TLineInfo): PNode =
result = newNodeI(nkCall, info)

View File

@@ -993,6 +993,11 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
result = isNone
assert(f != nil)
when declared(deallocatedRefId):
let corrupt = deallocatedRefId(cast[pointer](f))
if corrupt != 0:
quit "it's corrupt " & $corrupt
if f.kind == tyUntyped:
if aOrig != nil: put(c, f, aOrig)
return isGeneric
@@ -1409,7 +1414,6 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
let roota = a.skipGenericAlias
let rootf = f.skipGenericAlias
var m = c
if a.kind == tyGenericInst:
if roota.base == rootf.base:
let nextFlags = flags + {trNoCovariance}

30
lib/system/bitmasks.nim Normal file
View File

@@ -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

View File

@@ -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

View File

@@ -9,20 +9,28 @@
# Efficient set of pointers for the GC (and repr)
when defined(gcOrc) or defined(gcArc):
type
PCell = Cell
include bitmasks
else:
type
RefCount = int
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
RefCount = int
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
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 ---------------------------------------

View File

@@ -60,7 +60,6 @@ const
colGreen = 0b000
colYellow = 0b001
colRed = 0b010
rcShift = 3 # shift by rcShift to get the reference counter
colorMask = 0b011
type

View File

@@ -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

View File

@@ -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()

View File

@@ -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:

View File

@@ -15,7 +15,6 @@ proc supportsCopyMem(t: typedesc): bool {.magic: "TypeTrait".}
## Default seq implementation used by Nim's core.
type
NimSeqPayloadBase = object
cap: int