|  | @@ -41,7 +41,7 @@
 | 
	
		
			
				|  |  |  #include <initializer_list>
 | 
	
		
			
				|  |  |  #include <iterator>
 | 
	
		
			
				|  |  |  #include <limits>  // To support Visual Studio 2008
 | 
	
		
			
				|  |  | -#include <set>
 | 
	
		
			
				|  |  | +#include <map>
 | 
	
		
			
				|  |  |  #include <type_traits>
 | 
	
		
			
				|  |  |  #include <utility>
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -181,39 +181,10 @@ class MapAllocator {
 | 
	
		
			
				|  |  |    Arena* const arena_;
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -template <typename Key>
 | 
	
		
			
				|  |  | -struct DerefCompare {
 | 
	
		
			
				|  |  | -  bool operator()(const Key* n0, const Key* n1) const { return *n0 < *n1; }
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -// This class is used to get trivially destructible views of std::string and
 | 
	
		
			
				|  |  | -// MapKey, which are the only non-trivially destructible allowed key types.
 | 
	
		
			
				|  |  | -template <typename Key>
 | 
	
		
			
				|  |  | -class KeyView {
 | 
	
		
			
				|  |  | - public:
 | 
	
		
			
				|  |  | -  KeyView(const Key& key) : key_(&key) {}  // NOLINT(runtime/explicit)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  const Key& get() const { return *key_; }
 | 
	
		
			
				|  |  | -  // Allows implicit conversions to `const Key&`, which allows us to use the
 | 
	
		
			
				|  |  | -  // hasher defined for Key.
 | 
	
		
			
				|  |  | -  operator const Key&() const { return get(); }  // NOLINT(runtime/explicit)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  bool operator==(const KeyView& other) const { return get() == other.get(); }
 | 
	
		
			
				|  |  | -  bool operator==(const Key& other) const { return get() == other; }
 | 
	
		
			
				|  |  | -  bool operator<(const KeyView& other) const { return get() < other.get(); }
 | 
	
		
			
				|  |  | -  bool operator<(const Key& other) const { return get() < other; }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | - private:
 | 
	
		
			
				|  |  | -  const Key* key_;
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -// Allows the InnerMap type to support skippable destruction.
 | 
	
		
			
				|  |  | -template <typename Key>
 | 
	
		
			
				|  |  | -struct GetTrivialKey {
 | 
	
		
			
				|  |  | -  using type =
 | 
	
		
			
				|  |  | -      typename std::conditional<std::is_trivially_destructible<Key>::value, Key,
 | 
	
		
			
				|  |  | -                                KeyView<Key>>::type;
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | +template <typename T>
 | 
	
		
			
				|  |  | +using KeyForTree =
 | 
	
		
			
				|  |  | +    typename std::conditional<std::is_scalar<T>::value, T,
 | 
	
		
			
				|  |  | +                              std::reference_wrapper<const T>>::type;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  }  // namespace internal
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -313,31 +284,9 @@ class Map {
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |   private:
 | 
	
		
			
				|  |  | -  void Init() { elements_ = Arena::CreateMessage<InnerMap>(arena_, 0u); }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // InnerMap's key type is TrivialKey and its value type is value_type*.  We
 | 
	
		
			
				|  |  | -  // use a custom class here and for Node, below, to ensure that k_ is at offset
 | 
	
		
			
				|  |  | -  // 0, allowing safe conversion from pointer to Node to pointer to TrivialKey,
 | 
	
		
			
				|  |  | -  // and vice versa when appropriate.  We use GetTrivialKey to adapt Key to
 | 
	
		
			
				|  |  | -  // be a trivially destructible view if Key is not already trivially
 | 
	
		
			
				|  |  | -  // destructible.  This view points into the Key inside v_ once it's
 | 
	
		
			
				|  |  | -  // initialized.
 | 
	
		
			
				|  |  | -  using TrivialKey = typename internal::GetTrivialKey<Key>::type;
 | 
	
		
			
				|  |  | -  class KeyValuePair {
 | 
	
		
			
				|  |  | -   public:
 | 
	
		
			
				|  |  | -    KeyValuePair(const TrivialKey& k, value_type* v) : k_(k), v_(v) {}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    const TrivialKey& key() const { return k_; }
 | 
	
		
			
				|  |  | -    TrivialKey& key() { return k_; }
 | 
	
		
			
				|  |  | -    value_type* value() const { return v_; }
 | 
	
		
			
				|  |  | -    value_type*& value() { return v_; }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -   private:
 | 
	
		
			
				|  |  | -    TrivialKey k_;
 | 
	
		
			
				|  |  | -    value_type* v_;
 | 
	
		
			
				|  |  | -  };
 | 
	
		
			
				|  |  | +  void Init() { elements_ = Arena::CreateMessage<InnerMap>(arena_, 0); }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  using Allocator = internal::MapAllocator<KeyValuePair>;
 | 
	
		
			
				|  |  | +  using Allocator = internal::MapAllocator<void*>;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    // InnerMap is a generic hash-based map.  It doesn't contain any
 | 
	
		
			
				|  |  |    // protocol-buffer-specific logic.  It is a chaining hash map with the
 | 
	
	
		
			
				|  | @@ -368,14 +317,11 @@ class Map {
 | 
	
		
			
				|  |  |    // 8. Mutations to a map do not invalidate the map's iterators, pointers to
 | 
	
		
			
				|  |  |    //    elements, or references to elements.
 | 
	
		
			
				|  |  |    // 9. Except for erase(iterator), any non-const method can reorder iterators.
 | 
	
		
			
				|  |  | -  // 10. InnerMap's key is TrivialKey, which is either Key, if Key is trivially
 | 
	
		
			
				|  |  | -  //    destructible, or a trivially destructible view of Key otherwise. This
 | 
	
		
			
				|  |  | -  //    allows InnerMap's destructor to be skipped when InnerMap is
 | 
	
		
			
				|  |  | -  //    arena-allocated.
 | 
	
		
			
				|  |  | +  // 10. InnerMap uses KeyForTree<Key> when using the Tree representation, which
 | 
	
		
			
				|  |  | +  //    is either `Key`, if Key is a scalar, or `reference_wrapper<const Key>`
 | 
	
		
			
				|  |  | +  //    otherwise. This avoids unncessary copies of string keys, for example.
 | 
	
		
			
				|  |  |    class InnerMap : private hasher {
 | 
	
		
			
				|  |  |     public:
 | 
	
		
			
				|  |  | -    using Value = value_type*;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |      explicit InnerMap(size_type n) : InnerMap(nullptr, n) {}
 | 
	
		
			
				|  |  |      InnerMap(Arena* arena, size_type n)
 | 
	
		
			
				|  |  |          : hasher(),
 | 
	
	
		
			
				|  | @@ -386,10 +332,6 @@ class Map {
 | 
	
		
			
				|  |  |        n = TableSize(n);
 | 
	
		
			
				|  |  |        table_ = CreateEmptyTable(n);
 | 
	
		
			
				|  |  |        num_buckets_ = index_of_first_non_null_ = n;
 | 
	
		
			
				|  |  | -      static_assert(
 | 
	
		
			
				|  |  | -          std::is_trivially_destructible<KeyValuePair>::value,
 | 
	
		
			
				|  |  | -          "We require KeyValuePair to be trivially destructible so that we can "
 | 
	
		
			
				|  |  | -          "skip InnerMap's destructor when it's arena allocated.");
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      ~InnerMap() {
 | 
	
	
		
			
				|  | @@ -404,27 +346,25 @@ class Map {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      // Linked-list nodes, as one would expect for a chaining hash table.
 | 
	
		
			
				|  |  |      struct Node {
 | 
	
		
			
				|  |  | -      KeyValuePair kv;
 | 
	
		
			
				|  |  | +      value_type kv;
 | 
	
		
			
				|  |  |        Node* next;
 | 
	
		
			
				|  |  |      };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    // This is safe only if the given pointer is known to point to a Key that is
 | 
	
		
			
				|  |  | -    // part of a Node.
 | 
	
		
			
				|  |  | -    static Node* NodePtrFromKeyPtr(TrivialKey* k) {
 | 
	
		
			
				|  |  | -      return reinterpret_cast<Node*>(k);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    static TrivialKey* KeyPtrFromNodePtr(Node* node) { return &node->kv.key(); }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // Trees.  The payload type is pointer to Key, so that we can query the tree
 | 
	
		
			
				|  |  | -    // with Keys that are not in any particular data structure.  When we insert,
 | 
	
		
			
				|  |  | -    // though, the pointer is always pointing to a Key that is inside a Node.
 | 
	
		
			
				|  |  | -    using KeyPtrAllocator =
 | 
	
		
			
				|  |  | -        typename Allocator::template rebind<TrivialKey*>::other;
 | 
	
		
			
				|  |  | -    using Tree = std::set<TrivialKey*, internal::DerefCompare<TrivialKey>,
 | 
	
		
			
				|  |  | -                          KeyPtrAllocator>;
 | 
	
		
			
				|  |  | +    // Trees. The payload type is a copy of Key, so that we can query the tree
 | 
	
		
			
				|  |  | +    // with Keys that are not in any particular data structure.
 | 
	
		
			
				|  |  | +    // The value is a void* pointing to Node. We use void* instead of Node* to
 | 
	
		
			
				|  |  | +    // avoid code bloat. That way there is only one instantiation of the tree
 | 
	
		
			
				|  |  | +    // class per key type.
 | 
	
		
			
				|  |  | +    using TreeAllocator = typename Allocator::template rebind<
 | 
	
		
			
				|  |  | +        std::pair<const internal::KeyForTree<Key>, void*>>::other;
 | 
	
		
			
				|  |  | +    using Tree = std::map<internal::KeyForTree<Key>, void*, std::less<Key>,
 | 
	
		
			
				|  |  | +                          TreeAllocator>;
 | 
	
		
			
				|  |  |      using TreeIterator = typename Tree::iterator;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    static Node* NodeFromTreeIterator(TreeIterator it) {
 | 
	
		
			
				|  |  | +      return static_cast<Node*>(it->second);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      // iterator and const_iterator are instantiations of iterator_base.
 | 
	
		
			
				|  |  |      template <typename KeyValueType>
 | 
	
		
			
				|  |  |      class iterator_base {
 | 
	
	
		
			
				|  | @@ -456,7 +396,7 @@ class Map {
 | 
	
		
			
				|  |  |            : node_(n), m_(m), bucket_index_(index) {}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |        iterator_base(TreeIterator tree_it, const InnerMap* m, size_type index)
 | 
	
		
			
				|  |  | -          : node_(NodePtrFromKeyPtr(*tree_it)), m_(m), bucket_index_(index) {
 | 
	
		
			
				|  |  | +          : node_(NodeFromTreeIterator(tree_it)), m_(m), bucket_index_(index) {
 | 
	
		
			
				|  |  |          // Invariant: iterators that use buckets with trees have an even
 | 
	
		
			
				|  |  |          // bucket_index_.
 | 
	
		
			
				|  |  |          GOOGLE_DCHECK_EQ(bucket_index_ % 2, 0u);
 | 
	
	
		
			
				|  | @@ -476,7 +416,7 @@ class Map {
 | 
	
		
			
				|  |  |            } else if (m_->TableEntryIsTree(bucket_index_)) {
 | 
	
		
			
				|  |  |              Tree* tree = static_cast<Tree*>(m_->table_[bucket_index_]);
 | 
	
		
			
				|  |  |              GOOGLE_DCHECK(!tree->empty());
 | 
	
		
			
				|  |  | -            node_ = NodePtrFromKeyPtr(*tree->begin());
 | 
	
		
			
				|  |  | +            node_ = NodeFromTreeIterator(tree->begin());
 | 
	
		
			
				|  |  |              break;
 | 
	
		
			
				|  |  |            }
 | 
	
		
			
				|  |  |          }
 | 
	
	
		
			
				|  | @@ -504,7 +444,7 @@ class Map {
 | 
	
		
			
				|  |  |              if (++tree_it == tree->end()) {
 | 
	
		
			
				|  |  |                SearchFrom(bucket_index_ + 2);
 | 
	
		
			
				|  |  |              } else {
 | 
	
		
			
				|  |  | -              node_ = NodePtrFromKeyPtr(*tree_it);
 | 
	
		
			
				|  |  | +              node_ = NodeFromTreeIterator(tree_it);
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |            }
 | 
	
		
			
				|  |  |          } else {
 | 
	
	
		
			
				|  | @@ -542,8 +482,8 @@ class Map {
 | 
	
		
			
				|  |  |          // Well, bucket_index_ still might be correct, but probably
 | 
	
		
			
				|  |  |          // not.  Revalidate just to be sure.  This case is rare enough that we
 | 
	
		
			
				|  |  |          // don't worry about potential optimizations, such as having a custom
 | 
	
		
			
				|  |  | -        // find-like method that compares Node* instead of TrivialKey.
 | 
	
		
			
				|  |  | -        iterator_base i(m_->find(*KeyPtrFromNodePtr(node_), it));
 | 
	
		
			
				|  |  | +        // find-like method that compares Node* instead of the key.
 | 
	
		
			
				|  |  | +        iterator_base i(m_->find(node_->kv.first, it));
 | 
	
		
			
				|  |  |          bucket_index_ = i.bucket_index_;
 | 
	
		
			
				|  |  |          return m_->TableEntryIsList(bucket_index_);
 | 
	
		
			
				|  |  |        }
 | 
	
	
		
			
				|  | @@ -554,8 +494,8 @@ class Map {
 | 
	
		
			
				|  |  |      };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |     public:
 | 
	
		
			
				|  |  | -    using iterator = iterator_base<KeyValuePair>;
 | 
	
		
			
				|  |  | -    using const_iterator = iterator_base<const KeyValuePair>;
 | 
	
		
			
				|  |  | +    using iterator = iterator_base<value_type>;
 | 
	
		
			
				|  |  | +    using const_iterator = iterator_base<const value_type>;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      iterator begin() { return iterator(this); }
 | 
	
		
			
				|  |  |      iterator end() { return iterator(); }
 | 
	
	
		
			
				|  | @@ -578,7 +518,7 @@ class Map {
 | 
	
		
			
				|  |  |            table_[b] = table_[b + 1] = nullptr;
 | 
	
		
			
				|  |  |            typename Tree::iterator tree_it = tree->begin();
 | 
	
		
			
				|  |  |            do {
 | 
	
		
			
				|  |  | -            Node* node = NodePtrFromKeyPtr(*tree_it);
 | 
	
		
			
				|  |  | +            Node* node = NodeFromTreeIterator(tree_it);
 | 
	
		
			
				|  |  |              typename Tree::iterator next = tree_it;
 | 
	
		
			
				|  |  |              ++next;
 | 
	
		
			
				|  |  |              tree->erase(tree_it);
 | 
	
	
		
			
				|  | @@ -601,31 +541,13 @@ class Map {
 | 
	
		
			
				|  |  |      size_type size() const { return num_elements_; }
 | 
	
		
			
				|  |  |      bool empty() const { return size() == 0; }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    iterator find(const TrivialKey& k) { return iterator(FindHelper(k).first); }
 | 
	
		
			
				|  |  | -    const_iterator find(const TrivialKey& k) const { return find(k, nullptr); }
 | 
	
		
			
				|  |  | -    bool contains(const TrivialKey& k) const { return find(k) != end(); }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // In traditional C++ style, this performs "insert if not present."
 | 
	
		
			
				|  |  | -    std::pair<iterator, bool> insert(const KeyValuePair& kv) {
 | 
	
		
			
				|  |  | -      std::pair<const_iterator, size_type> p = FindHelper(kv.key());
 | 
	
		
			
				|  |  | -      // Case 1: key was already present.
 | 
	
		
			
				|  |  | -      if (p.first.node_ != nullptr)
 | 
	
		
			
				|  |  | -        return std::make_pair(iterator(p.first), false);
 | 
	
		
			
				|  |  | -      // Case 2: insert.
 | 
	
		
			
				|  |  | -      if (ResizeIfLoadIsOutOfRange(num_elements_ + 1)) {
 | 
	
		
			
				|  |  | -        p = FindHelper(kv.key());
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -      const size_type b = p.second;  // bucket number
 | 
	
		
			
				|  |  | -      Node* node = Alloc<Node>(1);
 | 
	
		
			
				|  |  | -      alloc_.construct(&node->kv, kv);
 | 
	
		
			
				|  |  | -      iterator result = InsertUnique(b, node);
 | 
	
		
			
				|  |  | -      ++num_elements_;
 | 
	
		
			
				|  |  | -      return std::make_pair(result, true);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | +    iterator find(const Key& k) { return iterator(FindHelper(k).first); }
 | 
	
		
			
				|  |  | +    const_iterator find(const Key& k) const { return find(k, nullptr); }
 | 
	
		
			
				|  |  | +    bool contains(const Key& k) const { return find(k) != end(); }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    // The same, but if an insertion is necessary then the value portion of the
 | 
	
		
			
				|  |  | -    // inserted key-value pair is left uninitialized.
 | 
	
		
			
				|  |  | -    std::pair<iterator, bool> insert(const TrivialKey& k) {
 | 
	
		
			
				|  |  | +    // Insert the key into the map, if not present. In that case, the value will
 | 
	
		
			
				|  |  | +    // be value initialized.
 | 
	
		
			
				|  |  | +    std::pair<iterator, bool> insert(const Key& k) {
 | 
	
		
			
				|  |  |        std::pair<const_iterator, size_type> p = FindHelper(k);
 | 
	
		
			
				|  |  |        // Case 1: key was already present.
 | 
	
		
			
				|  |  |        if (p.first.node_ != nullptr)
 | 
	
	
		
			
				|  | @@ -635,21 +557,22 @@ class Map {
 | 
	
		
			
				|  |  |          p = FindHelper(k);
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |        const size_type b = p.second;  // bucket number
 | 
	
		
			
				|  |  | -      Node* node = Alloc<Node>(1);
 | 
	
		
			
				|  |  | -      using KeyAllocator =
 | 
	
		
			
				|  |  | -          typename Allocator::template rebind<TrivialKey>::other;
 | 
	
		
			
				|  |  | -      KeyAllocator(alloc_).construct(&node->kv.key(), k);
 | 
	
		
			
				|  |  | +      Node* node;
 | 
	
		
			
				|  |  | +      if (alloc_.arena() == nullptr) {
 | 
	
		
			
				|  |  | +        node = new Node{value_type(k), nullptr};
 | 
	
		
			
				|  |  | +      } else {
 | 
	
		
			
				|  |  | +        node = Alloc<Node>(1);
 | 
	
		
			
				|  |  | +        Arena::CreateInArenaStorage(const_cast<Key*>(&node->kv.first),
 | 
	
		
			
				|  |  | +                                    alloc_.arena(), k);
 | 
	
		
			
				|  |  | +        Arena::CreateInArenaStorage(&node->kv.second, alloc_.arena());
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |        iterator result = InsertUnique(b, node);
 | 
	
		
			
				|  |  |        ++num_elements_;
 | 
	
		
			
				|  |  |        return std::make_pair(result, true);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    // Returns iterator so that outer map can update the TrivialKey to point to
 | 
	
		
			
				|  |  | -    // the Key inside value_type in case TrivialKey is a view type.
 | 
	
		
			
				|  |  | -    iterator operator[](const TrivialKey& k) {
 | 
	
		
			
				|  |  | -      KeyValuePair kv(k, Value());
 | 
	
		
			
				|  |  | -      return insert(kv).first;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | +    value_type& operator[](const Key& k) { return *insert(k).first; }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      void erase(iterator it) {
 | 
	
		
			
				|  |  |        GOOGLE_DCHECK_EQ(it.m_, this);
 | 
	
	
		
			
				|  | @@ -665,7 +588,7 @@ class Map {
 | 
	
		
			
				|  |  |        } else {
 | 
	
		
			
				|  |  |          GOOGLE_DCHECK(TableEntryIsTree(b));
 | 
	
		
			
				|  |  |          Tree* tree = static_cast<Tree*>(table_[b]);
 | 
	
		
			
				|  |  | -        tree->erase(*tree_it);
 | 
	
		
			
				|  |  | +        tree->erase(tree_it);
 | 
	
		
			
				|  |  |          if (tree->empty()) {
 | 
	
		
			
				|  |  |            // Force b to be the minimum of b and b ^ 1.  This is important
 | 
	
		
			
				|  |  |            // only because we want index_of_first_non_null_ to be correct.
 | 
	
	
		
			
				|  | @@ -685,19 +608,19 @@ class Map {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |     private:
 | 
	
		
			
				|  |  | -    const_iterator find(const TrivialKey& k, TreeIterator* it) const {
 | 
	
		
			
				|  |  | +    const_iterator find(const Key& k, TreeIterator* it) const {
 | 
	
		
			
				|  |  |        return FindHelper(k, it).first;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    std::pair<const_iterator, size_type> FindHelper(const TrivialKey& k) const {
 | 
	
		
			
				|  |  | +    std::pair<const_iterator, size_type> FindHelper(const Key& k) const {
 | 
	
		
			
				|  |  |        return FindHelper(k, nullptr);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    std::pair<const_iterator, size_type> FindHelper(const TrivialKey& k,
 | 
	
		
			
				|  |  | +    std::pair<const_iterator, size_type> FindHelper(const Key& k,
 | 
	
		
			
				|  |  |                                                      TreeIterator* it) const {
 | 
	
		
			
				|  |  |        size_type b = BucketNumber(k);
 | 
	
		
			
				|  |  |        if (TableEntryIsNonEmptyList(b)) {
 | 
	
		
			
				|  |  |          Node* node = static_cast<Node*>(table_[b]);
 | 
	
		
			
				|  |  |          do {
 | 
	
		
			
				|  |  | -          if (IsMatch(*KeyPtrFromNodePtr(node), k)) {
 | 
	
		
			
				|  |  | +          if (IsMatch(node->kv.first, k)) {
 | 
	
		
			
				|  |  |              return std::make_pair(const_iterator(node, this, b), b);
 | 
	
		
			
				|  |  |            } else {
 | 
	
		
			
				|  |  |              node = node->next;
 | 
	
	
		
			
				|  | @@ -707,8 +630,7 @@ class Map {
 | 
	
		
			
				|  |  |          GOOGLE_DCHECK_EQ(table_[b], table_[b ^ 1]);
 | 
	
		
			
				|  |  |          b &= ~static_cast<size_t>(1);
 | 
	
		
			
				|  |  |          Tree* tree = static_cast<Tree*>(table_[b]);
 | 
	
		
			
				|  |  | -        TrivialKey* key = const_cast<TrivialKey*>(&k);
 | 
	
		
			
				|  |  | -        typename Tree::iterator tree_it = tree->find(key);
 | 
	
		
			
				|  |  | +        auto tree_it = tree->find(k);
 | 
	
		
			
				|  |  |          if (tree_it != tree->end()) {
 | 
	
		
			
				|  |  |            if (it != nullptr) *it = tree_it;
 | 
	
		
			
				|  |  |            return std::make_pair(const_iterator(tree_it, this, b), b);
 | 
	
	
		
			
				|  | @@ -729,7 +651,7 @@ class Map {
 | 
	
		
			
				|  |  |        // or whatever.  But it's probably cheap enough to recompute that here;
 | 
	
		
			
				|  |  |        // it's likely that we're inserting into an empty or short list.
 | 
	
		
			
				|  |  |        iterator result;
 | 
	
		
			
				|  |  | -      GOOGLE_DCHECK(find(*KeyPtrFromNodePtr(node)) == end());
 | 
	
		
			
				|  |  | +      GOOGLE_DCHECK(find(node->kv.first) == end());
 | 
	
		
			
				|  |  |        if (TableEntryIsEmpty(b)) {
 | 
	
		
			
				|  |  |          result = InsertUniqueInList(b, node);
 | 
	
		
			
				|  |  |        } else if (TableEntryIsNonEmptyList(b)) {
 | 
	
	
		
			
				|  | @@ -768,7 +690,7 @@ class Map {
 | 
	
		
			
				|  |  |        // Maintain the invariant that node->next is null for all Nodes in Trees.
 | 
	
		
			
				|  |  |        node->next = nullptr;
 | 
	
		
			
				|  |  |        return iterator(
 | 
	
		
			
				|  |  | -          static_cast<Tree*>(table_[b])->insert(KeyPtrFromNodePtr(node)).first,
 | 
	
		
			
				|  |  | +          static_cast<Tree*>(table_[b])->insert({node->kv.first, node}).first,
 | 
	
		
			
				|  |  |            this, b & ~static_cast<size_t>(1));
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -836,7 +758,7 @@ class Map {
 | 
	
		
			
				|  |  |        Node* node = static_cast<Node*>(table[index]);
 | 
	
		
			
				|  |  |        do {
 | 
	
		
			
				|  |  |          Node* next = node->next;
 | 
	
		
			
				|  |  | -        InsertUnique(BucketNumber(*KeyPtrFromNodePtr(node)), node);
 | 
	
		
			
				|  |  | +        InsertUnique(BucketNumber(node->kv.first), node);
 | 
	
		
			
				|  |  |          node = next;
 | 
	
		
			
				|  |  |        } while (node != nullptr);
 | 
	
		
			
				|  |  |      }
 | 
	
	
		
			
				|  | @@ -845,8 +767,8 @@ class Map {
 | 
	
		
			
				|  |  |        Tree* tree = static_cast<Tree*>(table[index]);
 | 
	
		
			
				|  |  |        typename Tree::iterator tree_it = tree->begin();
 | 
	
		
			
				|  |  |        do {
 | 
	
		
			
				|  |  | -        Node* node = NodePtrFromKeyPtr(*tree_it);
 | 
	
		
			
				|  |  | -        InsertUnique(BucketNumber(**tree_it), node);
 | 
	
		
			
				|  |  | +        InsertUnique(BucketNumber(tree_it->first),
 | 
	
		
			
				|  |  | +                     NodeFromTreeIterator(tree_it));
 | 
	
		
			
				|  |  |        } while (++tree_it != tree->end());
 | 
	
		
			
				|  |  |        DestroyTree(tree);
 | 
	
		
			
				|  |  |      }
 | 
	
	
		
			
				|  | @@ -888,15 +810,9 @@ class Map {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      void TreeConvert(size_type b) {
 | 
	
		
			
				|  |  |        GOOGLE_DCHECK(!TableEntryIsTree(b) && !TableEntryIsTree(b ^ 1));
 | 
	
		
			
				|  |  | -      typename Allocator::template rebind<Tree>::other tree_allocator(alloc_);
 | 
	
		
			
				|  |  | -      Tree* tree = tree_allocator.allocate(1);
 | 
	
		
			
				|  |  | -      // We want to use the three-arg form of construct, if it exists, but we
 | 
	
		
			
				|  |  | -      // create a temporary and use the two-arg construct that's known to exist.
 | 
	
		
			
				|  |  | -      // It's clunky, but the compiler should be able to generate more-or-less
 | 
	
		
			
				|  |  | -      // the same code.
 | 
	
		
			
				|  |  | -      tree_allocator.construct(
 | 
	
		
			
				|  |  | -          tree, Tree(typename Tree::key_compare(), KeyPtrAllocator(alloc_)));
 | 
	
		
			
				|  |  | -      // Now the tree is ready to use.
 | 
	
		
			
				|  |  | +      Tree* tree =
 | 
	
		
			
				|  |  | +          Arena::Create<Tree>(alloc_.arena(), typename Tree::key_compare(),
 | 
	
		
			
				|  |  | +                              typename Tree::allocator_type(alloc_));
 | 
	
		
			
				|  |  |        size_type count = CopyListToTree(b, tree) + CopyListToTree(b ^ 1, tree);
 | 
	
		
			
				|  |  |        GOOGLE_DCHECK_EQ(count, tree->size());
 | 
	
		
			
				|  |  |        table_[b] = table_[b ^ 1] = static_cast<void*>(tree);
 | 
	
	
		
			
				|  | @@ -908,7 +824,7 @@ class Map {
 | 
	
		
			
				|  |  |        size_type count = 0;
 | 
	
		
			
				|  |  |        Node* node = static_cast<Node*>(table_[b]);
 | 
	
		
			
				|  |  |        while (node != nullptr) {
 | 
	
		
			
				|  |  | -        tree->insert(KeyPtrFromNodePtr(node));
 | 
	
		
			
				|  |  | +        tree->insert({node->kv.first, node});
 | 
	
		
			
				|  |  |          ++count;
 | 
	
		
			
				|  |  |          Node* next = node->next;
 | 
	
		
			
				|  |  |          node->next = nullptr;
 | 
	
	
		
			
				|  | @@ -932,14 +848,12 @@ class Map {
 | 
	
		
			
				|  |  |        return count >= kMaxLength;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    size_type BucketNumber(const TrivialKey& k) const {
 | 
	
		
			
				|  |  | +    size_type BucketNumber(const Key& k) const {
 | 
	
		
			
				|  |  |        size_type h = hash_function()(k);
 | 
	
		
			
				|  |  |        return (h + seed_) & (num_buckets_ - 1);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    bool IsMatch(const TrivialKey& k0, const TrivialKey& k1) const {
 | 
	
		
			
				|  |  | -      return k0 == k1;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | +    bool IsMatch(const Key& k0, const Key& k1) const { return k0 == k1; }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      // Return a power of two no less than max(kMinTableSize, n).
 | 
	
		
			
				|  |  |      // Assumes either n < kMinTableSize or n is a power of two.
 | 
	
	
		
			
				|  | @@ -964,14 +878,15 @@ class Map {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      void DestroyNode(Node* node) {
 | 
	
		
			
				|  |  | -      alloc_.destroy(&node->kv);
 | 
	
		
			
				|  |  | -      Dealloc<Node>(node, 1);
 | 
	
		
			
				|  |  | +      if (alloc_.arena() == nullptr) {
 | 
	
		
			
				|  |  | +        delete node;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      void DestroyTree(Tree* tree) {
 | 
	
		
			
				|  |  | -      typename Allocator::template rebind<Tree>::other tree_allocator(alloc_);
 | 
	
		
			
				|  |  | -      tree_allocator.destroy(tree);
 | 
	
		
			
				|  |  | -      tree_allocator.deallocate(tree, 1);
 | 
	
		
			
				|  |  | +      if (alloc_.arena() == nullptr) {
 | 
	
		
			
				|  |  | +        delete tree;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      void** CreateEmptyTable(size_type n) {
 | 
	
	
		
			
				|  | @@ -1022,7 +937,7 @@ class Map {
 | 
	
		
			
				|  |  |      const_iterator() {}
 | 
	
		
			
				|  |  |      explicit const_iterator(const InnerIt& it) : it_(it) {}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    const_reference operator*() const { return *it_->value(); }
 | 
	
		
			
				|  |  | +    const_reference operator*() const { return *it_; }
 | 
	
		
			
				|  |  |      const_pointer operator->() const { return &(operator*()); }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      const_iterator& operator++() {
 | 
	
	
		
			
				|  | @@ -1055,7 +970,7 @@ class Map {
 | 
	
		
			
				|  |  |      iterator() {}
 | 
	
		
			
				|  |  |      explicit iterator(const InnerIt& it) : it_(it) {}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    reference operator*() const { return *it_->value(); }
 | 
	
		
			
				|  |  | +    reference operator*() const { return *it_; }
 | 
	
		
			
				|  |  |      pointer operator->() const { return &(operator*()); }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      iterator& operator++() {
 | 
	
	
		
			
				|  | @@ -1098,18 +1013,7 @@ class Map {
 | 
	
		
			
				|  |  |    bool empty() const { return size() == 0; }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    // Element access
 | 
	
		
			
				|  |  | -  T& operator[](const key_type& key) {
 | 
	
		
			
				|  |  | -    typename InnerMap::iterator it = (*elements_)[key];
 | 
	
		
			
				|  |  | -    value_type** value = &it->value();
 | 
	
		
			
				|  |  | -    if (*value == nullptr) {
 | 
	
		
			
				|  |  | -      *value = CreateValueTypeInternal(key);
 | 
	
		
			
				|  |  | -      // We need to update the key in case it's a view type.
 | 
	
		
			
				|  |  | -      it->key() = (*value)->first;
 | 
	
		
			
				|  |  | -      internal::MapValueInitializer<is_proto_enum<T>::value, T>::Initialize(
 | 
	
		
			
				|  |  | -          (*value)->second, default_enum_value_);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    return (*value)->second;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | +  T& operator[](const key_type& key) { return (*elements_)[key].second; }
 | 
	
		
			
				|  |  |    const T& at(const key_type& key) const {
 | 
	
		
			
				|  |  |      const_iterator it = find(key);
 | 
	
		
			
				|  |  |      GOOGLE_CHECK(it != end()) << "key not found: " << key;
 | 
	
	
		
			
				|  | @@ -1157,9 +1061,7 @@ class Map {
 | 
	
		
			
				|  |  |      std::pair<typename InnerMap::iterator, bool> p =
 | 
	
		
			
				|  |  |          elements_->insert(value.first);
 | 
	
		
			
				|  |  |      if (p.second) {
 | 
	
		
			
				|  |  | -      p.first->value() = CreateValueTypeInternal(value);
 | 
	
		
			
				|  |  | -      // We need to update the key in case it's a view type.
 | 
	
		
			
				|  |  | -      p.first->key() = p.first->value()->first;
 | 
	
		
			
				|  |  | +      p.first->second = value.second;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      return std::pair<iterator, bool>(iterator(p.first), p.second);
 | 
	
		
			
				|  |  |    }
 | 
	
	
		
			
				|  | @@ -1187,12 +1089,8 @@ class Map {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    iterator erase(iterator pos) {
 | 
	
		
			
				|  |  | -    value_type* value = pos.operator->();
 | 
	
		
			
				|  |  |      iterator i = pos++;
 | 
	
		
			
				|  |  |      elements_->erase(i.it_);
 | 
	
		
			
				|  |  | -    // Note: we need to delete the value after erasing from the inner map
 | 
	
		
			
				|  |  | -    // because the inner map's key may be a view of the value's key.
 | 
	
		
			
				|  |  | -    if (arena_ == nullptr) delete value;
 | 
	
		
			
				|  |  |      return pos;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    void erase(iterator first, iterator last) {
 | 
	
	
		
			
				|  | @@ -1235,32 +1133,6 @@ class Map {
 | 
	
		
			
				|  |  |      default_enum_value_ = default_enum_value;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  value_type* CreateValueTypeInternal(const Key& key) {
 | 
	
		
			
				|  |  | -    if (arena_ == nullptr) {
 | 
	
		
			
				|  |  | -      return new value_type(key);
 | 
	
		
			
				|  |  | -    } else {
 | 
	
		
			
				|  |  | -      value_type* value = reinterpret_cast<value_type*>(
 | 
	
		
			
				|  |  | -          Arena::CreateArray<uint8>(arena_, sizeof(value_type)));
 | 
	
		
			
				|  |  | -      Arena::CreateInArenaStorage(const_cast<Key*>(&value->first), arena_, key);
 | 
	
		
			
				|  |  | -      Arena::CreateInArenaStorage(&value->second, arena_);
 | 
	
		
			
				|  |  | -      return value;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  value_type* CreateValueTypeInternal(const value_type& value) {
 | 
	
		
			
				|  |  | -    if (arena_ == nullptr) {
 | 
	
		
			
				|  |  | -      return new value_type(value);
 | 
	
		
			
				|  |  | -    } else {
 | 
	
		
			
				|  |  | -      value_type* p = reinterpret_cast<value_type*>(
 | 
	
		
			
				|  |  | -          Arena::CreateArray<uint8>(arena_, sizeof(value_type)));
 | 
	
		
			
				|  |  | -      Arena::CreateInArenaStorage(const_cast<Key*>(&p->first), arena_,
 | 
	
		
			
				|  |  | -                                  value.first);
 | 
	
		
			
				|  |  | -      Arena::CreateInArenaStorage(&p->second, arena_);
 | 
	
		
			
				|  |  | -      p->second = value.second;
 | 
	
		
			
				|  |  | -      return p;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    Arena* arena_;
 | 
	
		
			
				|  |  |    int default_enum_value_;
 | 
	
		
			
				|  |  |    InnerMap* elements_;
 |