summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorhlaaftana <10591326+hlaaftana@users.noreply.github.com>2022-01-17 15:03:40 +0300
committerGitHub <noreply@github.com>2022-01-17 13:03:40 +0100
commit07c7a8a526cf4fd12c96192cda7a750fbea3382f (patch)
tree5ed5efb53bc4e091e32961cbab469e6788b53fa8
parentdc8ac66873d5189f2e5cf5dbf56a12ab64a38140 (diff)
downloadNim-07c7a8a526cf4fd12c96192cda7a750fbea3382f.tar.gz
Optimize lent in JS [backport:1.6] (#19393)
* Optimize lent in JS [backport:1.6]

* addr on lent doesn't work anymore, don't use it

* use unsafeAddr  in test again for older versions
-rw-r--r--compiler/jsgen.nim51
-rw-r--r--tests/js/tlent.nim33
-rw-r--r--tests/lent/tbasic_lent_check.nim20
3 files changed, 81 insertions, 23 deletions
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim
index 7e8c25173..0a7036b46 100644
--- a/compiler/jsgen.nim
+++ b/compiler/jsgen.nim
@@ -178,7 +178,7 @@ const
 proc mapType(typ: PType): TJSTypeKind =
   let t = skipTypes(typ, abstractInst)
   case t.kind
-  of tyVar, tyRef, tyPtr, tyLent:
+  of tyVar, tyRef, tyPtr:
     if skipTypes(t.lastSon, abstractInst).kind in MappedToObject:
       result = etyObject
     else:
@@ -186,7 +186,8 @@ proc mapType(typ: PType): TJSTypeKind =
   of tyPointer:
     # treat a tyPointer like a typed pointer to an array of bytes
     result = etyBaseIndex
-  of tyRange, tyDistinct, tyOrdinal, tyProxy:
+  of tyRange, tyDistinct, tyOrdinal, tyProxy, tyLent:
+    # tyLent is no-op as JS has pass-by-reference semantics
     result = mapType(t[0])
   of tyInt..tyInt64, tyUInt..tyUInt64, tyEnum, tyChar: result = etyInt
   of tyBool: result = etyBool
@@ -1060,14 +1061,14 @@ proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) =
     xtyp = etySeq
   case xtyp
   of etySeq:
-    if (needsNoCopy(p, y) and needsNoCopy(p, x)) or noCopyNeeded:
+    if x.typ.kind in {tyVar, tyLent} or (needsNoCopy(p, y) and needsNoCopy(p, x)) or noCopyNeeded:
       lineF(p, "$1 = $2;$n", [a.rdLoc, b.rdLoc])
     else:
       useMagic(p, "nimCopy")
       lineF(p, "$1 = nimCopy(null, $2, $3);$n",
                [a.rdLoc, b.res, genTypeInfo(p, y.typ)])
   of etyObject:
-    if x.typ.kind in {tyVar} or (needsNoCopy(p, y) and needsNoCopy(p, x)) or noCopyNeeded:
+    if x.typ.kind in {tyVar, tyLent} or (needsNoCopy(p, y) and needsNoCopy(p, x)) or noCopyNeeded:
       lineF(p, "$1 = $2;$n", [a.rdLoc, b.rdLoc])
     else:
       useMagic(p, "nimCopy")
@@ -1092,10 +1093,18 @@ proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) =
         lineF(p, "$# = [$#, $#];$n", [a.res, b.address, b.res])
         lineF(p, "$1 = $2;$n", [a.address, b.res])
         lineF(p, "$1 = $2;$n", [a.rdLoc, b.rdLoc])
+      elif a.typ == etyBaseIndex:
+        # array indexing may not map to var type
+        if b.address != nil:
+          lineF(p, "$1 = $2; $3 = $4;$n", [a.address, b.address, a.res, b.res])
+        else:
+          lineF(p, "$1 = $2;$n", [a.address, b.res])
       else:
         internalError(p.config, x.info, $("genAsgn", b.typ, a.typ))
