• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

GNU Binutils with patches for OS216


Commit MetaInfo

Revision3286a5fda95c1f1988fdecf0f542a0e58d1f4e27 (tree)
Time2019-09-25 09:53:35
AuthorChristian Biesinger <cbiesinger@goog...>
CommiterChristian Biesinger

Log Message

Fork GCC's hash-table.h for use in GDB

And use it at one callsite in dwarf2read.

Change Summary

Incremental Difference

--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -1037,6 +1037,7 @@ COMMON_SFILES = \
10371037 go-lang.c \
10381038 go-typeprint.c \
10391039 go-valprint.c \
1040+ hash-table.c \
10401041 inf-child.c \
10411042 inf-loop.c \
10421043 infcall.c \
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -90,6 +90,7 @@
9090 #include <forward_list>
9191 #include "rust-lang.h"
9292 #include "gdbsupport/pathstuff.h"
93+#include "hash-map.h"
9394
9495 /* When == 1, print basic high level tracing messages.
9596 When > 1, be more verbose.
@@ -5076,12 +5077,8 @@ dw_expand_symtabs_matching_file_matcher
50765077
50775078 objfile *const objfile = dwarf2_per_objfile->objfile;
50785079
5079- htab_up visited_found (htab_create_alloc (10, htab_hash_pointer,
5080- htab_eq_pointer,
5081- NULL, xcalloc, xfree));
5082- htab_up visited_not_found (htab_create_alloc (10, htab_hash_pointer,
5083- htab_eq_pointer,
5084- NULL, xcalloc, xfree));
5080+ hash_table<nofree_ptr_hash <quick_file_names>> visited_found (10);
5081+ hash_table<nofree_ptr_hash <quick_file_names>> visited_not_found (10);
50855082
50865083 /* The rule is CUs specify all the files, including those used by
50875084 any TU, so there's no need to scan TUs here. */
@@ -5100,9 +5097,9 @@ dw_expand_symtabs_matching_file_matcher
51005097 if (file_data == NULL)
51015098 continue;
51025099
5103- if (htab_find (visited_not_found.get (), file_data) != NULL)
5100+ if (visited_not_found.find_slot (file_data, NO_INSERT) != NULL)
51045101 continue;
5105- else if (htab_find (visited_found.get (), file_data) != NULL)
5102+ else if (visited_found.find_slot (file_data, NO_INSERT) != NULL)
51065103 {
51075104 per_cu->v.quick->mark = 1;
51085105 continue;
@@ -5132,12 +5129,10 @@ dw_expand_symtabs_matching_file_matcher
51325129 break;
51335130 }
51345131 }
5135-
5136- void **slot = htab_find_slot (per_cu->v.quick->mark
5137- ? visited_found.get ()
5138- : visited_not_found.get (),
5139- file_data, INSERT);
5140- *slot = file_data;
5132+ if (per_cu->v.quick->mark)
5133+ *visited_found.find_slot (file_data, INSERT) = file_data;
5134+ else
5135+ *visited_not_found.find_slot (file_data, INSERT) = file_data;
51415136 }
51425137 }
51435138
--- /dev/null
+++ b/gdb/hash-map-traits.h
@@ -0,0 +1,188 @@
1+/* A hash map traits.
2+ Copyright (C) 2015-2019 Free Software Foundation, Inc.
3+
4+This file is part of GCC.
5+
6+GCC is free software; you can redistribute it and/or modify it under
7+the terms of the GNU General Public License as published by the Free
8+Software Foundation; either version 3, or (at your option) any later
9+version.
10+
11+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12+WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+for more details.
15+
16+You should have received a copy of the GNU General Public License
17+along with GCC; see the file COPYING3. If not see
18+<http://www.gnu.org/licenses/>. */
19+
20+#ifndef HASH_MAP_TRAITS_H
21+#define HASH_MAP_TRAITS_H
22+
23+/* Bacause mem-stats.h uses default hashmap traits, we have to
24+ put the class to this separate header file. */
25+
26+#include "hash-traits.h"
27+
28+/* Implement hash_map traits for a key with hash traits H. Empty and
29+ deleted map entries are represented as empty and deleted keys. */
30+
31+template <typename H, typename Value>
32+struct simple_hashmap_traits
33+{
34+ typedef typename H::value_type key_type;
35+ static const bool maybe_mx = true;
36+ static inline hashval_t hash (const key_type &);
37+ static inline bool equal_keys (const key_type &, const key_type &);
38+ template <typename T> static inline void remove (T &);
39+ template <typename T> static inline bool is_empty (const T &);
40+ template <typename T> static inline bool is_deleted (const T &);
41+ template <typename T> static inline void mark_empty (T &);
42+ template <typename T> static inline void mark_deleted (T &);
43+};
44+
45+template <typename H, typename Value>
46+inline hashval_t
47+simple_hashmap_traits <H, Value>::hash (const key_type &h)
48+{
49+ return H::hash (h);
50+}
51+
52+template <typename H, typename Value>
53+inline bool
54+simple_hashmap_traits <H, Value>::equal_keys (const key_type &k1,
55+ const key_type &k2)
56+{
57+ return H::equal (k1, k2);
58+}
59+
60+template <typename H, typename Value>
61+template <typename T>
62+inline void
63+simple_hashmap_traits <H, Value>::remove (T &entry)
64+{
65+ H::remove (entry.m_key);
66+ entry.m_value.~Value ();
67+}
68+
69+template <typename H, typename Value>
70+template <typename T>
71+inline bool
72+simple_hashmap_traits <H, Value>::is_empty (const T &entry)
73+{
74+ return H::is_empty (entry.m_key);
75+}
76+
77+template <typename H, typename Value>
78+template <typename T>
79+inline bool
80+simple_hashmap_traits <H, Value>::is_deleted (const T &entry)
81+{
82+ return H::is_deleted (entry.m_key);
83+}
84+
85+template <typename H, typename Value>
86+template <typename T>
87+inline void
88+simple_hashmap_traits <H, Value>::mark_empty (T &entry)
89+{
90+ H::mark_empty (entry.m_key);
91+}
92+
93+template <typename H, typename Value>
94+template <typename T>
95+inline void
96+simple_hashmap_traits <H, Value>::mark_deleted (T &entry)
97+{
98+ H::mark_deleted (entry.m_key);
99+}
100+
101+template <typename H, typename Value>
102+struct simple_cache_map_traits: public simple_hashmap_traits<H,Value>
103+{
104+ static const bool maybe_mx = false;
105+};
106+
107+/* Implement traits for a hash_map with values of type Value for cases
108+ in which the key cannot represent empty and deleted slots. Instead
109+ record empty and deleted entries in Value. Derived classes must
110+ implement the hash and equal_keys functions. */
111+
112+template <typename Value>
113+struct unbounded_hashmap_traits
114+{
115+ template <typename T> static inline void remove (T &);
116+ template <typename T> static inline bool is_empty (const T &);
117+ template <typename T> static inline bool is_deleted (const T &);
118+ template <typename T> static inline void mark_empty (T &);
119+ template <typename T> static inline void mark_deleted (T &);
120+};
121+
122+template <typename Value>
123+template <typename T>
124+inline void
125+unbounded_hashmap_traits <Value>::remove (T &entry)
126+{
127+ default_hash_traits <Value>::remove (entry.m_value);
128+}
129+
130+template <typename Value>
131+template <typename T>
132+inline bool
133+unbounded_hashmap_traits <Value>::is_empty (const T &entry)
134+{
135+ return default_hash_traits <Value>::is_empty (entry.m_value);
136+}
137+
138+template <typename Value>
139+template <typename T>
140+inline bool
141+unbounded_hashmap_traits <Value>::is_deleted (const T &entry)
142+{
143+ return default_hash_traits <Value>::is_deleted (entry.m_value);
144+}
145+
146+template <typename Value>
147+template <typename T>
148+inline void
149+unbounded_hashmap_traits <Value>::mark_empty (T &entry)
150+{
151+ default_hash_traits <Value>::mark_empty (entry.m_value);
152+}
153+
154+template <typename Value>
155+template <typename T>
156+inline void
157+unbounded_hashmap_traits <Value>::mark_deleted (T &entry)
158+{
159+ default_hash_traits <Value>::mark_deleted (entry.m_value);
160+}
161+
162+/* Implement traits for a hash_map from integer type Key to Value in
163+ cases where Key has no spare values for recording empty and deleted
164+ slots. */
165+
166+template <typename Key, typename Value>
167+struct unbounded_int_hashmap_traits : unbounded_hashmap_traits <Value>
168+{
169+ typedef Key key_type;
170+ static inline hashval_t hash (Key);
171+ static inline bool equal_keys (Key, Key);
172+};
173+
174+template <typename Key, typename Value>
175+inline hashval_t
176+unbounded_int_hashmap_traits <Key, Value>::hash (Key k)
177+{
178+ return k;
179+}
180+
181+template <typename Key, typename Value>
182+inline bool
183+unbounded_int_hashmap_traits <Key, Value>::equal_keys (Key k1, Key k2)
184+{
185+ return k1 == k2;
186+}
187+
188+#endif // HASH_MAP_TRAITS_H
--- /dev/null
+++ b/gdb/hash-map.h
@@ -0,0 +1,220 @@
1+/* A type-safe hash map.
2+ Copyright (C) 2014-2019 Free Software Foundation, Inc.
3+
4+This file is part of GCC.
5+
6+GCC is free software; you can redistribute it and/or modify it under
7+the terms of the GNU General Public License as published by the Free
8+Software Foundation; either version 3, or (at your option) any later
9+version.
10+
11+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12+WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+for more details.
15+
16+You should have received a copy of the GNU General Public License
17+along with GCC; see the file COPYING3. If not see
18+<http://www.gnu.org/licenses/>. */
19+
20+
21+#ifndef hash_map_h
22+#define hash_map_h
23+
24+#include "hash-table.h"
25+
26+/* Class hash_map is a hash-value based container mapping objects of
27+ KeyId type to those of the Value type.
28+ Both KeyId and Value may be non-trivial (non-POD) types provided
29+ a suitabe Traits class. A few default Traits specializations are
30+ provided for basic types such as integers, pointers, and std::pair.
31+ Inserted elements are value-initialized either to zero for POD types
32+ or by invoking their default ctor. Removed elements are destroyed
33+ by invoking their dtor. On hash_map destruction all elements are
34+ removed. Objects of hash_map type are copy-constructible but not
35+ assignable. */
36+
37+template<typename KeyId, typename Value,
38+ typename Traits /* = simple_hashmap_traits<default_hash_traits<Key>,
39+ Value> */>
40+class hash_map
41+{
42+ typedef typename Traits::key_type Key;
43+ struct hash_entry
44+ {
45+ Key m_key;
46+ Value m_value;
47+
48+ typedef hash_entry value_type;
49+ typedef Key compare_type;
50+
51+ static hashval_t hash (const hash_entry &e)
52+ {
53+ return Traits::hash (e.m_key);
54+ }
55+
56+ static bool equal (const hash_entry &a, const Key &b)
57+ {
58+ return Traits::equal_keys (a.m_key, b);
59+ }
60+
61+ static void remove (hash_entry &e) { Traits::remove (e); }
62+
63+ static void mark_deleted (hash_entry &e) { Traits::mark_deleted (e); }
64+
65+ static bool is_deleted (const hash_entry &e)
66+ {
67+ return Traits::is_deleted (e);
68+ }
69+
70+ static void mark_empty (hash_entry &e) { Traits::mark_empty (e); }
71+ static bool is_empty (const hash_entry &e) { return Traits::is_empty (e); }
72+ };
73+
74+public:
75+ explicit hash_map (size_t n = 13,
76+ bool sanitize_eq_and_hash = true)
77+ : m_table (n, sanitize_eq_and_hash)
78+ {
79+ }
80+
81+ explicit hash_map (const hash_map &h,
82+ bool sanitize_eq_and_hash = true)
83+ : m_table (h.m_table, sanitize_eq_and_hash) {}
84+
85+ /* If key k isn't already in the map add key k with value v to the map, and
86+ return false. Otherwise set the value of the entry for key k to be v and
87+ return true. */
88+
89+ bool put (const Key &k, const Value &v)
90+ {
91+ hash_entry *e = m_table.find_slot_with_hash (k, Traits::hash (k),
92+ INSERT);
93+ bool ins = hash_entry::is_empty (*e);
94+ if (ins)
95+ {
96+ e->m_key = k;
97+ new ((void *) &e->m_value) Value (v);
98+ }
99+ else
100+ e->m_value = v;
101+
102+ return !ins;
103+ }
104+
105+ /* if the passed in key is in the map return its value otherwise NULL. */
106+
107+ Value *get (const Key &k)
108+ {
109+ hash_entry &e = m_table.find_with_hash (k, Traits::hash (k));
110+ return Traits::is_empty (e) ? NULL : &e.m_value;
111+ }
112+
113+ /* Return a reference to the value for the passed in key, creating the entry
114+ if it doesn't already exist. If existed is not NULL then it is set to
115+ false if the key was not previously in the map, and true otherwise. */
116+
117+ Value &get_or_insert (const Key &k, bool *existed = NULL)
118+ {
119+ hash_entry *e = m_table.find_slot_with_hash (k, Traits::hash (k),
120+ INSERT);
121+ bool ins = Traits::is_empty (*e);
122+ if (ins)
123+ {
124+ e->m_key = k;
125+ new ((void *)&e->m_value) Value ();
126+ }
127+
128+ if (existed != NULL)
129+ *existed = !ins;
130+
131+ return e->m_value;
132+ }
133+
134+ void remove (const Key &k)
135+ {
136+ m_table.remove_elt_with_hash (k, Traits::hash (k));
137+ }
138+
139+ /* Call the call back on each pair of key and value with the passed in
140+ arg. */
141+
142+ template<typename Arg, bool (*f)(const typename Traits::key_type &,
143+ const Value &, Arg)>
144+ void traverse (Arg a) const
145+ {
146+ for (typename hash_table<hash_entry>::iterator iter = m_table.begin ();
147+ iter != m_table.end (); ++iter)
148+ f ((*iter).m_key, (*iter).m_value, a);
149+ }
150+
151+ template<typename Arg, bool (*f)(const typename Traits::key_type &,
152+ Value *, Arg)>
153+ void traverse (Arg a) const
154+ {
155+ for (typename hash_table<hash_entry>::iterator iter = m_table.begin ();
156+ iter != m_table.end (); ++iter)
157+ if (!f ((*iter).m_key, &(*iter).m_value, a))
158+ break;
159+ }
160+
161+ size_t elements () const { return m_table.elements (); }
162+
163+ void empty () { m_table.empty(); }
164+
165+ /* Return true when there are no elements in this hash map. */
166+ bool is_empty () const { return m_table.is_empty (); }
167+
168+ class iterator
169+ {
170+ public:
171+ explicit iterator (const typename hash_table<hash_entry>::iterator &iter) :
172+ m_iter (iter) {}
173+
174+ iterator &operator++ ()
175+ {
176+ ++m_iter;
177+ return *this;
178+ }
179+
180+ /* Can't use std::pair here, because GCC before 4.3 don't handle
181+ std::pair where template parameters are references well.
182+ See PR86739. */
183+ class reference_pair {
184+ public:
185+ const Key &first;
186+ Value &second;
187+
188+ reference_pair (const Key &key, Value &value) : first (key), second (value) {}
189+
190+ template <typename K, typename V>
191+ operator std::pair<K, V> () const { return std::pair<K, V> (first, second); }
192+ };
193+
194+ reference_pair operator* ()
195+ {
196+ hash_entry &e = *m_iter;
197+ return reference_pair (e.m_key, e.m_value);
198+ }
199+
200+ bool
201+ operator != (const iterator &other) const
202+ {
203+ return m_iter != other.m_iter;
204+ }
205+
206+ private:
207+ typename hash_table<hash_entry>::iterator m_iter;
208+ };
209+
210+ /* Standard iterator retrieval methods. */
211+
212+ iterator begin () const { return iterator (m_table.begin ()); }
213+ iterator end () const { return iterator (m_table.end ()); }
214+
215+private:
216+
217+ hash_table<hash_entry> m_table;
218+};
219+
220+#endif
--- /dev/null
+++ b/gdb/hash-table.c
@@ -0,0 +1,97 @@
1+/* A type-safe hash table template.
2+ Copyright (C) 2012-2019 Free Software Foundation, Inc.
3+ Contributed by Lawrence Crowl <crowl@google.com>
4+
5+This file is part of GCC.
6+
7+GCC is free software; you can redistribute it and/or modify it under
8+the terms of the GNU General Public License as published by the Free
9+Software Foundation; either version 3, or (at your option) any later
10+version.
11+
12+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13+WARRANTY; without even the implied warranty of MERCHANTABILITY or
14+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15+for more details.
16+
17+You should have received a copy of the GNU General Public License
18+along with GCC; see the file COPYING3. If not see
19+<http://www.gnu.org/licenses/>. */
20+
21+
22+/* This file implements a typed hash table.
23+ The implementation borrows from libiberty's hashtab. */
24+
25+#include "defs.h"
26+#include "gdbtypes.h"
27+#include "hash-table.h"
28+
29+/* Table of primes and multiplicative inverses.
30+
31+ Note that these are not minimally reduced inverses. Unlike when generating
32+ code to divide by a constant, we want to be able to use the same algorithm
33+ all the time. All of these inverses (are implied to) have bit 32 set.
34+
35+ For the record, here's the function that computed the table; it's a
36+ vastly simplified version of the function of the same name from gcc. */
37+
38+struct prime_ent const prime_tab[] = {
39+ { 7, 0x24924925, 0x9999999b, 2 },
40+ { 13, 0x3b13b13c, 0x745d1747, 3 },
41+ { 31, 0x08421085, 0x1a7b9612, 4 },
42+ { 61, 0x0c9714fc, 0x15b1e5f8, 5 },
43+ { 127, 0x02040811, 0x0624dd30, 6 },
44+ { 251, 0x05197f7e, 0x073260a5, 7 },
45+ { 509, 0x01824366, 0x02864fc8, 8 },
46+ { 1021, 0x00c0906d, 0x014191f7, 9 },
47+ { 2039, 0x0121456f, 0x0161e69e, 10 },
48+ { 4093, 0x00300902, 0x00501908, 11 },
49+ { 8191, 0x00080041, 0x00180241, 12 },
50+ { 16381, 0x000c0091, 0x00140191, 13 },
51+ { 32749, 0x002605a5, 0x002a06e6, 14 },
52+ { 65521, 0x000f00e2, 0x00110122, 15 },
53+ { 131071, 0x00008001, 0x00018003, 16 },
54+ { 262139, 0x00014002, 0x0001c004, 17 },
55+ { 524287, 0x00002001, 0x00006001, 18 },
56+ { 1048573, 0x00003001, 0x00005001, 19 },
57+ { 2097143, 0x00004801, 0x00005801, 20 },
58+ { 4194301, 0x00000c01, 0x00001401, 21 },
59+ { 8388593, 0x00001e01, 0x00002201, 22 },
60+ { 16777213, 0x00000301, 0x00000501, 23 },
61+ { 33554393, 0x00001381, 0x00001481, 24 },
62+ { 67108859, 0x00000141, 0x000001c1, 25 },
63+ { 134217689, 0x000004e1, 0x00000521, 26 },
64+ { 268435399, 0x00000391, 0x000003b1, 27 },
65+ { 536870909, 0x00000019, 0x00000029, 28 },
66+ { 1073741789, 0x0000008d, 0x00000095, 29 },
67+ { 2147483647, 0x00000003, 0x00000007, 30 },
68+ /* Avoid "decimal constant so large it is unsigned" for 4294967291. */
69+ { 0xfffffffb, 0x00000006, 0x00000008, 31 }
70+};
71+
72+/* Limit number of comparisons when calling hash_table<>::verify. */
73+unsigned int hash_table_sanitize_eq_limit;
74+
75+/* The following function returns an index into the above table of the
76+ nearest prime number which is greater than N, and near a power of two. */
77+
78+unsigned int
79+hash_table_higher_prime_index (unsigned long n)
80+{
81+ unsigned int low = 0;
82+ unsigned int high = sizeof (prime_tab) / sizeof (prime_tab[0]);
83+
84+ while (low != high)
85+ {
86+ unsigned int mid = low + (high - low) / 2;
87+ if (n > prime_tab[mid].prime)
88+ low = mid + 1;
89+ else
90+ high = mid;
91+ }
92+
93+ /* If we've run out of primes, abort. */
94+ gdb_assert (n <= prime_tab[low].prime);
95+
96+ return low;
97+}
--- /dev/null
+++ b/gdb/hash-table.h
@@ -0,0 +1,1038 @@
1+/* A type-safe hash table template.
2+ Copyright (C) 2012-2019 Free Software Foundation, Inc.
3+ Contributed by Lawrence Crowl <crowl@google.com>
4+
5+This file is part of GDB. It was forked from GCC.
6+
7+GCC is free software; you can redistribute it and/or modify it under
8+the terms of the GNU General Public License as published by the Free
9+Software Foundation; either version 3, or (at your option) any later
10+version.
11+
12+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13+WARRANTY; without even the implied warranty of MERCHANTABILITY or
14+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15+for more details.
16+
17+You should have received a copy of the GNU General Public License
18+along with GCC; see the file COPYING3. If not see
19+<http://www.gnu.org/licenses/>. */
20+
21+
22+/* This file implements a typed hash table.
23+ The implementation borrows from libiberty's htab_t in hashtab.h.
24+
25+
26+ INTRODUCTION TO TYPES
27+
28+ Users of the hash table generally need to be aware of three types.
29+
30+ 1. The type being placed into the hash table. This type is called
31+ the value type.
32+
33+ 2. The type used to describe how to handle the value type within
34+ the hash table. This descriptor type provides the hash table with
35+ several things.
36+
37+ - A typedef named 'value_type' to the value type (from above).
38+ Provided a suitable Descriptor class it may be a user-defined,
39+ non-POD type.
40+
41+ - A static member function named 'hash' that takes a value_type
42+ (or 'const value_type &') and returns a hashval_t value.
43+
44+ - A typedef named 'compare_type' that is used to test when a value
45+ is found. This type is the comparison type. Usually, it will be
46+ the same as value_type and may be a user-defined, non-POD type.
47+ If it is not the same type, you must generally explicitly compute
48+ hash values and pass them to the hash table.
49+
50+ - A static member function named 'equal' that takes a value_type
51+ and a compare_type, and returns a bool. Both arguments can be
52+ const references.
53+
54+ - A static function named 'remove' that takes an value_type pointer
55+ and frees the memory allocated by it. This function is used when
56+ individual elements of the table need to be disposed of (e.g.,
57+ when deleting a hash table, removing elements from the table, etc).
58+
59+ - An optional static function named 'keep_cache_entry'. This
60+ function is provided only for garbage-collected elements that
61+ are not marked by the normal gc mark pass. It describes what
62+ what should happen to the element at the end of the gc mark phase.
63+ The return value should be:
64+ - 0 if the element should be deleted
65+ - 1 if the element should be kept and needs to be marked
66+ - -1 if the element should be kept and is already marked.
67+ Returning -1 rather than 1 is purely an optimization.
68+
69+ 3. The type of the hash table itself. (More later.)
70+
71+ In very special circumstances, users may need to know about a fourth type.
72+
73+ 4. The template type used to describe how hash table memory
74+ is allocated. This type is called the allocator type. It is
75+ parameterized on the value type. It provides two functions:
76+
77+ - A static member function named 'data_alloc'. This function
78+ allocates the data elements in the table.
79+
80+ - A static member function named 'data_free'. This function
81+ deallocates the data elements in the table.
82+
83+ Hash table are instantiated with two type arguments.
84+
85+ * The descriptor type, (2) above.
86+
87+ * The allocator type, (4) above. In general, you will not need to
88+ provide your own allocator type. By default, hash tables will use
89+ the class template xcallocator, which uses malloc/free for allocation.
90+
91+
92+ DEFINING A DESCRIPTOR TYPE
93+
94+ The first task in using the hash table is to describe the element type.
95+ We compose this into a few steps.
96+
97+ 1. Decide on a removal policy for values stored in the table.
98+ hash-traits.h provides class templates for the four most common
99+ policies:
100+
101+ * typed_free_remove implements the static 'remove' member function
102+ by calling free().
103+
104+ * typed_noop_remove implements the static 'remove' member function
105+ by doing nothing.
106+
107+ You can use these policies by simply deriving the descriptor type
108+ from one of those class template, with the appropriate argument.
109+
110+ Otherwise, you need to write the static 'remove' member function
111+ in the descriptor class.
112+
113+ 2. Choose a hash function. Write the static 'hash' member function.
114+
115+ 3. Decide whether the lookup function should take as input an object
116+ of type value_type or something more restricted. Define compare_type
117+ accordingly.
118+
119+ 4. Choose an equality testing function 'equal' that compares a value_type
120+ and a compare_type.
121+
122+ If your elements are pointers, it is usually easiest to start with one
123+ of the generic pointer descriptors described below and override the bits
124+ you need to change.
125+
126+ AN EXAMPLE DESCRIPTOR TYPE
127+
128+ Suppose you want to put some_type into the hash table. You could define
129+ the descriptor type as follows.
130+
131+ struct some_type_hasher : nofree_ptr_hash <some_type>
132+ // Deriving from nofree_ptr_hash means that we get a 'remove' that does
133+ // nothing. This choice is good for raw values.
134+ {
135+ static inline hashval_t hash (const value_type *);
136+ static inline bool equal (const value_type *, const compare_type *);
137+ };
138+
139+ inline hashval_t
140+ some_type_hasher::hash (const value_type *e)
141+ { ... compute and return a hash value for E ... }
142+
143+ inline bool
144+ some_type_hasher::equal (const value_type *p1, const compare_type *p2)
145+ { ... compare P1 vs P2. Return true if they are the 'same' ... }
146+
147+
148+ AN EXAMPLE HASH_TABLE DECLARATION
149+
150+ To instantiate a hash table for some_type:
151+
152+ hash_table <some_type_hasher> some_type_hash_table;
153+
154+ There is no need to mention some_type directly, as the hash table will
155+ obtain it using some_type_hasher::value_type.
156+
157+ You can then use any of the functions in hash_table's public interface.
158+ See hash_table for details. The interface is very similar to libiberty's
159+ htab_t.
160+
161+ If a hash table is used only in some rare cases, it is possible
162+ to construct the hash_table lazily before first use. This is done
163+ through:
164+
165+ hash_table <some_type_hasher, true> some_type_hash_table;
166+
167+ which will cause whatever methods actually need the allocated entries
168+ array to allocate it later.
169+
170+
171+ EASY DESCRIPTORS FOR POINTERS
172+
173+ There are four descriptors for pointer elements, one for each of
174+ the removal policies above:
175+
176+ * nofree_ptr_hash (based on typed_noop_remove)
177+ * free_ptr_hash (based on typed_free_remove)
178+
179+ These descriptors hash and compare elements by their pointer value,
180+ rather than what they point to. So, to instantiate a hash table over
181+ pointers to whatever_type, without freeing the whatever_types, use:
182+
183+ hash_table <nofree_ptr_hash <whatever_type> > whatever_type_hash_table;
184+
185+
186+ HASH TABLE ITERATORS
187+
188+ The hash table provides standard C++ iterators. For example, consider a
189+ hash table of some_info. We wish to consume each element of the table:
190+
191+ extern void consume (some_info *);
192+
193+ We define a convenience typedef and the hash table:
194+
195+ typedef hash_table <some_info_hasher> info_table_type;
196+ info_table_type info_table;
197+
198+ Then we write the loop in typical C++ style:
199+
200+ for (info_table_type::iterator iter = info_table.begin ();
201+ iter != info_table.end ();
202+ ++iter)
203+ if ((*iter).status == INFO_READY)
204+ consume (&*iter);
205+
206+ Or with common sub-expression elimination:
207+
208+ for (info_table_type::iterator iter = info_table.begin ();
209+ iter != info_table.end ();
210+ ++iter)
211+ {
212+ some_info &elem = *iter;
213+ if (elem.status == INFO_READY)
214+ consume (&elem);
215+ }
216+
217+ One can also use a more typical GCC style:
218+
219+ typedef some_info *some_info_p;
220+ some_info *elem_ptr;
221+ info_table_type::iterator iter;
222+ FOR_EACH_HASH_TABLE_ELEMENT (info_table, elem_ptr, some_info_p, iter)
223+ if (elem_ptr->status == INFO_READY)
224+ consume (elem_ptr);
225+
226+*/
227+
228+
229+#ifndef TYPED_HASHTAB_H
230+#define TYPED_HASHTAB_H
231+
232+#include "hashtab.h"
233+#include "hash-traits.h"
234+#include "hash-map-traits.h"
235+
236+template<typename, typename, typename> class hash_map;
237+template<typename, bool, typename> class hash_set;
238+
239+/* The ordinary memory allocator. */
240+/* FIXME (crowl): This allocator may be extracted for wider sharing later. */
241+
242+template <typename Type>
243+struct xcallocator
244+{
245+ static Type *data_alloc (size_t count);
246+ static void data_free (Type *memory);
247+};
248+
249+
250+/* Allocate memory for COUNT data blocks. */
251+
252+template <typename Type>
253+inline Type *
254+xcallocator <Type>::data_alloc (size_t count)
255+{
256+ return static_cast <Type *> (xcalloc (count, sizeof (Type)));
257+}
258+
259+
260+/* Free memory for data blocks. */
261+
262+template <typename Type>
263+inline void
264+xcallocator <Type>::data_free (Type *memory)
265+{
266+ return ::free (memory);
267+}
268+
269+
270+/* Table of primes and their inversion information. */
271+
272+struct prime_ent
273+{
274+ hashval_t prime;
275+ hashval_t inv;
276+ hashval_t inv_m2; /* inverse of prime-2 */
277+ hashval_t shift;
278+};
279+
280+extern struct prime_ent const prime_tab[];
281+
282+/* Limit number of comparisons when calling hash_table<>::verify. */
283+extern unsigned int hash_table_sanitize_eq_limit;
284+
285+/* Functions for computing hash table indexes. */
286+
287+extern unsigned int hash_table_higher_prime_index (unsigned long n)
288+ ATTRIBUTE_PURE;
289+
290+extern ATTRIBUTE_NORETURN ATTRIBUTE_COLD void hashtab_chk_error ();
291+
292+/* Return X % Y using multiplicative inverse values INV and SHIFT.
293+
294+ The multiplicative inverses computed above are for 32-bit types,
295+ and requires that we be able to compute a highpart multiply.
296+
297+ FIX: I am not at all convinced that
298+ 3 loads, 2 multiplications, 3 shifts, and 3 additions
299+ will be faster than
300+ 1 load and 1 modulus
301+ on modern systems running a compiler. */
302+
303+inline hashval_t
304+mul_mod (hashval_t x, hashval_t y, hashval_t inv, int shift)
305+{
306+ hashval_t t1, t2, t3, t4, q, r;
307+
308+ t1 = ((uint64_t)x * inv) >> 32;
309+ t2 = x - t1;
310+ t3 = t2 >> 1;
311+ t4 = t1 + t3;
312+ q = t4 >> shift;
313+ r = x - (q * y);
314+
315+ return r;
316+}
317+
318+/* Compute the primary table index for HASH given current prime index. */
319+
320+inline hashval_t
321+hash_table_mod1 (hashval_t hash, unsigned int index)
322+{
323+ const struct prime_ent *p = &prime_tab[index];
324+ gdb_assert (sizeof (hashval_t) * CHAR_BIT <= 32);
325+ return mul_mod (hash, p->prime, p->inv, p->shift);
326+}
327+
328+/* Compute the secondary table index for HASH given current prime index. */
329+
330+inline hashval_t
331+hash_table_mod2 (hashval_t hash, unsigned int index)
332+{
333+ const struct prime_ent *p = &prime_tab[index];
334+ gdb_assert (sizeof (hashval_t) * CHAR_BIT <= 32);
335+ return 1 + mul_mod (hash, p->prime - 2, p->inv_m2, p->shift);
336+}
337+
338+class mem_usage;
339+
340+/* User-facing hash table type.
341+
342+ The table stores elements of type Descriptor::value_type and uses
343+ the static descriptor functions described at the top of the file
344+ to hash, compare and remove elements.
345+
346+ Specify the template Allocator to allocate and free memory.
347+ The default is xcallocator.
348+
349+ Storage is an implementation detail and should not be used outside the
350+ hash table code.
351+
352+*/
353+template <typename Descriptor, bool Lazy = false,
354+ template<typename Type> class Allocator = xcallocator>
355+class hash_table
356+{
357+ typedef typename Descriptor::value_type value_type;
358+ typedef typename Descriptor::compare_type compare_type;
359+
360+public:
361+ explicit hash_table (size_t,
362+ bool sanitize_eq_and_hash = true);
363+ explicit hash_table (const hash_table &,
364+ bool sanitize_eq_and_hash = true);
365+ ~hash_table ();
366+
367+ /* Current size (in entries) of the hash table. */
368+ size_t size () const { return m_size; }
369+
370+ /* Return the current number of elements in this hash table. */
371+ size_t elements () const { return m_n_elements - m_n_deleted; }
372+
373+ /* Return the current number of elements in this hash table. */
374+ size_t elements_with_deleted () const { return m_n_elements; }
375+
376+ /* This function clears all entries in this hash table. */
377+ void empty () { if (elements ()) empty_slow (); }
378+
379+ /* Return true when there are no elements in this hash table. */
380+ bool is_empty () const { return elements () == 0; }
381+
382+ /* This function clears a specified SLOT in a hash table. It is
383+ useful when you've already done the lookup and don't want to do it
384+ again. */
385+ void clear_slot (value_type *);
386+
387+ /* This function searches for a hash table entry equal to the given
388+ COMPARABLE element starting with the given HASH value. It cannot
389+ be used to insert or delete an element. */
390+ value_type &find_with_hash (const compare_type &, hashval_t);
391+
392+ /* Like find_slot_with_hash, but compute the hash value from the element. */
393+ value_type &find (const value_type &value)
394+ {
395+ return find_with_hash (value, Descriptor::hash (value));
396+ }
397+
398+ value_type *find_slot (const value_type &value, insert_option insert)
399+ {
400+ return find_slot_with_hash (value, Descriptor::hash (value), insert);
401+ }
402+
403+ /* This function searches for a hash table slot containing an entry
404+ equal to the given COMPARABLE element and starting with the given
405+ HASH. To delete an entry, call this with insert=NO_INSERT, then
406+ call clear_slot on the slot returned (possibly after doing some
407+ checks). To insert an entry, call this with insert=INSERT, then
408+ write the value you want into the returned slot. When inserting an
409+ entry, NULL may be returned if memory allocation fails. */
410+ value_type *find_slot_with_hash (const compare_type &comparable,
411+ hashval_t hash, enum insert_option insert);
412+
413+ /* This function deletes an element with the given COMPARABLE value
414+ from hash table starting with the given HASH. If there is no
415+ matching element in the hash table, this function does nothing. */
416+ void remove_elt_with_hash (const compare_type &, hashval_t);
417+
418+ /* Like remove_elt_with_hash, but compute the hash value from the
419+ element. */
420+ void remove_elt (const value_type &value)
421+ {
422+ remove_elt_with_hash (value, Descriptor::hash (value));
423+ }
424+
425+ /* This function scans over the entire hash table calling CALLBACK for
426+ each live entry. If CALLBACK returns false, the iteration stops.
427+ ARGUMENT is passed as CALLBACK's second argument. */
428+ template <typename Argument,
429+ int (*Callback) (value_type *slot, Argument argument)>
430+ void traverse_noresize (Argument argument);
431+
432+ /* Like traverse_noresize, but does resize the table when it is too empty
433+ to improve effectivity of subsequent calls. */
434+ template <typename Argument,
435+ int (*Callback) (value_type *slot, Argument argument)>
436+ void traverse (Argument argument);
437+
438+ class iterator
439+ {
440+ public:
441+ iterator () : m_slot (NULL), m_limit (NULL) {}
442+
443+ iterator (value_type *slot, value_type *limit) :
444+ m_slot (slot), m_limit (limit) {}
445+
446+ inline value_type &operator * () { return *m_slot; }
447+ void slide ();
448+ inline iterator &operator ++ ();
449+ bool operator != (const iterator &other) const
450+ {
451+ return m_slot != other.m_slot || m_limit != other.m_limit;
452+ }
453+
454+ private:
455+ value_type *m_slot;
456+ value_type *m_limit;
457+ };
458+
459+ iterator begin () const
460+ {
461+ if (Lazy && m_entries == NULL)
462+ return iterator ();
463+ iterator iter (m_entries, m_entries + m_size);
464+ iter.slide ();
465+ return iter;
466+ }
467+
468+ iterator end () const { return iterator (); }
469+
470+ double collisions () const
471+ {
472+ return m_searches ? static_cast <double> (m_collisions) / m_searches : 0;
473+ }
474+
475+private:
476+ /* FIXME: Make the class assignable. See pr90959. */
477+ void operator= (hash_table&);
478+
479+ void empty_slow ();
480+
481+ value_type *alloc_entries (size_t n) const;
482+ value_type *find_empty_slot_for_expand (hashval_t);
483+ void verify (const compare_type &comparable, hashval_t hash);
484+ bool too_empty_p (unsigned int);
485+ void expand ();
486+ static bool is_deleted (value_type &v)
487+ {
488+ return Descriptor::is_deleted (v);
489+ }
490+
491+ static bool is_empty (value_type &v)
492+ {
493+ return Descriptor::is_empty (v);
494+ }
495+
496+ static void mark_deleted (value_type &v)
497+ {
498+ Descriptor::mark_deleted (v);
499+ }
500+
501+ static void mark_empty (value_type &v)
502+ {
503+ Descriptor::mark_empty (v);
504+ }
505+
506+ /* Table itself. */
507+ typename Descriptor::value_type *m_entries;
508+
509+ size_t m_size;
510+
511+ /* Current number of elements including also deleted elements. */
512+ size_t m_n_elements;
513+
514+ /* Current number of deleted elements in the table. */
515+ size_t m_n_deleted;
516+
517+ /* The following member is used for debugging. Its value is number
518+ of all calls of `htab_find_slot' for the hash table. */
519+ unsigned int m_searches;
520+
521+ /* The following member is used for debugging. Its value is number
522+ of collisions fixed for time of work with the hash table. */
523+ unsigned int m_collisions;
524+
525+ /* Current size (in entries) of the hash table, as an index into the
526+ table of primes. */
527+ unsigned int m_size_prime_index;
528+
529+ /* True if the table should be sanitized for equal and hash functions. */
530+ bool m_sanitize_eq_and_hash;
531+};
532+
533+/* As mem-stats.h heavily utilizes hash maps (hash tables), we have to include
534+ mem-stats.h after hash_table declaration. */
535+
536+#include "hash-map.h"
537+
538+/* Support function for statistics. */
539+extern void dump_hash_table_loc_statistics (void);
540+
541+template<typename Descriptor, bool Lazy,
542+ template<typename Type> class Allocator>
543+hash_table<Descriptor, Lazy, Allocator>::hash_table (size_t size,
544+ bool sanitize_eq_and_hash) :
545+ m_n_elements (0), m_n_deleted (0), m_searches (0), m_collisions (0),
546+ m_sanitize_eq_and_hash (sanitize_eq_and_hash)
547+{
548+ unsigned int size_prime_index;
549+
550+ size_prime_index = hash_table_higher_prime_index (size);
551+ size = prime_tab[size_prime_index].prime;
552+
553+ if (Lazy)
554+ m_entries = NULL;
555+ else
556+ m_entries = alloc_entries (size);
557+ m_size = size;
558+ m_size_prime_index = size_prime_index;
559+}
560+
561+template<typename Descriptor, bool Lazy,
562+ template<typename Type> class Allocator>
563+hash_table<Descriptor, Lazy, Allocator>::hash_table (const hash_table &h,
564+ bool sanitize_eq_and_hash) :
565+ m_n_elements (h.m_n_elements), m_n_deleted (h.m_n_deleted),
566+ m_searches (0), m_collisions (0),
567+ m_sanitize_eq_and_hash (sanitize_eq_and_hash)
568+{
569+ size_t size = h.m_size;
570+
571+ if (Lazy && h.m_entries == NULL)
572+ m_entries = NULL;
573+ else
574+ {
575+ value_type *nentries = alloc_entries (size);
576+ for (size_t i = 0; i < size; ++i)
577+ {
578+ value_type &entry = h.m_entries[i];
579+ if (is_deleted (entry))
580+ mark_deleted (nentries[i]);
581+ else if (!is_empty (entry))
582+ new ((void*) (nentries + i)) value_type (entry);
583+ }
584+ m_entries = nentries;
585+ }
586+ m_size = size;
587+ m_size_prime_index = h.m_size_prime_index;
588+}
589+
590+template<typename Descriptor, bool Lazy,
591+ template<typename Type> class Allocator>
592+hash_table<Descriptor, Lazy, Allocator>::~hash_table ()
593+{
594+ if (!Lazy || m_entries)
595+ {
596+ for (size_t i = m_size - 1; i < m_size; i--)
597+ if (!is_empty (m_entries[i]) && !is_deleted (m_entries[i]))
598+ Descriptor::remove (m_entries[i]);
599+
600+ Allocator <value_type> ::data_free (m_entries);
601+ }
602+}
603+
604+/* This function returns an array of empty hash table elements. */
605+
606+template<typename Descriptor, bool Lazy,
607+ template<typename Type> class Allocator>
608+inline typename hash_table<Descriptor, Lazy, Allocator>::value_type *
609+hash_table<Descriptor, Lazy,
610+ Allocator>::alloc_entries (size_t n) const
611+{
612+ value_type *nentries;
613+
614+ nentries = Allocator <value_type> ::data_alloc (n);
615+
616+ gdb_assert (nentries != NULL);
617+ for (size_t i = 0; i < n; i++)
618+ mark_empty (nentries[i]);
619+
620+ return nentries;
621+}
622+
623+/* Similar to find_slot, but without several unwanted side effects:
624+ - Does not call equal when it finds an existing entry.
625+ - Does not change the count of elements/searches/collisions in the
626+ hash table.
627+ This function also assumes there are no deleted entries in the table.
628+ HASH is the hash value for the element to be inserted. */
629+
630+template<typename Descriptor, bool Lazy,
631+ template<typename Type> class Allocator>
632+typename hash_table<Descriptor, Lazy, Allocator>::value_type *
633+hash_table<Descriptor, Lazy,
634+ Allocator>::find_empty_slot_for_expand (hashval_t hash)
635+{
636+ hashval_t index = hash_table_mod1 (hash, m_size_prime_index);
637+ size_t size = m_size;
638+ value_type *slot = m_entries + index;
639+ hashval_t hash2;
640+
641+ if (is_empty (*slot))
642+ return slot;
643+ gdb_assert (!is_deleted (*slot));
644+
645+ hash2 = hash_table_mod2 (hash, m_size_prime_index);
646+ for (;;)
647+ {
648+ index += hash2;
649+ if (index >= size)
650+ index -= size;
651+
652+ slot = m_entries + index;
653+ if (is_empty (*slot))
654+ return slot;
655+ gdb_assert (!is_deleted (*slot));
656+ }
657+}
658+
659+/* Return true if the current table is excessively big for ELTS elements. */
660+
661+template<typename Descriptor, bool Lazy,
662+ template<typename Type> class Allocator>
663+inline bool
664+hash_table<Descriptor, Lazy, Allocator>::too_empty_p (unsigned int elts)
665+{
666+ return elts * 8 < m_size && m_size > 32;
667+}
668+
669+/* The following function changes size of memory allocated for the
670+ entries and repeatedly inserts the table elements. The occupancy
671+ of the table after the call will be about 50%. Naturally the hash
672+ table must already exist. Remember also that the place of the
673+ table entries is changed. If memory allocation fails, this function
674+ will abort. */
675+
676+template<typename Descriptor, bool Lazy,
677+ template<typename Type> class Allocator>
678+void
679+hash_table<Descriptor, Lazy, Allocator>::expand ()
680+{
681+ value_type *oentries = m_entries;
682+ unsigned int oindex = m_size_prime_index;
683+ size_t osize = size ();
684+ value_type *olimit = oentries + osize;
685+ size_t elts = elements ();
686+
687+ /* Resize only when table after removal of unused elements is either
688+ too full or too empty. */
689+ unsigned int nindex;
690+ size_t nsize;
691+ if (elts * 2 > osize || too_empty_p (elts))
692+ {
693+ nindex = hash_table_higher_prime_index (elts * 2);
694+ nsize = prime_tab[nindex].prime;
695+ }
696+ else
697+ {
698+ nindex = oindex;
699+ nsize = osize;
700+ }
701+
702+ value_type *nentries = alloc_entries (nsize);
703+
704+ m_entries = nentries;
705+ m_size = nsize;
706+ m_size_prime_index = nindex;
707+ m_n_elements -= m_n_deleted;
708+ m_n_deleted = 0;
709+
710+ value_type *p = oentries;
711+ do
712+ {
713+ value_type &x = *p;
714+
715+ if (!is_empty (x) && !is_deleted (x))
716+ {
717+ value_type *q = find_empty_slot_for_expand (Descriptor::hash (x));
718+
719+ *q = x;
720+ }
721+
722+ p++;
723+ }
724+ while (p < olimit);
725+
726+ Allocator <value_type> ::data_free (oentries);
727+}
728+
729+/* Implements empty() in cases where it isn't a no-op. */
730+
731+template<typename Descriptor, bool Lazy,
732+ template<typename Type> class Allocator>
733+void
734+hash_table<Descriptor, Lazy, Allocator>::empty_slow ()
735+{
736+ size_t size = m_size;
737+ size_t nsize = size;
738+ value_type *entries = m_entries;
739+ int i;
740+
741+ for (i = size - 1; i >= 0; i--)
742+ if (!is_empty (entries[i]) && !is_deleted (entries[i]))
743+ Descriptor::remove (entries[i]);
744+
745+ /* Instead of clearing megabyte, downsize the table. */
746+ if (size > 1024*1024 / sizeof (value_type))
747+ nsize = 1024 / sizeof (value_type);
748+ else if (too_empty_p (m_n_elements))
749+ nsize = m_n_elements * 2;
750+
751+ if (nsize != size)
752+ {
753+ int nindex = hash_table_higher_prime_index (nsize);
754+ int nsize2 = prime_tab[nindex].prime;
755+
756+ Allocator <value_type> ::data_free (m_entries);
757+
758+ m_entries = alloc_entries (nsize);
759+ m_size = nsize2;
760+ m_size_prime_index = nindex;
761+ }
762+ else
763+ {
764+#ifndef BROKEN_VALUE_INITIALIZATION
765+ for ( ; size; ++entries, --size)
766+ *entries = value_type ();
767+#else
768+ memset (entries, 0, size * sizeof (value_type));
769+#endif
770+ }
771+ m_n_deleted = 0;
772+ m_n_elements = 0;
773+}
774+
775+/* This function clears a specified SLOT in a hash table. It is
776+ useful when you've already done the lookup and don't want to do it
777+ again. */
778+
779+template<typename Descriptor, bool Lazy,
780+ template<typename Type> class Allocator>
781+void
782+hash_table<Descriptor, Lazy, Allocator>::clear_slot (value_type *slot)
783+{
784+ gdb_assert (!(slot < m_entries || slot >= m_entries + size ()
785+ || is_empty (*slot) || is_deleted (*slot)));
786+
787+ Descriptor::remove (*slot);
788+
789+ mark_deleted (*slot);
790+ m_n_deleted++;
791+}
792+
793+/* This function searches for a hash table entry equal to the given
794+ COMPARABLE element starting with the given HASH value. It cannot
795+ be used to insert or delete an element. */
796+
797+template<typename Descriptor, bool Lazy,
798+ template<typename Type> class Allocator>
799+typename hash_table<Descriptor, Lazy, Allocator>::value_type &
800+hash_table<Descriptor, Lazy, Allocator>
801+::find_with_hash (const compare_type &comparable, hashval_t hash)
802+{
803+ m_searches++;
804+ size_t size = m_size;
805+ hashval_t index = hash_table_mod1 (hash, m_size_prime_index);
806+
807+ if (Lazy && m_entries == NULL)
808+ m_entries = alloc_entries (size);
809+ value_type *entry = &m_entries[index];
810+ if (is_empty (*entry)
811+ || (!is_deleted (*entry) && Descriptor::equal (*entry, comparable)))
812+ return *entry;
813+
814+ hashval_t hash2 = hash_table_mod2 (hash, m_size_prime_index);
815+ for (;;)
816+ {
817+ m_collisions++;
818+ index += hash2;
819+ if (index >= size)
820+ index -= size;
821+
822+ entry = &m_entries[index];
823+ if (is_empty (*entry)
824+ || (!is_deleted (*entry) && Descriptor::equal (*entry, comparable)))
825+ {
826+#if CHECKING_P
827+ if (m_sanitize_eq_and_hash)
828+ verify (comparable, hash);
829+#endif
830+ return *entry;
831+ }
832+ }
833+}
834+
835+/* This function searches for a hash table slot containing an entry
836+ equal to the given COMPARABLE element and starting with the given
837+ HASH. To delete an entry, call this with insert=NO_INSERT, then
838+ call clear_slot on the slot returned (possibly after doing some
839+ checks). To insert an entry, call this with insert=INSERT, then
840+ write the value you want into the returned slot. When inserting an
841+ entry, NULL may be returned if memory allocation fails. */
842+
843+template<typename Descriptor, bool Lazy,
844+ template<typename Type> class Allocator>
845+typename hash_table<Descriptor, Lazy, Allocator>::value_type *
846+hash_table<Descriptor, Lazy, Allocator>
847+::find_slot_with_hash (const compare_type &comparable, hashval_t hash,
848+ enum insert_option insert)
849+{
850+ if (Lazy && m_entries == NULL)
851+ {
852+ if (insert == INSERT)
853+ m_entries = alloc_entries (m_size);
854+ else
855+ return NULL;
856+ }
857+ if (insert == INSERT && m_size * 3 <= m_n_elements * 4)
858+ expand ();
859+
860+#if CHECKING_P
861+ if (m_sanitize_eq_and_hash)
862+ verify (comparable, hash);
863+#endif
864+
865+ m_searches++;
866+ value_type *first_deleted_slot = NULL;
867+ hashval_t index = hash_table_mod1 (hash, m_size_prime_index);
868+ hashval_t hash2 = hash_table_mod2 (hash, m_size_prime_index);
869+ value_type *entry = &m_entries[index];
870+ size_t size = m_size;
871+ if (is_empty (*entry))
872+ goto empty_entry;
873+ else if (is_deleted (*entry))
874+ first_deleted_slot = &m_entries[index];
875+ else if (Descriptor::equal (*entry, comparable))
876+ return &m_entries[index];
877+
878+ for (;;)
879+ {
880+ m_collisions++;
881+ index += hash2;
882+ if (index >= size)
883+ index -= size;
884+
885+ entry = &m_entries[index];
886+ if (is_empty (*entry))
887+ goto empty_entry;
888+ else if (is_deleted (*entry))
889+ {
890+ if (!first_deleted_slot)
891+ first_deleted_slot = &m_entries[index];
892+ }
893+ else if (Descriptor::equal (*entry, comparable))
894+ return &m_entries[index];
895+ }
896+
897+ empty_entry:
898+ if (insert == NO_INSERT)
899+ return NULL;
900+
901+ if (first_deleted_slot)
902+ {
903+ m_n_deleted--;
904+ mark_empty (*first_deleted_slot);
905+ return first_deleted_slot;
906+ }
907+
908+ m_n_elements++;
909+ return &m_entries[index];
910+}
911+
912+/* Verify that all existing elements in the hash table which are
913+ equal to COMPARABLE have an equal HASH value provided as argument. */
914+
915+template<typename Descriptor, bool Lazy,
916+ template<typename Type> class Allocator>
917+void
918+hash_table<Descriptor, Lazy, Allocator>
919+::verify (const compare_type &comparable, hashval_t hash)
920+{
921+ for (size_t i = 0; i < std::min<size_t> (hash_table_sanitize_eq_limit, m_size); i++)
922+ {
923+ value_type *entry = &m_entries[i];
924+ if (!is_empty (*entry) && !is_deleted (*entry)
925+ && hash != Descriptor::hash (*entry)
926+ && Descriptor::equal (*entry, comparable))
927+ hashtab_chk_error ();
928+ }
929+}
930+
931+/* This function deletes an element with the given COMPARABLE value
932+ from hash table starting with the given HASH. If there is no
933+ matching element in the hash table, this function does nothing. */
934+
935+template<typename Descriptor, bool Lazy,
936+ template<typename Type> class Allocator>
937+void
938+hash_table<Descriptor, Lazy, Allocator>
939+::remove_elt_with_hash (const compare_type &comparable, hashval_t hash)
940+{
941+ value_type *slot = find_slot_with_hash (comparable, hash, NO_INSERT);
942+ if (slot == NULL)
943+ return;
944+
945+ Descriptor::remove (*slot);
946+
947+ mark_deleted (*slot);
948+ m_n_deleted++;
949+}
950+
951+/* This function scans over the entire hash table calling CALLBACK for
952+ each live entry. If CALLBACK returns false, the iteration stops.
953+ ARGUMENT is passed as CALLBACK's second argument. */
954+
955+template<typename Descriptor, bool Lazy,
956+ template<typename Type> class Allocator>
957+template<typename Argument,
958+ int (*Callback)
959+ (typename hash_table<Descriptor, Lazy, Allocator>::value_type *slot,
960+ Argument argument)>
961+void
962+hash_table<Descriptor, Lazy, Allocator>::traverse_noresize (Argument argument)
963+{
964+ if (Lazy && m_entries == NULL)
965+ return;
966+
967+ value_type *slot = m_entries;
968+ value_type *limit = slot + size ();
969+
970+ do
971+ {
972+ value_type &x = *slot;
973+
974+ if (!is_empty (x) && !is_deleted (x))
975+ if (! Callback (slot, argument))
976+ break;
977+ }
978+ while (++slot < limit);
979+}
980+
981+/* Like traverse_noresize, but does resize the table when it is too empty
982+ to improve effectivity of subsequent calls. */
983+
984+template <typename Descriptor, bool Lazy,
985+ template <typename Type> class Allocator>
986+template <typename Argument,
987+ int (*Callback)
988+ (typename hash_table<Descriptor, Lazy, Allocator>::value_type *slot,
989+ Argument argument)>
990+void
991+hash_table<Descriptor, Lazy, Allocator>::traverse (Argument argument)
992+{
993+ if (too_empty_p (elements ()) && (!Lazy || m_entries))
994+ expand ();
995+
996+ traverse_noresize <Argument, Callback> (argument);
997+}
998+
999+/* Slide down the iterator slots until an active entry is found. */
1000+
1001+template<typename Descriptor, bool Lazy,
1002+ template<typename Type> class Allocator>
1003+void
1004+hash_table<Descriptor, Lazy, Allocator>::iterator::slide ()
1005+{
1006+ for ( ; m_slot < m_limit; ++m_slot )
1007+ {
1008+ value_type &x = *m_slot;
1009+ if (!is_empty (x) && !is_deleted (x))
1010+ return;
1011+ }
1012+ m_slot = NULL;
1013+ m_limit = NULL;
1014+}
1015+
1016+/* Bump the iterator. */
1017+
1018+template<typename Descriptor, bool Lazy,
1019+ template<typename Type> class Allocator>
1020+inline typename hash_table<Descriptor, Lazy, Allocator>::iterator &
1021+hash_table<Descriptor, Lazy, Allocator>::iterator::operator ++ ()
1022+{
1023+ ++m_slot;
1024+ slide ();
1025+ return *this;
1026+}
1027+
1028+
1029+/* Iterate through the elements of hash_table HTAB,
1030+ using hash_table <....>::iterator ITER,
1031+ storing each element in RESULT, which is of type TYPE. */
1032+
1033+#define FOR_EACH_HASH_TABLE_ELEMENT(HTAB, RESULT, TYPE, ITER) \
1034+ for ((ITER) = (HTAB).begin (); \
1035+ (ITER) != (HTAB).end () ? (RESULT = *(ITER) , true) : false; \
1036+ ++(ITER))
1037+
1038+#endif /* TYPED_HASHTAB_H */
--- /dev/null
+++ b/gdb/hash-traits.h
@@ -0,0 +1,322 @@
1+/* Traits for hashable types.
2+ Copyright (C) 2014-2019 Free Software Foundation, Inc.
3+
4+This file is part of GCC.
5+
6+GCC is free software; you can redistribute it and/or modify it under
7+the terms of the GNU General Public License as published by the Free
8+Software Foundation; either version 3, or (at your option) any later
9+version.
10+
11+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12+WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+for more details.
15+
16+You should have received a copy of the GNU General Public License
17+along with GCC; see the file COPYING3. If not see
18+<http://www.gnu.org/licenses/>. */
19+
20+#ifndef hash_traits_h
21+#define hash_traits_h
22+
23+/* Helpful type for removing with free. */
24+
25+template <typename Type>
26+struct typed_free_remove
27+{
28+ static inline void remove (Type *p);
29+};
30+
31+
32+/* Remove with free. */
33+
34+template <typename Type>
35+inline void
36+typed_free_remove <Type>::remove (Type *p)
37+{
38+ free (p);
39+}
40+
41+/* Helpful type for removing with delete. */
42+
43+template <typename Type>
44+struct typed_delete_remove
45+{
46+ static inline void remove (Type *p);
47+};
48+
49+
50+/* Remove with delete. */
51+
52+template <typename Type>
53+inline void
54+typed_delete_remove <Type>::remove (Type *p)
55+{
56+ delete p;
57+}
58+
59+/* Helpful type for a no-op remove. */
60+
61+template <typename Type>
62+struct typed_noop_remove
63+{
64+ static inline void remove (Type &);
65+};
66+
67+
68+/* Remove doing nothing. */
69+
70+template <typename Type>
71+inline void
72+typed_noop_remove <Type>::remove (Type &)
73+{
74+}
75+
76+
77+/* Hasher for integer type Type in which Empty is a spare value that can be
78+ used to mark empty slots. If Deleted != Empty then Deleted is another
79+ spare value that can be used for deleted slots; if Deleted == Empty then
80+ hash table entries cannot be deleted. */
81+
82+template <typename Type, Type Empty, Type Deleted = Empty>
83+struct int_hash : typed_noop_remove <Type>
84+{
85+ typedef Type value_type;
86+ typedef Type compare_type;
87+
88+ static inline hashval_t hash (value_type);
89+ static inline bool equal (value_type existing, value_type candidate);
90+ static inline void mark_deleted (Type &);
91+ static inline void mark_empty (Type &);
92+ static inline bool is_deleted (Type);
93+ static inline bool is_empty (Type);
94+};
95+
96+template <typename Type, Type Empty, Type Deleted>
97+inline hashval_t
98+int_hash <Type, Empty, Deleted>::hash (value_type x)
99+{
100+ return x;
101+}
102+
103+template <typename Type, Type Empty, Type Deleted>
104+inline bool
105+int_hash <Type, Empty, Deleted>::equal (value_type x, value_type y)
106+{
107+ return x == y;
108+}
109+
110+template <typename Type, Type Empty, Type Deleted>
111+inline void
112+int_hash <Type, Empty, Deleted>::mark_deleted (Type &x)
113+{
114+ gdb_assert (Empty != Deleted);
115+ x = Deleted;
116+}
117+
118+template <typename Type, Type Empty, Type Deleted>
119+inline void
120+int_hash <Type, Empty, Deleted>::mark_empty (Type &x)
121+{
122+ x = Empty;
123+}
124+
125+template <typename Type, Type Empty, Type Deleted>
126+inline bool
127+int_hash <Type, Empty, Deleted>::is_deleted (Type x)
128+{
129+ return Empty != Deleted && x == Deleted;
130+}
131+
132+template <typename Type, Type Empty, Type Deleted>
133+inline bool
134+int_hash <Type, Empty, Deleted>::is_empty (Type x)
135+{
136+ return x == Empty;
137+}
138+
139+/* Pointer hasher based on pointer equality. Other types of pointer hash
140+ can inherit this and override the hash and equal functions with some
141+ other form of equality (such as string equality). */
142+
143+template <typename Type>
144+struct pointer_hash
145+{
146+ typedef Type *value_type;
147+ typedef Type *compare_type;
148+
149+ static inline hashval_t hash (const value_type &);
150+ static inline bool equal (const value_type &existing,
151+ const compare_type &candidate);
152+ static inline void mark_deleted (Type *&);
153+ static inline void mark_empty (Type *&);
154+ static inline bool is_deleted (Type *);
155+ static inline bool is_empty (Type *);
156+};
157+
158+template <typename Type>
159+inline hashval_t
160+pointer_hash <Type>::hash (const value_type &candidate)
161+{
162+ /* This is a really poor hash function, but it is what the current code uses,
163+ so I am reusing it to avoid an additional axis in testing. */
164+ return (hashval_t) ((intptr_t)candidate >> 3);
165+}
166+
167+template <typename Type>
168+inline bool
169+pointer_hash <Type>::equal (const value_type &existing,
170+ const compare_type &candidate)
171+{
172+ return existing == candidate;
173+}
174+
175+template <typename Type>
176+inline void
177+pointer_hash <Type>::mark_deleted (Type *&e)
178+{
179+ e = reinterpret_cast<Type *> (1);
180+}
181+
182+template <typename Type>
183+inline void
184+pointer_hash <Type>::mark_empty (Type *&e)
185+{
186+ e = NULL;
187+}
188+
189+template <typename Type>
190+inline bool
191+pointer_hash <Type>::is_deleted (Type *e)
192+{
193+ return e == reinterpret_cast<Type *> (1);
194+}
195+
196+template <typename Type>
197+inline bool
198+pointer_hash <Type>::is_empty (Type *e)
199+{
200+ return e == NULL;
201+}
202+
203+/* Hasher for "const char *" strings, using string rather than pointer
204+ equality. */
205+
206+struct string_hash : pointer_hash <const char>
207+{
208+ static inline hashval_t hash (const char *);
209+ static inline bool equal (const char *, const char *);
210+};
211+
212+inline hashval_t
213+string_hash::hash (const char *id)
214+{
215+ return htab_hash_string (id);
216+}
217+
218+inline bool
219+string_hash::equal (const char *id1, const char *id2)
220+{
221+ return strcmp (id1, id2) == 0;
222+}
223+
224+/* Traits for pointer elements that should not be freed when an element
225+ is deleted. */
226+
227+template <typename T>
228+struct nofree_ptr_hash : pointer_hash <T>, typed_noop_remove <T *> {};
229+
230+/* Traits for pointer elements that should be freed via free() when an
231+ element is deleted. */
232+
233+template <typename T>
234+struct free_ptr_hash : pointer_hash <T>, typed_free_remove <T> {};
235+
236+/* Traits for pointer elements that should be freed via delete operand when an
237+ element is deleted. */
238+
239+template <typename T>
240+struct delete_ptr_hash : pointer_hash <T>, typed_delete_remove <T> {};
241+
242+/* Traits for string elements that should not be freed when an element
243+ is deleted. */
244+
245+struct nofree_string_hash : string_hash, typed_noop_remove <const char *> {};
246+
247+/* Traits for pairs of values, using the first to record empty and
248+ deleted slots. */
249+
250+template <typename T1, typename T2>
251+struct pair_hash
252+{
253+ typedef std::pair <typename T1::value_type,
254+ typename T2::value_type> value_type;
255+ typedef std::pair <typename T1::compare_type,
256+ typename T2::compare_type> compare_type;
257+
258+ static inline hashval_t hash (const value_type &);
259+ static inline bool equal (const value_type &, const compare_type &);
260+ static inline void remove (value_type &);
261+ static inline void mark_deleted (value_type &);
262+ static inline void mark_empty (value_type &);
263+ static inline bool is_deleted (const value_type &);
264+ static inline bool is_empty (const value_type &);
265+};
266+
267+template <typename T1, typename T2>
268+inline hashval_t
269+pair_hash <T1, T2>::hash (const value_type &x)
270+{
271+ return iterative_hash_hashval_t (T1::hash (x.first), T2::hash (x.second));
272+}
273+
274+template <typename T1, typename T2>
275+inline bool
276+pair_hash <T1, T2>::equal (const value_type &x, const compare_type &y)
277+{
278+ return T1::equal (x.first, y.first) && T2::equal (x.second, y.second);
279+}
280+
281+template <typename T1, typename T2>
282+inline void
283+pair_hash <T1, T2>::remove (value_type &x)
284+{
285+ T1::remove (x.first);
286+ T2::remove (x.second);
287+}
288+
289+template <typename T1, typename T2>
290+inline void
291+pair_hash <T1, T2>::mark_deleted (value_type &x)
292+{
293+ T1::mark_deleted (x.first);
294+}
295+
296+template <typename T1, typename T2>
297+inline void
298+pair_hash <T1, T2>::mark_empty (value_type &x)
299+{
300+ T1::mark_empty (x.first);
301+}
302+
303+template <typename T1, typename T2>
304+inline bool
305+pair_hash <T1, T2>::is_deleted (const value_type &x)
306+{
307+ return T1::is_deleted (x.first);
308+}
309+
310+template <typename T1, typename T2>
311+inline bool
312+pair_hash <T1, T2>::is_empty (const value_type &x)
313+{
314+ return T1::is_empty (x.first);
315+}
316+
317+template <typename T> struct default_hash_traits : T {};
318+
319+template <typename T>
320+struct default_hash_traits <T *> : pointer_hash <T> {};
321+
322+#endif