113 #define PREFETCH(addr, write_p) __builtin_prefetch(addr, write_p) 114 #define EXPECT(expr, val) __builtin_expect(expr, val) 115 #define ATTRIBUTE_UNUSED __attribute__((unused)) 117 #define PREFETCH(addr, write_p) 118 #define EXPECT(expr, val) (expr) 119 #define ATTRIBUTE_UNUSED 123 #define st_assert(cond) assert(cond) 125 #define st_assert(cond) ((void)(0 && (cond))) 137 #define type_numhash st_hashtype_num 159 #define ST_INIT_VAL 0xafafafafafafafaf 160 #define ST_INIT_VAL_BYTE 0xafa 167 #define malloc ruby_xmalloc 168 #define calloc ruby_xcalloc 169 #define realloc ruby_xrealloc 170 #define free ruby_xfree 173 #define EQUAL(tab,x,y) ((x) == (y) || (*(tab)->type->compare)((x),(y)) == 0) 174 #define PTR_EQUAL(tab, ptr, hash_val, key) \ 175 ((ptr)->hash == (hash_val) && EQUAL((tab), (key), (ptr)->key)) 193 #if SIZEOF_ST_INDEX_T == 8 194 #define MAX_POWER2 62 212 {16, 17, 2, 0x10000},
213 {17, 18, 2, 0x20000},
214 {18, 19, 2, 0x40000},
215 {19, 20, 2, 0x80000},
216 {20, 21, 2, 0x100000},
217 {21, 22, 2, 0x200000},
218 {22, 23, 2, 0x400000},
219 {23, 24, 2, 0x800000},
220 {24, 25, 2, 0x1000000},
221 {25, 26, 2, 0x2000000},
222 {26, 27, 2, 0x4000000},
223 {27, 28, 2, 0x8000000},
224 {28, 29, 2, 0x10000000},
225 {29, 30, 2, 0x20000000},
226 {30, 31, 2, 0x40000000},
227 {31, 32, 2, 0x80000000},
228 {32, 33, 3, 0x200000000},
229 {33, 34, 3, 0x400000000},
230 {34, 35, 3, 0x800000000},
231 {35, 36, 3, 0x1000000000},
232 {36, 37, 3, 0x2000000000},
233 {37, 38, 3, 0x4000000000},
234 {38, 39, 3, 0x8000000000},
235 {39, 40, 3, 0x10000000000},
236 {40, 41, 3, 0x20000000000},
237 {41, 42, 3, 0x40000000000},
238 {42, 43, 3, 0x80000000000},
239 {43, 44, 3, 0x100000000000},
240 {44, 45, 3, 0x200000000000},
241 {45, 46, 3, 0x400000000000},
242 {46, 47, 3, 0x800000000000},
243 {47, 48, 3, 0x1000000000000},
244 {48, 49, 3, 0x2000000000000},
245 {49, 50, 3, 0x4000000000000},
246 {50, 51, 3, 0x8000000000000},
247 {51, 52, 3, 0x10000000000000},
248 {52, 53, 3, 0x20000000000000},
249 {53, 54, 3, 0x40000000000000},
250 {54, 55, 3, 0x80000000000000},
251 {55, 56, 3, 0x100000000000000},
252 {56, 57, 3, 0x200000000000000},
253 {57, 58, 3, 0x400000000000000},
254 {58, 59, 3, 0x800000000000000},
255 {59, 60, 3, 0x1000000000000000},
256 {60, 61, 3, 0x2000000000000000},
257 {61, 62, 3, 0x4000000000000000},
258 {62, 63, 3, 0x8000000000000000},
262 #define MAX_POWER2 30 281 {16, 17, 2, 0x20000},
282 {17, 18, 2, 0x40000},
283 {18, 19, 2, 0x80000},
284 {19, 20, 2, 0x100000},
285 {20, 21, 2, 0x200000},
286 {21, 22, 2, 0x400000},
287 {22, 23, 2, 0x800000},
288 {23, 24, 2, 0x1000000},
289 {24, 25, 2, 0x2000000},
290 {25, 26, 2, 0x4000000},
291 {26, 27, 2, 0x8000000},
292 {27, 28, 2, 0x10000000},
293 {28, 29, 2, 0x20000000},
294 {29, 30, 2, 0x40000000},
295 {30, 31, 2, 0x80000000},
301 #define RESERVED_HASH_VAL (~(st_hash_t) 0) 302 #define RESERVED_HASH_SUBSTITUTION_VAL ((st_hash_t) 0) 316 #define MINIMAL_POWER2 2 318 #if MINIMAL_POWER2 < 2 319 #error "MINIMAL_POWER2 should be >= 2" 324 #define MAX_POWER2_FOR_TABLES_WITHOUT_BINS 4 332 for (n = 0; size != 0; n++)
349 return (s == 0 ? ((
unsigned char *) bins)[n]
350 : s == 1 ? ((
unsigned short *) bins)[n]
351 : s == 2 ? ((
unsigned int *) bins)[n]
360 if (s == 0) ((
unsigned char *) bins)[n] = (
unsigned char) v;
361 else if (s == 1) ((
unsigned short *) bins)[n] = (
unsigned short) v;
362 else if (s == 2) ((
unsigned int *) bins)[n] = (
unsigned int) v;
370 #define DELETED_BIN 1 376 #define MARK_BIN_EMPTY(tab, i) (set_bin((tab)->bins, get_size_ind(tab), i, EMPTY_BIN)) 380 #define UNDEFINED_ENTRY_IND (~(st_index_t) 0) 381 #define UNDEFINED_BIN_IND (~(st_index_t) 0) 386 #define MARK_BIN_DELETED(tab, i) \ 388 st_assert(i != UNDEFINED_BIN_IND); \ 389 st_assert(! IND_EMPTY_OR_DELETED_BIN_P(tab, i)); \ 390 set_bin((tab)->bins, get_size_ind(tab), i, DELETED_BIN); \ 395 #define EMPTY_BIN_P(b) ((b) == EMPTY_BIN) 396 #define DELETED_BIN_P(b) ((b) == DELETED_BIN) 397 #define EMPTY_OR_DELETED_BIN_P(b) ((b) <= DELETED_BIN) 401 #define IND_EMPTY_BIN_P(tab, i) (EMPTY_BIN_P(get_bin((tab)->bins, get_size_ind(tab), i))) 402 #define IND_DELETED_BIN_P(tab, i) (DELETED_BIN_P(get_bin((tab)->bins, get_size_ind(tab), i))) 403 #define IND_EMPTY_OR_DELETED_BIN_P(tab, i) (EMPTY_OR_DELETED_BIN_P(get_bin((tab)->bins, get_size_ind(tab), i))) 407 #define MARK_ENTRY_DELETED(e_ptr) ((e_ptr)->hash = RESERVED_HASH_VAL) 408 #define DELETED_ENTRY_P(e_ptr) ((e_ptr)->hash == RESERVED_HASH_VAL) 411 static inline unsigned int 526 int all, total, num, str, strcase;
531 static int init_st = 0;
538 char fname[10+
sizeof(long)*3];
540 if (!collision.total)
return;
541 f = fopen((
snprintf(fname,
sizeof(fname),
"/tmp/col%ld", (
long)getpid()), fname),
"w");
542 fprintf(f,
"collision: %d / %d (%6.2f)\n", collision.all, collision.total,
543 ((
double)collision.all / (collision.total)) * 100);
544 fprintf(f,
"num: %d, str: %d, strcase: %d\n", collision.num, collision.str, collision.strcase);
561 const char *e =
getenv(
"ST_HASH_LOG");
562 if (!e || !*e) init_st = 1;
702 else if (type == &type_strhash) {
705 else if (type == &type_strcasehash) {
710 #define COLLISION (collision_check ? count_collision(tab->type) : (void)0) 711 #define FOUND_BIN (collision_check ? collision.total++ : (void)0) 712 #define collision_check 0 721 #define REBUILD_THRESHOLD 4 723 #if REBUILD_THRESHOLD < 2 724 #error "REBUILD_THRESHOLD should be >= 2" 735 unsigned int size_ind;
753 new_entries = entries;
758 new_entries = new_tab->
entries;
761 bins = new_tab->
bins;
764 curr_entry_ptr = &entries[i];
768 if (&new_entries[ni] != curr_entry_ptr)
769 new_entries[ni] = *curr_entry_ptr;
772 curr_entry_ptr->
key);
781 if (new_tab != tab) {
817 ind = (ind << 2) + ind + *perterb + 1;
833 if (
PTR_EQUAL(tab, &entries[i], hash_value, key))
850 #ifdef QUADRATIC_PROBE 860 #ifdef QUADRATIC_PROBE 873 #ifdef QUADRATIC_PROBE 891 #ifdef QUADRATIC_PROBE 901 #ifdef QUADRATIC_PROBE 914 #ifdef QUADRATIC_PROBE 932 #ifdef QUADRATIC_PROBE 942 #ifdef QUADRATIC_PROBE 953 #ifdef QUADRATIC_PROBE 976 #ifdef QUADRATIC_PROBE 988 ind =
hash_bin(curr_hash_value, tab);
989 #ifdef QUADRATIC_PROBE 992 peterb = curr_hash_value;
1004 ind = first_deleted_bin_ind;
1012 first_deleted_bin_ind = ind;
1013 #ifdef QUADRATIC_PROBE 1096 hash_value =
do_hash(key, tab);
1113 entry->
hash = hash_value;
1163 hash_value =
do_hash(key, tab);
1181 hash_value =
do_hash(key, tab);
1197 &&
do_hash(key, tab) == hash_value);
1200 entry->
hash = hash_value;
1224 *new_tab = *old_tab;
1269 if (value != 0) *value = 0;
1275 if (value != 0) *value = 0;
1283 if (value != 0) *value = entry->
record;
1325 curr_entry_ptr = &entries[i];
1327 if (value != 0) *value = curr_entry_ptr->
record;
1328 *key = curr_entry_ptr->
key;
1332 && &entries[bin] == curr_entry_ptr);
1335 curr_entry_ptr->
key);
1352 if (value != 0) *value = 0;
1379 int retval, existing;
1386 entry = &entries[
bin];
1393 entry = &entries[
bin];
1402 retval = (*func)(&
key, &value, arg, existing);
1410 if (old_key != key) {
1452 int error_p, packed_p = tab->
bins ==
NULL;
1459 curr_entry_ptr = &entries[i];
1462 key = curr_entry_ptr->
key;
1464 hash = curr_entry_ptr->
hash;
1465 retval = (*func)(
key, curr_entry_ptr->
record, arg, 0);
1477 if (error_p && check_p) {
1479 retval = (*func)(0, 0, arg, 1);
1485 curr_entry_ptr = &entries[i];
1510 st_assert(&entries[bin] == curr_entry_ptr);
1550 keys_end = keys +
size;
1552 if (keys == keys_end)
1554 curr_entry_ptr = &entries[i];
1555 key = curr_entry_ptr->
key;
1560 return keys - keys_start;
1585 values_start = values;
1586 values_end = values +
size;
1590 if (values == values_end)
1592 curr_entry_ptr = &entries[i];
1594 *values++ = curr_entry_ptr->
record;
1597 return values - values_start;
1613 #define FNV1_32A_INIT 0x811c9dc5 1618 #define FNV_32_PRIME 0x01000193 1620 #ifndef UNALIGNED_WORD_ACCESS 1621 # if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ 1622 defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || \ 1623 defined(__powerpc64__) || \ 1624 defined(__mc68020__) 1625 # define UNALIGNED_WORD_ACCESS 1 1628 #ifndef UNALIGNED_WORD_ACCESS 1629 # define UNALIGNED_WORD_ACCESS 0 1635 #define BIG_CONSTANT(x,y) ((st_index_t)(x)<<32|(st_index_t)(y)) 1636 #define ROTL(x,n) ((x)<<(n)|(x)>>(SIZEOF_ST_INDEX_T*CHAR_BIT-(n))) 1638 #if ST_INDEX_BITS <= 32 1639 #define C1 (st_index_t)0xcc9e2d51 1640 #define C2 (st_index_t)0x1b873593 1642 #define C1 BIG_CONSTANT(0x87c37b91,0x114253d5); 1643 #define C2 BIG_CONSTANT(0x4cf5ad43,0x2745937f); 1648 #if ST_INDEX_BITS <= 32 1667 #if ST_INDEX_BITS <= 32 1681 #if ST_INDEX_BITS > 64 1700 const char *data = ptr;
1704 #define data_at(n) (st_index_t)((unsigned char)data[(n)]) 1705 #define UNALIGNED_ADD_4 UNALIGNED_ADD(2); UNALIGNED_ADD(1); UNALIGNED_ADD(0) 1706 #if SIZEOF_ST_INDEX_T > 4 1707 #define UNALIGNED_ADD_8 UNALIGNED_ADD(6); UNALIGNED_ADD(5); UNALIGNED_ADD(4); UNALIGNED_ADD(3); UNALIGNED_ADD_4 1708 #if SIZEOF_ST_INDEX_T > 8 1709 #define UNALIGNED_ADD_16 UNALIGNED_ADD(14); UNALIGNED_ADD(13); UNALIGNED_ADD(12); UNALIGNED_ADD(11); \ 1710 UNALIGNED_ADD(10); UNALIGNED_ADD(9); UNALIGNED_ADD(8); UNALIGNED_ADD(7); UNALIGNED_ADD_8 1711 #define UNALIGNED_ADD_ALL UNALIGNED_ADD_16 1713 #define UNALIGNED_ADD_ALL UNALIGNED_ADD_8 1715 #define UNALIGNED_ADD_ALL UNALIGNED_ADD_4 1719 #if !UNALIGNED_WORD_ACCESS 1726 #ifdef WORDS_BIGENDIAN 1727 # define UNALIGNED_ADD(n) case SIZEOF_ST_INDEX_T - (n) - 1: \ 1728 t |= data_at(n) << CHAR_BIT*(SIZEOF_ST_INDEX_T - (n) - 2) 1730 # define UNALIGNED_ADD(n) case SIZEOF_ST_INDEX_T - (n) - 1: \ 1731 t |= data_at(n) << CHAR_BIT*(n) 1734 #undef UNALIGNED_ADD 1737 #ifdef WORDS_BIGENDIAN 1751 #ifdef WORDS_BIGENDIAN 1752 t = (t << sr) | (d >> sl);
1754 t = (t >> sr) | (d << sl);
1762 pack = len < (size_t)align ? (
int)
len : align;
1765 #ifdef WORDS_BIGENDIAN 1766 # define UNALIGNED_ADD(n) case (n) + 1: \ 1767 d |= data_at(n) << CHAR_BIT*(SIZEOF_ST_INDEX_T - (n) - 1) 1769 # define UNALIGNED_ADD(n) case (n) + 1: \ 1770 d |= data_at(n) << CHAR_BIT*(n) 1773 #undef UNALIGNED_ADD 1775 #ifdef WORDS_BIGENDIAN 1776 t = (t << sr) | (d >> sl);
1778 t = (t >> sr) | (d << sl);
1781 if (len < (
size_t)align)
goto skip_tail;
1782 # define SKIP_TAIL 1 1800 #if UNALIGNED_WORD_ACCESS && SIZEOF_ST_INDEX_T <= 8 && CHAR_BIT == 8 1802 #if SIZEOF_ST_INDEX_T > 4 1803 case 7: t |=
data_at(6) << 48;
1804 case 6: t |=
data_at(5) << 40;
1805 case 5: t |=
data_at(4) << 32;
1809 # define SKIP_TAIL 1 1811 case 3: t |=
data_at(2) << 16;
1815 #ifdef WORDS_BIGENDIAN 1816 # define UNALIGNED_ADD(n) case (n) + 1: \ 1817 t |= data_at(n) << CHAR_BIT*(SIZEOF_ST_INDEX_T - (n) - 1) 1819 # define UNALIGNED_ADD(n) case (n) + 1: \ 1820 t |= data_at(n) << CHAR_BIT*(n) 1823 #undef UNALIGNED_ADD 1828 h ^= t; h -=
ROTL(t, 7);
1848 #if SIZEOF_ST_INDEX_T*CHAR_BIT > 8*8 1862 #undef st_hash_start 1872 register const char *
string = (
const char *)arg;
1879 unsigned int c1, c2;
1882 c1 = (
unsigned char)*s1++;
1883 c2 = (
unsigned char)*s2++;
1884 if (c1 ==
'\0' || c2 ==
'\0') {
1885 if (c1 !=
'\0')
return 1;
1886 if (c2 !=
'\0')
return -1;
1889 if ((
unsigned int)(c1 -
'A') <= (
'Z' -
'A')) c1 +=
'a' -
'A';
1890 if ((
unsigned int)(c2 -
'A') <= (
'Z' -
'A')) c2 +=
'a' -
'A';
1903 unsigned int c1, c2;
1906 c1 = (
unsigned char)*s1++;
1907 c2 = (
unsigned char)*s2++;
1908 if (c1 ==
'\0' || c2 ==
'\0') {
1909 if (c1 !=
'\0')
return 1;
1910 if (c2 !=
'\0')
return -1;
1913 if ((
unsigned int)(c1 -
'A') <= (
'Z' -
'A')) c1 +=
'a' -
'A';
1914 if ((
unsigned int)(c2 -
'A') <= (
'Z' -
'A')) c2 +=
'a' -
'A';
1929 register const char *
string = (
const char *)arg;
1936 unsigned int c = (
unsigned char)*
string++;
1937 if ((
unsigned int)(c -
'A') <= (
'Z' -
'A')) c +=
'a' -
'A';
1955 enum {s1 = 11, s2 = 3};
1956 return (
st_index_t)((n>>s1|(n<<s2)) ^ (n>>s2));
int st_insert2(st_table *tab, st_data_t key, st_data_t value, st_data_t(*func)(st_data_t))
static st_index_t bins_size(const st_table *tab)
size_t strlen(const char *)
int st_foreach_check(st_table *tab, int(*func)(ANYARGS), st_data_t arg, st_data_t never ATTRIBUTE_UNUSED)
static int st_general_delete(st_table *tab, st_data_t *key, st_data_t *value)
st_index_t st_hash_uint32(st_index_t h, uint32_t i)
int st_locale_insensitive_strcasecmp(const char *s1, const char *s2)
#define IND_DELETED_BIN_P(tab, i)
static const struct st_features features[]
st_index_t st_numhash(st_data_t n)
void st_add_direct(st_table *tab, st_data_t key, st_data_t value)
#define RESERVED_HASH_SUBSTITUTION_VAL
PUREFUNC(static st_index_t strcasehash(st_data_t))
static st_index_t murmur_step(st_index_t h, st_index_t k)
static st_index_t get_bins_num(const st_table *tab)
static st_index_t st_general_keys(st_table *tab, st_data_t *keys, st_index_t size)
SSL_METHOD *(* func)(void)
#define BIG_CONSTANT(x, y)
st_table * st_init_strcasetable_with_size(st_index_t size)
int st_update(st_table *tab, st_data_t key, st_update_callback_func *func, st_data_t arg)
#define PTR_EQUAL(tab, ptr, hash_val, key)
static const struct st_hash_type type_strhash
static st_index_t bins_mask(const st_table *tab)
st_index_t st_hash_start(st_index_t h)
void rb_raise(VALUE exc, const char *fmt,...)
static void set_bin(st_index_t *bins, int s, st_index_t n, st_index_t v)
static void initialize_bins(st_table *tab)
static st_index_t get_bin(st_index_t *bins, int s, st_index_t n)
st_table * st_init_table_with_size(const struct st_hash_type *type, st_index_t size)
st_table * st_init_numtable(void)
unsigned char entry_power
static st_hash_t do_hash(st_data_t key, st_table *tab)
static st_index_t find_entry(st_table *tab, st_hash_t hash_value, st_data_t key)
#define PREFETCH(addr, write_p)
static st_index_t find_table_entry_ind(st_table *tab, st_hash_t hash_value, st_data_t key)
static st_index_t find_table_bin_ptr_and_reserve(st_table *tab, st_hash_t *hash_value, st_data_t key, st_index_t *bin_ind)
RUBY_SYMBOL_EXPORT_BEGIN typedef unsigned long st_data_t
int st_lookup(st_table *tab, st_data_t key, st_data_t *value)
st_table * st_init_strtable_with_size(st_index_t size)
st_table * st_init_strtable(void)
void st_free_table(st_table *tab)
#define SIZEOF_ST_INDEX_T
static st_index_t secondary_hash(st_index_t ind, st_table *tab, st_index_t *perterb)
st_table * st_init_strcasetable(void)
st_index_t st_hash_end(st_index_t h)
static void rebuild_table(st_table *tab)
size_t st_memsize(const st_table *tab)
static st_index_t find_table_bin_ind_direct(st_table *table, st_hash_t hash_value, st_data_t key)
#define UNALIGNED_ADD_ALL
static st_index_t murmur_finish(st_index_t h)
#define EXPECT(expr, val)
#define UNDEFINED_ENTRY_IND
int st_foreach(st_table *tab, int(*func)(ANYARGS), st_data_t arg)
static st_index_t get_allocated_entries(const st_table *tab)
static st_index_t strhash(st_data_t)
#define RESERVED_HASH_VAL
#define IND_EMPTY_BIN_P(tab, i)
st_index_t st_keys(st_table *tab, st_data_t *keys, st_index_t size)
static void make_tab_empty(st_table *tab)
#define MEMCPY(p1, p2, type, n)
st_index_t(* hash)(ANYARGS)
#define MAX_POWER2_FOR_TABLES_WITHOUT_BINS
static st_index_t find_table_bin_ind(st_table *tab, st_hash_t hash_value, st_data_t key)
unsigned int rebuilds_num
st_index_t st_hash(const void *ptr, size_t len, st_index_t h)
st_index_t st_keys_check(st_table *tab, st_data_t *keys, st_index_t size, st_data_t never ATTRIBUTE_UNUSED)
static const struct st_hash_type type_strcasehash
#define MARK_BIN_DELETED(tab, i)
static void rebuild_table_if_necessary(st_table *tab)
st_index_t st_values(st_table *tab, st_data_t *values, st_index_t size)
static int get_power2(st_index_t size)
#define MARK_ENTRY_DELETED(e_ptr)
int st_delete(st_table *tab, st_data_t *key, st_data_t *value)
static st_index_t hash_bin(st_hash_t hash_value, st_table *tab)
int st_shift(st_table *tab, st_data_t *key, st_data_t *value)
#define REBUILD_THRESHOLD
register unsigned int len
unsigned char entry_power
st_table * st_copy(st_table *old_tab)
int st_insert(st_table *tab, st_data_t key, st_data_t value)
static void st_add_direct_with_hash(st_table *tab, st_data_t key, st_data_t value, st_hash_t hash)
int st_locale_insensitive_strncasecmp(const char *s1, const char *s2, size_t n)
const struct st_hash_type * type
int st_delete_safe(st_table *tab, st_data_t *key, st_data_t *value, st_data_t never ATTRIBUTE_UNUSED)
static st_index_t st_general_values(st_table *tab, st_data_t *values, st_index_t size)
int st_numcmp(st_data_t x, st_data_t y)
st_index_t st_values_check(st_table *tab, st_data_t *values, st_index_t size, st_data_t never ATTRIBUTE_UNUSED)
static void update_range_for_deleted(st_table *tab, st_index_t n)
void st_clear(st_table *tab)
static unsigned int get_size_ind(const st_table *tab)
static int st_general_foreach(st_table *tab, int(*func)(ANYARGS), st_data_t arg, int check_p)
const struct st_hash_type st_hashtype_num
#define UNDEFINED_BIN_IND
struct st_table_entry st_table_entry
static st_index_t strcasehash(st_data_t)
#define MARK_BIN_EMPTY(tab, i)
st_index_t st_hash_uint(st_index_t h, st_index_t i)
void st_cleanup_safe(st_table *tab ATTRIBUTE_UNUSED, st_data_t never ATTRIBUTE_UNUSED)
int st_update_callback_func(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
#define DELETED_ENTRY_P(e_ptr)
st_table * st_init_table(const struct st_hash_type *type)
st_table * st_init_numtable_with_size(st_index_t size)
#define EMPTY_OR_DELETED_BIN_P(b)
int st_get_key(st_table *tab, st_data_t key, st_data_t *result)