allow old styled RTTI for arc/orc (#15331)

This commit is contained in:
Andreas Rumpf
2020-09-16 14:57:01 +02:00
committed by GitHub
parent 0aaf4e2dfa
commit fd31e8ff6f
23 changed files with 512 additions and 303 deletions

View File

@@ -59,12 +59,6 @@ type
Cell = ptr RefHeader
template `+!`(p: pointer, s: int): pointer =
cast[pointer](cast[int](p) +% s)
template `-!`(p: pointer, s: int): pointer =
cast[pointer](cast[int](p) -% s)
template head(p: pointer): Cell =
cast[Cell](cast[int](p) -% sizeof(RefHeader))
@@ -132,6 +126,14 @@ proc nimIncRef(p: pointer) {.compilerRtl, inl.} =
when traceCollector:
cprintf("[INCREF] %p\n", head(p))
proc unsureAsgnRef(dest: ptr pointer, src: pointer) {.inline.} =
# This is only used by the old RTTI mechanism and we know
# that 'dest[]' is nil and needs no destruction. Which is really handy
# as we cannot destroy the object reliably if it's an object of unknown
# compile-time type.
dest[] = src
if src != nil: nimIncRef src
when not defined(nimscript) and defined(nimArcDebug):
proc deallocatedRefId*(p: pointer): int =
## Returns the ref's ID if the ref was already deallocated. This
@@ -165,10 +167,10 @@ template dispose*[T](x: owned(ref T)) = nimRawDispose(cast[pointer](x))
#proc dispose*(x: pointer) = nimRawDispose(x)
proc nimDestroyAndDispose(p: pointer) {.compilerRtl, raises: [].} =
let d = cast[ptr PNimType](p)[].destructor
let d = cast[ptr PNimTypeV2](p)[].destructor
if d != nil: cast[DestructorProc](d)(p)
when false:
cstderr.rawWrite cast[ptr PNimType](p)[].name
cstderr.rawWrite cast[ptr PNimTypeV2](p)[].name
cstderr.rawWrite "\n"
if d == nil:
cstderr.rawWrite "bah, nil\n"
@@ -226,11 +228,11 @@ template tearDownForeignThreadGc* =
## With ``--gc:arc`` a nop.
discard
proc isObj(obj: PNimType, subclass: cstring): bool {.compilerRtl, inl.} =
proc isObj(obj: PNimTypeV2, subclass: cstring): bool {.compilerRtl, inl.} =
proc strstr(s, sub: cstring): cstring {.header: "<string.h>", importc.}
result = strstr(obj.name, subclass) != nil
proc chckObj(obj: PNimType, subclass: cstring) {.compilerRtl.} =
proc chckObj(obj: PNimTypeV2, subclass: cstring) {.compilerRtl.} =
# checks if obj is of type subclass:
if not isObj(obj, subclass): sysFatal(ObjectConversionDefect, "invalid object conversion")

View File

@@ -7,6 +7,8 @@
# distribution, for details about the copyright.
#
include seqs_v2_reimpl
proc genericResetAux(dest: pointer, n: ptr TNimNode) {.benign.}
proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) {.benign.}
@@ -38,6 +40,20 @@ proc genericAssignAux(dest, src: pointer, n: ptr TNimNode,
# echo "ugh memory corruption! ", n.kind
# quit 1
template deepSeqAssignImpl(operation, additionalArg) {.dirty.} =
var d = cast[ptr NimSeqV2Reimpl](dest)
var s = cast[ptr NimSeqV2Reimpl](src)
d.len = s.len
let elem = mt.base
d.p = cast[ptr NimSeqPayloadReimpl](newSeqPayload(s.len, elem.size, elem.align))
let bs = elem.size
let ba = elem.align
let headerSize = align(sizeof(NimSeqPayloadBase), ba)
for i in 0..d.len-1:
operation(d.p +! (headerSize+i*bs), s.p +! (headerSize+i*bs), mt.base, additionalArg)
proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) =
var
d = cast[ByteAddress](dest)
@@ -45,38 +61,46 @@ proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) =
sysAssert(mt != nil, "genericAssignAux 2")
case mt.kind
of tyString:
var x = cast[PPointer](dest)
var s2 = cast[PPointer](s)[]
if s2 == nil or shallow or (
cast[PGenericSeq](s2).reserved and seqShallowFlag) != 0:
unsureAsgnRef(x, s2)
when defined(nimSeqsV2):
var x = cast[ptr NimStringV2](dest)
var s2 = cast[ptr NimStringV2](s)[]
nimAsgnStrV2(x[], s2)
else:
unsureAsgnRef(x, copyString(cast[NimString](s2)))
var x = cast[PPointer](dest)
var s2 = cast[PPointer](s)[]
if s2 == nil or shallow or (
cast[PGenericSeq](s2).reserved and seqShallowFlag) != 0:
unsureAsgnRef(x, s2)
else:
unsureAsgnRef(x, copyString(cast[NimString](s2)))
of tySequence:
var s2 = cast[PPointer](src)[]
var seq = cast[PGenericSeq](s2)
var x = cast[PPointer](dest)
if s2 == nil or shallow or (seq.reserved and seqShallowFlag) != 0:
# this can happen! nil sequences are allowed
unsureAsgnRef(x, s2)
return
sysAssert(dest != nil, "genericAssignAux 3")
if ntfNoRefs in mt.base.flags:
var ss = nimNewSeqOfCap(mt, seq.len)
cast[PGenericSeq](ss).len = seq.len
unsureAsgnRef(x, ss)
var dst = cast[ByteAddress](cast[PPointer](dest)[])
copyMem(cast[pointer](dst +% align(GenericSeqSize, mt.base.align)),
cast[pointer](cast[ByteAddress](s2) +% align(GenericSeqSize, mt.base.align)),
seq.len *% mt.base.size)
when defined(nimSeqsV2):
deepSeqAssignImpl(genericAssignAux, shallow)
else:
unsureAsgnRef(x, newSeq(mt, seq.len))
var dst = cast[ByteAddress](cast[PPointer](dest)[])
for i in 0..seq.len-1:
genericAssignAux(
cast[pointer](dst +% align(GenericSeqSize, mt.base.align) +% i *% mt.base.size ),
cast[pointer](cast[ByteAddress](s2) +% align(GenericSeqSize, mt.base.align) +% i *% mt.base.size ),
mt.base, shallow)
var s2 = cast[PPointer](src)[]
var seq = cast[PGenericSeq](s2)
var x = cast[PPointer](dest)
if s2 == nil or shallow or (seq.reserved and seqShallowFlag) != 0:
# this can happen! nil sequences are allowed
unsureAsgnRef(x, s2)
return
sysAssert(dest != nil, "genericAssignAux 3")
if ntfNoRefs in mt.base.flags:
var ss = nimNewSeqOfCap(mt, seq.len)
cast[PGenericSeq](ss).len = seq.len
unsureAsgnRef(x, ss)
var dst = cast[ByteAddress](cast[PPointer](dest)[])
copyMem(cast[pointer](dst +% align(GenericSeqSize, mt.base.align)),
cast[pointer](cast[ByteAddress](s2) +% align(GenericSeqSize, mt.base.align)),
seq.len *% mt.base.size)
else:
unsureAsgnRef(x, newSeq(mt, seq.len))
var dst = cast[ByteAddress](cast[PPointer](dest)[])
for i in 0..seq.len-1:
genericAssignAux(
cast[pointer](dst +% align(GenericSeqSize, mt.base.align) +% i *% mt.base.size ),
cast[pointer](cast[ByteAddress](s2) +% align(GenericSeqSize, mt.base.align) +% i *% mt.base.size ),
mt.base, shallow)
of tyObject:
var it = mt.base
# don't use recursion here on the PNimType because the subtype
@@ -87,14 +111,19 @@ proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) =
genericAssignAux(dest, src, mt.node, shallow)
# we need to copy m_type field for tyObject, as it could be empty for
# sequence reallocations:
var pint = cast[ptr PNimType](dest)
# We need to copy the *static* type not the dynamic type:
# if p of TB:
# var tbObj = TB(p)
# tbObj of TC # needs to be false!
#c_fprintf(stdout, "%s %s\n", pint[].name, mt.name)
chckObjAsgn(cast[ptr PNimType](src)[], mt)
pint[] = mt # cast[ptr PNimType](src)[]
when defined(nimSeqsV2):
var pint = cast[ptr PNimTypeV2](dest)
#chckObjAsgn(cast[ptr PNimTypeV2](src)[].typeInfoV2, mt)
pint[] = cast[PNimTypeV2](mt.typeInfoV2)
else:
var pint = cast[ptr PNimType](dest)
# We need to copy the *static* type not the dynamic type:
# if p of TB:
# var tbObj = TB(p)
# tbObj of TC # needs to be false!
#c_fprintf(stdout, "%s %s\n", pint[].name, mt.name)
chckObjAsgn(cast[ptr PNimType](src)[], mt)
pint[] = mt # cast[ptr PNimType](src)[]
of tyTuple:
genericAssignAux(dest, src, mt.node, shallow)
of tyArray, tyArrayConstr:
@@ -175,8 +204,12 @@ proc objectInit(dest: pointer, typ: PNimType) =
of tyObject:
# iterate over any structural type
# here we have to init the type field:
var pint = cast[ptr PNimType](dest)
pint[] = typ
when defined(nimSeqsV2):
var pint = cast[ptr PNimTypeV2](dest)
pint[] = cast[PNimTypeV2](typ.typeInfoV2)
else:
var pint = cast[ptr PNimType](dest)
pint[] = typ
objectInitAux(dest, typ.node)
of tyTuple:
objectInitAux(dest, typ.node)
@@ -204,15 +237,34 @@ proc genericReset(dest: pointer, mt: PNimType) =
var d = cast[ByteAddress](dest)
sysAssert(mt != nil, "genericReset 2")
case mt.kind
of tyString, tyRef, tySequence:
of tyRef:
unsureAsgnRef(cast[PPointer](dest), nil)
of tyString:
when defined(nimSeqsV2):
var s = cast[ptr NimStringV2](dest)
frees(s[])
zeroMem(dest, mt.size)
else:
unsureAsgnRef(cast[PPointer](dest), nil)
of tySequence:
when defined(nimSeqsV2):
var s = cast[ptr NimSeqV2Reimpl](dest)
if s.p != nil:
deallocShared(s.p)
zeroMem(dest, mt.size)
else:
unsureAsgnRef(cast[PPointer](dest), nil)
of tyTuple:
genericResetAux(dest, mt.node)
of tyObject:
genericResetAux(dest, mt.node)
# also reset the type field for tyObject, for correct branch switching!
var pint = cast[ptr PNimType](dest)
pint[] = nil
when defined(nimSeqsV2):
var pint = cast[ptr PNimTypeV2](dest)
pint[] = nil
else:
var pint = cast[ptr PNimType](dest)
pint[] = nil
of tyArray, tyArrayConstr:
for i in 0..(mt.size div mt.base.size)-1:
genericReset(cast[pointer](d +% i *% mt.base.size), mt.base)

