mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-30 19:23:57 +00:00
allow old styled RTTI for arc/orc (#15331)
This commit is contained in:
@@ -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")
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
17
lib/system/seqs_v2_reimpl.nim
Normal file
17
lib/system/seqs_v2_reimpl.nim
Normal 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
|
||||
Reference in New Issue
Block a user