-    else:
+    elif b.address != nil:
       lineF(p, "$1 = $2; $3 = $4;$n", [a.address, b.address, a.res, b.res])
+    else:
+      lineF(p, "$1 = $2;$n", [a.address, b.res])
   else:
     lineF(p, "$1 = $2;$n", [a.rdLoc, b.rdLoc])
 
@@ -1288,7 +1297,7 @@ template isIndirect(x: PSym): bool =
     v.kind notin {skProc, skFunc, skConverter, skMethod, skIterator,
                   skConst, skTemp, skLet})
 
-proc genSymAddr(p: PProc, n: PNode, typ: PType, r: var TCompRes) = 
+proc genSymAddr(p: PProc, n: PNode, typ: PType, r: var TCompRes) =
   let s = n.sym
   if s.loc.r == nil: internalError(p.config, n.info, "genAddr: 3")
   case s.kind
@@ -1456,13 +1465,17 @@ proc genSym(p: PProc, n: PNode, r: var TCompRes) =
   else:
     if s.loc.r == nil:
       internalError(p.config, n.info, "symbol has no generated name: " & s.name.s)
-    r.res = s.loc.r
+    if mapType(p, s.typ) == etyBaseIndex:
+      r.address = s.loc.r
+      r.res = s.loc.r & "_Idx"
+    else:
+      r.res = s.loc.r
   r.kind = resVal
 
 proc genDeref(p: PProc, n: PNode, r: var TCompRes) =
   let it = n[0]
   let t = mapType(p, it.typ)
-  if t == etyObject:
+  if t == etyObject or it.typ.kind == tyLent:
     gen(p, it, r)
   else:
     var a: TCompRes
@@ -1703,7 +1716,7 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope =
       result = putToSeq("0", indirect)
   of tyFloat..tyFloat128:
     result = putToSeq("0.0", indirect)
-  of tyRange, tyGenericInst, tyAlias, tySink, tyOwned:
+  of tyRange, tyGenericInst, tyAlias, tySink, tyOwned, tyLent:
     result = createVar(p, lastSon(typ), indirect)
   of tySet:
     result = putToSeq("{}", indirect)
@@ -1745,7 +1758,7 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope =
     createObjInitList(p, t, initIntSet(), initList)
     result = ("({$1})") % [initList]
     if indirect: result = "[$1]" % [result]
-  of tyVar, tyPtr, tyLent, tyRef, tyPointer:
+  of tyVar, tyPtr, tyRef, tyPointer:
     if mapType(p, t) == etyBaseIndex:
       result = putToSeq("[null, 0]", indirect)
     else:
@@ -2394,16 +2407,17 @@ proc genProc(oldProc: PProc, prc: PSym): Rope =
   if prc.typ[0] != nil and sfPure notin prc.flags:
     resultSym = prc.ast[resultPos].sym
     let mname = mangleName(p.module, resultSym)
-    if not isIndirect(resultSym) and
+    let returnAddress = not isIndirect(resultSym) and
       resultSym.typ.kind in {tyVar, tyPtr, tyLent, tyRef, tyOwned} and
-        mapType(p, resultSym.typ) == etyBaseIndex:
+        mapType(p, resultSym.typ) == etyBaseIndex
+    if returnAddress:
       resultAsgn = p.indentLine(("var $# = null;$n") % [mname])
       resultAsgn.add p.indentLine("var $#_Idx = 0;$n" % [mname])
     else:
       let resVar = createVar(p, resultSym.typ, isIndirect(resultSym))
       resultAsgn = p.indentLine(("var $# = $#;$n") % [mname, resVar])
     gen(p, prc.ast[resultPos], a)
-    if mapType(p, resultSym.typ) == etyBaseIndex:
+    if returnAddress:
       returnStmt = "return [$#, $#];$n" % [a.address, a.res]
     else:
       returnStmt = "return $#;$n" % [a.res]
