Skip to content

Commit f725026

Browse files
mkustermannCommit Queue
authored andcommitted
[dart2wasm] Make dynamic call forwarders use normal CallTarget infrastructure
So far running the compiler with `--print-wasm` wouldn't print the code for dynamic call forwarders as it doesn't use the same compiler infrastructure as normal function compilations. This CL makes the dynamic call forwarders be `CallTarget`s that can be called and if so will enqueue a `CompilationTask` in the compilation queue. This will ensure we treat those forwarders as any other target we may call, which will also make e.g. `--print-wasm` work. Change-Id: Ieb5673befa1456e941276d538e2212ff8d4077fc Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/428700 Reviewed-by: Ömer Ağacan <[email protected]> Commit-Queue: Martin Kustermann <[email protected]>
1 parent 70a56b3 commit f725026

File tree

2 files changed

+57
-32
lines changed

2 files changed

+57
-32
lines changed

pkg/dart2wasm/lib/code_generator.dart

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1754,9 +1754,10 @@ abstract class AstCodeGenerator
17541754
final typeArguments = node.arguments.types;
17551755
final positionalArguments = node.arguments.positional;
17561756
final namedArguments = node.arguments.named;
1757+
final memberName = node.name.text;
17571758
final forwarder = translator
17581759
.getDynamicForwardersForModule(b.module)
1759-
.getDynamicInvocationForwarder(node.name.text);
1760+
.getDynamicInvocationForwarder(memberName);
17601761

