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