Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/ast.nim
Original file line number Diff line number Diff line change
Expand Up @@ -926,7 +926,7 @@ proc newProcNode*(kind: TNodeKind, info: TLineInfo, body: PNode,

const
AttachedOpToStr*: array[TTypeAttachedOp, string] = [
"=wasMoved", "=destroy", "=copy", "=dup", "=sink", "=trace", "=deepcopy"]
"=wasMoved", "=destroy", "=dispose", "=copy", "=dup", "=sink", "=trace", "=deepcopy"]

proc `$`*(s: PSym): string =
if s != nil:
Expand Down
5 changes: 5 additions & 0 deletions compiler/ast2nif.nim
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,7 @@ proc trExport(w: var Writer; n: PNode) =
let replayTag = registerTag("replay")
let repConverterTag = registerTag("repconverter")
let repDestroyTag = registerTag("repdestroy")
let repDisposeTag = registerTag("repdispose")
let repWasMovedTag = registerTag("repwasmoved")
let repCopyTag = registerTag("repcopy")
let repSinkTag = registerTag("repsink")
Expand Down Expand Up @@ -677,6 +678,8 @@ proc writeOp(w: var Writer; content: var TokenBuf; op: LogEntry) =
case op.op
of attachedDestructor:
content.addParLe repDestroyTag, NoLineInfo
of attachedDispose:
content.addParLe repDisposeTag, NoLineInfo
of attachedAsgn:
content.addParLe repCopyTag, NoLineInfo
of attachedWasMoved:
Expand Down Expand Up @@ -1576,6 +1579,8 @@ proc processTopLevel(c: var DecodeContext; s: var Stream; flags: set[LoadFlag];
t = loadLogOp(c, result.logOps, s, ConverterEntry, attachedTrace, module)
elif t.tagId == repDestroyTag:
t = loadLogOp(c, result.logOps, s, HookEntry, attachedDestructor, module)
elif t.tagId == repDisposeTag:
t = loadLogOp(c, result.logOps, s, HookEntry, attachedDispose, module)
elif t.tagId == repWasMovedTag:
t = loadLogOp(c, result.logOps, s, HookEntry, attachedWasMoved, module)
elif t.tagId == repCopyTag:
Expand Down
1 change: 1 addition & 0 deletions compiler/astdef.nim
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,7 @@ type
attachedAsgn,
attachedDup,
attachedSink,
attachedDispose,
attachedTrace,
attachedDeepCopy

Expand Down
4 changes: 4 additions & 0 deletions compiler/ccgtypes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1855,6 +1855,10 @@ proc genTypeInfoV2Impl(m: BModule; t, origType: PType, name: Rope; info: TLineIn
typeEntry.addCast(CPointer):
genHook(m, t, info, attachedTrace, typeEntry)

typeEntry.addField(typeInit, name = "disposeImpl"):
typeEntry.addCast(CPointer):
genHook(m, t, info, attachedDispose, typeEntry)

let dispatchMethods = toSeq(getMethodsPerType(m.g.graph, t))
if dispatchMethods.len > 0:
typeEntry.addField(typeInit, name = "flags"):
Expand Down
36 changes: 31 additions & 5 deletions compiler/liftdestructors.nim
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,22 @@ proc considerUserDefinedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
else:
result = false
#result = addDestructorCall(c, t, body, x)
of attachedDispose:
var op = getAttachedOp(c.g, t, c.kind)
if op != nil and sfOverridden in op.flags:

if op.ast.isGenericRoutine:
# patch generic destructor:
op = instantiateGeneric(c, op, t, t.typeInst)
setAttachedOp(c.g, c.idgen.module, t, attachedDispose, op)

#markUsed(c.g.config, c.info, op, c.g.usageSym)
onUse(c.info, op)
body.add destructorCall(c, op, x) # fine for `dispose` too!
result = true
else:
result = false

of attachedAsgn, attachedSink, attachedTrace:
var op = getAttachedOp(c.g, t, c.kind)
if op != nil and sfOverridden in op.flags:
Expand Down Expand Up @@ -646,6 +662,9 @@ proc fillSeqOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
# destroy all elements:
forallElements(c, t, body, x, y)
body.add genBuiltin(c, mDestroy, "destroy", x)
of attachedDispose:
# The mDestroy that the C code generator produces is right for `dispose`:
body.add genBuiltin(c, mDestroy, "destroy", x)
of attachedTrace:
if canFormAcycle(c.g, t.elemType):
# follow all elements:
Expand Down Expand Up @@ -682,6 +701,9 @@ proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
of attachedDestructor:
doAssert t.destructor != nil
body.add destructorCall(c, t.destructor, x)
of attachedDispose:
# The mDestroy that the C code generator produces is right for `dispose`:
body.add genBuiltin(c, mDestroy, "destroy", x)
of attachedTrace:
if t.kind != tyString and canFormAcycle(c.g, t.elemType):
let op = getAttachedOp(c.g, t, c.kind)
Expand All @@ -706,7 +728,7 @@ proc fillStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
doAssert t.destructor != nil
moveCall.add destructorCall(c, t.destructor, x)
body.add moveCall
of attachedDestructor:
of attachedDestructor, attachedDispose:
body.add genBuiltin(c, mDestroy, "destroy", x)
of attachedTrace:
discard "strings are atomic and have no inner elements that are to trace"
Expand Down Expand Up @@ -828,6 +850,8 @@ proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
of attachedDestructor:
body.add genIf(c, cond, actions)
of attachedDeepCopy: assert(false, "cannot happen")
of attachedDispose:
discard "the whole point of this exercise! Do not traverse `ref` fields for `=dispose`!"
of attachedTrace:
if isCyclic:
if isFinal(elemType):
Expand Down Expand Up @@ -920,6 +944,8 @@ proc atomicClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
body.add genIf(c, yenv, callCodegenProc(c.g, "nimIncRef", c.info, yenv))
of attachedDestructor:
body.add genIf(c, cond, actions)
of attachedDispose:
discard "the whole point of this exercise! Do not traverse `closure` fields for `=dispose`!"
of attachedDeepCopy: assert(false, "cannot happen")
of attachedTrace:
body.add callCodegenProc(c.g, "nimTraceRefDyn", c.info, genAddrOf(xenv, c.idgen), y)
Expand Down Expand Up @@ -950,7 +976,7 @@ proc weakrefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
else:
body.sons.insert(des, 0)
of attachedDeepCopy: assert(false, "cannot happen")
of attachedTrace: discard
of attachedTrace, attachedDispose: discard
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "wasMoved", x)

proc ownedRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
Expand Down Expand Up @@ -978,7 +1004,7 @@ proc ownedRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
of attachedDestructor:
body.add genIf(c, x, actions)
of attachedDeepCopy: assert(false, "cannot happen")
of attachedTrace: discard
of attachedTrace, attachedDispose: discard
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "wasMoved", x)

