]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/hash-table.h
gcc/
[thirdparty/gcc.git] / gcc / hash-table.h
1 /* A type-safe hash table template.
2 Copyright (C) 2012-2015 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 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
39 - A static member function named 'hash' that takes a value_type
40 pointer and returns a hashval_t value.
41
42 - A typedef named 'compare_type' that is used to test when an value
43 is found. This type is the comparison type. Usually, it will be the
44 same as value_type. If it is not the same type, you must generally
45 explicitly compute hash values and pass them to the hash table.
46
47 - A static member function named 'equal' that takes a value_type
48 pointer and a compare_type pointer, and returns a bool.
49
50 - A static function named 'remove' that takes an value_type pointer
51 and frees the memory allocated by it. This function is used when
52 individual elements of the table need to be disposed of (e.g.,
53 when deleting a hash table, removing elements from the table, etc).
54
55 - An optional static function named 'keep_cache_entry'. This
56 function is provided only for garbage-collected elements that
57 are not marked by the normal gc mark pass. It describes what
58 what should happen to the element at the end of the gc mark phase.
59 The return value should be:
60 - 0 if the element should be deleted
61 - 1 if the element should be kept and needs to be marked
62 - -1 if the element should be kept and is already marked.
63 Returning -1 rather than 1 is purely an optimization.
64
65 3. The type of the hash table itself. (More later.)
66
67 In very special circumstances, users may need to know about a fourth type.
68
69 4. The template type used to describe how hash table memory
70 is allocated. This type is called the allocator type. It is
71 parameterized on the value type. It provides four functions.
72
73 - A static member function named 'data_alloc'. This function
74 allocates the data elements in the table.
75
76 - A static member function named 'data_free'. This function
77 deallocates the data elements in the table.
78
79 Hash table are instantiated with two type arguments.
80
81 * The descriptor type, (2) above.
82
83 * The allocator type, (4) above. In general, you will not need to
84 provide your own allocator type. By default, hash tables will use
85 the class template xcallocator, which uses malloc/free for allocation.
86
87
88 DEFINING A DESCRIPTOR TYPE
89
90 The first task in using the hash table is to describe the element type.
91 We compose this into a few steps.
92
93 1. Decide on a removal policy for values stored in the table.
94 hash-traits.h provides class templates for the two most common
95 policies.
96
97 * typed_free_remove implements the static 'remove' member function
98 by calling free().
99
100 * typed_noop_remove implements the static 'remove' member function
101 by doing nothing.
102
103 You can use these policies by simply deriving the descriptor type
104 from one of those class template, with the appropriate argument.
105
106 Otherwise, you need to write the static 'remove' member function
107 in the descriptor class.
108
109 2. Choose a hash function. Write the static 'hash' member function.
110
111 3. Choose an equality testing function. In most cases, its two
112 arguments will be value_type pointers. If not, the first argument must
113 be a value_type pointer, and the second argument a compare_type pointer.
114
115
116 AN EXAMPLE DESCRIPTOR TYPE
117
118 Suppose you want to put some_type into the hash table. You could define
119 the descriptor type as follows.
120
121 struct some_type_hasher : nofree_ptr_hash <some_type>
122 // Deriving from nofree_ptr_hash means that we get a 'remove' that does
123 // nothing. This choice is good for raw values.
124 {
125 static inline hashval_t hash (const value_type *);
126 static inline bool equal (const value_type *, const compare_type *);
127 };
128
129 inline hashval_t
130 some_type_hasher::hash (const value_type *e)
131 { ... compute and return a hash value for E ... }
132
133 inline bool
134 some_type_hasher::equal (const value_type *p1, const compare_type *p2)
135 { ... compare P1 vs P2. Return true if they are the 'same' ... }
136
137
138 AN EXAMPLE HASH_TABLE DECLARATION
139
140 To instantiate a hash table for some_type:
141
142 hash_table <some_type_hasher> some_type_hash_table;
143
144 There is no need to mention some_type directly, as the hash table will
145 obtain it using some_type_hasher::value_type.
146
147 You can then used any of the functions in hash_table's public interface.
148 See hash_table for details. The interface is very similar to libiberty's
149 htab_t.
150
151
152 EASY DESCRIPTORS FOR POINTERS
153
154 The class template pointer_hash provides everything you need to hash
155 pointers (as opposed to what they point to). So, to instantiate a hash
156 table over pointers to whatever_type,
157
158 hash_table <pointer_hash <whatever_type>> whatever_type_hash_table;
159
160
161 HASH TABLE ITERATORS
162
163 The hash table provides standard C++ iterators. For example, consider a
164 hash table of some_info. We wish to consume each element of the table:
165
166 extern void consume (some_info *);
167
168 We define a convenience typedef and the hash table:
169
170 typedef hash_table <some_info_hasher> info_table_type;
171 info_table_type info_table;
172
173 Then we write the loop in typical C++ style:
174
175 for (info_table_type::iterator iter = info_table.begin ();
176 iter != info_table.end ();
177 ++iter)
178 if ((*iter).status == INFO_READY)
179 consume (&*iter);
180
181 Or with common sub-expression elimination:
182
183 for (info_table_type::iterator iter = info_table.begin ();
184 iter != info_table.end ();
185 ++iter)
186 {
187 some_info &elem = *iter;
188 if (elem.status == INFO_READY)
189 consume (&elem);
190 }
191
192 One can also use a more typical GCC style:
193
194 typedef some_info *some_info_p;
195 some_info *elem_ptr;
196 info_table_type::iterator iter;
197 FOR_EACH_HASH_TABLE_ELEMENT (info_table, elem_ptr, some_info_p, iter)
198 if (elem_ptr->status == INFO_READY)
199 consume (elem_ptr);
200
201 */
202
203
204 #ifndef TYPED_HASHTAB_H
205 #define TYPED_HASHTAB_H
206
207 #include "statistics.h"
208 #include "ggc.h"
209 #include "vec.h"
210 #include "hashtab.h"
211 #include "inchash.h"
212 #include "mem-stats-traits.h"
213 #include "hash-traits.h"
214 #include "hash-map-traits.h"
215
216 template<typename, typename, typename> class hash_map;
217 template<typename, typename> class hash_set;
218
219 /* The ordinary memory allocator. */
220 /* FIXME (crowl): This allocator may be extracted for wider sharing later. */
221
222 template <typename Type>
223 struct xcallocator
224 {
225 static Type *data_alloc (size_t count);
226 static void data_free (Type *memory);
227 };
228
229
230 /* Allocate memory for COUNT data blocks. */
231
232 template <typename Type>
233 inline Type *
234 xcallocator <Type>::data_alloc (size_t count)
235 {
236 return static_cast <Type *> (xcalloc (count, sizeof (Type)));
237 }
238
239
240 /* Free memory for data blocks. */
241
242 template <typename Type>
243 inline void
244 xcallocator <Type>::data_free (Type *memory)
245 {
246 return ::free (memory);
247 }
248
249
250 /* Table of primes and their inversion information. */
251
252 struct prime_ent
253 {
254 hashval_t prime;
255 hashval_t inv;
256 hashval_t inv_m2; /* inverse of prime-2 */
257 hashval_t shift;
258 };
259
260 extern struct prime_ent const prime_tab[];
261
262
263 /* Functions for computing hash table indexes. */
264
265 extern unsigned int hash_table_higher_prime_index (unsigned long n)
266 ATTRIBUTE_PURE;
267
268 /* Return X % Y using multiplicative inverse values INV and SHIFT.
269
270 The multiplicative inverses computed above are for 32-bit types,
271 and requires that we be able to compute a highpart multiply.
272
273 FIX: I am not at all convinced that
274 3 loads, 2 multiplications, 3 shifts, and 3 additions
275 will be faster than
276 1 load and 1 modulus
277 on modern systems running a compiler. */
278
279 inline hashval_t
280 mul_mod (hashval_t x, hashval_t y, hashval_t inv, int shift)
281 {
282 hashval_t t1, t2, t3, t4, q, r;
283
284 t1 = ((uint64_t)x * inv) >> 32;
285 t2 = x - t1;
286 t3 = t2 >> 1;
287 t4 = t1 + t3;
288 q = t4 >> shift;
289 r = x - (q * y);
290
291 return r;
292 }
293
294 /* Compute the primary table index for HASH given current prime index. */
295
296 inline hashval_t
297 hash_table_mod1 (hashval_t hash, unsigned int index)
298 {
299 const struct prime_ent *p = &prime_tab[index];
300 gcc_checking_assert (sizeof (hashval_t) * CHAR_BIT <= 32);
301 return mul_mod (hash, p->prime, p->inv, p->shift);
302 }
303
304 /* Compute the secondary table index for HASH given current prime index. */
305
306 inline hashval_t
307 hash_table_mod2 (hashval_t hash, unsigned int index)
308 {
309 const struct prime_ent *p = &prime_tab[index];
310 gcc_checking_assert (sizeof (hashval_t) * CHAR_BIT <= 32);
311 return 1 + mul_mod (hash, p->prime - 2, p->inv_m2, p->shift);
312 }
313
314 template<typename Traits>
315 struct has_is_deleted
316 {
317 template<typename U, bool (*)(U &)> struct helper {};
318 template<typename U> static char test (helper<U, U::is_deleted> *);
319 template<typename U> static int test (...);
320 static const bool value = sizeof (test<Traits> (0)) == sizeof (char);
321 };
322
323 template<typename Type, typename Traits, bool = has_is_deleted<Traits>::value>
324 struct is_deleted_helper
325 {
326 static inline bool
327 call (Type &v)
328 {
329 return Traits::is_deleted (v);
330 }
331 };
332
333 template<typename Type, typename Traits>
334 struct is_deleted_helper<Type *, Traits, false>
335 {
336 static inline bool
337 call (Type *v)
338 {
339 return v == HTAB_DELETED_ENTRY;
340 }
341 };
342
343 template<typename Traits>
344 struct has_is_empty
345 {
346 template<typename U, bool (*)(U &)> struct helper {};
347 template<typename U> static char test (helper<U, U::is_empty> *);
348 template<typename U> static int test (...);
349 static const bool value = sizeof (test<Traits> (0)) == sizeof (char);
350 };
351
352 template<typename Type, typename Traits, bool = has_is_deleted<Traits>::value>
353 struct is_empty_helper
354 {
355 static inline bool
356 call (Type &v)
357 {
358 return Traits::is_empty (v);
359 }
360 };
361
362 template<typename Type, typename Traits>
363 struct is_empty_helper<Type *, Traits, false>
364 {
365 static inline bool
366 call (Type *v)
367 {
368 return v == HTAB_EMPTY_ENTRY;
369 }
370 };
371
372 template<typename Traits>
373 struct has_mark_deleted
374 {
375 template<typename U, void (*)(U &)> struct helper {};
376 template<typename U> static char test (helper<U, U::mark_deleted> *);
377 template<typename U> static int test (...);
378 static const bool value = sizeof (test<Traits> (0)) == sizeof (char);
379 };
380
381 template<typename Type, typename Traits, bool = has_is_deleted<Traits>::value>
382 struct mark_deleted_helper
383 {
384 static inline void
385 call (Type &v)
386 {
387 Traits::mark_deleted (v);
388 }
389 };
390
391 template<typename Type, typename Traits>
392 struct mark_deleted_helper<Type *, Traits, false>
393 {
394 static inline void
395 call (Type *&v)
396 {
397 v = static_cast<Type *> (HTAB_DELETED_ENTRY);
398 }
399 };
400
401 template<typename Traits>
402 struct has_mark_empty
403 {
404 template<typename U, void (*)(U &)> struct helper {};
405 template<typename U> static char test (helper<U, U::mark_empty> *);
406 template<typename U> static int test (...);
407 static const bool value = sizeof (test<Traits> (0)) == sizeof (char);
408 };
409
410 template<typename Type, typename Traits, bool = has_is_deleted<Traits>::value>
411 struct mark_empty_helper
412 {
413 static inline void
414 call (Type &v)
415 {
416 Traits::mark_empty (v);
417 }
418 };
419
420 template<typename Type, typename Traits>
421 struct mark_empty_helper<Type *, Traits, false>
422 {
423 static inline void
424 call (Type *&v)
425 {
426 v = static_cast<Type *> (HTAB_EMPTY_ENTRY);
427 }
428 };
429
430 class mem_usage;
431
432 /* User-facing hash table type.
433
434 The table stores elements of type Descriptor::value_type.
435
436 It hashes values with the hash member function.
437 The table currently works with relatively weak hash functions.
438 Use typed_pointer_hash <Value> when hashing pointers instead of objects.
439
440 It compares elements with the equal member function.
441 Two elements with the same hash may not be equal.
442 Use typed_pointer_equal <Value> when hashing pointers instead of objects.
443
444 It removes elements with the remove member function.
445 This feature is useful for freeing memory.
446 Derive from typed_null_remove <Value> when not freeing objects.
447 Derive from typed_free_remove <Value> when doing a simple object free.
448
449 Specify the template Allocator to allocate and free memory.
450 The default is xcallocator.
451
452 Storage is an implementation detail and should not be used outside the
453 hash table code.
454
455 */
456 template <typename Descriptor,
457 template<typename Type> class Allocator = xcallocator>
458 class hash_table
459 {
460 typedef typename Descriptor::value_type value_type;
461 typedef typename Descriptor::compare_type compare_type;
462
463 public:
464 explicit hash_table (size_t, bool ggc = false, bool gather_mem_stats = true,
465 mem_alloc_origin origin = HASH_TABLE_ORIGIN
466 CXX_MEM_STAT_INFO);
467 ~hash_table ();
468
469 /* Create a hash_table in gc memory. */
470
471 static hash_table *
472 create_ggc (size_t n CXX_MEM_STAT_INFO)
473 {
474 hash_table *table = ggc_alloc<hash_table> ();
475 new (table) hash_table (n, true, true, HASH_TABLE_ORIGIN PASS_MEM_STAT);
476 return table;
477 }
478
479 /* Current size (in entries) of the hash table. */
480 size_t size () const { return m_size; }
481
482 /* Return the current number of elements in this hash table. */
483 size_t elements () const { return m_n_elements - m_n_deleted; }
484
485 /* Return the current number of elements in this hash table. */
486 size_t elements_with_deleted () const { return m_n_elements; }
487
488 /* This function clears all entries in the given hash table. */
489 void empty ();
490
491 /* This function clears a specified SLOT in a hash table. It is
492 useful when you've already done the lookup and don't want to do it
493 again. */
494
495 void clear_slot (value_type *);
496
497 /* This function searches for a hash table entry equal to the given
498 COMPARABLE element starting with the given HASH value. It cannot
499 be used to insert or delete an element. */
500 value_type &find_with_hash (const compare_type &, hashval_t);
501
502 /* Like find_slot_with_hash, but compute the hash value from the element. */
503 value_type &find (const value_type &value)
504 {
505 return find_with_hash (value, Descriptor::hash (value));
506 }
507
508 value_type *find_slot (const value_type &value, insert_option insert)
509 {
510 return find_slot_with_hash (value, Descriptor::hash (value), insert);
511 }
512
513 /* This function searches for a hash table slot containing an entry
514 equal to the given COMPARABLE element and starting with the given
515 HASH. To delete an entry, call this with insert=NO_INSERT, then
516 call clear_slot on the slot returned (possibly after doing some
517 checks). To insert an entry, call this with insert=INSERT, then
518 write the value you want into the returned slot. When inserting an
519 entry, NULL may be returned if memory allocation fails. */
520 value_type *find_slot_with_hash (const compare_type &comparable,
521 hashval_t hash, enum insert_option insert);
522
523 /* This function deletes an element with the given COMPARABLE value
524 from hash table starting with the given HASH. If there is no
525 matching element in the hash table, this function does nothing. */
526 void remove_elt_with_hash (const compare_type &, hashval_t);
527
528 /* Like remove_elt_with_hash, but compute the hash value from the element. */
529 void remove_elt (const value_type &value)
530 {
531 remove_elt_with_hash (value, Descriptor::hash (value));
532 }
533
534 /* This function scans over the entire hash table calling CALLBACK for
535 each live entry. If CALLBACK returns false, the iteration stops.
536 ARGUMENT is passed as CALLBACK's second argument. */
537 template <typename Argument,
538 int (*Callback) (value_type *slot, Argument argument)>
539 void traverse_noresize (Argument argument);
540
541 /* Like traverse_noresize, but does resize the table when it is too empty
542 to improve effectivity of subsequent calls. */
543 template <typename Argument,
544 int (*Callback) (value_type *slot, Argument argument)>
545 void traverse (Argument argument);
546
547 class iterator
548 {
549 public:
550 iterator () : m_slot (NULL), m_limit (NULL) {}
551
552 iterator (value_type *slot, value_type *limit) :
553 m_slot (slot), m_limit (limit) {}
554
555 inline value_type &operator * () { return *m_slot; }
556 void slide ();
557 inline iterator &operator ++ ();
558 bool operator != (const iterator &other) const
559 {
560 return m_slot != other.m_slot || m_limit != other.m_limit;
561 }
562
563 private:
564 value_type *m_slot;
565 value_type *m_limit;
566 };
567
568 iterator begin () const
569 {
570 iterator iter (m_entries, m_entries + m_size);
571 iter.slide ();
572 return iter;
573 }
574
575 iterator end () const { return iterator (); }
576
577 double collisions () const
578 {
579 return m_searches ? static_cast <double> (m_collisions) / m_searches : 0;
580 }
581
582 private:
583 template<typename T> friend void gt_ggc_mx (hash_table<T> *);
584 template<typename T> friend void gt_pch_nx (hash_table<T> *);
585 template<typename T> friend void
586 hashtab_entry_note_pointers (void *, void *, gt_pointer_operator, void *);
587 template<typename T, typename U, typename V> friend void
588 gt_pch_nx (hash_map<T, U, V> *, gt_pointer_operator, void *);
589 template<typename T, typename U> friend void gt_pch_nx (hash_set<T, U> *,
590 gt_pointer_operator,
591 void *);
592 template<typename T> friend void gt_pch_nx (hash_table<T> *,
593 gt_pointer_operator, void *);
594
595 template<typename T> friend void gt_cleare_cache (hash_table<T> *);
596
597 value_type *alloc_entries (size_t n CXX_MEM_STAT_INFO) const;
598 value_type *find_empty_slot_for_expand (hashval_t);
599 void expand ();
600 static bool is_deleted (value_type &v)
601 {
602 return is_deleted_helper<value_type, Descriptor>::call (v);
603 }
604 static bool is_empty (value_type &v)
605 {
606 return is_empty_helper<value_type, Descriptor>::call (v);
607 }
608
609 static void mark_deleted (value_type &v)
610 {
611 return mark_deleted_helper<value_type, Descriptor>::call (v);
612 }
613
614 static void mark_empty (value_type &v)
615 {
616 return mark_empty_helper<value_type, Descriptor>::call (v);
617 }
618
619 /* Table itself. */
620 typename Descriptor::value_type *m_entries;
621
622 size_t m_size;
623
624 /* Current number of elements including also deleted elements. */
625 size_t m_n_elements;
626
627 /* Current number of deleted elements in the table. */
628 size_t m_n_deleted;
629
630 /* The following member is used for debugging. Its value is number
631 of all calls of `htab_find_slot' for the hash table. */
632 unsigned int m_searches;
633
634 /* The following member is used for debugging. Its value is number
635 of collisions fixed for time of work with the hash table. */
636 unsigned int m_collisions;
637
638 /* Current size (in entries) of the hash table, as an index into the
639 table of primes. */
640 unsigned int m_size_prime_index;
641
642 /* if m_entries is stored in ggc memory. */
643 bool m_ggc;
644
645 /* If we should gather memory statistics for the table. */
646 bool m_gather_mem_stats;
647 };
648
649 /* As mem-stats.h heavily utilizes hash maps (hash tables), we have to include
650 mem-stats.h after hash_table declaration. */
651
652 #include "mem-stats.h"
653 #include "hash-map.h"
654
655 extern mem_alloc_description<mem_usage> hash_table_usage;
656
657 /* Support function for statistics. */
658 extern void dump_hash_table_loc_statistics (void);
659
660 template<typename Descriptor, template<typename Type> class Allocator>
661 hash_table<Descriptor, Allocator>::hash_table (size_t size, bool ggc, bool
662 gather_mem_stats,
663 mem_alloc_origin origin
664 MEM_STAT_DECL) :
665 m_n_elements (0), m_n_deleted (0), m_searches (0), m_collisions (0),
666 m_ggc (ggc), m_gather_mem_stats (gather_mem_stats)
667 {
668 unsigned int size_prime_index;
669
670 size_prime_index = hash_table_higher_prime_index (size);
671 size = prime_tab[size_prime_index].prime;
672
673 if (m_gather_mem_stats)
674 hash_table_usage.register_descriptor (this, origin, ggc
675 FINAL_PASS_MEM_STAT);
676
677 m_entries = alloc_entries (size PASS_MEM_STAT);
678 m_size = size;
679 m_size_prime_index = size_prime_index;
680 }
681
682 template<typename Descriptor, template<typename Type> class Allocator>
683 hash_table<Descriptor, Allocator>::~hash_table ()
684 {
685 for (size_t i = m_size - 1; i < m_size; i--)
686 if (!is_empty (m_entries[i]) && !is_deleted (m_entries[i]))
687 Descriptor::remove (m_entries[i]);
688
689 if (!m_ggc)
690 Allocator <value_type> ::data_free (m_entries);
691 else
692 ggc_free (m_entries);
693
694 if (m_gather_mem_stats)
695 hash_table_usage.release_instance_overhead (this,
696 sizeof (value_type) * m_size,
697 true);
698 }
699
700 /* This function returns an array of empty hash table elements. */
701
702 template<typename Descriptor, template<typename Type> class Allocator>
703 inline typename hash_table<Descriptor, Allocator>::value_type *
704 hash_table<Descriptor, Allocator>::alloc_entries (size_t n MEM_STAT_DECL) const
705 {
706 value_type *nentries;
707
708 if (m_gather_mem_stats)
709 hash_table_usage.register_instance_overhead (sizeof (value_type) * n, this);
710
711 if (!m_ggc)
712 nentries = Allocator <value_type> ::data_alloc (n);
713 else
714 nentries = ::ggc_cleared_vec_alloc<value_type> (n PASS_MEM_STAT);
715
716 gcc_assert (nentries != NULL);
717 for (size_t i = 0; i < n; i++)
718 mark_empty (nentries[i]);
719
720 return nentries;
721 }
722
723 /* Similar to find_slot, but without several unwanted side effects:
724 - Does not call equal when it finds an existing entry.
725 - Does not change the count of elements/searches/collisions in the
726 hash table.
727 This function also assumes there are no deleted entries in the table.
728 HASH is the hash value for the element to be inserted. */
729
730 template<typename Descriptor, template<typename Type> class Allocator>
731 typename hash_table<Descriptor, Allocator>::value_type *
732 hash_table<Descriptor, Allocator>::find_empty_slot_for_expand (hashval_t hash)
733 {
734 hashval_t index = hash_table_mod1 (hash, m_size_prime_index);
735 size_t size = m_size;
736 value_type *slot = m_entries + index;
737 hashval_t hash2;
738
739 if (is_empty (*slot))
740 return slot;
741 #ifdef ENABLE_CHECKING
742 gcc_checking_assert (!is_deleted (*slot));
743 #endif
744
745 hash2 = hash_table_mod2 (hash, m_size_prime_index);
746 for (;;)
747 {
748 index += hash2;
749 if (index >= size)
750 index -= size;
751
752 slot = m_entries + index;
753 if (is_empty (*slot))
754 return slot;
755 #ifdef ENABLE_CHECKING
756 gcc_checking_assert (!is_deleted (*slot));
757 #endif
758 }
759 }
760
761 /* The following function changes size of memory allocated for the
762 entries and repeatedly inserts the table elements. The occupancy
763 of the table after the call will be about 50%. Naturally the hash
764 table must already exist. Remember also that the place of the
765 table entries is changed. If memory allocation fails, this function
766 will abort. */
767
768 template<typename Descriptor, template<typename Type> class Allocator>
769 void
770 hash_table<Descriptor, Allocator>::expand ()
771 {
772 value_type *oentries = m_entries;
773 unsigned int oindex = m_size_prime_index;
774 size_t osize = size ();
775 value_type *olimit = oentries + osize;
776 size_t elts = elements ();
777
778 /* Resize only when table after removal of unused elements is either
779 too full or too empty. */
780 unsigned int nindex;
781 size_t nsize;
782 if (elts * 2 > osize || (elts * 8 < osize && osize > 32))
783 {
784 nindex = hash_table_higher_prime_index (elts * 2);
785 nsize = prime_tab[nindex].prime;
786 }
787 else
788 {
789 nindex = oindex;
790 nsize = osize;
791 }
792
793 value_type *nentries = alloc_entries (nsize);
794
795 if (m_gather_mem_stats)
796 hash_table_usage.release_instance_overhead (this, sizeof (value_type)
797 * osize);
798
799 m_entries = nentries;
800 m_size = nsize;
801 m_size_prime_index = nindex;
802 m_n_elements -= m_n_deleted;
803 m_n_deleted = 0;
804
805 value_type *p = oentries;
806 do
807 {
808 value_type &x = *p;
809
810 if (!is_empty (x) && !is_deleted (x))
811 {
812 value_type *q = find_empty_slot_for_expand (Descriptor::hash (x));
813
814 *q = x;
815 }
816
817 p++;
818 }
819 while (p < olimit);
820
821 if (!m_ggc)
822 Allocator <value_type> ::data_free (oentries);
823 else
824 ggc_free (oentries);
825 }
826
827 template<typename Descriptor, template<typename Type> class Allocator>
828 void
829 hash_table<Descriptor, Allocator>::empty ()
830 {
831 size_t size = m_size;
832 value_type *entries = m_entries;
833 int i;
834
835 for (i = size - 1; i >= 0; i--)
836 if (!is_empty (entries[i]) && !is_deleted (entries[i]))
837 Descriptor::remove (entries[i]);
838
839 /* Instead of clearing megabyte, downsize the table. */
840 if (size > 1024*1024 / sizeof (PTR))
841 {
842 int nindex = hash_table_higher_prime_index (1024 / sizeof (PTR));
843 int nsize = prime_tab[nindex].prime;
844
845 if (!m_ggc)
846 Allocator <value_type> ::data_free (m_entries);
847 else
848 ggc_free (m_entries);
849
850 m_entries = alloc_entries (nsize);
851 m_size = nsize;
852 m_size_prime_index = nindex;
853 }
854 else
855 memset (entries, 0, size * sizeof (value_type));
856 m_n_deleted = 0;
857 m_n_elements = 0;
858 }
859
860 /* This function clears a specified SLOT in a hash table. It is
861 useful when you've already done the lookup and don't want to do it
862 again. */
863
864 template<typename Descriptor, template<typename Type> class Allocator>
865 void
866 hash_table<Descriptor, Allocator>::clear_slot (value_type *slot)
867 {
868 gcc_checking_assert (!(slot < m_entries || slot >= m_entries + size ()
869 || is_empty (*slot) || is_deleted (*slot)));
870
871 Descriptor::remove (*slot);
872
873 mark_deleted (*slot);
874 m_n_deleted++;
875 }
876
877 /* This function searches for a hash table entry equal to the given
878 COMPARABLE element starting with the given HASH value. It cannot
879 be used to insert or delete an element. */
880
881 template<typename Descriptor, template<typename Type> class Allocator>
882 typename hash_table<Descriptor, Allocator>::value_type &
883 hash_table<Descriptor, Allocator>
884 ::find_with_hash (const compare_type &comparable, hashval_t hash)
885 {
886 m_searches++;
887 size_t size = m_size;
888 hashval_t index = hash_table_mod1 (hash, m_size_prime_index);
889
890 value_type *entry = &m_entries[index];
891 if (is_empty (*entry)
892 || (!is_deleted (*entry) && Descriptor::equal (*entry, comparable)))
893 return *entry;
894
895 hashval_t hash2 = hash_table_mod2 (hash, m_size_prime_index);
896 for (;;)
897 {
898 m_collisions++;
899 index += hash2;
900 if (index >= size)
901 index -= size;
902
903 entry = &m_entries[index];
904 if (is_empty (*entry)
905 || (!is_deleted (*entry) && Descriptor::equal (*entry, comparable)))
906 return *entry;
907 }
908 }
909
910 /* This function searches for a hash table slot containing an entry
911 equal to the given COMPARABLE element and starting with the given
912 HASH. To delete an entry, call this with insert=NO_INSERT, then
913 call clear_slot on the slot returned (possibly after doing some
914 checks). To insert an entry, call this with insert=INSERT, then
915 write the value you want into the returned slot. When inserting an
916 entry, NULL may be returned if memory allocation fails. */
917
918 template<typename Descriptor, template<typename Type> class Allocator>
919 typename hash_table<Descriptor, Allocator>::value_type *
920 hash_table<Descriptor, Allocator>
921 ::find_slot_with_hash (const compare_type &comparable, hashval_t hash,
922 enum insert_option insert)
923 {
924 if (insert == INSERT && m_size * 3 <= m_n_elements * 4)
925 expand ();
926
927 m_searches++;
928
929 value_type *first_deleted_slot = NULL;
930 hashval_t index = hash_table_mod1 (hash, m_size_prime_index);
931 hashval_t hash2 = hash_table_mod2 (hash, m_size_prime_index);
932 value_type *entry = &m_entries[index];
933 size_t size = m_size;
934 if (is_empty (*entry))
935 goto empty_entry;
936 else if (is_deleted (*entry))
937 first_deleted_slot = &m_entries[index];
938 else if (Descriptor::equal (*entry, comparable))
939 return &m_entries[index];
940
941 for (;;)
942 {
943 m_collisions++;
944 index += hash2;
945 if (index >= size)
946 index -= size;
947
948 entry = &m_entries[index];
949 if (is_empty (*entry))
950 goto empty_entry;
951 else if (is_deleted (*entry))
952 {
953 if (!first_deleted_slot)
954 first_deleted_slot = &m_entries[index];
955 }
956 else if (Descriptor::equal (*entry, comparable))
957 return &m_entries[index];
958 }
959
960 empty_entry:
961 if (insert == NO_INSERT)
962 return NULL;
963
964 if (first_deleted_slot)
965 {
966 m_n_deleted--;
967 mark_empty (*first_deleted_slot);
968 return first_deleted_slot;
969 }
970
971 m_n_elements++;
972 return &m_entries[index];
973 }
974
975 /* This function deletes an element with the given COMPARABLE value
976 from hash table starting with the given HASH. If there is no
977 matching element in the hash table, this function does nothing. */
978
979 template<typename Descriptor, template<typename Type> class Allocator>
980 void
981 hash_table<Descriptor, Allocator>
982 ::remove_elt_with_hash (const compare_type &comparable, hashval_t hash)
983 {
984 value_type *slot = find_slot_with_hash (comparable, hash, NO_INSERT);
985 if (is_empty (*slot))
986 return;
987
988 Descriptor::remove (*slot);
989
990 mark_deleted (*slot);
991 m_n_deleted++;
992 }
993
994 /* This function scans over the entire hash table calling CALLBACK for
995 each live entry. If CALLBACK returns false, the iteration stops.
996 ARGUMENT is passed as CALLBACK's second argument. */
997
998 template<typename Descriptor,
999 template<typename Type> class Allocator>
1000 template<typename Argument,
1001 int (*Callback)
1002 (typename hash_table<Descriptor, Allocator>::value_type *slot,
1003 Argument argument)>
1004 void
1005 hash_table<Descriptor, Allocator>::traverse_noresize (Argument argument)
1006 {
1007 value_type *slot = m_entries;
1008 value_type *limit = slot + size ();
1009
1010 do
1011 {
1012 value_type &x = *slot;
1013
1014 if (!is_empty (x) && !is_deleted (x))
1015 if (! Callback (slot, argument))
1016 break;
1017 }
1018 while (++slot < limit);
1019 }
1020
1021 /* Like traverse_noresize, but does resize the table when it is too empty
1022 to improve effectivity of subsequent calls. */
1023
1024 template <typename Descriptor,
1025 template <typename Type> class Allocator>
1026 template <typename Argument,
1027 int (*Callback)
1028 (typename hash_table<Descriptor, Allocator>::value_type *slot,
1029 Argument argument)>
1030 void
1031 hash_table<Descriptor, Allocator>::traverse (Argument argument)
1032 {
1033 size_t size = m_size;
1034 if (elements () * 8 < size && size > 32)
1035 expand ();
1036
1037 traverse_noresize <Argument, Callback> (argument);
1038 }
1039
1040 /* Slide down the iterator slots until an active entry is found. */
1041
1042 template<typename Descriptor, template<typename Type> class Allocator>
1043 void
1044 hash_table<Descriptor, Allocator>::iterator::slide ()
1045 {
1046 for ( ; m_slot < m_limit; ++m_slot )
1047 {
1048 value_type &x = *m_slot;
1049 if (!is_empty (x) && !is_deleted (x))
1050 return;
1051 }
1052 m_slot = NULL;
1053 m_limit = NULL;
1054 }
1055
1056 /* Bump the iterator. */
1057
1058 template<typename Descriptor, template<typename Type> class Allocator>
1059 inline typename hash_table<Descriptor, Allocator>::iterator &
1060 hash_table<Descriptor, Allocator>::iterator::operator ++ ()
1061 {
1062 ++m_slot;
1063 slide ();
1064 return *this;
1065 }
1066
1067
1068 /* Iterate through the elements of hash_table HTAB,
1069 using hash_table <....>::iterator ITER,
1070 storing each element in RESULT, which is of type TYPE. */
1071
1072 #define FOR_EACH_HASH_TABLE_ELEMENT(HTAB, RESULT, TYPE, ITER) \
1073 for ((ITER) = (HTAB).begin (); \
1074 (ITER) != (HTAB).end () ? (RESULT = *(ITER) , true) : false; \
1075 ++(ITER))
1076
1077 /* ggc walking routines. */
1078
1079 template<typename E>
1080 static inline void
1081 gt_ggc_mx (hash_table<E> *h)
1082 {
1083 typedef hash_table<E> table;
1084
1085 if (!ggc_test_and_set_mark (h->m_entries))
1086 return;
1087
1088 for (size_t i = 0; i < h->m_size; i++)
1089 {
1090 if (table::is_empty (h->m_entries[i])
1091 || table::is_deleted (h->m_entries[i]))
1092 continue;
1093
1094 E::ggc_mx (h->m_entries[i]);
1095 }
1096 }
1097
1098 template<typename D>
1099 static inline void
1100 hashtab_entry_note_pointers (void *obj, void *h, gt_pointer_operator op,
1101 void *cookie)
1102 {
1103 hash_table<D> *map = static_cast<hash_table<D> *> (h);
1104 gcc_checking_assert (map->m_entries == obj);
1105 for (size_t i = 0; i < map->m_size; i++)
1106 {
1107 typedef hash_table<D> table;
1108 if (table::is_empty (map->m_entries[i])
1109 || table::is_deleted (map->m_entries[i]))
1110 continue;
1111
1112 D::pch_nx (map->m_entries[i], op, cookie);
1113 }
1114 }
1115
1116 template<typename D>
1117 static void
1118 gt_pch_nx (hash_table<D> *h)
1119 {
1120 bool success
1121 = gt_pch_note_object (h->m_entries, h, hashtab_entry_note_pointers<D>);
1122 gcc_checking_assert (success);
1123 for (size_t i = 0; i < h->m_size; i++)
1124 {
1125 if (hash_table<D>::is_empty (h->m_entries[i])
1126 || hash_table<D>::is_deleted (h->m_entries[i]))
1127 continue;
1128
1129 D::pch_nx (h->m_entries[i]);
1130 }
1131 }
1132
1133 template<typename D>
1134 static inline void
1135 gt_pch_nx (hash_table<D> *h, gt_pointer_operator op, void *cookie)
1136 {
1137 op (&h->m_entries, cookie);
1138 }
1139
1140 template<typename H>
1141 inline void
1142 gt_cleare_cache (hash_table<H> *h)
1143 {
1144 extern void gt_ggc_mx (typename H::value_type &t);
1145 typedef hash_table<H> table;
1146 if (!h)
1147 return;
1148
1149 for (typename table::iterator iter = h->begin (); iter != h->end (); ++iter)
1150 if (!table::is_empty (*iter) && !table::is_deleted (*iter))
1151 {
1152 int res = H::keep_cache_entry (*iter);
1153 if (res == 0)
1154 h->clear_slot (&*iter);
1155 else if (res != -1)
1156 gt_ggc_mx (*iter);
1157 }
1158 }
1159
1160 #endif /* TYPED_HASHTAB_H */