diff --git a/src/hb-map.hh b/src/hb-map.hh index 9bfe338eb..6794a1ef8 100644 --- a/src/hb-map.hh +++ b/src/hb-map.hh @@ -198,14 +198,49 @@ struct hb_hashmap_t return true; } + template + bool set_with_hash (K key, uint32_t hash, VV&& value, bool is_delete=false) + { + if (unlikely (!successful)) return false; + if (unlikely ((occupancy + occupancy / 2) >= mask && !resize ())) return false; + item_t &item = item_for_hash (key, hash); + + if (is_delete && !(item == key)) + return true; /* Trying to delete non-existent key. */ + + if (item.is_used ()) + { + occupancy--; + if (!item.is_tombstone ()) + population--; + } + + item.key = key; + item.value = std::forward (value); + item.hash = hash; + item.set_used (true); + item.set_tombstone (is_delete); + + occupancy++; + if (!is_delete) + population++; + + return true; + } + template bool set (K key, VV&& value) { return set_with_hash (key, hb_hash (key), std::forward (value)); } + const V& get_with_hash (K key, uint32_t hash) const + { + if (unlikely (!items)) return item_t::default_value (); + auto &item = item_for_hash (key, hash); + return item.is_real () && item == key ? item.value : item_t::default_value (); + } const V& get (K key) const { if (unlikely (!items)) return item_t::default_value (); - auto &item = item_for (key); - return item.is_real () && item == key ? item.value : item_t::default_value (); + return get_with_hash (key, hb_hash (key)); } void del (K key) { set_with_hash (key, hb_hash (key), item_t::default_value (), true); } @@ -218,7 +253,7 @@ struct hb_hashmap_t { if (unlikely (!items)) return false; - auto &item = item_for (key); + auto &item = item_for_hash (key, hb_hash (key)); if (item.is_real () && item == key) { if (vp) *vp = std::addressof (item.value); @@ -322,43 +357,6 @@ struct hb_hashmap_t hb_hashmap_t& operator << (const hb_pair_t& v) { set (std::move (v.first), std::move (v.second)); return *this; } - protected: - - template - bool set_with_hash (K key, uint32_t hash, VV&& value, bool is_delete=false) - { - if (unlikely (!successful)) return false; - if (unlikely ((occupancy + occupancy / 2) >= mask && !resize ())) return false; - item_t &item = item_for_hash (key, hash); - - if (is_delete && !(item == key)) - return true; /* Trying to delete non-existent key. */ - - if (item.is_used ()) - { - occupancy--; - if (!item.is_tombstone ()) - population--; - } - - item.key = key; - item.value = std::forward (value); - item.hash = hash; - item.set_used (true); - item.set_tombstone (is_delete); - - occupancy++; - if (!is_delete) - population++; - - return true; - } - - item_t& item_for (const K &key) const - { - return item_for_hash (key, hb_hash (key)); - } - item_t& item_for_hash (const K &key, uint32_t hash) const { hash &= 0x3FFFFFFF; // We only store lower 30bit of hash diff --git a/src/hb-serialize.hh b/src/hb-serialize.hh index 3c26bf402..9ad89f045 100644 --- a/src/hb-serialize.hh +++ b/src/hb-serialize.hh @@ -354,9 +354,11 @@ struct hb_serialize_context_t } objidx_t objidx; + uint32_t hash; if (share) { - objidx = packed_map.get (obj); + hash = hb_hash (obj); + objidx = packed_map.get_with_hash (obj, hash); if (objidx) { merge_virtual_links (obj, objidx); @@ -384,7 +386,7 @@ struct hb_serialize_context_t objidx = packed.length - 1; - if (share) packed_map.set (obj, objidx); + if (share) packed_map.set_with_hash (obj, hash, objidx); propagate_error (packed_map); return objidx; diff --git a/src/test-map.cc b/src/test-map.cc index 12455ea8e..acd5d7cc1 100644 --- a/src/test-map.cc +++ b/src/test-map.cc @@ -232,7 +232,7 @@ main (int argc, char **argv) // See commit f657ef7e57c889309c2d9d37934368ca255f9d5b and its revert. //m.set (hb::unique_ptr (hb_set_get_empty ()), // hb::unique_ptr (hb_set_get_empty ())); - m.get (hb::unique_ptr (hb_set_get_empty ())); + //m.get (hb::unique_ptr (hb_set_get_empty ())); m.iter_ref (); m.keys_ref (); m.values_ref ();