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