Skip to content
This repository was archived by the owner on Jul 12, 2024. It is now read-only.

Commit c24131d

Browse files
committed
Make undef and emptyString global imports rather than functions.
In addition to the likely performance benefit, it allows us to use them in constant expressions, without support for the expression builder. We use that opportunity when creating the field values in `newDefault` functions, like we already did for static fields.
1 parent c9b8270 commit c24131d

File tree

5 files changed

+30
-20
lines changed

5 files changed

+30
-20
lines changed

Diff for: wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/ClassEmitter.scala

+17-11
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class ClassEmitter(coreSpec: CoreSpec) {
4242
val global = WasmGlobal(
4343
genGlobalName.forStaticField(name.name),
4444
transformType(ftpe),
45-
WasmExpr(List(genStaticVarInit(ftpe))),
45+
WasmExpr(List(genZeroOf(ftpe))),
4646
isMutable = true
4747
)
4848
ctx.addGlobal(global)
@@ -67,18 +67,24 @@ class ClassEmitter(coreSpec: CoreSpec) {
6767
}
6868
}
6969

70-
private def genStaticVarInit(tpe: IRTypes.Type)(implicit ctx: WasmContext): WasmInstr = {
70+
private def genZeroOf(tpe: IRTypes.Type)(implicit ctx: WasmContext): WasmInstr = {
7171
import IRTypes._
7272

7373
tpe match {
74-
case BooleanType | CharType | ByteType | ShortType | IntType => I32_CONST(0)
75-
case LongType => I64_CONST(0L)
76-
case FloatType => F32_CONST(0.0f)
77-
case DoubleType => F64_CONST(0.0)
78-
case AnyType | ClassType(_) | ArrayType(_) | NullType => REF_NULL(WasmHeapType.None)
79-
80-
case NoType | NothingType | StringType | UndefType | _: RecordType =>
81-
throw new AssertionError(s"Unexpected type for static variable: ${tpe.show()}")
74+
case BooleanType | CharType | ByteType | ShortType | IntType =>
75+
I32_CONST(0)
76+
77+
case LongType => I64_CONST(0L)
78+
case FloatType => F32_CONST(0.0f)
79+
case DoubleType => F64_CONST(0.0)
80+
case StringType => GLOBAL_GET(genGlobalName.emptyString)
81+
case UndefType => GLOBAL_GET(genGlobalName.undef)
82+
83+
case AnyType | ClassType(_) | ArrayType(_) | NullType =>
84+
REF_NULL(WasmHeapType.None)
85+
86+
case NoType | NothingType | _: RecordType =>
87+
throw new AssertionError(s"Unexpected type for field: ${tpe.show()}")
8288
}
8389
}
8490

@@ -533,7 +539,7 @@ class ClassEmitter(coreSpec: CoreSpec) {
533539
instrs += REF_NULL(WasmHeapType(genTypeName.itables))
534540

535541
classInfo.allFieldDefs.foreach { f =>
536-
WasmExpressionBuilder.generateIRBody(IRTypes.zeroOf(f.ftpe)(clazz.pos), f.ftpe)
542+
instrs += genZeroOf(f.ftpe)
537543
}
538544
instrs += STRUCT_NEW(structName)
539545

Diff for: wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/CoreWasmLib.scala

+3-3
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,8 @@ object CoreWasmLib {
168168
)
169169
}
170170

171+
addGlobalHelperImport(genGlobalName.undef, WasmRefType.any, isMutable = false)
172+
addGlobalHelperImport(genGlobalName.emptyString, WasmRefType.any, isMutable = false)
171173
addGlobalHelperImport(genGlobalName.idHashCodeMap, WasmRefType.extern, isMutable = false)
172174
}
173175

