Skip to content

Commit 572b501

Browse files
mkustermannCommit Queue
authored andcommitted
[dart2wasm] Avoid indirect call to key.hashCode in json map creations
After a recent change we started to eagerly calculate the hash code of json object keys so when we create the string objects we initialize the hash as well (as we know it will be needed to create the map). This means that the actual creation of the hash map can do less work. Right now it does an indirect call to `key.hashCode`, but since we know those particular maps from the json decoder come only with string keys and most of them will have their hash code already prepopulated we can get avoid the indirect call to `key.hashCode` in most cases. Change-Id: I38987281bd8b216832cac950ea74d0ca201ff651 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/409980 Reviewed-by: Ömer Ağacan <[email protected]> Commit-Queue: Martin Kustermann <[email protected]>
1 parent 9820c8d commit 572b501

File tree

2 files changed

+19
-6
lines changed

2 files changed

+19
-6
lines changed

sdk/lib/_internal/wasm/lib/compact_hash.dart

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import "dart:_internal"
1111
TypeTest,
1212
unsafeCast;
1313
import "dart:_list" show GrowableList;
14+
import "dart:_object_helper";
1415
import "dart:_wasm";
1516

1617
import "dart:collection";
@@ -459,7 +460,7 @@ mixin _LinkedHashMapMixin<K, V> on _HashBase, _EqualsAndHashCode {
459460
/// This function is unsafe: it does not perform any type checking on
460461
/// keys and values assuming that caller has ensured that types are
461462
/// correct.
462-
void _populateUnsafe(WasmArray<Object?> data, int usedData) {
463+
void _populateUnsafeOnlyStringKeys(WasmArray<Object?> data, int usedData) {
463464
assert(usedData.isEven);
464465
int size = data.length;
465466
if (size == 0) {
@@ -486,7 +487,17 @@ mixin _LinkedHashMapMixin<K, V> on _HashBase, _EqualsAndHashCode {
486487
for (int i = 0; i < usedData; i += 2) {
487488
final key = unsafeCast<K>(data[i]);
488489
final value = unsafeCast<V>(data[i + 1]);
489-
_set(key, value, _hashCode(key));
490+
491+
// Strings store their hash code in the object header's identity hash code
492+
// field. So before doing a indirect call to obtain the hash code, we can
493+
// check if it was already computed and if so just use it.
494+
final int idHash = getIdentityHashField(unsafeCast<Object>(key));
495+
if (idHash != 0) {
496+
assert(idHash == key.hashCode);
497+
_set(key, value, idHash);
498+
} else {
499+
_set(key, value, key.hashCode);
500+
}
490501
}
491502
}
492503

@@ -1254,7 +1265,9 @@ base class CompactLinkedCustomHashSet<E> extends _HashFieldBase
12541265
}
12551266

12561267
@pragma('wasm:prefer-inline')
1257-
Map<K, V> createMapFromKeyValueListUnsafe<K, V>(
1268+
Map<K, V> createMapFromStringKeyValueListUnsafe<K, V>(
12581269
WasmArray<Object?> keyValuePairData,
12591270
int usedData,
1260-
) => DefaultMap<K, V>().._populateUnsafe(keyValuePairData, usedData);
1271+
) =>
1272+
DefaultMap<K, V>()
1273+
.._populateUnsafeOnlyStringKeys(keyValuePairData, usedData);

sdk/lib/_internal/wasm/lib/convert_patch.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
import "dart:_compact_hash" show createMapFromKeyValueListUnsafe;
5+
import "dart:_compact_hash" show createMapFromStringKeyValueListUnsafe;
66
import "dart:_error_utils";
77
import "dart:_internal"
88
show patch, POWERS_OF_TEN, unsafeCast, pushWasmArray, popWasmArray;
@@ -210,7 +210,7 @@ class _JsonListener {
210210
}
211211

212212
void endObject() {
213-
value = createMapFromKeyValueListUnsafe<String, dynamic>(
213+
value = createMapFromStringKeyValueListUnsafe<String, dynamic>(
214214
unsafeCast<WasmArray<Object?>>(currentContainer),
215215
currentContainerLength,
216216
);

0 commit comments

Comments
 (0)