[dart2wasm] Fix signature selection for direct closure invocation.
Direct closure invocation on tearoffs was using the signature of the raw member reference rather than the checked entry function. These don't always have the same signature and therefore it was possible to generate an invalid code by putting the incorrect # of parameters on the stack. The added test fails prior to this fix when assertions are enabled. Also include some small changes that helped with debugging this. Change-Id: I8c50dca3999781213ea251c6ab97eb1eaf7d0c8b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/467500 Reviewed-by: Martin Kustermann <kustermann@google.com> Commit-Queue: Nate Biggs <natebiggs@google.com>
This commit is contained in:
@@ -127,7 +127,8 @@ class CompilerPhaseInputOutputManager {
|
||||
final wasmOptPath = options.wasmOptPath?.toFilePath() ?? 'wasm-opt';
|
||||
final result = await _runProcess(wasmOptPath, args);
|
||||
if (result.exitCode != 0) {
|
||||
throw Exception('wasm-opt failed with exit code ${result.exitCode}:'
|
||||
throw Exception(
|
||||
'wasm-opt failed on module $inputModuleName with exit code ${result.exitCode}:'
|
||||
'\n${result.stdout}\n${result.stderr}');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1695,10 +1695,13 @@ class Translator with KernelNodes {
|
||||
return null;
|
||||
}
|
||||
|
||||
final entryReference =
|
||||
getFunctionEntry(member.reference, uncheckedEntry: false);
|
||||
|
||||
return SingleClosureTarget._(
|
||||
member,
|
||||
paramInfoForDirectCall(member.reference),
|
||||
signatureForDirectCall(member.reference),
|
||||
paramInfoForDirectCall(entryReference),
|
||||
signatureForDirectCall(entryReference),
|
||||
null,
|
||||
);
|
||||
} else {
|
||||
|
||||
@@ -72,6 +72,7 @@ VM_ARGS=()
|
||||
DART2WASM_ARGS=("--require-js-string-builtin")
|
||||
DART_FILE=""
|
||||
OUTPUT_FILE=""
|
||||
PHASES=""
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--compile-benchmark=*)
|
||||
@@ -102,6 +103,11 @@ while [ $# -gt 0 ]; do
|
||||
shift
|
||||
;;
|
||||
|
||||
--phases=*)
|
||||
PHASES="${1#--phases=}"
|
||||
shift
|
||||
;;
|
||||
|
||||
--extra-compiler-option=--platform=*)
|
||||
PLATFORM_FILENAME="${1#--extra-compiler-option=--platform=}"
|
||||
shift
|
||||
@@ -156,6 +162,10 @@ if [ -z "$DART_FILE" -o -z "$OUTPUT_FILE" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$PHASES" ]; then
|
||||
PHASES="cfe,tfa,codegen"
|
||||
fi
|
||||
|
||||
|
||||
PLATFORM_ARG="--platform=$PLATFORM_FILENAME"
|
||||
DART2WASM_AOT_SNAPSHOT="$BIN_DIR/$SNAPSHOT_NAME.snapshot"
|
||||
@@ -192,9 +202,9 @@ COMPILER_GZIP_SIZE=0
|
||||
|
||||
function run_compiler() {
|
||||
if [ $RUN_SRC -eq 1 ]; then
|
||||
dart2wasm_command=("$DART" "${VM_ARGS[@]}" "$DART2WASM_SRC" "$LIBRARIES_JSON_ARG" "${DART2WASM_ARGS[@]}" "--phases=cfe,tfa,codegen" "$DART_FILE" "$OUTPUT_FILE")
|
||||
dart2wasm_command=("$DART" "${VM_ARGS[@]}" "$DART2WASM_SRC" "$LIBRARIES_JSON_ARG" "${DART2WASM_ARGS[@]}" "--phases=$PHASES" "$DART_FILE" "$OUTPUT_FILE")
|
||||
else
|
||||
dart2wasm_command=("$DART_AOT_RUNTIME" "${VM_ARGS[@]}" "$DART2WASM_AOT_SNAPSHOT" "$PLATFORM_ARG" "${DART2WASM_ARGS[@]}" "--phases=cfe,tfa,codegen" "$DART_FILE" "$OUTPUT_FILE")
|
||||
dart2wasm_command=("$DART_AOT_RUNTIME" "${VM_ARGS[@]}" "$DART2WASM_AOT_SNAPSHOT" "$PLATFORM_ARG" "${DART2WASM_ARGS[@]}" "--phases=$PHASES" "$DART_FILE" "$OUTPUT_FILE")
|
||||
fi
|
||||
|
||||
if [ -n "$COMPILE_BENCHMARK_BASE_NAME" ]; then
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
// 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.
|
||||
|
||||
class Arg {}
|
||||
|
||||
abstract class Base<T> {
|
||||
void foo(T a);
|
||||
}
|
||||
|
||||
class A extends Base<Arg> {
|
||||
@override
|
||||
void foo(Arg a, [String? b]) {
|
||||
print(a);
|
||||
print(b);
|
||||
}
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
@override
|
||||
void foo(Arg a, [String? b, int c = 0]) {
|
||||
print(a);
|
||||
print(b);
|
||||
print(c);
|
||||
}
|
||||
}
|
||||
|
||||
void check(void Function(Arg) closure) {
|
||||
closure(Arg());
|
||||
}
|
||||
|
||||
void main() {
|
||||
final closure = A().foo;
|
||||
check(closure);
|
||||
B().foo(Arg(), 'b', 3);
|
||||
}
|
||||
Reference in New Issue
Block a user