Skip to content

Commit 27134f2

Browse files
Abseil Teamcopybara-github
authored andcommitted
Speed up raw_hash_map::[] with ABSL hardening enabled by unchecking dereference of iterator returned by try_emplace.
PiperOrigin-RevId: 597920257 Change-Id: I1b2e8f10a2f1efa763a6f0760294beafdb6fd9c0
1 parent 41a2a25 commit 27134f2

File tree

2 files changed

+16
-3
lines changed

2 files changed

+16
-3
lines changed

absl/container/internal/raw_hash_map.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,13 +177,20 @@ class raw_hash_map : public raw_hash_set<Policy, Hash, Eq, Alloc> {
177177
template <class K = key_type, class P = Policy, K* = nullptr>
178178
MappedReference<P> operator[](key_arg<K>&& key)
179179
ABSL_ATTRIBUTE_LIFETIME_BOUND {
180-
return Policy::value(&*try_emplace(std::forward<K>(key)).first);
180+
// It is safe to use unchecked_deref here because try_emplace
181+
// will always return an iterator pointing to a valid item in the table,
182+
// since it inserts if nothing is found for the given key.
183+
return Policy::value(
184+
&this->unchecked_deref(try_emplace(std::forward<K>(key)).first));
181185
}
182186

183187
template <class K = key_type, class P = Policy>
184188
MappedReference<P> operator[](const key_arg<K>& key)
185189
ABSL_ATTRIBUTE_LIFETIME_BOUND {
186-
return Policy::value(&*try_emplace(key).first);
190+
// It is safe to use unchecked_deref here because try_emplace
191+
// will always return an iterator pointing to a valid item in the table,
192+
// since it inserts if nothing is found for the given key.
193+
return Policy::value(&this->unchecked_deref(try_emplace(key).first));
187194
}
188195

189196
private:

absl/container/internal/raw_hash_set.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1943,7 +1943,7 @@ class raw_hash_set {
19431943
// PRECONDITION: not an end() iterator.
19441944
reference operator*() const {
19451945
AssertIsFull(ctrl_, generation(), generation_ptr(), "operator*()");
1946-
return PolicyTraits::element(slot_);
1946+
return unchecked_deref();
19471947
}
19481948

19491949
// PRECONDITION: not an end() iterator.
@@ -2023,6 +2023,10 @@ class raw_hash_set {
20232023
// Should be used when the lifetimes of the iterators are well-enough
20242024
// understood to prove that they cannot be invalid.
20252025
bool unchecked_equals(const iterator& b) { return ctrl_ == b.control(); }
2026+
2027+
// Dereferences the iterator without ABSL Hardening iterator invalidation
2028+
// checks.
2029+
reference unchecked_deref() const { return PolicyTraits::element(slot_); }
20262030
};
20272031

20282032
class const_iterator {
@@ -3159,6 +3163,8 @@ class raw_hash_set {
31593163
return {control() + i, slot_array() + i, common().generation_ptr()};
31603164
}
31613165

3166+
reference unchecked_deref(iterator it) { return it.unchecked_deref(); }
3167+
31623168
private:
31633169
friend struct RawHashSetTestOnlyAccess;
31643170

0 commit comments

Comments
 (0)