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
This commit is contained in:
parent
dc8ac66873
commit
07c7a8a526
3 changed files with 81 additions and 23 deletions
|
|
@ -178,7 +178,7 @@ const
|
||||||
proc mapType(typ: PType): TJSTypeKind =
|
proc mapType(typ: PType): TJSTypeKind =
|
||||||
let t = skipTypes(typ, abstractInst)
|
let t = skipTypes(typ, abstractInst)
|
||||||
case t.kind
|
case t.kind
|
||||||
of tyVar, tyRef, tyPtr, tyLent:
|
of tyVar, tyRef, tyPtr:
|
||||||
if skipTypes(t.lastSon, abstractInst).kind in MappedToObject:
|
if skipTypes(t.lastSon, abstractInst).kind in MappedToObject:
|
||||||
result = etyObject
|
result = etyObject
|
||||||
else:
|
else:
|
||||||
|
|
@ -186,7 +186,8 @@ proc mapType(typ: PType): TJSTypeKind =
|
||||||
of tyPointer:
|
of tyPointer:
|
||||||
# treat a tyPointer like a typed pointer to an array of bytes
|
# treat a tyPointer like a typed pointer to an array of bytes
|
||||||
result = etyBaseIndex
|
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])
|
result = mapType(t[0])
|
||||||
of tyInt..tyInt64, tyUInt..tyUInt64, tyEnum, tyChar: result = etyInt
|
of tyInt..tyInt64, tyUInt..tyUInt64, tyEnum, tyChar: result = etyInt
|
||||||
of tyBool: result = etyBool
|
of tyBool: result = etyBool
|
||||||
|
|
@ -1060,14 +1061,14 @@ proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) =
|
||||||
xtyp = etySeq
|
xtyp = etySeq
|
||||||
case xtyp
|
case xtyp
|
||||||
of etySeq:
|
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])
|
lineF(p, "$1 = $2;$n", [a.rdLoc, b.rdLoc])
|
||||||
else:
|
else:
|
||||||
useMagic(p, "nimCopy")
|
useMagic(p, "nimCopy")
|
||||||
lineF(p, "$1 = nimCopy(null, $2, $3);$n",
|
lineF(p, "$1 = nimCopy(null, $2, $3);$n",
|
||||||
[a.rdLoc, b.res, genTypeInfo(p, y.typ)])
|
[a.rdLoc, b.res, genTypeInfo(p, y.typ)])
|
||||||
of etyObject:
|
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])
|
lineF(p, "$1 = $2;$n", [a.rdLoc, b.rdLoc])
|
||||||
else:
|
else:
|
||||||
useMagic(p, "nimCopy")
|
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, "$# = [$#, $#];$n", [a.res, b.address, b.res])
|
||||||
lineF(p, "$1 = $2;$n", [a.address, b.res])
|
lineF(p, "$1 = $2;$n", [a.address, b.res])
|
||||||
lineF(p, "$1 = $2;$n", [a.rdLoc, b.rdLoc])
|
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:
|
else:
|
||||||
internalError(p.config, x.info, $("genAsgn", b.typ, a.typ))
|
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])
|
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:
|
else:
|
||||||
lineF(p, "$1 = $2;$n", [a.rdLoc, b.rdLoc])
|
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,
|
v.kind notin {skProc, skFunc, skConverter, skMethod, skIterator,
|
||||||
skConst, skTemp, skLet})
|
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
|
let s = n.sym
|
||||||
if s.loc.r == nil: internalError(p.config, n.info, "genAddr: 3")
|
if s.loc.r == nil: internalError(p.config, n.info, "genAddr: 3")
|
||||||
case s.kind
|
case s.kind
|
||||||
|
|
@ -1456,13 +1465,17 @@ proc genSym(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
else:
|
else:
|
||||||
if s.loc.r == nil:
|
if s.loc.r == nil:
|
||||||
internalError(p.config, n.info, "symbol has no generated name: " & s.name.s)
|
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
|
r.kind = resVal
|
||||||
|
|
||||||
proc genDeref(p: PProc, n: PNode, r: var TCompRes) =
|
proc genDeref(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
let it = n[0]
|
let it = n[0]
|
||||||
let t = mapType(p, it.typ)
|
let t = mapType(p, it.typ)
|
||||||
if t == etyObject:
|
if t == etyObject or it.typ.kind == tyLent:
|
||||||
gen(p, it, r)
|
gen(p, it, r)
|
||||||
else:
|
else:
|
||||||
var a: TCompRes
|
var a: TCompRes
|
||||||
|
|
@ -1703,7 +1716,7 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope =
|
||||||
result = putToSeq("0", indirect)
|
result = putToSeq("0", indirect)
|
||||||
of tyFloat..tyFloat128:
|
of tyFloat..tyFloat128:
|
||||||
result = putToSeq("0.0", indirect)
|
result = putToSeq("0.0", indirect)
|
||||||
of tyRange, tyGenericInst, tyAlias, tySink, tyOwned:
|
of tyRange, tyGenericInst, tyAlias, tySink, tyOwned, tyLent:
|
||||||
result = createVar(p, lastSon(typ), indirect)
|
result = createVar(p, lastSon(typ), indirect)
|
||||||
of tySet:
|
of tySet:
|
||||||
result = putToSeq("{}", indirect)
|
result = putToSeq("{}", indirect)
|
||||||
|
|
@ -1745,7 +1758,7 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope =
|
||||||
createObjInitList(p, t, initIntSet(), initList)
|
createObjInitList(p, t, initIntSet(), initList)
|
||||||
result = ("({$1})") % [initList]
|
result = ("({$1})") % [initList]
|
||||||
if indirect: result = "[$1]" % [result]
|
if indirect: result = "[$1]" % [result]
|
||||||
of tyVar, tyPtr, tyLent, tyRef, tyPointer:
|
of tyVar, tyPtr, tyRef, tyPointer:
|
||||||
if mapType(p, t) == etyBaseIndex:
|
if mapType(p, t) == etyBaseIndex:
|
||||||
result = putToSeq("[null, 0]", indirect)
|
result = putToSeq("[null, 0]", indirect)
|
||||||
else:
|
else:
|
||||||
|
|
@ -2394,16 +2407,17 @@ proc genProc(oldProc: PProc, prc: PSym): Rope =
|
||||||
if prc.typ[0] != nil and sfPure notin prc.flags:
|
if prc.typ[0] != nil and sfPure notin prc.flags:
|
||||||
resultSym = prc.ast[resultPos].sym
|
resultSym = prc.ast[resultPos].sym
|
||||||
let mname = mangleName(p.module, resultSym)
|
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
|
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 = p.indentLine(("var $# = null;$n") % [mname])
|
||||||
resultAsgn.add p.indentLine("var $#_Idx = 0;$n" % [mname])
|
resultAsgn.add p.indentLine("var $#_Idx = 0;$n" % [mname])
|
||||||
else:
|
else:
|
||||||
let resVar = createVar(p, resultSym.typ, isIndirect(resultSym))
|
let resVar = createVar(p, resultSym.typ, isIndirect(resultSym))
|
||||||
resultAsgn = p.indentLine(("var $# = $#;$n") % [mname, resVar])
|
resultAsgn = p.indentLine(("var $# = $#;$n") % [mname, resVar])
|
||||||
gen(p, prc.ast[resultPos], a)
|
gen(p, prc.ast[resultPos], a)
|
||||||
if mapType(p, resultSym.typ) == etyBaseIndex:
|
if returnAddress:
|
||||||
returnStmt = "return [$#, $#];$n" % [a.address, a.res]
|
returnStmt = "return [$#, $#];$n" % [a.address, a.res]
|
||||||
else:
|
else:
|
||||||
returnStmt = "return $#;$n" % [a.res]
|
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 nkObjConstr: genObjConstr(p, n, r)
|
||||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv: genConv(p, n, r)
|
of nkHiddenStdConv, nkHiddenSubConv, nkConv: genConv(p, n, r)
|
||||||
of nkAddr, nkHiddenAddr:
|
of nkAddr, nkHiddenAddr:
|
||||||
genAddr(p, n, r)
|
if n.typ.kind in {tyLent}:
|
||||||
of nkDerefExpr, nkHiddenDeref: genDeref(p, n, r)
|
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 nkBracketExpr: genArrayAccess(p, n, r)
|
||||||
of nkDotExpr: genFieldAccess(p, n, r)
|
of nkDotExpr: genFieldAccess(p, n, r)
|
||||||
of nkCheckedFieldExpr: genCheckedFieldOp(p, n, nil, r)
|
of nkCheckedFieldExpr: genCheckedFieldOp(p, n, nil, r)
|
||||||
|
|
|
||||||
33
tests/js/tlent.nim
Normal file
33
tests/js/tlent.nim
Normal file
|
|
@ -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()
|
||||||
|
|
@ -17,22 +17,26 @@ proc main =
|
||||||
main()
|
main()
|
||||||
|
|
||||||
template main2 = # bug #15958
|
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
|
proc byLent[T](a: T): lent T = a
|
||||||
let a = [11,12]
|
let a = [11,12]
|
||||||
let b = @[21,23]
|
let b = @[21,23]
|
||||||
let ss = {1, 2, 3, 5}
|
let ss = {1, 2, 3, 5}
|
||||||
doAssert byLent(a) == [11,12]
|
doAssert byLent(a) == [11,12]
|
||||||
doAssert byLent(a).addr == a.addr
|
doAssert sameAddress(byLent(a), a)
|
||||||
doAssert byLent(b) == @[21,23]
|
doAssert byLent(b) == @[21,23]
|
||||||
when not defined(js): # pending bug #16073
|
# pending bug #16073
|
||||||
doAssert byLent(b).addr == b.addr
|
doAssert sameAddress(byLent(b), b)
|
||||||
doAssert byLent(ss) == {1, 2, 3, 5}
|
doAssert byLent(ss) == {1, 2, 3, 5}
|
||||||
doAssert byLent(ss).addr == ss.addr
|
doAssert sameAddress(byLent(ss), ss)
|
||||||
|
|
||||||
let r = new(float)
|
let r = new(float)
|
||||||
r[] = 10.0
|
r[] = 10.0
|
||||||
when not defined(js): # pending bug #16073
|
# bug #16073
|
||||||
doAssert byLent(r)[] == 10.0
|
doAssert byLent(r)[] == 10.0
|
||||||
|
|
||||||
when not defined(js): # pending bug https://github.com/timotheecour/Nim/issues/372
|
when not defined(js): # pending bug https://github.com/timotheecour/Nim/issues/372
|
||||||
let p = create(float)
|
let p = create(float)
|
||||||
|
|
@ -41,9 +45,9 @@ template main2 = # bug #15958
|
||||||
|
|
||||||
proc byLent2[T](a: openArray[T]): lent T = a[0]
|
proc byLent2[T](a: openArray[T]): lent T = a[0]
|
||||||
doAssert byLent2(a) == 11
|
doAssert byLent2(a) == 11
|
||||||
doAssert byLent2(a).addr == a[0].addr
|
doAssert sameAddress(byLent2(a), a[0])
|
||||||
doAssert byLent2(b) == 21
|
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]
|
proc byLent3[T](a: varargs[T]): lent T = a[1]
|
||||||
let
|
let
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue