@@ -337,7 +337,7 @@ class WasmBuilder(coreSpec: CoreSpec) {
337
337
val proxyId = ctx.getReflectiveProxyId(proxyInfo.methodName)
338
338
List (
339
339
I32_CONST (proxyId),
340
- REF_FUNC (proxyInfo.wasmName ),
340
+ REF_FUNC (proxyInfo.tableEntryName ),
341
341
STRUCT_NEW (WasmStructTypeName .reflectiveProxy)
342
342
)
343
343
} :+ ARRAY_NEW_FIXED (WasmArrayTypeName .reflectiveProxies, reflectiveProxies.size)
@@ -417,7 +417,7 @@ class WasmBuilder(coreSpec: CoreSpec) {
417
417
classInfo.resolvedMethodInfos.valuesIterator.filter(_.methodName.isReflectiveProxy).toList
418
418
val typeDataFieldValues = genTypeDataFieldValues(clazz, reflectiveProxies)
419
419
val vtableElems = classInfo.tableEntries.map { methodName =>
420
- REF_FUNC (classInfo.resolvedMethodInfos(methodName).wasmName )
420
+ REF_FUNC (classInfo.resolvedMethodInfos(methodName).tableEntryName )
421
421
}
422
422
val globalVTable =
423
423
genTypeDataGlobal(typeRef, vtableTypeName, typeDataFieldValues, vtableElems)
@@ -489,29 +489,35 @@ class WasmBuilder(coreSpec: CoreSpec) {
489
489
ctor.name.name
490
490
)
491
491
492
+ val resultTyp = WasmRefType (typeName)
493
+
492
494
implicit val fctx = WasmFunctionContext (
493
495
WasmFunctionName .loadModule(clazz.className),
494
496
Nil ,
495
- List (WasmRefType .nullable(typeName) )
497
+ List (resultTyp )
496
498
)
497
499
500
+ val instanceLocal = fctx.addLocal(" instance" , resultTyp)
501
+
498
502
import fctx .instrs
499
503
500
- // global.get $module_name
501
- // ref.if_null
502
- // ref.null $module_type
503
- // call $module_init ;; should set to global
504
- // end
505
- // global.get $module_name
506
- instrs += GLOBAL_GET (globalInstanceName) // [rt]
507
- instrs += REF_IS_NULL // [rt] -> [i32] (bool)
508
- instrs += IF (BlockType .ValueType ())
509
- instrs += CALL (WasmFunctionName .newDefault(clazz.name.name))
510
- instrs += GLOBAL_SET (globalInstanceName)
511
- instrs += GLOBAL_GET (globalInstanceName)
512
- instrs += CALL (ctorName)
513
- instrs += END
514
- instrs += GLOBAL_GET (globalInstanceName) // [rt]
504
+ fctx.block(resultTyp) { nonNullLabel =>
505
+ // load global, return if not null
506
+ instrs += GLOBAL_GET (globalInstanceName)
507
+ instrs += BR_ON_NON_NULL (nonNullLabel)
508
+
509
+ // create an instance and call its constructor
510
+ instrs += CALL (WasmFunctionName .newDefault(clazz.name.name))
511
+ instrs += LOCAL_TEE (instanceLocal)
512
+ instrs += CALL (ctorName)
513
+
514
+ // store it in the global
515
+ instrs += LOCAL_GET (instanceLocal)
516
+ instrs += GLOBAL_SET (globalInstanceName)
517
+
518
+ // return it
519
+ instrs += LOCAL_GET (instanceLocal)
520
+ }
515
521
516
522
fctx.buildAndAddToContext()
517
523
}
@@ -1076,31 +1082,28 @@ class WasmBuilder(coreSpec: CoreSpec) {
1076
1082
private def genFunction (
1077
1083
clazz : LinkedClass ,
1078
1084
method : IRTrees .MethodDef
1079
- )(implicit ctx : WasmContext ): WasmFunction = {
1085
+ )(implicit ctx : WasmContext ): Unit = {
1080
1086
implicit val pos = method.pos
1081
1087
1082
- val functionName = Names .WasmFunctionName (
1083
- method.flags.namespace,
1084
- clazz.name.name,
1085
- method.name.name
1086
- )
1088
+ val namespace = method.flags.namespace
1089
+ val className = clazz.className
1090
+ val methodName = method.methodName
1091
+
1092
+ val functionName = Names .WasmFunctionName (namespace, className, methodName)
1093
+
1094
+ val isHijackedClass = ctx.getClassInfo(className).kind == ClassKind .HijackedClass
1087
1095
1088
- // Receiver type for non-constructor methods needs to be `(ref any)` because params are invariant
1089
- // Otherwise, vtable can't be a subtype of the supertype's subtype
1090
- // Constructor can use the exact type because it won't be registered to vtables.
1091
1096
val receiverTyp =
1092
- if (method.flags. namespace.isStatic)
1097
+ if (namespace.isStatic)
1093
1098
None
1094
- else if (clazz.kind == ClassKind .HijackedClass )
1095
- Some (transformType(IRTypes .BoxedClassToPrimType (clazz.name.name)))
1096
- else if (method.flags.namespace.isConstructor)
1097
- Some (WasmRefType .nullable(WasmTypeName .WasmStructTypeName .forClass(clazz.name.name)))
1099
+ else if (isHijackedClass)
1100
+ Some (transformType(IRTypes .BoxedClassToPrimType (className)))
1098
1101
else
1099
- Some (WasmRefType .any )
1102
+ Some (transformClassType(className).toNonNullable )
1100
1103
1101
1104
// Prepare for function context, set receiver and parameters
1102
1105
implicit val fctx = WasmFunctionContext (
1103
- Some (clazz. className),
1106
+ Some (className),
1104
1107
functionName,
1105
1108
receiverTyp,
1106
1109
method.args,
@@ -1111,7 +1114,48 @@ class WasmBuilder(coreSpec: CoreSpec) {
1111
1114
val body = method.body.getOrElse(throw new Exception (" abstract method cannot be transformed" ))
1112
1115
WasmExpressionBuilder .generateIRBody(body, method.resultType)
1113
1116
1114
- fctx.buildAndAddToContext(useFunctionTypeInMainRecType = true )
1117
+ fctx.buildAndAddToContext()
1118
+
1119
+ if (namespace == IRTrees .MemberNamespace .Public && ! isHijackedClass) {
1120
+ /* Also generate the bridge that is stored in the table entries. In table
1121
+ * entries, the receiver type is always `(ref any)`.
1122
+ *
1123
+ * TODO: generate this only when the method is actually referred to from
1124
+ * at least one table.
1125
+ */
1126
+
1127
+ implicit val fctx = WasmFunctionContext (
1128
+ Some (className),
1129
+ WasmFunctionName .forTableEntry(className, methodName),
1130
+ Some (WasmRefType .any),
1131
+ method.args,
1132
+ method.resultType
1133
+ )
1134
+
1135
+ import fctx .instrs
1136
+
1137
+ val receiverLocal :: paramLocals = fctx.paramIndices: @ unchecked
1138
+
1139
+ // Load and cast down the receiver
1140
+ instrs += LOCAL_GET (receiverLocal)
1141
+ receiverTyp match {
1142
+ case Some (Types .WasmRefType (_, WasmHeapType .Any )) =>
1143
+ () // no cast necessary
1144
+ case Some (receiverTyp : Types .WasmRefType ) =>
1145
+ instrs += REF_CAST (receiverTyp)
1146
+ case _ =>
1147
+ throw new AssertionError (s " Unexpected receiver type $receiverTyp" )
1148
+ }
1149
+
1150
+ // Load the other parameters
1151
+ for (paramLocal <- paramLocals)
1152
+ instrs += LOCAL_GET (paramLocal)
1153
+
1154
+ // Call the statically resolved method
1155
+ instrs += RETURN_CALL (functionName)
1156
+
1157
+ fctx.buildAndAddToContext(useFunctionTypeInMainRecType = true )
1158
+ }
1115
1159
}
1116
1160
1117
1161
private def transformField (
0 commit comments