diff options
-rw-r--r-- | compiler/liftdestructors.nim | 9 | ||||
-rw-r--r-- | tests/destructor/towned_binary_tree.nim | 92 |
2 files changed, 96 insertions, 5 deletions
diff --git a/compiler/liftdestructors.nim b/compiler/liftdestructors.nim index 5fbf86071..2dcaa7984 100644 --- a/compiler/liftdestructors.nim +++ b/compiler/liftdestructors.nim @@ -126,7 +126,7 @@ proc newDeepCopyCall(op: PSym; x, y: PNode): PNode = proc useNoGc(c: TLiftCtx; t: PType): bool {.inline.} = result = optNimV2 in c.graph.config.globalOptions and - (tfHasGCedMem in t.flags or t.isGCedMem) + ({tfHasGCedMem, tfHasOwned} * t.flags != {} or t.isGCedMem) proc considerAsgnOrSink(c: var TLiftCtx; t: PType; body, x, y: PNode; field: var PSym): bool = @@ -171,7 +171,7 @@ proc considerAsgnOrSink(c: var TLiftCtx; t: PType; body, x, y: PNode; body.add newAsgnCall(c.graph, op, x, y) result = true -proc addDestructorCall(c: var TLiftCtx; t: PType; body, x: PNode): bool = +proc addDestructorCall(c: var TLiftCtx; t: PType; body, x: PNode) = var op = t.destructor if op == nil and useNoGc(c, t): op = produceSym(c.c, t, attachedDestructor, c.info) @@ -182,7 +182,6 @@ proc addDestructorCall(c: var TLiftCtx; t: PType; body, x: PNode): bool = markUsed(c.graph.config, c.info, op, c.graph.usageSym) onUse(c.info, op) body.add destructorCall(c.graph, op, x) - result = true elif useNoGc(c, t): internalError(c.graph.config, c.info, "type-bound operator could not be resolved") @@ -365,10 +364,10 @@ proc ownedRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = #var disposeCall = genBuiltin(c.graph, mDispose, "dispose", x) if isFinal(elemType): - discard addDestructorCall(c, elemType, actions, genDeref(x)) + addDestructorCall(c, elemType, actions, genDeref(x)) actions.add callCodegenProc(c.graph, "nimRawDispose", c.info, x) else: - discard addDestructorCall(c, elemType, newNodeI(nkStmtList, c.info), genDeref(x)) + addDestructorCall(c, elemType, newNodeI(nkStmtList, c.info), genDeref(x)) actions.add callCodegenProc(c.graph, "nimDestroyAndDispose", c.info, x) case c.kind diff --git a/tests/destructor/towned_binary_tree.nim b/tests/destructor/towned_binary_tree.nim new file mode 100644 index 000000000..372b1d3d8 --- /dev/null +++ b/tests/destructor/towned_binary_tree.nim @@ -0,0 +1,92 @@ +discard """ + cmd: '''nim c --newruntime $file''' + output: '''331665 +allocs 0''' +""" + +# bug #11053 + +import random + +type Node = ref object + x, y: int32 + left, right: owned Node + +proc newNode(x: int32): owned Node = + result = Node(x: x, y: rand(high int32).int32) + +proc merge(lower, greater: owned Node): owned Node = + if lower.isNil: + result = greater + elif greater.isNil: + result = lower + elif lower.y < greater.y: + lower.right = merge(lower.right, greater) + result = lower + else: + greater.left = merge(lower, greater.left) + result = greater + +proc splitBinary(orig: owned Node, value: int32): (owned Node, owned Node) = + if orig.isNil: + result = (nil, nil) + elif orig.x < value: + let splitPair = splitBinary(orig.right, value) + orig.right = splitPair[0] + result = (orig, splitPair[1]) + else: + let splitPair = splitBinary(orig.left, value) + orig.left = splitPair[1] + result = (splitPair[0], orig) + +proc merge3(lower, equal, greater: owned Node): owned Node = + merge(merge(lower, equal), greater) + +proc split(orig: owned Node, value: int32): tuple[lower, equal, greater: owned Node] = + let + (lower, equalGreater) = splitBinary(orig, value) + (equal, greater) = splitBinary(equalGreater, value + 1) + result = (lower, equal, greater) + +type Tree = object + root: owned Node + +proc hasValue(self: var Tree, x: int32): bool = + let splited = split(move self.root, x) + result = not splited.equal.isNil + self.root = merge3(splited.lower, splited.equal, splited.greater) + +proc insert(self: var Tree, x: int32) = + var splited = split(move self.root, x) + if splited.equal.isNil: + splited.equal = newNode(x) + self.root = merge3(splited.lower, splited.equal, splited.greater) + +proc erase(self: var Tree, x: int32) = + let splited = split(move self.root, x) + self.root = merge(splited.lower, splited.greater) + +proc main() = + var + tree = Tree() + cur = 5'i32 + res = 0 + + for i in 1 ..< 1000000: + let a = i mod 3 + cur = (cur * 57 + 43) mod 10007 + case a: + of 0: + tree.insert(cur) + of 1: + tree.erase(cur) + of 2: + if tree.hasValue(cur): + res += 1 + else: + discard + echo res + +when isMainModule: + main() + echo "allocs ", allocs |