comparison gcc/hash-table.h @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents 84e7813d76e9
children
comparison
equal deleted inserted replaced
131:84e7813d76e9 145:1830386684a0
1 /* A type-safe hash table template. 1 /* A type-safe hash table template.
2 Copyright (C) 2012-2018 Free Software Foundation, Inc. 2 Copyright (C) 2012-2020 Free Software Foundation, Inc.
3 Contributed by Lawrence Crowl <crowl@google.com> 3 Contributed by Lawrence Crowl <crowl@google.com>
4 4
5 This file is part of GCC. 5 This file is part of GCC.
6 6
7 GCC is free software; you can redistribute it and/or modify it under 7 GCC is free software; you can redistribute it and/or modify it under
33 2. The type used to describe how to handle the value type within 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 34 the hash table. This descriptor type provides the hash table with
35 several things. 35 several things.
36 36
37 - A typedef named 'value_type' to the value type (from above). 37 - A typedef named 'value_type' to the value type (from above).
38 Provided a suitable Descriptor class it may be a user-defined,
39 non-POD type.
38 40
39 - A static member function named 'hash' that takes a value_type 41 - A static member function named 'hash' that takes a value_type
40 (or 'const value_type &') and returns a hashval_t value. 42 (or 'const value_type &') and returns a hashval_t value.
41 43
42 - A typedef named 'compare_type' that is used to test when a value 44 - A typedef named 'compare_type' that is used to test when a value
43 is found. This type is the comparison type. Usually, it will be the 45 is found. This type is the comparison type. Usually, it will be
44 same as value_type. If it is not the same type, you must generally 46 the same as value_type and may be a user-defined, non-POD type.
45 explicitly compute hash values and pass them to the hash table. 47 If it is not the same type, you must generally explicitly compute
48 hash values and pass them to the hash table.
46 49
47 - A static member function named 'equal' that takes a value_type 50 - A static member function named 'equal' that takes a value_type
48 and a compare_type, and returns a bool. Both arguments can be 51 and a compare_type, and returns a bool. Both arguments can be
49 const references. 52 const references.
50 53
165 168
166 You can then use any of the functions in hash_table's public interface. 169 You can then use any of the functions in hash_table's public interface.
167 See hash_table for details. The interface is very similar to libiberty's 170 See hash_table for details. The interface is very similar to libiberty's
168 htab_t. 171 htab_t.
169 172
173 If a hash table is used only in some rare cases, it is possible
174 to construct the hash_table lazily before first use. This is done
175 through:
176
177 hash_table <some_type_hasher, true> some_type_hash_table;
178
179 which will cause whatever methods actually need the allocated entries
180 array to allocate it later.
181
170 182
171 EASY DESCRIPTORS FOR POINTERS 183 EASY DESCRIPTORS FOR POINTERS
172 184
173 There are four descriptors for pointer elements, one for each of 185 There are four descriptors for pointer elements, one for each of
174 the removal policies above: 186 the removal policies above:
239 #include "mem-stats-traits.h" 251 #include "mem-stats-traits.h"
240 #include "hash-traits.h" 252 #include "hash-traits.h"
241 #include "hash-map-traits.h" 253 #include "hash-map-traits.h"
242 254
243 template<typename, typename, typename> class hash_map; 255 template<typename, typename, typename> class hash_map;
244 template<typename, typename> class hash_set; 256 template<typename, bool, typename> class hash_set;
245 257
246 /* The ordinary memory allocator. */ 258 /* The ordinary memory allocator. */
247 /* FIXME (crowl): This allocator may be extracted for wider sharing later. */ 259 /* FIXME (crowl): This allocator may be extracted for wider sharing later. */
248 260
249 template <typename Type> 261 template <typename Type>
284 hashval_t shift; 296 hashval_t shift;
285 }; 297 };
286 298
287 extern struct prime_ent const prime_tab[]; 299 extern struct prime_ent const prime_tab[];
288 300
301 /* Limit number of comparisons when calling hash_table<>::verify. */
302 extern unsigned int hash_table_sanitize_eq_limit;
289 303
290 /* Functions for computing hash table indexes. */ 304 /* Functions for computing hash table indexes. */
291 305
292 extern unsigned int hash_table_higher_prime_index (unsigned long n) 306 extern unsigned int hash_table_higher_prime_index (unsigned long n)
293 ATTRIBUTE_PURE; 307 ATTRIBUTE_PURE;
308
309 extern ATTRIBUTE_NORETURN ATTRIBUTE_COLD void hashtab_chk_error ();
294 310
295 /* Return X % Y using multiplicative inverse values INV and SHIFT. 311 /* Return X % Y using multiplicative inverse values INV and SHIFT.
296 312
297 The multiplicative inverses computed above are for 32-bit types, 313 The multiplicative inverses computed above are for 32-bit types,
298 and requires that we be able to compute a highpart multiply. 314 and requires that we be able to compute a highpart multiply.
351 367
352 Storage is an implementation detail and should not be used outside the 368 Storage is an implementation detail and should not be used outside the
353 hash table code. 369 hash table code.
354 370
355 */ 371 */
356 template <typename Descriptor, 372 template <typename Descriptor, bool Lazy = false,
357 template<typename Type> class Allocator = xcallocator> 373 template<typename Type> class Allocator = xcallocator>
358 class hash_table 374 class hash_table
359 { 375 {
360 typedef typename Descriptor::value_type value_type; 376 typedef typename Descriptor::value_type value_type;
361 typedef typename Descriptor::compare_type compare_type; 377 typedef typename Descriptor::compare_type compare_type;
362 378
363 public: 379 public:
364 explicit hash_table (size_t, bool ggc = false, 380 explicit hash_table (size_t, bool ggc = false,
381 bool sanitize_eq_and_hash = true,
365 bool gather_mem_stats = GATHER_STATISTICS, 382 bool gather_mem_stats = GATHER_STATISTICS,
366 mem_alloc_origin origin = HASH_TABLE_ORIGIN 383 mem_alloc_origin origin = HASH_TABLE_ORIGIN
367 CXX_MEM_STAT_INFO); 384 CXX_MEM_STAT_INFO);
368 explicit hash_table (const hash_table &, bool ggc = false, 385 explicit hash_table (const hash_table &, bool ggc = false,
386 bool sanitize_eq_and_hash = true,
369 bool gather_mem_stats = GATHER_STATISTICS, 387 bool gather_mem_stats = GATHER_STATISTICS,
370 mem_alloc_origin origin = HASH_TABLE_ORIGIN 388 mem_alloc_origin origin = HASH_TABLE_ORIGIN
371 CXX_MEM_STAT_INFO); 389 CXX_MEM_STAT_INFO);
372 ~hash_table (); 390 ~hash_table ();
373 391
374 /* Create a hash_table in gc memory. */ 392 /* Create a hash_table in gc memory. */
375 static hash_table * 393 static hash_table *
376 create_ggc (size_t n CXX_MEM_STAT_INFO) 394 create_ggc (size_t n, bool sanitize_eq_and_hash = true CXX_MEM_STAT_INFO)
377 { 395 {
378 hash_table *table = ggc_alloc<hash_table> (); 396 hash_table *table = ggc_alloc<hash_table> ();
379 new (table) hash_table (n, true, GATHER_STATISTICS, 397 new (table) hash_table (n, true, sanitize_eq_and_hash, GATHER_STATISTICS,
380 HASH_TABLE_ORIGIN PASS_MEM_STAT); 398 HASH_TABLE_ORIGIN PASS_MEM_STAT);
381 return table; 399 return table;
382 } 400 }
383 401
384 /* Current size (in entries) of the hash table. */ 402 /* Current size (in entries) of the hash table. */
390 /* Return the current number of elements in this hash table. */ 408 /* Return the current number of elements in this hash table. */
391 size_t elements_with_deleted () const { return m_n_elements; } 409 size_t elements_with_deleted () const { return m_n_elements; }
392 410
393 /* This function clears all entries in this hash table. */ 411 /* This function clears all entries in this hash table. */
394 void empty () { if (elements ()) empty_slow (); } 412 void empty () { if (elements ()) empty_slow (); }
413
414 /* Return true when there are no elements in this hash table. */
415 bool is_empty () const { return elements () == 0; }
395 416
396 /* This function clears a specified SLOT in a hash table. It is 417 /* This function clears a specified SLOT in a hash table. It is
397 useful when you've already done the lookup and don't want to do it 418 useful when you've already done the lookup and don't want to do it
398 again. */ 419 again. */
399 void clear_slot (value_type *); 420 void clear_slot (value_type *);
420 call clear_slot on the slot returned (possibly after doing some 441 call clear_slot on the slot returned (possibly after doing some
421 checks). To insert an entry, call this with insert=INSERT, then 442 checks). To insert an entry, call this with insert=INSERT, then
422 write the value you want into the returned slot. When inserting an 443 write the value you want into the returned slot. When inserting an
423 entry, NULL may be returned if memory allocation fails. */ 444 entry, NULL may be returned if memory allocation fails. */
424 value_type *find_slot_with_hash (const compare_type &comparable, 445 value_type *find_slot_with_hash (const compare_type &comparable,
425 hashval_t hash, enum insert_option insert); 446 hashval_t hash, enum insert_option insert);
426 447
427 /* This function deletes an element with the given COMPARABLE value 448 /* This function deletes an element with the given COMPARABLE value
428 from hash table starting with the given HASH. If there is no 449 from hash table starting with the given HASH. If there is no
429 matching element in the hash table, this function does nothing. */ 450 matching element in the hash table, this function does nothing. */
430 void remove_elt_with_hash (const compare_type &, hashval_t); 451 void remove_elt_with_hash (const compare_type &, hashval_t);
470 value_type *m_limit; 491 value_type *m_limit;
471 }; 492 };
472 493
473 iterator begin () const 494 iterator begin () const
474 { 495 {
496 if (Lazy && m_entries == NULL)
497 return iterator ();
475 iterator iter (m_entries, m_entries + m_size); 498 iterator iter (m_entries, m_entries + m_size);
476 iter.slide (); 499 iter.slide ();
477 return iter; 500 return iter;
478 } 501 }
479 502
483 { 506 {
484 return m_searches ? static_cast <double> (m_collisions) / m_searches : 0; 507 return m_searches ? static_cast <double> (m_collisions) / m_searches : 0;
485 } 508 }
486 509
487 private: 510 private:
511 /* FIXME: Make the class assignable. See pr90959. */
512 void operator= (hash_table&);
513
488 template<typename T> friend void gt_ggc_mx (hash_table<T> *); 514 template<typename T> friend void gt_ggc_mx (hash_table<T> *);
489 template<typename T> friend void gt_pch_nx (hash_table<T> *); 515 template<typename T> friend void gt_pch_nx (hash_table<T> *);
490 template<typename T> friend void 516 template<typename T> friend void
491 hashtab_entry_note_pointers (void *, void *, gt_pointer_operator, void *); 517 hashtab_entry_note_pointers (void *, void *, gt_pointer_operator, void *);
492 template<typename T, typename U, typename V> friend void 518 template<typename T, typename U, typename V> friend void
493 gt_pch_nx (hash_map<T, U, V> *, gt_pointer_operator, void *); 519 gt_pch_nx (hash_map<T, U, V> *, gt_pointer_operator, void *);
494 template<typename T, typename U> friend void gt_pch_nx (hash_set<T, U> *, 520 template<typename T, typename U>
495 gt_pointer_operator, 521 friend void gt_pch_nx (hash_set<T, false, U> *, gt_pointer_operator, void *);
496 void *);
497 template<typename T> friend void gt_pch_nx (hash_table<T> *, 522 template<typename T> friend void gt_pch_nx (hash_table<T> *,
498 gt_pointer_operator, void *); 523 gt_pointer_operator, void *);
499 524
500 template<typename T> friend void gt_cleare_cache (hash_table<T> *); 525 template<typename T> friend void gt_cleare_cache (hash_table<T> *);
501 526
502 void empty_slow (); 527 void empty_slow ();
503 528
504 value_type *alloc_entries (size_t n CXX_MEM_STAT_INFO) const; 529 value_type *alloc_entries (size_t n CXX_MEM_STAT_INFO) const;
505 value_type *find_empty_slot_for_expand (hashval_t); 530 value_type *find_empty_slot_for_expand (hashval_t);
531 void verify (const compare_type &comparable, hashval_t hash);
506 bool too_empty_p (unsigned int); 532 bool too_empty_p (unsigned int);
507 void expand (); 533 void expand ();
508 static bool is_deleted (value_type &v) 534 static bool is_deleted (value_type &v)
509 { 535 {
510 return Descriptor::is_deleted (v); 536 return Descriptor::is_deleted (v);
549 unsigned int m_size_prime_index; 575 unsigned int m_size_prime_index;
550 576
551 /* if m_entries is stored in ggc memory. */ 577 /* if m_entries is stored in ggc memory. */
552 bool m_ggc; 578 bool m_ggc;
553 579
580 /* True if the table should be sanitized for equal and hash functions. */
581 bool m_sanitize_eq_and_hash;
582
554 /* If we should gather memory statistics for the table. */ 583 /* If we should gather memory statistics for the table. */
584 #if GATHER_STATISTICS
555 bool m_gather_mem_stats; 585 bool m_gather_mem_stats;
586 #else
587 static const bool m_gather_mem_stats = false;
588 #endif
556 }; 589 };
557 590
558 /* As mem-stats.h heavily utilizes hash maps (hash tables), we have to include 591 /* As mem-stats.h heavily utilizes hash maps (hash tables), we have to include
559 mem-stats.h after hash_table declaration. */ 592 mem-stats.h after hash_table declaration. */
560 593
564 extern mem_alloc_description<mem_usage>& hash_table_usage (void); 597 extern mem_alloc_description<mem_usage>& hash_table_usage (void);
565 598
566 /* Support function for statistics. */ 599 /* Support function for statistics. */
567 extern void dump_hash_table_loc_statistics (void); 600 extern void dump_hash_table_loc_statistics (void);
568 601
569 template<typename Descriptor, template<typename Type> class Allocator> 602 template<typename Descriptor, bool Lazy,
570 hash_table<Descriptor, Allocator>::hash_table (size_t size, bool ggc, bool 603 template<typename Type> class Allocator>
571 gather_mem_stats, 604 hash_table<Descriptor, Lazy, Allocator>::hash_table (size_t size, bool ggc,
572 mem_alloc_origin origin 605 bool sanitize_eq_and_hash,
573 MEM_STAT_DECL) : 606 bool gather_mem_stats
607 ATTRIBUTE_UNUSED,
608 mem_alloc_origin origin
609 MEM_STAT_DECL) :
574 m_n_elements (0), m_n_deleted (0), m_searches (0), m_collisions (0), 610 m_n_elements (0), m_n_deleted (0), m_searches (0), m_collisions (0),
575 m_ggc (ggc), m_gather_mem_stats (gather_mem_stats) 611 m_ggc (ggc), m_sanitize_eq_and_hash (sanitize_eq_and_hash)
612 #if GATHER_STATISTICS
613 , m_gather_mem_stats (gather_mem_stats)
614 #endif
576 { 615 {
577 unsigned int size_prime_index; 616 unsigned int size_prime_index;
578 617
579 size_prime_index = hash_table_higher_prime_index (size); 618 size_prime_index = hash_table_higher_prime_index (size);
580 size = prime_tab[size_prime_index].prime; 619 size = prime_tab[size_prime_index].prime;
620
621 if (m_gather_mem_stats)
622 hash_table_usage ().register_descriptor (this, origin, ggc
623 FINAL_PASS_MEM_STAT);
624
625 if (Lazy)
626 m_entries = NULL;
627 else
628 m_entries = alloc_entries (size PASS_MEM_STAT);
629 m_size = size;
630 m_size_prime_index = size_prime_index;
631 }
632
633 template<typename Descriptor, bool Lazy,
634 template<typename Type> class Allocator>
635 hash_table<Descriptor, Lazy, Allocator>::hash_table (const hash_table &h,
636 bool ggc,
637 bool sanitize_eq_and_hash,
638 bool gather_mem_stats
639 ATTRIBUTE_UNUSED,
640 mem_alloc_origin origin
641 MEM_STAT_DECL) :
642 m_n_elements (h.m_n_elements), m_n_deleted (h.m_n_deleted),
643 m_searches (0), m_collisions (0), m_ggc (ggc),
644 m_sanitize_eq_and_hash (sanitize_eq_and_hash)
645 #if GATHER_STATISTICS
646 , m_gather_mem_stats (gather_mem_stats)
647 #endif
648 {
649 size_t size = h.m_size;
581 650
582 if (m_gather_mem_stats) 651 if (m_gather_mem_stats)
583 hash_table_usage ().register_descriptor (this, origin, ggc 652 hash_table_usage ().register_descriptor (this, origin, ggc
584 FINAL_PASS_MEM_STAT); 653 FINAL_PASS_MEM_STAT);
585 654
586 m_entries = alloc_entries (size PASS_MEM_STAT); 655 if (Lazy && h.m_entries == NULL)
587 m_size = size; 656 m_entries = NULL;
588 m_size_prime_index = size_prime_index; 657 else
589 } 658 {
590 659 value_type *nentries = alloc_entries (size PASS_MEM_STAT);
591 template<typename Descriptor, template<typename Type> class Allocator> 660 for (size_t i = 0; i < size; ++i)
592 hash_table<Descriptor, Allocator>::hash_table (const hash_table &h, bool ggc, 661 {
593 bool gather_mem_stats, 662 value_type &entry = h.m_entries[i];
594 mem_alloc_origin origin 663 if (is_deleted (entry))
595 MEM_STAT_DECL) : 664 mark_deleted (nentries[i]);
596 m_n_elements (h.m_n_elements), m_n_deleted (h.m_n_deleted), 665 else if (!is_empty (entry))
597 m_searches (0), m_collisions (0), m_ggc (ggc), 666 new ((void*) (nentries + i)) value_type (entry);
598 m_gather_mem_stats (gather_mem_stats) 667 }
599 { 668 m_entries = nentries;
600 size_t size = h.m_size; 669 }
601
602 if (m_gather_mem_stats)
603 hash_table_usage ().register_descriptor (this, origin, ggc
604 FINAL_PASS_MEM_STAT);
605
606 value_type *nentries = alloc_entries (size PASS_MEM_STAT);
607 for (size_t i = 0; i < size; ++i)
608 {
609 value_type &entry = h.m_entries[i];
610 if (is_deleted (entry))
611 mark_deleted (nentries[i]);
612 else if (!is_empty (entry))
613 nentries[i] = entry;
614 }
615 m_entries = nentries;
616 m_size = size; 670 m_size = size;
617 m_size_prime_index = h.m_size_prime_index; 671 m_size_prime_index = h.m_size_prime_index;
618 } 672 }
619 673
620 template<typename Descriptor, template<typename Type> class Allocator> 674 template<typename Descriptor, bool Lazy,
621 hash_table<Descriptor, Allocator>::~hash_table () 675 template<typename Type> class Allocator>
622 { 676 hash_table<Descriptor, Lazy, Allocator>::~hash_table ()
623 for (size_t i = m_size - 1; i < m_size; i--) 677 {
624 if (!is_empty (m_entries[i]) && !is_deleted (m_entries[i])) 678 if (!Lazy || m_entries)
625 Descriptor::remove (m_entries[i]); 679 {
626 680 for (size_t i = m_size - 1; i < m_size; i--)
627 if (!m_ggc) 681 if (!is_empty (m_entries[i]) && !is_deleted (m_entries[i]))
628 Allocator <value_type> ::data_free (m_entries); 682 Descriptor::remove (m_entries[i]);
629 else 683
630 ggc_free (m_entries); 684 if (!m_ggc)
631 685 Allocator <value_type> ::data_free (m_entries);
632 if (m_gather_mem_stats) 686 else
633 hash_table_usage ().release_instance_overhead (this, 687 ggc_free (m_entries);
634 sizeof (value_type) * m_size, 688 if (m_gather_mem_stats)
635 true); 689 hash_table_usage ().release_instance_overhead (this,
690 sizeof (value_type)
691 * m_size, true);
692 }
693 else if (m_gather_mem_stats)
694 hash_table_usage ().unregister_descriptor (this);
636 } 695 }
637 696
638 /* This function returns an array of empty hash table elements. */ 697 /* This function returns an array of empty hash table elements. */
639 698
640 template<typename Descriptor, template<typename Type> class Allocator> 699 template<typename Descriptor, bool Lazy,
641 inline typename hash_table<Descriptor, Allocator>::value_type * 700 template<typename Type> class Allocator>
642 hash_table<Descriptor, Allocator>::alloc_entries (size_t n MEM_STAT_DECL) const 701 inline typename hash_table<Descriptor, Lazy, Allocator>::value_type *
702 hash_table<Descriptor, Lazy,
703 Allocator>::alloc_entries (size_t n MEM_STAT_DECL) const
643 { 704 {
644 value_type *nentries; 705 value_type *nentries;
645 706
646 if (m_gather_mem_stats) 707 if (m_gather_mem_stats)
647 hash_table_usage ().register_instance_overhead (sizeof (value_type) * n, this); 708 hash_table_usage ().register_instance_overhead (sizeof (value_type) * n, this);
650 nentries = Allocator <value_type> ::data_alloc (n); 711 nentries = Allocator <value_type> ::data_alloc (n);
651 else 712 else
652 nentries = ::ggc_cleared_vec_alloc<value_type> (n PASS_MEM_STAT); 713 nentries = ::ggc_cleared_vec_alloc<value_type> (n PASS_MEM_STAT);
653 714
654 gcc_assert (nentries != NULL); 715 gcc_assert (nentries != NULL);
655 for (size_t i = 0; i < n; i++) 716 if (!Descriptor::empty_zero_p)
656 mark_empty (nentries[i]); 717 for (size_t i = 0; i < n; i++)
718 mark_empty (nentries[i]);
657 719
658 return nentries; 720 return nentries;
659 } 721 }
660 722
661 /* Similar to find_slot, but without several unwanted side effects: 723 /* Similar to find_slot, but without several unwanted side effects:
663 - Does not change the count of elements/searches/collisions in the 725 - Does not change the count of elements/searches/collisions in the
664 hash table. 726 hash table.
665 This function also assumes there are no deleted entries in the table. 727 This function also assumes there are no deleted entries in the table.
666 HASH is the hash value for the element to be inserted. */ 728 HASH is the hash value for the element to be inserted. */
667 729
668 template<typename Descriptor, template<typename Type> class Allocator> 730 template<typename Descriptor, bool Lazy,
669 typename hash_table<Descriptor, Allocator>::value_type * 731 template<typename Type> class Allocator>
670 hash_table<Descriptor, Allocator>::find_empty_slot_for_expand (hashval_t hash) 732 typename hash_table<Descriptor, Lazy, Allocator>::value_type *
733 hash_table<Descriptor, Lazy,
734 Allocator>::find_empty_slot_for_expand (hashval_t hash)
671 { 735 {
672 hashval_t index = hash_table_mod1 (hash, m_size_prime_index); 736 hashval_t index = hash_table_mod1 (hash, m_size_prime_index);
673 size_t size = m_size; 737 size_t size = m_size;
674 value_type *slot = m_entries + index; 738 value_type *slot = m_entries + index;
675 hashval_t hash2; 739 hashval_t hash2;
692 } 756 }
693 } 757 }
694 758
695 /* Return true if the current table is excessively big for ELTS elements. */ 759 /* Return true if the current table is excessively big for ELTS elements. */
696 760
697 template<typename Descriptor, template<typename Type> class Allocator> 761 template<typename Descriptor, bool Lazy,
762 template<typename Type> class Allocator>
698 inline bool 763 inline bool
699 hash_table<Descriptor, Allocator>::too_empty_p (unsigned int elts) 764 hash_table<Descriptor, Lazy, Allocator>::too_empty_p (unsigned int elts)
700 { 765 {
701 return elts * 8 < m_size && m_size > 32; 766 return elts * 8 < m_size && m_size > 32;
702 } 767 }
703 768
704 /* The following function changes size of memory allocated for the 769 /* The following function changes size of memory allocated for the
706 of the table after the call will be about 50%. Naturally the hash 771 of the table after the call will be about 50%. Naturally the hash
707 table must already exist. Remember also that the place of the 772 table must already exist. Remember also that the place of the
708 table entries is changed. If memory allocation fails, this function 773 table entries is changed. If memory allocation fails, this function
709 will abort. */ 774 will abort. */
710 775
711 template<typename Descriptor, template<typename Type> class Allocator> 776 template<typename Descriptor, bool Lazy,
777 template<typename Type> class Allocator>
712 void 778 void
713 hash_table<Descriptor, Allocator>::expand () 779 hash_table<Descriptor, Lazy, Allocator>::expand ()
714 { 780 {
715 value_type *oentries = m_entries; 781 value_type *oentries = m_entries;
716 unsigned int oindex = m_size_prime_index; 782 unsigned int oindex = m_size_prime_index;
717 size_t osize = size (); 783 size_t osize = size ();
718 value_type *olimit = oentries + osize; 784 value_type *olimit = oentries + osize;
751 value_type &x = *p; 817 value_type &x = *p;
752 818
753 if (!is_empty (x) && !is_deleted (x)) 819 if (!is_empty (x) && !is_deleted (x))
754 { 820 {
755 value_type *q = find_empty_slot_for_expand (Descriptor::hash (x)); 821 value_type *q = find_empty_slot_for_expand (Descriptor::hash (x));
756 822 new ((void*) q) value_type (x);
757 *q = x;
758 } 823 }
759 824
760 p++; 825 p++;
761 } 826 }
762 while (p < olimit); 827 while (p < olimit);
767 ggc_free (oentries); 832 ggc_free (oentries);
768 } 833 }
769 834
770 /* Implements empty() in cases where it isn't a no-op. */ 835 /* Implements empty() in cases where it isn't a no-op. */
771 836
772 template<typename Descriptor, template<typename Type> class Allocator> 837 template<typename Descriptor, bool Lazy,
838 template<typename Type> class Allocator>
773 void 839 void
774 hash_table<Descriptor, Allocator>::empty_slow () 840 hash_table<Descriptor, Lazy, Allocator>::empty_slow ()
775 { 841 {
776 size_t size = m_size; 842 size_t size = m_size;
777 size_t nsize = size; 843 size_t nsize = size;
778 value_type *entries = m_entries; 844 value_type *entries = m_entries;
779 int i; 845
780 846 for (size_t i = size - 1; i < size; i--)
781 for (i = size - 1; i >= 0; i--)
782 if (!is_empty (entries[i]) && !is_deleted (entries[i])) 847 if (!is_empty (entries[i]) && !is_deleted (entries[i]))
783 Descriptor::remove (entries[i]); 848 Descriptor::remove (entries[i]);
784 849
785 /* Instead of clearing megabyte, downsize the table. */ 850 /* Instead of clearing megabyte, downsize the table. */
786 if (size > 1024*1024 / sizeof (value_type)) 851 if (size > 1024*1024 / sizeof (value_type))
788 else if (too_empty_p (m_n_elements)) 853 else if (too_empty_p (m_n_elements))
789 nsize = m_n_elements * 2; 854 nsize = m_n_elements * 2;
790 855
791 if (nsize != size) 856 if (nsize != size)
792 { 857 {
793 int nindex = hash_table_higher_prime_index (nsize); 858 unsigned int nindex = hash_table_higher_prime_index (nsize);
794 int nsize = prime_tab[nindex].prime; 859
860 nsize = prime_tab[nindex].prime;
795 861
796 if (!m_ggc) 862 if (!m_ggc)
797 Allocator <value_type> ::data_free (m_entries); 863 Allocator <value_type> ::data_free (m_entries);
798 else 864 else
799 ggc_free (m_entries); 865 ggc_free (m_entries);
800 866
801 m_entries = alloc_entries (nsize); 867 m_entries = alloc_entries (nsize);
802 m_size = nsize; 868 m_size = nsize;
803 m_size_prime_index = nindex; 869 m_size_prime_index = nindex;
804 } 870 }
871 else if (Descriptor::empty_zero_p)
872 memset ((void *) entries, 0, size * sizeof (value_type));
805 else 873 else
806 { 874 for (size_t i = 0; i < size; i++)
807 #ifndef BROKEN_VALUE_INITIALIZATION 875 mark_empty (entries[i]);
808 for ( ; size; ++entries, --size) 876
809 *entries = value_type ();
810 #else
811 memset (entries, 0, size * sizeof (value_type));
812 #endif
813 }
814 m_n_deleted = 0; 877 m_n_deleted = 0;
815 m_n_elements = 0; 878 m_n_elements = 0;
816 } 879 }
817 880
818 /* This function clears a specified SLOT in a hash table. It is 881 /* This function clears a specified SLOT in a hash table. It is
819 useful when you've already done the lookup and don't want to do it 882 useful when you've already done the lookup and don't want to do it
820 again. */ 883 again. */
821 884
822 template<typename Descriptor, template<typename Type> class Allocator> 885 template<typename Descriptor, bool Lazy,
886 template<typename Type> class Allocator>
823 void 887 void
824 hash_table<Descriptor, Allocator>::clear_slot (value_type *slot) 888 hash_table<Descriptor, Lazy, Allocator>::clear_slot (value_type *slot)
825 { 889 {
826 gcc_checking_assert (!(slot < m_entries || slot >= m_entries + size () 890 gcc_checking_assert (!(slot < m_entries || slot >= m_entries + size ()
827 || is_empty (*slot) || is_deleted (*slot))); 891 || is_empty (*slot) || is_deleted (*slot)));
828 892
829 Descriptor::remove (*slot); 893 Descriptor::remove (*slot);
834 898
835 /* This function searches for a hash table entry equal to the given 899 /* This function searches for a hash table entry equal to the given
836 COMPARABLE element starting with the given HASH value. It cannot 900 COMPARABLE element starting with the given HASH value. It cannot
837 be used to insert or delete an element. */ 901 be used to insert or delete an element. */
838 902
839 template<typename Descriptor, template<typename Type> class Allocator> 903 template<typename Descriptor, bool Lazy,
840 typename hash_table<Descriptor, Allocator>::value_type & 904 template<typename Type> class Allocator>
841 hash_table<Descriptor, Allocator> 905 typename hash_table<Descriptor, Lazy, Allocator>::value_type &
906 hash_table<Descriptor, Lazy, Allocator>
842 ::find_with_hash (const compare_type &comparable, hashval_t hash) 907 ::find_with_hash (const compare_type &comparable, hashval_t hash)
843 { 908 {
844 m_searches++; 909 m_searches++;
845 size_t size = m_size; 910 size_t size = m_size;
846 hashval_t index = hash_table_mod1 (hash, m_size_prime_index); 911 hashval_t index = hash_table_mod1 (hash, m_size_prime_index);
847 912
913 if (Lazy && m_entries == NULL)
914 m_entries = alloc_entries (size);
848 value_type *entry = &m_entries[index]; 915 value_type *entry = &m_entries[index];
849 if (is_empty (*entry) 916 if (is_empty (*entry)
850 || (!is_deleted (*entry) && Descriptor::equal (*entry, comparable))) 917 || (!is_deleted (*entry) && Descriptor::equal (*entry, comparable)))
851 return *entry; 918 return *entry;
852 919
859 index -= size; 926 index -= size;
860 927
861 entry = &m_entries[index]; 928 entry = &m_entries[index];
862 if (is_empty (*entry) 929 if (is_empty (*entry)
863 || (!is_deleted (*entry) && Descriptor::equal (*entry, comparable))) 930 || (!is_deleted (*entry) && Descriptor::equal (*entry, comparable)))
864 return *entry; 931 {
932 #if CHECKING_P
933 if (m_sanitize_eq_and_hash)
934 verify (comparable, hash);
935 #endif
936 return *entry;
937 }
865 } 938 }
866 } 939 }
867 940
868 /* This function searches for a hash table slot containing an entry 941 /* This function searches for a hash table slot containing an entry
869 equal to the given COMPARABLE element and starting with the given 942 equal to the given COMPARABLE element and starting with the given
871 call clear_slot on the slot returned (possibly after doing some 944 call clear_slot on the slot returned (possibly after doing some
872 checks). To insert an entry, call this with insert=INSERT, then 945 checks). To insert an entry, call this with insert=INSERT, then
873 write the value you want into the returned slot. When inserting an 946 write the value you want into the returned slot. When inserting an
874 entry, NULL may be returned if memory allocation fails. */ 947 entry, NULL may be returned if memory allocation fails. */
875 948
876 template<typename Descriptor, template<typename Type> class Allocator> 949 template<typename Descriptor, bool Lazy,
877 typename hash_table<Descriptor, Allocator>::value_type * 950 template<typename Type> class Allocator>
878 hash_table<Descriptor, Allocator> 951 typename hash_table<Descriptor, Lazy, Allocator>::value_type *
952 hash_table<Descriptor, Lazy, Allocator>
879 ::find_slot_with_hash (const compare_type &comparable, hashval_t hash, 953 ::find_slot_with_hash (const compare_type &comparable, hashval_t hash,
880 enum insert_option insert) 954 enum insert_option insert)
881 { 955 {
956 if (Lazy && m_entries == NULL)
957 {
958 if (insert == INSERT)
959 m_entries = alloc_entries (m_size);
960 else
961 return NULL;
962 }
882 if (insert == INSERT && m_size * 3 <= m_n_elements * 4) 963 if (insert == INSERT && m_size * 3 <= m_n_elements * 4)
883 expand (); 964 expand ();
884 965
966 #if CHECKING_P
967 if (m_sanitize_eq_and_hash)
968 verify (comparable, hash);
969 #endif
970
885 m_searches++; 971 m_searches++;
886
887 value_type *first_deleted_slot = NULL; 972 value_type *first_deleted_slot = NULL;
888 hashval_t index = hash_table_mod1 (hash, m_size_prime_index); 973 hashval_t index = hash_table_mod1 (hash, m_size_prime_index);
889 hashval_t hash2 = hash_table_mod2 (hash, m_size_prime_index); 974 hashval_t hash2 = hash_table_mod2 (hash, m_size_prime_index);
890 value_type *entry = &m_entries[index]; 975 value_type *entry = &m_entries[index];
891 size_t size = m_size; 976 size_t size = m_size;
928 1013
929 m_n_elements++; 1014 m_n_elements++;
930 return &m_entries[index]; 1015 return &m_entries[index];
931 } 1016 }
932 1017
1018 /* Verify that all existing elements in th hash table which are
1019 equal to COMPARABLE have an equal HASH value provided as argument. */
1020
1021 template<typename Descriptor, bool Lazy,
1022 template<typename Type> class Allocator>
1023 void
1024 hash_table<Descriptor, Lazy, Allocator>
1025 ::verify (const compare_type &comparable, hashval_t hash)
1026 {
1027 for (size_t i = 0; i < MIN (hash_table_sanitize_eq_limit, m_size); i++)
1028 {
1029 value_type *entry = &m_entries[i];
1030 if (!is_empty (*entry) && !is_deleted (*entry)
1031 && hash != Descriptor::hash (*entry)
1032 && Descriptor::equal (*entry, comparable))
1033 hashtab_chk_error ();
1034 }
1035 }
1036
933 /* This function deletes an element with the given COMPARABLE value 1037 /* This function deletes an element with the given COMPARABLE value
934 from hash table starting with the given HASH. If there is no 1038 from hash table starting with the given HASH. If there is no
935 matching element in the hash table, this function does nothing. */ 1039 matching element in the hash table, this function does nothing. */
936 1040
937 template<typename Descriptor, template<typename Type> class Allocator> 1041 template<typename Descriptor, bool Lazy,
1042 template<typename Type> class Allocator>
938 void 1043 void
939 hash_table<Descriptor, Allocator> 1044 hash_table<Descriptor, Lazy, Allocator>
940 ::remove_elt_with_hash (const compare_type &comparable, hashval_t hash) 1045 ::remove_elt_with_hash (const compare_type &comparable, hashval_t hash)
941 { 1046 {
942 value_type *slot = find_slot_with_hash (comparable, hash, NO_INSERT); 1047 value_type *slot = find_slot_with_hash (comparable, hash, NO_INSERT);
943 if (is_empty (*slot)) 1048 if (slot == NULL)
944 return; 1049 return;
945 1050
946 Descriptor::remove (*slot); 1051 Descriptor::remove (*slot);
947 1052
948 mark_deleted (*slot); 1053 mark_deleted (*slot);
951 1056
952 /* This function scans over the entire hash table calling CALLBACK for 1057 /* This function scans over the entire hash table calling CALLBACK for
953 each live entry. If CALLBACK returns false, the iteration stops. 1058 each live entry. If CALLBACK returns false, the iteration stops.
954 ARGUMENT is passed as CALLBACK's second argument. */ 1059 ARGUMENT is passed as CALLBACK's second argument. */
955 1060
956 template<typename Descriptor, 1061 template<typename Descriptor, bool Lazy,
957 template<typename Type> class Allocator> 1062 template<typename Type> class Allocator>
958 template<typename Argument, 1063 template<typename Argument,
959 int (*Callback) 1064 int (*Callback)
960 (typename hash_table<Descriptor, Allocator>::value_type *slot, 1065 (typename hash_table<Descriptor, Lazy, Allocator>::value_type *slot,
961 Argument argument)> 1066 Argument argument)>
962 void 1067 void
963 hash_table<Descriptor, Allocator>::traverse_noresize (Argument argument) 1068 hash_table<Descriptor, Lazy, Allocator>::traverse_noresize (Argument argument)
964 { 1069 {
1070 if (Lazy && m_entries == NULL)
1071 return;
1072
965 value_type *slot = m_entries; 1073 value_type *slot = m_entries;
966 value_type *limit = slot + size (); 1074 value_type *limit = slot + size ();
967 1075
968 do 1076 do
969 { 1077 {
977 } 1085 }
978 1086
979 /* Like traverse_noresize, but does resize the table when it is too empty 1087 /* Like traverse_noresize, but does resize the table when it is too empty
980 to improve effectivity of subsequent calls. */ 1088 to improve effectivity of subsequent calls. */
981 1089
982 template <typename Descriptor, 1090 template <typename Descriptor, bool Lazy,
983 template <typename Type> class Allocator> 1091 template <typename Type> class Allocator>
984 template <typename Argument, 1092 template <typename Argument,
985 int (*Callback) 1093 int (*Callback)
986 (typename hash_table<Descriptor, Allocator>::value_type *slot, 1094 (typename hash_table<Descriptor, Lazy, Allocator>::value_type *slot,
987 Argument argument)> 1095 Argument argument)>
988 void 1096 void
989 hash_table<Descriptor, Allocator>::traverse (Argument argument) 1097 hash_table<Descriptor, Lazy, Allocator>::traverse (Argument argument)
990 { 1098 {
991 if (too_empty_p (elements ())) 1099 if (too_empty_p (elements ()) && (!Lazy || m_entries))
992 expand (); 1100 expand ();
993 1101
994 traverse_noresize <Argument, Callback> (argument); 1102 traverse_noresize <Argument, Callback> (argument);
995 } 1103 }
996 1104
997 /* Slide down the iterator slots until an active entry is found. */ 1105 /* Slide down the iterator slots until an active entry is found. */
998 1106
999 template<typename Descriptor, template<typename Type> class Allocator> 1107 template<typename Descriptor, bool Lazy,
1108 template<typename Type> class Allocator>
1000 void 1109 void
1001 hash_table<Descriptor, Allocator>::iterator::slide () 1110 hash_table<Descriptor, Lazy, Allocator>::iterator::slide ()
1002 { 1111 {
1003 for ( ; m_slot < m_limit; ++m_slot ) 1112 for ( ; m_slot < m_limit; ++m_slot )
1004 { 1113 {
1005 value_type &x = *m_slot; 1114 value_type &x = *m_slot;
1006 if (!is_empty (x) && !is_deleted (x)) 1115 if (!is_empty (x) && !is_deleted (x))
1010 m_limit = NULL; 1119 m_limit = NULL;
1011 } 1120 }
1012 1121
1013 /* Bump the iterator. */ 1122 /* Bump the iterator. */
1014 1123
1015 template<typename Descriptor, template<typename Type> class Allocator> 1124 template<typename Descriptor, bool Lazy,
1016 inline typename hash_table<Descriptor, Allocator>::iterator & 1125 template<typename Type> class Allocator>
1017 hash_table<Descriptor, Allocator>::iterator::operator ++ () 1126 inline typename hash_table<Descriptor, Lazy, Allocator>::iterator &
1127 hash_table<Descriptor, Lazy, Allocator>::iterator::operator ++ ()
1018 { 1128 {
1019 ++m_slot; 1129 ++m_slot;
1020 slide (); 1130 slide ();
1021 return *this; 1131 return *this;
1022 } 1132 }