Ruby 4.1.0dev (2026-09-07 revision b57404b461ba8bf34e802d86b0db78388216e182)
st.c (b57404b461ba8bf34e802d86b0db78388216e182)
1/* This is a public domain general purpose hash table package
2 originally written by Peter Moore @ UCB.
3
4 The hash table data structures were redesigned and the package was
5 rewritten by Vladimir Makarov <vmakarov@redhat.com>. */
6
7/* The original package implemented classic bucket-based hash tables
8 with entries doubly linked for an access by their insertion order.
9 To decrease pointer chasing and as a consequence to improve a data
10 locality the current implementation is based on storing entries in
11 an array and using hash tables with open addressing. The current
12 entries are more compact in comparison with the original ones and
13 this also improves the data locality.
14
15 The hash table has two arrays called *bins* and *entries*.
16
17 bins:
18 -------
19 | | entries array:
20 |-------| --------------------------------
21 | index | | | entry: | | |
22 |-------| | | | | |
23 | ... | | ... | hash | ... | ... |
24 |-------| | | key | | |
25 | empty | | | record | | |
26 |-------| --------------------------------
27 | ... | ^ ^
28 |-------| |_ entries start |_ entries bound
29 |deleted|
30 -------
31
32 o The entry array contains table entries in the same order as they
33 were inserted.
34
35 When the first entry is deleted, a variable containing index of
36 the current first entry (*entries start*) is changed. In all
37 other cases of the deletion, we just mark the entry as deleted by
38 using a reserved hash value.
39
40 Such organization of the entry storage makes operations of the
41 table shift and the entries traversal very fast.
42
43 o The bins provide access to the entries by their keys. The
44 key hash is mapped to a bin containing *index* of the
45 corresponding entry in the entry array.
46
47 The bin array size is always power of two, it makes mapping very
48 fast by using the corresponding lower bits of the hash.
49 Generally it is not a good idea to ignore some part of the hash.
50 But alternative approach is worse. For example, we could use a
51 modulo operation for mapping and a prime number for the size of
52 the bin array. Unfortunately, the modulo operation for big
53 64-bit numbers are extremely slow (it takes more than 100 cycles
54 on modern Intel CPUs).
55
56 Still other bits of the hash value are used when the mapping
57 results in a collision. In this case we use a secondary hash
58 value which is a result of a function of the collision bin
59 index and the original hash value. The function choice
60 guarantees that we can traverse all bins and finally find the
61 corresponding bin as after several iterations the function
62 becomes a full cycle linear congruential generator because it
63 satisfies requirements of the Hull-Dobell theorem.
64
65 When an entry is removed from the table besides marking the
66 hash in the corresponding entry described above, we also mark
67 the bin by a special value in order to find entries which had
68 a collision with the removed entries.
69
70 There are two reserved values for the bins. One denotes an
71 empty bin, another one denotes a bin for a deleted entry.
72
73 o The length of the bin array is at least two times more than the
74 entry array length. This keeps the table load factor healthy.
75 The trigger of rebuilding the table is always a case when we can
76 not insert an entry anymore at the entries bound. We could
77 change the entries bound too in case of deletion but than we need
78 a special code to count bins with corresponding deleted entries
79 and reset the bin values when there are too many bins
80 corresponding deleted entries
81
82 Table rebuilding is done by creation of a new entry array and
83 bins of an appropriate size. We also try to reuse the arrays
84 in some cases by compacting the array and removing deleted
85 entries.
86
87 o To save memory very small tables have no allocated arrays
88 bins. We use a linear search for an access by a key.
89
90 o To save more memory we use 8-, 16-, 32- and 64- bit indexes in
91 bins depending on the current hash table size.
92
93 o The implementation takes into account that the table can be
94 rebuilt during hashing or comparison functions. It can happen if
95 the functions are implemented in Ruby and a thread switch occurs
96 during their execution.
97
98 This implementation speeds up the Ruby hash table benchmarks in
99 average by more 40% on Intel Haswell CPU.
100
101*/
102
103#ifdef NOT_RUBY
104#include "regint.h"
105#include "st.h"
106#include <assert.h>
107#elif defined RUBY_EXPORT
108#include "internal.h"
109#include "internal/bits.h"
110#include "internal/gc.h"
111#include "internal/hash.h"
112#include "internal/sanitizers.h"
113#include "internal/set_table.h"
114#include "internal/st.h"
115#include "ruby_assert.h"
116#endif
117
118#include <stdio.h>
119#ifdef HAVE_STDLIB_H
120#include <stdlib.h>
121#endif
122#include <string.h>
123
124#ifdef __GNUC__
125#define PREFETCH(addr, write_p) __builtin_prefetch(addr, write_p)
126#define EXPECT(expr, val) __builtin_expect(expr, val)
127#define ATTRIBUTE_UNUSED __attribute__((unused))
128#else
129#define PREFETCH(addr, write_p)
130#define EXPECT(expr, val) (expr)
131#define ATTRIBUTE_UNUSED
132#endif
133
134#define MAX_ENTRIES_START ((unsigned int)-1)
135
136/* The type of hashes. */
137typedef st_index_t st_hash_t;
138
140 st_hash_t hash;
141 st_data_t key;
142 st_data_t record;
143};
144
145#define type_numhash st_hashtype_num
146static const struct st_hash_type st_hashtype_num = {
147 st_numcmp,
148 st_numhash,
149};
150
151static int st_strcmp(st_data_t, st_data_t);
152static st_index_t strhash(st_data_t);
153static const struct st_hash_type type_strhash = {
154 st_strcmp,
155 strhash,
156};
157
158static int st_locale_insensitive_strcasecmp_i(st_data_t lhs, st_data_t rhs);
159static st_index_t strcasehash(st_data_t);
160static const struct st_hash_type type_strcasehash = {
161 st_locale_insensitive_strcasecmp_i,
162 strcasehash,
163};
164
165/* Value used to catch uninitialized entries/bins during debugging.
166 There is a possibility for a false alarm, but its probability is
167 extremely small. */
168#define ST_INIT_VAL 0xafafafafafafafaf
169#define ST_INIT_VAL_BYTE 0xafa
170
171#ifdef RUBY
172#undef malloc
173#undef realloc
174#undef calloc
175#undef free
176#define malloc ruby_xmalloc
177#define calloc ruby_xcalloc
178#define realloc ruby_xrealloc
179#define sized_realloc ruby_xrealloc_sized
180#define free ruby_xfree
181#define sized_free ruby_xfree_sized
182#define free_fixed_ptr(v) ruby_xfree_sized((v), sizeof(*(v)))
183#else
184#define sized_realloc(ptr, new_size, old_size) realloc(ptr, new_size)
185#define sized_free(v, s) free(v)
186#define free_fixed_ptr(v) free(v)
187#endif
188
189/* Compare an entry's hash and key against given hash_val and key.
190 Entry fields must be read into locals by the caller before passing
191 them here, to avoid re-reading from potentially-freed memory after
192 #eql? triggers a table rebuild. */
193static inline int
194entry_equal(const struct st_hash_type *type,
195 st_hash_t entry_hash, st_data_t entry_key,
196 st_hash_t hash_val, st_data_t key)
197{
198 return (entry_hash == hash_val) &&
199 ((entry_key == key) || (*type->compare)(key, entry_key) == 0);
200}
201
202/* As entry_equal, but also checks whether the table was rebuilt
203 during the comparison (i.e. #eql? mutated it). */
204static inline void
205ptr_equal_check(const st_table *tab, const st_table_entry *entry,
206 st_hash_t hash_val, st_data_t key,
207 int *res, int *rebuilt_p)
208{
209 unsigned int old_rebuilds_num = tab->rebuilds_num;
210 *res = entry_equal(tab->type, entry->hash, entry->key, hash_val, key);
211 *rebuilt_p = old_rebuilds_num != tab->rebuilds_num;
212}
213
214#define DO_PTR_EQUAL_CHECK(tab, ptr, hash_val, key, res, rebuilt_p) \
215 ptr_equal_check((tab), (ptr), (hash_val), (key), &(res), &(rebuilt_p))
216
217/* Features of a table. */
219 /* Power of 2 used for number of allocated entries. */
220 unsigned char entry_power;
221 /* Power of 2 used for number of allocated bins. Depending on the
222 table size, the number of bins is 2-4 times more than the
223 number of entries. */
224 unsigned char bin_power;
225 /* Enumeration of sizes of bins (8-bit, 16-bit etc). */
226 unsigned char size_ind;
227 /* Bins are packed in words of type st_index_t. The following is
228 a size of bins counted by words. */
229 st_index_t bins_words;
230};
231
232/* Features of all possible size tables. */
233#if SIZEOF_ST_INDEX_T == 8
234#define MAX_POWER2 62
235static const struct st_features features[] = {
236 {0, 1, 0, 0x0},
237 {1, 2, 0, 0x1},
238 {2, 3, 0, 0x1},
239 {3, 4, 0, 0x2},
240 {4, 5, 0, 0x4},
241 {5, 6, 0, 0x8},
242 {6, 7, 0, 0x10},
243 {7, 8, 0, 0x20},
244 {8, 9, 1, 0x80},
245 {9, 10, 1, 0x100},
246 {10, 11, 1, 0x200},
247 {11, 12, 1, 0x400},
248 {12, 13, 1, 0x800},
249 {13, 14, 1, 0x1000},
250 {14, 15, 1, 0x2000},
251 {15, 16, 1, 0x4000},
252 {16, 17, 2, 0x10000},
253 {17, 18, 2, 0x20000},
254 {18, 19, 2, 0x40000},
255 {19, 20, 2, 0x80000},
256 {20, 21, 2, 0x100000},
257 {21, 22, 2, 0x200000},
258 {22, 23, 2, 0x400000},
259 {23, 24, 2, 0x800000},
260 {24, 25, 2, 0x1000000},
261 {25, 26, 2, 0x2000000},
262 {26, 27, 2, 0x4000000},
263 {27, 28, 2, 0x8000000},
264 {28, 29, 2, 0x10000000},
265 {29, 30, 2, 0x20000000},
266 {30, 31, 2, 0x40000000},
267 {31, 32, 2, 0x80000000},
268 {32, 33, 3, 0x200000000},
269 {33, 34, 3, 0x400000000},
270 {34, 35, 3, 0x800000000},
271 {35, 36, 3, 0x1000000000},
272 {36, 37, 3, 0x2000000000},
273 {37, 38, 3, 0x4000000000},
274 {38, 39, 3, 0x8000000000},
275 {39, 40, 3, 0x10000000000},
276 {40, 41, 3, 0x20000000000},
277 {41, 42, 3, 0x40000000000},
278 {42, 43, 3, 0x80000000000},
279 {43, 44, 3, 0x100000000000},
280 {44, 45, 3, 0x200000000000},
281 {45, 46, 3, 0x400000000000},
282 {46, 47, 3, 0x800000000000},
283 {47, 48, 3, 0x1000000000000},
284 {48, 49, 3, 0x2000000000000},
285 {49, 50, 3, 0x4000000000000},
286 {50, 51, 3, 0x8000000000000},
287 {51, 52, 3, 0x10000000000000},
288 {52, 53, 3, 0x20000000000000},
289 {53, 54, 3, 0x40000000000000},
290 {54, 55, 3, 0x80000000000000},
291 {55, 56, 3, 0x100000000000000},
292 {56, 57, 3, 0x200000000000000},
293 {57, 58, 3, 0x400000000000000},
294 {58, 59, 3, 0x800000000000000},
295 {59, 60, 3, 0x1000000000000000},
296 {60, 61, 3, 0x2000000000000000},
297 {61, 62, 3, 0x4000000000000000},
298 {62, 63, 3, 0x8000000000000000},
299};
300
301#else
302#define MAX_POWER2 30
303
304static const struct st_features features[] = {
305 {0, 1, 0, 0x1},
306 {1, 2, 0, 0x1},
307 {2, 3, 0, 0x2},
308 {3, 4, 0, 0x4},
309 {4, 5, 0, 0x8},
310 {5, 6, 0, 0x10},
311 {6, 7, 0, 0x20},
312 {7, 8, 0, 0x40},
313 {8, 9, 1, 0x100},
314 {9, 10, 1, 0x200},
315 {10, 11, 1, 0x400},
316 {11, 12, 1, 0x800},
317 {12, 13, 1, 0x1000},
318 {13, 14, 1, 0x2000},
319 {14, 15, 1, 0x4000},
320 {15, 16, 1, 0x8000},
321 {16, 17, 2, 0x20000},
322 {17, 18, 2, 0x40000},
323 {18, 19, 2, 0x80000},
324 {19, 20, 2, 0x100000},
325 {20, 21, 2, 0x200000},
326 {21, 22, 2, 0x400000},
327 {22, 23, 2, 0x800000},
328 {23, 24, 2, 0x1000000},
329 {24, 25, 2, 0x2000000},
330 {25, 26, 2, 0x4000000},
331 {26, 27, 2, 0x8000000},
332 {27, 28, 2, 0x10000000},
333 {28, 29, 2, 0x20000000},
334 {29, 30, 2, 0x40000000},
335 {30, 31, 2, 0x80000000},
336};
337
338#endif
339
340/* The reserved hash value and its substitution. */
341#define RESERVED_HASH_VAL (~(st_hash_t) 0)
342#define RESERVED_HASH_SUBSTITUTION_VAL ((st_hash_t) 0)
343
344static inline st_hash_t
345normalize_hash_value(st_hash_t hash)
346{
347 /* RESERVED_HASH_VAL is used for a deleted entry. Map it into
348 another value. Such mapping should be extremely rare. */
349 return hash == RESERVED_HASH_VAL ? RESERVED_HASH_SUBSTITUTION_VAL : hash;
350}
351
352/* Return hash value of KEY for table TAB. */
353static inline st_hash_t
354do_hash(st_data_t key, st_table *tab)
355{
356 st_hash_t hash = (st_hash_t)(tab->type->hash)(key);
357 return normalize_hash_value(hash);
358}
359
360/* Power of 2 defining the minimal number of allocated entries. */
361#define MINIMAL_POWER2 2
362
363#if MINIMAL_POWER2 < 2
364#error "MINIMAL_POWER2 should be >= 2"
365#endif
366
367/* If the power2 of the allocated `entries` is less than the following
368 value, don't allocate bins and use a linear search. */
369#define MAX_POWER2_FOR_TABLES_WITHOUT_BINS 4
370
371/* Return smallest n >= MINIMAL_POWER2 such 2^n > SIZE. */
372static int
373get_power2(st_index_t size)
374{
375 unsigned int n = ST_INDEX_BITS - nlz_intptr(size);
376 if (n <= MAX_POWER2)
377 return n < MINIMAL_POWER2 ? MINIMAL_POWER2 : n;
378#ifdef RUBY
379 /* Ran out of the table entries */
380 rb_raise(rb_eRuntimeError, "st_table too big");
381#endif
382 /* should raise exception */
383 return -1;
384}
385
386/* Return value of N-th bin in array BINS of table with bins size
387 index S. */
388static inline st_index_t
389get_bin(st_index_t *bins, int s, st_index_t n)
390{
391 return (s == 0 ? ((unsigned char *) bins)[n]
392 : s == 1 ? ((unsigned short *) bins)[n]
393 : s == 2 ? ((unsigned int *) bins)[n]
394 : ((st_index_t *) bins)[n]);
395}
396
397/* Set up N-th bin in array BINS of table with bins size index S to
398 value V. */
399static inline void
400set_bin(st_index_t *bins, int s, st_index_t n, st_index_t v)
401{
402 if (s == 0) ((unsigned char *) bins)[n] = (unsigned char) v;
403 else if (s == 1) ((unsigned short *) bins)[n] = (unsigned short) v;
404 else if (s == 2) ((unsigned int *) bins)[n] = (unsigned int) v;
405 else ((st_index_t *) bins)[n] = v;
406}
407
408/* These macros define reserved values for empty table bin and table
409 bin which contains a deleted entry. We will never use such values
410 for an entry index in bins. */
411#define EMPTY_BIN 0
412#define DELETED_BIN 1
413/* Base of a real entry index in the bins. */
414#define ENTRY_BASE 2
415
416/* Mark I-th bin of table TAB as empty, in other words not
417 corresponding to any entry. */
418#define MARK_BIN_EMPTY(tab, i) (set_bin(st_bins_ptr(tab), get_size_ind(tab), i, EMPTY_BIN))
419
420/* Values used for not found entry and bin with given
421 characteristics. */
422#define UNDEFINED_ENTRY_IND (~(st_index_t) 0)
423#define UNDEFINED_BIN_IND (~(st_index_t) 0)
424
425/* Entry and bin values returned when we found a table rebuild during
426 the search. */
427#define REBUILT_TABLE_ENTRY_IND (~(st_index_t) 1)
428#define REBUILT_TABLE_BIN_IND (~(st_index_t) 1)
429
430/* Mark I-th bin of table TAB as corresponding to a deleted table
431 entry. Update number of entries in the table and number of bins
432 corresponding to deleted entries. */
433#define MARK_BIN_DELETED(tab, i) \
434 do { \
435 set_bin(st_bins_ptr(tab), get_size_ind(tab), i, DELETED_BIN); \
436 } while (0)
437
438/* Macros to check that value B is used empty bins and bins
439 corresponding deleted entries. */
440#define EMPTY_BIN_P(b) ((b) == EMPTY_BIN)
441#define DELETED_BIN_P(b) ((b) == DELETED_BIN)
442#define EMPTY_OR_DELETED_BIN_P(b) ((b) <= DELETED_BIN)
443
444/* Macros to check empty bins and bins corresponding to deleted
445 entries. Bins are given by their index I in table TAB. */
446#define IND_EMPTY_BIN_P(tab, i) (EMPTY_BIN_P(get_bin(st_bins_ptr(tab), get_size_ind(tab), i)))
447#define IND_DELETED_BIN_P(tab, i) (DELETED_BIN_P(get_bin(st_bins_ptr(tab), get_size_ind(tab), i)))
448#define IND_EMPTY_OR_DELETED_BIN_P(tab, i) (EMPTY_OR_DELETED_BIN_P(get_bin(st_bins_ptr(tab), get_size_ind(tab), i)))
449
450/* Macros for marking and checking deleted entries given by their
451 pointer E_PTR. */
452#define MARK_ENTRY_DELETED(e_ptr) ((e_ptr)->hash = RESERVED_HASH_VAL)
453#define DELETED_ENTRY_P(e_ptr) ((e_ptr)->hash == RESERVED_HASH_VAL)
454
455/* Return the number of allocated entries of table TAB. */
456static inline st_index_t
457get_allocated_entries(const st_table *tab)
458{
459 return ((st_index_t) 1)<<tab->entry_power;
460}
461
462/* Return bin size index of table TAB. */
463static inline unsigned int
464get_size_ind(const st_table *tab)
465{
466 return tab->size_ind;
467}
468
469/* Return the number of allocated bins of table TAB. */
470static inline st_index_t
471get_bins_num(const st_table *tab)
472{
473 return ((st_index_t) 1)<<tab->bin_power;
474}
475
476/* Return mask for a bin index in table TAB. */
477static inline st_index_t
478bins_mask(const st_table *tab)
479{
480 return get_bins_num(tab) - 1;
481}
482
483static inline bool
484st_has_bins(const st_table *tab)
485{
486 return tab->entry_power > MAX_POWER2_FOR_TABLES_WITHOUT_BINS;
487}
488
489static inline size_t
490st_allocated_entries_size(const st_table *tab)
491{
492 return get_allocated_entries(tab) * sizeof(st_table_entry);
493}
494
495static inline st_index_t *
496st_bins_ptr(const st_table *tab)
497{
498 if (st_has_bins(tab)) {
499 return (st_index_t *)(((char *)tab->entries) + st_allocated_entries_size(tab));
500 }
501
502 return NULL;
503}
504
505/* Return the index of table TAB bin corresponding to
506 HASH_VALUE. */
507static inline st_index_t
508hash_bin(st_hash_t hash_value, st_table *tab)
509{
510 return hash_value & bins_mask(tab);
511}
512
513/* Return size of the allocated bins of table TAB. */
514static inline st_index_t
515bins_size(const st_table *tab)
516{
517 if (st_has_bins(tab)) {
518 return features[tab->entry_power].bins_words * sizeof (st_index_t);
519 }
520 return 0;
521}
522
523/* Mark all bins of table TAB as empty. */
524static void
525initialize_bins(st_table *tab)
526{
527 memset(st_bins_ptr(tab), 0, bins_size(tab));
528}
529
530/* Make table TAB empty. */
531static void
532make_tab_empty(st_table *tab)
533{
534 tab->num_entries = 0;
535 tab->entries_start = tab->entries_bound = 0;
536 if (st_bins_ptr(tab) != NULL)
537 initialize_bins(tab);
538}
539
540#ifdef HASH_LOG
541#ifdef HAVE_UNISTD_H
542#include <unistd.h>
543#endif
544static struct {
545 int all, total, num, str, strcase;
546} collision;
547
548/* Flag switching off output of package statistics at the end of
549 program. */
550static int init_st = 0;
551
552/* Output overall number of table searches and collisions into a
553 temporary file. */
554static void
555stat_col(void)
556{
557 char fname[10+sizeof(long)*3];
558 FILE *f;
559 if (!collision.total) return;
560 f = fopen((snprintf(fname, sizeof(fname), "/tmp/col%ld", (long)getpid()), fname), "w");
561 if (f == NULL)
562 return;
563 fprintf(f, "collision: %d / %d (%6.2f)\n", collision.all, collision.total,
564 ((double)collision.all / (collision.total)) * 100);
565 fprintf(f, "num: %d, str: %d, strcase: %d\n", collision.num, collision.str, collision.strcase);
566 fclose(f);
567}
568#endif
569
570st_table *
571st_init_existing_table_with_size(st_table *tab, const struct st_hash_type *type, st_index_t size)
572{
573 int n;
574
575#ifdef HASH_LOG
576#if HASH_LOG+0 < 0
577 {
578 const char *e = getenv("ST_HASH_LOG");
579 if (!e || !*e) init_st = 1;
580 }
581#endif
582 if (init_st == 0) {
583 init_st = 1;
584 atexit(stat_col);
585 }
586#endif
587
588 n = get_power2(size);
589#ifndef RUBY
590 if (n < 0)
591 return NULL;
592#endif
593
594 tab->type = type;
595 tab->entry_power = n;
596 tab->bin_power = features[n].bin_power;
597 tab->size_ind = features[n].size_ind;
598
599 size_t memsize = get_allocated_entries(tab) * sizeof(st_table_entry);
600 if (tab->entry_power > MAX_POWER2_FOR_TABLES_WITHOUT_BINS) {
601 memsize += bins_size(tab);
602 }
603 tab->entries = (st_table_entry *)malloc(memsize);
604#ifndef RUBY
605 if (tab->entries == NULL) {
606 st_free_table(tab);
607 return NULL;
608 }
609#endif
610 make_tab_empty(tab);
611 tab->rebuilds_num = 0;
612 return tab;
613}
614
615st_table *
616st_init_existing_numtable_with_size(st_table *tab, st_index_t size)
617{
618 return st_init_existing_table_with_size(tab, &type_numhash, size);
619}
620
621/* Create and return table with TYPE which can hold at least SIZE
622 entries. The real number of entries which the table can hold is
623 the nearest power of two for SIZE. */
624st_table *
625st_init_table_with_size(const struct st_hash_type *type, st_index_t size)
626{
627 st_table *tab = malloc(sizeof(st_table));
628#ifndef RUBY
629 if (tab == NULL)
630 return NULL;
631#endif
632
633#ifdef RUBY
634 st_init_existing_table_with_size(tab, type, size);
635#else
636 if (st_init_existing_table_with_size(tab, type, size) == NULL) {
637 free_fixed_ptr(tab);
638 return NULL;
639 }
640#endif
641
642 return tab;
643}
644
645size_t
646st_table_size(const struct st_table *tbl)
647{
648 return tbl->num_entries;
649}
650
651/* Create and return table with TYPE which can hold a minimal number
652 of entries (see comments for get_power2). */
653st_table *
654st_init_table(const struct st_hash_type *type)
655{
656 return st_init_table_with_size(type, 0);
657}
658
659/* Create and return table which can hold a minimal number of
660 numbers. */
661st_table *
662st_init_numtable(void)
663{
664 return st_init_table(&type_numhash);
665}
666
667/* Create and return table which can hold SIZE numbers. */
668st_table *
669st_init_numtable_with_size(st_index_t size)
670{
671 return st_init_table_with_size(&type_numhash, size);
672}
673
674/* Create and return table which can hold a minimal number of
675 strings. */
676st_table *
677st_init_strtable(void)
678{
679 return st_init_table(&type_strhash);
680}
681
682/* Create and return table which can hold SIZE strings. */
683st_table *
684st_init_strtable_with_size(st_index_t size)
685{
686 return st_init_table_with_size(&type_strhash, size);
687}
688
689st_table *
690st_init_existing_strtable_with_size(st_table *tab, st_index_t size)
691{
692 return st_init_existing_table_with_size(tab, &type_strhash, size);
693}
694
695
696/* Create and return table which can hold a minimal number of strings
697 whose character case is ignored. */
698st_table *
699st_init_strcasetable(void)
700{
701 return st_init_table(&type_strcasehash);
702}
703
704/* Create and return table which can hold SIZE strings whose character
705 case is ignored. */
706st_table *
707st_init_strcasetable_with_size(st_index_t size)
708{
709 return st_init_table_with_size(&type_strcasehash, size);
710}
711
712/* Make table TAB empty. */
713void
714st_clear(st_table *tab)
715{
716 make_tab_empty(tab);
717 tab->rebuilds_num++;
718}
719
720static inline size_t
721st_entries_memsize(const st_table *tab)
722{
723 return get_allocated_entries(tab) * sizeof(st_table_entry);
724}
725
726static inline void
727st_free_entries(const st_table *tab)
728{
729 sized_free(tab->entries, st_entries_memsize(tab) + bins_size(tab));
730}
731
732void
733st_free_embedded_table(st_table *tab)
734{
735 st_free_entries(tab);
736}
737
738/* Free table TAB space. */
739void
740st_free_table(st_table *tab)
741{
742 st_free_embedded_table(tab);
743 free_fixed_ptr(tab);
744}
745
746/* Return byte size of memory allocated for table TAB. */
747size_t
748st_memsize(const st_table *tab)
749{
750 RUBY_ASSERT(tab != NULL);
751 return(sizeof(st_table)
752 + bins_size(tab)
753 + st_entries_memsize(tab));
754}
755
756static st_index_t
757find_table_entry_ind(st_table *tab, st_hash_t hash_value, st_data_t key);
758
759static st_index_t
760find_table_bin_ind(st_table *tab, st_hash_t hash_value, st_data_t key);
761
762static st_index_t
763find_table_bin_ind_direct(st_table *table, st_hash_t hash_value, st_data_t key);
764
765static st_index_t
766find_table_bin_ptr_and_reserve(st_table *tab, st_hash_t *hash_value,
767 st_data_t key, st_index_t *bin_ind);
768
769#ifdef HASH_LOG
770static void
771count_collision(const struct st_hash_type *type)
772{
773 collision.all++;
774 if (type == &type_numhash) {
775 collision.num++;
776 }
777 else if (type == &type_strhash) {
778 collision.strcase++;
779 }
780 else if (type == &type_strcasehash) {
781 collision.str++;
782 }
783}
784
785#define COLLISION (collision_check ? count_collision(tab->type) : (void)0)
786#define FOUND_BIN (collision_check ? collision.total++ : (void)0)
787#define collision_check 0
788#else
789#define COLLISION
790#define FOUND_BIN
791#endif
792
793/* If the number of entries in the table is at least REBUILD_THRESHOLD
794 times less than the entry array length, decrease the table
795 size. */
796#define REBUILD_THRESHOLD 4
797
798#if REBUILD_THRESHOLD < 2
799#error "REBUILD_THRESHOLD should be >= 2"
800#endif
801
802static void rebuild_table_with(st_table *const new_tab, st_table *const tab);
803static void rebuild_move_table(st_table *const new_tab, st_table *const tab);
804static void rebuild_cleanup(st_table *const tab);
805
806/* Rebuild table TAB. Rebuilding removes all deleted bins and entries
807 and can change size of the table entries and bins arrays.
808 Rebuilding is implemented by creation of a new table or by
809 compaction of the existing one. */
810static void
811rebuild_table(st_table *tab)
812{
813 if ((2 * tab->num_entries <= get_allocated_entries(tab)
814 && REBUILD_THRESHOLD * tab->num_entries > get_allocated_entries(tab))
815 || tab->num_entries < (1 << MINIMAL_POWER2)) {
816 /* Compaction: */
817 tab->num_entries = 0;
818 if (st_has_bins(tab))
819 initialize_bins(tab);
820 rebuild_table_with(tab, tab);
821 }
822 else {
823 st_table *new_tab;
824 /* This allocation could trigger GC and compaction. If tab is the
825 * gen_fields_tbl, then tab could have changed in size due to objects being
826 * freed and/or moved. Do not store attributes of tab before this line. */
827 new_tab = st_init_table_with_size(tab->type,
828 2 * tab->num_entries - 1);
829 rebuild_table_with(new_tab, tab);
830 rebuild_move_table(new_tab, tab);
831 }
832 rebuild_cleanup(tab);
833}
834
835static void
836rebuild_table_with(st_table *const new_tab, st_table *const tab)
837{
838 st_index_t i, ni;
839 unsigned int size_ind;
840 st_table_entry *new_entries;
841 st_table_entry *curr_entry_ptr;
842 st_index_t *bins;
843 st_index_t bin_ind;
844
845 new_entries = new_tab->entries;
846
847 ni = 0;
848 bins = st_bins_ptr(new_tab);
849 size_ind = get_size_ind(new_tab);
850 st_index_t bound = tab->entries_bound;
851 st_table_entry *entries = tab->entries;
852
853 for (i = tab->entries_start; i < bound; i++) {
854 curr_entry_ptr = &entries[i];
855 PREFETCH(entries + i + 1, 0);
856 if (EXPECT(DELETED_ENTRY_P(curr_entry_ptr), 0))
857 continue;
858 if (&new_entries[ni] != curr_entry_ptr)
859 new_entries[ni] = *curr_entry_ptr;
860 if (EXPECT(bins != NULL, 1)) {
861 bin_ind = find_table_bin_ind_direct(new_tab, curr_entry_ptr->hash,
862 curr_entry_ptr->key);
863 set_bin(bins, size_ind, bin_ind, ni + ENTRY_BASE);
864 }
865 new_tab->num_entries++;
866 ni++;
867 }
868
869 assert(new_tab->num_entries == tab->num_entries);
870}
871
872static void
873rebuild_move_table(st_table *const new_tab, st_table *const tab)
874{
875 st_free_entries(tab);
876 tab->entry_power = new_tab->entry_power;
877 tab->bin_power = new_tab->bin_power;
878 tab->size_ind = new_tab->size_ind;
879 tab->entries = new_tab->entries;
880 free_fixed_ptr(new_tab);
881}
882
883static void
884rebuild_cleanup(st_table *const tab)
885{
886 tab->entries_start = 0;
887 tab->entries_bound = tab->num_entries;
888 tab->rebuilds_num++;
889}
890
891/* Return the next secondary hash index for table TAB using previous
892 index IND and PERTURB. Finally modulo of the function becomes a
893 full *cycle linear congruential generator*, in other words it
894 guarantees traversing all table bins in extreme case.
895
896 According the Hull-Dobell theorem a generator
897 "Xnext = (a*Xprev + c) mod m" is a full cycle generator if and only if
898 o m and c are relatively prime
899 o a-1 is divisible by all prime factors of m
900 o a-1 is divisible by 4 if m is divisible by 4.
901
902 For our case a is 5, c is 1, and m is a power of two. */
903static inline st_index_t
904secondary_hash(st_index_t ind, st_table *tab, st_index_t *perturb)
905{
906 *perturb >>= 11;
907 ind = (ind << 2) + ind + *perturb + 1;
908 return hash_bin(ind, tab);
909}
910
911/* Find an entry with HASH_VALUE and KEY in TABLE using a linear
912 search. Return the index of the found entry in array `entries`.
913 If it is not found, return UNDEFINED_ENTRY_IND. If the table was
914 rebuilt during the search, return REBUILT_TABLE_ENTRY_IND. */
915static inline st_index_t
916find_entry(st_table *tab, st_hash_t hash_value, st_data_t key)
917{
918 int eq_p, rebuilt_p;
919 st_index_t i, bound;
920 st_table_entry *entries;
921
922 bound = tab->entries_bound;
923 entries = tab->entries;
924 for (i = tab->entries_start; i < bound; i++) {
925 DO_PTR_EQUAL_CHECK(tab, &entries[i], hash_value, key, eq_p, rebuilt_p);
926 if (EXPECT(rebuilt_p, 0))
927 return REBUILT_TABLE_ENTRY_IND;
928 if (eq_p)
929 return i;
930 }
931 return UNDEFINED_ENTRY_IND;
932}
933
934/* Use the quadratic probing. The method has a better data locality
935 but more collisions than the current approach. In average it
936 results in a bit slower search. */
937/*#define QUADRATIC_PROBE*/
938
939/* Return index of entry with HASH_VALUE and KEY in table TAB. If
940 there is no such entry, return UNDEFINED_ENTRY_IND. If the table
941 was rebuilt during the search, return REBUILT_TABLE_ENTRY_IND. */
942static st_index_t
943find_table_entry_ind(st_table *tab, st_hash_t hash_value, st_data_t key)
944{
945 int eq_p, rebuilt_p;
946 st_index_t ind;
947#ifdef QUADRATIC_PROBE
948 st_index_t d;
949#else
950 st_index_t perturb;
951#endif
952 st_index_t bin;
953 st_table_entry *entries = tab->entries;
954
955 ind = hash_bin(hash_value, tab);
956#ifdef QUADRATIC_PROBE
957 d = 1;
958#else
959 perturb = hash_value;
960#endif
961 FOUND_BIN;
962 for (;;) {
963 bin = get_bin(st_bins_ptr(tab), get_size_ind(tab), ind);
964 if (! EMPTY_OR_DELETED_BIN_P(bin)) {
965 DO_PTR_EQUAL_CHECK(tab, &entries[bin - ENTRY_BASE], hash_value, key, eq_p, rebuilt_p);
966 if (EXPECT(rebuilt_p, 0))
967 return REBUILT_TABLE_ENTRY_IND;
968 if (eq_p)
969 break;
970 }
971 else if (EMPTY_BIN_P(bin))
972 return UNDEFINED_ENTRY_IND;
973#ifdef QUADRATIC_PROBE
974 ind = hash_bin(ind + d, tab);
975 d++;
976#else
977 ind = secondary_hash(ind, tab, &perturb);
978#endif
979 COLLISION;
980 }
981 return bin;
982}
983
984/* Find and return index of table TAB bin corresponding to an entry
985 with HASH_VALUE and KEY. If there is no such bin, return
986 UNDEFINED_BIN_IND. If the table was rebuilt during the search,
987 return REBUILT_TABLE_BIN_IND. */
988static st_index_t
989find_table_bin_ind(st_table *tab, st_hash_t hash_value, st_data_t key)
990{
991 int eq_p, rebuilt_p;
992 st_index_t ind;
993#ifdef QUADRATIC_PROBE
994 st_index_t d;
995#else
996 st_index_t perturb;
997#endif
998 st_index_t bin;
999 st_table_entry *entries = tab->entries;
1000
1001 ind = hash_bin(hash_value, tab);
1002#ifdef QUADRATIC_PROBE
1003 d = 1;
1004#else
1005 perturb = hash_value;
1006#endif
1007 FOUND_BIN;
1008 for (;;) {
1009 bin = get_bin(st_bins_ptr(tab), get_size_ind(tab), ind);
1010 if (! EMPTY_OR_DELETED_BIN_P(bin)) {
1011 DO_PTR_EQUAL_CHECK(tab, &entries[bin - ENTRY_BASE], hash_value, key, eq_p, rebuilt_p);
1012 if (EXPECT(rebuilt_p, 0))
1013 return REBUILT_TABLE_BIN_IND;
1014 if (eq_p)
1015 break;
1016 }
1017 else if (EMPTY_BIN_P(bin))
1018 return UNDEFINED_BIN_IND;
1019#ifdef QUADRATIC_PROBE
1020 ind = hash_bin(ind + d, tab);
1021 d++;
1022#else
1023 ind = secondary_hash(ind, tab, &perturb);
1024#endif
1025 COLLISION;
1026 }
1027 return ind;
1028}
1029
1030/* Find and return index of table TAB bin corresponding to an entry
1031 with HASH_VALUE and KEY. The entry should be in the table
1032 already. */
1033static st_index_t
1034find_table_bin_ind_direct(st_table *tab, st_hash_t hash_value, st_data_t key)
1035{
1036 st_index_t ind;
1037#ifdef QUADRATIC_PROBE
1038 st_index_t d;
1039#else
1040 st_index_t perturb;
1041#endif
1042 st_index_t bin;
1043
1044 ind = hash_bin(hash_value, tab);
1045#ifdef QUADRATIC_PROBE
1046 d = 1;
1047#else
1048 perturb = hash_value;
1049#endif
1050 FOUND_BIN;
1051 for (;;) {
1052 bin = get_bin(st_bins_ptr(tab), get_size_ind(tab), ind);
1053 if (EMPTY_OR_DELETED_BIN_P(bin))
1054 return ind;
1055#ifdef QUADRATIC_PROBE
1056 ind = hash_bin(ind + d, tab);
1057 d++;
1058#else
1059 ind = secondary_hash(ind, tab, &perturb);
1060#endif
1061 COLLISION;
1062 }
1063}
1064
1065/* Return index of table TAB bin for HASH_VALUE and KEY through
1066 BIN_IND and the pointed value as the function result. Reserve the
1067 bin for inclusion of the corresponding entry into the table if it
1068 is not there yet. We always find such bin as bins array length is
1069 bigger entries array. Although we can reuse a deleted bin, the
1070 result bin value is always empty if the table has no entry with
1071 KEY. Return the entries array index of the found entry or
1072 UNDEFINED_ENTRY_IND if it is not found. If the table was rebuilt
1073 during the search, return REBUILT_TABLE_ENTRY_IND. */
1074static st_index_t
1075find_table_bin_ptr_and_reserve(st_table *tab, st_hash_t *hash_value,
1076 st_data_t key, st_index_t *bin_ind)
1077{
1078 int eq_p, rebuilt_p;
1079 st_index_t ind;
1080 st_hash_t curr_hash_value = *hash_value;
1081#ifdef QUADRATIC_PROBE
1082 st_index_t d;
1083#else
1084 st_index_t perturb;
1085#endif
1086 st_index_t entry_index;
1087 st_index_t first_deleted_bin_ind;
1088 st_table_entry *entries;
1089
1090 ind = hash_bin(curr_hash_value, tab);
1091#ifdef QUADRATIC_PROBE
1092 d = 1;
1093#else
1094 perturb = curr_hash_value;
1095#endif
1096 FOUND_BIN;
1097 first_deleted_bin_ind = UNDEFINED_BIN_IND;
1098 entries = tab->entries;
1099 for (;;) {
1100 entry_index = get_bin(st_bins_ptr(tab), get_size_ind(tab), ind);
1101 if (EMPTY_BIN_P(entry_index)) {
1102 tab->num_entries++;
1103 entry_index = UNDEFINED_ENTRY_IND;
1104 if (first_deleted_bin_ind != UNDEFINED_BIN_IND) {
1105 /* We can reuse bin of a deleted entry. */
1106 ind = first_deleted_bin_ind;
1107 MARK_BIN_EMPTY(tab, ind);
1108 }
1109 break;
1110 }
1111 else if (! DELETED_BIN_P(entry_index)) {
1112 DO_PTR_EQUAL_CHECK(tab, &entries[entry_index - ENTRY_BASE], curr_hash_value, key, eq_p, rebuilt_p);
1113 if (EXPECT(rebuilt_p, 0))
1114 return REBUILT_TABLE_ENTRY_IND;
1115 if (eq_p)
1116 break;
1117 }
1118 else if (first_deleted_bin_ind == UNDEFINED_BIN_IND)
1119 first_deleted_bin_ind = ind;
1120#ifdef QUADRATIC_PROBE
1121 ind = hash_bin(ind + d, tab);
1122 d++;
1123#else
1124 ind = secondary_hash(ind, tab, &perturb);
1125#endif
1126 COLLISION;
1127 }
1128 *bin_ind = ind;
1129 return entry_index;
1130}
1131
1132/* Find an entry with KEY in table TAB. Return non-zero if we found
1133 it. Set up *RECORD to the found entry record. */
1134int
1135st_lookup(st_table *tab, st_data_t key, st_data_t *value)
1136{
1137 st_index_t bin;
1138 st_hash_t hash = do_hash(key, tab);
1139
1140 retry:
1141 if (!st_has_bins(tab)) {
1142 bin = find_entry(tab, hash, key);
1143 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
1144 goto retry;
1145 if (bin == UNDEFINED_ENTRY_IND)
1146 return 0;
1147 }
1148 else {
1149 bin = find_table_entry_ind(tab, hash, key);
1150 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
1151 goto retry;
1152 if (bin == UNDEFINED_ENTRY_IND)
1153 return 0;
1154 bin -= ENTRY_BASE;
1155 }
1156 if (value != 0)
1157 *value = tab->entries[bin].record;
1158 return 1;
1159}
1160
1161/* Find an entry with KEY in table TAB. Return non-zero if we found
1162 it. Set up *RESULT to the found table entry key. */
1163int
1164st_get_key(st_table *tab, st_data_t key, st_data_t *result)
1165{
1166 st_index_t bin;
1167 st_hash_t hash = do_hash(key, tab);
1168
1169 retry:
1170 if (!st_has_bins(tab)) {
1171 bin = find_entry(tab, hash, key);
1172 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
1173 goto retry;
1174 if (bin == UNDEFINED_ENTRY_IND)
1175 return 0;
1176 }
1177 else {
1178 bin = find_table_entry_ind(tab, hash, key);
1179 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
1180 goto retry;
1181 if (bin == UNDEFINED_ENTRY_IND)
1182 return 0;
1183 bin -= ENTRY_BASE;
1184 }
1185 if (result != 0)
1186 *result = tab->entries[bin].key;
1187 return 1;
1188}
1189
1190/* Check the table and rebuild it if it is necessary. */
1191static inline void
1192rebuild_table_if_necessary(st_table *tab)
1193{
1194 st_index_t bound = tab->entries_bound;
1195
1196 if (bound == get_allocated_entries(tab) || tab->entries_start == MAX_ENTRIES_START) {
1197 rebuild_table(tab);
1198 }
1199}
1200
1201/* Insert (KEY, VALUE) into table TAB and return zero. If there is
1202 already entry with KEY in the table, return nonzero and update
1203 the value of the found entry. */
1204int
1205st_insert(st_table *tab, st_data_t key, st_data_t value)
1206{
1207 st_table_entry *entry;
1208 st_index_t bin;
1209 st_index_t ind;
1210 st_hash_t hash_value;
1211 st_index_t bin_ind;
1212 int new_p;
1213
1214 hash_value = do_hash(key, tab);
1215 retry:
1216 rebuild_table_if_necessary(tab);
1217 if (!st_has_bins(tab)) {
1218 bin = find_entry(tab, hash_value, key);
1219 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
1220 goto retry;
1221 new_p = bin == UNDEFINED_ENTRY_IND;
1222 if (new_p)
1223 tab->num_entries++;
1224 bin_ind = UNDEFINED_BIN_IND;
1225 }
1226 else {
1227 bin = find_table_bin_ptr_and_reserve(tab, &hash_value,
1228 key, &bin_ind);
1229 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
1230 goto retry;
1231 new_p = bin == UNDEFINED_ENTRY_IND;
1232 bin -= ENTRY_BASE;
1233 }
1234 if (new_p) {
1235 ind = tab->entries_bound++;
1236 entry = &tab->entries[ind];
1237 entry->hash = hash_value;
1238 entry->key = key;
1239 entry->record = value;
1240 if (bin_ind != UNDEFINED_BIN_IND)
1241 set_bin(st_bins_ptr(tab), get_size_ind(tab), bin_ind, ind + ENTRY_BASE);
1242 return 0;
1243 }
1244 tab->entries[bin].record = value;
1245 return 1;
1246}
1247
1248#ifdef RUBY
1249/* Insert (KEY, VALUE) into table TAB like st_insert(), but return -1
1250 without any change when st_insert() would rebuild the table. The
1251 insertion is guaranteed to be allocation (and GC) free when it is done. */
1252int
1253st_insert_no_rebuild(st_table *tab, st_data_t key, st_data_t value)
1254{
1255 if (tab->entries_bound == get_allocated_entries(tab)) {
1256 /* st_insert() will rebuild the table */
1257 return -1;
1258 }
1259 return st_insert(tab, key, value);
1260}
1261#endif
1262
1263/* Insert (KEY, VALUE, HASH) into table TAB. The table should not have
1264 entry with KEY before the insertion. */
1265static inline void
1266st_add_direct_with_hash(st_table *tab,
1267 st_data_t key, st_data_t value, st_hash_t hash)
1268{
1269 st_table_entry *entry;
1270 st_index_t ind;
1271 st_index_t bin_ind;
1272
1273 assert(hash != RESERVED_HASH_VAL);
1274
1275 rebuild_table_if_necessary(tab);
1276 ind = tab->entries_bound++;
1277 entry = &tab->entries[ind];
1278 entry->hash = hash;
1279 entry->key = key;
1280 entry->record = value;
1281 tab->num_entries++;
1282 if (st_has_bins(tab)) {
1283 bin_ind = find_table_bin_ind_direct(tab, hash, key);
1284 set_bin(st_bins_ptr(tab), get_size_ind(tab), bin_ind, ind + ENTRY_BASE);
1285 }
1286}
1287
1288void
1289rb_st_add_direct_with_hash(st_table *tab,
1290 st_data_t key, st_data_t value, st_hash_t hash)
1291{
1292 st_add_direct_with_hash(tab, key, value, normalize_hash_value(hash));
1293}
1294
1295/* Insert (KEY, VALUE) into table TAB. The table should not have
1296 entry with KEY before the insertion. */
1297void
1298st_add_direct(st_table *tab, st_data_t key, st_data_t value)
1299{
1300 st_hash_t hash_value;
1301
1302 hash_value = do_hash(key, tab);
1303 st_add_direct_with_hash(tab, key, value, hash_value);
1304}
1305
1306/* Insert (FUNC(KEY), VALUE) into table TAB and return zero. If
1307 there is already entry with KEY in the table, return nonzero and
1308 update the value of the found entry. */
1309int
1310st_insert2(st_table *tab, st_data_t key, st_data_t value,
1311 st_data_t (*func)(st_data_t))
1312{
1313 st_table_entry *entry;
1314 st_index_t bin;
1315 st_index_t ind;
1316 st_hash_t hash_value;
1317 st_index_t bin_ind;
1318 int new_p;
1319
1320 hash_value = do_hash(key, tab);
1321 retry:
1322 rebuild_table_if_necessary(tab);
1323 if (!st_has_bins(tab)) {
1324 bin = find_entry(tab, hash_value, key);
1325 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
1326 goto retry;
1327 new_p = bin == UNDEFINED_ENTRY_IND;
1328 if (new_p)
1329 tab->num_entries++;
1330 bin_ind = UNDEFINED_BIN_IND;
1331 }
1332 else {
1333 bin = find_table_bin_ptr_and_reserve(tab, &hash_value,
1334 key, &bin_ind);
1335 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
1336 goto retry;
1337 new_p = bin == UNDEFINED_ENTRY_IND;
1338 bin -= ENTRY_BASE;
1339 }
1340 if (new_p) {
1341 key = (*func)(key);
1342 ind = tab->entries_bound++;
1343 entry = &tab->entries[ind];
1344 entry->hash = hash_value;
1345 entry->key = key;
1346 entry->record = value;
1347 if (bin_ind != UNDEFINED_BIN_IND)
1348 set_bin(st_bins_ptr(tab), get_size_ind(tab), bin_ind, ind + ENTRY_BASE);
1349 return 0;
1350 }
1351 tab->entries[bin].record = value;
1352 return 1;
1353}
1354
1355static st_table *
1356st_replace_no_check(st_table *new_tab, st_table *old_tab)
1357{
1358 *new_tab = *old_tab;
1359 size_t memsize = get_allocated_entries(old_tab) * sizeof(st_table_entry);
1360 memsize += bins_size(old_tab);
1361 new_tab->entries = (st_table_entry *) malloc(memsize);
1362#ifndef RUBY
1363 if (new_tab->entries == NULL) {
1364 return NULL;
1365 }
1366#endif
1367 MEMCPY(new_tab->entries, old_tab->entries, char, memsize);
1368
1369 return new_tab;
1370}
1371
1372
1373/* Create a copy of old_tab into new_tab. */
1374st_table *
1375st_replace(st_table *new_tab, st_table *old_tab)
1376{
1377 RUBY_ASSERT(new_tab->entries == NULL);
1378 return st_replace_no_check(new_tab, old_tab);
1379}
1380
1381/* Create and return a copy of table OLD_TAB. */
1382st_table *
1383st_copy(st_table *old_tab)
1384{
1385 st_table *new_tab;
1386
1387 new_tab = (st_table *) malloc(sizeof(st_table));
1388#ifndef RUBY
1389 if (new_tab == NULL)
1390 return NULL;
1391#endif
1392
1393 if (st_replace_no_check(new_tab, old_tab) == NULL) {
1394 st_free_table(new_tab);
1395 return NULL;
1396 }
1397
1398 return new_tab;
1399}
1400
1401/* Update the entries start of table TAB after removing an entry
1402 with index N in the array entries. */
1403static inline void
1404update_range_for_deleted(st_table *tab, st_index_t n)
1405{
1406 /* Do not update entries_bound here. Otherwise, we can fill all
1407 bins by deleted entry value before rebuilding the table. */
1408 if (tab->entries_start == n) {
1409 st_index_t start = n + 1;
1410 st_index_t bound = tab->entries_bound;
1411 st_table_entry *entries = tab->entries;
1412 while (start < bound && DELETED_ENTRY_P(&entries[start])) start++;
1413 tab->entries_start = start > MAX_ENTRIES_START ? MAX_ENTRIES_START : (unsigned int)start;
1414 }
1415}
1416
1417/* Delete entry with KEY from table TAB, set up *VALUE (unless
1418 VALUE is zero) from deleted table entry, and return non-zero. If
1419 there is no entry with KEY in the table, clear *VALUE (unless VALUE
1420 is zero), and return zero. */
1421static int
1422st_general_delete(st_table *tab, st_data_t *key, st_data_t *value)
1423{
1424 st_table_entry *entry;
1425 st_index_t bin;
1426 st_index_t bin_ind;
1427 st_hash_t hash;
1428
1429 hash = do_hash(*key, tab);
1430 retry:
1431 if (!st_has_bins(tab)) {
1432 bin = find_entry(tab, hash, *key);
1433 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
1434 goto retry;
1435 if (bin == UNDEFINED_ENTRY_IND) {
1436 if (value != 0) *value = 0;
1437 return 0;
1438 }
1439 }
1440 else {
1441 bin_ind = find_table_bin_ind(tab, hash, *key);
1442 if (EXPECT(bin_ind == REBUILT_TABLE_BIN_IND, 0))
1443 goto retry;
1444 if (bin_ind == UNDEFINED_BIN_IND) {
1445 if (value != 0) *value = 0;
1446 return 0;
1447 }
1448 bin = get_bin(st_bins_ptr(tab), get_size_ind(tab), bin_ind) - ENTRY_BASE;
1449 MARK_BIN_DELETED(tab, bin_ind);
1450 }
1451 entry = &tab->entries[bin];
1452 *key = entry->key;
1453 if (value != 0) *value = entry->record;
1454 MARK_ENTRY_DELETED(entry);
1455 tab->num_entries--;
1456 update_range_for_deleted(tab, bin);
1457 return 1;
1458}
1459
1460int
1461st_delete(st_table *tab, st_data_t *key, st_data_t *value)
1462{
1463 return st_general_delete(tab, key, value);
1464}
1465
1466/* The function and other functions with suffix '_safe' or '_check'
1467 are originated from the previous implementation of the hash tables.
1468 It was necessary for correct deleting entries during traversing
1469 tables. The current implementation permits deletion during
1470 traversing without a specific way to do this. */
1471int
1472st_delete_safe(st_table *tab, st_data_t *key, st_data_t *value,
1473 st_data_t never ATTRIBUTE_UNUSED)
1474{
1475 return st_general_delete(tab, key, value);
1476}
1477
1478/* If table TAB is empty, clear *VALUE (unless VALUE is zero), and
1479 return zero. Otherwise, remove the first entry in the table.
1480 Return its key through KEY and its record through VALUE (unless
1481 VALUE is zero). */
1482int
1483st_shift(st_table *tab, st_data_t *key, st_data_t *value)
1484{
1485 st_index_t i, bound;
1486 st_index_t bin;
1487 st_table_entry *entries, *curr_entry_ptr;
1488 st_index_t bin_ind;
1489
1490 entries = tab->entries;
1491 bound = tab->entries_bound;
1492 for (i = tab->entries_start; i < bound; i++) {
1493 curr_entry_ptr = &entries[i];
1494 if (! DELETED_ENTRY_P(curr_entry_ptr)) {
1495 st_hash_t entry_hash = curr_entry_ptr->hash;
1496 st_data_t entry_key = curr_entry_ptr->key;
1497
1498 if (value != 0) *value = curr_entry_ptr->record;
1499 *key = entry_key;
1500 retry:
1501 if (!st_has_bins(tab)) {
1502 bin = find_entry(tab, entry_hash, entry_key);
1503 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0)) {
1504 entries = tab->entries;
1505 goto retry;
1506 }
1507 curr_entry_ptr = &entries[bin];
1508 }
1509 else {
1510 bin_ind = find_table_bin_ind(tab, entry_hash, entry_key);
1511 if (EXPECT(bin_ind == REBUILT_TABLE_BIN_IND, 0)) {
1512 entries = tab->entries;
1513 goto retry;
1514 }
1515 curr_entry_ptr = &entries[get_bin(st_bins_ptr(tab), get_size_ind(tab), bin_ind)
1516 - ENTRY_BASE];
1517 MARK_BIN_DELETED(tab, bin_ind);
1518 }
1519 MARK_ENTRY_DELETED(curr_entry_ptr);
1520 tab->num_entries--;
1521 update_range_for_deleted(tab, i);
1522 return 1;
1523 }
1524 }
1525 if (value != 0) *value = 0;
1526 return 0;
1527}
1528
1529/* See comments for function st_delete_safe. */
1530void
1531st_cleanup_safe(st_table *tab ATTRIBUTE_UNUSED,
1532 st_data_t never ATTRIBUTE_UNUSED)
1533{
1534}
1535
1536/* Find entry with KEY in table TAB, call FUNC with pointers to copies
1537 of the key and the value of the found entry, and non-zero as the
1538 3rd argument. If the entry is not found, call FUNC with a pointer
1539 to KEY, a pointer to zero, and a zero argument. If the call
1540 returns ST_CONTINUE, the table will have an entry with key and
1541 value returned by FUNC through the 1st and 2nd parameters. If the
1542 call of FUNC returns ST_DELETE, the table will not have entry with
1543 KEY. The function returns flag of that the entry with KEY was in
1544 the table before the call. */
1545int
1546st_update(st_table *tab, st_data_t key,
1547 st_update_callback_func *func, st_data_t arg)
1548{
1549 st_table_entry *entry = NULL; /* to avoid uninitialized value warning */
1550 st_index_t bin = 0; /* Ditto */
1551 st_table_entry *entries;
1552 st_index_t bin_ind;
1553 st_data_t value = 0, old_key;
1554 int retval, existing;
1555 st_hash_t hash = do_hash(key, tab);
1556
1557 retry:
1558 entries = tab->entries;
1559 if (!st_has_bins(tab)) {
1560 bin = find_entry(tab, hash, key);
1561 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
1562 goto retry;
1563 existing = bin != UNDEFINED_ENTRY_IND;
1564 entry = &entries[bin];
1565 bin_ind = UNDEFINED_BIN_IND;
1566 }
1567 else {
1568 bin_ind = find_table_bin_ind(tab, hash, key);
1569 if (EXPECT(bin_ind == REBUILT_TABLE_BIN_IND, 0))
1570 goto retry;
1571 existing = bin_ind != UNDEFINED_BIN_IND;
1572 if (existing) {
1573 bin = get_bin(st_bins_ptr(tab), get_size_ind(tab), bin_ind) - ENTRY_BASE;
1574 entry = &entries[bin];
1575 }
1576 }
1577 if (existing) {
1578 key = entry->key;
1579 value = entry->record;
1580 }
1581 old_key = key;
1582
1583 unsigned int rebuilds_num = tab->rebuilds_num;
1584
1585 retval = (*func)(&key, &value, arg, existing);
1586
1587 // We need to make sure that the callback didn't cause a table rebuild
1588 // Ideally we would make sure no operations happened
1589 assert(rebuilds_num == tab->rebuilds_num);
1590 (void)rebuilds_num;
1591
1592 switch (retval) {
1593 case ST_CONTINUE:
1594 if (! existing) {
1595 st_add_direct_with_hash(tab, key, value, hash);
1596 break;
1597 }
1598 if (old_key != key) {
1599 entry->key = key;
1600 }
1601 entry->record = value;
1602 break;
1603 case ST_DELETE:
1604 if (existing) {
1605 if (bin_ind != UNDEFINED_BIN_IND)
1606 MARK_BIN_DELETED(tab, bin_ind);
1607 MARK_ENTRY_DELETED(entry);
1608 tab->num_entries--;
1609 update_range_for_deleted(tab, bin);
1610 }
1611 break;
1612 }
1613 return existing;
1614}
1615
1616/* Traverse all entries in table TAB calling FUNC with current entry
1617 key and value and zero. If the call returns ST_STOP, stop
1618 traversing. If the call returns ST_DELETE, delete the current
1619 entry from the table. In case of ST_CHECK or ST_CONTINUE, continue
1620 traversing. The function returns zero unless an error is found.
1621 CHECK_P is flag of st_foreach_check call. The behavior is a bit
1622 different for ST_CHECK and when the current element is removed
1623 during traversing. */
1624static inline int
1625st_general_foreach(st_table *tab, st_foreach_check_callback_func *func, st_update_callback_func *replace, st_data_t arg,
1626 int check_p)
1627{
1628 st_index_t bin;
1629 st_index_t bin_ind;
1630 st_table_entry *entries, *curr_entry_ptr;
1631 enum st_retval retval;
1632 st_index_t i, rebuilds_num;
1633 st_hash_t hash;
1634 st_data_t key;
1635 int error_p, packed_p = !st_has_bins(tab);
1636
1637 entries = tab->entries;
1638 /* The bound can change inside the loop even without rebuilding
1639 the table, e.g. by an entry insertion. */
1640 for (i = tab->entries_start; i < tab->entries_bound; i++) {
1641 curr_entry_ptr = &entries[i];
1642 if (EXPECT(DELETED_ENTRY_P(curr_entry_ptr), 0))
1643 continue;
1644 key = curr_entry_ptr->key;
1645 rebuilds_num = tab->rebuilds_num;
1646 hash = curr_entry_ptr->hash;
1647 retval = (*func)(key, curr_entry_ptr->record, arg, 0);
1648
1649 if (retval == ST_REPLACE && replace) {
1650 st_data_t value;
1651 value = curr_entry_ptr->record;
1652 retval = (*replace)(&key, &value, arg, TRUE);
1653 curr_entry_ptr->key = key;
1654 curr_entry_ptr->record = value;
1655 }
1656
1657 if (rebuilds_num != tab->rebuilds_num) {
1658 retry:
1659 entries = tab->entries;
1660 packed_p = !st_has_bins(tab);
1661 if (packed_p) {
1662 i = find_entry(tab, hash, key);
1663 if (EXPECT(i == REBUILT_TABLE_ENTRY_IND, 0))
1664 goto retry;
1665 error_p = i == UNDEFINED_ENTRY_IND;
1666 }
1667 else {
1668 i = find_table_entry_ind(tab, hash, key);
1669 if (EXPECT(i == REBUILT_TABLE_ENTRY_IND, 0))
1670 goto retry;
1671 error_p = i == UNDEFINED_ENTRY_IND;
1672 i -= ENTRY_BASE;
1673 }
1674 if (error_p && check_p) {
1675 /* call func with error notice */
1676 retval = (*func)(0, 0, arg, 1);
1677 return 1;
1678 }
1679 curr_entry_ptr = &entries[i];
1680 }
1681 switch (retval) {
1682 case ST_REPLACE:
1683 break;
1684 case ST_CONTINUE:
1685 break;
1686 case ST_CHECK:
1687 if (check_p)
1688 break;
1689 case ST_STOP:
1690 return 0;
1691 case ST_DELETE: {
1692 st_data_t key = curr_entry_ptr->key;
1693
1694 again:
1695 if (packed_p) {
1696 bin = find_entry(tab, hash, key);
1697 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
1698 goto again;
1699 if (bin == UNDEFINED_ENTRY_IND)
1700 break;
1701 }
1702 else {
1703 bin_ind = find_table_bin_ind(tab, hash, key);
1704 if (EXPECT(bin_ind == REBUILT_TABLE_BIN_IND, 0))
1705 goto again;
1706 if (bin_ind == UNDEFINED_BIN_IND)
1707 break;
1708 bin = get_bin(st_bins_ptr(tab), get_size_ind(tab), bin_ind) - ENTRY_BASE;
1709 MARK_BIN_DELETED(tab, bin_ind);
1710 }
1711 curr_entry_ptr = &entries[bin];
1712 MARK_ENTRY_DELETED(curr_entry_ptr);
1713 tab->num_entries--;
1714 update_range_for_deleted(tab, bin);
1715 break;
1716 }
1717 }
1718 }
1719 return 0;
1720}
1721
1722#ifdef INTERNAL_ST_H
1723int
1724st_foreach_with_hash(st_table *tab, st_foreach_with_hash_callback_func *func, st_data_t arg)
1725{
1726 st_table_entry *entries, *curr_entry_ptr;
1727 enum st_retval retval;
1728 st_index_t i, rebuilds_num;
1729 st_hash_t hash;
1730 st_data_t key;
1731 int packed_p = !st_has_bins(tab);
1732
1733 entries = tab->entries;
1734 /* The bound can change inside the loop even without rebuilding
1735 the table, e.g. by an entry insertion. */
1736 for (i = tab->entries_start; i < tab->entries_bound; i++) {
1737 curr_entry_ptr = &entries[i];
1738 if (EXPECT(DELETED_ENTRY_P(curr_entry_ptr), 0))
1739 continue;
1740 key = curr_entry_ptr->key;
1741 rebuilds_num = tab->rebuilds_num;
1742 hash = curr_entry_ptr->hash;
1743 retval = (*func)(key, curr_entry_ptr->record, hash, arg);
1744
1745 if (rebuilds_num != tab->rebuilds_num) {
1746 retry:
1747 entries = tab->entries;
1748 packed_p = !st_has_bins(tab);
1749 if (packed_p) {
1750 i = find_entry(tab, hash, key);
1751 if (EXPECT(i == REBUILT_TABLE_ENTRY_IND, 0))
1752 goto retry;
1753 }
1754 else {
1755 i = find_table_entry_ind(tab, hash, key);
1756 if (EXPECT(i == REBUILT_TABLE_ENTRY_IND, 0))
1757 goto retry;
1758 i -= ENTRY_BASE;
1759 }
1760 curr_entry_ptr = &entries[i];
1761 }
1762 switch (retval) {
1763 case ST_STOP:
1764 return 0;
1765 default:
1766 break;
1767 }
1768 }
1769 return 0;
1770}
1771#endif
1772
1773int
1774st_foreach_with_replace(st_table *tab, st_foreach_check_callback_func *func, st_update_callback_func *replace, st_data_t arg)
1775{
1776 return st_general_foreach(tab, func, replace, arg, TRUE);
1777}
1778
1779struct functor {
1780 st_foreach_callback_func *func;
1781 st_data_t arg;
1782};
1783
1784static int
1785apply_functor(st_data_t k, st_data_t v, st_data_t d, int _)
1786{
1787 const struct functor *f = (void *)d;
1788 return f->func(k, v, f->arg);
1789}
1790
1791int
1792st_foreach(st_table *tab, st_foreach_callback_func *func, st_data_t arg)
1793{
1794 const struct functor f = { func, arg };
1795 return st_general_foreach(tab, apply_functor, 0, (st_data_t)&f, FALSE);
1796}
1797
1798/* See comments for function st_delete_safe. */
1799int
1800st_foreach_check(st_table *tab, st_foreach_check_callback_func *func, st_data_t arg,
1801 st_data_t never ATTRIBUTE_UNUSED)
1802{
1803 return st_general_foreach(tab, func, 0, arg, TRUE);
1804}
1805
1806/* Set up array KEYS by at most SIZE keys of head table TAB entries.
1807 Return the number of keys set up in array KEYS. */
1808static inline st_index_t
1809st_general_keys(st_table *tab, st_data_t *keys, st_index_t size)
1810{
1811 st_index_t i, bound;
1812 st_data_t key, *keys_start, *keys_end;
1813 st_table_entry *curr_entry_ptr, *entries = tab->entries;
1814
1815 bound = tab->entries_bound;
1816 keys_start = keys;
1817 keys_end = keys + size;
1818 for (i = tab->entries_start; i < bound; i++) {
1819 if (keys == keys_end)
1820 break;
1821 curr_entry_ptr = &entries[i];
1822 key = curr_entry_ptr->key;
1823 if (! DELETED_ENTRY_P(curr_entry_ptr))
1824 *keys++ = key;
1825 }
1826
1827 return keys - keys_start;
1828}
1829
1830st_index_t
1831st_keys(st_table *tab, st_data_t *keys, st_index_t size)
1832{
1833 return st_general_keys(tab, keys, size);
1834}
1835
1836/* See comments for function st_delete_safe. */
1837st_index_t
1838st_keys_check(st_table *tab, st_data_t *keys, st_index_t size,
1839 st_data_t never ATTRIBUTE_UNUSED)
1840{
1841 return st_general_keys(tab, keys, size);
1842}
1843
1844/* Set up array VALUES by at most SIZE values of head table TAB
1845 entries. Return the number of values set up in array VALUES. */
1846static inline st_index_t
1847st_general_values(st_table *tab, st_data_t *values, st_index_t size)
1848{
1849 st_index_t i, bound;
1850 st_data_t *values_start, *values_end;
1851 st_table_entry *curr_entry_ptr, *entries = tab->entries;
1852
1853 values_start = values;
1854 values_end = values + size;
1855 bound = tab->entries_bound;
1856 for (i = tab->entries_start; i < bound; i++) {
1857 if (values == values_end)
1858 break;
1859 curr_entry_ptr = &entries[i];
1860 if (! DELETED_ENTRY_P(curr_entry_ptr))
1861 *values++ = curr_entry_ptr->record;
1862 }
1863
1864 return values - values_start;
1865}
1866
1867st_index_t
1868st_values(st_table *tab, st_data_t *values, st_index_t size)
1869{
1870 return st_general_values(tab, values, size);
1871}
1872
1873/* See comments for function st_delete_safe. */
1874st_index_t
1875st_values_check(st_table *tab, st_data_t *values, st_index_t size,
1876 st_data_t never ATTRIBUTE_UNUSED)
1877{
1878 return st_general_values(tab, values, size);
1879}
1880
1881#define FNV1_32A_INIT 0x811c9dc5
1882
1883/*
1884 * 32 bit magic FNV-1a prime
1885 */
1886#define FNV_32_PRIME 0x01000193
1887
1888/* __POWERPC__ added to accommodate Darwin case. */
1889#ifndef UNALIGNED_WORD_ACCESS
1890# if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
1891 defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || \
1892 defined(__powerpc64__) || defined(__POWERPC__) || defined(__aarch64__) || \
1893 defined(__mc68020__)
1894# define UNALIGNED_WORD_ACCESS 1
1895# endif
1896#endif
1897#ifndef UNALIGNED_WORD_ACCESS
1898# define UNALIGNED_WORD_ACCESS 0
1899#endif
1900
1901/* This hash function is quite simplified MurmurHash3
1902 * Simplification is legal, cause most of magic still happens in finalizator.
1903 * And finalizator is almost the same as in MurmurHash3 */
1904#define BIG_CONSTANT(x,y) ((st_index_t)(x)<<32|(st_index_t)(y))
1905#define ROTL(x,n) ((x)<<(n)|(x)>>(SIZEOF_ST_INDEX_T*CHAR_BIT-(n)))
1906
1907#if ST_INDEX_BITS <= 32
1908#define C1 (st_index_t)0xcc9e2d51
1909#define C2 (st_index_t)0x1b873593
1910#else
1911#define C1 BIG_CONSTANT(0x87c37b91,0x114253d5);
1912#define C2 BIG_CONSTANT(0x4cf5ad43,0x2745937f);
1913#endif
1914NO_SANITIZE("unsigned-integer-overflow", static inline st_index_t murmur_step(st_index_t h, st_index_t k));
1915NO_SANITIZE("unsigned-integer-overflow", static inline st_index_t murmur_finish(st_index_t h));
1916NO_SANITIZE("unsigned-integer-overflow", extern st_index_t st_hash(const void *ptr, size_t len, st_index_t h));
1917
1918static inline st_index_t
1919murmur_step(st_index_t h, st_index_t k)
1920{
1921#if ST_INDEX_BITS <= 32
1922#define r1 (17)
1923#define r2 (11)
1924#else
1925#define r1 (33)
1926#define r2 (24)
1927#endif
1928 k *= C1;
1929 h ^= ROTL(k, r1);
1930 h *= C2;
1931 h = ROTL(h, r2);
1932 return h;
1933}
1934#undef r1
1935#undef r2
1936
1937static inline st_index_t
1938murmur_finish(st_index_t h)
1939{
1940#if ST_INDEX_BITS <= 32
1941#define r1 (16)
1942#define r2 (13)
1943#define r3 (16)
1944 const st_index_t c1 = 0x85ebca6b;
1945 const st_index_t c2 = 0xc2b2ae35;
1946#else
1947/* values are taken from Mix13 on http://zimbry.blogspot.ru/2011/09/better-bit-mixing-improving-on.html */
1948#define r1 (30)
1949#define r2 (27)
1950#define r3 (31)
1951 const st_index_t c1 = BIG_CONSTANT(0xbf58476d,0x1ce4e5b9);
1952 const st_index_t c2 = BIG_CONSTANT(0x94d049bb,0x133111eb);
1953#endif
1954#if ST_INDEX_BITS > 64
1955 h ^= h >> 64;
1956 h *= c2;
1957 h ^= h >> 65;
1958#endif
1959 h ^= h >> r1;
1960 h *= c1;
1961 h ^= h >> r2;
1962 h *= c2;
1963 h ^= h >> r3;
1964 return h;
1965}
1966#undef r1
1967#undef r2
1968#undef r3
1969
1970st_index_t
1971st_hash(const void *ptr, size_t len, st_index_t h)
1972{
1973 const char *data = ptr;
1974 st_index_t t = 0;
1975 size_t l = len;
1976
1977#define data_at(n) (st_index_t)((unsigned char)data[(n)])
1978#define UNALIGNED_ADD_4 UNALIGNED_ADD(2); UNALIGNED_ADD(1); UNALIGNED_ADD(0)
1979#if SIZEOF_ST_INDEX_T > 4
1980#define UNALIGNED_ADD_8 UNALIGNED_ADD(6); UNALIGNED_ADD(5); UNALIGNED_ADD(4); UNALIGNED_ADD(3); UNALIGNED_ADD_4
1981#if SIZEOF_ST_INDEX_T > 8
1982#define UNALIGNED_ADD_16 UNALIGNED_ADD(14); UNALIGNED_ADD(13); UNALIGNED_ADD(12); UNALIGNED_ADD(11); \
1983 UNALIGNED_ADD(10); UNALIGNED_ADD(9); UNALIGNED_ADD(8); UNALIGNED_ADD(7); UNALIGNED_ADD_8
1984#define UNALIGNED_ADD_ALL UNALIGNED_ADD_16
1985#endif
1986#define UNALIGNED_ADD_ALL UNALIGNED_ADD_8
1987#else
1988#define UNALIGNED_ADD_ALL UNALIGNED_ADD_4
1989#endif
1990#undef SKIP_TAIL
1991 if (len >= sizeof(st_index_t)) {
1992#if !UNALIGNED_WORD_ACCESS
1993 int align = (int)((st_data_t)data % sizeof(st_index_t));
1994 if (align) {
1995 st_index_t d = 0;
1996 int sl, sr, pack;
1997
1998 switch (align) {
1999#ifdef WORDS_BIGENDIAN
2000# define UNALIGNED_ADD(n) case SIZEOF_ST_INDEX_T - (n) - 1: \
2001 t |= data_at(n) << CHAR_BIT*(SIZEOF_ST_INDEX_T - (n) - 2)
2002#else
2003# define UNALIGNED_ADD(n) case SIZEOF_ST_INDEX_T - (n) - 1: \
2004 t |= data_at(n) << CHAR_BIT*(n)
2005#endif
2006 UNALIGNED_ADD_ALL;
2007#undef UNALIGNED_ADD
2008 }
2009
2010#ifdef WORDS_BIGENDIAN
2011 t >>= (CHAR_BIT * align) - CHAR_BIT;
2012#else
2013 t <<= (CHAR_BIT * align);
2014#endif
2015
2016 data += sizeof(st_index_t)-align;
2017 len -= sizeof(st_index_t)-align;
2018
2019 sl = CHAR_BIT * (SIZEOF_ST_INDEX_T-align);
2020 sr = CHAR_BIT * align;
2021
2022 while (len >= sizeof(st_index_t)) {
2023 d = *(st_index_t *)data;
2024#ifdef WORDS_BIGENDIAN
2025 t = (t << sr) | (d >> sl);
2026#else
2027 t = (t >> sr) | (d << sl);
2028#endif
2029 h = murmur_step(h, t);
2030 t = d;
2031 data += sizeof(st_index_t);
2032 len -= sizeof(st_index_t);
2033 }
2034
2035 pack = len < (size_t)align ? (int)len : align;
2036 d = 0;
2037 switch (pack) {
2038#ifdef WORDS_BIGENDIAN
2039# define UNALIGNED_ADD(n) case (n) + 1: \
2040 d |= data_at(n) << CHAR_BIT*(SIZEOF_ST_INDEX_T - (n) - 1)
2041#else
2042# define UNALIGNED_ADD(n) case (n) + 1: \
2043 d |= data_at(n) << CHAR_BIT*(n)
2044#endif
2045 UNALIGNED_ADD_ALL;
2046#undef UNALIGNED_ADD
2047 }
2048#ifdef WORDS_BIGENDIAN
2049 t = (t << sr) | (d >> sl);
2050#else
2051 t = (t >> sr) | (d << sl);
2052#endif
2053
2054 if (len < (size_t)align) goto skip_tail;
2055# define SKIP_TAIL 1
2056 h = murmur_step(h, t);
2057 data += pack;
2058 len -= pack;
2059 }
2060 else
2061#endif
2062#ifdef HAVE_BUILTIN___BUILTIN_ASSUME_ALIGNED
2063#define aligned_data __builtin_assume_aligned(data, sizeof(st_index_t))
2064#else
2065#define aligned_data data
2066#endif
2067 {
2068 do {
2069 h = murmur_step(h, *(st_index_t *)aligned_data);
2070 data += sizeof(st_index_t);
2071 len -= sizeof(st_index_t);
2072 } while (len >= sizeof(st_index_t));
2073 }
2074 }
2075
2076 t = 0;
2077 switch (len) {
2078#if UNALIGNED_WORD_ACCESS && SIZEOF_ST_INDEX_T <= 8 && CHAR_BIT == 8
2079 /* in this case byteorder doesn't really matter */
2080#if SIZEOF_ST_INDEX_T > 4
2081 case 7: t |= data_at(6) << 48;
2082 case 6: t |= data_at(5) << 40;
2083 case 5: t |= data_at(4) << 32;
2084 case 4:
2085 t |= (st_index_t)*(uint32_t*)aligned_data;
2086 goto skip_tail;
2087# define SKIP_TAIL 1
2088#endif
2089 case 3: t |= data_at(2) << 16;
2090 case 2: t |= data_at(1) << 8;
2091 case 1: t |= data_at(0);
2092#else
2093#ifdef WORDS_BIGENDIAN
2094# define UNALIGNED_ADD(n) case (n) + 1: \
2095 t |= data_at(n) << CHAR_BIT*(SIZEOF_ST_INDEX_T - (n) - 1)
2096#else
2097# define UNALIGNED_ADD(n) case (n) + 1: \
2098 t |= data_at(n) << CHAR_BIT*(n)
2099#endif
2100 UNALIGNED_ADD_ALL;
2101#undef UNALIGNED_ADD
2102#endif
2103#ifdef SKIP_TAIL
2104 skip_tail:
2105#endif
2106 h ^= t; h -= ROTL(t, 7);
2107 h *= C2;
2108 }
2109 h ^= l;
2110#undef aligned_data
2111
2112 return murmur_finish(h);
2113}
2114
2115st_index_t
2116st_hash_uint32(st_index_t h, uint32_t i)
2117{
2118 return murmur_step(h, i);
2119}
2120
2121NO_SANITIZE("unsigned-integer-overflow", extern st_index_t st_hash_uint(st_index_t h, st_index_t i));
2122st_index_t
2123st_hash_uint(st_index_t h, st_index_t i)
2124{
2125 i += h;
2126/* no matter if it is BigEndian or LittleEndian,
2127 * we hash just integers */
2128#if SIZEOF_ST_INDEX_T*CHAR_BIT > 8*8
2129 h = murmur_step(h, i >> 8*8);
2130#endif
2131 h = murmur_step(h, i);
2132 return h;
2133}
2134
2135st_index_t
2136st_hash_end(st_index_t h)
2137{
2138 h = murmur_finish(h);
2139 return h;
2140}
2141
2142#undef st_hash_start
2143st_index_t
2144rb_st_hash_start(st_index_t h)
2145{
2146 return h;
2147}
2148
2149static st_index_t
2150strhash(st_data_t arg)
2151{
2152 register const char *string = (const char *)arg;
2153 return st_hash(string, strlen(string), FNV1_32A_INIT);
2154}
2155
2156int
2157st_locale_insensitive_strcasecmp(const char *s1, const char *s2)
2158{
2159 char c1, c2;
2160
2161 while (1) {
2162 c1 = *s1++;
2163 c2 = *s2++;
2164 if (c1 == '\0' || c2 == '\0') {
2165 if (c1 != '\0') return 1;
2166 if (c2 != '\0') return -1;
2167 return 0;
2168 }
2169 if (('A' <= c1) && (c1 <= 'Z')) c1 += 'a' - 'A';
2170 if (('A' <= c2) && (c2 <= 'Z')) c2 += 'a' - 'A';
2171 if (c1 != c2) {
2172 if (c1 > c2)
2173 return 1;
2174 else
2175 return -1;
2176 }
2177 }
2178}
2179
2180int
2181st_locale_insensitive_strncasecmp(const char *s1, const char *s2, size_t n)
2182{
2183 char c1, c2;
2184 size_t i;
2185
2186 for (i = 0; i < n; i++) {
2187 c1 = *s1++;
2188 c2 = *s2++;
2189 if (c1 == '\0' || c2 == '\0') {
2190 if (c1 != '\0') return 1;
2191 if (c2 != '\0') return -1;
2192 return 0;
2193 }
2194 if (('A' <= c1) && (c1 <= 'Z')) c1 += 'a' - 'A';
2195 if (('A' <= c2) && (c2 <= 'Z')) c2 += 'a' - 'A';
2196 if (c1 != c2) {
2197 if (c1 > c2)
2198 return 1;
2199 else
2200 return -1;
2201 }
2202 }
2203 return 0;
2204}
2205
2206static int
2207st_strcmp(st_data_t lhs, st_data_t rhs)
2208{
2209 const char *s1 = (char *)lhs;
2210 const char *s2 = (char *)rhs;
2211 return strcmp(s1, s2);
2212}
2213
2214static int
2215st_locale_insensitive_strcasecmp_i(st_data_t lhs, st_data_t rhs)
2216{
2217 const char *s1 = (char *)lhs;
2218 const char *s2 = (char *)rhs;
2219 return st_locale_insensitive_strcasecmp(s1, s2);
2220}
2221
2222NO_SANITIZE("unsigned-integer-overflow", PUREFUNC(static st_index_t strcasehash(st_data_t)));
2223static st_index_t
2224strcasehash(st_data_t arg)
2225{
2226 register const char *string = (const char *)arg;
2227 register st_index_t hval = FNV1_32A_INIT;
2228
2229 /*
2230 * FNV-1a hash each octet in the buffer
2231 */
2232 while (*string) {
2233 unsigned int c = (unsigned char)*string++;
2234 if ((unsigned int)(c - 'A') <= ('Z' - 'A')) c += 'a' - 'A';
2235 hval ^= c;
2236
2237 /* multiply by the 32 bit FNV magic prime mod 2^32 */
2238 hval *= FNV_32_PRIME;
2239 }
2240 return hval;
2241}
2242
2243int
2244st_numcmp(st_data_t x, st_data_t y)
2245{
2246 return x != y;
2247}
2248
2249st_index_t
2250st_numhash(st_data_t n)
2251{
2252 enum {s1 = 11, s2 = 3};
2253 return (st_index_t)((n>>s1|(n<<s2)) ^ (n>>s2));
2254}
2255
2256#ifdef RUBY
2257/* Expand TAB to be suitable for holding SIZ entries in total.
2258 Pre-existing entries remain not deleted inside of TAB, but its bins
2259 are cleared to expect future reconstruction. See rehash below. */
2260static void
2261st_expand_table(st_table *tab, st_index_t siz)
2262{
2263 st_table *tmp;
2264 st_index_t n;
2265
2266 if (siz <= get_allocated_entries(tab))
2267 return; /* enough room already */
2268
2269 tmp = st_init_table_with_size(tab->type, siz);
2270 n = get_allocated_entries(tab);
2271 MEMCPY(tmp->entries, tab->entries, st_table_entry, n);
2272 st_free_entries(tab);
2273
2274 tab->entry_power = tmp->entry_power;
2275 tab->bin_power = tmp->bin_power;
2276 tab->size_ind = tmp->size_ind;
2277 tab->entries = tmp->entries;
2278 tab->rebuilds_num++;
2279 free_fixed_ptr(tmp);
2280}
2281
2282/* Rehash using linear search. Return TRUE if we found that the table
2283 was rebuilt. */
2284static int
2285st_rehash_linear(st_table *tab)
2286{
2287 int eq_p, rebuilt_p;
2288 st_index_t i, j;
2289 st_table_entry *p, *q;
2290
2291 for (i = tab->entries_start; i < tab->entries_bound; i++) {
2292 p = &tab->entries[i];
2293 if (DELETED_ENTRY_P(p))
2294 continue;
2295 for (j = i + 1; j < tab->entries_bound; j++) {
2296 q = &tab->entries[j];
2297 if (DELETED_ENTRY_P(q))
2298 continue;
2299 DO_PTR_EQUAL_CHECK(tab, p, q->hash, q->key, eq_p, rebuilt_p);
2300 if (EXPECT(rebuilt_p, 0))
2301 return TRUE;
2302 if (eq_p) {
2303 *p = *q;
2304 MARK_ENTRY_DELETED(q);
2305 tab->num_entries--;
2306 update_range_for_deleted(tab, j);
2307 }
2308 }
2309 }
2310 return FALSE;
2311}
2312
2313/* Rehash using index. Return TRUE if we found that the table was
2314 rebuilt. */
2315static int
2316st_rehash_indexed(st_table *tab)
2317{
2318 int eq_p, rebuilt_p;
2319 st_index_t i;
2320
2321 unsigned int const size_ind = get_size_ind(tab);
2322 initialize_bins(tab);
2323 for (i = tab->entries_start; i < tab->entries_bound; i++) {
2324 st_table_entry *p = &tab->entries[i];
2325 st_index_t ind;
2326#ifdef QUADRATIC_PROBE
2327 st_index_t d = 1;
2328#else
2329 st_index_t perturb = p->hash;
2330#endif
2331
2332 if (DELETED_ENTRY_P(p))
2333 continue;
2334
2335 ind = hash_bin(p->hash, tab);
2336 for (;;) {
2337 st_index_t bin = get_bin(st_bins_ptr(tab), size_ind, ind);
2338 if (EMPTY_OR_DELETED_BIN_P(bin)) {
2339 /* ok, new room */
2340 set_bin(st_bins_ptr(tab), size_ind, ind, i + ENTRY_BASE);
2341 break;
2342 }
2343 else {
2344 st_table_entry *q = &tab->entries[bin - ENTRY_BASE];
2345 DO_PTR_EQUAL_CHECK(tab, q, p->hash, p->key, eq_p, rebuilt_p);
2346 if (EXPECT(rebuilt_p, 0))
2347 return TRUE;
2348 if (eq_p) {
2349 /* duplicated key; delete it */
2350 q->record = p->record;
2351 MARK_ENTRY_DELETED(p);
2352 tab->num_entries--;
2353 update_range_for_deleted(tab, bin);
2354 break;
2355 }
2356 else {
2357 /* hash collision; skip it */
2358#ifdef QUADRATIC_PROBE
2359 ind = hash_bin(ind + d, tab);
2360 d++;
2361#else
2362 ind = secondary_hash(ind, tab, &perturb);
2363#endif
2364 }
2365 }
2366 }
2367 }
2368 return FALSE;
2369}
2370
2371/* Reconstruct TAB's bins according to TAB's entries. This function
2372 permits conflicting keys inside of entries. No errors are reported
2373 then. All but one of them are discarded silently. */
2374static void
2375st_rehash(st_table *tab)
2376{
2377 int rebuilt_p;
2378
2379 do {
2380 if (tab->entry_power <= MAX_POWER2_FOR_TABLES_WITHOUT_BINS)
2381 rebuilt_p = st_rehash_linear(tab);
2382 else
2383 rebuilt_p = st_rehash_indexed(tab);
2384 } while (rebuilt_p);
2385}
2386
2387static st_data_t
2388st_stringify(VALUE key)
2389{
2390 return (rb_obj_class(key) == rb_cString && !RB_OBJ_FROZEN(key)) ?
2391 rb_hash_key_str(key) : key;
2392}
2393
2394static void
2395st_insert_single(st_table *tab, VALUE hash, VALUE key, VALUE val)
2396{
2397 st_data_t k = st_stringify(key);
2399 e.hash = do_hash(k, tab);
2400 e.key = k;
2401 e.record = val;
2402
2403 tab->entries[tab->entries_bound++] = e;
2404 tab->num_entries++;
2405 RB_OBJ_WRITTEN(hash, Qundef, k);
2406 RB_OBJ_WRITTEN(hash, Qundef, val);
2407}
2408
2409static void
2410st_insert_linear(st_table *tab, long argc, const VALUE *argv, VALUE hash)
2411{
2412 long i;
2413
2414 for (i = 0; i < argc; /* */) {
2415 st_data_t k = st_stringify(argv[i++]);
2416 st_data_t v = argv[i++];
2417 st_insert(tab, k, v);
2418 RB_OBJ_WRITTEN(hash, Qundef, k);
2419 RB_OBJ_WRITTEN(hash, Qundef, v);
2420 }
2421}
2422
2423static void
2424st_insert_generic(st_table *tab, long argc, const VALUE *argv, VALUE hash)
2425{
2426 long i;
2427
2428 /* push elems */
2429 for (i = 0; i < argc; /* */) {
2430 VALUE key = argv[i++];
2431 VALUE val = argv[i++];
2432 st_insert_single(tab, hash, key, val);
2433 }
2434
2435 /* reindex */
2436 st_rehash(tab);
2437}
2438
2439/* Mimics ruby's { foo => bar } syntax. This function is subpart
2440 of rb_hash_bulk_insert. */
2441void
2442rb_hash_bulk_insert_into_st_table(long argc, const VALUE *argv, VALUE hash)
2443{
2444 st_index_t n, size = argc / 2;
2445 st_table *tab = RHASH_ST_TABLE(hash);
2446
2447 tab = RHASH_TBL_RAW(hash);
2448 n = tab->entries_bound + size;
2449 st_expand_table(tab, n);
2450 if (UNLIKELY(tab->num_entries))
2451 st_insert_generic(tab, argc, argv, hash);
2452 else if (argc <= 2)
2453 st_insert_single(tab, hash, argv[0], argv[1]);
2454 else if (tab->entry_power <= MAX_POWER2_FOR_TABLES_WITHOUT_BINS)
2455 st_insert_linear(tab, argc, argv, hash);
2456 else
2457 st_insert_generic(tab, argc, argv, hash);
2458}
2459
2460void
2461rb_st_compact_table(st_table *tab)
2462{
2463 st_index_t num = tab->num_entries;
2464 if (REBUILD_THRESHOLD * num <= get_allocated_entries(tab)) {
2465 /* Compaction: */
2466 st_table *new_tab = st_init_table_with_size(tab->type, 2 * num);
2467 rebuild_table_with(new_tab, tab);
2468 rebuild_move_table(new_tab, tab);
2469 rebuild_cleanup(tab);
2470 }
2471}
2472
2473/*
2474 * set_table related code
2475 */
2476
2477struct set_table_entry {
2478 st_hash_t hash;
2479 st_data_t key;
2480};
2481
2482static inline void
2483set_ptr_equal_check(const set_table *tab, const set_table_entry *entry,
2484 st_hash_t hash_val, st_data_t key,
2485 int *res, int *rebuilt_p)
2486{
2487 unsigned int old_rebuilds_num = tab->rebuilds_num;
2488 *res = entry_equal(tab->type, entry->hash, entry->key, hash_val, key);
2489 *rebuilt_p = old_rebuilds_num != tab->rebuilds_num;
2490}
2491
2492#define SET_DO_PTR_EQUAL_CHECK(tab, ptr, hash_val, key, res, rebuilt_p) \
2493 set_ptr_equal_check((tab), (ptr), (hash_val), (key), &(res), &(rebuilt_p))
2494
2495/* Return hash value of KEY for table TAB. */
2496static inline st_hash_t
2497set_do_hash(st_data_t key, set_table *tab)
2498{
2499 st_hash_t hash = (st_hash_t)(tab->type->hash)(key);
2500 return normalize_hash_value(hash);
2501}
2502
2503/* Return bin size index of table TAB. */
2504static inline unsigned int
2505set_get_size_ind(const set_table *tab)
2506{
2507 return tab->size_ind;
2508}
2509
2510/* Return the number of allocated bins of table TAB. */
2511static inline st_index_t
2512set_get_bins_num(const set_table *tab)
2513{
2514 return ((st_index_t) 1)<<tab->bin_power;
2515}
2516
2517/* Return mask for a bin index in table TAB. */
2518static inline st_index_t
2519set_bins_mask(const set_table *tab)
2520{
2521 return set_get_bins_num(tab) - 1;
2522}
2523
2524/* Return the index of table TAB bin corresponding to
2525 HASH_VALUE. */
2526static inline st_index_t
2527set_hash_bin(st_hash_t hash_value, set_table *tab)
2528{
2529 return hash_value & set_bins_mask(tab);
2530}
2531
2532/* Return the number of allocated entries of table TAB. */
2533static inline st_index_t
2534set_get_allocated_entries(const set_table *tab)
2535{
2536 return ((st_index_t) 1)<<tab->entry_power;
2537}
2538
2539static inline size_t
2540set_allocated_entries_size(const set_table *tab)
2541{
2542 return set_get_allocated_entries(tab) * sizeof(set_table_entry);
2543}
2544
2545static inline bool
2546set_has_bins(const set_table *tab)
2547{
2548 return tab->entry_power > MAX_POWER2_FOR_TABLES_WITHOUT_BINS;
2549}
2550
2551/* Return size of the allocated bins of table TAB. */
2552static inline st_index_t
2553set_bins_size(const set_table *tab)
2554{
2555 if (set_has_bins(tab)) {
2556 return features[tab->entry_power].bins_words * sizeof (st_index_t);
2557 }
2558
2559 return 0;
2560}
2561
2562static inline st_index_t *
2563set_bins_ptr(const set_table *tab)
2564{
2565 if (set_has_bins(tab)) {
2566 return (st_index_t *)(((char *)tab->entries) + set_allocated_entries_size(tab));
2567 }
2568
2569 return NULL;
2570}
2571
2572/* Mark all bins of table TAB as empty. */
2573static void
2574set_initialize_bins(set_table *tab)
2575{
2576 memset(set_bins_ptr(tab), 0, set_bins_size(tab));
2577}
2578
2579/* Make table TAB empty. */
2580static void
2581set_make_tab_empty(set_table *tab)
2582{
2583 tab->num_entries = 0;
2584 tab->entries_start = tab->entries_bound = 0;
2585 if (set_bins_ptr(tab) != NULL)
2586 set_initialize_bins(tab);
2587}
2588
2589static inline size_t
2590set_entries_memsize(set_table *tab)
2591{
2592 size_t memsize = set_get_allocated_entries(tab) * sizeof(set_table_entry);
2593 if (set_has_bins(tab)) {
2594 memsize += set_bins_size(tab);
2595 }
2596 return memsize;
2597}
2598
2599static set_table *
2600set_init_existing_table_with_size(set_table *tab, const struct st_hash_type *type, st_index_t size)
2601{
2602 int n;
2603
2604#ifdef HASH_LOG
2605#if HASH_LOG+0 < 0
2606 {
2607 const char *e = getenv("ST_HASH_LOG");
2608 if (!e || !*e) init_st = 1;
2609 }
2610#endif
2611 if (init_st == 0) {
2612 init_st = 1;
2613 atexit(stat_col);
2614 }
2615#endif
2616
2617 n = get_power2(size);
2618
2619 tab->type = type;
2620 tab->entry_power = n;
2621 tab->bin_power = features[n].bin_power;
2622 tab->size_ind = features[n].size_ind;
2623
2624 tab->entries = (set_table_entry *)malloc(set_entries_memsize(tab));
2625 set_make_tab_empty(tab);
2626 tab->rebuilds_num = 0;
2627 return tab;
2628}
2629
2630/* Create and return table with TYPE which can hold at least SIZE
2631 entries. The real number of entries which the table can hold is
2632 the nearest power of two for SIZE. */
2633set_table *
2634set_init_table_with_size(set_table *tab, const struct st_hash_type *type, st_index_t size)
2635{
2636 if (tab == NULL) tab = malloc(sizeof(set_table));
2637
2638 set_init_existing_table_with_size(tab, type, size);
2639
2640 return tab;
2641}
2642
2643set_table *
2644set_init_numtable(void)
2645{
2646 return set_init_table_with_size(NULL, &type_numhash, 0);
2647}
2648
2649set_table *
2650set_init_numtable_with_size(st_index_t size)
2651{
2652 return set_init_table_with_size(NULL, &type_numhash, size);
2653}
2654
2655set_table *
2656set_init_embedded_numtable_with_size(set_table *tab, st_index_t size)
2657{
2658 return set_init_existing_table_with_size(tab, &type_numhash, size);
2659}
2660
2661size_t
2662set_table_size(const struct set_table *tbl)
2663{
2664 return tbl->num_entries;
2665}
2666
2667/* Make table TAB empty. */
2668void
2669set_table_clear(set_table *tab)
2670{
2671 set_make_tab_empty(tab);
2672 tab->rebuilds_num++;
2673}
2674
2675void
2676set_free_embedded_table(set_table *tab)
2677{
2678 sized_free(tab->entries, set_entries_memsize(tab));
2679}
2680
2681/* Free table TAB space. This should only be used if you passed NULL to
2682 set_init_table_with_size/set_copy when creating the table. */
2683void
2684set_free_table(set_table *tab)
2685{
2686 set_free_embedded_table(tab);
2687 free_fixed_ptr(tab);
2688}
2689
2690/* Return byte size of memory allocated for table TAB. */
2691size_t
2692set_memsize(const set_table *tab)
2693{
2694 return(sizeof(set_table)
2695 + (tab->entry_power <= MAX_POWER2_FOR_TABLES_WITHOUT_BINS ? 0 : set_bins_size(tab))
2696 + set_get_allocated_entries(tab) * sizeof(set_table_entry));
2697}
2698
2699static st_index_t
2700set_find_table_entry_ind(set_table *tab, st_hash_t hash_value, st_data_t key);
2701
2702static st_index_t
2703set_find_table_bin_ind(set_table *tab, st_hash_t hash_value, st_data_t key);
2704
2705static st_index_t
2706set_find_table_bin_ind_direct(set_table *table, st_hash_t hash_value, st_data_t key);
2707
2708static st_index_t
2709set_find_table_bin_ptr_and_reserve(set_table *tab, st_hash_t *hash_value,
2710 st_data_t key, st_index_t *bin_ind);
2711
2712static void set_rebuild_table_with(set_table *const new_tab, set_table *const tab);
2713static void set_rebuild_move_table(set_table *const new_tab, set_table *const tab);
2714static void set_rebuild_cleanup(set_table *const tab);
2715
2716/* Rebuild table TAB. Rebuilding removes all deleted bins and entries
2717 and can change size of the table entries and bins arrays.
2718 Rebuilding is implemented by creation of a new table or by
2719 compaction of the existing one. */
2720static void
2721set_rebuild_table(set_table *tab)
2722{
2723 if ((2 * tab->num_entries <= set_get_allocated_entries(tab)
2724 && REBUILD_THRESHOLD * tab->num_entries > set_get_allocated_entries(tab))
2725 || tab->num_entries < (1 << MINIMAL_POWER2)) {
2726 /* Compaction: */
2727 tab->num_entries = 0;
2728 if (set_has_bins(tab))
2729 set_initialize_bins(tab);
2730 set_rebuild_table_with(tab, tab);
2731 }
2732 else {
2733 set_table *new_tab;
2734 /* This allocation could trigger GC and compaction. If tab is the
2735 * gen_fields_tbl, then tab could have changed in size due to objects being
2736 * freed and/or moved. Do not store attributes of tab before this line. */
2737 new_tab = set_init_table_with_size(NULL, tab->type,
2738 2 * tab->num_entries - 1);
2739 set_rebuild_table_with(new_tab, tab);
2740 set_rebuild_move_table(new_tab, tab);
2741 }
2742 set_rebuild_cleanup(tab);
2743}
2744
2745static void
2746set_rebuild_table_with(set_table *const new_tab, set_table *const tab)
2747{
2748 st_index_t i, ni;
2749 unsigned int size_ind;
2750 set_table_entry *new_entries;
2751 set_table_entry *curr_entry_ptr;
2752 st_index_t *bins;
2753 st_index_t bin_ind;
2754
2755 new_entries = new_tab->entries;
2756
2757 ni = 0;
2758 bins = set_bins_ptr(new_tab);
2759 size_ind = set_get_size_ind(new_tab);
2760 st_index_t bound = tab->entries_bound;
2761 set_table_entry *entries = tab->entries;
2762
2763 for (i = tab->entries_start; i < bound; i++) {
2764 curr_entry_ptr = &entries[i];
2765 PREFETCH(entries + i + 1, 0);
2766 if (EXPECT(DELETED_ENTRY_P(curr_entry_ptr), 0))
2767 continue;
2768 if (&new_entries[ni] != curr_entry_ptr)
2769 new_entries[ni] = *curr_entry_ptr;
2770 if (EXPECT(bins != NULL, 1)) {
2771 bin_ind = set_find_table_bin_ind_direct(new_tab, curr_entry_ptr->hash,
2772 curr_entry_ptr->key);
2773 set_bin(bins, size_ind, bin_ind, ni + ENTRY_BASE);
2774 }
2775 new_tab->num_entries++;
2776 ni++;
2777 }
2778
2779 assert(new_tab->num_entries == tab->num_entries);
2780}
2781
2782static void
2783set_rebuild_move_table(set_table *const new_tab, set_table *const tab)
2784{
2785 sized_free(tab->entries, set_entries_memsize(tab));
2786 tab->entries = new_tab->entries;
2787
2788 tab->entry_power = new_tab->entry_power;
2789 tab->bin_power = new_tab->bin_power;
2790 tab->size_ind = new_tab->size_ind;
2791
2792 free_fixed_ptr(new_tab);
2793}
2794
2795static void
2796set_rebuild_cleanup(set_table *const tab)
2797{
2798 tab->entries_start = 0;
2799 tab->entries_bound = tab->num_entries;
2800 tab->rebuilds_num++;
2801}
2802
2803/* Return the next secondary hash index for table TAB using previous
2804 index IND and PERTURB. Finally modulo of the function becomes a
2805 full *cycle linear congruential generator*, in other words it
2806 guarantees traversing all table bins in extreme case.
2807
2808 According the Hull-Dobell theorem a generator
2809 "Xnext = (a*Xprev + c) mod m" is a full cycle generator if and only if
2810 o m and c are relatively prime
2811 o a-1 is divisible by all prime factors of m
2812 o a-1 is divisible by 4 if m is divisible by 4.
2813
2814 For our case a is 5, c is 1, and m is a power of two. */
2815static inline st_index_t
2816set_secondary_hash(st_index_t ind, set_table *tab, st_index_t *perturb)
2817{
2818 *perturb >>= 11;
2819 ind = (ind << 2) + ind + *perturb + 1;
2820 return set_hash_bin(ind, tab);
2821}
2822
2823/* Find an entry with HASH_VALUE and KEY in TABLE using a linear
2824 search. Return the index of the found entry in array `entries`.
2825 If it is not found, return UNDEFINED_ENTRY_IND. If the table was
2826 rebuilt during the search, return REBUILT_TABLE_ENTRY_IND. */
2827static inline st_index_t
2828set_find_entry(set_table *tab, st_hash_t hash_value, st_data_t key)
2829{
2830 int eq_p, rebuilt_p;
2831 st_index_t i, bound;
2832 set_table_entry *entries;
2833
2834 bound = tab->entries_bound;
2835 entries = tab->entries;
2836 for (i = tab->entries_start; i < bound; i++) {
2837 SET_DO_PTR_EQUAL_CHECK(tab, &entries[i], hash_value, key, eq_p, rebuilt_p);
2838 if (EXPECT(rebuilt_p, 0))
2839 return REBUILT_TABLE_ENTRY_IND;
2840 if (eq_p)
2841 return i;
2842 }
2843 return UNDEFINED_ENTRY_IND;
2844}
2845
2846/* Use the quadratic probing. The method has a better data locality
2847 but more collisions than the current approach. In average it
2848 results in a bit slower search. */
2849/*#define QUADRATIC_PROBE*/
2850
2851/* Return index of entry with HASH_VALUE and KEY in table TAB. If
2852 there is no such entry, return UNDEFINED_ENTRY_IND. If the table
2853 was rebuilt during the search, return REBUILT_TABLE_ENTRY_IND. */
2854static st_index_t
2855set_find_table_entry_ind(set_table *tab, st_hash_t hash_value, st_data_t key)
2856{
2857 int eq_p, rebuilt_p;
2858 st_index_t ind;
2859#ifdef QUADRATIC_PROBE
2860 st_index_t d;
2861#else
2862 st_index_t perturb;
2863#endif
2864 st_index_t bin;
2865 set_table_entry *entries = tab->entries;
2866
2867 ind = set_hash_bin(hash_value, tab);
2868#ifdef QUADRATIC_PROBE
2869 d = 1;
2870#else
2871 perturb = hash_value;
2872#endif
2873 for (;;) {
2874 bin = get_bin(set_bins_ptr(tab), set_get_size_ind(tab), ind);
2875 if (! EMPTY_OR_DELETED_BIN_P(bin)) {
2876 SET_DO_PTR_EQUAL_CHECK(tab, &entries[bin - ENTRY_BASE], hash_value, key, eq_p, rebuilt_p);
2877 if (EXPECT(rebuilt_p, 0))
2878 return REBUILT_TABLE_ENTRY_IND;
2879 if (eq_p)
2880 break;
2881 }
2882 else if (EMPTY_BIN_P(bin))
2883 return UNDEFINED_ENTRY_IND;
2884#ifdef QUADRATIC_PROBE
2885 ind = set_hash_bin(ind + d, tab);
2886 d++;
2887#else
2888 ind = set_secondary_hash(ind, tab, &perturb);
2889#endif
2890 }
2891 return bin;
2892}
2893
2894/* Find and return index of table TAB bin corresponding to an entry
2895 with HASH_VALUE and KEY. If there is no such bin, return
2896 UNDEFINED_BIN_IND. If the table was rebuilt during the search,
2897 return REBUILT_TABLE_BIN_IND. */
2898static st_index_t
2899set_find_table_bin_ind(set_table *tab, st_hash_t hash_value, st_data_t key)
2900{
2901 int eq_p, rebuilt_p;
2902 st_index_t ind;
2903#ifdef QUADRATIC_PROBE
2904 st_index_t d;
2905#else
2906 st_index_t perturb;
2907#endif
2908 st_index_t bin;
2909 set_table_entry *entries = tab->entries;
2910
2911 ind = set_hash_bin(hash_value, tab);
2912#ifdef QUADRATIC_PROBE
2913 d = 1;
2914#else
2915 perturb = hash_value;
2916#endif
2917 for (;;) {
2918 bin = get_bin(set_bins_ptr(tab), set_get_size_ind(tab), ind);
2919 if (! EMPTY_OR_DELETED_BIN_P(bin)) {
2920 SET_DO_PTR_EQUAL_CHECK(tab, &entries[bin - ENTRY_BASE], hash_value, key, eq_p, rebuilt_p);
2921 if (EXPECT(rebuilt_p, 0))
2922 return REBUILT_TABLE_BIN_IND;
2923 if (eq_p)
2924 break;
2925 }
2926 else if (EMPTY_BIN_P(bin))
2927 return UNDEFINED_BIN_IND;
2928#ifdef QUADRATIC_PROBE
2929 ind = set_hash_bin(ind + d, tab);
2930 d++;
2931#else
2932 ind = set_secondary_hash(ind, tab, &perturb);
2933#endif
2934 }
2935 return ind;
2936}
2937
2938/* Find and return index of table TAB bin corresponding to an entry
2939 with HASH_VALUE and KEY. The entry should be in the table
2940 already. */
2941static st_index_t
2942set_find_table_bin_ind_direct(set_table *tab, st_hash_t hash_value, st_data_t key)
2943{
2944 st_index_t ind;
2945#ifdef QUADRATIC_PROBE
2946 st_index_t d;
2947#else
2948 st_index_t perturb;
2949#endif
2950 st_index_t bin;
2951
2952 ind = set_hash_bin(hash_value, tab);
2953#ifdef QUADRATIC_PROBE
2954 d = 1;
2955#else
2956 perturb = hash_value;
2957#endif
2958 for (;;) {
2959 bin = get_bin(set_bins_ptr(tab), set_get_size_ind(tab), ind);
2960 if (EMPTY_OR_DELETED_BIN_P(bin))
2961 return ind;
2962#ifdef QUADRATIC_PROBE
2963 ind = set_hash_bin(ind + d, tab);
2964 d++;
2965#else
2966 ind = set_secondary_hash(ind, tab, &perturb);
2967#endif
2968 }
2969}
2970
2971/* Mark I-th bin of table TAB as empty, in other words not
2972 corresponding to any entry. */
2973#define MARK_SET_BIN_EMPTY(tab, i) (set_bin(set_bins_ptr(tab), set_get_size_ind(tab), i, EMPTY_BIN))
2974
2975/* Return index of table TAB bin for HASH_VALUE and KEY through
2976 BIN_IND and the pointed value as the function result. Reserve the
2977 bin for inclusion of the corresponding entry into the table if it
2978 is not there yet. We always find such bin as bins array length is
2979 bigger entries array. Although we can reuse a deleted bin, the
2980 result bin value is always empty if the table has no entry with
2981 KEY. Return the entries array index of the found entry or
2982 UNDEFINED_ENTRY_IND if it is not found. If the table was rebuilt
2983 during the search, return REBUILT_TABLE_ENTRY_IND. */
2984static st_index_t
2985set_find_table_bin_ptr_and_reserve(set_table *tab, st_hash_t *hash_value,
2986 st_data_t key, st_index_t *bin_ind)
2987{
2988 int eq_p, rebuilt_p;
2989 st_index_t ind;
2990 st_hash_t curr_hash_value = *hash_value;
2991#ifdef QUADRATIC_PROBE
2992 st_index_t d;
2993#else
2994 st_index_t perturb;
2995#endif
2996 st_index_t entry_index;
2997 st_index_t firset_deleted_bin_ind;
2998 set_table_entry *entries;
2999
3000 ind = set_hash_bin(curr_hash_value, tab);
3001#ifdef QUADRATIC_PROBE
3002 d = 1;
3003#else
3004 perturb = curr_hash_value;
3005#endif
3006 firset_deleted_bin_ind = UNDEFINED_BIN_IND;
3007 entries = tab->entries;
3008 for (;;) {
3009 entry_index = get_bin(set_bins_ptr(tab), set_get_size_ind(tab), ind);
3010 if (EMPTY_BIN_P(entry_index)) {
3011 tab->num_entries++;
3012 entry_index = UNDEFINED_ENTRY_IND;
3013 if (firset_deleted_bin_ind != UNDEFINED_BIN_IND) {
3014 /* We can reuse bin of a deleted entry. */
3015 ind = firset_deleted_bin_ind;
3016 MARK_SET_BIN_EMPTY(tab, ind);
3017 }
3018 break;
3019 }
3020 else if (! DELETED_BIN_P(entry_index)) {
3021 SET_DO_PTR_EQUAL_CHECK(tab, &entries[entry_index - ENTRY_BASE], curr_hash_value, key, eq_p, rebuilt_p);
3022 if (EXPECT(rebuilt_p, 0))
3023 return REBUILT_TABLE_ENTRY_IND;
3024 if (eq_p)
3025 break;
3026 }
3027 else if (firset_deleted_bin_ind == UNDEFINED_BIN_IND)
3028 firset_deleted_bin_ind = ind;
3029#ifdef QUADRATIC_PROBE
3030 ind = set_hash_bin(ind + d, tab);
3031 d++;
3032#else
3033 ind = set_secondary_hash(ind, tab, &perturb);
3034#endif
3035 }
3036 *bin_ind = ind;
3037 return entry_index;
3038}
3039
3040/* Find an entry with KEY in table TAB. Return non-zero if we found
3041 it. */
3042int
3043set_table_lookup(set_table *tab, st_data_t key)
3044{
3045 st_index_t bin;
3046 st_hash_t hash = set_do_hash(key, tab);
3047
3048 retry:
3049 if (!set_has_bins(tab)) {
3050 bin = set_find_entry(tab, hash, key);
3051 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
3052 goto retry;
3053 if (bin == UNDEFINED_ENTRY_IND)
3054 return 0;
3055 }
3056 else {
3057 bin = set_find_table_entry_ind(tab, hash, key);
3058 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
3059 goto retry;
3060 if (bin == UNDEFINED_ENTRY_IND)
3061 return 0;
3062 bin -= ENTRY_BASE;
3063 }
3064 return 1;
3065}
3066
3067/* Check the table and rebuild it if it is necessary. */
3068static inline void
3069set_rebuild_table_if_necessary(set_table *tab)
3070{
3071 st_index_t bound = tab->entries_bound;
3072
3073 if (bound == set_get_allocated_entries(tab) || tab->entries_start == MAX_ENTRIES_START) {
3074 set_rebuild_table(tab);
3075 }
3076}
3077
3078/* Insert KEY into table TAB and return zero. If there is
3079 already entry with KEY in the table, return nonzero and update
3080 the value of the found entry. */
3081int
3082set_insert(set_table *tab, st_data_t key)
3083{
3084 set_table_entry *entry;
3085 st_index_t bin;
3086 st_index_t ind;
3087 st_hash_t hash_value;
3088 st_index_t bin_ind;
3089 int new_p;
3090
3091 hash_value = set_do_hash(key, tab);
3092 retry:
3093 set_rebuild_table_if_necessary(tab);
3094 if (!set_has_bins(tab)) {
3095 bin = set_find_entry(tab, hash_value, key);
3096 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
3097 goto retry;
3098 new_p = bin == UNDEFINED_ENTRY_IND;
3099 if (new_p)
3100 tab->num_entries++;
3101 bin_ind = UNDEFINED_BIN_IND;
3102 }
3103 else {
3104 bin = set_find_table_bin_ptr_and_reserve(tab, &hash_value,
3105 key, &bin_ind);
3106 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
3107 goto retry;
3108 new_p = bin == UNDEFINED_ENTRY_IND;
3109 bin -= ENTRY_BASE;
3110 }
3111 if (new_p) {
3112 ind = tab->entries_bound++;
3113 entry = &tab->entries[ind];
3114 entry->hash = hash_value;
3115 entry->key = key;
3116 if (bin_ind != UNDEFINED_BIN_IND)
3117 set_bin(set_bins_ptr(tab), set_get_size_ind(tab), bin_ind, ind + ENTRY_BASE);
3118 return 0;
3119 }
3120 return 1;
3121}
3122
3123/* Create a copy of old_tab into new_tab. */
3124static set_table *
3125set_replace(set_table *new_tab, set_table *old_tab)
3126{
3127 *new_tab = *old_tab;
3128 size_t memsize = set_allocated_entries_size(old_tab) + set_bins_size(old_tab);
3129 new_tab->entries = (set_table_entry *)malloc(memsize);
3130 MEMCPY(new_tab->entries, old_tab->entries, char, memsize);
3131 return new_tab;
3132}
3133
3134/* Create and return a copy of table OLD_TAB. */
3135set_table *
3136set_copy(set_table *new_tab, set_table *old_tab)
3137{
3138 if (new_tab == NULL) new_tab = (set_table *) malloc(sizeof(set_table));
3139
3140 if (set_replace(new_tab, old_tab) == NULL) {
3141 set_free_table(new_tab);
3142 return NULL;
3143 }
3144
3145 return new_tab;
3146}
3147
3148/* Update the entries start of table TAB after removing an entry
3149 with index N in the array entries. */
3150static inline void
3151set_update_range_for_deleted(set_table *tab, st_index_t n)
3152{
3153 /* Do not update entries_bound here. Otherwise, we can fill all
3154 bins by deleted entry value before rebuilding the table. */
3155 if (tab->entries_start == n) {
3156 st_index_t start = n + 1;
3157 st_index_t bound = tab->entries_bound;
3158 set_table_entry *entries = tab->entries;
3159 while (start < bound && DELETED_ENTRY_P(&entries[start])) start++;
3160 tab->entries_start = start > MAX_ENTRIES_START ? MAX_ENTRIES_START : (unsigned int)start;
3161 }
3162}
3163
3164/* Mark I-th bin of table TAB as corresponding to a deleted table
3165 entry. Update number of entries in the table and number of bins
3166 corresponding to deleted entries. */
3167#define MARK_SET_BIN_DELETED(tab, i) \
3168 do { \
3169 set_bin(set_bins_ptr(tab), set_get_size_ind(tab), i, DELETED_BIN); \
3170 } while (0)
3171
3172/* Delete entry with KEY from table TAB, and return non-zero. If
3173 there is no entry with KEY in the table, return zero. */
3174int
3175set_table_delete(set_table *tab, st_data_t *key)
3176{
3177 set_table_entry *entry;
3178 st_index_t bin;
3179 st_index_t bin_ind;
3180 st_hash_t hash;
3181
3182 hash = set_do_hash(*key, tab);
3183 retry:
3184 if (!set_has_bins(tab)) {
3185 bin = set_find_entry(tab, hash, *key);
3186 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
3187 goto retry;
3188 if (bin == UNDEFINED_ENTRY_IND) {
3189 return 0;
3190 }
3191 }
3192 else {
3193 bin_ind = set_find_table_bin_ind(tab, hash, *key);
3194 if (EXPECT(bin_ind == REBUILT_TABLE_BIN_IND, 0))
3195 goto retry;
3196 if (bin_ind == UNDEFINED_BIN_IND) {
3197 return 0;
3198 }
3199 bin = get_bin(set_bins_ptr(tab), set_get_size_ind(tab), bin_ind) - ENTRY_BASE;
3200 MARK_SET_BIN_DELETED(tab, bin_ind);
3201 }
3202 entry = &tab->entries[bin];
3203 *key = entry->key;
3204 MARK_ENTRY_DELETED(entry);
3205 tab->num_entries--;
3206 set_update_range_for_deleted(tab, bin);
3207 return 1;
3208}
3209
3210/* Traverse all entries in table TAB calling FUNC with current entry
3211 key and zero. If the call returns ST_STOP, stop
3212 traversing. If the call returns ST_DELETE, delete the current
3213 entry from the table. In case of ST_CHECK or ST_CONTINUE, continue
3214 traversing. The function returns zero unless an error is found.
3215 CHECK_P is flag of set_foreach_check call. The behavior is a bit
3216 different for ST_CHECK and when the current element is removed
3217 during traversing. */
3218static inline int
3219set_general_foreach(set_table *tab, set_foreach_check_callback_func *func,
3220 set_update_callback_func *replace, st_data_t arg,
3221 int check_p)
3222{
3223 st_index_t bin;
3224 st_index_t bin_ind;
3225 set_table_entry *entries, *curr_entry_ptr;
3226 enum st_retval retval;
3227 st_index_t i, rebuilds_num;
3228 st_hash_t hash;
3229 st_data_t key;
3230 int error_p, packed_p = !set_has_bins(tab);
3231
3232 entries = tab->entries;
3233 /* The bound can change inside the loop even without rebuilding
3234 the table, e.g. by an entry insertion. */
3235 for (i = tab->entries_start; i < tab->entries_bound; i++) {
3236 curr_entry_ptr = &entries[i];
3237 if (EXPECT(DELETED_ENTRY_P(curr_entry_ptr), 0))
3238 continue;
3239 key = curr_entry_ptr->key;
3240 rebuilds_num = tab->rebuilds_num;
3241 hash = curr_entry_ptr->hash;
3242 retval = (*func)(key, arg, 0);
3243
3244 if (retval == ST_REPLACE && replace) {
3245 retval = (*replace)(&key, arg, TRUE);
3246 curr_entry_ptr->key = key;
3247 }
3248
3249 if (rebuilds_num != tab->rebuilds_num) {
3250 retry:
3251 entries = tab->entries;
3252 packed_p = !set_has_bins(tab);
3253 if (packed_p) {
3254 i = set_find_entry(tab, hash, key);
3255 if (EXPECT(i == REBUILT_TABLE_ENTRY_IND, 0))
3256 goto retry;
3257 error_p = i == UNDEFINED_ENTRY_IND;
3258 }
3259 else {
3260 i = set_find_table_entry_ind(tab, hash, key);
3261 if (EXPECT(i == REBUILT_TABLE_ENTRY_IND, 0))
3262 goto retry;
3263 error_p = i == UNDEFINED_ENTRY_IND;
3264 i -= ENTRY_BASE;
3265 }
3266 if (error_p && check_p) {
3267 /* call func with error notice */
3268 retval = (*func)(0, arg, 1);
3269 return 1;
3270 }
3271 curr_entry_ptr = &entries[i];
3272 }
3273 switch (retval) {
3274 case ST_REPLACE:
3275 break;
3276 case ST_CONTINUE:
3277 break;
3278 case ST_CHECK:
3279 if (check_p)
3280 break;
3281 case ST_STOP:
3282 return 0;
3283 case ST_DELETE: {
3284 st_data_t key = curr_entry_ptr->key;
3285
3286 again:
3287 if (packed_p) {
3288 bin = set_find_entry(tab, hash, key);
3289 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
3290 goto again;
3291 if (bin == UNDEFINED_ENTRY_IND)
3292 break;
3293 }
3294 else {
3295 bin_ind = set_find_table_bin_ind(tab, hash, key);
3296 if (EXPECT(bin_ind == REBUILT_TABLE_BIN_IND, 0))
3297 goto again;
3298 if (bin_ind == UNDEFINED_BIN_IND)
3299 break;
3300 bin = get_bin(set_bins_ptr(tab), set_get_size_ind(tab), bin_ind) - ENTRY_BASE;
3301 MARK_SET_BIN_DELETED(tab, bin_ind);
3302 }
3303 curr_entry_ptr = &entries[bin];
3304 MARK_ENTRY_DELETED(curr_entry_ptr);
3305 tab->num_entries--;
3306 set_update_range_for_deleted(tab, bin);
3307 break;
3308 }
3309 }
3310 }
3311 return 0;
3312}
3313
3314int
3315set_foreach_with_replace(set_table *tab, set_foreach_check_callback_func *func, set_update_callback_func *replace, st_data_t arg)
3316{
3317 return set_general_foreach(tab, func, replace, arg, TRUE);
3318}
3319
3320struct set_functor {
3321 set_foreach_callback_func *func;
3322 st_data_t arg;
3323};
3324
3325static int
3326set_apply_functor(st_data_t k, st_data_t d, int _)
3327{
3328 const struct set_functor *f = (void *)d;
3329 return f->func(k, f->arg);
3330}
3331
3332int
3333set_table_foreach(set_table *tab, set_foreach_callback_func *func, st_data_t arg)
3334{
3335 const struct set_functor f = { func, arg };
3336 return set_general_foreach(tab, set_apply_functor, NULL, (st_data_t)&f, FALSE);
3337}
3338
3339/* See comments for function set_delete_safe. */
3340int
3341set_foreach_check(set_table *tab, set_foreach_check_callback_func *func, st_data_t arg,
3342 st_data_t never ATTRIBUTE_UNUSED)
3343{
3344 return set_general_foreach(tab, func, NULL, arg, TRUE);
3345}
3346
3347/* Set up array KEYS by at most SIZE keys of head table TAB entries.
3348 Return the number of keys set up in array KEYS. */
3349inline st_index_t
3350set_keys(set_table *tab, st_data_t *keys, st_index_t size)
3351{
3352 st_index_t i, bound;
3353 st_data_t key, *keys_start, *keys_end;
3354 set_table_entry *curr_entry_ptr, *entries = tab->entries;
3355
3356 bound = tab->entries_bound;
3357 keys_start = keys;
3358 keys_end = keys + size;
3359 for (i = tab->entries_start; i < bound; i++) {
3360 if (keys == keys_end)
3361 break;
3362 curr_entry_ptr = &entries[i];
3363 key = curr_entry_ptr->key;
3364 if (! DELETED_ENTRY_P(curr_entry_ptr))
3365 *keys++ = key;
3366 }
3367
3368 return keys - keys_start;
3369}
3370
3371void
3372set_compact_table(set_table *tab)
3373{
3374 st_index_t num = tab->num_entries;
3375 if (REBUILD_THRESHOLD * num <= set_get_allocated_entries(tab)) {
3376 /* Compaction: */
3377 set_table *new_tab = set_init_table_with_size(NULL, tab->type, 2 * num);
3378 set_rebuild_table_with(new_tab, tab);
3379 set_rebuild_move_table(new_tab, tab);
3380 set_rebuild_cleanup(tab);
3381 }
3382}
3383
3384#endif
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
Definition assert.h:219
static bool RB_OBJ_FROZEN(VALUE obj)
Checks if an object is frozen.
Definition fl_type.h:711
#define Qundef
Old name of RUBY_Qundef.
VALUE rb_eRuntimeError
RuntimeError exception.
Definition error.c:1429
VALUE rb_obj_class(VALUE obj)
Queries the class of an object.
Definition object.c:234
VALUE rb_cString
String class.
Definition string.c:85
#define RB_OBJ_WRITTEN(old, oldv, young)
Identical to RB_OBJ_WRITE(), except it doesn't write any values, but only a WB declaration.
Definition gc.h:468
int len
Length of the buffer.
Definition io.h:8
#define MEMCPY(p1, p2, type, n)
Handy macro to call memcpy.
Definition memory.h:372
VALUE type(ANYARGS)
ANYARGS-ed function type.
#define _(args)
This was a transition path from K&R to ANSI.
Definition stdarg.h:35
set_table_entry * entries
Array of size 2^entry_power.
Definition set_table.h:31
Definition st.c:139
Definition st.h:79
uintptr_t VALUE
Type that represents a Ruby object.
Definition value.h:40