VM: don't inject destructor calls, refs #7041

This commit is contained in:
Andreas Rumpf 2018-11-06 19:36:29 +01:00
commit 24902394f7
4 changed files with 29 additions and 23 deletions

View file

@ -24,7 +24,8 @@ import
sempass2, lowerings, destroyer, liftlocals, sempass2, lowerings, destroyer, liftlocals,
modulegraphs, lineinfos modulegraphs, lineinfos
proc transformBody*(g: ModuleGraph, prc: PSym, cache = true): PNode proc transformBody*(g: ModuleGraph, prc: PSym, cache = true;
noDestructors = false): PNode
import closureiters, lambdalifting import closureiters, lambdalifting
@ -48,7 +49,7 @@ type
inlining: int # > 0 if we are in inlining context (copy vars) inlining: int # > 0 if we are in inlining context (copy vars)
nestedProcs: int # > 0 if we are in a nested proc nestedProcs: int # > 0 if we are in a nested proc
contSyms, breakSyms: seq[PSym] # to transform 'continue' and 'break' contSyms, breakSyms: seq[PSym] # to transform 'continue' and 'break'
deferDetected, tooEarly, needsDestroyPass: bool deferDetected, tooEarly, needsDestroyPass, noDestructors: bool
graph: ModuleGraph graph: ModuleGraph
PTransf = ref TTransfContext PTransf = ref TTransfContext
@ -130,7 +131,7 @@ proc transformSymAux(c: PTransf, n: PNode): PNode =
let s = n.sym let s = n.sym
if s.typ != nil and s.typ.callConv == ccClosure: if s.typ != nil and s.typ.callConv == ccClosure:
if s.kind in routineKinds: if s.kind in routineKinds:
discard transformBody(c.graph, s) discard transformBody(c.graph, s, true, c.noDestructors)
if s.kind == skIterator: if s.kind == skIterator:
if c.tooEarly: return n if c.tooEarly: return n
else: return liftIterSym(c.graph, n, getCurrOwner(c)) else: return liftIterSym(c.graph, n, getCurrOwner(c))
@ -159,7 +160,7 @@ proc transformSymAux(c: PTransf, n: PNode): PNode =
return return
tc = tc.next tc = tc.next
result = b result = b
proc transformSym(c: PTransf, n: PNode): PTransNode = proc transformSym(c: PTransf, n: PNode): PTransNode =
result = PTransNode(transformSymAux(c, n)) result = PTransNode(transformSymAux(c, n))
@ -243,7 +244,7 @@ proc newLabel(c: PTransf, n: PNode): PSym =
result.name = getIdent(c.graph.cache, genPrefix & $result.id) result.name = getIdent(c.graph.cache, genPrefix & $result.id)
proc transformBlock(c: PTransf, n: PNode): PTransNode = proc transformBlock(c: PTransf, n: PNode): PTransNode =
var labl: PSym var labl: PSym
if c.inlining > 0: if c.inlining > 0:
labl = newLabel(c, n[0]) labl = newLabel(c, n[0])
idNodeTablePut(c.transCon.mapping, n[0].sym, newSymNode(labl)) idNodeTablePut(c.transCon.mapping, n[0].sym, newSymNode(labl))
@ -611,7 +612,7 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
add(stmtList, newAsgnStmt(c, nkFastAsgn, temp, arg.PTransNode)) add(stmtList, newAsgnStmt(c, nkFastAsgn, temp, arg.PTransNode))
idNodeTablePut(newC.mapping, formal, temp) idNodeTablePut(newC.mapping, formal, temp)
let body = transformBody(c.graph, iter) let body = transformBody(c.graph, iter, true, c.noDestructors)
pushInfoContext(c.graph.config, n.info) pushInfoContext(c.graph.config, n.info)
inc(c.inlining) inc(c.inlining)
add(stmtList, transform(c, body)) add(stmtList, transform(c, body))
@ -1029,7 +1030,8 @@ template liftDefer(c, root) =
if c.deferDetected: if c.deferDetected:
liftDeferAux(root) liftDeferAux(root)
proc transformBody*(g: ModuleGraph, prc: PSym, cache = true): PNode = proc transformBody*(g: ModuleGraph, prc: PSym, cache = true;
noDestructors = false): PNode =
assert prc.kind in routineKinds assert prc.kind in routineKinds
if prc.transformedBody != nil: if prc.transformedBody != nil:
@ -1037,22 +1039,22 @@ proc transformBody*(g: ModuleGraph, prc: PSym, cache = true): PNode =
elif nfTransf in prc.ast[bodyPos].flags or prc.kind in {skTemplate}: elif nfTransf in prc.ast[bodyPos].flags or prc.kind in {skTemplate}:
result = prc.ast[bodyPos] result = prc.ast[bodyPos]
else: else:
prc.transformedBody = newNode(nkEmpty) # protects from recursion prc.transformedBody = newNode(nkEmpty) # protects from recursion
var c = openTransf(g, prc.getModule, "") var c = openTransf(g, prc.getModule, "")
c.noDestructors = noDestructors
result = liftLambdas(g, prc, prc.ast[bodyPos], c.tooEarly) result = liftLambdas(g, prc, prc.ast[bodyPos], c.tooEarly)
result = processTransf(c, result, prc) result = processTransf(c, result, prc)
liftDefer(c, result) liftDefer(c, result)
result = liftLocalsIfRequested(prc, result, g.cache, g.config) result = liftLocalsIfRequested(prc, result, g.cache, g.config)
if c.needsDestroyPass: #and newDestructors: if c.needsDestroyPass and not noDestructors:
result = injectDestructorCalls(g, prc, result) result = injectDestructorCalls(g, prc, result)
if prc.isIterator: if prc.isIterator:
result = g.transformClosureIterator(prc, result) result = g.transformClosureIterator(prc, result)
incl(result.flags, nfTransf) incl(result.flags, nfTransf)
let cache = cache or prc.typ.callConv == ccInline let cache = cache or prc.typ.callConv == ccInline
if cache: if cache:
# genProc for inline procs will be called multiple times from diffrent modules, # genProc for inline procs will be called multiple times from diffrent modules,
# it is important to transform exactly once to get sym ids and locations right # it is important to transform exactly once to get sym ids and locations right
@ -1072,7 +1074,8 @@ proc transformStmt*(g: ModuleGraph; module: PSym, n: PNode): PNode =
result = injectDestructorCalls(g, module, result) result = injectDestructorCalls(g, module, result)
incl(result.flags, nfTransf) incl(result.flags, nfTransf)
proc transformExpr*(g: ModuleGraph; module: PSym, n: PNode): PNode = proc transformExpr*(g: ModuleGraph; module: PSym, n: PNode;
noDestructors = false): PNode =
if nfTransf in n.flags: if nfTransf in n.flags:
result = n result = n
else: else:
@ -1081,6 +1084,6 @@ proc transformExpr*(g: ModuleGraph; module: PSym, n: PNode): PNode =
liftDefer(c, result) liftDefer(c, result)
# expressions are not to be injected with destructor calls as that # expressions are not to be injected with destructor calls as that
# the list of top level statements needs to be collected before. # the list of top level statements needs to be collected before.
if c.needsDestroyPass: if c.needsDestroyPass and not noDestructors:
result = injectDestructorCalls(g, module, result) result = injectDestructorCalls(g, module, result)
incl(result.flags, nfTransf) incl(result.flags, nfTransf)

