Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit c5ea3e8

Browse files
alexmarkovcommit-bot@chromium.org
authored andcommitted
[vm/nnbd] Further specialize invocations of List.filled factory
If 'growable' argument of List.filled factory invocation is known at compile time we can replace it with more specialized constructors creating growable or fixed-size lists. This results in a more accurate inferred type and more efficient code which uses the created list. Fixes dart-lang/sdk#42551 Change-Id: I427e1bdb8a0f2a83410a9533050d19cbca2d27d6 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/153064 Reviewed-by: Vyacheslav Egorov <[email protected]> Commit-Queue: Alexander Markov <[email protected]>
1 parent d1c9b09 commit c5ea3e8

File tree

6 files changed

+62
-12
lines changed

6 files changed

+62
-12
lines changed

pkg/front_end/lib/src/fasta/source/source_loader.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1300,10 +1300,12 @@ class List<E> extends Iterable {
13001300
13011301
class _GrowableList<E> {
13021302
factory _GrowableList() => null;
1303+
factory _GrowableList.filled() => null;
13031304
}
13041305
13051306
class _List<E> {
13061307
factory _List() => null;
1308+
factory _List.filled() => null;
13071309
}
13081310
13091311
class MapEntry<K, V> {

pkg/vm/lib/transformations/list_factory_specializer.dart

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,17 @@ import 'package:kernel/core_types.dart' show CoreTypes;
1313
/// new List() => new _GrowableList(0)
1414
/// new List(n) => new _List(n)
1515
/// new List.filled(n, null, growable: true) => new _GrowableList(n)
16+
/// new List.filled(n, x, growable: true) => new _GrowableList.filled(n, x)
1617
/// new List.filled(n, null) => new _List(n)
18+
/// new List.filled(n, x) => new _List.filled(n, x)
1719
///
1820
class ListFactorySpecializer {
1921
final Procedure _defaultListFactory;
2022
final Procedure _listFilledFactory;
2123
final Procedure _growableListFactory;
24+
final Procedure _growableListFilledFactory;
2225
final Procedure _fixedListFactory;
26+
final Procedure _fixedListFilledFactory;
2327

2428
ListFactorySpecializer(CoreTypes coreTypes)
2529
: _defaultListFactory =
@@ -28,12 +32,17 @@ class ListFactorySpecializer {
2832
coreTypes.index.getMember('dart:core', 'List', 'filled'),
2933
_growableListFactory =
3034
coreTypes.index.getMember('dart:core', '_GrowableList', ''),
31-
_fixedListFactory =
32-
coreTypes.index.getMember('dart:core', '_List', '') {
35+
_growableListFilledFactory =
36+
coreTypes.index.getMember('dart:core', '_GrowableList', 'filled'),
37+
_fixedListFactory = coreTypes.index.getMember('dart:core', '_List', ''),
38+
_fixedListFilledFactory =
39+
coreTypes.index.getMember('dart:core', '_List', 'filled') {
3340
assert(_defaultListFactory.isFactory);
3441
assert(_listFilledFactory.isFactory);
3542
assert(_growableListFactory.isFactory);
43+
assert(_growableListFilledFactory.isFactory);
3644
assert(_fixedListFactory.isFactory);
45+
assert(_fixedListFilledFactory.isFactory);
3746
}
3847

3948
TreeNode transformStaticInvocation(StaticInvocation node) {
@@ -53,10 +62,8 @@ class ListFactorySpecializer {
5362
assert(args.positional.length == 2);
5463
final length = args.positional[0];
5564
final fill = args.positional[1];
56-
if (fill is! NullLiteral &&
57-
!(fill is ConstantExpression && fill.constant is NullConstant)) {
58-
return node;
59-
}
65+
final fillingWithNull = fill is NullLiteral ||
66+
(fill is ConstantExpression && fill.constant is NullConstant);
6067
bool growable;
6168
if (args.named.isEmpty) {
6269
growable = false;
@@ -78,13 +85,25 @@ class ListFactorySpecializer {
7885
}
7986
}
8087
if (growable) {
81-
return StaticInvocation(
82-
_growableListFactory, Arguments([length], types: args.types))
83-
..fileOffset = node.fileOffset;
88+
if (fillingWithNull) {
89+
return StaticInvocation(
90+
_growableListFactory, Arguments([length], types: args.types))
91+
..fileOffset = node.fileOffset;
92+
} else {
93+
return StaticInvocation(_growableListFilledFactory,
94+
Arguments([length, fill], types: args.types))
95+
..fileOffset = node.fileOffset;
96+
}
8497
} else {
85-
return StaticInvocation(
86-
_fixedListFactory, Arguments([length], types: args.types))
87-
..fileOffset = node.fileOffset;
98+
if (fillingWithNull) {
99+
return StaticInvocation(
100+
_fixedListFactory, Arguments([length], types: args.types))
101+
..fileOffset = node.fileOffset;
102+
} else {
103+
return StaticInvocation(_fixedListFilledFactory,
104+
Arguments([length, fill], types: args.types))
105+
..fileOffset = node.fileOffset;
106+
}
88107
}
89108
}
90109

runtime/vm/compiler/recognized_methods_list.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,8 +444,11 @@ namespace dart {
444444
// result-cid, fingerprint).
445445
#define RECOGNIZED_LIST_FACTORY_LIST(V) \
446446
V(_ListFactory, _List, ., kArrayCid, 0x03ddbd3a) \
447+
V(_ListFilledFactory, _List, .filled, kArrayCid, 0x0) \
447448
V(_GrowableListWithData, _GrowableList, ._withData, kGrowableObjectArrayCid, \
448449
0x5cfd6a7f) \
450+
V(_GrowableListFilledFactory, _GrowableList, .filled, \
451+
kGrowableObjectArrayCid, 0x0) \
449452
V(_GrowableListFactory, _GrowableList, ., kGrowableObjectArrayCid, \
450453
0x3eed680b) \
451454
V(_Int8ArrayFactory, Int8List, ., kTypedDataInt8ArrayCid, 0x6ce2f102) \

runtime/vm/symbols.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,7 @@ class ObjectPointerVisitor;
361361
V(_FutureListener, "_FutureListener") \
362362
V(_GrowableList, "_GrowableList") \
363363
V(_GrowableListFactory, "_GrowableList.") \
364+
V(_GrowableListFilledFactory, "_GrowableList.filled") \
364365
V(_GrowableListWithData, "_GrowableList._withData") \
365366
V(_ImmutableList, "_ImmutableList") \
366367
V(_Int16ArrayFactory, "Int16List.") \
@@ -388,6 +389,7 @@ class ObjectPointerVisitor;
388389
V(_LinkedHashSet, "_CompactLinkedHashSet") \
389390
V(_List, "_List") \
390391
V(_ListFactory, "_List.") \
392+
V(_ListFilledFactory, "_List.filled") \
391393
V(_MethodMirror, "_MethodMirror") \
392394
V(_Mint, "_Mint") \
393395
V(_MirrorReference, "_MirrorReference") \

sdk/lib/_internal/vm/lib/array.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,18 @@ class _List<E> extends FixedLengthListBase<E> {
1111
@pragma("vm:prefer-inline")
1212
factory _List(length) native "List_allocate";
1313

14+
// Specialization of List.filled constructor for growable == false.
15+
// Used by pkg/vm/lib/transformations/list_factory_specializer.dart.
16+
factory _List.filled(int length, E fill) {
17+
final result = _List<E>(length);
18+
if (fill != null) {
19+
for (int i = 0; i < result.length; i++) {
20+
result[i] = fill;
21+
}
22+
}
23+
return result;
24+
}
25+
1426
E operator [](int index) native "List_getIndexed";
1527

1628
void operator []=(int index, E value) {

sdk/lib/_internal/vm/lib/growable_array.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,18 @@ class _GrowableList<T> extends ListBase<T> {
107107
return new _GrowableList<T>._withData(data);
108108
}
109109

110+
// Specialization of List.filled constructor for growable == true.
111+
// Used by pkg/vm/lib/transformations/list_factory_specializer.dart.
112+
factory _GrowableList.filled(int length, T fill) {
113+
final result = _GrowableList<T>(length);
114+
if (fill != null) {
115+
for (int i = 0; i < result.length; i++) {
116+
result[i] = fill;
117+
}
118+
}
119+
return result;
120+
}
121+
110122
@pragma("vm:exact-result-type",
111123
<dynamic>[_GrowableList, "result-type-uses-passed-type-arguments"])
112124
factory _GrowableList._withData(_List data) native "GrowableList_allocate";

0 commit comments

Comments
 (0)