Commit 27134f25 by Abseil Team Committed by Copybara-Service

Speed up `raw_hash_map::[]` with ABSL hardening enabled by unchecking…

Speed up `raw_hash_map::[]` with ABSL hardening enabled by unchecking dereference of iterator returned by `try_emplace`.

PiperOrigin-RevId: 597920257
Change-Id: I1b2e8f10a2f1efa763a6f0760294beafdb6fd9c0
parent 41a2a255
...@@ -177,13 +177,20 @@ class raw_hash_map : public raw_hash_set<Policy, Hash, Eq, Alloc> { ...@@ -177,13 +177,20 @@ class raw_hash_map : public raw_hash_set<Policy, Hash, Eq, Alloc> {
template <class K = key_type, class P = Policy, K* = nullptr> template <class K = key_type, class P = Policy, K* = nullptr>
MappedReference<P> operator[](key_arg<K>&& key) MappedReference<P> operator[](key_arg<K>&& key)
ABSL_ATTRIBUTE_LIFETIME_BOUND { ABSL_ATTRIBUTE_LIFETIME_BOUND {
return Policy::value(&*try_emplace(std::forward<K>(key)).first); // It is safe to use unchecked_deref here because try_emplace
// will always return an iterator pointing to a valid item in the table,
// since it inserts if nothing is found for the given key.
return Policy::value(
&this->unchecked_deref(try_emplace(std::forward<K>(key)).first));
} }
template <class K = key_type, class P = Policy> template <class K = key_type, class P = Policy>
MappedReference<P> operator[](const key_arg<K>& key) MappedReference<P> operator[](const key_arg<K>& key)
ABSL_ATTRIBUTE_LIFETIME_BOUND { ABSL_ATTRIBUTE_LIFETIME_BOUND {
return Policy::value(&*try_emplace(key).first); // It is safe to use unchecked_deref here because try_emplace
// will always return an iterator pointing to a valid item in the table,
// since it inserts if nothing is found for the given key.
return Policy::value(&this->unchecked_deref(try_emplace(key).first));
} }
private: private:
......
...@@ -1943,7 +1943,7 @@ class raw_hash_set { ...@@ -1943,7 +1943,7 @@ class raw_hash_set {
// PRECONDITION: not an end() iterator. // PRECONDITION: not an end() iterator.
reference operator*() const { reference operator*() const {
AssertIsFull(ctrl_, generation(), generation_ptr(), "operator*()"); AssertIsFull(ctrl_, generation(), generation_ptr(), "operator*()");
return PolicyTraits::element(slot_); return unchecked_deref();
} }
// PRECONDITION: not an end() iterator. // PRECONDITION: not an end() iterator.
...@@ -2023,6 +2023,10 @@ class raw_hash_set { ...@@ -2023,6 +2023,10 @@ class raw_hash_set {
// Should be used when the lifetimes of the iterators are well-enough // Should be used when the lifetimes of the iterators are well-enough
// understood to prove that they cannot be invalid. // understood to prove that they cannot be invalid.
bool unchecked_equals(const iterator& b) { return ctrl_ == b.control(); } bool unchecked_equals(const iterator& b) { return ctrl_ == b.control(); }
// Dereferences the iterator without ABSL Hardening iterator invalidation
// checks.
reference unchecked_deref() const { return PolicyTraits::element(slot_); }
}; };
class const_iterator { class const_iterator {
...@@ -3159,6 +3163,8 @@ class raw_hash_set { ...@@ -3159,6 +3163,8 @@ class raw_hash_set {
return {control() + i, slot_array() + i, common().generation_ptr()}; return {control() + i, slot_array() + i, common().generation_ptr()};
} }
reference unchecked_deref(iterator it) { return it.unchecked_deref(); }
private: private:
friend struct RawHashSetTestOnlyAccess; friend struct RawHashSetTestOnlyAccess;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment