summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2019-09-17 10:24:25 +0200
committerAndreas Rumpf <rumpf_a@web.de>2019-09-17 15:15:12 +0200
commitf1b7c0494edbe8e2a6c6eb4764354bbfd6703bf1 (patch)
treebd433c48b2b57882ae97966ef99af7d925c3c58a /compiler
parent62aa1a3cfe904da7309f0b067635bef5d2d57077 (diff)
downloadNim-f1b7c0494edbe8e2a6c6eb4764354bbfd6703bf1.tar.gz
fixes #12195
Diffstat (limited to 'compiler')
-rw-r--r--compiler/vm.nim20
-rw-r--r--compiler/vmdef.nim2
-rw-r--r--compiler/vmgen.nim35
3 files changed, 32 insertions, 25 deletions
diff --git a/compiler/vm.nim b/compiler/vm.nim
index a7980ae1d..b57db3aaa 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -216,6 +216,18 @@ proc asgnComplex(x: var TFullReg, y: TFullReg) =
   of rkRegisterAddr: x.regAddr = y.regAddr
   of rkNodeAddr: x.nodeAddr = y.nodeAddr
 
+proc fastAsgnComplex(x: var TFullReg, y: TFullReg) =
+  if x.kind != y.kind:
+    myreset(x)
+    x.kind = y.kind
+  case x.kind
+  of rkNone: discard
+  of rkInt: x.intVal = y.intVal
+  of rkFloat: x.floatVal = y.floatVal
+  of rkNode: x.node = y.node
+  of rkRegisterAddr: x.regAddr = y.regAddr
+  of rkNodeAddr: x.nodeAddr = y.nodeAddr
+
 proc writeField(n: var PNode, x: TFullReg) =
   case x.kind
   of rkNone: discard
@@ -535,10 +547,6 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
     of opcAsgnInt:
       decodeB(rkInt)
       regs[ra].intVal = regs[rb].intVal
-    of opcAsgnStr:
-      decodeBC(rkNode)
-      createStrKeepNode regs[ra], rc != 0
-      regs[ra].node.strVal = regs[rb].node.strVal
     of opcAsgnFloat:
       decodeB(rkFloat)
       regs[ra].floatVal = regs[rb].floatVal
@@ -560,6 +568,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
       regs[ra].floatVal = cast[float64](int64(regs[rb].intVal))
     of opcAsgnComplex:
       asgnComplex(regs[ra], regs[instr.regB])
+    of opcFastAsgnComplex:
+      fastAsgnComplex(regs[ra], regs[instr.regB])
     of opcAsgnRef:
       asgnRef(regs[ra], regs[instr.regB])
     of opcNodeToReg:
@@ -976,11 +986,9 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
         regs[ra].node.strVal.add getstr(regs[i])
     of opcAddStrCh:
       decodeB(rkNode)
-      #createStrKeepNode regs[ra]
       regs[ra].node.strVal.add(regs[rb].intVal.chr)
     of opcAddStrStr:
       decodeB(rkNode)
-      #createStrKeepNode regs[ra]
       regs[ra].node.strVal.add(regs[rb].node.strVal)
     of opcAddSeqElem:
       decodeB(rkNode)
diff --git a/compiler/vmdef.nim b/compiler/vmdef.nim
index 17c133b08..f530ceeb2 100644
--- a/compiler/vmdef.nim
+++ b/compiler/vmdef.nim
@@ -31,7 +31,6 @@ type
     opcYldVal,      # yield with a value
 
     opcAsgnInt,
-    opcAsgnStr,
     opcAsgnFloat,
     opcAsgnRef,
     opcAsgnIntFromFloat32,    # int and float must be of the same byte size
@@ -39,6 +38,7 @@ type
     opcAsgnFloat32FromInt,    # int and float must be of the same byte size
     opcAsgnFloat64FromInt,    # int and float must be of the same byte size
     opcAsgnComplex,
