Skip to content

Commit def28b5

Browse files
authored
Merge pull request #4959 from sjrd/opt-char-tostring-in-fun-emitter
Optimize `String_+` for `char` at the emitter level.
2 parents b694955 + 58bec3f commit def28b5

File tree

4 files changed

+18
-8
lines changed

4 files changed

+18
-8
lines changed

javalib/src/main/scala/java/lang/Character.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ object Character {
118118
@inline def hashCode(value: Char): Int = value.toInt
119119

120120
@inline def toString(c: Char): String =
121-
js.Dynamic.global.String.fromCharCode(c.toInt).asInstanceOf[String]
121+
"" + c
122122

123123
def toString(codePoint: Int): String = {
124124
if (isBmpCodePoint(codePoint)) {

linker/shared/src/main/scala/org/scalajs/linker/backend/emitter/CoreJSLib.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -930,6 +930,9 @@ private[emitter] object CoreJSLib {
930930
defineFunction1(VarField.doubleToInt) { x =>
931931
Return(If(x > 2147483647, 2147483647, If(x < -2147483648, -2147483648, x | 0)))
932932
} :::
933+
defineFunction1(VarField.charToString) { x =>
934+
Return(Apply(genIdentBracketSelect(StringRef, "fromCharCode"), x :: Nil))
935+
} :::
933936
condDefs(semantics.stringIndexOutOfBounds != CheckedBehavior.Unchecked)(
934937
defineFunction2(VarField.charAt) { (s, i) =>
935938
val r = varRef("r")

linker/shared/src/main/scala/org/scalajs/linker/backend/emitter/FunctionEmitter.scala

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2391,8 +2391,8 @@ private[emitter] class FunctionEmitter(sjsGen: SJSGen) {
23912391

23922392
case BinaryOp(op, lhs, rhs) =>
23932393
import BinaryOp._
2394-
val newLhs = transformExprNoChar(lhs)
2395-
val newRhs = transformExprNoChar(rhs)
2394+
val newLhs = transformExpr(lhs, preserveChar = (op == String_+))
2395+
val newRhs = transformExpr(rhs, preserveChar = (op == String_+))
23962396

23972397
(op: @switch) match {
23982398
case === | !== =>
@@ -2445,11 +2445,16 @@ private[emitter] class FunctionEmitter(sjsGen: SJSGen) {
24452445
js.BinaryOp(JSBinaryOp.!==, newLhs, newRhs)
24462446

24472447
case String_+ =>
2448-
if (lhs.tpe == StringType || rhs.tpe == StringType) {
2449-
js.BinaryOp(JSBinaryOp.+, newLhs, newRhs)
2450-
} else {
2451-
js.BinaryOp(JSBinaryOp.+, js.BinaryOp(JSBinaryOp.+,
2452-
js.StringLiteral(""), newLhs), newRhs)
2448+
def charToString(t: js.Tree): js.Tree =
2449+
genCallHelper(VarField.charToString, t)
2450+
2451+
(lhs.tpe, rhs.tpe) match {
2452+
case (CharType, CharType) => charToString(newLhs) + charToString(newRhs)
2453+
case (CharType, _) => charToString(newLhs) + newRhs
2454+
case (_, CharType) => newLhs + charToString(newRhs)
2455+
case (StringType, _) => newLhs + newRhs
2456+
case (_, StringType) => newLhs + newRhs
2457+
case _ => (js.StringLiteral("") + newLhs) + newRhs
24532458
}
24542459

24552460
case Int_+ => or0(js.BinaryOp(JSBinaryOp.+, newLhs, newRhs))

linker/shared/src/main/scala/org/scalajs/linker/backend/emitter/VarField.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,8 @@ private[emitter] object VarField {
157157
/** Box char. */
158158
final val bC = mk("$bC")
159159

160+
final val charToString = mk("$cToS")
161+
160162
final val charAt = mk("$charAt")
161163

162164
// Object helpers

0 commit comments

Comments
 (0)