proc closureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
Expand Down Expand Up @@ -1018,7 +1044,7 @@ proc closureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
else:
body.sons.insert(des, 0)
of attachedDeepCopy: assert(false, "cannot happen")
of attachedTrace: discard
of attachedTrace, attachedDispose: discard
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "wasMoved", x)

proc ownedClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
Expand All @@ -1036,7 +1062,7 @@ proc ownedClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
of attachedDestructor:
body.add genIf(c, xx, actions)
of attachedDeepCopy: assert(false, "cannot happen")
of attachedTrace: discard
of attachedTrace, attachedDispose: discard
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "wasMoved", x)

proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
Expand Down
4 changes: 2 additions & 2 deletions compiler/semdata.nim
Original file line number Diff line number Diff line change
Expand Up @@ -728,10 +728,10 @@ proc analyseIfAddressTakenInCall*(c: PContext, n: PNode, isConverter = false) =
proc replaceHookMagic*(c: PContext, n: PNode, kind: TTypeAttachedOp): PNode =
## Replaces builtin generic hooks with lifted hooks.
case kind
of attachedDestructor:
of attachedDestructor, attachedDispose:
result = n
let t = n[1].typ.skipTypes(abstractVar)
let op = getAttachedOp(c.graph, t, attachedDestructor)
let op = getAttachedOp(c.graph, t, kind)
if op != nil:
result[0] = newSymNode(op)
if op.typ != nil and op.typ.len == 2 and op.typ.firstParamType.kind != tyVar:
Expand Down
2 changes: 1 addition & 1 deletion doc/destructors.md
Original file line number Diff line number Diff line change
Expand Up @@ -761,7 +761,7 @@ used to specialize the object traversal in order to avoid deep recursions:
if x.left != nil: s.add(x.left)
if x.right != nil: s.add(x.right)
# free the memory explicitly:
`=dispose`(x)
deallocRef(x)
# notice how even the destructor for 's' is not called implicitly
# anymore thanks to .nodestroy, so we have to call it on our own:
`=destroy`(s)
Expand Down
1 change: 1 addition & 0 deletions lib/system.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1674,6 +1674,7 @@ when not defined(js) and defined(nimV2):
when defined(nimTypeNames) or defined(nimArcIds) or defined(nimOrcLeakDetector):
name: cstring
traceImpl: pointer
disposeImpl: pointer
typeInfoV1: pointer # for backwards compat, usually nil
flags: int
when defined(gcDestructors):
Expand Down
2 changes: 1 addition & 1 deletion lib/system/arc.nim
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ proc nimRawDispose(p: pointer, alignment: int) {.compilerRtl.} =
let hdrSize = align(sizeof(RefHeader), alignment)
alignedDealloc(p -! hdrSize, alignment)

