[dart2wasm] Fix incorrect setup of checked entrypoints

A method may be overriden multiple times, the overriden methods may add
optional parameters. Dart2wasm generates a signature for such selectors
that includes all optional parameters from all overriden methods.

That means
* callers may pass more arguments than the signature of the target
  => it passes dummy values
* implementations get more parameters passed than their Dart function
  => it ignores them

The checked/unchecked entry functions need to also support this
mechanism.

Issue https://github.com/dart-lang/sdk/issues/60148

Change-Id: Ifb60c44d3c5e5b6e374a15731723e16d22bfc094
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/414720
Reviewed-by: Ömer Ağacan <omersa@google.com>
Commit-Queue: Martin Kustermann <kustermann@google.com>
This commit is contained in:
Martin Kustermann
2025-03-11 03:57:09 -07:00
committed by Commit Queue
parent 8d46b7cd81
commit f4b4e5e297
2 changed files with 37 additions and 2 deletions
+10 -2
View File
@@ -379,10 +379,18 @@ abstract class AstCodeGenerator
canSafelyOmitImplicitChecks: !translator.needToCheckTypesFor(member));
}
void setupParametersForCheckedEntry(Member member) {
assert(member.isInstanceMember);
assert(translator.needToCheckTypesFor(member));
setupParameters(member.checkedEntryReference,
canSafelyOmitImplicitChecks: false);
}
void setupParametersForUncheckedEntry(Member member) {
assert(member.isInstanceMember);
assert(translator.needToCheckTypesFor(member));
setupParameters(member.reference, canSafelyOmitImplicitChecks: true);
setupParameters(member.uncheckedEntryReference,
canSafelyOmitImplicitChecks: true);
}
void setupContexts(Member member) {
@@ -3299,7 +3307,7 @@ class SynchronousProcedureCodeGenerator extends AstCodeGenerator {
final function = member.function;
final signature = translator.signatureForDirectCall(member.bodyReference);
if (checked) {
setupParametersForNormalEntry(member);
setupParametersForCheckedEntry(member);
} else {
setupParametersForUncheckedEntry(member);
}
@@ -0,0 +1,27 @@
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'package:expect/expect.dart';
main() async {
final l = <A<int>>[B<int>(), C<int>()];
Expect.equals('B.foo(1, first=1)', l[0].foo(1));
Expect.equals('C.foo(2, second=true)', l[1].foo(2));
Expect.equals('B.foo(3, first=2)', B<int>().foo(3, first: 2));
Expect.equals('C.foo(4, second=false)', C<int>().foo(4, second: false));
}
abstract class A<T> {
String foo(T a);
}
class B<T> extends A<T> {
String foo(T a, {int first = 1}) => 'B.foo($a, first=$first)';
}
class C<T> extends A<T> {
String foo(T a, {bool second = true}) => 'C.foo($a, second=$second)';
}