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