1 /* A type-safe hash table template.
2 Copyright (C) 2012-2015 Free Software Foundation, Inc.
3 Contributed by Lawrence Crowl <crowl@google.com>
5 This file is part of GCC.
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
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
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/>. */
22 /* This file implements a typed hash table.
23 The implementation borrows from libiberty's htab_t in hashtab.h.
28 Users of the hash table generally need to be aware of three types.
30 1. The type being placed into the hash table. This type is called
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
37 - A typedef named 'value_type' to the value type (from above).
39 - A static member function named 'hash' that takes a value_type
40 pointer and returns a hashval_t value.
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.
47 - A static member function named 'equal' that takes a value_type
48 pointer and a compare_type pointer, and returns a bool.
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).
55 3. The type of the hash table itself. (More later.)
57 In very special circumstances, users may need to know about a fourth type.
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.
63 - A static member function named 'data_alloc'. This function
64 allocates the data elements in the table.
66 - A static member function named 'data_free'. This function
67 deallocates the data elements in the table.
69 Hash table are instantiated with two type arguments.
71 * The descriptor type, (2) above.
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.
78 DEFINING A DESCRIPTOR TYPE
80 The first task in using the hash table is to describe the element type.
81 We compose this into a few steps.
83 1. Decide on a removal policy for values stored in the table.
84 This header provides class templates for the two most common
87 * typed_free_remove implements the static 'remove' member function
90 * typed_noop_remove implements the static 'remove' member function
93 You can use these policies by simply deriving the descriptor type
94 from one of those class template, with the appropriate argument.
96 Otherwise, you need to write the static 'remove' member function
97 in the descriptor class.
99 2. Choose a hash function. Write the static 'hash' member function.
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.
106 AN EXAMPLE DESCRIPTOR TYPE
108 Suppose you want to put some_type into the hash table. You could define
109 the descriptor type as follows.
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.
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 *);
122 some_type_hasher::hash (const value_type *e)
123 { ... compute and return a hash value for E ... }
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' ... }
130 AN EXAMPLE HASH_TABLE DECLARATION
132 To instantiate a hash table for some_type:
134 hash_table <some_type_hasher> some_type_hash_table;
136 There is no need to mention some_type directly, as the hash table will
137 obtain it using some_type_hasher::value_type.
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
144 EASY DESCRIPTORS FOR POINTERS
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,
150 hash_table <pointer_hash <whatever_type>> whatever_type_hash_table;
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:
158 extern void consume (some_info *);
160 We define a convenience typedef and the hash table:
162 typedef hash_table <some_info_hasher> info_table_type;
163 info_table_type info_table;
165 Then we write the loop in typical C++ style:
167 for (info_table_type::iterator iter = info_table.begin ();
168 iter != info_table.end ();
170 if ((*iter).status == INFO_READY)
173 Or with common sub-expression elimination:
175 for (info_table_type::iterator iter = info_table.begin ();
176 iter != info_table.end ();
179 some_info &elem = *iter;
180 if (elem.status == INFO_READY)
184 One can also use a more typical GCC style:
186 typedef some_info *some_info_p;
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)
196 #ifndef TYPED_HASHTAB_H
197 #define TYPED_HASHTAB_H
199 #include "statistics.h"
204 #include "mem-stats-traits.h"
205 #include "hash-map-traits.h"
207 template<typename
, typename
, typename
> class hash_map
;
208 template<typename
, typename
> class hash_set
;
210 /* The ordinary memory allocator. */
211 /* FIXME (crowl): This allocator may be extracted for wider sharing later. */
213 template <typename Type
>
216 static Type
*data_alloc (size_t count
);
217 static void data_free (Type
*memory
);
221 /* Allocate memory for COUNT data blocks. */
223 template <typename Type
>
225 xcallocator
<Type
>::data_alloc (size_t count
)
227 return static_cast <Type
*> (xcalloc (count
, sizeof (Type
)));
231 /* Free memory for data blocks. */
233 template <typename Type
>
235 xcallocator
<Type
>::data_free (Type
*memory
)
237 return ::free (memory
);
241 /* Helpful type for removing with free. */
243 template <typename Type
>
244 struct typed_free_remove
246 static inline void remove (Type
*p
);
250 /* Remove with free. */
252 template <typename Type
>
254 typed_free_remove
<Type
>::remove (Type
*p
)
260 /* Helpful type for a no-op remove. */
262 template <typename Type
>
263 struct typed_noop_remove
265 static inline void remove (Type
*p
);
269 /* Remove doing nothing. */
271 template <typename Type
>
273 typed_noop_remove
<Type
>::remove (Type
*p ATTRIBUTE_UNUSED
)
278 /* Pointer hash with a no-op remove method. */
280 template <typename Type
>
281 struct pointer_hash
: typed_noop_remove
<Type
>
283 typedef Type
*value_type
;
284 typedef Type
*compare_type
;
286 static inline hashval_t
hash (const value_type
&);
288 static inline bool equal (const value_type
&existing
,
289 const compare_type
&candidate
);
292 template <typename Type
>
294 pointer_hash
<Type
>::hash (const value_type
&candidate
)
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);
301 template <typename Type
>
303 pointer_hash
<Type
>::equal (const value_type
&existing
,
304 const compare_type
&candidate
)
306 return existing
== candidate
;
309 /* Hasher for entry in gc memory. */
314 typedef T value_type
;
315 typedef T compare_type
;
317 static void remove (T
) {}
322 extern void gt_ggc_mx (T
&);
329 extern void gt_pch_nx (T
&);
334 pch_nx (T
&p
, gt_pointer_operator op
, void *cookie
)
340 /* Hasher for cache entry in gc memory. */
343 struct ggc_cache_hasher
345 typedef T value_type
;
346 typedef T compare_type
;
348 static void remove (T
&) {}
350 /* Entries are weakly held because this is for caches. */
352 static void ggc_mx (T
&) {}
357 extern void gt_pch_nx (T
&);
362 pch_nx (T
&p
, gt_pointer_operator op
, void *cookie
)
367 /* Clear out entries if they are about to be gc'd. */
370 handle_cache_entry (T
&e
)
372 if (e
!= HTAB_EMPTY_ENTRY
&& e
!= HTAB_DELETED_ENTRY
&& !ggc_marked_p (e
))
373 e
= static_cast<T
> (HTAB_DELETED_ENTRY
);
378 /* Table of primes and their inversion information. */
384 hashval_t inv_m2
; /* inverse of prime-2 */
388 extern struct prime_ent
const prime_tab
[];
391 /* Functions for computing hash table indexes. */
393 extern unsigned int hash_table_higher_prime_index (unsigned long n
)
396 /* Return X % Y using multiplicative inverse values INV and SHIFT.
398 The multiplicative inverses computed above are for 32-bit types,
399 and requires that we be able to compute a highpart multiply.
401 FIX: I am not at all convinced that
402 3 loads, 2 multiplications, 3 shifts, and 3 additions
405 on modern systems running a compiler. */
408 mul_mod (hashval_t x
, hashval_t y
, hashval_t inv
, int shift
)
410 hashval_t t1
, t2
, t3
, t4
, q
, r
;
412 t1
= ((uint64_t)x
* inv
) >> 32;
422 /* Compute the primary table index for HASH given current prime index. */
425 hash_table_mod1 (hashval_t hash
, unsigned int index
)
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
);
432 /* Compute the secondary table index for HASH given current prime index. */
435 hash_table_mod2 (hashval_t hash
, unsigned int index
)
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
);
442 template<typename Traits
>
443 struct has_is_deleted
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);
451 template<typename Type
, typename Traits
, bool = has_is_deleted
<Traits
>::value
>
452 struct is_deleted_helper
457 return Traits::is_deleted (v
);
461 template<typename Type
, typename Traits
>
462 struct is_deleted_helper
<Type
*, Traits
, false>
467 return v
== HTAB_DELETED_ENTRY
;
471 template<typename Traits
>
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);
480 template<typename Type
, typename Traits
, bool = has_is_deleted
<Traits
>::value
>
481 struct is_empty_helper
486 return Traits::is_empty (v
);
490 template<typename Type
, typename Traits
>
491 struct is_empty_helper
<Type
*, Traits
, false>
496 return v
== HTAB_EMPTY_ENTRY
;
500 template<typename Traits
>
501 struct has_mark_deleted
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);
509 template<typename Type
, typename Traits
, bool = has_is_deleted
<Traits
>::value
>
510 struct mark_deleted_helper
515 Traits::mark_deleted (v
);
519 template<typename Type
, typename Traits
>
520 struct mark_deleted_helper
<Type
*, Traits
, false>
525 v
= static_cast<Type
*> (HTAB_DELETED_ENTRY
);
529 template<typename Traits
>
530 struct has_mark_empty
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);
538 template<typename Type
, typename Traits
, bool = has_is_deleted
<Traits
>::value
>
539 struct mark_empty_helper
544 Traits::mark_empty (v
);
548 template<typename Type
, typename Traits
>
549 struct mark_empty_helper
<Type
*, Traits
, false>
554 v
= static_cast<Type
*> (HTAB_EMPTY_ENTRY
);
560 /* User-facing hash table type.
562 The table stores elements of type Descriptor::value_type.
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.
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.
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.
577 Specify the template Allocator to allocate and free memory.
578 The default is xcallocator.
580 Storage is an implementation detail and should not be used outside the
584 template <typename Descriptor
,
585 template<typename Type
> class Allocator
= xcallocator
>
588 typedef typename
Descriptor::value_type value_type
;
589 typedef typename
Descriptor::compare_type compare_type
;
592 explicit hash_table (size_t, bool ggc
= false, bool gather_mem_stats
= true,
593 mem_alloc_origin origin
= HASH_TABLE_ORIGIN
597 /* Create a hash_table in gc memory. */
600 create_ggc (size_t n CXX_MEM_STAT_INFO
)
602 hash_table
*table
= ggc_alloc
<hash_table
> ();
603 new (table
) hash_table (n
, true, true, HASH_TABLE_ORIGIN PASS_MEM_STAT
);
607 /* Current size (in entries) of the hash table. */
608 size_t size () const { return m_size
; }
610 /* Return the current number of elements in this hash table. */
611 size_t elements () const { return m_n_elements
- m_n_deleted
; }
613 /* Return the current number of elements in this hash table. */
614 size_t elements_with_deleted () const { return m_n_elements
; }
616 /* This function clears all entries in the given hash table. */
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
623 void clear_slot (value_type
*);
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
);
630 /* Like find_slot_with_hash, but compute the hash value from the element. */
631 value_type
&find (const value_type
&value
)
633 return find_with_hash (value
, Descriptor::hash (value
));
636 value_type
*find_slot (const value_type
&value
, insert_option insert
)
638 return find_slot_with_hash (value
, Descriptor::hash (value
), insert
);
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
);
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
);
656 /* Like remove_elt_with_hash, but compute the hash value from the element. */
657 void remove_elt (const value_type
&value
)
659 remove_elt_with_hash (value
, Descriptor::hash (value
));
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
);
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
);
678 iterator () : m_slot (NULL
), m_limit (NULL
) {}
680 iterator (value_type
*slot
, value_type
*limit
) :
681 m_slot (slot
), m_limit (limit
) {}
683 inline value_type
&operator * () { return *m_slot
; }
685 inline iterator
&operator ++ ();
686 bool operator != (const iterator
&other
) const
688 return m_slot
!= other
.m_slot
|| m_limit
!= other
.m_limit
;
696 iterator
begin () const
698 iterator
iter (m_entries
, m_entries
+ m_size
);
703 iterator
end () const { return iterator (); }
705 double collisions () const
707 return m_searches
? static_cast <double> (m_collisions
) / m_searches
: 0;
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
> *,
720 template<typename T
> friend void gt_pch_nx (hash_table
<T
> *,
721 gt_pointer_operator
, void *);
723 value_type
*alloc_entries (size_t n CXX_MEM_STAT_INFO
) const;
724 value_type
*find_empty_slot_for_expand (hashval_t
);
726 static bool is_deleted (value_type
&v
)
728 return is_deleted_helper
<value_type
, Descriptor
>::call (v
);
730 static bool is_empty (value_type
&v
)
732 return is_empty_helper
<value_type
, Descriptor
>::call (v
);
735 static void mark_deleted (value_type
&v
)
737 return mark_deleted_helper
<value_type
, Descriptor
>::call (v
);
740 static void mark_empty (value_type
&v
)
742 return mark_empty_helper
<value_type
, Descriptor
>::call (v
);
746 typename
Descriptor::value_type
*m_entries
;
750 /* Current number of elements including also deleted elements. */
753 /* Current number of deleted elements in the table. */
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
;
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
;
764 /* Current size (in entries) of the hash table, as an index into the
766 unsigned int m_size_prime_index
;
768 /* if m_entries is stored in ggc memory. */
771 /* If we should gather memory statistics for the table. */
772 bool m_gather_mem_stats
;
775 /* As mem-stats.h heavily utilizes hash maps (hash tables), we have to include
776 mem-stats.h after hash_table declaration. */
778 #include "mem-stats.h"
779 #include "hash-map.h"
781 extern mem_alloc_description
<mem_usage
> hash_table_usage
;
783 /* Support function for statistics. */
784 extern void dump_hash_table_loc_statistics (void);
786 template<typename Descriptor
, template<typename Type
> class Allocator
>
787 hash_table
<Descriptor
, Allocator
>::hash_table (size_t size
, bool ggc
, bool
789 mem_alloc_origin origin
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
)
794 unsigned int size_prime_index
;
796 size_prime_index
= hash_table_higher_prime_index (size
);
797 size
= prime_tab
[size_prime_index
].prime
;
799 if (m_gather_mem_stats
)
800 hash_table_usage
.register_descriptor (this, origin
, ggc
801 FINAL_PASS_MEM_STAT
);
803 m_entries
= alloc_entries (size PASS_MEM_STAT
);
805 m_size_prime_index
= size_prime_index
;
808 template<typename Descriptor
, template<typename Type
> class Allocator
>
809 hash_table
<Descriptor
, Allocator
>::~hash_table ()
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
]);
816 Allocator
<value_type
> ::data_free (m_entries
);
818 ggc_free (m_entries
);
820 if (m_gather_mem_stats
)
821 hash_table_usage
.release_instance_overhead (this,
822 sizeof (value_type
) * m_size
,
826 /* This function returns an array of empty hash table elements. */
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
832 value_type
*nentries
;
834 if (m_gather_mem_stats
)
835 hash_table_usage
.register_instance_overhead (sizeof (value_type
) * n
, this);
838 nentries
= Allocator
<value_type
> ::data_alloc (n
);
840 nentries
= ::ggc_cleared_vec_alloc
<value_type
> (n PASS_MEM_STAT
);
842 gcc_assert (nentries
!= NULL
);
843 for (size_t i
= 0; i
< n
; i
++)
844 mark_empty (nentries
[i
]);
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
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. */
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
)
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
;
865 if (is_empty (*slot
))
867 #ifdef ENABLE_CHECKING
868 gcc_checking_assert (!is_deleted (*slot
));
871 hash2
= hash_table_mod2 (hash
, m_size_prime_index
);
878 slot
= m_entries
+ index
;
879 if (is_empty (*slot
))
881 #ifdef ENABLE_CHECKING
882 gcc_checking_assert (!is_deleted (*slot
));
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
894 template<typename Descriptor
, template<typename Type
> class Allocator
>
896 hash_table
<Descriptor
, Allocator
>::expand ()
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 ();
904 /* Resize only when table after removal of unused elements is either
905 too full or too empty. */
908 if (elts
* 2 > osize
|| (elts
* 8 < osize
&& osize
> 32))
910 nindex
= hash_table_higher_prime_index (elts
* 2);
911 nsize
= prime_tab
[nindex
].prime
;
919 value_type
*nentries
= alloc_entries (nsize
);
921 if (m_gather_mem_stats
)
922 hash_table_usage
.release_instance_overhead (this, sizeof (value_type
)
925 m_entries
= nentries
;
927 m_size_prime_index
= nindex
;
928 m_n_elements
-= m_n_deleted
;
931 value_type
*p
= oentries
;
936 if (!is_empty (x
) && !is_deleted (x
))
938 value_type
*q
= find_empty_slot_for_expand (Descriptor::hash (x
));
948 Allocator
<value_type
> ::data_free (oentries
);
953 template<typename Descriptor
, template<typename Type
> class Allocator
>
955 hash_table
<Descriptor
, Allocator
>::empty ()
957 size_t size
= m_size
;
958 value_type
*entries
= m_entries
;
961 for (i
= size
- 1; i
>= 0; i
--)
962 if (!is_empty (entries
[i
]) && !is_deleted (entries
[i
]))
963 Descriptor::remove (entries
[i
]);
965 /* Instead of clearing megabyte, downsize the table. */
966 if (size
> 1024*1024 / sizeof (PTR
))
968 int nindex
= hash_table_higher_prime_index (1024 / sizeof (PTR
));
969 int nsize
= prime_tab
[nindex
].prime
;
972 Allocator
<value_type
> ::data_free (m_entries
);
974 ggc_free (m_entries
);
976 m_entries
= alloc_entries (nsize
);
978 m_size_prime_index
= nindex
;
981 memset (entries
, 0, size
* sizeof (value_type
));
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
990 template<typename Descriptor
, template<typename Type
> class Allocator
>
992 hash_table
<Descriptor
, Allocator
>::clear_slot (value_type
*slot
)
994 gcc_checking_assert (!(slot
< m_entries
|| slot
>= m_entries
+ size ()
995 || is_empty (*slot
) || is_deleted (*slot
)));
997 Descriptor::remove (*slot
);
999 mark_deleted (*slot
);
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. */
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
)
1013 size_t size
= m_size
;
1014 hashval_t index
= hash_table_mod1 (hash
, m_size_prime_index
);
1016 value_type
*entry
= &m_entries
[index
];
1017 if (is_empty (*entry
)
1018 || (!is_deleted (*entry
) && Descriptor::equal (*entry
, comparable
)))
1021 hashval_t hash2
= hash_table_mod2 (hash
, m_size_prime_index
);
1029 entry
= &m_entries
[index
];
1030 if (is_empty (*entry
)
1031 || (!is_deleted (*entry
) && Descriptor::equal (*entry
, comparable
)))
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. */
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
)
1050 if (insert
== INSERT
&& m_size
* 3 <= m_n_elements
* 4)
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
))
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
];
1074 entry
= &m_entries
[index
];
1075 if (is_empty (*entry
))
1077 else if (is_deleted (*entry
))
1079 if (!first_deleted_slot
)
1080 first_deleted_slot
= &m_entries
[index
];
1082 else if (Descriptor::equal (*entry
, comparable
))
1083 return &m_entries
[index
];
1087 if (insert
== NO_INSERT
)
1090 if (first_deleted_slot
)
1093 mark_empty (*first_deleted_slot
);
1094 return first_deleted_slot
;
1098 return &m_entries
[index
];
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. */
1105 template<typename Descriptor
, template<typename Type
> class Allocator
>
1107 hash_table
<Descriptor
, Allocator
>
1108 ::remove_elt_with_hash (const compare_type
&comparable
, hashval_t hash
)
1110 value_type
*slot
= find_slot_with_hash (comparable
, hash
, NO_INSERT
);
1111 if (is_empty (*slot
))
1114 Descriptor::remove (*slot
);
1116 mark_deleted (*slot
);
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. */
1124 template<typename Descriptor
,
1125 template<typename Type
> class Allocator
>
1126 template<typename Argument
,
1128 (typename hash_table
<Descriptor
, Allocator
>::value_type
*slot
,
1131 hash_table
<Descriptor
, Allocator
>::traverse_noresize (Argument argument
)
1133 value_type
*slot
= m_entries
;
1134 value_type
*limit
= slot
+ size ();
1138 value_type
&x
= *slot
;
1140 if (!is_empty (x
) && !is_deleted (x
))
1141 if (! Callback (slot
, argument
))
1144 while (++slot
< limit
);
1147 /* Like traverse_noresize, but does resize the table when it is too empty
1148 to improve effectivity of subsequent calls. */
1150 template <typename Descriptor
,
1151 template <typename Type
> class Allocator
>
1152 template <typename Argument
,
1154 (typename hash_table
<Descriptor
, Allocator
>::value_type
*slot
,
1157 hash_table
<Descriptor
, Allocator
>::traverse (Argument argument
)
1159 size_t size
= m_size
;
1160 if (elements () * 8 < size
&& size
> 32)
1163 traverse_noresize
<Argument
, Callback
> (argument
);
1166 /* Slide down the iterator slots until an active entry is found. */
1168 template<typename Descriptor
, template<typename Type
> class Allocator
>
1170 hash_table
<Descriptor
, Allocator
>::iterator::slide ()
1172 for ( ; m_slot
< m_limit
; ++m_slot
)
1174 value_type
&x
= *m_slot
;
1175 if (!is_empty (x
) && !is_deleted (x
))
1182 /* Bump the iterator. */
1184 template<typename Descriptor
, template<typename Type
> class Allocator
>
1185 inline typename hash_table
<Descriptor
, Allocator
>::iterator
&
1186 hash_table
<Descriptor
, Allocator
>::iterator::operator ++ ()
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. */
1198 #define FOR_EACH_HASH_TABLE_ELEMENT(HTAB, RESULT, TYPE, ITER) \
1199 for ((ITER) = (HTAB).begin (); \
1200 (ITER) != (HTAB).end () ? (RESULT = *(ITER) , true) : false; \
1203 /* ggc walking routines. */
1205 template<typename E
>
1207 gt_ggc_mx (hash_table
<E
> *h
)
1209 typedef hash_table
<E
> table
;
1211 if (!ggc_test_and_set_mark (h
->m_entries
))
1214 for (size_t i
= 0; i
< h
->m_size
; i
++)
1216 if (table::is_empty (h
->m_entries
[i
])
1217 || table::is_deleted (h
->m_entries
[i
]))
1220 E::ggc_mx (h
->m_entries
[i
]);
1224 template<typename D
>
1226 hashtab_entry_note_pointers (void *obj
, void *h
, gt_pointer_operator op
,
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
++)
1233 typedef hash_table
<D
> table
;
1234 if (table::is_empty (map
->m_entries
[i
])
1235 || table::is_deleted (map
->m_entries
[i
]))
1238 D::pch_nx (map
->m_entries
[i
], op
, cookie
);
1242 template<typename D
>
1244 gt_pch_nx (hash_table
<D
> *h
)
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
++)
1251 if (hash_table
<D
>::is_empty (h
->m_entries
[i
])
1252 || hash_table
<D
>::is_deleted (h
->m_entries
[i
]))
1255 D::pch_nx (h
->m_entries
[i
]);
1259 template<typename D
>
1261 gt_pch_nx (hash_table
<D
> *h
, gt_pointer_operator op
, void *cookie
)
1263 op (&h
->m_entries
, cookie
);
1266 template<typename H
>
1268 gt_cleare_cache (hash_table
<H
> *h
)
1273 for (typename hash_table
<H
>::iterator iter
= h
->begin (); iter
!= h
->end ();
1275 H::handle_cache_entry (*iter
);
1278 #endif /* TYPED_HASHTAB_H */