[dart2wasm] Make most void functions have no return values

This gives around 0.2% improvement in compressed e main module.

In Dart a function with `void` return type can actually return values
that callers can observe. But most of the time this doesn't happen, most
times those functions return `null` values and callers don't observe
them.

Let's use inferred return value information to see if a function is
guaranteed to only return `null`. If so we make the wasm function
signature not return any values. Callers will then synthesize a `null`
which may immediatly be dropped or (in rare cases) actually be used.

This leads to less less instructions in the callee (as a callee doesn't
need to push the null onto the stack) and the caller (as the caller
doesn't have to drop it from the stack).

Change-Id: I3ed1be7592798ad0c697c5bc3ab2c4b64c156f03
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/497620
Commit-Queue: Martin Kustermann <kustermann@google.com>
Reviewed-by: Srujan Gaddam <srujzs@google.com>
This commit is contained in:
Martin Kustermann
2026-04-28 00:20:02 -07:00
committed by dart-scoped@luci-project-accounts.iam.gserviceaccount.com
parent 75479bc7a7
commit b8b0cad67a
28 changed files with 261 additions and 185 deletions
+16 -1
View File
@@ -2065,6 +2065,11 @@ abstract class AstCodeGenerator
table: dispatchTable,
);
}
if (selector.synthesizeNullReturnValue) {
assert(selector.signature.outputs.isEmpty);
b.ref_null(w.HeapType.none);
return w.RefType(w.HeapType.none, nullable: true);
}
return translator.outputOrVoid(signature.outputs);
}
@@ -3546,6 +3551,7 @@ CodeGenerator? getInlinableMemberCodeGenerator(
translator,
functionType,
member,
reference,
reference.entryKind,
);
}
@@ -3558,12 +3564,14 @@ CodeGenerator? getInlinableMemberCodeGenerator(
class SynchronousProcedureCodeGenerator extends AstCodeGenerator {
final Procedure member;
final Reference reference;
final EntryPoint kind;
SynchronousProcedureCodeGenerator(
Translator translator,
w.FunctionType functionType,
this.member,
this.reference,
this.kind,
) : super(translator, functionType, member) {
assert(
@@ -3639,7 +3647,7 @@ class SynchronousProcedureCodeGenerator extends AstCodeGenerator {
final outputs = call(member.bodyReference);
if (outputs.isNotEmpty) {
translator.convertType(b, outputs.single, functionType.outputs.single);
translator.convertType(b, outputs.single, returnType);
}
_returnFromFunction();
b.end();
@@ -6094,6 +6102,9 @@ abstract class CallTarget {
CallTarget(this.signature);
/// Whether callers should synthesize a `null` return value.
bool get synthesizeNullReturnValue => false;
/// Whether this call target supports inlining.
bool get supportsInlining => false;
@@ -6123,6 +6134,10 @@ class AstCallTarget extends CallTarget {
AstCallTarget(super.signature, this._translator, this._reference);
@override
bool get synthesizeNullReturnValue =>
_translator.synthesizeNullReturnValue(_reference);
@override
String get name => _translator.functions.getFunctionName(_reference);
+14
View File
@@ -61,6 +61,11 @@ class SelectorInfo {
/// This should be read after all targets have been added to the selector.
late final w.FunctionType signature = _computeSignature();
/// Whether callers should synthesize a `null` return value.
///
/// Will be set during `_computeSignature`.
late final bool synthesizeNullReturnValue;
/// The selector's member's name.
final String name;
@@ -203,6 +208,15 @@ class SelectorInfo {
outputSets.length,
(i) => _upperBound(outputSets[i], ensureBoxed: false),
);
if (outputs case [w.RefType(heapType: w.HeapType.none, nullable: true)]) {
// All functions are guaranteed to return null.
// Will prune the signature and make call sites synthesize `null` if
// needed.
outputs.clear();
synthesizeNullReturnValue = true;
} else {
synthesizeNullReturnValue = false;
}
return translator.typesBuilder.defineFunction([
inputs[0],
...typeParameters,
+61 -10
View File
@@ -105,6 +105,7 @@ class FunctionCollector {
member.reference,
null,
isImportOrExport: true,
synthesizeNullReturnValue: false,
);
return _functions[member.reference] =
translator
@@ -133,7 +134,13 @@ class FunctionCollector {
}
final w.FunctionType ftype = exportName != null
? _makeFunctionType(translator, target, null, isImportOrExport: true)
? _makeFunctionType(
translator,
target,
null,
isImportOrExport: true,
synthesizeNullReturnValue: false,
)
: translator.signatureForDirectCall(target);
final function = module.functions.define(ftype, getFunctionName(target))
@@ -232,15 +239,35 @@ class FunctionCollector {
w.FunctionType _getFunctionType(Reference target) {
final Member member = target.asMember;
final synthesizeNullReturnValue = this.synthesizeNullReturnValue(target);
if (target.isBodyReference) {
// This is the function body that is always called directly (never via
// dispatch table) and with checked arguments. That means we can make a
// precise function type signature based on that member's argument types.
return makeFunctionTypeForBody(translator, member);
return makeFunctionTypeForBody(
translator,
member,
synthesizeNullReturnValue,
);
}
return member.accept1(_FunctionTypeGenerator(translator), target);
return member.accept1(
_FunctionTypeGenerator(translator, synthesizeNullReturnValue),
target,
);
}
bool synthesizeNullReturnValue(Reference target) {
final member = target.asMember;
if (member is! Procedure) return false;
final returnType = translator.typeOfReturnValue(member);
final wasmType = translator.translateType(returnType);
if (wasmType case w.RefType(heapType: w.HeapType.none, nullable: true)) {
return true;
}
return false;
}
String getFunctionName(Reference target) {
@@ -379,14 +406,20 @@ class FunctionCollector {
class _FunctionTypeGenerator extends MemberVisitor1<w.FunctionType, Reference> {
final Translator translator;
final bool synthesizeNullReturnValue;
_FunctionTypeGenerator(this.translator);
_FunctionTypeGenerator(this.translator, this.synthesizeNullReturnValue);
@override
w.FunctionType visitField(Field node, Reference target) {
if (!node.isInstanceMember) {
// Static field initializer function or implicit getter/setter.
return _makeFunctionType(translator, target, null);
return _makeFunctionType(
translator,
target,
null,
synthesizeNullReturnValue: synthesizeNullReturnValue,
);
}
assert(
!translator.dispatchTable
@@ -405,6 +438,7 @@ class _FunctionTypeGenerator extends MemberVisitor1<w.FunctionType, Reference> {
translator,
target,
translator.translateType(receiverType),
synthesizeNullReturnValue: synthesizeNullReturnValue,
);
}
@@ -412,7 +446,12 @@ class _FunctionTypeGenerator extends MemberVisitor1<w.FunctionType, Reference> {
w.FunctionType visitProcedure(Procedure node, Reference target) {
assert(!node.isAbstract);
if (!node.isInstanceMember) {
return _makeFunctionType(translator, target, null);
return _makeFunctionType(
translator,
target,
null,
synthesizeNullReturnValue: synthesizeNullReturnValue,
);
}
assert(
@@ -432,7 +471,12 @@ class _FunctionTypeGenerator extends MemberVisitor1<w.FunctionType, Reference> {
return makeTearOffFunctionType(translator, node.function, receiverType);
}
return _makeFunctionType(translator, target, receiverType);
return _makeFunctionType(
translator,
target,
receiverType,
synthesizeNullReturnValue: synthesizeNullReturnValue,
);
}
@override
@@ -664,7 +708,11 @@ List<w.ValueType> _getInputTypes(
// Implicit setters also support checked/unchecked entries, but those will not
// call a shared body but have such body (which is trivial) in the checked &
// unchecked functions directly.
w.FunctionType makeFunctionTypeForBody(Translator translator, Member member) {
w.FunctionType makeFunctionTypeForBody(
Translator translator,
Member member,
bool synthesizeNullReturnValue,
) {
assert(member.isInstanceMember);
assert(member is Procedure);
final function = member.function!;
@@ -685,7 +733,8 @@ w.FunctionType makeFunctionTypeForBody(Translator translator, Member member) {
];
final hasNoReturnValue =
member is Procedure && (member.isSetter || member.name.text == '[]=');
member is Procedure && (member.isSetter || member.name.text == '[]=') ||
synthesizeNullReturnValue;
final outputs = [
if (!hasNoReturnValue)
translator.translateReturnType(translator.typeOfReturnValue(member)),
@@ -770,6 +819,7 @@ w.FunctionType _makeFunctionType(
Translator translator,
Reference target,
w.ValueType? receiverType, {
required bool synthesizeNullReturnValue,
bool isImportOrExport = false,
}) {
Member member = target.asMember;
@@ -804,7 +854,8 @@ w.FunctionType _makeFunctionType(
(t is InterfaceType && t.classNode == translator.wasmVoidClass);
final List<w.ValueType> outputs;
final hasNoReturnValue = target.isSetter || member.name.text == '[]=';
final hasNoReturnValue =
target.isSetter || member.name.text == '[]=' || synthesizeNullReturnValue;
if (hasNoReturnValue) {
// Setters and []= are the only functions without any returned values. All
// other functions can return values (even `void` returning functions).
+37 -2
View File
@@ -759,10 +759,19 @@ class Translator with KernelNodes {
w.InstructionsBuilder b,
) {
final callTarget = directCallTarget(reference);
late final List<w.ValueType> outputs;
if (callTarget.supportsInlining && callTarget.shouldInline) {
return b.inlineCallTo(callTarget);
outputs = b.inlineCallTo(callTarget);
} else {
outputs = callFunction(callTarget.function, b);
}
return callFunction(functions.getFunction(reference), b);
if (callTarget.synthesizeNullReturnValue) {
assert(outputs.isEmpty);
b.ref_null(w.HeapType.none);
return [w.RefType(w.HeapType.none, nullable: true)];
}
return outputs;
}
late final WasmMemoryImporter _importedMemories = WasmMemoryImporter(
@@ -944,6 +953,10 @@ class Translator with KernelNodes {
if (type is InterfaceType) {
Class cls = type.classNode;
if (cls == coreTypes.deprecatedNullClass) {
return const w.RefType.none(nullable: true);
}
// Abstract `Function`?
if (cls == coreTypes.functionClass) {
return w.RefType.def(
@@ -1752,6 +1765,22 @@ class Translator with KernelNodes {
return functions.getFunctionType(target);
}
bool synthesizeNullReturnValue(Reference target) {
final member = target.asMember;
if (member.isInstanceMember) {
final table = dispatchTable;
final selector = table.selectorForTarget(target);
if (selector.containsTarget(target)) {
assert(
!selector.synthesizeNullReturnValue ||
selector.signature.outputs.isEmpty,
);
return selector.synthesizeNullReturnValue;
}
}
return functions.synthesizeNullReturnValue(target);
}
ParameterInfo paramInfoForDirectCall(Reference target) {
if (target.asMember.isInstanceMember) {
final table = dispatchTable;
@@ -2012,6 +2041,10 @@ class Translator with KernelNodes {
) {
if (inferredType == null) return null;
if (defaultType is VoidType) {
defaultType = coreTypes.objectNullableRawType;
}
// To check whether [inferredType] is more precise than [defaultType] we
// require it (for now) to be an interface type.
if (defaultType is! InterfaceType) return null;
@@ -2037,6 +2070,8 @@ class Translator with KernelNodes {
return null;
}
if (concreteClass == coreTypes.deprecatedNullClass) return const NullType();
final typeParameters = concreteClass.typeParameters;
final typeArguments = typeParameters.isEmpty
? const <DartType>[]
+6 -1
View File
@@ -102,6 +102,7 @@
struct.get $SubNamed $subInitializerField
call $JSStringImpl._interpolate4
call $print
ref.null none
drop
)
(func $"new SubNamed (initializer)" (param $var0 (ref $_Type)) (param $onlyUsedInSubField i64) (param $onlyUsedInSuper i64) (result (ref $_Type)) (result (ref $WasmListBase)) (result (ref null $#Top)) (result (ref null $#Top)) (result i64)
@@ -144,6 +145,7 @@
struct.get $SubOptionalNamed $subInitializerField
call $JSStringImpl._interpolate4
call $print
ref.null none
drop
)
(func $"new SubOptionalNamed (initializer)" (param $var0 (ref $_Type)) (param $onlyUsedInSubField (ref null $BoxedInt)) (param $onlyUsedInSuper (ref null $BoxedInt)) (result (ref $_Type)) (result (ref $WasmListBase)) (result (ref null $#Top)) (result (ref $_Type)) (result (ref null $#Top)) (result i64)
@@ -186,6 +188,7 @@
array.new_fixed $Array<Object?> 6
call $JSStringImpl._interpolate
call $print
ref.null none
drop
)
(func $"new SubOptionalPos (initializer)" (param $var0 (ref $_Type)) (param $onlyUsedInSubField (ref null $BoxedInt)) (param $onlyUsedInSubBody (ref null $BoxedInt)) (param $onlyUsedInSuper1 (ref null $BoxedInt)) (param $onlyUsedInSuper2 (ref null $BoxedInt)) (result (ref null $BoxedInt)) (result i64) (result (ref $_Type)) (result (ref $WasmListBase)) (result (ref null $#Top)) (result (ref $_Type)) (result (ref null $#Top)) (result i64)
@@ -251,6 +254,7 @@
array.new_fixed $Array<Object?> 6
call $JSStringImpl._interpolate
call $print
ref.null none
drop
)
(func $"new SubPos1 (initializer)" (param $var0 (ref $_Type)) (param $onlyUsedInSubField i64) (param $onlyUsedInSubBody i64) (param $onlyUsedInSuper1 i64) (param $onlyUsedInSuper2 i64) (result i64) (result i64) (result (ref $_Type)) (result (ref $WasmListBase)) (result (ref null $#Top)) (result (ref $_Type)) (result (ref null $#Top)) (result i64)
@@ -310,6 +314,7 @@
struct.get $SubPos2 $subInitializerField
call $JSStringImpl._interpolate4
call $print
ref.null none
drop
)
(func $"new SubPos2 (initializer)" (param $var0 (ref $_Type)) (param $onlyUsedInSubField i64) (param $onlyUsedInSuper1 i64) (result (ref $_Type)) (result (ref $WasmListBase)) (result (ref null $#Top)) (result (ref null $#Top)) (result i64)
@@ -616,5 +621,5 @@
struct.get $SubPos2 $field2
array.new_fixed $Array<_Type> 1
)
(func $print (param $object (ref null $#Top)) (result (ref null $#Top)) <...>)
(func $print (param $object (ref null $#Top)) <...>)
)
@@ -29,8 +29,8 @@
(set 13 (ref.func $JSStringImpl._interpolate))
(set 14 (ref.func $JSStringImpl.fromRefUnchecked))
(set 15 (ref.func $JSStringImpl._interpolate2)))
(func $Error._throwWithCurrentStackTrace <noInline> (param $var0 (ref $#Top)) (result (ref none)) <...>)
(func $_throwIndexError <noInline> (param $var0 i64) (param $var1 i64) (param $var2 (ref null $JSExternWrapper)) (result (ref none)) <...>)
(func $Error._throwWithCurrentStackTrace <noInline> (param $var0 (ref $#Top)) <...>)
(func $_throwIndexError <noInline> (param $var0 i64) (param $var1 i64) (param $var2 (ref null $JSExternWrapper)) <...>)
(func $IntegerDivisionByZeroException (result (ref $Object)) <...>)
(func $JSStringImpl.+ (param $var0 (ref $JSExternWrapper)) (param $var1 (ref $JSExternWrapper)) (result (ref $JSExternWrapper)) <...>)
(func $JSStringImpl._interpolate (param $var0 (ref $Array<Object?>)) (result (ref $JSExternWrapper)) <...>)
@@ -26,7 +26,7 @@
(elem $module0.cross-module-funcs-0
(set 0 (ref.func $int.parse))
(set 1 (ref.func $"mainImpl <noInline>")))
(func $"mainImpl <noInline>" (param $var0 i32) (result (ref null $#Top))
(func $"mainImpl <noInline>" (param $var0 i32)
i64.const 0
i32.const 2
call_indirect $module0.cross-module-funcs-0 (param i64) (result i32)
@@ -45,10 +45,9 @@
if
global.get $"\"bad\""
i32.const 4
call_indirect $module0.cross-module-funcs-0 (param (ref $#Top)) (result (ref none))
call_indirect $module0.cross-module-funcs-0 (param (ref $#Top))
unreachable
end
ref.null none
)
(func $"modH1Use <noInline>" (param $var0 i32) (result (ref $MyConstClass))
local.get $var0
@@ -8,5 +8,5 @@
(set 3 (ref.func $print)))
(func $JSStringImpl._interpolate2 (param $var0 (ref null $#Top)) (param $var1 (ref null $#Top)) (result (ref $JSExternWrapper)) <...>)
(func $checkLibraryIsLoadedFromLoadId (param $var0 i64) (result i32) <...>)
(func $print (param $var0 (ref null $#Top)) (result (ref null $#Top)) <...>)
(func $print (param $var0 (ref null $#Top)) <...>)
)
@@ -17,14 +17,13 @@
(global $_InterfaceType (ref $_InterfaceType) <...>)
(elem $module0.cross-module-funcs-0
(set 0 (ref.func $"useFoo <noInline>")))
(func $"useFoo <noInline>" (result (ref null $#Top))
(func $"useFoo <noInline>"
call $"useFooAsType <noInline>"
i64.const 0
i32.const 1
call_indirect (param i64) (result i32)
drop
call $"useFooAsObject <noInline>"
ref.null none
)
(func $"useFooAsObject <noInline>"
(local $var0 (ref $Foo))
@@ -40,8 +39,7 @@
(func $"useFooAsType <noInline>"
global.get $_InterfaceType
i32.const 3
call_indirect (param (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect (param (ref null $#Top))
)
(func $Foo.printFoo (param $var0 (ref $Foo)) <...>)
)
@@ -17,5 +17,5 @@
(func $SystemHash.combine (param $var0 i64) (param $var1 i64) (result i64) <...>)
(func $_TypeUniverse.substituteFunctionTypeArgument (param $var0 (ref $_FunctionType)) (param $var1 (ref $Array<_Type>)) (result (ref $_FunctionType)) <...>)
(func $checkLibraryIsLoadedFromLoadId (param $var0 i64) (result i32) <...>)
(func $print (param $var0 (ref null $#Top)) (result (ref null $#Top)) <...>)
(func $print (param $var0 (ref null $#Top)) <...>)
)
@@ -123,10 +123,11 @@
i32.const 6
call_indirect $module0.cross-module-funcs-0 (param (ref $Array<Object?>)) (result (ref $JSExternWrapper))
i32.const 5
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top)) (result (ref null $#Top))
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top))
ref.null none
)
(func $instantiation constant trampoline (param $var0 (ref struct)) (param $var1 (ref null $#Top)) (result (ref null $#Top)) <...>)
(func $"modH1UseH1 <noInline>" (result (ref null $#Top))
(func $"modH1UseH1 <noInline>"
(local $var0 (ref $#Closure-0-1))
block $label0 (result (ref $H1))
global.get $H1
@@ -134,8 +135,7 @@
call $"H1 (lazy initializer)"
end $label0
i32.const 5
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top))
block $label1 (result (ref $H1))
global.get $H1
br_on_non_null $label1
@@ -152,9 +152,8 @@
struct.get $#Vtable-0-1 $closureCallEntry-0-1
call_ref $type0
drop
ref.null none
)
(func $"modMainUseH0 <noInline>" (result (ref null $#Top))
(func $"modMainUseH0 <noInline>"
i64.const 0
i32.const 7
call_indirect $module0.cross-module-funcs-0 (param i64) (result i32)
@@ -167,8 +166,7 @@
call_indirect $module0.cross-module-funcs-0 (result (ref $H0))
end $label0
i32.const 5
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top))
i64.const 0
i32.const 7
call_indirect $module0.cross-module-funcs-0 (param i64) (result i32)
@@ -183,8 +181,6 @@
drop
i64.const 1
i32.const 8
call_indirect $module0.cross-module-funcs-0 (param i64) (result (ref null $#Top))
drop
ref.null none
call_indirect $module0.cross-module-funcs-0 (param i64)
)
)
@@ -84,11 +84,12 @@
ref.cast $BoxedInt
struct.get $BoxedInt $value
call $globalH0Foo
ref.null none
)
(func $null (result (ref null $H0)) <...>)
(func $globalH0Foo (param $var0 i64) (result (ref null $#Top))
(func $globalH0Foo (param $var0 i64)
global.get $"\"globalH0Foo\""
i32.const 5
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top)) (result (ref null $#Top))
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top))
)
)
@@ -25,9 +25,9 @@
(set 15 (ref.func $JSStringImpl._interpolate))
(set 16 (ref.func $JSStringImpl.fromRefUnchecked))
(set 17 (ref.func $JSStringImpl._interpolate2)))
(func $Error._throwWithCurrentStackTrace <noInline> (param $var0 (ref $#Top)) (result (ref none)) <...>)
(func $_TypeError._throwNullCheckErrorWithCurrentStack <noInline> (result (ref none)) <...>)
(func $_throwIndexError <noInline> (param $var0 i64) (param $var1 i64) (param $var2 (ref null $JSExternWrapper)) (result (ref none)) <...>)
(func $Error._throwWithCurrentStackTrace <noInline> (param $var0 (ref $#Top)) <...>)
(func $_TypeError._throwNullCheckErrorWithCurrentStack <noInline> <...>)
(func $_throwIndexError <noInline> (param $var0 i64) (param $var1 i64) (param $var2 (ref null $JSExternWrapper)) <...>)
(func $IntegerDivisionByZeroException (result (ref $Object)) <...>)
(func $JSStringImpl.+ (param $var0 (ref $JSExternWrapper)) (param $var1 (ref $JSExternWrapper)) (result (ref $JSExternWrapper)) <...>)
(func $JSStringImpl._interpolate (param $var0 (ref $Array<Object?>)) (result (ref $JSExternWrapper)) <...>)
@@ -36,5 +36,5 @@
(func $JSStringImpl.fromRefUnchecked (param $var0 externref) (result (ref $JSExternWrapper)) <...>)
(func $JSStringImpl.substring (param $var0 (ref $JSExternWrapper)) (param $var1 i64) (param $var2 i64) (result (ref $JSExternWrapper)) <...>)
(func $checkLibraryIsLoadedFromLoadId (param $var0 i64) (result i32) <...>)
(func $print (param $var0 (ref null $#Top)) (result (ref null $#Top)) <...>)
(func $print (param $var0 (ref null $#Top)) <...>)
)
@@ -39,7 +39,7 @@
(set 1 (ref.func $"foo1 <noInline>"))
(set 2 (ref.func $"foo0 <noInline>")))
(elem $module0.dispatch0 <...>)
(func $"foo0 <noInline>" (result (ref null $#Top))
(func $"foo0 <noInline>"
call $"runtimeTrue implicit getter"
if (result (ref $Object))
i32.const 108
@@ -58,10 +58,8 @@
call_indirect $module0.cross-module-funcs-0 (param i64) (result i32)
drop
call $"foo1 <noInline>"
drop
ref.null none
)
(func $"foo1 <noInline>" (result (ref null $#Top))
(func $"foo1 <noInline>"
(local $var0 (ref $Object))
block $label0
block $label1 (result (ref $Object))
@@ -75,8 +73,7 @@
struct.get $Object $field0
i32.const 457
i32.add
call_indirect $module0.dispatch0 (param (ref $Object) (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect $module0.dispatch0 (param (ref $Object) (ref null $#Top))
block $label2 (result (ref $Object))
global.get $foo1Obj
br_on_non_null $label2
@@ -84,7 +81,6 @@
end $label2
global.get $2
call $Foo1.doitDispatch
drop
block $label3 (result (ref $Object))
global.get $foo1Obj
br_on_non_null $label3
@@ -99,26 +95,23 @@
end $label4
drop
call $Foo1.doitDevirt
ref.null none
return
end $label0
i32.const 4
call_indirect $module0.cross-module-funcs-0 (result (ref none))
call_indirect $module0.cross-module-funcs-0
unreachable
)
(func $runtimeTrue implicit getter (result i32) <...>)
(func $Foo0.doitDispatch (param $var0 (ref $Object)) (param $var1 (ref null $#Top)) (result (ref null $#Top))
(func $Foo0.doitDispatch (param $var0 (ref $Object)) (param $var1 (ref null $#Top))
global.get $"\"Foo0.doitDispatch(\""
local.get $var1
global.get $"\")\""
i32.const 5
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top) (ref null $#Top) (ref null $#Top)) (result (ref $JSExternWrapper))
i32.const 6
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top))
local.get $var1
call $FooBase.doitDispatch
ref.null none
)
(func $Foo1 (result (ref $Object)) <...>)
(func $Foo1.doitDevirt
@@ -128,29 +121,25 @@
i32.const 5
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top) (ref null $#Top) (ref null $#Top)) (result (ref $JSExternWrapper))
i32.const 6
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top))
global.get $"\"FooBase(\""
global.get $1
global.get $"\")\""
i32.const 5
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top) (ref null $#Top) (ref null $#Top)) (result (ref $JSExternWrapper))
i32.const 6
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top))
)
(func $Foo1.doitDispatch (param $var0 (ref $Object)) (param $var1 (ref null $#Top)) (result (ref null $#Top))
(func $Foo1.doitDispatch (param $var0 (ref $Object)) (param $var1 (ref null $#Top))
global.get $"\"Foo1.doitDispatch(\""
local.get $var1
global.get $"\")\""
i32.const 5
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top) (ref null $#Top) (ref null $#Top)) (result (ref $JSExternWrapper))
i32.const 6
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top))
local.get $var1
call $FooBase.doitDispatch
ref.null none
)
(func $FooBase.doitDispatch (param $var0 (ref null $#Top))
global.get $"\"FooBase(\""
@@ -159,7 +148,6 @@
i32.const 5
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top) (ref null $#Top) (ref null $#Top)) (result (ref $JSExternWrapper))
i32.const 6
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top))
)
)
@@ -52,21 +52,18 @@
(set 32 (ref.func $JSStringImpl._interpolate))
(set 33 (ref.func $JSStringImpl.fromRefUnchecked))
(set 34 (ref.func $JSStringImpl._interpolate2)))
(func $Error._throwWithCurrentStackTrace <noInline> (param $var0 (ref $#Top)) (result (ref none)) <...>)
(func $_throwIndexError <noInline> (param $var0 i64) (param $var1 i64) (param $var2 (ref null $JSExternWrapper)) (result (ref none)) <...>)
(func $"foo0Code <noInline>" (param $var0 (ref null $#Top)) (result (ref null $#Top))
(func $Error._throwWithCurrentStackTrace <noInline> (param $var0 (ref $#Top)) <...>)
(func $_throwIndexError <noInline> (param $var0 i64) (param $var1 i64) (param $var2 (ref null $JSExternWrapper)) <...>)
(func $"foo0Code <noInline>" (param $var0 (ref null $#Top))
global.get $FooConst0
call $print
drop
global.get $"\"foo0Code(\""
local.get $var0
global.get $"\")\""
call $JSStringImpl._interpolate3
call $print
drop
global.get $0
global.set $fooGlobal0
ref.null none
)
(func $GrowableList._withData (param $var0 (ref $_Type)) (param $var1 (ref $Array<Object?>)) (result (ref $WasmListBase)) <...>)
(func $IntegerDivisionByZeroException (result (ref $Object)) <...>)
@@ -76,14 +73,14 @@
(func $JSStringImpl._interpolate3 (param $var0 (ref null $#Top)) (param $var1 (ref null $#Top)) (param $var2 (ref null $#Top)) (result (ref $JSExternWrapper)) <...>)
(func $JSStringImpl.fromRefUnchecked (param $var0 externref) (result (ref $JSExternWrapper)) <...>)
(func $JSStringImpl.substring (param $var0 (ref $JSExternWrapper)) (param $var1 i64) (param $var2 i64) (result (ref $JSExternWrapper)) <...>)
(func $_AsyncSuspendState._complete (param $var0 (ref $_AsyncSuspendState)) (param $var1 (ref null $#Top)) (result (ref null $#Top)) <...>)
(func $_AsyncSuspendState._completeError (param $var0 (ref $_AsyncSuspendState)) (param $var1 (ref $#Top)) (param $var2 (ref $Object)) (result (ref null $#Top)) <...>)
(func $_awaitHelper (param $var0 (ref $_AsyncSuspendState)) (param $var1 (ref $_Future)) (result (ref null $#Top)) <...>)
(func $_AsyncSuspendState._complete (param $var0 (ref $_AsyncSuspendState)) (param $var1 (ref null $#Top)) <...>)
(func $_AsyncSuspendState._completeError (param $var0 (ref $_AsyncSuspendState)) (param $var1 (ref $#Top)) (param $var2 (ref $Object)) <...>)
(func $_awaitHelper (param $var0 (ref $_AsyncSuspendState)) (param $var1 (ref $_Future)) <...>)
(func $_makeFuture (param $var0 (ref $_Type)) (result (ref $_Future)) <...>)
(func $_newAsyncSuspendState (param $var0 (ref $type0)) (param $var1 structref) (param $var2 (ref $_Future)) (result (ref $_AsyncSuspendState)) <...>)
(func $boxJsException (param $var0 externref) (result (ref $#Top)) <...>)
(func $checkLibraryIsLoadedFromLoadId (param $var0 i64) (result i32) <...>)
(func $jsExceptionStackTrace (param $var0 externref) (result (ref $JavaScriptStack)) <...>)
(func $loadLibraryFromLoadId (param $var0 i64) (result (ref $_Future)) <...>)
(func $print (param $var0 (ref null $#Top)) (result (ref null $#Top)) <...>)
(func $print (param $var0 (ref null $#Top)) <...>)
)
@@ -18,22 +18,19 @@
(set 39 (ref.func $0))
(set 40 (ref.func $1))
(set 41 (ref.func $2)))
(func $"foo1Code <noInline>" (param $var0 (ref null $#Top)) (result (ref null $#Top))
(func $"foo1Code <noInline>" (param $var0 (ref null $#Top))
global.get $FooConst1
i32.const 18
call_indirect (param (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect (param (ref null $#Top))
global.get $"\"foo1Code(\""
local.get $var0
global.get $"\")\""
i32.const 19
call_indirect (param (ref null $#Top) (ref null $#Top) (ref null $#Top)) (result (ref $JSExternWrapper))
i32.const 18
call_indirect (param (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect (param (ref null $#Top))
global.get $1
global.set $fooGlobal1
ref.null none
)
(func $null (result (ref null $#Top)) <...>)
(func $null (param $var0 (ref null $#Top)) <...>)
@@ -82,16 +82,14 @@
(local $var3 i64)
global.get $FooConst5
i32.const 18
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top))
global.get $"\"foo5Code(\""
local.get $var0
global.get $"\")\""
i32.const 19
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top) (ref null $#Top) (ref null $#Top)) (result (ref $JSExternWrapper))
i32.const 18
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top))
global.get $5
global.set $fooGlobal5
block $label0 (result (ref $#Top))
@@ -109,8 +107,7 @@
local.get $var0
end $label0
i32.const 20
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top))
block $label1 (result (ref $#Top))
i32.const 39
call_indirect $module0.cross-module-funcs-0 (result (ref null $#Top))
@@ -128,8 +125,7 @@
local.get $var0
end $label1
i32.const 3
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top))
block $label2 (result (ref $#Top))
i32.const 37
call_indirect $module0.cross-module-funcs-0 (result (ref null $#Top))
@@ -147,8 +143,7 @@
local.get $var0
end $label2
i32.const 12
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top))
block $label3 (result (ref $#Top))
i32.const 35
call_indirect $module0.cross-module-funcs-0 (result (ref null $#Top))
@@ -166,8 +161,7 @@
local.get $var0
end $label3
i32.const 14
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top))
block $label4 (result (ref $#Top))
i32.const 23
call_indirect $module0.cross-module-funcs-0 (result (ref null $#Top))
@@ -185,8 +179,7 @@
local.get $var0
end $label4
i32.const 16
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top))
block $label5 (result (ref $WasmListBase))
global.get $allFooConstants
br_on_non_null $label5
@@ -217,8 +210,7 @@
local.get $var3
global.get $"\"[]\""
i32.const 21
call_indirect $module0.cross-module-funcs-0 (param i64 i64 (ref null $JSExternWrapper)) (result (ref none))
unreachable
call_indirect $module0.cross-module-funcs-0 (param i64 i64 (ref null $JSExternWrapper))
end
local.get $var1
struct.get $WasmListBase $_data
@@ -231,87 +223,74 @@
struct.get $Object $field0
i32.const 378
i32.add
call_indirect $module0.dispatch0 (param (ref $Object) (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect $module0.dispatch0 (param (ref $Object) (ref null $#Top))
)
(func $fooGlobal5 implicit getter (result (ref $#Top)) <...>)
(func $FooConst0.doit (param $var0 (ref $Object)) (param $var1 (ref null $#Top)) (result (ref null $#Top))
(func $FooConst0.doit (param $var0 (ref $Object)) (param $var1 (ref null $#Top))
global.get $"\"FooConst0(\""
local.get $var1
global.get $"\")\""
i32.const 19
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top) (ref null $#Top) (ref null $#Top)) (result (ref $JSExternWrapper))
i32.const 18
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top))
local.get $var1
call $FooConstBase.doit
ref.null none
)
(func $FooConst1.doit (param $var0 (ref $Object)) (param $var1 (ref null $#Top)) (result (ref null $#Top))
(func $FooConst1.doit (param $var0 (ref $Object)) (param $var1 (ref null $#Top))
global.get $"\"FooConst1(\""
local.get $var1
global.get $"\")\""
i32.const 19
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top) (ref null $#Top) (ref null $#Top)) (result (ref $JSExternWrapper))
i32.const 18
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top))
local.get $var1
call $FooConstBase.doit
ref.null none
)
(func $FooConst2.doit (param $var0 (ref $Object)) (param $var1 (ref null $#Top)) (result (ref null $#Top))
(func $FooConst2.doit (param $var0 (ref $Object)) (param $var1 (ref null $#Top))
global.get $"\"FooConst2(\""
local.get $var1
global.get $"\")\""
i32.const 19
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top) (ref null $#Top) (ref null $#Top)) (result (ref $JSExternWrapper))
i32.const 18
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top))
local.get $var1
call $FooConstBase.doit
ref.null none
)
(func $FooConst3.doit (param $var0 (ref $Object)) (param $var1 (ref null $#Top)) (result (ref null $#Top))
(func $FooConst3.doit (param $var0 (ref $Object)) (param $var1 (ref null $#Top))
global.get $"\"FooConst3(\""
local.get $var1
global.get $"\")\""
i32.const 19
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top) (ref null $#Top) (ref null $#Top)) (result (ref $JSExternWrapper))
i32.const 18
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top))
local.get $var1
call $FooConstBase.doit
ref.null none
)
(func $FooConst4.doit (param $var0 (ref $Object)) (param $var1 (ref null $#Top)) (result (ref null $#Top))
(func $FooConst4.doit (param $var0 (ref $Object)) (param $var1 (ref null $#Top))
global.get $"\"FooConst4(\""
local.get $var1
global.get $"\")\""
i32.const 19
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top) (ref null $#Top) (ref null $#Top)) (result (ref $JSExternWrapper))
i32.const 18
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top))
local.get $var1
call $FooConstBase.doit
ref.null none
)
(func $FooConst5.doit (param $var0 (ref $Object)) (param $var1 (ref null $#Top)) (result (ref null $#Top))
(func $FooConst5.doit (param $var0 (ref $Object)) (param $var1 (ref null $#Top))
global.get $"\"FooConst5(\""
local.get $var1
global.get $"\")\""
i32.const 19
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top) (ref null $#Top) (ref null $#Top)) (result (ref $JSExternWrapper))
i32.const 18
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top))
local.get $var1
call $FooConstBase.doit
ref.null none
)
(func $FooConstBase.doit (param $var0 (ref null $#Top))
global.get $"\"FooConstBase(\""
@@ -320,8 +299,7 @@
i32.const 19
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top) (ref null $#Top) (ref null $#Top)) (result (ref $JSExternWrapper))
i32.const 18
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top))
)
(func $foo5 (result (ref $_Future)) <...>)
(func $int.parse (param $var0 (ref $JSExternWrapper)) (result i64) <...>)
@@ -18,22 +18,19 @@
(set 37 (ref.func $0))
(set 38 (ref.func $1))
(set 42 (ref.func $2)))
(func $"foo2Code <noInline>" (param $var0 (ref null $#Top)) (result (ref null $#Top))
(func $"foo2Code <noInline>" (param $var0 (ref null $#Top))
global.get $FooConst2
i32.const 18
call_indirect (param (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect (param (ref null $#Top))
global.get $"\"foo2Code(\""
local.get $var0
global.get $"\")\""
i32.const 19
call_indirect (param (ref null $#Top) (ref null $#Top) (ref null $#Top)) (result (ref $JSExternWrapper))
i32.const 18
call_indirect (param (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect (param (ref null $#Top))
global.get $2
global.set $fooGlobal2
ref.null none
)
(func $null (result (ref null $#Top)) <...>)
(func $null (param $var0 (ref null $#Top)) <...>)
@@ -18,22 +18,19 @@
(set 35 (ref.func $0))
(set 36 (ref.func $1))
(set 43 (ref.func $2)))
(func $"foo3Code <noInline>" (param $var0 (ref null $#Top)) (result (ref null $#Top))
(func $"foo3Code <noInline>" (param $var0 (ref null $#Top))
global.get $FooConst3
i32.const 18
call_indirect (param (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect (param (ref null $#Top))
global.get $"\"foo3Code(\""
local.get $var0
global.get $"\")\""
i32.const 19
call_indirect (param (ref null $#Top) (ref null $#Top) (ref null $#Top)) (result (ref $JSExternWrapper))
i32.const 18
call_indirect (param (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect (param (ref null $#Top))
global.get $3
global.set $fooGlobal3
ref.null none
)
(func $null (result (ref null $#Top)) <...>)
(func $null (param $var0 (ref null $#Top)) <...>)
@@ -18,22 +18,19 @@
(set 23 (ref.func $0))
(set 24 (ref.func $1))
(set 44 (ref.func $2)))
(func $"foo4Code <noInline>" (param $var0 (ref null $#Top)) (result (ref null $#Top))
(func $"foo4Code <noInline>" (param $var0 (ref null $#Top))
global.get $FooConst4
i32.const 18
call_indirect (param (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect (param (ref null $#Top))
global.get $"\"foo4Code(\""
local.get $var0
global.get $"\")\""
i32.const 19
call_indirect (param (ref null $#Top) (ref null $#Top) (ref null $#Top)) (result (ref $JSExternWrapper))
i32.const 18
call_indirect (param (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect (param (ref null $#Top))
global.get $4
global.set $fooGlobal4
ref.null none
)
(func $null (result (ref null $#Top)) <...>)
(func $null (param $var0 (ref null $#Top)) <...>)
@@ -36,10 +36,10 @@
(set 17 (ref.func $JSStringImpl._interpolate4))
(set 18 (ref.func $IntegerDivisionByZeroException))
(set 19 (ref.func $"_TypeError._throwNullCheckErrorWithCurrentStack <noInline>")))
(func $Error._throwWithCurrentStackTrace <noInline> (param $var0 (ref $#Top)) (result (ref none)) <...>)
(func $_TypeError._throwNullCheckErrorWithCurrentStack <noInline> (result (ref none)) <...>)
(func $_throwIndexError <noInline> (param $var0 i64) (param $var1 i64) (param $var2 (ref null $JSExternWrapper)) (result (ref none)) <...>)
(func $_throwRangeError <noInline> (param $var0 i64) (param $var1 i64) (param $var2 i64) (param $var3 (ref null $JSExternWrapper)) (param $var4 (ref null $JSExternWrapper)) (result (ref none)) <...>)
(func $Error._throwWithCurrentStackTrace <noInline> (param $var0 (ref $#Top)) <...>)
(func $_TypeError._throwNullCheckErrorWithCurrentStack <noInline> <...>)
(func $_throwIndexError <noInline> (param $var0 i64) (param $var1 i64) (param $var2 (ref null $JSExternWrapper)) <...>)
(func $_throwRangeError <noInline> (param $var0 i64) (param $var1 i64) (param $var2 i64) (param $var3 (ref null $JSExternWrapper)) (param $var4 (ref null $JSExternWrapper)) <...>)
(func $#init
global.get $"\"1.0\""
i32.const 16
@@ -20,7 +20,7 @@
array.new_default $Array<String?>
global.set $array
)
(func $Expect.equals (param $var0 (ref null $#Top)) (result (ref null $#Top)) <...>)
(func $Expect.equals (param $var0 (ref null $#Top)) <...>)
(func $read (result (ref $JSExternWrapper))
block $label0 (result (ref $JSExternWrapper))
global.get $array
@@ -28,11 +28,11 @@
array.get $Array<String?>
br_on_non_null $label0
i32.const 19
call_indirect $module0.cross-module-funcs-0 (result (ref none))
call_indirect $module0.cross-module-funcs-0
unreachable
end $label0
)
(func $write (result (ref null $#Top))
(func $write (result (ref $JSExternWrapper))
(local $var0 (ref $JSExternWrapper))
global.get $array
i32.const 0
@@ -8,6 +8,7 @@
(type $_InterfaceType <...>)
(type $_Type <...>)
(global $"\")\"_11" (import "$" "2") (ref $JSExternWrapper))
(global $"\"Attempt to execute code remove<...>\"" (import "$" "(") (ref $JSExternWrapper))
(global $_InterfaceType (import "$" "0") (ref $_InterfaceType))
(table $$.% (import "$" "%") 742 funcref)
(table $$.' (import "$" "'") 22 funcref)
@@ -27,8 +28,7 @@
i32.const 16
call_indirect $$.' (param (ref $Array<Object?>)) (result (ref $JSExternWrapper))
i32.const 20
call_indirect $$.' (param (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect $$.' (param (ref null $#Top))
global.get $_InterfaceType
local.set $var2
block $label0 (result i32)
@@ -62,13 +62,12 @@
i32.eqz
if
i32.const 2
call_indirect $$.' (result (ref none))
call_indirect $$.'
unreachable
end
local.get $var0
i32.const 20
call_indirect $$.' (param (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect $$.' (param (ref null $#Top))
)
(func $"Foo.takeT (checked entry)" (param $var0 (ref $Foo)) (param $var1 (ref $#Top))
(local $var2 i32)
@@ -167,7 +166,10 @@
i32.eqz
if
i32.const 2
call_indirect $$.' (result (ref none))
call_indirect $$.'
global.get $"\"Attempt to execute code remove<...>\""
i32.const 3
call_indirect $$.' (param (ref $#Top))
unreachable
end
local.get $var0
+4 -3
View File
@@ -109,7 +109,7 @@
(func $Foo (result (ref $Object)) <...>)
(func $Object._invokeNoSuchMethod (param $receiver (ref null $#Top)) (param $invocation (ref $_Invocation)) (result (ref null $#Top)) <...>)
(func $confuse (param $a (ref null $#Top)) (result (ref null $#Top)) <...>)
(func $main (result (ref null $#Top))
(func $main
(local $var0 (ref null $#Top))
(local $var1 (ref null $#Top))
call $Foo
@@ -119,6 +119,7 @@
local.get $var0
call $"Dynamic dispatcher for MethodCallShape(toString names:a)"
call $print
ref.null none
drop
call $Bar
call $confuse
@@ -127,8 +128,8 @@
local.get $var1
call $"Dynamic dispatcher for MethodCallShape(toString names:a)"
call $print
drop
ref.null none
drop
)
(func $print (param $object (ref null $#Top)) (result (ref null $#Top)) <...>)
(func $print (param $object (ref null $#Top)) <...>)
)
@@ -17,14 +17,12 @@
(struct.new $JSExternWrapper))
(elem $module0.cross-module-funcs-0
(set 0 (ref.func $"deferredFoo <noInline>")))
(func $"deferredFoo <noInline>" (result (ref null $#Top))
(func $"deferredFoo <noInline>"
call $"mainFoo <noInline>"
ref.null none
)
(func $"mainFoo <noInline>"
global.get $"\"hello world\""
i32.const 1
call_indirect (param (ref null $#Top)) (result (ref null $#Top))
drop
call_indirect (param (ref null $#Top))
)
)
@@ -26,7 +26,7 @@ import 'dart:_wasm';
@pragma("wasm:import", "dart.scheduleOnce")
external WasmExternRef scheduleOnce(
WasmI64 delay,
WasmFunction<void Function(WasmAnyRef)> callback,
WasmFunction<WasmVoid Function(WasmAnyRef)> callback,
WasmAnyRef arg,
);
@@ -37,21 +37,21 @@ external WasmExternRef scheduleOnce(
@pragma("wasm:import", "dart.scheduleRepeated")
external WasmExternRef scheduleRepeated(
WasmI64 interval,
WasmFunction<void Function(WasmAnyRef)> callback,
WasmFunction<WasmVoid Function(WasmAnyRef)> callback,
WasmAnyRef arg,
);
/// Instructs the runtime to invoke `callback(arg)` before returning to the
/// event loop.
@pragma("wasm:import", "dart.queueMicrotask")
external void queueMicrotask(
WasmFunction<void Function(WasmAnyRef)> callback,
external WasmVoid queueMicrotask(
WasmFunction<WasmVoid Function(WasmAnyRef)> callback,
WasmAnyRef arg,
);
/// Cancels a schedule created through [scheduleOnce] or [scheduleRepeated].
@pragma("wasm:import", "dart.clearSchedule")
external void clearSchedule(WasmExternRef? schedule);
external WasmVoid clearSchedule(WasmExternRef? schedule);
@pragma("wasm:import", "dart.currentTime")
external WasmI64 currentTimeMicros();
@@ -51,9 +51,10 @@ abstract class _Timer implements Timer {
}
}
static void runtimeCallback(WasmAnyRef timer) {
static WasmVoid runtimeCallback(WasmAnyRef timer) {
final dartTimer = timer.toObject() as _Timer;
dartTimer._processTick();
return WasmVoid();
}
}
@@ -117,8 +118,10 @@ class _AsyncRun {
);
}
static void _runtimeCallback(WasmAnyRef callbackFunction) {
static WasmVoid _runtimeCallback(WasmAnyRef callbackFunction) {
final function = callbackFunction.toObject() as void Function();
function();
return WasmVoid();
}
}
+22 -15
View File
@@ -9,15 +9,16 @@ import 'dart:_wasm';
import 'package:expect/expect.dart';
WasmTable<WasmFuncRef?> funcrefTable = WasmTable(3);
WasmTable<WasmFunction<int Function(int)>?> funcTable = WasmTable(1);
WasmTable<WasmFunction<WasmI32 Function(WasmI32)>?> funcTable = WasmTable(1);
void f1() {}
WasmVoid f1() => WasmVoid();
void f2(int x) {
Expect.equals(4, x);
WasmVoid f2(WasmI32 x) {
Expect.equals(4, x.toIntSigned());
return WasmVoid();
}
int f3(int x) => x + 1;
WasmI32 f3(WasmI32 x) => x + 1.toWasmI32();
main() {
// Initialize untyped function table
@@ -27,25 +28,29 @@ main() {
funcrefTable[2.toWasmI32()] = WasmFunction.fromFunction(f3);
// Reading and calling functions in untyped function table
WasmFunction<void Function()>.fromFuncRef(
WasmFunction<WasmVoid Function()>.fromFuncRef(
funcrefTable[0.toWasmI32()]!,
).call();
WasmFunction<void Function(int)>.fromFuncRef(
WasmFunction<WasmVoid Function(WasmI32)>.fromFuncRef(
funcrefTable[1.toWasmI32()]!,
).call(4);
).call(4.toWasmI32());
Expect.equals(
6,
WasmFunction<int Function(int)>.fromFuncRef(
WasmFunction<WasmI32 Function(WasmI32)>.fromFuncRef(
funcrefTable[2.toWasmI32()]!,
).call(5),
).call(5.toWasmI32()).toIntSigned(),
);
// Calling functions in untyped function table with callIndirect
funcrefTable.callIndirect<void Function()>(0.toWasmI32())();
funcrefTable.callIndirect<void Function(int)>(1.toWasmI32())(4);
funcrefTable.callIndirect<WasmVoid Function()>(0.toWasmI32())();
funcrefTable.callIndirect<WasmVoid Function(WasmI32)>(1.toWasmI32())(
4.toWasmI32(),
);
Expect.equals(
16,
funcrefTable.callIndirect<int Function(int)>(2.toWasmI32())(15),
funcrefTable
.callIndirect<WasmI32 Function(WasmI32)>(2.toWasmI32())(15.toWasmI32())
.toIntSigned(),
);
// Initialize typed function table
@@ -53,11 +58,13 @@ main() {
funcTable[0.toWasmI32()] = WasmFunction.fromFunction(f3);
// Reading and calling function in typed function table
Expect.equals(8, funcTable[0.toWasmI32()]!.call(7));
Expect.equals(8, funcTable[0.toWasmI32()]!.call(7.toWasmI32()).toIntSigned());
// Calling function in typed function table with callIndirect
Expect.equals(
18,
funcTable.callIndirect<int Function(int)>(0.toWasmI32())(17),
funcTable
.callIndirect<WasmI32 Function(WasmI32)>(0.toWasmI32())(17.toWasmI32())
.toIntSigned(),
);
}