[vm,dyn_modules] Support implicit dynamic calls in bytecode
TEST=ci (co19/Language/Expressions/Function_Invocation/Function_Expression_Invocation/call_A04_t01)
Change-Id: I49faf7c6f8d8f9353683dd94e9aa9a7ac7d30921
Cq-Include-Trybots: luci.dart.try:vm-aot-dyn-linux-debug-x64-try,vm-aot-dyn-linux-product-x64-try,vm-dyn-linux-debug-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/443882
Reviewed-by: Tess Strickland <sstrickl@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
diff --git a/pkg/dart2bytecode/lib/bytecode_generator.dart b/pkg/dart2bytecode/lib/bytecode_generator.dart
index c8b356f..37a74c6 100644
--- a/pkg/dart2bytecode/lib/bytecode_generator.dart
+++ b/pkg/dart2bytecode/lib/bytecode_generator.dart
@@ -1039,6 +1039,10 @@
late Library? dartFfiLibrary = libraryIndex.tryGetLibrary('dart:ffi');
+ // Selector for implicit dynamic calls 'foo(...)' where
+ // variable 'foo' has type 'dynamic'.
+ late final implicitCallName = Name('implicit:call');
+
void _recordSourcePosition(int fileOffset) {
asm.currentSourcePosition = fileOffset;
maxSourcePosition = math.max(maxSourcePosition, fileOffset);
@@ -3128,12 +3132,13 @@
@override
void visitDynamicInvocation(DynamicInvocation node) {
- _genMethodInvocation(node, null);
+ final targetName = node.isImplicitCall ? implicitCallName : node.name;
+ _genMethodInvocation(node, null, targetName);
}
@override
void visitInstanceInvocation(InstanceInvocation node) {
- _genMethodInvocation(node, node.interfaceTarget);
+ _genMethodInvocation(node, node.interfaceTarget, node.name);
}
@override
@@ -3151,8 +3156,8 @@
asm.emitSpecializedBytecode(Opcode.kEqualsNull);
}
- void _genMethodInvocation(
- InstanceInvocationExpression node, Procedure? interfaceTarget) {
+ void _genMethodInvocation(InstanceInvocationExpression node,
+ Procedure? interfaceTarget, Name targetName) {
final Opcode? opcode = recognizedMethods.specializedBytecodeFor(node);
if (opcode != null) {
_genMethodInvocationUsingSpecializedBytecode(opcode, node);
@@ -3172,7 +3177,7 @@
final argDesc =
objectTable.getArgDescHandleByArguments(args, hasReceiver: true);
- _genInstanceCall(node, InvocationKind.method, interfaceTarget, node.name,
+ _genInstanceCall(node, InvocationKind.method, interfaceTarget, targetName,
node.receiver, totalArgCount, argDesc);
}
diff --git a/pkg/dart2bytecode/testcases/super_calls.dart.expect b/pkg/dart2bytecode/testcases/super_calls.dart.expect
index 509e7b9..2ace24c 100644
--- a/pkg/dart2bytecode/testcases/super_calls.dart.expect
+++ b/pkg/dart2bytecode/testcases/super_calls.dart.expect
@@ -184,7 +184,7 @@
[1] = DirectCall 'DART_SDK/pkg/dart2bytecode/testcases/super_calls.dart::Base1::get:bar', ArgDesc num-args 1, num-type-args 0, names []
[2] = Reserved
[3] = ObjectRef 'param'
- [4] = DynamicCall 'call', ArgDesc num-args 2, num-type-args 1, names []
+ [4] = DynamicCall 'implicit:call', ArgDesc num-args 2, num-type-args 1, names []
[5] = Reserved
}
@@ -404,7 +404,7 @@
[6] = DirectCall 'dart:core::Object::noSuchMethod', ArgDesc num-args 2, num-type-args 0, names []
[7] = Reserved
[8] = ObjectRef 'param'
- [9] = DynamicCall 'call', ArgDesc num-args 2, num-type-args 1, names []
+ [9] = DynamicCall 'implicit:call', ArgDesc num-args 2, num-type-args 1, names []
[10] = Reserved
}
diff --git a/pkg/dart2bytecode/testcases/try_blocks.dart.expect b/pkg/dart2bytecode/testcases/try_blocks.dart.expect
index c07bdbc..8396252 100644
--- a/pkg/dart2bytecode/testcases/try_blocks.dart.expect
+++ b/pkg/dart2bytecode/testcases/try_blocks.dart.expect
@@ -762,7 +762,7 @@
[6] = Type dynamic
[7] = ObjectRef 'try 2'
[8] = EndClosureFunctionScope
- [9] = DynamicCall 'call', ArgDesc num-args 1, num-type-args 0, names []
+ [9] = DynamicCall 'implicit:call', ArgDesc num-args 1, num-type-args 0, names []
[10] = Reserved
}
Closure DART_SDK/pkg/dart2bytecode/testcases/try_blocks.dart::testTryFinally3::'<anonymous closure>' () -> dart:core::int
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index 1bff4dd..013aba7 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -3194,7 +3194,8 @@
// o.foo(...) failed, invoke noSuchMethod is foo exists but has the wrong
// number of arguments, or try (o.foo).call(...)
- if ((target_name.ptr() == Symbols::call().ptr()) && receiver.IsClosure()) {
+ if ((demangled_target_name.ptr() == Symbols::call().ptr()) &&
+ receiver.IsClosure()) {
// Special case: closures are implemented with a call getter instead of a
// call method and with lazy dispatchers the field-invocation-dispatcher
// would perform the closure call.