@@ -2579,8 +2593,15 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
   of nkObjConstr: genObjConstr(p, n, r)
   of nkHiddenStdConv, nkHiddenSubConv, nkConv: genConv(p, n, r)
   of nkAddr, nkHiddenAddr:
-    genAddr(p, n, r)
-  of nkDerefExpr, nkHiddenDeref: genDeref(p, n, r)
+    if n.typ.kind in {tyLent}:
+      gen(p, n[0], r)
+    else:
+      genAddr(p, n, r)
+  of nkDerefExpr, nkHiddenDeref:
+    if n.typ.kind in {tyLent}:
+      gen(p, n[0], r)
+    else:
+      genDeref(p, n, r)
   of nkBracketExpr: genArrayAccess(p, n, r)
   of nkDotExpr: genFieldAccess(p, n, r)
   of nkCheckedFieldExpr: genCheckedFieldOp(p, n, nil, r)
diff --git a/tests/js/tlent.nim b/tests/js/tlent.nim
new file mode 100644
index 000000000..2546e5b1d
--- /dev/null
+++ b/tests/js/tlent.nim
@@ -0,0 +1,33 @@
+discard """
+  output: '''
+hmm
+100
+hmm
+100
+'''
+"""
+
+# #16800
+
+type A = object
+  b: int
+var t = A(b: 100)
+block:
+  proc getValues: lent int =
+    echo "hmm"
+    result = t.b
+  echo getValues()
+block:
+  proc getValues: lent int =
+    echo "hmm"
+    t.b
+  echo getValues()
+
+when false: # still an issue, #16908
+  template main =
+    iterator fn[T](a:T): lent T = yield a
+    let a = @[10]
+    for b in fn(a): echo b
+
+  static: main()
+  main()
diff --git a/tests/lent/tbasic_lent_check.nim b/tests/lent/tbasic_lent_check.nim
index 0787e36d9..92d731451 100644
--- a/tests/lent/tbasic_lent_check.nim
+++ b/tests/lent/tbasic_lent_check.nim
@@ -17,22 +17,26 @@ proc main =
 main()
 
 template main2 = # bug #15958
+  when defined(js):
+    proc sameAddress[T](a, b: T): bool {.importjs: "(# === #)".}
+  else:
+    template sameAddress(a, b): bool = a.unsafeAddr == b.unsafeAddr
   proc byLent[T](a: T): lent T = a
   let a = [11,12]
   let b = @[21,23]
   let ss = {1, 2, 3, 5}
   doAssert byLent(a) == [11,12]
-  doAssert byLent(a).addr == a.addr
+  doAssert sameAddress(byLent(a), a)
   doAssert byLent(b) == @[21,23]
-  when not defined(js): # pending bug #16073
-    doAssert byLent(b).addr == b.addr
+  # pending bug #16073
+  doAssert sameAddress(byLent(b), b)
   doAssert byLent(ss) == {1, 2, 3, 5}
-  doAssert byLent(ss).addr == ss.addr
+  doAssert sameAddress(byLent(ss), ss)
 
   let r = new(float)
   r[] = 10.0
-  when not defined(js): # pending bug #16073
-    doAssert byLent(r)[] == 10.0
+  # bug #16073
+  doAssert byLent(r)[] == 10.0
 
   when not defined(js): # pending bug https://github.com/timotheecour/Nim/issues/372
     let p = create(float)
@@ -41,9 +45,9 @@ template main2 = # bug #15958
 
   proc byLent2[T](a: openArray[T]): lent T = a[0]
   doAssert byLent2(a) == 11
-  doAssert byLent2(a).addr == a[0].addr
+  doAssert sameAddress(byLent2(a), a[0])
   doAssert byLent2(b) == 21
-  doAssert byLent2(b).addr == b[0].addr
+  doAssert sameAddress(byLent2(b), b[0])
 
   proc byLent3[T](a: varargs[T]): lent T = a[1]
   let