mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-31 10:22:15 +00:00
more checking for --gc:arc, no need for valgrind (#14467)
* sigmatch: removed dead code
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
30
lib/system/bitmasks.nim
Normal 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
|
||||
43
lib/system/cellseqs_v1.nim
Normal file
43
lib/system/cellseqs_v1.nim
Normal 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
|
||||
@@ -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 ---------------------------------------
|
||||
|
||||
|
||||
@@ -60,7 +60,6 @@ const
|
||||
colGreen = 0b000
|
||||
colYellow = 0b001
|
||||
colRed = 0b010
|
||||
rcShift = 3 # shift by rcShift to get the reference counter
|
||||
colorMask = 0b011
|
||||
|
||||
type
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -15,7 +15,6 @@ proc supportsCopyMem(t: typedesc): bool {.magic: "TypeTrait".}
|
||||
|
||||
## Default seq implementation used by Nim's core.
|
||||
type
|
||||
|
||||
NimSeqPayloadBase = object
|
||||
cap: int
|
||||
|
||||
|
||||
Reference in New Issue
Block a user