Skip to content

Commit 0c527e1

Browse files
rakudramaCommit Queue
authored andcommitted
[dart2js] Separate Iterables for Map.{keys,values,entries}
The default `MapBase.entries` and `MapBase.values` maps over the keys and does lookups. It is faster to scan the data like `get keys`. This is essentially the dart2js version of 23a98d808c0 Change-Id: I03894efda459d9a4f7f07c4c79524ba5e4d925cb Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/399027 Reviewed-by: Mayank Patke <[email protected]> Commit-Queue: Stephen Adams <[email protected]>
1 parent a279ee1 commit 0c527e1

File tree

2 files changed

+111
-18
lines changed

2 files changed

+111
-18
lines changed

pkg/compiler/test/inference/data/map_tracer_keys.dart

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ test1() {
2929
theMap
3030
/*update: Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSNumNotInt], map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: [null|exact=JSNumNotInt]})*/
3131
['d'] = 5.5;
32-
/*iterator: [exact=LinkedHashMapKeyIterable]*/
32+
/*iterator: [exact=LinkedHashMapKeysIterable]*/
3333
/*current: [exact=LinkedHashMapKeyIterator]*/
3434
/*moveNext: [exact=LinkedHashMapKeyIterator]*/
3535
for (var key in theMap.
@@ -60,7 +60,7 @@ test2() {
6060
theMap
6161
/*update: Map([exact=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSNumNotInt])*/
6262
[aList2] = 5.5;
63-
/*iterator: [exact=LinkedHashMapKeyIterable]*/
63+
/*iterator: [exact=LinkedHashMapKeysIterable]*/
6464
/*current: [exact=LinkedHashMapKeyIterator]*/
6565
/*moveNext: [exact=LinkedHashMapKeyIterator]*/
6666
for (var key in theMap.
@@ -91,7 +91,7 @@ test3() {
9191
theMap
9292
/*update: Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt]), map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: Container([null|exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)})*/
9393
['d'] = aList3;
94-
/*iterator: [exact=LinkedHashMapKeyIterable]*/
94+
/*iterator: [exact=LinkedHashMapKeysIterable]*/
9595
/*current: [exact=LinkedHashMapKeyIterator]*/
9696
/*moveNext: [exact=LinkedHashMapKeyIterator]*/
9797
for (var key in theMap.
@@ -119,7 +119,7 @@ consume4(
119119
/*member: test4:[null]*/
120120
test4() {
121121
var theMap = {'a': 2.2, 'b': 3.3, 'c': 4.4, 'd': 5.5};
122-
/*iterator: [exact=LinkedHashMapKeyIterable]*/
122+
/*iterator: [exact=LinkedHashMapKeysIterable]*/
123123
/*current: [exact=LinkedHashMapKeyIterator]*/
124124
/*moveNext: [exact=LinkedHashMapKeyIterator]*/
125125
for (var key in theMap.
@@ -147,7 +147,7 @@ consume5(
147147
/*member: test5:[null]*/
148148
test5() {
149149
var theMap = {'a': 2.2, 'b': 3.3, 'c': 4.4, aList5: 5.5};
150-
/*iterator: [exact=LinkedHashMapKeyIterable]*/
150+
/*iterator: [exact=LinkedHashMapKeysIterable]*/
151151
/*current: [exact=LinkedHashMapKeyIterator]*/
152152
/*moveNext: [exact=LinkedHashMapKeyIterator]*/
153153
for (var key in theMap.
@@ -174,7 +174,7 @@ consume6(
174174
/*member: test6:[null]*/
175175
test6() {
176176
var theMap = {'a': 2.2, 'b': 3.3, 'c': 4.4, 'd': aList6};
177-
/*iterator: [exact=LinkedHashMapKeyIterable]*/
177+
/*iterator: [exact=LinkedHashMapKeysIterable]*/
178178
/*current: [exact=LinkedHashMapKeyIterator]*/
179179
/*moveNext: [exact=LinkedHashMapKeyIterator]*/
180180
for (var key in theMap.

sdk/lib/_internal/js_runtime/lib/linked_hash_map.dart

Lines changed: 105 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,11 @@ class JsLinkedHashMap<K, V> extends MapBase<K, V>
4444
bool get isEmpty => _length == 0;
4545
bool get isNotEmpty => !isEmpty;
4646

47-
Iterable<K> get keys {
48-
return LinkedHashMapKeyIterable<K>(this);
49-
}
47+
Iterable<K> get keys => LinkedHashMapKeysIterable<K>(this);
5048

51-
Iterable<V> get values {
52-
return MappedIterable<K, V>(keys, (each) => this[each] as V);
53-
}
49+
Iterable<V> get values => LinkedHashMapValuesIterable<V>(this);
50+
51+
Iterable<MapEntry<K, V>> get entries => LinkedHashMapEntriesIterable(this);
5452

5553
bool containsKey(Object? key) {
5654
if (_isStringKey(key)) {
@@ -339,13 +337,13 @@ class LinkedHashMapCell {
339337
LinkedHashMapCell(this.hashMapCellKey, this.hashMapCellValue);
340338
}
341339

342-
class LinkedHashMapKeyIterable<E> extends EfficientLengthIterable<E>
340+
class LinkedHashMapKeysIterable<E> extends EfficientLengthIterable<E>
343341
implements HideEfficientLengthIterable<E> {
344342
final JsLinkedHashMap _map;
345-
LinkedHashMapKeyIterable(this._map);
343+
LinkedHashMapKeysIterable(this._map);
346344

347345
int get length => _map._length;
348-
bool get isEmpty => _map._length == 0;
346+
bool get isEmpty => _map.isEmpty;
349347

350348
Iterator<E> get iterator {
351349
return LinkedHashMapKeyIterator<E>(_map, _map._modifications);
@@ -374,9 +372,8 @@ class LinkedHashMapKeyIterator<E> implements Iterator<E> {
374372
LinkedHashMapCell? _cell;
375373
E? _current;
376374

377-
LinkedHashMapKeyIterator(this._map, this._modifications) {
378-
_cell = _map._first;
379-
}
375+
LinkedHashMapKeyIterator(this._map, this._modifications)
376+
: _cell = _map._first;
380377

381378
@pragma('dart2js:as:trust')
382379
E get current => _current as E;
@@ -397,6 +394,102 @@ class LinkedHashMapKeyIterator<E> implements Iterator<E> {
397394
}
398395
}
399396

397+
class LinkedHashMapValuesIterable<E> extends EfficientLengthIterable<E>
398+
implements HideEfficientLengthIterable<E> {
399+
final JsLinkedHashMap _map;
400+
LinkedHashMapValuesIterable(this._map);
401+
402+
int get length => _map._length;
403+
bool get isEmpty => _map.isEmpty;
404+
405+
Iterator<E> get iterator {
406+
return LinkedHashMapValueIterator<E>(_map, _map._modifications);
407+
}
408+
409+
void forEach(void f(E element)) {
410+
LinkedHashMapCell? cell = _map._first;
411+
int modifications = _map._modifications;
412+
while (cell != null) {
413+
f(JS('', '#', cell.hashMapCellValue));
414+
if (modifications != _map._modifications) {
415+
throw ConcurrentModificationError(_map);
416+
}
417+
cell = cell._next;
418+
}
419+
}
420+
}
421+
422+
class LinkedHashMapValueIterator<E> implements Iterator<E> {
423+
final JsLinkedHashMap _map;
424+
final int _modifications;
425+
LinkedHashMapCell? _cell;
426+
E? _current;
427+
428+
LinkedHashMapValueIterator(this._map, this._modifications)
429+
: _cell = _map._first;
430+
431+
@pragma('dart2js:as:trust')
432+
E get current => _current as E;
433+
434+
bool moveNext() {
435+
if (_modifications != _map._modifications) {
436+
throw ConcurrentModificationError(_map);
437+
}
438+
var cell = _cell;
439+
if (cell == null) {
440+
_current = null;
441+
return false;
442+
} else {
443+
_current = JS('', '#', cell.hashMapCellValue);
444+
_cell = cell._next;
445+
return true;
446+
}
447+
}
448+
}
449+
450+
class LinkedHashMapEntriesIterable<K, V>
451+
extends EfficientLengthIterable<MapEntry<K, V>>
452+
implements HideEfficientLengthIterable<MapEntry<K, V>> {
453+
final JsLinkedHashMap _map;
454+
LinkedHashMapEntriesIterable(this._map);
455+
456+
int get length => _map._length;
457+
bool get isEmpty => _map.isEmpty;
458+
459+
Iterator<MapEntry<K, V>> get iterator {
460+
return LinkedHashMapEntryIterator<K, V>(_map, _map._modifications);
461+
}
462+
}
463+
464+
class LinkedHashMapEntryIterator<K, V> implements Iterator<MapEntry<K, V>> {
465+
final JsLinkedHashMap _map;
466+
final int _modifications;
467+
LinkedHashMapCell? _cell;
468+
MapEntry<K, V>? _current;
469+
470+
LinkedHashMapEntryIterator(this._map, this._modifications)
471+
: _cell = _map._first;
472+
473+
MapEntry<K, V> get current => _current!;
474+
475+
bool moveNext() {
476+
if (_modifications != _map._modifications) {
477+
throw ConcurrentModificationError(_map);
478+
}
479+
var cell = _cell;
480+
if (cell == null) {
481+
_current = null;
482+
return false;
483+
} else {
484+
final K key = JS('', '#', cell.hashMapCellKey);
485+
final V value = JS('', '#', cell.hashMapCellValue);
486+
_current = MapEntry(key, value);
487+
_cell = cell._next;
488+
return true;
489+
}
490+
}
491+
}
492+
400493
base class JsIdentityLinkedHashMap<K, V> extends JsLinkedHashMap<K, V> {
401494
JsIdentityLinkedHashMap();
402495

0 commit comments

Comments
 (0)