diff gcc/hash-map.h @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents 84e7813d76e9
children
line wrap: on
line diff
--- a/gcc/hash-map.h	Thu Oct 25 07:37:49 2018 +0900
+++ b/gcc/hash-map.h	Thu Feb 13 11:34:05 2020 +0900
@@ -1,5 +1,5 @@
 /* A type-safe hash map.
-   Copyright (C) 2014-2018 Free Software Foundation, Inc.
+   Copyright (C) 2014-2020 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -21,8 +21,21 @@
 #ifndef hash_map_h
 #define hash_map_h
 
+/* Class hash_map is a hash-value based container mapping objects of
+   KeyId type to those of the Value type.
+   Both KeyId and Value may be non-trivial (non-POD) types provided
+   a suitabe Traits class.  A few default Traits specializations are
+   provided for basic types such as integers, pointers, and std::pair.
+   Inserted elements are value-initialized either to zero for POD types
+   or by invoking their default ctor.  Removed elements are destroyed
+   by invoking their dtor.   On hash_map destruction all elements are
+   removed.  Objects of hash_map type are copy-constructible but not
+   assignable.  */
+
+const size_t default_hash_map_size = 13;
 template<typename KeyId, typename Value,
-	 typename Traits>
+	 typename Traits /* = simple_hashmap_traits<default_hash_traits<Key>,
+			                            Value> */>
 class GTY((user)) hash_map
 {
   typedef typename Traits::key_type Key;
@@ -53,6 +66,7 @@
        	return Traits::is_deleted (e);
       }
 
+    static const bool empty_zero_p = Traits::empty_zero_p;
     static void mark_empty (hash_entry &e) { Traits::mark_empty (e); }
     static bool is_empty (const hash_entry &e) { return Traits::is_empty (e); }
 
@@ -117,24 +131,29 @@
   };
 
 public:
-  explicit hash_map (size_t n = 13, bool ggc = false,
+  explicit hash_map (size_t n = default_hash_map_size, bool ggc = false,
+		     bool sanitize_eq_and_hash = true,
 		     bool gather_mem_stats = GATHER_STATISTICS
 		     CXX_MEM_STAT_INFO)
-    : m_table (n, ggc, gather_mem_stats, HASH_MAP_ORIGIN PASS_MEM_STAT) {}
+    : m_table (n, ggc, sanitize_eq_and_hash, gather_mem_stats,
+	       HASH_MAP_ORIGIN PASS_MEM_STAT)
+  {
+  }
 
   explicit hash_map (const hash_map &h, bool ggc = false,
+		     bool sanitize_eq_and_hash = true,
 		     bool gather_mem_stats = GATHER_STATISTICS
 		     CXX_MEM_STAT_INFO)
-    : m_table (h.m_table, ggc, gather_mem_stats,
+    : m_table (h.m_table, ggc, sanitize_eq_and_hash, gather_mem_stats,
 	       HASH_MAP_ORIGIN PASS_MEM_STAT) {}
 
   /* Create a hash_map in ggc memory.  */
-  static hash_map *create_ggc (size_t size,
+  static hash_map *create_ggc (size_t size = default_hash_map_size,
 			       bool gather_mem_stats = GATHER_STATISTICS
 			       CXX_MEM_STAT_INFO)
     {
       hash_map *map = ggc_alloc<hash_map> ();
-      new (map) hash_map (size, true, gather_mem_stats PASS_MEM_STAT);
+      new (map) hash_map (size, true, true, gather_mem_stats PASS_MEM_STAT);
       return map;
     }
 
@@ -146,12 +165,16 @@
     {
       hash_entry *e = m_table.find_slot_with_hash (k, Traits::hash (k),
 						   INSERT);
-      bool existed = !hash_entry::is_empty (*e);
-      if (!existed)
-	e->m_key = k;
+      bool ins = hash_entry::is_empty (*e);
+      if (ins)
+	{
+	  e->m_key = k;
+	  new ((void *) &e->m_value) Value (v);
+	}
+      else
+	e->m_value = v;
 
-      e->m_value = v;
-      return existed;
+      return !ins;
     }
 
   /* if the passed in key is in the map return its value otherwise NULL.  */
@@ -163,8 +186,8 @@
     }
 
   /* Return a reference to the value for the passed in key, creating the entry
-     if it doesn't already exist.  If existed is not NULL then it is set to false
-     if the key was not previously in the map, and true otherwise.  */
+     if it doesn't already exist.  If existed is not NULL then it is set to
+     false if the key was not previously in the map, and true otherwise.  */
 
   Value &get_or_insert (const Key &k, bool *existed = NULL)
     {
@@ -172,7 +195,10 @@
 						   INSERT);
       bool ins = Traits::is_empty (*e);
       if (ins)
-	e->m_key = k;
+	{
+	  e->m_key = k;
+	  new ((void *)&e->m_value) Value ();
+	}
 
       if (existed != NULL)
 	*existed = !ins;
@@ -211,6 +237,9 @@
 
   void empty () { m_table.empty(); }
 
+  /* Return true when there are no elements in this hash map.  */
+  bool is_empty () const { return m_table.is_empty (); }
+
   class iterator
   {
   public:
@@ -223,10 +252,24 @@
       return *this;
     }
 
-    std::pair<const Key&, Value&> operator* ()
+    /* Can't use std::pair here, because GCC before 4.3 don't handle
+       std::pair where template parameters are references well.
+       See PR86739.  */
+    class reference_pair {
+    public:
+      const Key &first;
+      Value &second;
+
+      reference_pair (const Key &key, Value &value) : first (key), second (value) {}
+
+      template <typename K, typename V>
+      operator std::pair<K, V> () const { return std::pair<K, V> (first, second); }
+    };
+
+    reference_pair operator* ()
     {
       hash_entry &e = *m_iter;
-      return std::pair<const Key&, Value&> (e.m_key, e.m_value);
+      return reference_pair (e.m_key, e.m_value);
     }
 
     bool
@@ -285,4 +328,46 @@
   op (&h->m_table.m_entries, cookie);
 }
 
+enum hm_alloc { hm_heap = false, hm_ggc = true };
+template<bool ggc, typename K, typename V, typename H>
+inline hash_map<K,V,H> *
+hash_map_maybe_create (hash_map<K,V,H> *&h,
+		       size_t size = default_hash_map_size)
+{
+  if (!h)
+    {
+      if (ggc)
+	h = hash_map<K,V,H>::create_ggc (size);
+      else
+	h = new hash_map<K,V,H> (size);
+    }
+  return h;
+}
+
+/* Like h->get, but handles null h.  */
+template<typename K, typename V, typename H>
+inline V*
+hash_map_safe_get (hash_map<K,V,H> *h, const K& k)
+{
+  return h ? h->get (k) : NULL;
+}
+
+/* Like h->get, but handles null h.  */
+template<bool ggc, typename K, typename V, typename H>
+inline V&
+hash_map_safe_get_or_insert (hash_map<K,V,H> *&h, const K& k, bool *e = NULL,
+			     size_t size = default_hash_map_size)
+{
+  return hash_map_maybe_create<ggc> (h, size)->get_or_insert (k, e);
+}
+
+/* Like h->put, but handles null h.  */
+template<bool ggc, typename K, typename V, typename H>
+inline bool
+hash_map_safe_put (hash_map<K,V,H> *&h, const K& k, const V& v,
+		   size_t size = default_hash_map_size)
+{
+  return hash_map_maybe_create<ggc> (h, size)->put (k, v);
+}
+
 #endif