+    opcFastAsgnComplex,
     opcNodeToReg,
 
     opcLdArr,  # a = b[c]
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index 648ab926c..58e3a35eb 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -43,6 +43,7 @@ type
   TGenFlag = enum
     gfNode # Affects how variables are loaded - always loads as rkNode
     gfNodeAddr # Affects how variables are loaded - always loads as rkNodeAddr
+    gfIsParam # do not deepcopy parameters, they are immutable
   TGenFlags = set[TGenFlag]
 
 proc debugInfo(c: PCtx; info: TLineInfo): string =
@@ -568,7 +569,7 @@ proc genCall(c: PCtx; n: PNode; dest: var TDest) =
     #  let paramType = fntyp.n.sons[i]
     #  if paramType.typ.isCompileTimeOnly: continue
     var r: TRegister = x+i
-    c.gen(n.sons[i], r)
+    c.gen(n.sons[i], r, {gfIsParam})
     if i >= fntyp.len:
       internalAssert c.config, tfVarargs in fntyp.flags
       c.gABx(n, opcSetType, r, c.genType(n.sons[i].typ))
@@ -917,20 +918,16 @@ proc ldNullOpcode(t: PType): TOpcode =
   assert t != nil
   if fitsRegister(t): opcLdNullReg else: opcLdNull
 
-proc whichAsgnOpc(n: PNode): TOpcode =
+proc whichAsgnOpc(n: PNode; requiresCopy = true): TOpcode =
   case n.typ.skipTypes(abstractRange+{tyOwned}-{tyTypeDesc}).kind
   of tyBool, tyChar, tyEnum, tyOrdinal, tyInt..tyInt64, tyUInt..tyUInt64:
     opcAsgnInt
-  of tyString, tyCString:
-    opcAsgnStr
   of tyFloat..tyFloat128:
     opcAsgnFloat
   of tyRef, tyNil, tyVar, tyLent, tyPtr:
     opcAsgnRef
   else:
-    opcAsgnComplex
-
-proc whichAsgnOpc(n: PNode; opc: TOpcode): TOpcode = opc
+    (if requiresCopy: opcAsgnComplex else: opcFastAsgnComplex)
 
 proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
   case m
@@ -1317,7 +1314,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
     let a = c.genx(arg)
     assert dest >= 0
     if dest < 0: dest = c.getTemp(arg.typ)
-    gABC(c, arg, whichAsgnOpc(arg), dest, a, 1)
+    gABC(c, arg, whichAsgnOpc(arg, requiresCopy=false), dest, a)
     # XXX use ldNullOpcode() here?
     c.gABx(n, opcLdNull, a, c.genType(arg.typ))
     c.gABx(n, opcNodeToReg, a, a)
@@ -1419,7 +1416,7 @@ proc genDeref(c: PCtx, n: PNode, dest: var TDest, flags: TGenFlags) =
 proc genAsgn(c: PCtx; dest: TDest; ri: PNode; requiresCopy: bool) =
   let tmp = c.genx(ri)
   assert dest >= 0
-  gABC(c, ri, whichAsgnOpc(ri), dest, tmp, 1-ord(requiresCopy))
+  gABC(c, ri, whichAsgnOpc(ri, requiresCopy), dest, tmp)
   c.freeTemp(tmp)
 
 proc setSlot(c: PCtx; v: PSym) =
@@ -1465,7 +1462,7 @@ template needsAdditionalCopy(n): untyped =
 proc genAdditionalCopy(c: PCtx; n: PNode; opc: TOpcode;
                        dest, idx, value: TRegister) =
   var cc = c.getTemp(n.typ)
-  c.gABC(n, whichAsgnOpc(n), cc, value, 0)
+  c.gABC(n, whichAsgnOpc(n), cc, value)
   c.gABC(n, opc, dest, idx, cc)
   c.freeTemp(cc)
 