17611762
// Evaluate receiver
17621763
translateExpression(receiver, translator.topInfo.nullableType);
@@ -1816,7 +1817,7 @@ abstract class AstCodeGenerator
18161817
// invocation of `noSuchMethod` (done in [_callNoSuchMethod]), but we don't
18171818
// have a `Null` class in dart2wasm so we throw directly.
18181819
b.local_get(nullableReceiverLocal);
1819-
createInvocationObject(translator, b, forwarder.memberName, typeArgsLocal,
1820+
createInvocationObject(translator, b, memberName, typeArgsLocal,
18201821
positionalArgsLocal, namedArgsLocal);
18211822

18221823
call(translator.noSuchMethodErrorThrowWithInvocation.reference);
@@ -2173,9 +2174,10 @@ abstract class AstCodeGenerator
21732174
@override
21742175
w.ValueType visitDynamicGet(DynamicGet node, w.ValueType expectedType) {
21752176
final receiver = node.receiver;
2177+
final memberName = node.name.text;
21762178
final forwarder = translator
21772179
.getDynamicForwardersForModule(b.module)
2178-
.getDynamicGetForwarder(node.name.text);
2180+
.getDynamicGetForwarder(memberName);
21792181

21802182
// Evaluate receiver
21812183
translateExpression(receiver, translator.topInfo.nullableType);
@@ -2189,7 +2191,7 @@ abstract class AstCodeGenerator
21892191
// invocation of `noSuchMethod` (done in [_callNoSuchMethod]), but we don't
21902192
// have a `Null` class in dart2wasm so we throw directly.
21912193
b.local_get(nullableReceiverLocal);
2192-
createGetterInvocationObject(translator, b, forwarder.memberName);
2194+
createGetterInvocationObject(translator, b, memberName);
21932195

21942196
call(translator.noSuchMethodErrorThrowWithInvocation.reference);
21952197
b.unreachable();
@@ -2205,9 +2207,10 @@ abstract class AstCodeGenerator
22052207
w.ValueType visitDynamicSet(DynamicSet node, w.ValueType expectedType) {
22062208
final receiver = node.receiver;
22072209
final value = node.value;
2210+
final memberName = node.name.text;
22082211
final forwarder = translator
22092212
.getDynamicForwardersForModule(b.module)
2210-
.getDynamicSetForwarder(node.name.text);
2213+
.getDynamicSetForwarder(memberName);
22112214

22122215
// Evaluate receiver
22132216
translateExpression(receiver, translator.topInfo.nullableType);
@@ -2226,8 +2229,7 @@ abstract class AstCodeGenerator
22262229
// invocation of `noSuchMethod` (done in [_callNoSuchMethod]), but we don't
22272230
// have a `Null` class in dart2wasm so we throw directly.
22282231
b.local_get(nullableReceiverLocal);
2229-
createSetterInvocationObject(
2230-
translator, b, forwarder.memberName, positionalArgLocal);
2232+
createSetterInvocationObject(translator, b, memberName, positionalArgLocal);
22312233

22322234
call(translator.noSuchMethodErrorThrowWithInvocation.reference);
22332235
b.unreachable();

pkg/dart2wasm/lib/dynamic_forwarders.dart

Lines changed: 48 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import 'package:kernel/ast.dart';
66
import 'package:wasm_builder/wasm_builder.dart' as w;
77

88
import 'class_info.dart';
9-
import 'code_generator.dart' show MacroAssembler;
9+
import 'code_generator.dart' show CallTarget, CodeGenerator, MacroAssembler;
1010
import 'dispatch_table.dart';
1111
import 'reference_extensions.dart';
1212
import 'translator.dart';
@@ -18,36 +18,61 @@ class DynamicForwarders {
1818
final Translator translator;
1919
final w.ModuleBuilder callingModule;
2020

21-
final Map<String, Forwarder> _getterForwarderOfName = {};
22-
final Map<String, Forwarder> _setterForwarderOfName = {};
23-
final Map<String, Forwarder> _methodForwarderOfName = {};
21+
final Map<String, CallTarget> _getterForwarderOfName = {};
22+
final Map<String, CallTarget> _setterForwarderOfName = {};
23+
final Map<String, CallTarget> _methodForwarderOfName = {};
2424

2525
DynamicForwarders(this.translator, this.callingModule);
2626

27-
Forwarder getDynamicGetForwarder(String memberName) =>
28-
_getterForwarderOfName[memberName] ??= Forwarder._(
29-
translator, _ForwarderKind.Getter, memberName, callingModule)
30-
.._generateCode(translator);
27+
CallTarget getDynamicGetForwarder(String memberName) =>
28+
_getterForwarderOfName[memberName] ??= _DynamicForwarderCallTarget(
29+
translator, _ForwarderKind.Getter, memberName, callingModule);
3130

32-
Forwarder getDynamicSetForwarder(String memberName) =>
33-
_setterForwarderOfName[memberName] ??= Forwarder._(
34-
translator, _ForwarderKind.Setter, memberName, callingModule)
35-
.._generateCode(translator);
31+
CallTarget getDynamicSetForwarder(String memberName) =>
32+
_setterForwarderOfName[memberName] ??= _DynamicForwarderCallTarget(
33+
translator, _ForwarderKind.Setter, memberName, callingModule);
3634

37-
Forwarder getDynamicInvocationForwarder(String memberName) {
35+
CallTarget getDynamicInvocationForwarder(String memberName) {
3836
// Add Wasm function to the map before generating the forwarder code, to
3937
// allow recursive calls in the "call" forwarder.
4038
var forwarder = _methodForwarderOfName[memberName];
4139
if (forwarder == null) {
42-
forwarder = Forwarder._(
40+
forwarder = _DynamicForwarderCallTarget(
4341
translator, _ForwarderKind.Method, memberName, callingModule);
4442
_methodForwarderOfName[memberName] = forwarder;
45-
forwarder._generateCode(translator);
4643
}
4744
return forwarder;
4845
}
4946
}
5047

48+
class _DynamicForwarderCallTarget extends CallTarget {
49+
final Translator translator;
50+
final _ForwarderKind _kind;
51+
final String memberName;
52+
final w.ModuleBuilder callingModule;
53+
54+
_DynamicForwarderCallTarget(
55+
this.translator, this._kind, this.memberName, this.callingModule)
56+
: assert(!translator.isDynamicSubmodule ||
57+
(memberName == 'call' && _kind == _ForwarderKind.Getter)),
58+
super(_kind.functionType(translator));
59+
60+
@override
61+
String get name => 'Dynamic $_kind forwarder for "$memberName"';
62+
63+
@override
64+
bool get supportsInlining => false;
65+
66+
@override
67+
late final w.BaseFunction function = (() {
68+
final function = callingModule.functions.define(signature, name);
69+
final forwarder =
70+
_DynamicForwarderCodeGenerator(translator, _kind, memberName, function);
71+
translator.compilationQueue.add(CompilationTask(function, forwarder));
72+
return function;
73+
})();
74+
}
75+
5176
/// A function that "forwards" a dynamic get, set, or invocation to the right
5277
/// type checking member.
5378
///
@@ -67,21 +92,19 @@ class DynamicForwarders {
6792
/// A forwarder calls `noSuchMethod` on the receiver when a matching member is
6893
/// not found, or the passed arguments do not match the expected parameters of
6994
/// the member.
70-
class Forwarder {
95+
class _DynamicForwarderCodeGenerator extends CodeGenerator {
96+
final Translator translator;
7197
final _ForwarderKind _kind;
72-
7398
final String memberName;
74-
7599
final w.FunctionBuilder function;
76100

77-
Forwarder._(Translator translator, this._kind, this.memberName,
78-
w.ModuleBuilder module)
79-
: function = module.functions.define(_kind.functionType(translator),
80-
"$_kind forwarder for '$memberName'"),
81-
assert(!translator.isDynamicSubmodule ||
82-
(memberName == 'call' && _kind == _ForwarderKind.Getter));
101+
_DynamicForwarderCodeGenerator(
102+
this.translator, this._kind, this.memberName, this.function);
83103

84-
void _generateCode(Translator translator) {
104+
@override
105+
void generate(w.InstructionsBuilder b, List<w.Local> paramLocals,
106+
w.Label? returnLabel) {
107+
assert(returnLabel == null); // no inlining support atm.
85108
switch (_kind) {
86109
case _ForwarderKind.Getter:
87110
_generateGetterCode(translator);

0 commit comments

Comments
 (0)