diff options
-rw-r--r-- | compiler/injectdestructors.nim | 8 | ||||
-rw-r--r-- | compiler/lambdalifting.nim | 15 | ||||
-rw-r--r-- | tests/destructor/tlists.nim | 9 |
3 files changed, 24 insertions, 8 deletions
diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim index 8d975e69e..0bb192036 100644 --- a/compiler/injectdestructors.nim +++ b/compiler/injectdestructors.nim @@ -32,7 +32,7 @@ type uninit: IntSet # set of uninit'ed vars uninitComputed: bool -const toDebug = "" # "server" # "serverNimAsyncContinue" +const toDebug {.strdefine.} = "" # "server" # "serverNimAsyncContinue" template dbg(body) = when toDebug.len > 0: @@ -450,7 +450,11 @@ proc p(n: PNode; c: var Con): PNode = for i in 1..<n.len: n[i] = pArg(n[i], c, i < L and isSinkTypeForParam(parameters[i])) result = n - of nkDiscardStmt: #Small optimization + if result[0].kind == nkSym and result[0].sym.magic in {mNew, mNewFinalize}: + if c.graph.config.selectedGC in {gcHooks, gcDestructors}: + let destroyOld = genDestroy(c, result[1]) + result = newTree(nkStmtList, destroyOld, result) + of nkDiscardStmt: # Small optimization if n[0].kind != nkEmpty: n[0] = pArg(n[0], c, false) result = n diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index 15ab7ec0a..9a12fb192 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -233,9 +233,12 @@ proc liftingHarmful(conf: ConfigRef; owner: PSym): bool {.inline.} = let isCompileTime = sfCompileTime in owner.flags or owner.kind == skMacro result = conf.cmd == cmdCompileToJS and not isCompileTime -proc createTypeBoundOpsLL(g: ModuleGraph; refType: PType; info: TLineInfo) = +proc createTypeBoundOpsLL(g: ModuleGraph; refType: PType; info: TLineInfo; owner: PSym) = createTypeBoundOps(g, nil, refType.lastSon, info) createTypeBoundOps(g, nil, refType, info) + if (tfHasAsgn in refType.flags) or + optSeqDestructors in g.config.globalOptions: + owner.flags.incl sfInjectDestructors proc liftIterSym*(g: ModuleGraph; n: PNode; owner: PSym): PNode = # transforms (iter) to (let env = newClosure[iter](); (iter, env)) @@ -261,7 +264,7 @@ proc liftIterSym*(g: ModuleGraph; n: PNode; owner: PSym): PNode = result.add(v) # add 'new' statement: result.add newCall(getSysSym(g, n.info, "internalNew"), env) - createTypeBoundOpsLL(g, env.typ, n.info) + createTypeBoundOpsLL(g, env.typ, n.info, owner) result.add makeClosure(g, iter, env, n.info) proc freshVarForClosureIter*(g: ModuleGraph; s, owner: PSym): PNode = @@ -592,7 +595,7 @@ proc rawClosureCreation(owner: PSym; let env2 = copyTree(env) env2.typ = unowned.typ result.add newAsgnStmt(unowned, env2, env.info) - createTypeBoundOpsLL(d.graph, unowned.typ, env.info) + createTypeBoundOpsLL(d.graph, unowned.typ, env.info, owner) # add assignment statements for captured parameters: for i in 1..<owner.typ.n.len: @@ -615,7 +618,7 @@ proc rawClosureCreation(owner: PSym; localError(d.graph.config, env.info, "internal error: cannot create up reference") # we are not in the sem'check phase anymore! so pass 'nil' for the PContext # and hope for the best: - createTypeBoundOpsLL(d.graph, env.typ, owner.info) + createTypeBoundOpsLL(d.graph, env.typ, owner.info, owner) proc finishClosureCreation(owner: PSym; d: DetectionPass; c: LiftingPass; info: TLineInfo; res: PNode) = @@ -643,7 +646,7 @@ proc closureCreationForIter(iter: PNode; addVar(vs, vnode) result.add(vs) result.add(newCall(getSysSym(d.graph, iter.info, "internalNew"), vnode)) - createTypeBoundOpsLL(d.graph, vnode.typ, iter.info) + createTypeBoundOpsLL(d.graph, vnode.typ, iter.info, owner) let upField = lookupInRecord(v.typ.skipTypes({tyOwned, tyRef, tyPtr}).n, getIdent(d.graph.cache, upName)) if upField != nil: @@ -926,7 +929,7 @@ proc liftForLoop*(g: ModuleGraph; body: PNode; owner: PSym): PNode = result.add(v) # add 'new' statement: result.add(newCall(getSysSym(g, env.info, "internalNew"), env.newSymNode)) - createTypeBoundOpsLL(g, env.typ, body.info) + createTypeBoundOpsLL(g, env.typ, body.info, owner) elif op.kind == nkStmtListExpr: let closure = op.lastSon diff --git a/tests/destructor/tlists.nim b/tests/destructor/tlists.nim index a9c78ab75..78c09b105 100644 --- a/tests/destructor/tlists.nim +++ b/tests/destructor/tlists.nim @@ -43,9 +43,18 @@ proc tlazyList = var x = LazyList(c: proc () = echo(dep)) x.c() +type + Foo = ref object + +proc tleakingNewStmt = + var x: Foo + for i in 0..10: + new(x) + let startMem = getOccupiedMem() tlazyList() mkManyLeaks() tsimpleClosureIterator() +tleakingNewStmt() echo getOccupiedMem() - startMem |