@@ -1529,7 +1526,7 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
       if needsAdditionalCopy(le) and s.kind in {skResult, skVar, skParam}:
         var cc = c.getTemp(le.typ)
         gen(c, ri, cc)
-        c.gABC(le, whichAsgnOpc(le), dest, cc, 1)
+        c.gABC(le, whichAsgnOpc(le), dest, cc)
         c.freeTemp(cc)
       else:
         gen(c, ri, dest)
@@ -1608,7 +1605,9 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
         internalAssert(c.config, c.prc.slots[dest].kind < slotSomeTemp)
       else:
         # we need to generate an assignment:
-        genAsgn(c, dest, n, c.prc.slots[dest].kind >= slotSomeTemp)
+        let requiresCopy = c.prc.slots[dest].kind >= slotSomeTemp and
+          gfIsParam notin flags
+        genAsgn(c, dest, n, requiresCopy)
     else:
       # see tests/t99bott for an example that triggers it:
       cannotEval(c, n)
@@ -1818,7 +1817,7 @@ proc genVarSection(c: PCtx; n: PNode) =
           if not fitsRegister(le.typ) and s.kind in {skResult, skVar, skParam}:
             var cc = c.getTemp(le.typ)
             gen(c, a.sons[2], cc)
-            c.gABC(le, whichAsgnOpc(le), s.position.TRegister, cc, 1)
+            c.gABC(le, whichAsgnOpc(le), s.position.TRegister, cc)
             c.freeTemp(cc)
           else:
             gen(c, a.sons[2], s.position.TRegister)
@@ -1849,7 +1848,7 @@ proc genArrayConstr(c: PCtx, n: PNode, dest: var TDest) =
     c.gABx(n, opcLdNullReg, tmp, c.genType(intType))
     for x in n:
       let a = c.genx(x)
-      c.preventFalseAlias(n, whichAsgnOpc(x, opcWrArr), dest, tmp, a)
+      c.preventFalseAlias(n, opcWrArr, dest, tmp, a)
       c.gABI(n, opcAddImmInt, tmp, tmp, 1)
       c.freeTemp(a)
     c.freeTemp(tmp)
@@ -1881,7 +1880,7 @@ proc genObjConstr(c: PCtx, n: PNode, dest: var TDest) =
     if it.kind == nkExprColonExpr and it.sons[0].kind == nkSym:
       let idx = genField(c, it.sons[0])
       let tmp = c.genx(it.sons[1])
-      c.preventFalseAlias(it.sons[1], whichAsgnOpc(it.sons[1], opcWrObj),
+      c.preventFalseAlias(it.sons[1], opcWrObj,
                           dest, idx, tmp)
       c.freeTemp(tmp)
     else:
@@ -1896,12 +1895,12 @@ proc genTupleConstr(c: PCtx, n: PNode, dest: var TDest) =
     if it.kind == nkExprColonExpr:
       let idx = genField(c, it.sons[0])
       let tmp = c.genx(it.sons[1])
-      c.preventFalseAlias(it.sons[1], whichAsgnOpc(it.sons[1], opcWrObj),
+      c.preventFalseAlias(it.sons[1], opcWrObj,
                           dest, idx, tmp)
       c.freeTemp(tmp)
     else:
       let tmp = c.genx(it)
-      c.preventFalseAlias(it, whichAsgnOpc(it, opcWrObj), dest, i.TRegister, tmp)
+      c.preventFalseAlias(it, opcWrObj, dest, i.TRegister, tmp)
       c.freeTemp(tmp)
 
 proc genProc*(c: PCtx; s: PSym): int
@@ -2065,7 +2064,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
     c.freeTemp(tmp1)
     c.freeTemp(tmp2)
     if dest >= 0:
-      gABC(c, n, whichAsgnOpc(n), dest, tmp0, 1)
+      gABC(c, n, whichAsgnOpc(n), dest, tmp0)
       c.freeTemp(tmp0)
     else:
       dest = tmp0