View File

@@ -10,13 +10,13 @@
# Cell seqs for cyclebreaker and cyclicrefs_v2.
type
CellTuple = (PT, PNimType)
CellTuple = (PT, PNimTypeV2)
CellArray = ptr UncheckedArray[CellTuple]
CellSeq = object
len, cap: int
d: CellArray
proc add(s: var CellSeq, c: PT; t: PNimType) {.inline.} =
proc add(s: var CellSeq, c: PT; t: PNimTypeV2) {.inline.} =
if s.len >= s.cap:
s.cap = s.cap * 3 div 2
when defined(useMalloc):
@@ -51,6 +51,6 @@ proc deinit(s: var CellSeq) =
s.len = 0
s.cap = 0
proc pop(s: var CellSeq): (PT, PNimType) =
proc pop(s: var CellSeq): (PT, PNimTypeV2) =
result = s.d[s.len-1]
dec s.len

View File

@@ -78,14 +78,14 @@ type
GcEnv = object
traceStack: CellSeq
proc trace(p: pointer; desc: PNimType; j: var GcEnv) {.inline.} =
proc trace(p: pointer; desc: PNimTypeV2; j: var GcEnv) {.inline.} =
when false:
cprintf("[Trace] desc: %p %p\n", desc, p)
cprintf("[Trace] trace: %p\n", desc.traceImpl)
if desc.traceImpl != nil:
cast[TraceProc](desc.traceImpl)(p, addr(j))
proc nimTraceRef(q: pointer; desc: PNimType; env: pointer) {.compilerRtl.} =
proc nimTraceRef(q: pointer; desc: PNimTypeV2; env: pointer) {.compilerRtl.} =
let p = cast[ptr pointer](q)
when traceCollector:
cprintf("[Trace] raw: %p\n", p)
@@ -101,11 +101,11 @@ proc nimTraceRefDyn(q: pointer; env: pointer) {.compilerRtl.} =
cprintf("[TraceDyn] deref: %p\n", p[])
if p[] != nil:
var j = cast[ptr GcEnv](env)
j.traceStack.add(p, cast[ptr PNimType](p[])[])
j.traceStack.add(p, cast[ptr PNimTypeV2](p[])[])
var markerGeneration: int
proc breakCycles(s: Cell; desc: PNimType) =
proc breakCycles(s: Cell; desc: PNimTypeV2) =
let markerColor = if (markerGeneration and 1) == 0: colRed
else: colYellow
atomicInc markerGeneration
@@ -147,7 +147,7 @@ proc thinout*[T](x: ref T) {.inline.} =
## and thus would keep the graph from being freed are `nil`'ed.
## This is a form of cycle collection that works well with Nim's ARC
## and its associated cost model.
proc getDynamicTypeInfo[T](x: T): PNimType {.magic: "GetTypeInfo", noSideEffect, locks: 0.}
proc getDynamicTypeInfo[T](x: T): PNimTypeV2 {.magic: "GetTypeInfoV2", noSideEffect, locks: 0.}
breakCycles(head(cast[pointer](x)), getDynamicTypeInfo(x[]))
@@ -158,7 +158,7 @@ proc thinout*[T: proc](x: T) {.inline.} =
""".}
let p = rawEnv(x)
breakCycles(head(p), cast[ptr PNimType](p)[])
breakCycles(head(p), cast[ptr PNimTypeV2](p)[])
proc nimDecRefIsLastCyclicDyn(p: pointer): bool {.compilerRtl, inl.} =
if p != nil:
@@ -171,7 +171,7 @@ proc nimDecRefIsLastCyclicDyn(p: pointer): bool {.compilerRtl, inl.} =
# According to Lins it's correct to do nothing else here.
#cprintf("[DeCREF] %p\n", p)
proc nimDecRefIsLastCyclicStatic(p: pointer; desc: PNimType): bool {.compilerRtl, inl.} =
proc nimDecRefIsLastCyclicStatic(p: pointer; desc: PNimTypeV2): bool {.compilerRtl, inl.} =
if p != nil:
var cell = head(p)
if (cell.rc and not rcMask) == 0:

View File

@@ -90,27 +90,35 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType; tab: var PtrTable) =
sysAssert(mt != nil, "genericDeepCopyAux 2")
case mt.kind
of tyString:
var x = cast[PPointer](dest)
var s2 = cast[PPointer](s)[]
if s2 == nil:
unsureAsgnRef(x, s2)
when defined(nimSeqsV2):
var x = cast[ptr NimStringV2](dest)
var s2 = cast[ptr NimStringV2](s)[]
nimAsgnStrV2(x[], s2)
else:
unsureAsgnRef(x, copyDeepString(cast[NimString](s2)))
var x = cast[PPointer](dest)
var s2 = cast[PPointer](s)[]
if s2 == nil:
unsureAsgnRef(x, s2)
else:
unsureAsgnRef(x, copyDeepString(cast[NimString](s2)))
of tySequence:
var s2 = cast[PPointer](src)[]
var seq = cast[PGenericSeq](s2)
var x = cast[PPointer](dest)
if s2 == nil:
unsureAsgnRef(x, s2)
return
sysAssert(dest != nil, "genericDeepCopyAux 3")
unsureAsgnRef(x, newSeq(mt, seq.len))
var dst = cast[ByteAddress](cast[PPointer](dest)[])
for i in 0..seq.len-1:
genericDeepCopyAux(
cast[pointer](dst +% align(GenericSeqSize, mt.base.align) +% i *% mt.base.size),
cast[pointer](cast[ByteAddress](s2) +% align(GenericSeqSize, mt.base.align) +% i *% mt.base.size),
mt.base, tab)
when defined(nimSeqsV2):
deepSeqAssignImpl(genericDeepCopyAux, tab)
else:
var s2 = cast[PPointer](src)[]
var seq = cast[PGenericSeq](s2)
var x = cast[PPointer](dest)
if s2 == nil:
unsureAsgnRef(x, s2)
return
sysAssert(dest != nil, "genericDeepCopyAux 3")
unsureAsgnRef(x, newSeq(mt, seq.len))
var dst = cast[ByteAddress](cast[PPointer](dest)[])
for i in 0..seq.len-1:
genericDeepCopyAux(
cast[pointer](dst +% align(GenericSeqSize, mt.base.align) +% i *% mt.base.size),
cast[pointer](cast[ByteAddress](s2) +% align(GenericSeqSize, mt.base.align) +% i *% mt.base.size),
mt.base, tab)
of tyObject:
# we need to copy m_type field for tyObject, as it could be empty for
# sequence reallocations:
@@ -151,7 +159,7 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType; tab: var PtrTable) =
sysAssert realType == mt, " types do differ"
# this version should work for any possible GC:
let typ = if mt.base.kind == tyObject: cast[ptr PNimType](s2)[] else: mt.base
let z = newObj(mt, typ.size)
let z = when defined(nimSeqsV2): nimNewObj(typ.size) else: newObj(mt, typ.size)
unsureAsgnRef(cast[PPointer](dest), z)
tab.put(s2, z)
genericDeepCopyAux(z, s2, typ, tab)
@@ -168,11 +176,11 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType; tab: var PtrTable) =
copyMem(dest, src, mt.size)
proc genericDeepCopy(dest, src: pointer, mt: PNimType) {.compilerproc.} =
GC_disable()
when not defined(nimSeqsV2): GC_disable()
var tab = initPtrTable()
genericDeepCopyAux(dest, src, mt, tab)
deinit tab
GC_enable()
when not defined(nimSeqsV2): GC_enable()
proc genericSeqDeepCopy(dest, src: pointer, mt: PNimType) {.compilerproc.} =
# also invoked for 'string'

View File

@@ -98,6 +98,8 @@ type
finalizer*: pointer # the finalizer for the type
marker*: proc (p: pointer, op: int) {.nimcall, benign, tags: [], raises: [].} # marker proc for GC
deepcopy: proc (p: pointer): pointer {.nimcall, benign, tags: [], raises: [].}
when defined(nimSeqsV2):
typeInfoV2*: pointer
when defined(nimTypeNames):
name: cstring
nextType: ptr TNimType

View File

@@ -65,8 +65,10 @@ proc growObj(old: pointer, newsize: int): pointer =
proc nimGCref(p: pointer) {.compilerproc, inline.} = discard
proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard
proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
dest[] = src
when not defined(gcDestructors):
proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
dest[] = src
proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
dest[] = src
proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline,

View File

@@ -53,7 +53,7 @@ type
toFree: CellSeq
freed, touched: int
proc trace(s: Cell; desc: PNimType; j: var GcEnv) {.inline.} =
proc trace(s: Cell; desc: PNimTypeV2; j: var GcEnv) {.inline.} =
if desc.traceImpl != nil:
var p = s +! sizeof(RefHeader)
cast[TraceProc](desc.traceImpl)(p, addr(j))
@@ -65,7 +65,7 @@ else:
let p = s +! sizeof(RefHeader)
cprintf("[%s] name %s RC %ld\n", str, p, s.rc shr rcShift)
proc free(s: Cell; desc: PNimType) {.inline.} =
proc free(s: Cell; desc: PNimTypeV2) {.inline.} =
when traceCollector:
cprintf("[From ] %p rc %ld color %ld\n", s, s.rc shr rcShift, s.color)
let p = s +! sizeof(RefHeader)
@@ -89,7 +89,7 @@ proc free(s: Cell; desc: PNimType) {.inline.} =
nimRawDispose(p)
proc nimTraceRef(q: pointer; desc: PNimType; env: pointer) {.compilerRtl.} =
proc nimTraceRef(q: pointer; desc: PNimTypeV2; env: pointer) {.compilerRtl.} =
let p = cast[ptr pointer](q)
if p[] != nil:
var j = cast[ptr GcEnv](env)
@@ -99,7 +99,7 @@ proc nimTraceRefDyn(q: pointer; env: pointer) {.compilerRtl.} =
let p = cast[ptr pointer](q)
if p[] != nil:
var j = cast[ptr GcEnv](env)
j.traceStack.add(head p[], cast[ptr PNimType](p[])[])
j.traceStack.add(head p[], cast[ptr PNimTypeV2](p[])[])
var
roots {.threadvar.}: CellSeq
@@ -115,7 +115,7 @@ proc unregisterCycle(s: Cell) =
roots.d[idx][0].rootIdx = idx
dec roots.len
proc scanBlack(s: Cell; desc: PNimType; j: var GcEnv) =
proc scanBlack(s: Cell; desc: PNimTypeV2; j: var GcEnv) =
#[
proc scanBlack(s: Cell) =
setColor(s, colBlack)
@@ -135,7 +135,7 @@ proc scanBlack(s: Cell; desc: PNimType; j: var GcEnv) =
t.setColor colBlack
trace(t, desc, j)
proc markGray(s: Cell; desc: PNimType; j: var GcEnv) =
proc markGray(s: Cell; desc: PNimTypeV2; j: var GcEnv) =
#[
proc markGray(s: Cell) =
if s.color != colGray:
@@ -163,7 +163,7 @@ proc markGray(s: Cell; desc: PNimType; j: var GcEnv) =
inc j.touched
trace(t, desc, j)
proc scan(s: Cell; desc: PNimType; j: var GcEnv) =
proc scan(s: Cell; desc: PNimTypeV2; j: var GcEnv) =
#[
proc scan(s: Cell) =
if s.color == colGray:
@@ -226,7 +226,7 @@ when false:
cfprintf(cstderr, "%s %p root index: %ld; RC: %ld; color: %ld\n",
msg, s, s.rootIdx, s.rc shr rcShift, s.color)
proc collectWhite(s: Cell; desc: PNimType; j: var GcEnv) =
proc collectWhite(s: Cell; desc: PNimTypeV2; j: var GcEnv) =
#[
proc collectWhite(s: Cell) =
if s.color == colWhite and not buffered(s):
@@ -315,7 +315,7 @@ proc collectCycles() =
when false:
cfprintf(cstderr, "[collectCycles] freed %ld new threshold %ld\n", j.freed, rootsThreshold)
proc registerCycle(s: Cell; desc: PNimType) =
proc registerCycle(s: Cell; desc: PNimTypeV2) =
if roots.len >= rootsThreshold:
collectCycles()
if roots.d == nil: init(roots)
@@ -334,7 +334,7 @@ proc GC_enableMarkAndSweep() =
proc GC_disableMarkAndSweep() =
rootsThreshold = high(int)
proc rememberCycle(isDestroyAction: bool; s: Cell; desc: PNimType) {.noinline.} =
proc rememberCycle(isDestroyAction: bool; s: Cell; desc: PNimTypeV2) {.noinline.} =
if isDestroyAction:
if (s.rc and isCycleCandidate) != 0:
s.rc = s.rc and not isCycleCandidate
@@ -356,9 +356,9 @@ proc nimDecRefIsLastCyclicDyn(p: pointer): bool {.compilerRtl, inl.} =
else:
dec cell.rc, rcIncrement
#if cell.color == colPurple:
rememberCycle(result, cell, cast[ptr PNimType](p)[])
rememberCycle(result, cell, cast[ptr PNimTypeV2](p)[])
proc nimDecRefIsLastCyclicStatic(p: pointer; desc: PNimType): bool {.compilerRtl, inl.} =
proc nimDecRefIsLastCyclicStatic(p: pointer; desc: PNimTypeV2): bool {.compilerRtl, inl.} =
if p != nil:
var cell = head(p)
if (cell.rc and not rcMask) == 0:

View File

@@ -22,7 +22,8 @@ type
cap: int
data: UncheckedArray[T]
NimSeqV2*[T] = object
NimSeqV2*[T] = object # \
# if you change this implementation, also change seqs_v2_reimpl.nim!
len: int
p: ptr NimSeqPayload[T]
@@ -40,12 +41,15 @@ proc newSeqPayload(cap, elemSize, elemAlign: int): pointer {.compilerRtl, raises
else:
result = nil
proc prepareSeqAdd(len: int; p: pointer; addlen, elemSize, elemAlign: int): pointer {.
noSideEffect, raises: [].} =
{.noSideEffect.}:
template `+!`(p: pointer, s: int): pointer =
cast[pointer](cast[int](p) +% s)
template `+!`(p: pointer, s: int): pointer =
cast[pointer](cast[int](p) +% s)
template `-!`(p: pointer, s: int): pointer =
cast[pointer](cast[int](p) -% s)
proc prepareSeqAdd(len: int; p: pointer; addlen, elemSize, elemAlign: int): pointer {.
noSideEffect, raises: [], compilerRtl.} =
{.noSideEffect.}:
let headerSize = align(sizeof(NimSeqPayloadBase), elemAlign)
if addlen <= 0:
result = p

View File

@@ -0,0 +1,17 @@
#
#
# Nim's Runtime Library
# (c) Copyright 2020 Nim contributors
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
type
NimSeqPayloadReimpl = object
cap: int
data: pointer
NimSeqV2Reimpl = object
len: int
p: ptr NimSeqPayloadReimpl