Version 3.0.0-54.0.dev
Merge 2dffe31edd413b39f024cf3d5a1c4335fdb674a4 into dev
diff --git a/DEPS b/DEPS
index 0e6387f..3a64473 100644
--- a/DEPS
+++ b/DEPS
@@ -53,7 +53,7 @@
# hashes.
"co19_rev": "be8f8ae44d3f5222713ab1c51e7dbf2296db0719",
# This line prevents conflicts when both packages are rolled simultaneously.
- "co19_2_rev": "f691647f1c2cc4f1019fb619932c52d0a1adbf2c",
+ "co19_2_rev": "8ba5eb65399044d20370c8cfd115e1f6bc51acb1",
# The internal benchmarks to use. See go/dart-benchmarks-internal
"benchmarks_internal_rev": "599aa474a03c37be146f82dfbad85f34f25ffa47",
@@ -66,7 +66,7 @@
# Checkout extra javascript engines for testing or benchmarking.
# d8, the V8 shell, is always checked out.
"checkout_javascript_engines": False,
- "d8_tag": "version:10.9.192",
+ "d8_tag": "version:11.1.11",
"jsshell_tag": "version:95.0",
# As Flutter does, we use Fuchsia's GN and Clang toolchain. These revision
@@ -111,7 +111,7 @@
"csslib_rev": "34203c09f073ed8267f5d6e333daddb02e6ff609",
# Prefer to use hashes of binaryen that have been reviewed & rolled into g3.
- "binaryen_rev" : "7769139efbe818c7ba36d1a382db5114ebee9df8",
+ "binaryen_rev" : "12ad604c17407f6b36d52c6404f2dab32e5c7960",
# Note: Updates to dart_style have to be coordinated with the infrastructure
# team so that the internal formatter `tools/sdks/dart-sdk/bin/dart format`
diff --git a/pkg/dart2wasm/lib/code_generator.dart b/pkg/dart2wasm/lib/code_generator.dart
index bec4d6d..cc4854d 100644
--- a/pkg/dart2wasm/lib/code_generator.dart
+++ b/pkg/dart2wasm/lib/code_generator.dart
@@ -2660,8 +2660,7 @@
translator.convertType(
function, argLocal.type, info.struct.fields[fieldIndex].type.unpacked);
b.struct_set(info.struct, fieldIndex);
- translator.constants.instantiateConstant(
- function, b, NullConstant(), translator.topInfo.nullableType);
+ b.local_get(argLocal);
b.end();
}
diff --git a/pkg/dart2wasm/lib/functions.dart b/pkg/dart2wasm/lib/functions.dart
index 916394b..96ce691 100644
--- a/pkg/dart2wasm/lib/functions.dart
+++ b/pkg/dart2wasm/lib/functions.dart
@@ -82,6 +82,18 @@
String? exportName =
translator.getPragma(member, "wasm:export", member.name.text);
if (exportName != null) {
+ if (member is Procedure) {
+ // Although we don't need type unification for the types of exported
+ // functions, we still place these types in singleton recursion groups,
+ // since Binaryen's `--closed-world` optimization mode requires all
+ // publicly exposed types to be defined in separate recursion groups
+ // from GC types.
+ m.splitRecursionGroup();
+ _makeFunctionType(
+ translator, member.reference, member.function.returnType, null,
+ isImportOrExport: true);
+ m.splitRecursionGroup();
+ }
addExport(member.reference, exportName);
}
}
diff --git a/pkg/dart2wasm/lib/translator.dart b/pkg/dart2wasm/lib/translator.dart
index 9f9d9c1..74a7223 100644
--- a/pkg/dart2wasm/lib/translator.dart
+++ b/pkg/dart2wasm/lib/translator.dart
@@ -84,6 +84,7 @@
final Map<TypeParameter, int> typeParameterIndex = {};
final Map<Reference, ParameterInfo> staticParamInfo = {};
final Map<Field, w.DefinedTable> declaredTables = {};
+ final List<_ClosureTrampolineGenerator> pendingClosureTrampolines = [];
late Procedure mainFunction;
late final w.Module m;
late final w.DefinedFunction initFunction;
@@ -287,6 +288,12 @@
}
}
+ // Use an indexed loop to handle pending closure trampolines, since new
+ // entries might be added during iteration.
+ for (int i = 0; i < pendingClosureTrampolines.length; i++) {
+ pendingClosureTrampolines[i].generate(this);
+ }
+
dispatchTable.output();
initFunction.body.end();
@@ -595,54 +602,20 @@
w.DefinedFunction makeTrampoline(
w.FunctionType signature, int posArgCount, List<String> argNames) {
- w.DefinedFunction function = m.addFunction(signature, name);
- w.Instructions b = function.body;
- int targetIndex = 0;
- if (takesContextOrReceiver) {
- w.Local receiver = function.locals[0];
- b.local_get(receiver);
- convertType(function, receiver.type, target.type.inputs[targetIndex++]);
- }
- int argIndex = 1;
- for (int i = 0; i < typeCount; i++) {
- b.local_get(function.locals[argIndex++]);
- targetIndex++;
- }
- for (int i = 0; i < paramInfo.positional.length; i++) {
- if (i < posArgCount) {
- w.Local arg = function.locals[argIndex++];
- b.local_get(arg);
- convertType(function, arg.type, target.type.inputs[targetIndex++]);
- } else {
- constants.instantiateConstant(function, b, paramInfo.positional[i]!,
- target.type.inputs[targetIndex++]);
- }
- }
- int argNameIndex = 0;
- for (int i = 0; i < paramInfo.names.length; i++) {
- String argName = paramInfo.names[i];
- if (argNameIndex < argNames.length &&
- argNames[argNameIndex] == argName) {
- w.Local arg = function.locals[argIndex++];
- b.local_get(arg);
- convertType(function, arg.type, target.type.inputs[targetIndex++]);
- argNameIndex++;
- } else {
- constants.instantiateConstant(function, b, paramInfo.named[argName]!,
- target.type.inputs[targetIndex++]);
- }
- }
- assert(argIndex == signature.inputs.length);
- assert(targetIndex == target.type.inputs.length);
- assert(argNameIndex == argNames.length);
+ w.DefinedFunction trampoline = m.addFunction(signature, name);
- b.call(target);
+ // Defer generation of the trampoline body to avoid cyclic dependency when
+ // a tear-off constant is used as default value in the torn-off function.
+ pendingClosureTrampolines.add(_ClosureTrampolineGenerator(
+ trampoline,
+ target,
+ typeCount,
+ posArgCount,
+ argNames,
+ paramInfo,
+ takesContextOrReceiver));
- convertType(function, outputOrVoid(target.type.outputs),
- outputOrVoid(signature.outputs));
- b.end();
-
- return function;
+ return trampoline;
}
void fillVtableEntry(
@@ -890,6 +863,77 @@
}
}
+class _ClosureTrampolineGenerator {
+ final w.DefinedFunction trampoline;
+ final w.BaseFunction target;
+ final int typeCount;
+ final int posArgCount;
+ final List<String> argNames;
+ final ParameterInfo paramInfo;
+ final bool takesContextOrReceiver;
+
+ _ClosureTrampolineGenerator(
+ this.trampoline,
+ this.target,
+ this.typeCount,
+ this.posArgCount,
+ this.argNames,
+ this.paramInfo,
+ this.takesContextOrReceiver);
+
+ void generate(Translator translator) {
+ w.Instructions b = trampoline.body;
+ int targetIndex = 0;
+ if (takesContextOrReceiver) {
+ w.Local receiver = trampoline.locals[0];
+ b.local_get(receiver);
+ translator.convertType(
+ trampoline, receiver.type, target.type.inputs[targetIndex++]);
+ }
+ int argIndex = 1;
+ for (int i = 0; i < typeCount; i++) {
+ b.local_get(trampoline.locals[argIndex++]);
+ targetIndex++;
+ }
+ for (int i = 0; i < paramInfo.positional.length; i++) {
+ if (i < posArgCount) {
+ w.Local arg = trampoline.locals[argIndex++];
+ b.local_get(arg);
+ translator.convertType(
+ trampoline, arg.type, target.type.inputs[targetIndex++]);
+ } else {
+ translator.constants.instantiateConstant(trampoline, b,
+ paramInfo.positional[i]!, target.type.inputs[targetIndex++]);
+ }
+ }
+ int argNameIndex = 0;
+ for (int i = 0; i < paramInfo.names.length; i++) {
+ String argName = paramInfo.names[i];
+ if (argNameIndex < argNames.length && argNames[argNameIndex] == argName) {
+ w.Local arg = trampoline.locals[argIndex++];
+ b.local_get(arg);
+ translator.convertType(
+ trampoline, arg.type, target.type.inputs[targetIndex++]);
+ argNameIndex++;
+ } else {
+ translator.constants.instantiateConstant(trampoline, b,
+ paramInfo.named[argName]!, target.type.inputs[targetIndex++]);
+ }
+ }
+ assert(argIndex == trampoline.type.inputs.length);
+ assert(targetIndex == target.type.inputs.length);
+ assert(argNameIndex == argNames.length);
+
+ b.call(target);
+
+ translator.convertType(
+ trampoline,
+ translator.outputOrVoid(target.type.outputs),
+ translator.outputOrVoid(trampoline.type.outputs));
+ b.end();
+ }
+}
+
class NodeCounter extends Visitor<void> with VisitorVoidMixin {
int count = 0;
diff --git a/sdk/lib/_internal/wasm/lib/bool.dart b/sdk/lib/_internal/wasm/lib/bool.dart
index 2aeab66..a949961 100644
--- a/sdk/lib/_internal/wasm/lib/bool.dart
+++ b/sdk/lib/_internal/wasm/lib/bool.dart
@@ -4,6 +4,18 @@
part of "core_patch.dart";
+@patch
+class bool {
+ // Note: this needs to be in `bool`, cannot be overridden in `_BoxedBool`. I
+ // suspect the problem is there's an assumption in the front-end that `bool`
+ // has one implementation class (unlike `double`, `int`, `String`) which is
+ // the `bool` class itself. So when `runtimeType` is not overridden in
+ // `bool`, in code like `x.runtimeType` where `x` is `bool`, direct call
+ // metadata says that the member is `Object.runtimeType`.
+ @override
+ Type get runtimeType => bool;
+}
+
@pragma("wasm:entry-point")
class _BoxedBool extends bool {
// A boxed bool contains an unboxed bool.
diff --git a/tools/VERSION b/tools/VERSION
index ee0fc81..a077dcd 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 3
MINOR 0
PATCH 0
-PRERELEASE 53
+PRERELEASE 54
PRERELEASE_PATCH 0