@@ -264,7 +266,6 @@ object CoreWasmLib {
264266

265267
addHelperImport(genFunctionName.is, List(anyref, anyref), List(WasmInt32))
266268

267-
addHelperImport(genFunctionName.undef, List(), List(WasmRefType.any))
268269
addHelperImport(genFunctionName.isUndef, List(anyref), List(WasmInt32))
269270

270271
for (primRef <- List(BooleanRef, ByteRef, ShortRef, IntRef, FloatRef, DoubleRef)) {
@@ -307,7 +308,6 @@ object CoreWasmLib {
307308
List(WasmRefType.any)
308309
)
309310

310-
addHelperImport(genFunctionName.emptyString, List(), List(WasmRefType.any))
311311
addHelperImport(genFunctionName.stringLength, List(WasmRefType.any), List(WasmInt32))
312312
addHelperImport(genFunctionName.stringCharAt, List(WasmRefType.any, WasmInt32), List(WasmInt32))
313313
addHelperImport(genFunctionName.jsValueToString, List(WasmRefType.any), List(WasmRefType.any))
@@ -521,7 +521,7 @@ object CoreWasmLib {
521521
instrs += LOCAL_SET(iLocal)
522522

523523
// result := ""
524-
instrs += CALL(genFunctionName.emptyString)
524+
instrs += GLOBAL_GET(genGlobalName.emptyString)
525525
instrs += LOCAL_SET(resultLocal)
526526

527527
instrs.loop() { labelLoop =>

Diff for: wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/LoaderContent.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ const scalaJSHelpers = {
7272
is: Object.is,
7373

7474
// undefined
75-
undef: () => void 0,
75+
undef: void 0,
7676
isUndef: (x) => x === (void 0),
7777

7878
// Boxes (upcast) -- most are identity at the JS level but with different types in Wasm
@@ -118,7 +118,7 @@ const scalaJSHelpers = {
118118
closureRestNoData: (f, n) => ((...args) => f(...args.slice(0, n), args.slice(n))),
119119

120120
// Strings
121-
emptyString: () => "",
121+
emptyString: "",
122122
stringLength: (s) => s.length,
123123
stringCharAt: (s, i) => s.charCodeAt(i),
124124
jsValueToString: (x) => (x === void 0) ? "undefined" : x.toString(),

Diff for: wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/VarGen.scala

+6-2
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ object VarGen {
3939
def forJSPrivateField(fieldName: FieldName): WasmGlobalName =
4040
WasmGlobalName(s"jspfield.${fieldName.nameString}")
4141

42+
val undef: WasmGlobalName =
43+
WasmGlobalName("undef")
44+
45+
val emptyString: WasmGlobalName =
46+
WasmGlobalName("emptyString")
47+
4248
val stringLiteralCache: WasmGlobalName =
4349
WasmGlobalName("string_literal")
4450

@@ -122,7 +128,6 @@ object VarGen {
122128

123129
val is = make("is")
124130

125-
val undef = make("undef")
126131
val isUndef = make("isUndef")
127132

128133
def box(primRef: PrimRef): WasmFunctionName = make("b" + primRef.charCode)
@@ -138,7 +143,6 @@ object VarGen {
138143
val closureThisRest = make("closureThisRest")
139144
val closureRestNoData = make("closureRestNoData")
140145

141-
val emptyString = make("emptyString")
142146
val stringLength = make("stringLength")
143147
val stringCharAt = make("stringCharAt")
144148
val jsValueToString = make("jsValueToString") // for actual toString() call

Diff for: wasm/src/main/scala/org/scalajs/linker/backend/wasmemitter/WasmExpressionBuilder.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -792,7 +792,7 @@ private class WasmExpressionBuilder private (
792792
case IRTrees.DoubleLiteral(v) => instrs += WasmInstr.F64_CONST(v)
793793

794794
case v: IRTrees.Undefined =>
795-
instrs += CALL(genFunctionName.undef)
795+
instrs += GLOBAL_GET(genGlobalName.undef)
796796
case v: IRTrees.Null =>
797797
instrs += WasmInstr.REF_NULL(Types.WasmHeapType.None)
798798

@@ -1586,7 +1586,7 @@ private class WasmExpressionBuilder private (
15861586
targetTpe match {
15871587
case IRTypes.UndefType =>
15881588
instrs += DROP
1589-
instrs += CALL(genFunctionName.undef)
1589+
instrs += GLOBAL_GET(genGlobalName.undef)
15901590
case IRTypes.StringType =>
15911591
instrs += REF_AS_NOT_NULL
15921592

0 commit comments

Comments
 (0)