View file

@ -503,7 +503,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
of opcAsgnFloat64FromInt: of opcAsgnFloat64FromInt:
let rb = instr.regB let rb = instr.regB
ensureKind(rkFloat) ensureKind(rkFloat)
regs[ra].floatVal = cast[float64](int64(regs[rb].intVal)) regs[ra].floatVal = cast[float64](int64(regs[rb].intVal))
of opcAsgnComplex: of opcAsgnComplex:
asgnComplex(regs[ra], regs[instr.regB]) asgnComplex(regs[ra], regs[instr.regB])
of opcAsgnRef: of opcAsgnRef:
@ -945,10 +945,10 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
let a = regs[rb].node let a = regs[rb].node
if a.kind == nkSym: if a.kind == nkSym:
regs[ra].node = if a.sym.ast.isNil: newNode(nkNilLit) regs[ra].node = if a.sym.ast.isNil: newNode(nkNilLit)
else: else:
let ast = a.sym.ast.shallowCopy let ast = a.sym.ast.shallowCopy
for i in 0..<a.sym.ast.len: for i in 0..<a.sym.ast.len:
ast[i] = a.sym.ast[i] ast[i] = a.sym.ast[i]
ast[bodyPos] = transformBody(c.graph, a.sym) ast[bodyPos] = transformBody(c.graph, a.sym)
ast.copyTree() ast.copyTree()
of opcSymOwner: of opcSymOwner:
@ -1822,7 +1822,7 @@ proc execProc*(c: PCtx; sym: PSym; args: openArray[PNode]): PNode =
"NimScript: attempt to call non-routine: " & sym.name.s) "NimScript: attempt to call non-routine: " & sym.name.s)
proc evalStmt*(c: PCtx, n: PNode) = proc evalStmt*(c: PCtx, n: PNode) =
let n = transformExpr(c.graph, c.module, n) let n = transformExpr(c.graph, c.module, n, noDestructors = true)
let start = genStmt(c, n) let start = genStmt(c, n)
# execute new instructions; this redundant opcEof check saves us lots # execute new instructions; this redundant opcEof check saves us lots
# of allocations in 'execute': # of allocations in 'execute':
@ -1830,7 +1830,7 @@ proc evalStmt*(c: PCtx, n: PNode) =
discard execute(c, start) discard execute(c, start)
proc evalExpr*(c: PCtx, n: PNode): PNode = proc evalExpr*(c: PCtx, n: PNode): PNode =
let n = transformExpr(c.graph, c.module, n) let n = transformExpr(c.graph, c.module, n, noDestructors = true)
let start = genExpr(c, n) let start = genExpr(c, n)
assert c.code[start].opcode != opcEof assert c.code[start].opcode != opcEof
result = execute(c, start) result = execute(c, start)
@ -1877,7 +1877,7 @@ const evalPass* = makePass(myOpen, myProcess, myClose)
proc evalConstExprAux(module: PSym; proc evalConstExprAux(module: PSym;
g: ModuleGraph; prc: PSym, n: PNode, g: ModuleGraph; prc: PSym, n: PNode,
mode: TEvalMode): PNode = mode: TEvalMode): PNode =
let n = transformExpr(g, module, n) let n = transformExpr(g, module, n, noDestructors = true)
setupGlobalCtx(module, g) setupGlobalCtx(module, g)
var c = PCtx g.vm var c = PCtx g.vm
let oldMode = c.mode let oldMode = c.mode

