1 /* A type-safe hash map.
2 Copyright (C) 2014 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
25 #include "hash-table.h"
27 /* implement default behavior for traits when types allow it. */
29 struct default_hashmap_traits
31 /* Hashes the passed in key. */
37 return uintptr_t(p
) >> 3;
40 /* If the value converts to hashval_t just use it. */
42 template<typename T
> static hashval_t
hash (T v
) { return v
; }
44 /* Return true if the two keys passed as arguments are equal. */
48 equal_keys (const T
&a
, const T
&b
)
53 /* Called to dispose of the key and value before marking the entry as
56 template<typename T
> static void remove (T
&v
) { v
.~T (); }
58 /* Mark the passed in entry as being deleted. */
64 mark_key_deleted (e
.m_key
);
67 /* Mark the passed in entry as being empty. */
73 mark_key_empty (e
.m_key
);
76 /* Return true if the passed in entry is marked as deleted. */
82 return e
.m_key
== (void *)1;
85 /* Return true if the passed in entry is marked as empty. */
87 template<typename T
> static bool is_empty (T
&e
) { return e
.m_key
== NULL
; }
92 mark_key_deleted (T
*&k
)
94 k
= reinterpret_cast<T
*> (1);
99 mark_key_empty (T
*&k
)
101 k
= static_cast<T
*> (0);
105 template<typename Key
, typename Value
,
106 typename Traits
= default_hashmap_traits
>
107 class GTY((user
)) hash_map
114 typedef hash_entry value_type
;
115 typedef Key compare_type
;
116 typedef int store_values_directly
;
118 static hashval_t
hash (const hash_entry
&e
)
120 return Traits::hash (e
.m_key
);
123 static bool equal (const hash_entry
&a
, const Key
&b
)
125 return Traits::equal_keys (a
.m_key
, b
);
128 static void remove (hash_entry
&e
) { Traits::remove (e
); }
130 static void mark_deleted (hash_entry
&e
) { Traits::mark_deleted (e
); }
132 static bool is_deleted (const hash_entry
&e
)
134 return Traits::is_deleted (e
);
137 static void mark_empty (hash_entry
&e
) { Traits::mark_empty (e
); }
138 static bool is_empty (const hash_entry
&e
) { return Traits::is_empty (e
); }
140 static void ggc_mx (hash_entry
&e
)
143 gt_ggc_mx (e
.m_value
);
146 static void pch_nx (hash_entry
&e
)
149 gt_pch_nx (e
.m_value
);
152 static void pch_nx (hash_entry
&e
, gt_pointer_operator op
, void *c
)
154 pch_nx_helper (e
.m_key
, op
, c
);
155 pch_nx_helper (e
.m_value
, op
, c
);
161 pch_nx_helper (T
&x
, gt_pointer_operator op
, void *cookie
)
163 gt_pch_nx (&x
, op
, cookie
);
167 pch_nx_helper (int, gt_pointer_operator
, void *)
173 pch_nx_helper (T
*&x
, gt_pointer_operator op
, void *cookie
)
180 explicit hash_map (size_t n
= 13, bool ggc
= false) : m_table (n
, ggc
) {}
182 /* Create a hash_map in ggc memory. */
183 static hash_map
*create_ggc (size_t size
)
185 hash_map
*map
= ggc_alloc
<hash_map
> ();
186 new (map
) hash_map (size
, true);
190 /* If key k isn't already in the map add key k with value v to the map, and
191 return false. Otherwise set the value of the entry for key k to be v and
194 bool put (const Key
&k
, const Value
&v
)
196 hash_entry
*e
= m_table
.find_slot_with_hash (k
, Traits::hash (k
),
198 bool existed
= !hash_entry::is_empty (*e
);
206 /* if the passed in key is in the map return its value otherwise NULL. */
208 Value
*get (const Key
&k
)
210 hash_entry
&e
= m_table
.find_with_hash (k
, Traits::hash (k
));
211 return Traits::is_empty (e
) ? NULL
: &e
.m_value
;
214 /* Return a reference to the value for the passed in key, creating the entry
215 if it doesn't already exist. If existed is not NULL then it is set to false
216 if the key was not previously in the map, and true otherwise. */
218 Value
&get_or_insert (const Key
&k
, bool *existed
= NULL
)
220 hash_entry
*e
= m_table
.find_slot_with_hash (k
, Traits::hash (k
),
222 bool ins
= Traits::is_empty (*e
);
232 void remove (const Key
&k
)
234 m_table
.remove_elt_with_hash (k
, Traits::hash (k
));
237 /* Call the call back on each pair of key and value with the passed in
240 template<typename Arg
, bool (*f
)(const Key
&, const Value
&, Arg
)>
241 void traverse (Arg a
) const
243 for (typename hash_table
<hash_entry
>::iterator iter
= m_table
.begin ();
244 iter
!= m_table
.end (); ++iter
)
245 f ((*iter
).m_key
, (*iter
).m_value
, a
);
248 template<typename Arg
, bool (*f
)(const Key
&, Value
*, Arg
)>
249 void traverse (Arg a
) const
251 for (typename hash_table
<hash_entry
>::iterator iter
= m_table
.begin ();
252 iter
!= m_table
.end (); ++iter
)
253 if (!f ((*iter
).m_key
, &(*iter
).m_value
, a
))
259 template<typename T
, typename U
, typename V
> friend void gt_ggc_mx (hash_map
<T
, U
, V
> *);
260 template<typename T
, typename U
, typename V
> friend void gt_pch_nx (hash_map
<T
, U
, V
> *);
261 template<typename T
, typename U
, typename V
> friend void gt_pch_nx (hash_map
<T
, U
, V
> *, gt_pointer_operator
, void *);
263 hash_table
<hash_entry
> m_table
;
266 /* ggc marking routines. */
268 template<typename K
, typename V
, typename H
>
270 gt_ggc_mx (hash_map
<K
, V
, H
> *h
)
272 gt_ggc_mx (&h
->m_table
);
275 template<typename K
, typename V
, typename H
>
277 gt_pch_nx (hash_map
<K
, V
, H
> *h
)
279 gt_pch_nx (&h
->m_table
);
282 template<typename K
, typename V
, typename H
>
284 gt_pch_nx (hash_map
<K
, V
, H
> *h
, gt_pointer_operator op
, void *cookie
)
286 op (&h
->m_table
.m_entries
, cookie
);