template `=dispose`*[T](x: owned(ref T)) = nimRawDispose(cast[pointer](x), T.alignOf)
template `deallocRef`*[T](x: owned(ref T)) = nimRawDispose(cast[pointer](x), T.alignOf)
#proc dispose*(x: pointer) = nimRawDispose(x)

proc nimDestroyAndDispose(p: pointer) {.compilerRtl, quirky, raises: [].} =
Expand Down
2 changes: 1 addition & 1 deletion lib/system/orc.nim
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ proc collectColor(s: Cell; desc: PNimTypeV2; col: int; j: var GcEnv) =
while j.traceStack.len > 0:
let (entry, desc) = j.traceStack.pop()
let t = head entry[]
entry[] = nil # ensure that the destructor does touch moribund objects!
entry[] = nil # ensure that the destructor does not touch moribund objects!
if t.color == col and t.rootIdx == 0:
j.toFree.add(t, desc)
t.setColor(colBlack)
Expand Down
6 changes: 3 additions & 3 deletions lib/system/yrc.nim
Original file line number Diff line number Diff line change
Expand Up @@ -258,8 +258,8 @@ proc free(s: Cell; desc: PNimTypeV2) {.inline.} =
if (s.rc and inRootsFlag) == 0:
let p = s +! sizeof(RefHeader)
when logOrc: writeCell("free", s, desc)
if desc.destructor != nil:
cast[DestructorProc](desc.destructor)(p)
if desc.disposeImpl != nil:
cast[DestructorProc](desc.disposeImpl)(p)
nimRawDispose(p, desc.align)

template orcAssert(cond, msg) =
Expand Down Expand Up @@ -339,7 +339,7 @@ proc collectColor(s: Cell; desc: PNimTypeV2; col: int; j: var GcEnv) =
while j.traceStack.len > 0:
let (entry, desc) = j.traceStack.pop()
let t = head entry[]
entry[] = nil
#entry[] = nil
if t.color == col and (t.rc and inRootsFlag) == 0:
j.toFree.add(t, desc)
t.setColor(colBlack)
Expand Down
2 changes: 1 addition & 1 deletion tests/destructor/tbintree2.nim
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ proc `=destroy`(t: var Tree) {.nodestroy.} =
let x = s.pop
if x.left != nil: s.add(x.left)
if x.right != nil: s.add(x.right)
`=dispose`(x)
deallocRef(x)
`=destroy`(s)

proc hasValue(self: var Tree, x: int32): bool =
Expand Down
Loading