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

Commit 210a78f

Browse files
committed
Explicitly include the namespace of methods in their Wasm names.
This will make sure that we do not confuse static and non-static methods with the same signatures.
1 parent 05d2288 commit 210a78f

File tree

6 files changed

+81
-27
lines changed

6 files changed

+81
-27
lines changed

Diff for: wasm/src/main/scala/ir2wasm/HelperFunctions.scala

+5-1
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,11 @@ object HelperFunctions {
322322
// TODO: "isInstance", "isAssignableFrom", "checkCast", "newArrayOfThisClass"
323323

324324
// Call java.lang.Class::<init>(dataObject)
325-
instrs += CALL(FuncIdx(WasmFunctionName(IRNames.ClassClass, SpecialNames.ClassCtor)))
325+
instrs += CALL(FuncIdx(WasmFunctionName(
326+
IRTrees.MemberNamespace.Constructor,
327+
IRNames.ClassClass,
328+
SpecialNames.ClassCtor
329+
)))
326330

327331
// typeData.classOf := classInstance
328332
instrs += LOCAL_GET(typeDataParam)

Diff for: wasm/src/main/scala/ir2wasm/Preprocessor.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ object Preprocessor {
4747
method: IRTrees.MethodDef
4848
): WasmFunctionInfo = {
4949
WasmFunctionInfo(
50-
Names.WasmFunctionName(clazz.name.name, method.name.name),
50+
Names.WasmFunctionName(method.flags.namespace, clazz.name.name, method.name.name),
5151
method.args.map(_.ptpe),
5252
method.resultType,
5353
isAbstract = method.body.isEmpty

Diff for: wasm/src/main/scala/ir2wasm/WasmBuilder.scala

+13-3
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,13 @@ class WasmBuilder {
235235
.getOrElse(throw new Error(s"Module class should have a constructor, ${clazz.name}"))
236236
val typeName = WasmTypeName.WasmStructTypeName(clazz.name.name)
237237
val globalInstanceName = WasmGlobalName.WasmModuleInstanceName.fromIR(clazz.name.name)
238-
val ctorName = WasmFunctionName(clazz.name.name, ctor.name.name)
238+
239+
val ctorName = WasmFunctionName(
240+
ctor.flags.namespace,
241+
clazz.name.name,
242+
ctor.name.name
243+
)
244+
239245
val body = List(
240246
// global.get $module_name
241247
// ref.if_null
@@ -360,7 +366,7 @@ class WasmBuilder {
360366
Names.WasmTypeName.WasmITableTypeName(className),
361367
classInfo.methods.map { m =>
362368
WasmStructField(
363-
Names.WasmFieldName(m.name.methodName),
369+
Names.WasmFieldName(m.name.simpleName),
364370
WasmRefNullType(WasmHeapType.Func(m.toWasmFunctionType().name)),
365371
isMutable = false
366372
)
@@ -429,7 +435,11 @@ class WasmBuilder {
429435
clazz: LinkedClass,
430436
method: IRTrees.MethodDef
431437
)(implicit ctx: WasmContext): WasmFunction = {
432-
val functionName = Names.WasmFunctionName(clazz.name.name, method.name.name)
438+
val functionName = Names.WasmFunctionName(
439+
method.flags.namespace,
440+
clazz.name.name,
441+
method.name.name
442+
)
433443

434444
// Receiver type for non-constructor methods needs to be `(ref any)` because params are invariant
435445
// Otherwise, vtable can't be a subtype of the supertype's subtype

Diff for: wasm/src/main/scala/ir2wasm/WasmExpressionBuilder.scala

+17-4
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,11 @@ private class WasmExpressionBuilder private (
337337
* After this code gen, the stack contains the result.
338338
*/
339339
def genHijackedClassCall(hijackedClass: IRNames.ClassName): Unit = {
340-
val funcName = Names.WasmFunctionName(hijackedClass, t.method.name)
340+
val funcName = Names.WasmFunctionName(
341+
IRTrees.MemberNamespace.Public,
342+
hijackedClass,
343+
t.method.name
344+
)
341345
instrs += CALL(FuncIdx(funcName))
342346
}
343347

@@ -522,7 +526,11 @@ private class WasmExpressionBuilder private (
522526

523527
val (methodIdx, info) = ctx
524528
.calculateVtableType(receiverClassName)
525-
.resolveWithIdx(WasmFunctionName(receiverClassName, methodName))
529+
.resolveWithIdx(WasmFunctionName(
530+
IRTrees.MemberNamespace.Public,
531+
receiverClassName,
532+
methodName
533+
))
526534

527535
// // push args to the stacks
528536
// local.get $this ;; for accessing funcref
@@ -582,7 +590,8 @@ private class WasmExpressionBuilder private (
582590
}
583591

584592
genArgs(t.args, t.method.name)
585-
val funcName = Names.WasmFunctionName(t.className, t.method.name)
593+
val namespace = IRTrees.MemberNamespace.forNonStaticCall(t.flags)
594+
val funcName = Names.WasmFunctionName(namespace, t.className, t.method.name)
586595
instrs += CALL(FuncIdx(funcName))
587596
if (t.tpe == IRTypes.NothingType)
588597
instrs += UNREACHABLE
@@ -1325,7 +1334,11 @@ private class WasmExpressionBuilder private (
13251334
instrs += CALL(FuncIdx(WasmFunctionName.newDefault(n.className)))
13261335
instrs += LOCAL_TEE(LocalIdx(localInstance.name))
13271336
genArgs(n.args, n.ctor.name)
1328-
instrs += CALL(FuncIdx(WasmFunctionName(n.className, n.ctor.name)))
1337+
instrs += CALL(FuncIdx(WasmFunctionName(
1338+
IRTrees.MemberNamespace.Constructor,
1339+
n.className,
1340+
n.ctor.name
1341+
)))
13291342
instrs += LOCAL_GET(LocalIdx(localInstance.name))
13301343
n.tpe
13311344
}

Diff for: wasm/src/main/scala/wasm4s/Names.scala

+31-8
Original file line numberDiff line numberDiff line change
@@ -97,23 +97,46 @@ object Names {
9797
// }
9898

9999
case class WasmFunctionName private (
100-
val className: String,
101-
val methodName: String
102-
) extends WasmName(s"$className#$methodName")
100+
val namespace: String,
101+
val simpleName: String
102+
) extends WasmName(namespace + "#" + simpleName)
103+
103104
object WasmFunctionName {
104-
def apply(clazz: IRNames.ClassName, method: IRNames.MethodName): WasmFunctionName =
105-
new WasmFunctionName(clazz.nameString, method.nameString)
105+
def apply(
106+
namespace: IRTrees.MemberNamespace,
107+
clazz: IRNames.ClassName,
108+
method: IRNames.MethodName
109+
): WasmFunctionName = {
110+
new WasmFunctionName(
111+
namespaceString(namespace) + "#" + clazz.nameString,
112+
method.nameString
113+
)
114+
}
115+
116+
private def namespaceString(namespace: IRTrees.MemberNamespace): String = {
117+
import IRTrees.MemberNamespace._
118+
119+
// These strings are the same ones that the JS back-end uses
120+
namespace match {
121+
case Public => "f"
122+
case Private => "p"
123+
case PublicStatic => "s"
124+
case PrivateStatic => "ps"
125+
case Constructor => "ct"
126+
case StaticConstructor => "sct"
127+
}
128+
}
106129

107130
def forExport(exportedName: String): WasmFunctionName =
108-
new WasmFunctionName(exportedName, "")
131+
new WasmFunctionName("export", exportedName)
109132

110133
// Adding prefix __ to avoid name clashes with user code.
111134
// It should be safe not to add prefix to the method name
112135
// since loadModule is a static method and it's not registered in the vtable.
113136
def loadModule(clazz: IRNames.ClassName): WasmFunctionName =
114-
new WasmFunctionName(s"__${clazz.nameString}", "loadModule")
137+
new WasmFunctionName("loadModule", clazz.nameString)
115138
def newDefault(clazz: IRNames.ClassName): WasmFunctionName =
116-
new WasmFunctionName(s"__${clazz.nameString}", "newDefault")
139+
new WasmFunctionName("new", clazz.nameString)
117140

118141
val start = new WasmFunctionName("start", "start")
119142

Diff for: wasm/src/main/scala/wasm4s/WasmContext.scala

+14-10
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ trait ReadOnlyWasmContext {
7070
): List[WasmFunctionInfo] = {
7171
collectMethods(name, includeAbstractMethods)
7272
.foldLeft(Array.empty[WasmFunctionInfo]) { case (acc, m) =>
73-
acc.indexWhere(_.name.methodName == m.name.methodName) match {
73+
acc.indexWhere(_.name.simpleName == m.name.simpleName) match {
7474
case i if i < 0 => acc :+ m
7575
case i => acc.updated(i, m)
7676
}
@@ -197,7 +197,7 @@ class WasmContext(val module: WasmModule) extends FunctionTypeWriterWasmContext
197197
): Unit = {
198198
val sig = WasmFunctionSignature(params, results)
199199
val typ = WasmFunctionType(addFunctionType(sig), sig)
200-
module.addImport(WasmImport(name.className, name.methodName, WasmImportDesc.Func(name, typ)))
200+
module.addImport(WasmImport(name.namespace, name.simpleName, WasmImportDesc.Func(name, typ)))
201201
}
202202

203203
addGCType(WasmStructType.typeData)
@@ -312,7 +312,11 @@ class WasmContext(val module: WasmModule) extends FunctionTypeWriterWasmContext
312312
instrs += WasmInstr.REF_AS_NOT_NULL
313313
instrs +=
314314
WasmInstr.CALL(
315-
WasmImmediate.FuncIdx(WasmFunctionName(name, encodedMainMethodName))
315+
WasmImmediate.FuncIdx(WasmFunctionName(
316+
IRTrees.MemberNamespace.Public,
317+
name,
318+
encodedMainMethodName
319+
))
316320
)
317321
}
318322
}
@@ -376,16 +380,16 @@ object WasmContext {
376380
def methods: List[WasmFunctionInfo] = _methods
377381

378382
def maybeAddAbstractMethod(methodName: IRNames.MethodName, ctx: WasmContext): Unit = {
379-
if (!methods.exists(_.name.methodName == methodName.nameString)) {
380-
val wasmName = WasmFunctionName(name, methodName)
383+
if (!methods.exists(_.name.simpleName == methodName.nameString)) {
384+
val wasmName = WasmFunctionName(IRTrees.MemberNamespace.Public, name, methodName)
381385
val argTypes = methodName.paramTypeRefs.map(ctx.inferTypeFromTypeRef(_))
382386
val resultType = ctx.inferTypeFromTypeRef(methodName.resultTypeRef)
383387
_methods = _methods :+ WasmFunctionInfo(wasmName, argTypes, resultType, isAbstract = true)
384388
}
385389
}
386390

387391
def getMethodInfo(methodName: IRNames.MethodName): WasmFunctionInfo = {
388-
methods.find(_.name.methodName == methodName.nameString).getOrElse {
392+
methods.find(_.name.simpleName == methodName.nameString).getOrElse {
389393
throw new IllegalArgumentException(
390394
s"Cannot find method ${methodName.nameString} in class ${name.nameString}"
391395
)
@@ -432,7 +436,7 @@ object WasmContext {
432436
val itableIdx =
433437
itables.lastIndexWhere { classInfo =>
434438
val methodIdx = classInfo.methods.lastIndexWhere { func =>
435-
func.name.methodName == name.nameString
439+
func.name.simpleName == name.nameString
436440
}
437441
if (methodIdx >= 0) {
438442
foundMethodIdx = methodIdx
@@ -447,12 +451,12 @@ object WasmContext {
447451
case class WasmVTable(val functions: List[WasmFunctionInfo]) {
448452
def resolve(name: WasmFunctionName): WasmFunctionInfo =
449453
functions
450-
.find(_.name.methodName == name.methodName)
454+
.find(_.name.simpleName == name.simpleName)
451455
.getOrElse(throw new Error(s"Function not found: $name"))
452456
def resolveWithIdx(name: WasmFunctionName): (Int, WasmFunctionInfo) = {
453-
val idx = functions.indexWhere(_.name.methodName == name.methodName)
457+
val idx = functions.indexWhere(_.name.simpleName == name.simpleName)
454458
if (idx < 0)
455-
throw new Error(s"Function not found: $name among ${functions.map(_.name.methodName)}")
459+
throw new Error(s"Function not found: $name among ${functions.map(_.name.simpleName)}")
456460
else (idx, functions(idx))
457461
}
458462
}

0 commit comments

Comments
 (0)