View file

@ -779,7 +779,7 @@ proc genCastIntFloat(c: PCtx; n: PNode; dest: var TDest) =
let src = n.sons[1].typ.skipTypes(abstractRange)#.kind let src = n.sons[1].typ.skipTypes(abstractRange)#.kind
let dst = n.sons[0].typ.skipTypes(abstractRange)#.kind let dst = n.sons[0].typ.skipTypes(abstractRange)#.kind
let src_size = getSize(c.config, src) let src_size = getSize(c.config, src)
let dst_size = getSize(c.config, dst) let dst_size = getSize(c.config, dst)
if c.config.target.intSize < 8: if c.config.target.intSize < 8:
signedIntegers.incl(tyInt) signedIntegers.incl(tyInt)
unsignedIntegers.incl(tyUInt) unsignedIntegers.incl(tyUInt)
@ -823,7 +823,7 @@ proc genCastIntFloat(c: PCtx; n: PNode; dest: var TDest) =
c.freeTemp(tmp) c.freeTemp(tmp)
elif src_size == dst_size and src.kind in {tyFloat, tyFloat32, tyFloat64} and elif src_size == dst_size and src.kind in {tyFloat, tyFloat32, tyFloat64} and
dst.kind in allowedIntegers: dst.kind in allowedIntegers:
let tmp = c.genx(n[1]) let tmp = c.genx(n[1])
if dest < 0: dest = c.getTemp(n[0].typ) if dest < 0: dest = c.getTemp(n[0].typ)
if src.kind == tyFloat32: if src.kind == tyFloat32:
@ -2153,7 +2153,8 @@ proc genProc(c: PCtx; s: PSym): int =
s.ast.sons[miscPos] = x s.ast.sons[miscPos] = x
# thanks to the jmp we can add top level statements easily and also nest # thanks to the jmp we can add top level statements easily and also nest
# procs easily: # procs easily:
let body = transformBody(c.graph, s, cache = not isCompileTimeProc(s)) let body = transformBody(c.graph, s, cache = not isCompileTimeProc(s),
noDestructors = true)
let procStart = c.xjmp(body, opcJmp, 0) let procStart = c.xjmp(body, opcJmp, 0)
var p = PProc(blocks: @[], sym: s) var p = PProc(blocks: @[], sym: s)
let oldPrc = c.prc let oldPrc = c.prc

View file

@ -8,9 +8,11 @@
# #
import typetraits # import typetraits
# strs already imported allocators for us. # strs already imported allocators for us.
proc supportsCopyMem(t: typedesc): bool {.magic: "TypeTrait".}
## Default seq implementation used by Nim's core. ## Default seq implementation used by Nim's core.
type type
NimSeqPayload {.core.}[T] = object NimSeqPayload {.core.}[T] = object