* fixes #21171; dyn destructors for acyclic inherited refs * add a test * Update compiler/liftdestructors.nim
This commit is contained in:
parent
7a74c2dc3a
commit
4b63ac4b87
3 changed files with 97 additions and 0 deletions
|
|
@ -609,6 +609,11 @@ proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
createTypeBoundOps(c.g, c.c, elemType, c.info, c.idgen)
|
createTypeBoundOps(c.g, c.c, elemType, c.info, c.idgen)
|
||||||
let isCyclic = c.g.config.selectedGC == gcOrc and types.canFormAcycle(elemType)
|
let isCyclic = c.g.config.selectedGC == gcOrc and types.canFormAcycle(elemType)
|
||||||
|
|
||||||
|
let isInheritableAcyclicRef = c.g.config.selectedGC == gcOrc and
|
||||||
|
(not isPureObject(elemType)) and
|
||||||
|
tfAcyclic in skipTypes(elemType, abstractInst+{tyOwned}-{tyTypeDesc}).flags
|
||||||
|
# dynamic Acyclic refs need to use dyn decRef
|
||||||
|
|
||||||
let tmp =
|
let tmp =
|
||||||
if isCyclic and c.kind in {attachedAsgn, attachedSink}:
|
if isCyclic and c.kind in {attachedAsgn, attachedSink}:
|
||||||
declareTempOf(c, body, x)
|
declareTempOf(c, body, x)
|
||||||
|
|
@ -632,6 +637,8 @@ proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||||
cond = callCodegenProc(c.g, "nimDecRefIsLastCyclicStatic", c.info, tmp, typInfo)
|
cond = callCodegenProc(c.g, "nimDecRefIsLastCyclicStatic", c.info, tmp, typInfo)
|
||||||
else:
|
else:
|
||||||
cond = callCodegenProc(c.g, "nimDecRefIsLastCyclicDyn", c.info, tmp)
|
cond = callCodegenProc(c.g, "nimDecRefIsLastCyclicDyn", c.info, tmp)
|
||||||
|
elif isInheritableAcyclicRef:
|
||||||
|
cond = callCodegenProc(c.g, "nimDecRefIsLastDyn", c.info, x)
|
||||||
else:
|
else:
|
||||||
cond = callCodegenProc(c.g, "nimDecRefIsLast", c.info, x)
|
cond = callCodegenProc(c.g, "nimDecRefIsLast", c.info, x)
|
||||||
cond.typ = getSysType(c.g, x.info, tyBool)
|
cond.typ = getSysType(c.g, x.info, tyBool)
|
||||||
|
|
|
||||||
|
|
@ -485,6 +485,19 @@ proc nimDecRefIsLastCyclicDyn(p: pointer): bool {.compilerRtl, inl.} =
|
||||||
#if cell.color == colPurple:
|
#if cell.color == colPurple:
|
||||||
rememberCycle(result, cell, cast[ptr PNimTypeV2](p)[])
|
rememberCycle(result, cell, cast[ptr PNimTypeV2](p)[])
|
||||||
|
|
||||||
|
proc nimDecRefIsLastDyn(p: pointer): bool {.compilerRtl, inl.} =
|
||||||
|
if p != nil:
|
||||||
|
var cell = head(p)
|
||||||
|
if (cell.rc and not rcMask) == 0:
|
||||||
|
result = true
|
||||||
|
#cprintf("[DESTROY] %p\n", p)
|
||||||
|
else:
|
||||||
|
dec cell.rc, rcIncrement
|
||||||
|
#if cell.color == colPurple:
|
||||||
|
if result:
|
||||||
|
if cell.rootIdx > 0:
|
||||||
|
unregisterCycle(cell)
|
||||||
|
|
||||||
proc nimDecRefIsLastCyclicStatic(p: pointer; desc: PNimTypeV2): bool {.compilerRtl, inl.} =
|
proc nimDecRefIsLastCyclicStatic(p: pointer; desc: PNimTypeV2): bool {.compilerRtl, inl.} =
|
||||||
if p != nil:
|
if p != nil:
|
||||||
var cell = head(p)
|
var cell = head(p)
|
||||||
|
|
|
||||||
77
tests/arc/t21184.nim
Normal file
77
tests/arc/t21184.nim
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
discard """
|
||||||
|
matrix: "--mm:orc"
|
||||||
|
"""
|
||||||
|
|
||||||
|
import std/[with]
|
||||||
|
|
||||||
|
type
|
||||||
|
Node* {.acyclic.} = ref object of RootObj
|
||||||
|
name: string
|
||||||
|
data: pointer
|
||||||
|
children: seq[Node]
|
||||||
|
TextNode = ref object of Node
|
||||||
|
text: string
|
||||||
|
|
||||||
|
proc fakeEcho(s: string) =
|
||||||
|
if s.len < 0:
|
||||||
|
echo s
|
||||||
|
|
||||||
|
proc newNode[T: Node](parent: Node): T =
|
||||||
|
new result
|
||||||
|
result.data = alloc0(250)
|
||||||
|
parent.children.add(result)
|
||||||
|
|
||||||
|
proc newRootNode(): Node =
|
||||||
|
new result
|
||||||
|
result.data = alloc0(250)
|
||||||
|
|
||||||
|
method printNode(node: Node) {.base.} =
|
||||||
|
fakeEcho node.name
|
||||||
|
|
||||||
|
method printNode(node: TextNode) =
|
||||||
|
procCall printNode(Node(node))
|
||||||
|
fakeEcho node.text
|
||||||
|
|
||||||
|
proc printChildren(node: Node) =
|
||||||
|
for child in node.children:
|
||||||
|
child.printNode()
|
||||||
|
printChildren(child)
|
||||||
|
|
||||||
|
proc free(node: Node) =
|
||||||
|
for child in node.children:
|
||||||
|
free(child)
|
||||||
|
dealloc(node.data)
|
||||||
|
|
||||||
|
template node(parent: Node, body: untyped): untyped =
|
||||||
|
var node = newNode[Node](parent)
|
||||||
|
with node:
|
||||||
|
body
|
||||||
|
|
||||||
|
proc textNode(parent: Node, text: string) =
|
||||||
|
var node = newNode[TextNode](parent)
|
||||||
|
node.text = text
|
||||||
|
|
||||||
|
template withRootNode(body: untyped): untyped =
|
||||||
|
var root = newRootNode()
|
||||||
|
root.name = "root"
|
||||||
|
with root:
|
||||||
|
body
|
||||||
|
root.printNode()
|
||||||
|
printChildren(root)
|
||||||
|
root.free()
|
||||||
|
|
||||||
|
proc doTest() =
|
||||||
|
withRootNode:
|
||||||
|
node:
|
||||||
|
name = "child1"
|
||||||
|
node:
|
||||||
|
name = "child2"
|
||||||
|
node:
|
||||||
|
name = "child3"
|
||||||
|
textNode "Hello, world!"
|
||||||
|
|
||||||
|
|
||||||
|
# bug #21171
|
||||||
|
if isMainModule:
|
||||||
|
for i in 0..100000:
|
||||||
|
doTest()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue