Made HashMap.update faster by reducing it to one lookup.

fixes https://github.com/dart-lang/sdk/issues/48866

Test=ci and golem

Change-Id: Ia56bd5b5de83dc8f7263eeda27e7abd3af42851e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/242120
Reviewed-by: Siva Annamalai <asiva@google.com>
Commit-Queue: Siva Annamalai <asiva@google.com>
Reviewed-by: Lasse Nielsen <lrn@google.com>
This commit is contained in:
Aaron Clarke 2022-04-27 18:30:14 +00:00 committed by Commit Bot
parent ad4126bba4
commit 904303f8a1

View file

@ -239,6 +239,28 @@ class _HashMap<K, V> extends MapBase<K, V> implements HashMap<K, V> {
_buckets = newBuckets;
}
@override
V update(K key, V update(V value), {V Function()? ifAbsent}) {
final hashCode = key.hashCode;
final buckets = _buckets;
final length = buckets.length;
final index = hashCode & (length - 1);
var entry = buckets[index];
while (entry != null) {
if (hashCode == entry.hashCode && entry.key == key) {
return entry.value = update(entry.value);
}
entry = entry.next;
}
if (ifAbsent != null) {
V newValue = ifAbsent();
_addEntry(buckets, index, length, key, newValue, hashCode);
return newValue;
} else {
throw ArgumentError.value(key, "key", "Key not in map.");
}
}
Set<K> _newKeySet() => new _HashSet<K>();
}
@ -429,6 +451,28 @@ class _IdentityHashMap<K, V> extends _HashMap<K, V> {
return null;
}
@override
V update(K key, V update(V value), {V Function()? ifAbsent}) {
final hashCode = identityHashCode(key);
final buckets = _buckets;
final length = buckets.length;
final index = hashCode & (length - 1);
var entry = buckets[index];
while (entry != null) {
if (hashCode == entry.hashCode && identical(entry.key, key)) {
return entry.value = update(entry.value);
}
entry = entry.next;
}
if (ifAbsent != null) {
V newValue = ifAbsent();
_addEntry(buckets, index, length, key, newValue, hashCode);
return newValue;
} else {
throw ArgumentError.value(key, "key", "Key not in map.");
}
}
Set<K> _newKeySet() => new _IdentityHashSet<K>();
}