diff options
author | Araq <rumpf_a@web.de> | 2019-04-06 17:32:33 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2019-04-06 17:32:53 +0200 |
commit | 6e6a9a721fc039c88851650e4ab989aeff04fc9f (patch) | |
tree | 1cbcab26559355e7b7ee4dee87454956661dc5da | |
parent | fab75fbaf1a2dd94cedfc0b41173edf49b581c6e (diff) | |
download | Nim-6e6a9a721fc039c88851650e4ab989aeff04fc9f.tar.gz |
destructors: we are cooking now
-rw-r--r-- | compiler/ast.nim | 3 | ||||
-rw-r--r-- | compiler/commands.nim | 13 | ||||
-rw-r--r-- | compiler/injectdestructors.nim | 18 | ||||
-rw-r--r-- | compiler/liftdestructors.nim | 14 | ||||
-rw-r--r-- | compiler/transf.nim | 2 | ||||
-rw-r--r-- | lib/core/runtime_v2.nim | 8 | ||||
-rw-r--r-- | lib/core/strs.nim | 20 | ||||
-rw-r--r-- | lib/system.nim | 33 | ||||
-rw-r--r-- | tests/destructor/tgcdestructors.nim | 5 |
9 files changed, 73 insertions, 43 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index a21d9f738..0aeb94bb5 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -1808,3 +1808,6 @@ template getBody*(s: PSym): PNode = s.ast[bodyPos] template detailedInfo*(sym: PSym): string = sym.name.s + +proc isInlineIterator*(s: PSym): bool {.inline.} = + s.kind == skIterator and s.typ.callConv != ccClosure diff --git a/compiler/commands.nim b/compiler/commands.nim index 0c574a079..6935e7747 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -745,12 +745,13 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; conf.cppDefine(arg) of "newruntime": expectNoArg(conf, switch, arg, pass, info) - doAssert(conf != nil) - incl(conf.features, destructor) - incl(conf.globalOptions, optNimV2) - defineSymbol(conf.symbols, "nimV2") - conf.selectedGC = gcDestructors - defineSymbol(conf.symbols, "gcdestructors") + if pass in {passCmd2, passPP}: + doAssert(conf != nil) + incl(conf.features, destructor) + incl(conf.globalOptions, optNimV2) + defineSymbol(conf.symbols, "nimV2") + conf.selectedGC = gcDestructors + defineSymbol(conf.symbols, "gcdestructors") of "stylecheck": case arg.normalize of "off": conf.globalOptions = conf.globalOptions - {optStyleHint, optStyleError} diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim index f1bda866b..350fd9c8d 100644 --- a/compiler/injectdestructors.nim +++ b/compiler/injectdestructors.nim @@ -456,7 +456,7 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode = result.add arg[0] for i in 1..<arg.len: result.add pArg(arg[i], c, i < L and parameters[i].kind == tySink) - elif arg.kind in {nkBracket, nkObjConstr, nkTupleConstr, nkBracket, nkCharLit..nkFloat128Lit}: + elif arg.kind in {nkBracket, nkObjConstr, nkTupleConstr, nkBracket, nkCharLit..nkTripleStrLit}: discard "object construction to sink parameter: nothing to do" result = arg elif arg.kind == nkSym and isSinkParam(arg.sym): @@ -616,7 +616,21 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode = else: result = genCopy(c, dest.typ, dest, ri) result.add p(ri, c) + of nkHiddenSubConv, nkHiddenStdConv: + let harmless = ri[1].kind in (nkCallKinds + {nkSym, nkTupleConstr, nkObjConstr, + nkBracket, nkBracketExpr, nkNilLit}) + if harmless: + result = moveOrCopy(dest, ri[1], c) + var b = newNodeIT(ri.kind, ri.info, ri.typ) + b.add ri[0] # add empty node + let L = result.len-1 + b.add result[L] + result[L] = b + else: + result = genCopy(c, dest.typ, dest, ri) + result.add p(ri, c) else: + # XXX At least string literals can be moved? result = genCopy(c, dest.typ, dest, ri) result.add p(ri, c) @@ -725,7 +739,7 @@ proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode = when defined(nimDebugDestroys): if owner.name.s == "main": echo "injecting into ", n - if sfGeneratedOp in owner.flags: return n + if sfGeneratedOp in owner.flags or isInlineIterator(owner): return n var c: Con c.owner = owner c.destroys = newNodeI(nkStmtList, n.info) diff --git a/compiler/liftdestructors.nim b/compiler/liftdestructors.nim index dba09b4ef..cfab1e221 100644 --- a/compiler/liftdestructors.nim +++ b/compiler/liftdestructors.nim @@ -309,13 +309,14 @@ proc seqOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = proc strOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = case c.kind of attachedAsgn, attachedDeepCopy: + body.add callCodegenProc(c.graph, "nimAsgnStrV2", c.info, genAddr(c.graph, x), y) # we generate: # setLen(dest, y.len) # var i = 0 # while i < y.len: dest[i] = y[i]; inc(i) # This is usually more efficient than a destroy/create pair. - body.add setLenStrCall(c.graph, x, y) - forallElements(c, t, body, x, y) + #body.add setLenStrCall(c.graph, x, y) + #forallElements(c, t, body, x, y) of attachedSink: let moveCall = genBuiltin(c.graph, mMove, "move", x) moveCall.add y @@ -473,8 +474,11 @@ proc liftBodyAux(c: var TLiftCtx; t: PType; body, x, y: PNode) = tyTypeDesc, tyGenericInvocation, tyForward: #internalError(c.graph.config, c.info, "assignment requested for type: " & typeToString(t)) discard + of tyVar, tyLent: + if c.kind != attachedDestructor: + liftBodyAux(c, lastSon(t), body, x, y) of tyOrdinal, tyRange, tyInferred, - tyGenericInst, tyStatic, tyVar, tyLent, tyAlias, tySink: + tyGenericInst, tyStatic, tyAlias, tySink: liftBodyAux(c, lastSon(t), body, x, y) proc newProcType(info: TLineInfo; owner: PSym): PType = @@ -650,7 +654,7 @@ proc createTypeBoundOps*(c: PContext; orig: PType; info: TLineInfo) = orig.assignment = canon.assignment orig.sink = canon.sink - #if not isTrival(orig.destructor): + if not isTrival(orig.destructor): #or not isTrival(orig.assignment) or # not isTrival(orig.sink): - # orig.flags.incl tfHasAsgn + orig.flags.incl tfHasAsgn diff --git a/compiler/transf.nim b/compiler/transf.nim index 640ed1136..a597123de 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -772,6 +772,8 @@ proc transformCall(c: PTransf, n: PNode): PTransNode = elif magic == mProcCall: # but do not change to its dispatcher: result = transformSons(c, n[1]) + elif magic == mStrToStr: + result = transform(c, n[1]) else: let s = transformSons(c, n).PNode # bugfix: check after 'transformSons' if it's still a method call: diff --git a/lib/core/runtime_v2.nim b/lib/core/runtime_v2.nim index 6463a5a27..f76fd2f3e 100644 --- a/lib/core/runtime_v2.nim +++ b/lib/core/runtime_v2.nim @@ -26,14 +26,6 @@ hash of ``package & "." & module & "." & name`` to save space. ]# type - TNimNode {.compilerProc.} = object # to keep the code generator simple - DestructorProc = proc (p: pointer) {.nimcall, benign.} - TNimType {.compilerProc.} = object - destructor: pointer - size: int - name: cstring - PNimType = ptr TNimType - RefHeader = object rc: int # the object header is now a single RC field. # we could remove it in non-debug builds but this seems diff --git a/lib/core/strs.nim b/lib/core/strs.nim index 7dd65bdb3..ccc261d95 100644 --- a/lib/core/strs.nim +++ b/lib/core/strs.nim @@ -177,17 +177,15 @@ proc nimAsgnStrV2(a: var NimStringV2, b: NimStringV2) {.compilerRtl.} = frees(a) a.len = b.len a.p = b.p - elif isLiteral(a) or a.p.cap < b.len: - let allocator = if a.p != nil and a.p.allocator != nil: a.p.allocator else: getLocalAllocator() - # we have to allocate the 'cap' here, consider - # 'let y = newStringOfCap(); var x = y' - # on the other hand... These get turned into moves now. - a.p = cast[ptr NimStrPayload](allocator.alloc(allocator, contentSize(b.len))) - a.p.allocator = allocator - a.p.cap = b.len - a.len = b.len - copyMem(unsafeAddr a.p.data[0], unsafeAddr b.p.data[0], b.len+1) else: + if isLiteral(a) or a.p.cap < b.len: + let allocator = if a.p != nil and a.p.allocator != nil: a.p.allocator else: getLocalAllocator() + # we have to allocate the 'cap' here, consider + # 'let y = newStringOfCap(); var x = y' + # on the other hand... These get turned into moves now. + frees(a) + a.p = cast[ptr NimStrPayload](allocator.alloc(allocator, contentSize(b.len))) + a.p.allocator = allocator + a.p.cap = b.len a.len = b.len - # reuse the storage we already have: copyMem(unsafeAddr a.p.data[0], unsafeAddr b.p.data[0], b.len+1) diff --git a/lib/system.nim b/lib/system.nim index 9d0871490..f51767950 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -2971,6 +2971,30 @@ proc compiles*(x: untyped): bool {.magic: "Compiles", noSideEffect, compileTime. when not defined(js) and not defined(nimscript): include "system/ansi_c" +when not defined(js): + {.push stackTrace:off.} + + when hasThreadSupport and hostOS != "standalone": + const insideRLocksModule = false + include "system/syslocks" + include "system/threadlocalstorage" + + when defined(nimV2): + type + TNimNode {.compilerProc.} = object # to keep the code generator simple + DestructorProc = proc (p: pointer) {.nimcall, benign.} + TNimType {.compilerProc.} = object + destructor: pointer + size: int + name: cstring + PNimType = ptr TNimType + + when defined(gcDestructors) and not defined(nimscript): + include "core/strs" + include "core/seqs" + + {.pop.} + when not declared(sysFatal): include "system/fatal" @@ -3481,15 +3505,6 @@ when not defined(JS): #and not defined(nimscript): when defined(endb): proc endbStep() - when hasThreadSupport and hostOS != "standalone": - const insideRLocksModule = false - include "system/syslocks" - include "system/threadlocalstorage" - - when defined(gcDestructors) and not defined(nimscript): - include "core/strs" - include "core/seqs" - when declared(newSeq): proc cstringArrayToSeq*(a: cstringArray, len: Natural): seq[string] = ## Converts a ``cstringArray`` to a ``seq[string]``. `a` is supposed to be diff --git a/tests/destructor/tgcdestructors.nim b/tests/destructor/tgcdestructors.nim index 4b7f4ccb4..fa778f49d 100644 --- a/tests/destructor/tgcdestructors.nim +++ b/tests/destructor/tgcdestructors.nim @@ -3,7 +3,7 @@ discard """ output: '''hi ho ha -7 1''' +7 7''' """ import allocators @@ -75,7 +75,7 @@ iterator interpolatedFragments*(s: string): tuple[kind: InterpolatedKind, break i = j -when true: +proc other = let input = "$test{} $this is ${an{ example}} " let expected = @[(ikVar, "test"), (ikStr, "{} "), (ikVar, "this"), (ikStr, " is "), (ikExpr, "an{ example}"), (ikStr, " ")] @@ -84,6 +84,7 @@ when true: doAssert s == expected[i] inc i +other() #echo s let (a, d) = allocCounters() |