mirror of
https://github.com/nim-lang/Nim.git
synced 2026-06-09 05:14:20 +00:00
* fixes #21171; dyn destructors for acyclic inherited refs * add a test * Update compiler/liftdestructors.nim
This commit is contained in:
@@ -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)
|
||||
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 =
|
||||
if isCyclic and c.kind in {attachedAsgn, attachedSink}:
|
||||
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)
|
||||
else:
|
||||
cond = callCodegenProc(c.g, "nimDecRefIsLastCyclicDyn", c.info, tmp)
|
||||
elif isInheritableAcyclicRef:
|
||||
cond = callCodegenProc(c.g, "nimDecRefIsLastDyn", c.info, x)
|
||||
else:
|
||||
cond = callCodegenProc(c.g, "nimDecRefIsLast", c.info, x)
|
||||
cond.typ = getSysType(c.g, x.info, tyBool)
|
||||
|
||||
@@ -485,6 +485,19 @@ proc nimDecRefIsLastCyclicDyn(p: pointer): bool {.compilerRtl, inl.} =
|
||||
#if cell.color == colPurple:
|
||||
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.} =
|
||||
if p != nil:
|
||||
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()
|
||||
Reference in New Issue
Block a user