ARC now capable of custom extra alignment. Ref, closure and seq support. (#15697)
This commit is contained in:
parent
732ddc02da
commit
0956a99537
11 changed files with 273 additions and 77 deletions
|
|
@ -75,14 +75,13 @@ when defined(nimArcDebug):
|
|||
elif defined(nimArcIds):
|
||||
var gRefId: int
|
||||
|
||||
proc nimNewObj(size: int): pointer {.compilerRtl.} =
|
||||
let s = size + sizeof(RefHeader)
|
||||
proc nimNewObj(size, alignment: int): pointer {.compilerRtl.} =
|
||||
let hdrSize = align(sizeof(RefHeader), alignment)
|
||||
let s = size + hdrSize
|
||||
when defined(nimscript):
|
||||
discard
|
||||
elif compileOption("threads"):
|
||||
result = allocShared0(s) +! sizeof(RefHeader)
|
||||
else:
|
||||
result = alloc0(s) +! sizeof(RefHeader)
|
||||
result = alignedAlloc0(s, alignment) +! hdrSize
|
||||
when defined(nimArcDebug) or defined(nimArcIds):
|
||||
head(result).refId = gRefId
|
||||
atomicInc gRefId
|
||||
|
|
@ -92,20 +91,18 @@ proc nimNewObj(size: int): pointer {.compilerRtl.} =
|
|||
when traceCollector:
|
||||
cprintf("[Allocated] %p result: %p\n", result -! sizeof(RefHeader), result)
|
||||
|
||||
proc nimNewObjUninit(size: int): pointer {.compilerRtl.} =
|
||||
proc nimNewObjUninit(size, alignment: int): pointer {.compilerRtl.} =
|
||||
# Same as 'newNewObj' but do not initialize the memory to zero.
|
||||
# The codegen proved for us that this is not necessary.
|
||||
let s = size + sizeof(RefHeader)
|
||||
let hdrSize = align(sizeof(RefHeader), alignment)
|
||||
let s = size + hdrSize
|
||||
when defined(nimscript):
|
||||
discard
|
||||
elif compileOption("threads"):
|
||||
var orig = cast[ptr RefHeader](allocShared(s))
|
||||
else:
|
||||
var orig = cast[ptr RefHeader](alloc(s))
|
||||
orig.rc = 0
|
||||
result = cast[ptr RefHeader](alignedAlloc0(s, alignment) +! hdrSize)
|
||||
head(result).rc = 0
|
||||
when defined(gcOrc):
|
||||
orig.rootIdx = 0
|
||||
result = orig +! sizeof(RefHeader)
|
||||
head(result).rootIdx = 0
|
||||
when defined(nimArcDebug):
|
||||
head(result).refId = gRefId
|
||||
atomicInc gRefId
|
||||
|
|
@ -147,7 +144,7 @@ when not defined(nimscript) and defined(nimArcDebug):
|
|||
else:
|
||||
result = 0
|
||||
|
||||
proc nimRawDispose(p: pointer) {.compilerRtl.} =
|
||||
proc nimRawDispose(p: pointer, alignment: int) {.compilerRtl.} =
|
||||
when not defined(nimscript):
|
||||
when traceCollector:
|
||||
cprintf("[Freed] %p\n", p -! sizeof(RefHeader))
|
||||
|
|
@ -155,27 +152,21 @@ proc nimRawDispose(p: pointer) {.compilerRtl.} =
|
|||
if head(p).rc >= rcIncrement:
|
||||
cstderr.rawWrite "[FATAL] dangling references exist\n"
|
||||
quit 1
|
||||
|
||||
when defined(gcOrc) and defined(nimArcDebug):
|
||||
if (head(p).rc and 0b100) != 0:
|
||||
cstderr.rawWrite "[FATAL] cycle root freed\n"
|
||||
quit 1
|
||||
|
||||
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 compileOption("threads"):
|
||||
deallocShared(p -! sizeof(RefHeader))
|
||||
else:
|
||||
dealloc(p -! sizeof(RefHeader))
|
||||
let hdrSize = align(sizeof(RefHeader), alignment)
|
||||
alignedDealloc(p -! hdrSize, alignment)
|
||||
|
||||
template dispose*[T](x: owned(ref T)) = nimRawDispose(cast[pointer](x))
|
||||
template dispose*[T](x: owned(ref T)) = nimRawDispose(cast[pointer](x), T.alignOf)
|
||||
#proc dispose*(x: pointer) = nimRawDispose(x)
|
||||
|
||||
proc nimDestroyAndDispose(p: pointer) {.compilerRtl, raises: [].} =
|
||||
let d = cast[ptr PNimTypeV2](p)[].destructor
|
||||
if d != nil: cast[DestructorProc](d)(p)
|
||||
let rti = cast[ptr PNimTypeV2](p)
|
||||
if rti.destructor != nil:
|
||||
cast[DestructorProc](rti.destructor)(p)
|
||||
when false:
|
||||
cstderr.rawWrite cast[ptr PNimTypeV2](p)[].name
|
||||
cstderr.rawWrite "\n"
|
||||
|
|
@ -183,7 +174,7 @@ proc nimDestroyAndDispose(p: pointer) {.compilerRtl, raises: [].} =
|
|||
cstderr.rawWrite "bah, nil\n"
|
||||
else:
|
||||
cstderr.rawWrite "has destructor!\n"
|
||||
nimRawDispose(p)
|
||||
nimRawDispose(p, rti.align)
|
||||
|
||||
when defined(gcOrc):
|
||||
when defined(nimThinout):
|
||||
|
|
@ -216,7 +207,7 @@ proc GC_unref*[T](x: ref T) =
|
|||
if nimDecRefIsLast(cast[pointer](x)):
|
||||
# XXX this does NOT work for virtual destructors!
|
||||
`=destroy`(x[])
|
||||
nimRawDispose(cast[pointer](x))
|
||||
nimRawDispose(cast[pointer](x), T.alignOf)
|
||||
|
||||
proc GC_ref*[T](x: ref T) =
|
||||
## New runtime only supports this operation for 'ref T'.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue