From b8302cdd97ddbb80240dab947fc794a81f790f65 Mon Sep 17 00:00:00 2001 From: ringabout <43030857+ringabout@users.noreply.github.com> Date: Mon, 10 Mar 2025 18:20:44 +0800 Subject: [PATCH] implements internal sink copy (#24747) TODO: - [x] other value types (arrays, strings, seqs, objects) - [x] replaces https://github.com/nim-lang/Nim/pull/24731 - [x] improve code shape - [ ] revert https://github.com/nim-lang/Nim/issues/24175 - [x] if possible, revert https://github.com/nim-lang/Nim/pull/23685 - [ ] if possible, revert https://github.com/nim-lang/Nim/pull/22229 and https://github.com/nim-lang/Nim/pull/23764 - [ ] if possible, remove `if n.containsConstSeq:` - [ ] if possible, always pass value (arrays, strings, seqs, tuples, or even objects without custom hooks (?)) sinks by ref because this PR should ensure these value types are not modified without a copy - [x] fixes `say a, (b = move a; a)` for potential writes https://github.com/nim-lang/Nim/pull/24753 --- compiler/ccgcalls.nim | 29 --------------- compiler/ccgutils.nim | 9 +---- compiler/injectdestructors.nim | 64 ++++++++++++++++++++++++++++++++-- compiler/trees.nim | 29 +++++++++++++++ 4 files changed, 91 insertions(+), 40 deletions(-) diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim index aaad53b64b..2017f7dffc 100644 --- a/compiler/ccgcalls.nim +++ b/compiler/ccgcalls.nim @@ -418,35 +418,6 @@ proc skipTrivialIndirections(n: PNode): PNode = result = result[1] else: break -proc getPotentialWrites(n: PNode; mutate: bool; result: var seq[PNode]) = - case n.kind: - of nkLiterals, nkIdent, nkFormalParams: discard - of nkSym: - if mutate: result.add n - of nkAsgn, nkFastAsgn, nkSinkAsgn: - getPotentialWrites(n[0], true, result) - getPotentialWrites(n[1], mutate, result) - of nkAddr, nkHiddenAddr: - getPotentialWrites(n[0], true, result) - of nkBracketExpr, nkDotExpr, nkCheckedFieldExpr: - getPotentialWrites(n[0], mutate, result) - of nkCallKinds: - case n.getMagic: - of mIncl, mExcl, mInc, mDec, mAppendStrCh, mAppendStrStr, mAppendSeqElem, - mAddr, mNew, mNewFinalize, mWasMoved, mDestroy: - getPotentialWrites(n[1], true, result) - for i in 2.. conf.target.floatSize * 3): result = true # requested anyway elif (tfFinal in pt.flags) and (pt[0] == nil): @@ -101,11 +98,7 @@ proc ccgIntroducedPtr*(conf: ConfigRef; s: PSym, retType: PType): bool = result = true # ordinary objects are always passed by reference, # otherwise casting doesn't work of tyTuple: - if s.typ.kind == tySink: - # it's a sink, so we pass it by value - result = false - else: - result = (getSize(conf, pt) > conf.target.floatSize*3) or (optByRef in s.options) + result = (getSize(conf, pt) > conf.target.floatSize*3) or (optByRef in s.options) else: result = false # first parameter and return type is 'lent T'? --> use pass by pointer diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim index 013ab1c506..be2df8c1f2 100644 --- a/compiler/injectdestructors.nim +++ b/compiler/injectdestructors.nim @@ -17,7 +17,7 @@ import ast, astalgo, msgs, renderer, magicsys, types, idents, options, lowerings, modulegraphs, lineinfos, parampatterns, sighashes, liftdestructors, optimizer, - varpartitions, aliasanalysis, dfa, wordrecg + varpartitions, aliasanalysis, dfa, wordrecg, trees import std/[strtabs, tables, strutils, intsets] @@ -1244,6 +1244,55 @@ when false: for i in 0.. 0: + result.add replaceSinkParam(n, mapping) + else: + result = n + proc injectDestructorCalls*(g: ModuleGraph; idgen: IdGenerator; owner: PSym; n: PNode): PNode = when toDebug.len > 0: shouldDebug = toDebug == owner.name.s or toDebug == "always" @@ -1257,15 +1306,24 @@ proc injectDestructorCalls*(g: ModuleGraph; idgen: IdGenerator; owner: PSym; n: var scope = Scope(body: n) let body = p(n, c, scope, normal) + var sinkParams = newSeq[PSym]() + if owner.kind in {skProc, skFunc, skMethod, skIterator, skConverter}: let params = owner.typ.n for i in 1.. 0: + result = addSinkCopy(c, scope, sinkParams, result) + dbg: echo ">---------transformed-to--------->" echo renderTree(result, {renderIds}) diff --git a/compiler/trees.nim b/compiler/trees.nim index da58878f82..6d85f920c8 100644 --- a/compiler/trees.nim +++ b/compiler/trees.nim @@ -243,3 +243,32 @@ proc isRunnableExamples*(n: PNode): bool = proc skipAddr*(n: PNode): PNode {.inline.} = result = if n.kind in {nkAddr, nkHiddenAddr}: n[0] else: n + +proc getPotentialWrites*(n: PNode; mutate: bool; result: var seq[PNode]) = + case n.kind: + of nkLiterals, nkIdent, nkFormalParams: discard + of nkSym: + if mutate: result.add n + of nkAsgn, nkFastAsgn, nkSinkAsgn: + getPotentialWrites(n[0], true, result) + getPotentialWrites(n[1], mutate, result) + of nkAddr, nkHiddenAddr: + getPotentialWrites(n[0], true, result) + of nkBracketExpr, nkDotExpr, nkCheckedFieldExpr: + getPotentialWrites(n[0], mutate, result) + of nkCallKinds: + case n.getMagic: + of mIncl, mExcl, mInc, mDec, mAppendStrCh, mAppendStrStr, mAppendSeqElem, + mAddr, mNew, mNewFinalize, mWasMoved, mDestroy: + getPotentialWrites(n[1], true, result) + for i in 2..