[dart2wasm] Copy VM's map and set factory transformers
Transform factory calls to default map and set classes to the
constructor calls to the classes to improve kernel.
Also remove some redundant null checks in VM's transformer.
`source_map_simple_optimized_test.dart` is updated: with improved kernel
wasm-opt now eliminates the `testMain` function, so the stack trace
doesn't mention it.
Fixes https://github.com/dart-lang/sdk/issues/60343.
Tested: minor refactoring in VM doesn't need testing. Wasm tested with
existing tests.
Change-Id: Ie448d1374ff0e1b278859f22bc250899e0e4cfd0
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/416640
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Ömer Ağacan <omersa@google.com>
diff --git a/pkg/dart2wasm/lib/factory_specializer.dart b/pkg/dart2wasm/lib/factory_specializer.dart
new file mode 100644
index 0000000..b77a4e1
--- /dev/null
+++ b/pkg/dart2wasm/lib/factory_specializer.dart
@@ -0,0 +1,41 @@
+// 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 'package:kernel/core_types.dart';
+import 'package:kernel/kernel.dart';
+
+import 'list_factory_specializer.dart';
+import 'map_factory_specializer.dart';
+import 'set_factory_specializer.dart';
+
+typedef SpecializerTransformer = TreeNode Function(StaticInvocation node);
+
+abstract class BaseSpecializer {
+ // Populated in constructors of subclasses.
+ final Map<Member, SpecializerTransformer> transformers = {};
+}
+
+class FactorySpecializer extends BaseSpecializer {
+ final ListFactorySpecializer _listFactorySpecializer;
+ final SetFactorySpecializer _setFactorySpecializer;
+ final MapFactorySpecializer _mapFactorySpecializer;
+
+ FactorySpecializer(CoreTypes coreTypes)
+ : _listFactorySpecializer = ListFactorySpecializer(coreTypes),
+ _setFactorySpecializer = SetFactorySpecializer(coreTypes),
+ _mapFactorySpecializer = MapFactorySpecializer(coreTypes) {
+ transformers.addAll(_listFactorySpecializer.transformers);
+ transformers.addAll(_setFactorySpecializer.transformers);
+ transformers.addAll(_mapFactorySpecializer.transformers);
+ }
+
+ TreeNode transformStaticInvocation(StaticInvocation invocation) {
+ final target = invocation.target;
+ final transformer = transformers[target];
+ if (transformer != null) {
+ return transformer(invocation);
+ }
+ return invocation;
+ }
+}
diff --git a/pkg/dart2wasm/lib/list_factory_specializer.dart b/pkg/dart2wasm/lib/list_factory_specializer.dart
index b64b096..45c181b 100644
--- a/pkg/dart2wasm/lib/list_factory_specializer.dart
+++ b/pkg/dart2wasm/lib/list_factory_specializer.dart
@@ -21,7 +21,7 @@
/// ```
class ListFactorySpecializer {
final Map<Member, StaticInvocation Function(StaticInvocation node)>
- _transformers = {};
+ transformers = {};
final Procedure _fixedListEmptyFactory;
final Procedure _fixedListFactory;
@@ -58,14 +58,14 @@
.getProcedure('dart:_list', 'ModifiableFixedLengthList', 'filled'),
_fixedListGenerateFactory = coreTypes.index.getProcedure(
'dart:_list', 'ModifiableFixedLengthList', 'generate') {
- _transformers[_listFilledFactory] = _transformListFilledFactory;
- _transformers[_listEmptyFactory] = _transformListEmptyFactory;
- _transformers[_listGenerateFactory] = _transformListGenerateFactory;
+ transformers[_listFilledFactory] = _transformListFilledFactory;
+ transformers[_listEmptyFactory] = _transformListEmptyFactory;
+ transformers[_listGenerateFactory] = _transformListGenerateFactory;
}
StaticInvocation transformStaticInvocation(StaticInvocation invocation) {
final target = invocation.target;
- final transformer = _transformers[target];
+ final transformer = transformers[target];
if (transformer != null) {
return transformer(invocation);
}
diff --git a/pkg/dart2wasm/lib/map_factory_specializer.dart b/pkg/dart2wasm/lib/map_factory_specializer.dart
new file mode 100644
index 0000000..565d032
--- /dev/null
+++ b/pkg/dart2wasm/lib/map_factory_specializer.dart
@@ -0,0 +1,37 @@
+// 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 'package:kernel/ast.dart';
+import 'package:kernel/core_types.dart';
+
+import 'factory_specializer.dart';
+
+/// Replaces invocation of Map factory constructors with factories of
+/// Wasm-specific classes.
+///
+/// new LinkedHashMap<K, V>() => new DefaultMap<K, V>()
+class MapFactorySpecializer extends BaseSpecializer {
+ final Procedure _linkedHashMapDefaultFactory;
+ final Constructor _internalLinkedHashMapConstructor;
+
+ MapFactorySpecializer(CoreTypes coreTypes)
+ : _linkedHashMapDefaultFactory = coreTypes.index
+ .getProcedure('dart:collection', 'LinkedHashMap', ''),
+ _internalLinkedHashMapConstructor = coreTypes.index
+ .getConstructor('dart:_compact_hash', 'DefaultMap', '') {
+ transformers.addAll({_linkedHashMapDefaultFactory: transformLinkedHashMap});
+ }
+
+ TreeNode transformLinkedHashMap(StaticInvocation node) {
+ final args = node.arguments;
+ if (args.named.isEmpty) {
+ return ConstructorInvocation(
+ _internalLinkedHashMapConstructor,
+ Arguments([], types: args.types),
+ )..fileOffset = node.fileOffset;
+ }
+
+ return node;
+ }
+}
diff --git a/pkg/dart2wasm/lib/set_factory_specializer.dart b/pkg/dart2wasm/lib/set_factory_specializer.dart
new file mode 100644
index 0000000..caba262
--- /dev/null
+++ b/pkg/dart2wasm/lib/set_factory_specializer.dart
@@ -0,0 +1,38 @@
+// 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 'package:kernel/ast.dart';
+import 'package:kernel/core_types.dart' show CoreTypes;
+import 'package:kernel/core_types.dart';
+
+import 'factory_specializer.dart';
+
+/// Replaces invocation of Set factory constructors with factories of
+/// Wasm-specific classes.
+///
+/// new LinkedHashSet<E>() => new DefaultSet<E>()
+class SetFactorySpecializer extends BaseSpecializer {
+ final Procedure _linkedHashSetDefaultFactory;
+ final Constructor _internalLinkedHashSetConstructor;
+
+ SetFactorySpecializer(CoreTypes coreTypes)
+ : _linkedHashSetDefaultFactory = coreTypes.index
+ .getProcedure('dart:collection', 'LinkedHashSet', ''),
+ _internalLinkedHashSetConstructor = coreTypes.index
+ .getConstructor('dart:_compact_hash', 'DefaultSet', '') {
+ transformers.addAll({_linkedHashSetDefaultFactory: transformLinkedHashSet});
+ }
+
+ TreeNode transformLinkedHashSet(StaticInvocation node) {
+ final args = node.arguments;
+ assert(args.positional.isEmpty);
+ if (args.named.isEmpty) {
+ return ConstructorInvocation(
+ _internalLinkedHashSetConstructor,
+ Arguments([], types: args.types),
+ );
+ }
+ return node;
+ }
+}
diff --git a/pkg/dart2wasm/lib/transformers.dart b/pkg/dart2wasm/lib/transformers.dart
index b2a01c7..60c3285 100644
--- a/pkg/dart2wasm/lib/transformers.dart
+++ b/pkg/dart2wasm/lib/transformers.dart
@@ -9,7 +9,7 @@
import 'package:kernel/type_algebra.dart';
import 'package:kernel/type_environment.dart';
-import 'list_factory_specializer.dart';
+import 'factory_specializer.dart';
import 'util.dart';
void transformLibraries(
@@ -63,7 +63,7 @@
final List<_AsyncStarFrame> _asyncStarFrames = [];
bool _enclosingIsAsyncStar = false;
- final ListFactorySpecializer _listFactorySpecializer;
+ final FactorySpecializer _factorySpecializer;
final PushPopWasmArrayTransformer _pushPopWasmArrayTransformer;
@@ -119,7 +119,7 @@
.getTopLevelProcedure("dart:_internal", "loadLibrary"),
_checkLibraryIsLoaded = coreTypes.index
.getTopLevelProcedure("dart:_internal", "checkLibraryIsLoaded"),
- _listFactorySpecializer = ListFactorySpecializer(coreTypes),
+ _factorySpecializer = FactorySpecializer(coreTypes),
_pushPopWasmArrayTransformer = PushPopWasmArrayTransformer(coreTypes);
@override
@@ -738,8 +738,14 @@
node.target = _trySetStackTrace;
}
- return _pushPopWasmArrayTransformer.transformStaticInvocation(
- _listFactorySpecializer.transformStaticInvocation(node));
+ TreeNode transformed =
+ _pushPopWasmArrayTransformer.transformStaticInvocation(node);
+
+ if (transformed is StaticInvocation) {
+ transformed = _factorySpecializer.transformStaticInvocation(transformed);
+ }
+
+ return transformed;
}
@override
diff --git a/pkg/vm/lib/modular/specializer/map_factory_specializer.dart b/pkg/vm/lib/modular/specializer/map_factory_specializer.dart
index 3cb5b49..73ba9a7 100644
--- a/pkg/vm/lib/modular/specializer/map_factory_specializer.dart
+++ b/pkg/vm/lib/modular/specializer/map_factory_specializer.dart
@@ -16,20 +16,20 @@
final Constructor _internalLinkedHashMapConstructor;
MapFactorySpecializer(CoreTypes coreTypes)
- : _linkedHashMapDefaultFactory = assertNotNull(
- coreTypes.index.getProcedure('dart:collection', 'LinkedHashMap', ''),
+ : _linkedHashMapDefaultFactory = coreTypes.index.getProcedure(
+ 'dart:collection',
+ 'LinkedHashMap',
+ '',
),
- _internalLinkedHashMapConstructor = assertNotNull(
- coreTypes.index.getConstructor('dart:_compact_hash', '_Map', ''),
+
+ _internalLinkedHashMapConstructor = coreTypes.index.getConstructor(
+ 'dart:_compact_hash',
+ '_Map',
+ '',
) {
transformers.addAll({_linkedHashMapDefaultFactory: transformLinkedHashMap});
}
- static T assertNotNull<T>(T t) {
- assert(t != null);
- return t;
- }
-
TreeNode transformLinkedHashMap(StaticInvocation node) {
final args = node.arguments;
if (args.named.isEmpty) {
diff --git a/pkg/vm/lib/modular/specializer/set_factory_specializer.dart b/pkg/vm/lib/modular/specializer/set_factory_specializer.dart
index c9882f8..82d4a2d 100644
--- a/pkg/vm/lib/modular/specializer/set_factory_specializer.dart
+++ b/pkg/vm/lib/modular/specializer/set_factory_specializer.dart
@@ -17,20 +17,20 @@
final Constructor _internalLinkedHashSetConstructor;
SetFactorySpecializer(CoreTypes coreTypes)
- : _linkedHashSetDefaultFactory = assertNotNull(
- coreTypes.index.getProcedure('dart:collection', 'LinkedHashSet', ''),
+ : _linkedHashSetDefaultFactory = coreTypes.index.getProcedure(
+ 'dart:collection',
+ 'LinkedHashSet',
+ '',
),
- _internalLinkedHashSetConstructor = assertNotNull(
- coreTypes.index.getConstructor('dart:_compact_hash', '_Set', ''),
+
+ _internalLinkedHashSetConstructor = coreTypes.index.getConstructor(
+ 'dart:_compact_hash',
+ '_Set',
+ '',
) {
transformers.addAll({_linkedHashSetDefaultFactory: transformLinkedHashSet});
}
- static T assertNotNull<T>(T t) {
- assert(t != null);
- return t;
- }
-
TreeNode transformLinkedHashSet(StaticInvocation node) {
final args = node.arguments;
assert(args.positional.isEmpty);
diff --git a/tests/web/wasm/source_map_simple_optimized_test.dart b/tests/web/wasm/source_map_simple_optimized_test.dart
index bda94e3..f854a2a 100644
--- a/tests/web/wasm/source_map_simple_optimized_test.dart
+++ b/tests/web/wasm/source_map_simple_optimized_test.dart
@@ -14,7 +14,6 @@
('errors_patch.dart', null, null, '_throwWithCurrentStackTrace'),
('source_map_simple_lib.dart', 16, 3, 'g'),
('source_map_simple_lib.dart', 12, 3, 'f'),
- ('source_map_simple_lib.dart', 39, 5, 'testMain'),
];
/*