mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-12 22:33:49 +00:00
experiment: =dispose hooks for Nim
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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")
|
||||
@@ -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:
|
||||
@@ -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:
|
||||
|
||||
@@ -764,6 +764,7 @@ type
|
||||
attachedAsgn,
|
||||
attachedDup,
|
||||
attachedSink,
|
||||
attachedDispose,
|
||||
attachedTrace,
|
||||
attachedDeepCopy
|
||||
|
||||
|
||||
@@ -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"):
|
||||
|
||||
@@ -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:
|
||||
@@ -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:
|
||||
@@ -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)
|
||||
@@ -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"
|
||||
@@ -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):
|
||||
@@ -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)
|
||||
@@ -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) =
|
||||
@@ -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) =
|
||||
@@ -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) =
|
||||
@@ -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) =
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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 `=disposeHidden`*[T](x: owned(ref T)) = nimRawDispose(cast[pointer](x), T.alignOf)
|
||||
#proc dispose*(x: pointer) = nimRawDispose(x)
|
||||
|
||||
proc nimDestroyAndDispose(p: pointer) {.compilerRtl, quirky, raises: [].} =
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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) =
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
`=disposeHidden`(x)
|
||||
`=destroy`(s)
|
||||
|
||||
proc hasValue(self: var Tree, x: int32): bool =
|
||||
|
||||
Reference in New Issue
Block a user