Ruby 4.1.0dev (2026-09-27 revision f6ff9e7d02e46360f8930b280a3dd921cccbda29)
st.c (f6ff9e7d02e46360f8930b280a3dd921cccbda29)
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 /* The table may be embedded in an object the GC can already reach (T_HASH,
600 imemo_cdhash), in which case the allocation below can mark it. Empty it
601 first, marking walks entries[entries_start..entries_bound). */
602 tab->entries = NULL;
603 tab->num_entries = 0;
604 tab->entries_start = tab->entries_bound = 0;
605
606 size_t memsize = get_allocated_entries(tab) * sizeof(st_table_entry);
607 if (tab->entry_power > MAX_POWER2_FOR_TABLES_WITHOUT_BINS) {
608 memsize += bins_size(tab);
609 }
610 tab->entries = (st_table_entry *)malloc(memsize);
611#ifndef RUBY
612 if (tab->entries == NULL) {
613 st_free_table(tab);
614 return NULL;
615 }
616#endif
617 make_tab_empty(tab);
618 tab->rebuilds_num = 0;
619 return tab;
620}
621
622st_table *
623st_init_existing_numtable_with_size(st_table *tab, st_index_t size)
624{
625 return st_init_existing_table_with_size(tab, &type_numhash, size);
626}
627
628/* Create and return table with TYPE which can hold at least SIZE
629 entries. The real number of entries which the table can hold is
630 the nearest power of two for SIZE. */
631st_table *
632st_init_table_with_size(const struct st_hash_type *type, st_index_t size)
633{
634 st_table *tab = malloc(sizeof(st_table));
635#ifndef RUBY
636 if (tab == NULL)
637 return NULL;
638#endif
639
640#ifdef RUBY
641 st_init_existing_table_with_size(tab, type, size);
642#else
643 if (st_init_existing_table_with_size(tab, type, size) == NULL) {
644 free_fixed_ptr(tab);
645 return NULL;
646 }
647#endif
648
649 return tab;
650}
651
652size_t
653st_table_size(const struct st_table *tbl)
654{
655 return tbl->num_entries;
656}
657
658/* Create and return table with TYPE which can hold a minimal number
659 of entries (see comments for get_power2). */
660st_table *
661st_init_table(const struct st_hash_type *type)
662{
663 return st_init_table_with_size(type, 0);
664}
665
666/* Create and return table which can hold a minimal number of
667 numbers. */
668st_table *
669st_init_numtable(void)
670{
671 return st_init_table(&type_numhash);
672}
673
674/* Create and return table which can hold SIZE numbers. */
675st_table *
676st_init_numtable_with_size(st_index_t size)
677{
678 return st_init_table_with_size(&type_numhash, size);
679}
680
681/* Create and return table which can hold a minimal number of
682 strings. */
683st_table *
684st_init_strtable(void)
685{
686 return st_init_table(&type_strhash);
687}
688
689/* Create and return table which can hold SIZE strings. */
690st_table *
691st_init_strtable_with_size(st_index_t size)
692{
693 return st_init_table_with_size(&type_strhash, size);
694}
695
696st_table *
697st_init_existing_strtable_with_size(st_table *tab, st_index_t size)
698{
699 return st_init_existing_table_with_size(tab, &type_strhash, size);
700}
701
702
703/* Create and return table which can hold a minimal number of strings
704 whose character case is ignored. */
705st_table *
706st_init_strcasetable(void)
707{
708 return st_init_table(&type_strcasehash);
709}
710
711/* Create and return table which can hold SIZE strings whose character
712 case is ignored. */
713st_table *
714st_init_strcasetable_with_size(st_index_t size)
715{
716 return st_init_table_with_size(&type_strcasehash, size);
717}
718
719/* Make table TAB empty. */
720void
721st_clear(st_table *tab)
722{
723 make_tab_empty(tab);
724 tab->rebuilds_num++;
725}
726
727static inline size_t
728st_entries_memsize(const st_table *tab)
729{
730 return get_allocated_entries(tab) * sizeof(st_table_entry);
731}
732
733static inline void
734st_free_entries(const st_table *tab)
735{
736 sized_free(tab->entries, st_entries_memsize(tab) + bins_size(tab));
737}
738
739void
740st_free_embedded_table(st_table *tab)
741{
742 st_free_entries(tab);
743}
744
745/* Free table TAB space. */
746void
747st_free_table(st_table *tab)
748{
749 st_free_embedded_table(tab);
750 free_fixed_ptr(tab);
751}
752
753size_t
754st_allocated_memsize(const st_table *tab)
755{
756 RUBY_ASSERT(tab != NULL);
757 return bins_size(tab) + st_entries_memsize(tab);
758}
759
760/* Return byte size of memory allocated for table TAB. */
761size_t
762st_memsize(const st_table *tab)
763{
764 RUBY_ASSERT(tab != NULL);
765 return sizeof(st_table) + st_allocated_memsize(tab);
766}
767
768static st_index_t
769find_table_entry_ind(st_table *tab, st_hash_t hash_value, st_data_t key);
770
771static st_index_t
772find_table_bin_ind(st_table *tab, st_hash_t hash_value, st_data_t key);
773
774static st_index_t
775find_table_bin_ind_direct(st_table *table, st_hash_t hash_value, st_data_t key);
776
777static st_index_t
778find_table_bin_ptr_and_reserve(st_table *tab, st_hash_t *hash_value,
779 st_data_t key, st_index_t *bin_ind);
780
781#ifdef HASH_LOG
782static void
783count_collision(const struct st_hash_type *type)
784{
785 collision.all++;
786 if (type == &type_numhash) {
787 collision.num++;
788 }
789 else if (type == &type_strhash) {
790 collision.strcase++;
791 }
792 else if (type == &type_strcasehash) {
793 collision.str++;
794 }
795}
796
797#define COLLISION (collision_check ? count_collision(tab->type) : (void)0)
798#define FOUND_BIN (collision_check ? collision.total++ : (void)0)
799#define collision_check 0
800#else
801#define COLLISION
802#define FOUND_BIN
803#endif
804
805/* If the number of entries in the table is at least REBUILD_THRESHOLD
806 times less than the entry array length, decrease the table
807 size. */
808#define REBUILD_THRESHOLD 4
809
810#if REBUILD_THRESHOLD < 2
811#error "REBUILD_THRESHOLD should be >= 2"
812#endif
813
814static void rebuild_table_with(st_table *const new_tab, st_table *const tab);
815static void rebuild_move_table(st_table *const new_tab, st_table *const tab);
816static void rebuild_cleanup(st_table *const tab);
817
818/* Rebuild table TAB. Rebuilding removes all deleted bins and entries
819 and can change size of the table entries and bins arrays.
820 Rebuilding is implemented by creation of a new table or by
821 compaction of the existing one. */
822static void
823rebuild_table(st_table *tab)
824{
825 if ((2 * tab->num_entries <= get_allocated_entries(tab)
826 && REBUILD_THRESHOLD * tab->num_entries > get_allocated_entries(tab))
827 || tab->num_entries < (1 << MINIMAL_POWER2)) {
828 /* Compaction: */
829 tab->num_entries = 0;
830 if (st_has_bins(tab))
831 initialize_bins(tab);
832 rebuild_table_with(tab, tab);
833 }
834 else {
835 st_table *new_tab;
836 /* This allocation could trigger GC and compaction. If tab is the
837 * gen_fields_tbl, then tab could have changed in size due to objects being
838 * freed and/or moved. Do not store attributes of tab before this line. */
839 new_tab = st_init_table_with_size(tab->type,
840 2 * tab->num_entries - 1);
841 rebuild_table_with(new_tab, tab);
842 rebuild_move_table(new_tab, tab);
843 }
844 rebuild_cleanup(tab);
845}
846
847static void
848rebuild_table_with(st_table *const new_tab, st_table *const tab)
849{
850 st_index_t i, ni;
851 unsigned int size_ind;
852 st_table_entry *new_entries;
853 st_table_entry *curr_entry_ptr;
854 st_index_t *bins;
855 st_index_t bin_ind;
856
857 new_entries = new_tab->entries;
858
859 ni = 0;
860 bins = st_bins_ptr(new_tab);
861 size_ind = get_size_ind(new_tab);
862 st_index_t bound = tab->entries_bound;
863 st_table_entry *entries = tab->entries;
864
865 for (i = tab->entries_start; i < bound; i++) {
866 curr_entry_ptr = &entries[i];
867 PREFETCH(entries + i + 1, 0);
868 if (EXPECT(DELETED_ENTRY_P(curr_entry_ptr), 0))
869 continue;
870 if (&new_entries[ni] != curr_entry_ptr)
871 new_entries[ni] = *curr_entry_ptr;
872 if (EXPECT(bins != NULL, 1)) {
873 bin_ind = find_table_bin_ind_direct(new_tab, curr_entry_ptr->hash,
874 curr_entry_ptr->key);
875 set_bin(bins, size_ind, bin_ind, ni + ENTRY_BASE);
876 }
877 new_tab->num_entries++;
878 ni++;
879 }
880
881 assert(new_tab->num_entries == tab->num_entries);
882}
883
884static void
885rebuild_move_table(st_table *const new_tab, st_table *const tab)
886{
887 st_free_entries(tab);
888 tab->entry_power = new_tab->entry_power;
889 tab->bin_power = new_tab->bin_power;
890 tab->size_ind = new_tab->size_ind;
891 tab->entries = new_tab->entries;
892 free_fixed_ptr(new_tab);
893}
894
895static void
896rebuild_cleanup(st_table *const tab)
897{
898 tab->entries_start = 0;
899 tab->entries_bound = tab->num_entries;
900 tab->rebuilds_num++;
901}
902
903/* Return the next secondary hash index for table TAB using previous
904 index IND and PERTURB. Finally modulo of the function becomes a
905 full *cycle linear congruential generator*, in other words it
906 guarantees traversing all table bins in extreme case.
907
908 According the Hull-Dobell theorem a generator
909 "Xnext = (a*Xprev + c) mod m" is a full cycle generator if and only if
910 o m and c are relatively prime
911 o a-1 is divisible by all prime factors of m
912 o a-1 is divisible by 4 if m is divisible by 4.
913
914 For our case a is 5, c is 1, and m is a power of two. */
915static inline st_index_t
916secondary_hash(st_index_t ind, st_table *tab, st_index_t *perturb)
917{
918 *perturb >>= 11;
919 ind = (ind << 2) + ind + *perturb + 1;
920 return hash_bin(ind, tab);
921}
922
923/* Find an entry with HASH_VALUE and KEY in TABLE using a linear
924 search. Return the index of the found entry in array `entries`.
925 If it is not found, return UNDEFINED_ENTRY_IND. If the table was
926 rebuilt during the search, return REBUILT_TABLE_ENTRY_IND. */
927static inline st_index_t
928find_entry(st_table *tab, st_hash_t hash_value, st_data_t key)
929{
930 int eq_p, rebuilt_p;
931 st_index_t i, bound;
932 st_table_entry *entries;
933
934 bound = tab->entries_bound;
935 entries = tab->entries;
936 for (i = tab->entries_start; i < bound; i++) {
937 DO_PTR_EQUAL_CHECK(tab, &entries[i], hash_value, key, eq_p, rebuilt_p);
938 if (EXPECT(rebuilt_p, 0))
939 return REBUILT_TABLE_ENTRY_IND;
940 if (eq_p)
941 return i;
942 }
943 return UNDEFINED_ENTRY_IND;
944}
945
946/* Use the quadratic probing. The method has a better data locality
947 but more collisions than the current approach. In average it
948 results in a bit slower search. */
949/*#define QUADRATIC_PROBE*/
950
951/* Return index of entry with HASH_VALUE and KEY in table TAB. If
952 there is no such entry, return UNDEFINED_ENTRY_IND. If the table
953 was rebuilt during the search, return REBUILT_TABLE_ENTRY_IND. */
954static st_index_t
955find_table_entry_ind(st_table *tab, st_hash_t hash_value, st_data_t key)
956{
957 int eq_p, rebuilt_p;
958 st_index_t ind;
959#ifdef QUADRATIC_PROBE
960 st_index_t d;
961#else
962 st_index_t perturb;
963#endif
964 st_index_t bin;
965 st_table_entry *entries = tab->entries;
966
967 ind = hash_bin(hash_value, tab);
968#ifdef QUADRATIC_PROBE
969 d = 1;
970#else
971 perturb = hash_value;
972#endif
973 FOUND_BIN;
974 for (;;) {
975 bin = get_bin(st_bins_ptr(tab), get_size_ind(tab), ind);
976 if (! EMPTY_OR_DELETED_BIN_P(bin)) {
977 DO_PTR_EQUAL_CHECK(tab, &entries[bin - ENTRY_BASE], hash_value, key, eq_p, rebuilt_p);
978 if (EXPECT(rebuilt_p, 0))
979 return REBUILT_TABLE_ENTRY_IND;
980 if (eq_p)
981 break;
982 }
983 else if (EMPTY_BIN_P(bin))
984 return UNDEFINED_ENTRY_IND;
985#ifdef QUADRATIC_PROBE
986 ind = hash_bin(ind + d, tab);
987 d++;
988#else
989 ind = secondary_hash(ind, tab, &perturb);
990#endif
991 COLLISION;
992 }
993 return bin;
994}
995
996/* Find and return index of table TAB bin corresponding to an entry
997 with HASH_VALUE and KEY. If there is no such bin, return
998 UNDEFINED_BIN_IND. If the table was rebuilt during the search,
999 return REBUILT_TABLE_BIN_IND. */
1000static st_index_t
1001find_table_bin_ind(st_table *tab, st_hash_t hash_value, st_data_t key)
1002{
1003 int eq_p, rebuilt_p;
1004 st_index_t ind;
1005#ifdef QUADRATIC_PROBE
1006 st_index_t d;
1007#else
1008 st_index_t perturb;
1009#endif
1010 st_index_t bin;
1011 st_table_entry *entries = tab->entries;
1012
1013 ind = hash_bin(hash_value, tab);
1014#ifdef QUADRATIC_PROBE
1015 d = 1;
1016#else
1017 perturb = hash_value;
1018#endif
1019 FOUND_BIN;
1020 for (;;) {
1021 bin = get_bin(st_bins_ptr(tab), get_size_ind(tab), ind);
1022 if (! EMPTY_OR_DELETED_BIN_P(bin)) {
1023 DO_PTR_EQUAL_CHECK(tab, &entries[bin - ENTRY_BASE], hash_value, key, eq_p, rebuilt_p);
1024 if (EXPECT(rebuilt_p, 0))
1025 return REBUILT_TABLE_BIN_IND;
1026 if (eq_p)
1027 break;
1028 }
1029 else if (EMPTY_BIN_P(bin))
1030 return UNDEFINED_BIN_IND;
1031#ifdef QUADRATIC_PROBE
1032 ind = hash_bin(ind + d, tab);
1033 d++;
1034#else
1035 ind = secondary_hash(ind, tab, &perturb);
1036#endif
1037 COLLISION;
1038 }
1039 return ind;
1040}
1041
1042/* Find and return index of table TAB bin corresponding to an entry
1043 with HASH_VALUE and KEY. The entry should be in the table
1044 already. */
1045static st_index_t
1046find_table_bin_ind_direct(st_table *tab, st_hash_t hash_value, st_data_t key)
1047{
1048 st_index_t ind;
1049#ifdef QUADRATIC_PROBE
1050 st_index_t d;
1051#else
1052 st_index_t perturb;
1053#endif
1054 st_index_t bin;
1055
1056 ind = hash_bin(hash_value, tab);
1057#ifdef QUADRATIC_PROBE
1058 d = 1;
1059#else
1060 perturb = hash_value;
1061#endif
1062 FOUND_BIN;
1063 for (;;) {
1064 bin = get_bin(st_bins_ptr(tab), get_size_ind(tab), ind);
1065 if (EMPTY_OR_DELETED_BIN_P(bin))
1066 return ind;
1067#ifdef QUADRATIC_PROBE
1068 ind = hash_bin(ind + d, tab);
1069 d++;
1070#else
1071 ind = secondary_hash(ind, tab, &perturb);
1072#endif
1073 COLLISION;
1074 }
1075}
1076
1077/* Return index of table TAB bin for HASH_VALUE and KEY through
1078 BIN_IND and the pointed value as the function result. Reserve the
1079 bin for inclusion of the corresponding entry into the table if it
1080 is not there yet. We always find such bin as bins array length is
1081 bigger entries array. Although we can reuse a deleted bin, the
1082 result bin value is always empty if the table has no entry with
1083 KEY. Return the entries array index of the found entry or
1084 UNDEFINED_ENTRY_IND if it is not found. If the table was rebuilt
1085 during the search, return REBUILT_TABLE_ENTRY_IND. */
1086static st_index_t
1087find_table_bin_ptr_and_reserve(st_table *tab, st_hash_t *hash_value,
1088 st_data_t key, st_index_t *bin_ind)
1089{
1090 int eq_p, rebuilt_p;
1091 st_index_t ind;
1092 st_hash_t curr_hash_value = *hash_value;
1093#ifdef QUADRATIC_PROBE
1094 st_index_t d;
1095#else
1096 st_index_t perturb;
1097#endif
1098 st_index_t entry_index;
1099 st_index_t first_deleted_bin_ind;
1100 st_table_entry *entries;
1101
1102 ind = hash_bin(curr_hash_value, tab);
1103#ifdef QUADRATIC_PROBE
1104 d = 1;
1105#else
1106 perturb = curr_hash_value;
1107#endif
1108 FOUND_BIN;
1109 first_deleted_bin_ind = UNDEFINED_BIN_IND;
1110 entries = tab->entries;
1111 for (;;) {
1112 entry_index = get_bin(st_bins_ptr(tab), get_size_ind(tab), ind);
1113 if (EMPTY_BIN_P(entry_index)) {
1114 tab->num_entries++;
1115 entry_index = UNDEFINED_ENTRY_IND;
1116 if (first_deleted_bin_ind != UNDEFINED_BIN_IND) {
1117 /* We can reuse bin of a deleted entry. */
1118 ind = first_deleted_bin_ind;
1119 MARK_BIN_EMPTY(tab, ind);
1120 }
1121 break;
1122 }
1123 else if (! DELETED_BIN_P(entry_index)) {
1124 DO_PTR_EQUAL_CHECK(tab, &entries[entry_index - ENTRY_BASE], curr_hash_value, key, eq_p, rebuilt_p);
1125 if (EXPECT(rebuilt_p, 0))
1126 return REBUILT_TABLE_ENTRY_IND;
1127 if (eq_p)
1128 break;
1129 }
1130 else if (first_deleted_bin_ind == UNDEFINED_BIN_IND)
1131 first_deleted_bin_ind = ind;
1132#ifdef QUADRATIC_PROBE
1133 ind = hash_bin(ind + d, tab);
1134 d++;
1135#else
1136 ind = secondary_hash(ind, tab, &perturb);
1137#endif
1138 COLLISION;
1139 }
1140 *bin_ind = ind;
1141 return entry_index;
1142}
1143
1144/* Find an entry with KEY in table TAB. Return non-zero if we found
1145 it. Set up *RECORD to the found entry record. */
1146int
1147st_lookup(st_table *tab, st_data_t key, st_data_t *value)
1148{
1149 st_index_t bin;
1150 st_hash_t hash = do_hash(key, tab);
1151
1152 retry:
1153 if (!st_has_bins(tab)) {
1154 bin = find_entry(tab, hash, key);
1155 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
1156 goto retry;
1157 if (bin == UNDEFINED_ENTRY_IND)
1158 return 0;
1159 }
1160 else {
1161 bin = find_table_entry_ind(tab, hash, key);
1162 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
1163 goto retry;
1164 if (bin == UNDEFINED_ENTRY_IND)
1165 return 0;
1166 bin -= ENTRY_BASE;
1167 }
1168 if (value != 0)
1169 *value = tab->entries[bin].record;
1170 return 1;
1171}
1172
1173/* Find an entry with KEY in table TAB. Return non-zero if we found
1174 it. Set up *RESULT to the found table entry key. */
1175int
1176st_get_key(st_table *tab, st_data_t key, st_data_t *result)
1177{
1178 st_index_t bin;
1179 st_hash_t hash = do_hash(key, tab);
1180
1181 retry:
1182 if (!st_has_bins(tab)) {
1183 bin = find_entry(tab, hash, key);
1184 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
1185 goto retry;
1186 if (bin == UNDEFINED_ENTRY_IND)
1187 return 0;
1188 }
1189 else {
1190 bin = find_table_entry_ind(tab, hash, key);
1191 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
1192 goto retry;
1193 if (bin == UNDEFINED_ENTRY_IND)
1194 return 0;
1195 bin -= ENTRY_BASE;
1196 }
1197 if (result != 0)
1198 *result = tab->entries[bin].key;
1199 return 1;
1200}
1201
1202/* Check the table and rebuild it if it is necessary. */
1203static inline void
1204rebuild_table_if_necessary(st_table *tab)
1205{
1206 st_index_t bound = tab->entries_bound;
1207
1208 if (bound == get_allocated_entries(tab) || tab->entries_start == MAX_ENTRIES_START) {
1209 rebuild_table(tab);
1210 }
1211}
1212
1213/* Insert (KEY, VALUE) into table TAB and return zero. If there is
1214 already entry with KEY in the table, return nonzero and update
1215 the value of the found entry. */
1216int
1217st_insert(st_table *tab, st_data_t key, st_data_t value)
1218{
1219 st_table_entry *entry;
1220 st_index_t bin;
1221 st_index_t ind;
1222 st_hash_t hash_value;
1223 st_index_t bin_ind;
1224 int new_p;
1225
1226 hash_value = do_hash(key, tab);
1227 retry:
1228 rebuild_table_if_necessary(tab);
1229 if (!st_has_bins(tab)) {
1230 bin = find_entry(tab, hash_value, key);
1231 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
1232 goto retry;
1233 new_p = bin == UNDEFINED_ENTRY_IND;
1234 if (new_p)
1235 tab->num_entries++;
1236 bin_ind = UNDEFINED_BIN_IND;
1237 }
1238 else {
1239 bin = find_table_bin_ptr_and_reserve(tab, &hash_value,
1240 key, &bin_ind);
1241 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
1242 goto retry;
1243 new_p = bin == UNDEFINED_ENTRY_IND;
1244 bin -= ENTRY_BASE;
1245 }
1246 if (new_p) {
1247 ind = tab->entries_bound++;
1248 entry = &tab->entries[ind];
1249 entry->hash = hash_value;
1250 entry->key = key;
1251 entry->record = value;
1252 if (bin_ind != UNDEFINED_BIN_IND)
1253 set_bin(st_bins_ptr(tab), get_size_ind(tab), bin_ind, ind + ENTRY_BASE);
1254 return 0;
1255 }
1256 tab->entries[bin].record = value;
1257 return 1;
1258}
1259
1260#ifdef RUBY
1261/* Insert (KEY, VALUE) into table TAB like st_insert(), but return -1
1262 without any change when st_insert() would rebuild the table. The
1263 insertion is guaranteed to be allocation (and GC) free when it is done. */
1264int
1265st_insert_no_rebuild(st_table *tab, st_data_t key, st_data_t value)
1266{
1267 if (tab->entries_bound == get_allocated_entries(tab)) {
1268 /* st_insert() will rebuild the table */
1269 return -1;
1270 }
1271 return st_insert(tab, key, value);
1272}
1273#endif
1274
1275/* Insert (KEY, VALUE, HASH) into table TAB. The table should not have
1276 entry with KEY before the insertion. */
1277static inline void
1278st_add_direct_with_hash(st_table *tab,
1279 st_data_t key, st_data_t value, st_hash_t hash)
1280{
1281 st_table_entry *entry;
1282 st_index_t ind;
1283 st_index_t bin_ind;
1284
1285 assert(hash != RESERVED_HASH_VAL);
1286
1287 rebuild_table_if_necessary(tab);
1288 ind = tab->entries_bound++;
1289 entry = &tab->entries[ind];
1290 entry->hash = hash;
1291 entry->key = key;
1292 entry->record = value;
1293 tab->num_entries++;
1294 if (st_has_bins(tab)) {
1295 bin_ind = find_table_bin_ind_direct(tab, hash, key);
1296 set_bin(st_bins_ptr(tab), get_size_ind(tab), bin_ind, ind + ENTRY_BASE);
1297 }
1298}
1299
1300void
1301rb_st_add_direct_with_hash(st_table *tab,
1302 st_data_t key, st_data_t value, st_hash_t hash)
1303{
1304 st_add_direct_with_hash(tab, key, value, normalize_hash_value(hash));
1305}
1306
1307/* Insert (KEY, VALUE) into table TAB. The table should not have
1308 entry with KEY before the insertion. */
1309void
1310st_add_direct(st_table *tab, st_data_t key, st_data_t value)
1311{
1312 st_hash_t hash_value;
1313
1314 hash_value = do_hash(key, tab);
1315 st_add_direct_with_hash(tab, key, value, hash_value);
1316}
1317
1318/* Insert (FUNC(KEY), VALUE) into table TAB and return zero. If
1319 there is already entry with KEY in the table, return nonzero and
1320 update the value of the found entry. */
1321int
1322st_insert2(st_table *tab, st_data_t key, st_data_t value,
1323 st_data_t (*func)(st_data_t))
1324{
1325 st_table_entry *entry;
1326 st_index_t bin;
1327 st_index_t ind;
1328 st_hash_t hash_value;
1329 st_index_t bin_ind;
1330 int new_p;
1331
1332 hash_value = do_hash(key, tab);
1333 retry:
1334 rebuild_table_if_necessary(tab);
1335 if (!st_has_bins(tab)) {
1336 bin = find_entry(tab, hash_value, key);
1337 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
1338 goto retry;
1339 new_p = bin == UNDEFINED_ENTRY_IND;
1340 if (new_p)
1341 tab->num_entries++;
1342 bin_ind = UNDEFINED_BIN_IND;
1343 }
1344 else {
1345 bin = find_table_bin_ptr_and_reserve(tab, &hash_value,
1346 key, &bin_ind);
1347 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
1348 goto retry;
1349 new_p = bin == UNDEFINED_ENTRY_IND;
1350 bin -= ENTRY_BASE;
1351 }
1352 if (new_p) {
1353 key = (*func)(key);
1354 ind = tab->entries_bound++;
1355 entry = &tab->entries[ind];
1356 entry->hash = hash_value;
1357 entry->key = key;
1358 entry->record = value;
1359 if (bin_ind != UNDEFINED_BIN_IND)
1360 set_bin(st_bins_ptr(tab), get_size_ind(tab), bin_ind, ind + ENTRY_BASE);
1361 return 0;
1362 }
1363 tab->entries[bin].record = value;
1364 return 1;
1365}
1366
1367static st_table *
1368st_replace_no_check(st_table *new_tab, st_table *old_tab)
1369{
1370 *new_tab = *old_tab;
1371 size_t memsize = get_allocated_entries(old_tab) * sizeof(st_table_entry);
1372 memsize += bins_size(old_tab);
1373 new_tab->entries = (st_table_entry *) malloc(memsize);
1374#ifndef RUBY
1375 if (new_tab->entries == NULL) {
1376 return NULL;
1377 }
1378#endif
1379 MEMCPY(new_tab->entries, old_tab->entries, char, memsize);
1380
1381 return new_tab;
1382}
1383
1384
1385/* Create a copy of old_tab into new_tab. */
1386st_table *
1387st_replace(st_table *new_tab, st_table *old_tab)
1388{
1389 RUBY_ASSERT(new_tab->entries == NULL);
1390 return st_replace_no_check(new_tab, old_tab);
1391}
1392
1393/* Create and return a copy of table OLD_TAB. */
1394st_table *
1395st_copy(st_table *old_tab)
1396{
1397 st_table *new_tab;
1398
1399 new_tab = (st_table *) malloc(sizeof(st_table));
1400#ifndef RUBY
1401 if (new_tab == NULL)
1402 return NULL;
1403#endif
1404
1405 if (st_replace_no_check(new_tab, old_tab) == NULL) {
1406 st_free_table(new_tab);
1407 return NULL;
1408 }
1409
1410 return new_tab;
1411}
1412
1413/* Update the entries start of table TAB after removing an entry
1414 with index N in the array entries. */
1415static inline void
1416update_range_for_deleted(st_table *tab, st_index_t n)
1417{
1418 /* Do not update entries_bound here. Otherwise, we can fill all
1419 bins by deleted entry value before rebuilding the table. */
1420 if (tab->entries_start == n) {
1421 st_index_t start = n + 1;
1422 st_index_t bound = tab->entries_bound;
1423 st_table_entry *entries = tab->entries;
1424 while (start < bound && DELETED_ENTRY_P(&entries[start])) start++;
1425 tab->entries_start = start > MAX_ENTRIES_START ? MAX_ENTRIES_START : (unsigned int)start;
1426 }
1427}
1428
1429/* Delete entry with KEY from table TAB, set up *VALUE (unless
1430 VALUE is zero) from deleted table entry, and return non-zero. If
1431 there is no entry with KEY in the table, clear *VALUE (unless VALUE
1432 is zero), and return zero. */
1433static int
1434st_general_delete(st_table *tab, st_data_t *key, st_data_t *value)
1435{
1436 st_table_entry *entry;
1437 st_index_t bin;
1438 st_index_t bin_ind;
1439 st_hash_t hash;
1440
1441 hash = do_hash(*key, tab);
1442 retry:
1443 if (!st_has_bins(tab)) {
1444 bin = find_entry(tab, hash, *key);
1445 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
1446 goto retry;
1447 if (bin == UNDEFINED_ENTRY_IND) {
1448 if (value != 0) *value = 0;
1449 return 0;
1450 }
1451 }
1452 else {
1453 bin_ind = find_table_bin_ind(tab, hash, *key);
1454 if (EXPECT(bin_ind == REBUILT_TABLE_BIN_IND, 0))
1455 goto retry;
1456 if (bin_ind == UNDEFINED_BIN_IND) {
1457 if (value != 0) *value = 0;
1458 return 0;
1459 }
1460 bin = get_bin(st_bins_ptr(tab), get_size_ind(tab), bin_ind) - ENTRY_BASE;
1461 MARK_BIN_DELETED(tab, bin_ind);
1462 }
1463 entry = &tab->entries[bin];
1464 *key = entry->key;
1465 if (value != 0) *value = entry->record;
1466 MARK_ENTRY_DELETED(entry);
1467 tab->num_entries--;
1468 update_range_for_deleted(tab, bin);
1469 return 1;
1470}
1471
1472int
1473st_delete(st_table *tab, st_data_t *key, st_data_t *value)
1474{
1475 return st_general_delete(tab, key, value);
1476}
1477
1478/* The function and other functions with suffix '_safe' or '_check'
1479 are originated from the previous implementation of the hash tables.
1480 It was necessary for correct deleting entries during traversing
1481 tables. The current implementation permits deletion during
1482 traversing without a specific way to do this. */
1483int
1484st_delete_safe(st_table *tab, st_data_t *key, st_data_t *value,
1485 st_data_t never ATTRIBUTE_UNUSED)
1486{
1487 return st_general_delete(tab, key, value);
1488}
1489
1490/* If table TAB is empty, clear *VALUE (unless VALUE is zero), and
1491 return zero. Otherwise, remove the first entry in the table.
1492 Return its key through KEY and its record through VALUE (unless
1493 VALUE is zero). */
1494int
1495st_shift(st_table *tab, st_data_t *key, st_data_t *value)
1496{
1497 st_index_t i, bound;
1498 st_index_t bin;
1499 st_table_entry *entries, *curr_entry_ptr;
1500 st_index_t bin_ind;
1501
1502 entries = tab->entries;
1503 bound = tab->entries_bound;
1504 for (i = tab->entries_start; i < bound; i++) {
1505 curr_entry_ptr = &entries[i];
1506 if (! DELETED_ENTRY_P(curr_entry_ptr)) {
1507 st_hash_t entry_hash = curr_entry_ptr->hash;
1508 st_data_t entry_key = curr_entry_ptr->key;
1509
1510 if (value != 0) *value = curr_entry_ptr->record;
1511 *key = entry_key;
1512 retry:
1513 if (!st_has_bins(tab)) {
1514 bin = find_entry(tab, entry_hash, entry_key);
1515 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0)) {
1516 entries = tab->entries;
1517 goto retry;
1518 }
1519 curr_entry_ptr = &entries[bin];
1520 }
1521 else {
1522 bin_ind = find_table_bin_ind(tab, entry_hash, entry_key);
1523 if (EXPECT(bin_ind == REBUILT_TABLE_BIN_IND, 0)) {
1524 entries = tab->entries;
1525 goto retry;
1526 }
1527 curr_entry_ptr = &entries[get_bin(st_bins_ptr(tab), get_size_ind(tab), bin_ind)
1528 - ENTRY_BASE];
1529 MARK_BIN_DELETED(tab, bin_ind);
1530 }
1531 MARK_ENTRY_DELETED(curr_entry_ptr);
1532 tab->num_entries--;
1533 update_range_for_deleted(tab, i);
1534 return 1;
1535 }
1536 }
1537 if (value != 0) *value = 0;
1538 return 0;
1539}
1540
1541/* See comments for function st_delete_safe. */
1542void
1543st_cleanup_safe(st_table *tab ATTRIBUTE_UNUSED,
1544 st_data_t never ATTRIBUTE_UNUSED)
1545{
1546}
1547
1548/* Find entry with KEY in table TAB, call FUNC with pointers to copies
1549 of the key and the value of the found entry, and non-zero as the
1550 3rd argument. If the entry is not found, call FUNC with a pointer
1551 to KEY, a pointer to zero, and a zero argument. If the call
1552 returns ST_CONTINUE, the table will have an entry with key and
1553 value returned by FUNC through the 1st and 2nd parameters. If the
1554 call of FUNC returns ST_DELETE, the table will not have entry with
1555 KEY. The function returns flag of that the entry with KEY was in
1556 the table before the call. */
1557int
1558st_update(st_table *tab, st_data_t key,
1559 st_update_callback_func *func, st_data_t arg)
1560{
1561 st_table_entry *entry = NULL; /* to avoid uninitialized value warning */
1562 st_index_t bin = 0; /* Ditto */
1563 st_table_entry *entries;
1564 st_index_t bin_ind;
1565 st_data_t value = 0, old_key;
1566 int retval, existing;
1567 st_hash_t hash = do_hash(key, tab);
1568
1569 retry:
1570 entries = tab->entries;
1571 if (!st_has_bins(tab)) {
1572 bin = find_entry(tab, hash, key);
1573 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
1574 goto retry;
1575 existing = bin != UNDEFINED_ENTRY_IND;
1576 entry = &entries[bin];
1577 bin_ind = UNDEFINED_BIN_IND;
1578 }
1579 else {
1580 bin_ind = find_table_bin_ind(tab, hash, key);
1581 if (EXPECT(bin_ind == REBUILT_TABLE_BIN_IND, 0))
1582 goto retry;
1583 existing = bin_ind != UNDEFINED_BIN_IND;
1584 if (existing) {
1585 bin = get_bin(st_bins_ptr(tab), get_size_ind(tab), bin_ind) - ENTRY_BASE;
1586 entry = &entries[bin];
1587 }
1588 }
1589 if (existing) {
1590 key = entry->key;
1591 value = entry->record;
1592 }
1593 old_key = key;
1594
1595 unsigned int rebuilds_num = tab->rebuilds_num;
1596
1597 retval = (*func)(&key, &value, arg, existing);
1598
1599 // We need to make sure that the callback didn't cause a table rebuild
1600 // Ideally we would make sure no operations happened
1601 assert(rebuilds_num == tab->rebuilds_num);
1602 (void)rebuilds_num;
1603
1604 switch (retval) {
1605 case ST_CONTINUE:
1606 if (! existing) {
1607 st_add_direct_with_hash(tab, key, value, hash);
1608 break;
1609 }
1610 if (old_key != key) {
1611 entry->key = key;
1612 }
1613 entry->record = value;
1614 break;
1615 case ST_DELETE:
1616 if (existing) {
1617 if (bin_ind != UNDEFINED_BIN_IND)
1618 MARK_BIN_DELETED(tab, bin_ind);
1619 MARK_ENTRY_DELETED(entry);
1620 tab->num_entries--;
1621 update_range_for_deleted(tab, bin);
1622 }
1623 break;
1624 }
1625 return existing;
1626}
1627
1628/* Traverse all entries in table TAB calling FUNC with current entry
1629 key and value and zero. If the call returns ST_STOP, stop
1630 traversing. If the call returns ST_DELETE, delete the current
1631 entry from the table. In case of ST_CHECK or ST_CONTINUE, continue
1632 traversing. The function returns zero unless an error is found.
1633 CHECK_P is flag of st_foreach_check call. The behavior is a bit
1634 different for ST_CHECK and when the current element is removed
1635 during traversing. */
1636static inline int
1637st_general_foreach(st_table *tab, st_foreach_check_callback_func *func, st_update_callback_func *replace, st_data_t arg,
1638 int check_p)
1639{
1640 st_index_t bin;
1641 st_index_t bin_ind;
1642 st_table_entry *entries, *curr_entry_ptr;
1643 enum st_retval retval;
1644 st_index_t i, rebuilds_num;
1645 st_hash_t hash;
1646 st_data_t key;
1647 int error_p, packed_p = !st_has_bins(tab);
1648
1649 entries = tab->entries;
1650 /* The bound can change inside the loop even without rebuilding
1651 the table, e.g. by an entry insertion. */
1652 for (i = tab->entries_start; i < tab->entries_bound; i++) {
1653 curr_entry_ptr = &entries[i];
1654 if (EXPECT(DELETED_ENTRY_P(curr_entry_ptr), 0))
1655 continue;
1656 key = curr_entry_ptr->key;
1657 rebuilds_num = tab->rebuilds_num;
1658 hash = curr_entry_ptr->hash;
1659 retval = (*func)(key, curr_entry_ptr->record, arg, 0);
1660
1661 if (retval == ST_REPLACE && replace) {
1662 st_data_t value;
1663 value = curr_entry_ptr->record;
1664 retval = (*replace)(&key, &value, arg, TRUE);
1665 curr_entry_ptr->key = key;
1666 curr_entry_ptr->record = value;
1667 }
1668
1669 if (rebuilds_num != tab->rebuilds_num) {
1670 retry:
1671 entries = tab->entries;
1672 packed_p = !st_has_bins(tab);
1673 if (packed_p) {
1674 i = find_entry(tab, hash, key);
1675 if (EXPECT(i == REBUILT_TABLE_ENTRY_IND, 0))
1676 goto retry;
1677 error_p = i == UNDEFINED_ENTRY_IND;
1678 }
1679 else {
1680 i = find_table_entry_ind(tab, hash, key);
1681 if (EXPECT(i == REBUILT_TABLE_ENTRY_IND, 0))
1682 goto retry;
1683 error_p = i == UNDEFINED_ENTRY_IND;
1684 i -= ENTRY_BASE;
1685 }
1686 if (error_p && check_p) {
1687 /* call func with error notice */
1688 retval = (*func)(0, 0, arg, 1);
1689 return 1;
1690 }
1691 curr_entry_ptr = &entries[i];
1692 }
1693 switch (retval) {
1694 case ST_REPLACE:
1695 break;
1696 case ST_CONTINUE:
1697 break;
1698 case ST_CHECK:
1699 if (check_p)
1700 break;
1701 case ST_STOP:
1702 return 0;
1703 case ST_DELETE: {
1704 st_data_t key = curr_entry_ptr->key;
1705
1706 again:
1707 if (packed_p) {
1708 bin = find_entry(tab, hash, key);
1709 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
1710 goto again;
1711 if (bin == UNDEFINED_ENTRY_IND)
1712 break;
1713 }
1714 else {
1715 bin_ind = find_table_bin_ind(tab, hash, key);
1716 if (EXPECT(bin_ind == REBUILT_TABLE_BIN_IND, 0))
1717 goto again;
1718 if (bin_ind == UNDEFINED_BIN_IND)
1719 break;
1720 bin = get_bin(st_bins_ptr(tab), get_size_ind(tab), bin_ind) - ENTRY_BASE;
1721 MARK_BIN_DELETED(tab, bin_ind);
1722 }
1723 curr_entry_ptr = &entries[bin];
1724 MARK_ENTRY_DELETED(curr_entry_ptr);
1725 tab->num_entries--;
1726 update_range_for_deleted(tab, bin);
1727 break;
1728 }
1729 }
1730 }
1731 return 0;
1732}
1733
1734#ifdef INTERNAL_ST_H
1735int
1736st_foreach_with_hash(st_table *tab, st_foreach_with_hash_callback_func *func, st_data_t arg)
1737{
1738 st_table_entry *entries, *curr_entry_ptr;
1739 enum st_retval retval;
1740 st_index_t i, rebuilds_num;
1741 st_hash_t hash;
1742 st_data_t key;
1743 int packed_p = !st_has_bins(tab);
1744
1745 entries = tab->entries;
1746 /* The bound can change inside the loop even without rebuilding
1747 the table, e.g. by an entry insertion. */
1748 for (i = tab->entries_start; i < tab->entries_bound; i++) {
1749 curr_entry_ptr = &entries[i];
1750 if (EXPECT(DELETED_ENTRY_P(curr_entry_ptr), 0))
1751 continue;
1752 key = curr_entry_ptr->key;
1753 rebuilds_num = tab->rebuilds_num;
1754 hash = curr_entry_ptr->hash;
1755 retval = (*func)(key, curr_entry_ptr->record, hash, arg);
1756
1757 if (rebuilds_num != tab->rebuilds_num) {
1758 retry:
1759 entries = tab->entries;
1760 packed_p = !st_has_bins(tab);
1761 if (packed_p) {
1762 i = find_entry(tab, hash, key);
1763 if (EXPECT(i == REBUILT_TABLE_ENTRY_IND, 0))
1764 goto retry;
1765 }
1766 else {
1767 i = find_table_entry_ind(tab, hash, key);
1768 if (EXPECT(i == REBUILT_TABLE_ENTRY_IND, 0))
1769 goto retry;
1770 i -= ENTRY_BASE;
1771 }
1772 curr_entry_ptr = &entries[i];
1773 }
1774 switch (retval) {
1775 case ST_STOP:
1776 return 0;
1777 default:
1778 break;
1779 }
1780 }
1781 return 0;
1782}
1783#endif
1784
1785int
1786st_foreach_with_replace(st_table *tab, st_foreach_check_callback_func *func, st_update_callback_func *replace, st_data_t arg)
1787{
1788 return st_general_foreach(tab, func, replace, arg, TRUE);
1789}
1790
1791struct functor {
1792 st_foreach_callback_func *func;
1793 st_data_t arg;
1794};
1795
1796static int
1797apply_functor(st_data_t k, st_data_t v, st_data_t d, int _)
1798{
1799 const struct functor *f = (void *)d;
1800 return f->func(k, v, f->arg);
1801}
1802
1803int
1804st_foreach(st_table *tab, st_foreach_callback_func *func, st_data_t arg)
1805{
1806 const struct functor f = { func, arg };
1807 return st_general_foreach(tab, apply_functor, 0, (st_data_t)&f, FALSE);
1808}
1809
1810/* See comments for function st_delete_safe. */
1811int
1812st_foreach_check(st_table *tab, st_foreach_check_callback_func *func, st_data_t arg,
1813 st_data_t never ATTRIBUTE_UNUSED)
1814{
1815 return st_general_foreach(tab, func, 0, arg, TRUE);
1816}
1817
1818/* Set up array KEYS by at most SIZE keys of head table TAB entries.
1819 Return the number of keys set up in array KEYS. */
1820static inline st_index_t
1821st_general_keys(st_table *tab, st_data_t *keys, st_index_t size)
1822{
1823 st_index_t i, bound;
1824 st_data_t key, *keys_start, *keys_end;
1825 st_table_entry *curr_entry_ptr, *entries = tab->entries;
1826
1827 bound = tab->entries_bound;
1828 keys_start = keys;
1829 keys_end = keys + size;
1830 for (i = tab->entries_start; i < bound; i++) {
1831 if (keys == keys_end)
1832 break;
1833 curr_entry_ptr = &entries[i];
1834 key = curr_entry_ptr->key;
1835 if (! DELETED_ENTRY_P(curr_entry_ptr))
1836 *keys++ = key;
1837 }
1838
1839 return keys - keys_start;
1840}
1841
1842st_index_t
1843st_keys(st_table *tab, st_data_t *keys, st_index_t size)
1844{
1845 return st_general_keys(tab, keys, size);
1846}
1847
1848/* See comments for function st_delete_safe. */
1849st_index_t
1850st_keys_check(st_table *tab, st_data_t *keys, st_index_t size,
1851 st_data_t never ATTRIBUTE_UNUSED)
1852{
1853 return st_general_keys(tab, keys, size);
1854}
1855
1856/* Set up array VALUES by at most SIZE values of head table TAB
1857 entries. Return the number of values set up in array VALUES. */
1858static inline st_index_t
1859st_general_values(st_table *tab, st_data_t *values, st_index_t size)
1860{
1861 st_index_t i, bound;
1862 st_data_t *values_start, *values_end;
1863 st_table_entry *curr_entry_ptr, *entries = tab->entries;
1864
1865 values_start = values;
1866 values_end = values + size;
1867 bound = tab->entries_bound;
1868 for (i = tab->entries_start; i < bound; i++) {
1869 if (values == values_end)
1870 break;
1871 curr_entry_ptr = &entries[i];
1872 if (! DELETED_ENTRY_P(curr_entry_ptr))
1873 *values++ = curr_entry_ptr->record;
1874 }
1875
1876 return values - values_start;
1877}
1878
1879st_index_t
1880st_values(st_table *tab, st_data_t *values, st_index_t size)
1881{
1882 return st_general_values(tab, values, size);
1883}
1884
1885/* See comments for function st_delete_safe. */
1886st_index_t
1887st_values_check(st_table *tab, st_data_t *values, st_index_t size,
1888 st_data_t never ATTRIBUTE_UNUSED)
1889{
1890 return st_general_values(tab, values, size);
1891}
1892
1893#define FNV1_32A_INIT 0x811c9dc5
1894
1895/*
1896 * 32 bit magic FNV-1a prime
1897 */
1898#define FNV_32_PRIME 0x01000193
1899
1900/* __POWERPC__ added to accommodate Darwin case. */
1901#ifndef UNALIGNED_WORD_ACCESS
1902# if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
1903 defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || \
1904 defined(__powerpc64__) || defined(__POWERPC__) || defined(__aarch64__) || \
1905 defined(__mc68020__)
1906# define UNALIGNED_WORD_ACCESS 1
1907# endif
1908#endif
1909#ifndef UNALIGNED_WORD_ACCESS
1910# define UNALIGNED_WORD_ACCESS 0
1911#endif
1912
1913/* This hash function is quite simplified MurmurHash3
1914 * Simplification is legal, cause most of magic still happens in finalizator.
1915 * And finalizator is almost the same as in MurmurHash3 */
1916#define BIG_CONSTANT(x,y) ((st_index_t)(x)<<32|(st_index_t)(y))
1917#define ROTL(x,n) ((x)<<(n)|(x)>>(SIZEOF_ST_INDEX_T*CHAR_BIT-(n)))
1918
1919#if ST_INDEX_BITS <= 32
1920#define C1 (st_index_t)0xcc9e2d51
1921#define C2 (st_index_t)0x1b873593
1922#else
1923#define C1 BIG_CONSTANT(0x87c37b91,0x114253d5);
1924#define C2 BIG_CONSTANT(0x4cf5ad43,0x2745937f);
1925#endif
1926NO_SANITIZE("unsigned-integer-overflow", static inline st_index_t murmur_step(st_index_t h, st_index_t k));
1927NO_SANITIZE("unsigned-integer-overflow", static inline st_index_t murmur_finish(st_index_t h));
1928NO_SANITIZE("unsigned-integer-overflow", extern st_index_t st_hash(const void *ptr, size_t len, st_index_t h));
1929
1930static inline st_index_t
1931murmur_step(st_index_t h, st_index_t k)
1932{
1933#if ST_INDEX_BITS <= 32
1934#define r1 (17)
1935#define r2 (11)
1936#else
1937#define r1 (33)
1938#define r2 (24)
1939#endif
1940 k *= C1;
1941 h ^= ROTL(k, r1);
1942 h *= C2;
1943 h = ROTL(h, r2);
1944 return h;
1945}
1946#undef r1
1947#undef r2
1948
1949static inline st_index_t
1950murmur_finish(st_index_t h)
1951{
1952#if ST_INDEX_BITS <= 32
1953#define r1 (16)
1954#define r2 (13)
1955#define r3 (16)
1956 const st_index_t c1 = 0x85ebca6b;
1957 const st_index_t c2 = 0xc2b2ae35;
1958#else
1959/* values are taken from Mix13 on http://zimbry.blogspot.ru/2011/09/better-bit-mixing-improving-on.html */
1960#define r1 (30)
1961#define r2 (27)
1962#define r3 (31)
1963 const st_index_t c1 = BIG_CONSTANT(0xbf58476d,0x1ce4e5b9);
1964 const st_index_t c2 = BIG_CONSTANT(0x94d049bb,0x133111eb);
1965#endif
1966#if ST_INDEX_BITS > 64
1967 h ^= h >> 64;
1968 h *= c2;
1969 h ^= h >> 65;
1970#endif
1971 h ^= h >> r1;
1972 h *= c1;
1973 h ^= h >> r2;
1974 h *= c2;
1975 h ^= h >> r3;
1976 return h;
1977}
1978#undef r1
1979#undef r2
1980#undef r3
1981
1982st_index_t
1983st_hash(const void *ptr, size_t len, st_index_t h)
1984{
1985 const char *data = ptr;
1986 st_index_t t = 0;
1987 size_t l = len;
1988
1989#define data_at(n) (st_index_t)((unsigned char)data[(n)])
1990#define UNALIGNED_ADD_4 UNALIGNED_ADD(2); UNALIGNED_ADD(1); UNALIGNED_ADD(0)
1991#if SIZEOF_ST_INDEX_T > 4
1992#define UNALIGNED_ADD_8 UNALIGNED_ADD(6); UNALIGNED_ADD(5); UNALIGNED_ADD(4); UNALIGNED_ADD(3); UNALIGNED_ADD_4
1993#if SIZEOF_ST_INDEX_T > 8
1994#define UNALIGNED_ADD_16 UNALIGNED_ADD(14); UNALIGNED_ADD(13); UNALIGNED_ADD(12); UNALIGNED_ADD(11); \
1995 UNALIGNED_ADD(10); UNALIGNED_ADD(9); UNALIGNED_ADD(8); UNALIGNED_ADD(7); UNALIGNED_ADD_8
1996#define UNALIGNED_ADD_ALL UNALIGNED_ADD_16
1997#endif
1998#define UNALIGNED_ADD_ALL UNALIGNED_ADD_8
1999#else
2000#define UNALIGNED_ADD_ALL UNALIGNED_ADD_4
2001#endif
2002#undef SKIP_TAIL
2003 if (len >= sizeof(st_index_t)) {
2004#if !UNALIGNED_WORD_ACCESS
2005 int align = (int)((st_data_t)data % sizeof(st_index_t));
2006 if (align) {
2007 st_index_t d = 0;
2008 int sl, sr, pack;
2009
2010 switch (align) {
2011#ifdef WORDS_BIGENDIAN
2012# define UNALIGNED_ADD(n) case SIZEOF_ST_INDEX_T - (n) - 1: \
2013 t |= data_at(n) << CHAR_BIT*(SIZEOF_ST_INDEX_T - (n) - 2)
2014#else
2015# define UNALIGNED_ADD(n) case SIZEOF_ST_INDEX_T - (n) - 1: \
2016 t |= data_at(n) << CHAR_BIT*(n)
2017#endif
2018 UNALIGNED_ADD_ALL;
2019#undef UNALIGNED_ADD
2020 }
2021
2022#ifdef WORDS_BIGENDIAN
2023 t >>= (CHAR_BIT * align) - CHAR_BIT;
2024#else
2025 t <<= (CHAR_BIT * align);
2026#endif
2027
2028 data += sizeof(st_index_t)-align;
2029 len -= sizeof(st_index_t)-align;
2030
2031 sl = CHAR_BIT * (SIZEOF_ST_INDEX_T-align);
2032 sr = CHAR_BIT * align;
2033
2034 while (len >= sizeof(st_index_t)) {
2035 d = *(st_index_t *)data;
2036#ifdef WORDS_BIGENDIAN
2037 t = (t << sr) | (d >> sl);
2038#else
2039 t = (t >> sr) | (d << sl);
2040#endif
2041 h = murmur_step(h, t);
2042 t = d;
2043 data += sizeof(st_index_t);
2044 len -= sizeof(st_index_t);
2045 }
2046
2047 pack = len < (size_t)align ? (int)len : align;
2048 d = 0;
2049 switch (pack) {
2050#ifdef WORDS_BIGENDIAN
2051# define UNALIGNED_ADD(n) case (n) + 1: \
2052 d |= data_at(n) << CHAR_BIT*(SIZEOF_ST_INDEX_T - (n) - 1)
2053#else
2054# define UNALIGNED_ADD(n) case (n) + 1: \
2055 d |= data_at(n) << CHAR_BIT*(n)
2056#endif
2057 UNALIGNED_ADD_ALL;
2058#undef UNALIGNED_ADD
2059 }
2060#ifdef WORDS_BIGENDIAN
2061 t = (t << sr) | (d >> sl);
2062#else
2063 t = (t >> sr) | (d << sl);
2064#endif
2065
2066 if (len < (size_t)align) goto skip_tail;
2067# define SKIP_TAIL 1
2068 h = murmur_step(h, t);
2069 data += pack;
2070 len -= pack;
2071 }
2072 else
2073#endif
2074#ifdef HAVE_BUILTIN___BUILTIN_ASSUME_ALIGNED
2075#define aligned_data __builtin_assume_aligned(data, sizeof(st_index_t))
2076#else
2077#define aligned_data data
2078#endif
2079 {
2080 do {
2081 h = murmur_step(h, *(st_index_t *)aligned_data);
2082 data += sizeof(st_index_t);
2083 len -= sizeof(st_index_t);
2084 } while (len >= sizeof(st_index_t));
2085 }
2086 }
2087
2088 t = 0;
2089 switch (len) {
2090#if UNALIGNED_WORD_ACCESS && SIZEOF_ST_INDEX_T <= 8 && CHAR_BIT == 8
2091 /* in this case byteorder doesn't really matter */
2092#if SIZEOF_ST_INDEX_T > 4
2093 case 7: t |= data_at(6) << 48;
2094 case 6: t |= data_at(5) << 40;
2095 case 5: t |= data_at(4) << 32;
2096 case 4:
2097 t |= (st_index_t)*(uint32_t*)aligned_data;
2098 goto skip_tail;
2099# define SKIP_TAIL 1
2100#endif
2101 case 3: t |= data_at(2) << 16;
2102 case 2: t |= data_at(1) << 8;
2103 case 1: t |= data_at(0);
2104#else
2105#ifdef WORDS_BIGENDIAN
2106# define UNALIGNED_ADD(n) case (n) + 1: \
2107 t |= data_at(n) << CHAR_BIT*(SIZEOF_ST_INDEX_T - (n) - 1)
2108#else
2109# define UNALIGNED_ADD(n) case (n) + 1: \
2110 t |= data_at(n) << CHAR_BIT*(n)
2111#endif
2112 UNALIGNED_ADD_ALL;
2113#undef UNALIGNED_ADD
2114#endif
2115#ifdef SKIP_TAIL
2116 skip_tail:
2117#endif
2118 h ^= t; h -= ROTL(t, 7);
2119 h *= C2;
2120 }
2121 h ^= l;
2122#undef aligned_data
2123
2124 return murmur_finish(h);
2125}
2126
2127st_index_t
2128st_hash_uint32(st_index_t h, uint32_t i)
2129{
2130 return murmur_step(h, i);
2131}
2132
2133NO_SANITIZE("unsigned-integer-overflow", extern st_index_t st_hash_uint(st_index_t h, st_index_t i));
2134st_index_t
2135st_hash_uint(st_index_t h, st_index_t i)
2136{
2137 i += h;
2138/* no matter if it is BigEndian or LittleEndian,
2139 * we hash just integers */
2140#if SIZEOF_ST_INDEX_T*CHAR_BIT > 8*8
2141 h = murmur_step(h, i >> 8*8);
2142#endif
2143 h = murmur_step(h, i);
2144 return h;
2145}
2146
2147st_index_t
2148st_hash_end(st_index_t h)
2149{
2150 h = murmur_finish(h);
2151 return h;
2152}
2153
2154#undef st_hash_start
2155st_index_t
2156rb_st_hash_start(st_index_t h)
2157{
2158 return h;
2159}
2160
2161static st_index_t
2162strhash(st_data_t arg)
2163{
2164 register const char *string = (const char *)arg;
2165 return st_hash(string, strlen(string), FNV1_32A_INIT);
2166}
2167
2168int
2169st_locale_insensitive_strcasecmp(const char *s1, const char *s2)
2170{
2171 char c1, c2;
2172
2173 while (1) {
2174 c1 = *s1++;
2175 c2 = *s2++;
2176 if (c1 == '\0' || c2 == '\0') {
2177 if (c1 != '\0') return 1;
2178 if (c2 != '\0') return -1;
2179 return 0;
2180 }
2181 if (('A' <= c1) && (c1 <= 'Z')) c1 += 'a' - 'A';
2182 if (('A' <= c2) && (c2 <= 'Z')) c2 += 'a' - 'A';
2183 if (c1 != c2) {
2184 if (c1 > c2)
2185 return 1;
2186 else
2187 return -1;
2188 }
2189 }
2190}
2191
2192int
2193st_locale_insensitive_strncasecmp(const char *s1, const char *s2, size_t n)
2194{
2195 char c1, c2;
2196 size_t i;
2197
2198 for (i = 0; i < n; i++) {
2199 c1 = *s1++;
2200 c2 = *s2++;
2201 if (c1 == '\0' || c2 == '\0') {
2202 if (c1 != '\0') return 1;
2203 if (c2 != '\0') return -1;
2204 return 0;
2205 }
2206 if (('A' <= c1) && (c1 <= 'Z')) c1 += 'a' - 'A';
2207 if (('A' <= c2) && (c2 <= 'Z')) c2 += 'a' - 'A';
2208 if (c1 != c2) {
2209 if (c1 > c2)
2210 return 1;
2211 else
2212 return -1;
2213 }
2214 }
2215 return 0;
2216}
2217
2218static int
2219st_strcmp(st_data_t lhs, st_data_t rhs)
2220{
2221 const char *s1 = (char *)lhs;
2222 const char *s2 = (char *)rhs;
2223 return strcmp(s1, s2);
2224}
2225
2226static int
2227st_locale_insensitive_strcasecmp_i(st_data_t lhs, st_data_t rhs)
2228{
2229 const char *s1 = (char *)lhs;
2230 const char *s2 = (char *)rhs;
2231 return st_locale_insensitive_strcasecmp(s1, s2);
2232}
2233
2234NO_SANITIZE("unsigned-integer-overflow", PUREFUNC(static st_index_t strcasehash(st_data_t)));
2235static st_index_t
2236strcasehash(st_data_t arg)
2237{
2238 register const char *string = (const char *)arg;
2239 register st_index_t hval = FNV1_32A_INIT;
2240
2241 /*
2242 * FNV-1a hash each octet in the buffer
2243 */
2244 while (*string) {
2245 unsigned int c = (unsigned char)*string++;
2246 if ((unsigned int)(c - 'A') <= ('Z' - 'A')) c += 'a' - 'A';
2247 hval ^= c;
2248
2249 /* multiply by the 32 bit FNV magic prime mod 2^32 */
2250 hval *= FNV_32_PRIME;
2251 }
2252 return hval;
2253}
2254
2255int
2256st_numcmp(st_data_t x, st_data_t y)
2257{
2258 return x != y;
2259}
2260
2261st_index_t
2262st_numhash(st_data_t n)
2263{
2264 enum {s1 = 11, s2 = 3};
2265 return (st_index_t)((n>>s1|(n<<s2)) ^ (n>>s2));
2266}
2267
2268#ifdef RUBY
2269/* Expand TAB to be suitable for holding SIZ entries in total.
2270 Pre-existing entries remain not deleted inside of TAB, but its bins
2271 are cleared to expect future reconstruction. See rehash below. */
2272static void
2273st_expand_table(st_table *tab, st_index_t siz)
2274{
2275 st_table *tmp;
2276 st_index_t n;
2277
2278 if (siz <= get_allocated_entries(tab))
2279 return; /* enough room already */
2280
2281 tmp = st_init_table_with_size(tab->type, siz);
2282 n = get_allocated_entries(tab);
2283 MEMCPY(tmp->entries, tab->entries, st_table_entry, n);
2284 st_free_entries(tab);
2285
2286 tab->entry_power = tmp->entry_power;
2287 tab->bin_power = tmp->bin_power;
2288 tab->size_ind = tmp->size_ind;
2289 tab->entries = tmp->entries;
2290 tab->rebuilds_num++;
2291 free_fixed_ptr(tmp);
2292}
2293
2294/* Rehash using linear search. Return TRUE if we found that the table
2295 was rebuilt. */
2296static int
2297st_rehash_linear(st_table *tab)
2298{
2299 int eq_p, rebuilt_p;
2300 st_index_t i, j;
2301 st_table_entry *p, *q;
2302
2303 for (i = tab->entries_start; i < tab->entries_bound; i++) {
2304 p = &tab->entries[i];
2305 if (DELETED_ENTRY_P(p))
2306 continue;
2307 for (j = i + 1; j < tab->entries_bound; j++) {
2308 q = &tab->entries[j];
2309 if (DELETED_ENTRY_P(q))
2310 continue;
2311 DO_PTR_EQUAL_CHECK(tab, p, q->hash, q->key, eq_p, rebuilt_p);
2312 if (EXPECT(rebuilt_p, 0))
2313 return TRUE;
2314 if (eq_p) {
2315 *p = *q;
2316 MARK_ENTRY_DELETED(q);
2317 tab->num_entries--;
2318 update_range_for_deleted(tab, j);
2319 }
2320 }
2321 }
2322 return FALSE;
2323}
2324
2325/* Rehash using index. Return TRUE if we found that the table was
2326 rebuilt. */
2327static int
2328st_rehash_indexed(st_table *tab)
2329{
2330 int eq_p, rebuilt_p;
2331 st_index_t i;
2332
2333 unsigned int const size_ind = get_size_ind(tab);
2334 initialize_bins(tab);
2335 for (i = tab->entries_start; i < tab->entries_bound; i++) {
2336 st_table_entry *p = &tab->entries[i];
2337 st_index_t ind;
2338#ifdef QUADRATIC_PROBE
2339 st_index_t d = 1;
2340#else
2341 st_index_t perturb = p->hash;
2342#endif
2343
2344 if (DELETED_ENTRY_P(p))
2345 continue;
2346
2347 ind = hash_bin(p->hash, tab);
2348 for (;;) {
2349 st_index_t bin = get_bin(st_bins_ptr(tab), size_ind, ind);
2350 if (EMPTY_OR_DELETED_BIN_P(bin)) {
2351 /* ok, new room */
2352 set_bin(st_bins_ptr(tab), size_ind, ind, i + ENTRY_BASE);
2353 break;
2354 }
2355 else {
2356 st_table_entry *q = &tab->entries[bin - ENTRY_BASE];
2357 DO_PTR_EQUAL_CHECK(tab, q, p->hash, p->key, eq_p, rebuilt_p);
2358 if (EXPECT(rebuilt_p, 0))
2359 return TRUE;
2360 if (eq_p) {
2361 /* duplicated key; delete it */
2362 q->record = p->record;
2363 MARK_ENTRY_DELETED(p);
2364 tab->num_entries--;
2365 update_range_for_deleted(tab, bin);
2366 break;
2367 }
2368 else {
2369 /* hash collision; skip it */
2370#ifdef QUADRATIC_PROBE
2371 ind = hash_bin(ind + d, tab);
2372 d++;
2373#else
2374 ind = secondary_hash(ind, tab, &perturb);
2375#endif
2376 }
2377 }
2378 }
2379 }
2380 return FALSE;
2381}
2382
2383/* Reconstruct TAB's bins according to TAB's entries. This function
2384 permits conflicting keys inside of entries. No errors are reported
2385 then. All but one of them are discarded silently. */
2386static void
2387st_rehash(st_table *tab)
2388{
2389 int rebuilt_p;
2390
2391 do {
2392 if (tab->entry_power <= MAX_POWER2_FOR_TABLES_WITHOUT_BINS)
2393 rebuilt_p = st_rehash_linear(tab);
2394 else
2395 rebuilt_p = st_rehash_indexed(tab);
2396 } while (rebuilt_p);
2397}
2398
2399static st_data_t
2400st_stringify(VALUE key)
2401{
2402 return (rb_obj_class(key) == rb_cString && !RB_OBJ_FROZEN(key)) ?
2403 rb_hash_key_str(key) : key;
2404}
2405
2406static void
2407st_insert_single(st_table *tab, VALUE hash, VALUE key, VALUE val)
2408{
2409 st_data_t k = st_stringify(key);
2411 e.hash = do_hash(k, tab);
2412 e.key = k;
2413 e.record = val;
2414
2415 tab->entries[tab->entries_bound++] = e;
2416 tab->num_entries++;
2417 RB_OBJ_WRITTEN(hash, Qundef, k);
2418 RB_OBJ_WRITTEN(hash, Qundef, val);
2419}
2420
2421static void
2422st_insert_linear(st_table *tab, long argc, const VALUE *argv, VALUE hash)
2423{
2424 long i;
2425
2426 for (i = 0; i < argc; /* */) {
2427 st_data_t k = st_stringify(argv[i++]);
2428 st_data_t v = argv[i++];
2429 st_insert(tab, k, v);
2430 RB_OBJ_WRITTEN(hash, Qundef, k);
2431 RB_OBJ_WRITTEN(hash, Qundef, v);
2432 }
2433}
2434
2435static void
2436st_insert_generic(st_table *tab, long argc, const VALUE *argv, VALUE hash)
2437{
2438 long i;
2439
2440 /* push elems */
2441 for (i = 0; i < argc; /* */) {
2442 VALUE key = argv[i++];
2443 VALUE val = argv[i++];
2444 st_insert_single(tab, hash, key, val);
2445 }
2446
2447 /* reindex */
2448 st_rehash(tab);
2449}
2450
2451/* Mimics ruby's { foo => bar } syntax. This function is subpart
2452 of rb_hash_bulk_insert. */
2453void
2454rb_hash_bulk_insert_into_st_table(long argc, const VALUE *argv, VALUE hash)
2455{
2456 st_index_t n, size = argc / 2;
2457 st_table *tab = RHASH_ST_TABLE(hash);
2458
2459 tab = RHASH_TBL_RAW(hash);
2460 n = tab->entries_bound + size;
2461 st_expand_table(tab, n);
2462 if (UNLIKELY(tab->num_entries))
2463 st_insert_generic(tab, argc, argv, hash);
2464 else if (argc <= 2)
2465 st_insert_single(tab, hash, argv[0], argv[1]);
2466 else if (tab->entry_power <= MAX_POWER2_FOR_TABLES_WITHOUT_BINS)
2467 st_insert_linear(tab, argc, argv, hash);
2468 else
2469 st_insert_generic(tab, argc, argv, hash);
2470}
2471
2472void
2473rb_st_compact_table(st_table *tab)
2474{
2475 st_index_t num = tab->num_entries;
2476 if (REBUILD_THRESHOLD * num <= get_allocated_entries(tab)) {
2477 /* Compaction: */
2478 st_table *new_tab = st_init_table_with_size(tab->type, 2 * num);
2479 rebuild_table_with(new_tab, tab);
2480 rebuild_move_table(new_tab, tab);
2481 rebuild_cleanup(tab);
2482 }
2483}
2484
2485/*
2486 * set_table related code
2487 */
2488
2489struct set_table_entry {
2490 st_hash_t hash;
2491 st_data_t key;
2492};
2493
2494static inline void
2495set_ptr_equal_check(const set_table *tab, const set_table_entry *entry,
2496 st_hash_t hash_val, st_data_t key,
2497 int *res, int *rebuilt_p)
2498{
2499 unsigned int old_rebuilds_num = tab->rebuilds_num;
2500 *res = entry_equal(tab->type, entry->hash, entry->key, hash_val, key);
2501 *rebuilt_p = old_rebuilds_num != tab->rebuilds_num;
2502}
2503
2504#define SET_DO_PTR_EQUAL_CHECK(tab, ptr, hash_val, key, res, rebuilt_p) \
2505 set_ptr_equal_check((tab), (ptr), (hash_val), (key), &(res), &(rebuilt_p))
2506
2507/* Return hash value of KEY for table TAB. */
2508static inline st_hash_t
2509set_do_hash(st_data_t key, set_table *tab)
2510{
2511 st_hash_t hash = (st_hash_t)(tab->type->hash)(key);
2512 return normalize_hash_value(hash);
2513}
2514
2515/* Return bin size index of table TAB. */
2516static inline unsigned int
2517set_get_size_ind(const set_table *tab)
2518{
2519 return tab->size_ind;
2520}
2521
2522/* Return the number of allocated bins of table TAB. */
2523static inline st_index_t
2524set_get_bins_num(const set_table *tab)
2525{
2526 return ((st_index_t) 1)<<tab->bin_power;
2527}
2528
2529/* Return mask for a bin index in table TAB. */
2530static inline st_index_t
2531set_bins_mask(const set_table *tab)
2532{
2533 return set_get_bins_num(tab) - 1;
2534}
2535
2536/* Return the index of table TAB bin corresponding to
2537 HASH_VALUE. */
2538static inline st_index_t
2539set_hash_bin(st_hash_t hash_value, set_table *tab)
2540{
2541 return hash_value & set_bins_mask(tab);
2542}
2543
2544/* Return the number of allocated entries of table TAB. */
2545static inline st_index_t
2546set_get_allocated_entries(const set_table *tab)
2547{
2548 return ((st_index_t) 1)<<tab->entry_power;
2549}
2550
2551static inline size_t
2552set_allocated_entries_size(const set_table *tab)
2553{
2554 return set_get_allocated_entries(tab) * sizeof(set_table_entry);
2555}
2556
2557static inline bool
2558set_has_bins(const set_table *tab)
2559{
2560 return tab->entry_power > MAX_POWER2_FOR_TABLES_WITHOUT_BINS;
2561}
2562
2563/* Return size of the allocated bins of table TAB. */
2564static inline st_index_t
2565set_bins_size(const set_table *tab)
2566{
2567 if (set_has_bins(tab)) {
2568 return features[tab->entry_power].bins_words * sizeof (st_index_t);
2569 }
2570
2571 return 0;
2572}
2573
2574static inline st_index_t *
2575set_bins_ptr(const set_table *tab)
2576{
2577 if (set_has_bins(tab)) {
2578 return (st_index_t *)(((char *)tab->entries) + set_allocated_entries_size(tab));
2579 }
2580
2581 return NULL;
2582}
2583
2584/* Mark all bins of table TAB as empty. */
2585static void
2586set_initialize_bins(set_table *tab)
2587{
2588 memset(set_bins_ptr(tab), 0, set_bins_size(tab));
2589}
2590
2591/* Make table TAB empty. */
2592static void
2593set_make_tab_empty(set_table *tab)
2594{
2595 tab->num_entries = 0;
2596 tab->entries_start = tab->entries_bound = 0;
2597 if (set_bins_ptr(tab) != NULL)
2598 set_initialize_bins(tab);
2599}
2600
2601static inline size_t
2602set_entries_memsize(set_table *tab)
2603{
2604 size_t memsize = set_get_allocated_entries(tab) * sizeof(set_table_entry);
2605 if (set_has_bins(tab)) {
2606 memsize += set_bins_size(tab);
2607 }
2608 return memsize;
2609}
2610
2611static set_table *
2612set_init_existing_table_with_size(set_table *tab, const struct st_hash_type *type, st_index_t size)
2613{
2614 int n;
2615
2616#ifdef HASH_LOG
2617#if HASH_LOG+0 < 0
2618 {
2619 const char *e = getenv("ST_HASH_LOG");
2620 if (!e || !*e) init_st = 1;
2621 }
2622#endif
2623 if (init_st == 0) {
2624 init_st = 1;
2625 atexit(stat_col);
2626 }
2627#endif
2628
2629 n = get_power2(size);
2630
2631 tab->type = type;
2632 tab->entry_power = n;
2633 tab->bin_power = features[n].bin_power;
2634 tab->size_ind = features[n].size_ind;
2635
2636 tab->entries = (set_table_entry *)malloc(set_entries_memsize(tab));
2637 set_make_tab_empty(tab);
2638 tab->rebuilds_num = 0;
2639 return tab;
2640}
2641
2642/* Create and return table with TYPE which can hold at least SIZE
2643 entries. The real number of entries which the table can hold is
2644 the nearest power of two for SIZE. */
2645set_table *
2646set_init_table_with_size(set_table *tab, const struct st_hash_type *type, st_index_t size)
2647{
2648 if (tab == NULL) tab = malloc(sizeof(set_table));
2649
2650 set_init_existing_table_with_size(tab, type, size);
2651
2652 return tab;
2653}
2654
2655set_table *
2656set_init_numtable(void)
2657{
2658 return set_init_table_with_size(NULL, &type_numhash, 0);
2659}
2660
2661set_table *
2662set_init_numtable_with_size(st_index_t size)
2663{
2664 return set_init_table_with_size(NULL, &type_numhash, size);
2665}
2666
2667set_table *
2668set_init_embedded_numtable_with_size(set_table *tab, st_index_t size)
2669{
2670 return set_init_existing_table_with_size(tab, &type_numhash, size);
2671}
2672
2673size_t
2674set_table_size(const struct set_table *tbl)
2675{
2676 return tbl->num_entries;
2677}
2678
2679/* Make table TAB empty. */
2680void
2681set_table_clear(set_table *tab)
2682{
2683 set_make_tab_empty(tab);
2684 tab->rebuilds_num++;
2685}
2686
2687void
2688set_free_embedded_table(set_table *tab)
2689{
2690 sized_free(tab->entries, set_entries_memsize(tab));
2691}
2692
2693/* Free table TAB space. This should only be used if you passed NULL to
2694 set_init_table_with_size/set_copy when creating the table. */
2695void
2696set_free_table(set_table *tab)
2697{
2698 set_free_embedded_table(tab);
2699 free_fixed_ptr(tab);
2700}
2701
2702/* Return byte size of memory allocated for table TAB. */
2703size_t
2704set_memsize(const set_table *tab)
2705{
2706 return(sizeof(set_table)
2707 + (tab->entry_power <= MAX_POWER2_FOR_TABLES_WITHOUT_BINS ? 0 : set_bins_size(tab))
2708 + set_get_allocated_entries(tab) * sizeof(set_table_entry));
2709}
2710
2711static st_index_t
2712set_find_table_entry_ind(set_table *tab, st_hash_t hash_value, st_data_t key);
2713
2714static st_index_t
2715set_find_table_bin_ind(set_table *tab, st_hash_t hash_value, st_data_t key);
2716
2717static st_index_t
2718set_find_table_bin_ind_direct(set_table *table, st_hash_t hash_value, st_data_t key);
2719
2720static st_index_t
2721set_find_table_bin_ptr_and_reserve(set_table *tab, st_hash_t *hash_value,
2722 st_data_t key, st_index_t *bin_ind);
2723
2724static void set_rebuild_table_with(set_table *const new_tab, set_table *const tab);
2725static void set_rebuild_move_table(set_table *const new_tab, set_table *const tab);
2726static void set_rebuild_cleanup(set_table *const tab);
2727
2728/* Rebuild table TAB. Rebuilding removes all deleted bins and entries
2729 and can change size of the table entries and bins arrays.
2730 Rebuilding is implemented by creation of a new table or by
2731 compaction of the existing one. */
2732static void
2733set_rebuild_table(set_table *tab)
2734{
2735 if ((2 * tab->num_entries <= set_get_allocated_entries(tab)
2736 && REBUILD_THRESHOLD * tab->num_entries > set_get_allocated_entries(tab))
2737 || tab->num_entries < (1 << MINIMAL_POWER2)) {
2738 /* Compaction: */
2739 tab->num_entries = 0;
2740 if (set_has_bins(tab))
2741 set_initialize_bins(tab);
2742 set_rebuild_table_with(tab, tab);
2743 }
2744 else {
2745 set_table *new_tab;
2746 /* This allocation could trigger GC and compaction. If tab is the
2747 * gen_fields_tbl, then tab could have changed in size due to objects being
2748 * freed and/or moved. Do not store attributes of tab before this line. */
2749 new_tab = set_init_table_with_size(NULL, tab->type,
2750 2 * tab->num_entries - 1);
2751 set_rebuild_table_with(new_tab, tab);
2752 set_rebuild_move_table(new_tab, tab);
2753 }
2754 set_rebuild_cleanup(tab);
2755}
2756
2757static void
2758set_rebuild_table_with(set_table *const new_tab, set_table *const tab)
2759{
2760 st_index_t i, ni;
2761 unsigned int size_ind;
2762 set_table_entry *new_entries;
2763 set_table_entry *curr_entry_ptr;
2764 st_index_t *bins;
2765 st_index_t bin_ind;
2766
2767 new_entries = new_tab->entries;
2768
2769 ni = 0;
2770 bins = set_bins_ptr(new_tab);
2771 size_ind = set_get_size_ind(new_tab);
2772 st_index_t bound = tab->entries_bound;
2773 set_table_entry *entries = tab->entries;
2774
2775 for (i = tab->entries_start; i < bound; i++) {
2776 curr_entry_ptr = &entries[i];
2777 PREFETCH(entries + i + 1, 0);
2778 if (EXPECT(DELETED_ENTRY_P(curr_entry_ptr), 0))
2779 continue;
2780 if (&new_entries[ni] != curr_entry_ptr)
2781 new_entries[ni] = *curr_entry_ptr;
2782 if (EXPECT(bins != NULL, 1)) {
2783 bin_ind = set_find_table_bin_ind_direct(new_tab, curr_entry_ptr->hash,
2784 curr_entry_ptr->key);
2785 set_bin(bins, size_ind, bin_ind, ni + ENTRY_BASE);
2786 }
2787 new_tab->num_entries++;
2788 ni++;
2789 }
2790
2791 assert(new_tab->num_entries == tab->num_entries);
2792}
2793
2794static void
2795set_rebuild_move_table(set_table *const new_tab, set_table *const tab)
2796{
2797 sized_free(tab->entries, set_entries_memsize(tab));
2798 tab->entries = new_tab->entries;
2799
2800 tab->entry_power = new_tab->entry_power;
2801 tab->bin_power = new_tab->bin_power;
2802 tab->size_ind = new_tab->size_ind;
2803
2804 free_fixed_ptr(new_tab);
2805}
2806
2807static void
2808set_rebuild_cleanup(set_table *const tab)
2809{
2810 tab->entries_start = 0;
2811 tab->entries_bound = tab->num_entries;
2812 tab->rebuilds_num++;
2813}
2814
2815/* Return the next secondary hash index for table TAB using previous
2816 index IND and PERTURB. Finally modulo of the function becomes a
2817 full *cycle linear congruential generator*, in other words it
2818 guarantees traversing all table bins in extreme case.
2819
2820 According the Hull-Dobell theorem a generator
2821 "Xnext = (a*Xprev + c) mod m" is a full cycle generator if and only if
2822 o m and c are relatively prime
2823 o a-1 is divisible by all prime factors of m
2824 o a-1 is divisible by 4 if m is divisible by 4.
2825
2826 For our case a is 5, c is 1, and m is a power of two. */
2827static inline st_index_t
2828set_secondary_hash(st_index_t ind, set_table *tab, st_index_t *perturb)
2829{
2830 *perturb >>= 11;
2831 ind = (ind << 2) + ind + *perturb + 1;
2832 return set_hash_bin(ind, tab);
2833}
2834
2835/* Find an entry with HASH_VALUE and KEY in TABLE using a linear
2836 search. Return the index of the found entry in array `entries`.
2837 If it is not found, return UNDEFINED_ENTRY_IND. If the table was
2838 rebuilt during the search, return REBUILT_TABLE_ENTRY_IND. */
2839static inline st_index_t
2840set_find_entry(set_table *tab, st_hash_t hash_value, st_data_t key)
2841{
2842 int eq_p, rebuilt_p;
2843 st_index_t i, bound;
2844 set_table_entry *entries;
2845
2846 bound = tab->entries_bound;
2847 entries = tab->entries;
2848 for (i = tab->entries_start; i < bound; i++) {
2849 SET_DO_PTR_EQUAL_CHECK(tab, &entries[i], hash_value, key, eq_p, rebuilt_p);
2850 if (EXPECT(rebuilt_p, 0))
2851 return REBUILT_TABLE_ENTRY_IND;
2852 if (eq_p)
2853 return i;
2854 }
2855 return UNDEFINED_ENTRY_IND;
2856}
2857
2858/* Use the quadratic probing. The method has a better data locality
2859 but more collisions than the current approach. In average it
2860 results in a bit slower search. */
2861/*#define QUADRATIC_PROBE*/
2862
2863/* Return index of entry with HASH_VALUE and KEY in table TAB. If
2864 there is no such entry, return UNDEFINED_ENTRY_IND. If the table
2865 was rebuilt during the search, return REBUILT_TABLE_ENTRY_IND. */
2866static st_index_t
2867set_find_table_entry_ind(set_table *tab, st_hash_t hash_value, st_data_t key)
2868{
2869 int eq_p, rebuilt_p;
2870 st_index_t ind;
2871#ifdef QUADRATIC_PROBE
2872 st_index_t d;
2873#else
2874 st_index_t perturb;
2875#endif
2876 st_index_t bin;
2877 set_table_entry *entries = tab->entries;
2878
2879 ind = set_hash_bin(hash_value, tab);
2880#ifdef QUADRATIC_PROBE
2881 d = 1;
2882#else
2883 perturb = hash_value;
2884#endif
2885 for (;;) {
2886 bin = get_bin(set_bins_ptr(tab), set_get_size_ind(tab), ind);
2887 if (! EMPTY_OR_DELETED_BIN_P(bin)) {
2888 SET_DO_PTR_EQUAL_CHECK(tab, &entries[bin - ENTRY_BASE], hash_value, key, eq_p, rebuilt_p);
2889 if (EXPECT(rebuilt_p, 0))
2890 return REBUILT_TABLE_ENTRY_IND;
2891 if (eq_p)
2892 break;
2893 }
2894 else if (EMPTY_BIN_P(bin))
2895 return UNDEFINED_ENTRY_IND;
2896#ifdef QUADRATIC_PROBE
2897 ind = set_hash_bin(ind + d, tab);
2898 d++;
2899#else
2900 ind = set_secondary_hash(ind, tab, &perturb);
2901#endif
2902 }
2903 return bin;
2904}
2905
2906/* Find and return index of table TAB bin corresponding to an entry
2907 with HASH_VALUE and KEY. If there is no such bin, return
2908 UNDEFINED_BIN_IND. If the table was rebuilt during the search,
2909 return REBUILT_TABLE_BIN_IND. */
2910static st_index_t
2911set_find_table_bin_ind(set_table *tab, st_hash_t hash_value, st_data_t key)
2912{
2913 int eq_p, rebuilt_p;
2914 st_index_t ind;
2915#ifdef QUADRATIC_PROBE
2916 st_index_t d;
2917#else
2918 st_index_t perturb;
2919#endif
2920 st_index_t bin;
2921 set_table_entry *entries = tab->entries;
2922
2923 ind = set_hash_bin(hash_value, tab);
2924#ifdef QUADRATIC_PROBE
2925 d = 1;
2926#else
2927 perturb = hash_value;
2928#endif
2929 for (;;) {
2930 bin = get_bin(set_bins_ptr(tab), set_get_size_ind(tab), ind);
2931 if (! EMPTY_OR_DELETED_BIN_P(bin)) {
2932 SET_DO_PTR_EQUAL_CHECK(tab, &entries[bin - ENTRY_BASE], hash_value, key, eq_p, rebuilt_p);
2933 if (EXPECT(rebuilt_p, 0))
2934 return REBUILT_TABLE_BIN_IND;
2935 if (eq_p)
2936 break;
2937 }
2938 else if (EMPTY_BIN_P(bin))
2939 return UNDEFINED_BIN_IND;
2940#ifdef QUADRATIC_PROBE
2941 ind = set_hash_bin(ind + d, tab);
2942 d++;
2943#else
2944 ind = set_secondary_hash(ind, tab, &perturb);
2945#endif
2946 }
2947 return ind;
2948}
2949
2950/* Find and return index of table TAB bin corresponding to an entry
2951 with HASH_VALUE and KEY. The entry should be in the table
2952 already. */
2953static st_index_t
2954set_find_table_bin_ind_direct(set_table *tab, st_hash_t hash_value, st_data_t key)
2955{
2956 st_index_t ind;
2957#ifdef QUADRATIC_PROBE
2958 st_index_t d;
2959#else
2960 st_index_t perturb;
2961#endif
2962 st_index_t bin;
2963
2964 ind = set_hash_bin(hash_value, tab);
2965#ifdef QUADRATIC_PROBE
2966 d = 1;
2967#else
2968 perturb = hash_value;
2969#endif
2970 for (;;) {
2971 bin = get_bin(set_bins_ptr(tab), set_get_size_ind(tab), ind);
2972 if (EMPTY_OR_DELETED_BIN_P(bin))
2973 return ind;
2974#ifdef QUADRATIC_PROBE
2975 ind = set_hash_bin(ind + d, tab);
2976 d++;
2977#else
2978 ind = set_secondary_hash(ind, tab, &perturb);
2979#endif
2980 }
2981}
2982
2983/* Mark I-th bin of table TAB as empty, in other words not
2984 corresponding to any entry. */
2985#define MARK_SET_BIN_EMPTY(tab, i) (set_bin(set_bins_ptr(tab), set_get_size_ind(tab), i, EMPTY_BIN))
2986
2987/* Return index of table TAB bin for HASH_VALUE and KEY through
2988 BIN_IND and the pointed value as the function result. Reserve the
2989 bin for inclusion of the corresponding entry into the table if it
2990 is not there yet. We always find such bin as bins array length is
2991 bigger entries array. Although we can reuse a deleted bin, the
2992 result bin value is always empty if the table has no entry with
2993 KEY. Return the entries array index of the found entry or
2994 UNDEFINED_ENTRY_IND if it is not found. If the table was rebuilt
2995 during the search, return REBUILT_TABLE_ENTRY_IND. */
2996static st_index_t
2997set_find_table_bin_ptr_and_reserve(set_table *tab, st_hash_t *hash_value,
2998 st_data_t key, st_index_t *bin_ind)
2999{
3000 int eq_p, rebuilt_p;
3001 st_index_t ind;
3002 st_hash_t curr_hash_value = *hash_value;
3003#ifdef QUADRATIC_PROBE
3004 st_index_t d;
3005#else
3006 st_index_t perturb;
3007#endif
3008 st_index_t entry_index;
3009 st_index_t firset_deleted_bin_ind;
3010 set_table_entry *entries;
3011
3012 ind = set_hash_bin(curr_hash_value, tab);
3013#ifdef QUADRATIC_PROBE
3014 d = 1;
3015#else
3016 perturb = curr_hash_value;
3017#endif
3018 firset_deleted_bin_ind = UNDEFINED_BIN_IND;
3019 entries = tab->entries;
3020 for (;;) {
3021 entry_index = get_bin(set_bins_ptr(tab), set_get_size_ind(tab), ind);
3022 if (EMPTY_BIN_P(entry_index)) {
3023 tab->num_entries++;
3024 entry_index = UNDEFINED_ENTRY_IND;
3025 if (firset_deleted_bin_ind != UNDEFINED_BIN_IND) {
3026 /* We can reuse bin of a deleted entry. */
3027 ind = firset_deleted_bin_ind;
3028 MARK_SET_BIN_EMPTY(tab, ind);
3029 }
3030 break;
3031 }
3032 else if (! DELETED_BIN_P(entry_index)) {
3033 SET_DO_PTR_EQUAL_CHECK(tab, &entries[entry_index - ENTRY_BASE], curr_hash_value, key, eq_p, rebuilt_p);
3034 if (EXPECT(rebuilt_p, 0))
3035 return REBUILT_TABLE_ENTRY_IND;
3036 if (eq_p)
3037 break;
3038 }
3039 else if (firset_deleted_bin_ind == UNDEFINED_BIN_IND)
3040 firset_deleted_bin_ind = ind;
3041#ifdef QUADRATIC_PROBE
3042 ind = set_hash_bin(ind + d, tab);
3043 d++;
3044#else
3045 ind = set_secondary_hash(ind, tab, &perturb);
3046#endif
3047 }
3048 *bin_ind = ind;
3049 return entry_index;
3050}
3051
3052/* Find an entry with KEY in table TAB. Return non-zero if we found
3053 it. */
3054int
3055set_table_lookup(set_table *tab, st_data_t key)
3056{
3057 st_index_t bin;
3058 st_hash_t hash = set_do_hash(key, tab);
3059
3060 retry:
3061 if (!set_has_bins(tab)) {
3062 bin = set_find_entry(tab, hash, key);
3063 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
3064 goto retry;
3065 if (bin == UNDEFINED_ENTRY_IND)
3066 return 0;
3067 }
3068 else {
3069 bin = set_find_table_entry_ind(tab, hash, key);
3070 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
3071 goto retry;
3072 if (bin == UNDEFINED_ENTRY_IND)
3073 return 0;
3074 bin -= ENTRY_BASE;
3075 }
3076 return 1;
3077}
3078
3079/* Check the table and rebuild it if it is necessary. */
3080static inline void
3081set_rebuild_table_if_necessary(set_table *tab)
3082{
3083 st_index_t bound = tab->entries_bound;
3084
3085 if (bound == set_get_allocated_entries(tab) || tab->entries_start == MAX_ENTRIES_START) {
3086 set_rebuild_table(tab);
3087 }
3088}
3089
3090/* Insert KEY into table TAB and return zero. If there is
3091 already entry with KEY in the table, return nonzero and update
3092 the value of the found entry. */
3093int
3094set_insert(set_table *tab, st_data_t key)
3095{
3096 set_table_entry *entry;
3097 st_index_t bin;
3098 st_index_t ind;
3099 st_hash_t hash_value;
3100 st_index_t bin_ind;
3101 int new_p;
3102
3103 hash_value = set_do_hash(key, tab);
3104 retry:
3105 set_rebuild_table_if_necessary(tab);
3106 if (!set_has_bins(tab)) {
3107 bin = set_find_entry(tab, hash_value, key);
3108 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
3109 goto retry;
3110 new_p = bin == UNDEFINED_ENTRY_IND;
3111 if (new_p)
3112 tab->num_entries++;
3113 bin_ind = UNDEFINED_BIN_IND;
3114 }
3115 else {
3116 bin = set_find_table_bin_ptr_and_reserve(tab, &hash_value,
3117 key, &bin_ind);
3118 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
3119 goto retry;
3120 new_p = bin == UNDEFINED_ENTRY_IND;
3121 bin -= ENTRY_BASE;
3122 }
3123 if (new_p) {
3124 ind = tab->entries_bound++;
3125 entry = &tab->entries[ind];
3126 entry->hash = hash_value;
3127 entry->key = key;
3128 if (bin_ind != UNDEFINED_BIN_IND)
3129 set_bin(set_bins_ptr(tab), set_get_size_ind(tab), bin_ind, ind + ENTRY_BASE);
3130 return 0;
3131 }
3132 return 1;
3133}
3134
3135/* Create a copy of old_tab into new_tab. */
3136static set_table *
3137set_replace(set_table *new_tab, set_table *old_tab)
3138{
3139 *new_tab = *old_tab;
3140 size_t memsize = set_allocated_entries_size(old_tab) + set_bins_size(old_tab);
3141 new_tab->entries = (set_table_entry *)malloc(memsize);
3142 MEMCPY(new_tab->entries, old_tab->entries, char, memsize);
3143 return new_tab;
3144}
3145
3146/* Create and return a copy of table OLD_TAB. */
3147set_table *
3148set_copy(set_table *new_tab, set_table *old_tab)
3149{
3150 if (new_tab == NULL) new_tab = (set_table *) malloc(sizeof(set_table));
3151
3152 if (set_replace(new_tab, old_tab) == NULL) {
3153 set_free_table(new_tab);
3154 return NULL;
3155 }
3156
3157 return new_tab;
3158}
3159
3160/* Update the entries start of table TAB after removing an entry
3161 with index N in the array entries. */
3162static inline void
3163set_update_range_for_deleted(set_table *tab, st_index_t n)
3164{
3165 /* Do not update entries_bound here. Otherwise, we can fill all
3166 bins by deleted entry value before rebuilding the table. */
3167 if (tab->entries_start == n) {
3168 st_index_t start = n + 1;
3169 st_index_t bound = tab->entries_bound;
3170 set_table_entry *entries = tab->entries;
3171 while (start < bound && DELETED_ENTRY_P(&entries[start])) start++;
3172 tab->entries_start = start > MAX_ENTRIES_START ? MAX_ENTRIES_START : (unsigned int)start;
3173 }
3174}
3175
3176/* Mark I-th bin of table TAB as corresponding to a deleted table
3177 entry. Update number of entries in the table and number of bins
3178 corresponding to deleted entries. */
3179#define MARK_SET_BIN_DELETED(tab, i) \
3180 do { \
3181 set_bin(set_bins_ptr(tab), set_get_size_ind(tab), i, DELETED_BIN); \
3182 } while (0)
3183
3184/* Delete entry with KEY from table TAB, and return non-zero. If
3185 there is no entry with KEY in the table, return zero. */
3186int
3187set_table_delete(set_table *tab, st_data_t *key)
3188{
3189 set_table_entry *entry;
3190 st_index_t bin;
3191 st_index_t bin_ind;
3192 st_hash_t hash;
3193
3194 hash = set_do_hash(*key, tab);
3195 retry:
3196 if (!set_has_bins(tab)) {
3197 bin = set_find_entry(tab, hash, *key);
3198 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
3199 goto retry;
3200 if (bin == UNDEFINED_ENTRY_IND) {
3201 return 0;
3202 }
3203 }
3204 else {
3205 bin_ind = set_find_table_bin_ind(tab, hash, *key);
3206 if (EXPECT(bin_ind == REBUILT_TABLE_BIN_IND, 0))
3207 goto retry;
3208 if (bin_ind == UNDEFINED_BIN_IND) {
3209 return 0;
3210 }
3211 bin = get_bin(set_bins_ptr(tab), set_get_size_ind(tab), bin_ind) - ENTRY_BASE;
3212 MARK_SET_BIN_DELETED(tab, bin_ind);
3213 }
3214 entry = &tab->entries[bin];
3215 *key = entry->key;
3216 MARK_ENTRY_DELETED(entry);
3217 tab->num_entries--;
3218 set_update_range_for_deleted(tab, bin);
3219 return 1;
3220}
3221
3222/* Traverse all entries in table TAB calling FUNC with current entry
3223 key and zero. If the call returns ST_STOP, stop
3224 traversing. If the call returns ST_DELETE, delete the current
3225 entry from the table. In case of ST_CHECK or ST_CONTINUE, continue
3226 traversing. The function returns zero unless an error is found.
3227 CHECK_P is flag of set_foreach_check call. The behavior is a bit
3228 different for ST_CHECK and when the current element is removed
3229 during traversing. */
3230static inline int
3231set_general_foreach(set_table *tab, set_foreach_check_callback_func *func,
3232 set_update_callback_func *replace, st_data_t arg,
3233 int check_p)
3234{
3235 st_index_t bin;
3236 st_index_t bin_ind;
3237 set_table_entry *entries, *curr_entry_ptr;
3238 enum st_retval retval;
3239 st_index_t i, rebuilds_num;
3240 st_hash_t hash;
3241 st_data_t key;
3242 int error_p, packed_p = !set_has_bins(tab);
3243
3244 entries = tab->entries;
3245 /* The bound can change inside the loop even without rebuilding
3246 the table, e.g. by an entry insertion. */
3247 for (i = tab->entries_start; i < tab->entries_bound; i++) {
3248 curr_entry_ptr = &entries[i];
3249 if (EXPECT(DELETED_ENTRY_P(curr_entry_ptr), 0))
3250 continue;
3251 key = curr_entry_ptr->key;
3252 rebuilds_num = tab->rebuilds_num;
3253 hash = curr_entry_ptr->hash;
3254 retval = (*func)(key, arg, 0);
3255
3256 if (retval == ST_REPLACE && replace) {
3257 retval = (*replace)(&key, arg, TRUE);
3258 curr_entry_ptr->key = key;
3259 }
3260
3261 if (rebuilds_num != tab->rebuilds_num) {
3262 retry:
3263 entries = tab->entries;
3264 packed_p = !set_has_bins(tab);
3265 if (packed_p) {
3266 i = set_find_entry(tab, hash, key);
3267 if (EXPECT(i == REBUILT_TABLE_ENTRY_IND, 0))
3268 goto retry;
3269 error_p = i == UNDEFINED_ENTRY_IND;
3270 }
3271 else {
3272 i = set_find_table_entry_ind(tab, hash, key);
3273 if (EXPECT(i == REBUILT_TABLE_ENTRY_IND, 0))
3274 goto retry;
3275 error_p = i == UNDEFINED_ENTRY_IND;
3276 i -= ENTRY_BASE;
3277 }
3278 if (error_p && check_p) {
3279 /* call func with error notice */
3280 retval = (*func)(0, arg, 1);
3281 return 1;
3282 }
3283 curr_entry_ptr = &entries[i];
3284 }
3285 switch (retval) {
3286 case ST_REPLACE:
3287 break;
3288 case ST_CONTINUE:
3289 break;
3290 case ST_CHECK:
3291 if (check_p)
3292 break;
3293 case ST_STOP:
3294 return 0;
3295 case ST_DELETE: {
3296 st_data_t key = curr_entry_ptr->key;
3297
3298 again:
3299 if (packed_p) {
3300 bin = set_find_entry(tab, hash, key);
3301 if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
3302 goto again;
3303 if (bin == UNDEFINED_ENTRY_IND)
3304 break;
3305 }
3306 else {
3307 bin_ind = set_find_table_bin_ind(tab, hash, key);
3308 if (EXPECT(bin_ind == REBUILT_TABLE_BIN_IND, 0))
3309 goto again;
3310 if (bin_ind == UNDEFINED_BIN_IND)
3311 break;
3312 bin = get_bin(set_bins_ptr(tab), set_get_size_ind(tab), bin_ind) - ENTRY_BASE;
3313 MARK_SET_BIN_DELETED(tab, bin_ind);
3314 }
3315 curr_entry_ptr = &entries[bin];
3316 MARK_ENTRY_DELETED(curr_entry_ptr);
3317 tab->num_entries--;
3318 set_update_range_for_deleted(tab, bin);
3319 break;
3320 }
3321 }
3322 }
3323 return 0;
3324}
3325
3326int
3327set_foreach_with_replace(set_table *tab, set_foreach_check_callback_func *func, set_update_callback_func *replace, st_data_t arg)
3328{
3329 return set_general_foreach(tab, func, replace, arg, TRUE);
3330}
3331
3332struct set_functor {
3333 set_foreach_callback_func *func;
3334 st_data_t arg;
3335};
3336
3337static int
3338set_apply_functor(st_data_t k, st_data_t d, int _)
3339{
3340 const struct set_functor *f = (void *)d;
3341 return f->func(k, f->arg);
3342}
3343
3344int
3345set_table_foreach(set_table *tab, set_foreach_callback_func *func, st_data_t arg)
3346{
3347 const struct set_functor f = { func, arg };
3348 return set_general_foreach(tab, set_apply_functor, NULL, (st_data_t)&f, FALSE);
3349}
3350
3351/* See comments for function set_delete_safe. */
3352int
3353set_foreach_check(set_table *tab, set_foreach_check_callback_func *func, st_data_t arg,
3354 st_data_t never ATTRIBUTE_UNUSED)
3355{
3356 return set_general_foreach(tab, func, NULL, arg, TRUE);
3357}
3358
3359/* Set up array KEYS by at most SIZE keys of head table TAB entries.
3360 Return the number of keys set up in array KEYS. */
3361st_index_t
3362set_keys(set_table *tab, st_data_t *keys, st_index_t size)
3363{
3364 st_index_t i, bound;
3365 st_data_t key, *keys_start, *keys_end;
3366 set_table_entry *curr_entry_ptr, *entries = tab->entries;
3367
3368 bound = tab->entries_bound;
3369 keys_start = keys;
3370 keys_end = keys + size;
3371 for (i = tab->entries_start; i < bound; i++) {
3372 if (keys == keys_end)
3373 break;
3374 curr_entry_ptr = &entries[i];
3375 key = curr_entry_ptr->key;
3376 if (! DELETED_ENTRY_P(curr_entry_ptr))
3377 *keys++ = key;
3378 }
3379
3380 return keys - keys_start;
3381}
3382
3383void
3384set_compact_table(set_table *tab)
3385{
3386 st_index_t num = tab->num_entries;
3387 if (REBUILD_THRESHOLD * num <= set_get_allocated_entries(tab)) {
3388 /* Compaction: */
3389 set_table *new_tab = set_init_table_with_size(NULL, tab->type, 2 * num);
3390 set_rebuild_table_with(new_tab, tab);
3391 set_rebuild_move_table(new_tab, tab);
3392 set_rebuild_cleanup(tab);
3393 }
3394}
3395
3396#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:714
#define Qundef
Old name of RUBY_Qundef.
VALUE rb_eRuntimeError
RuntimeError exception.
Definition error.c:1471
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:504
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