Project

General

Profile

base.patch

vmakarov (Vladimir Makarov), 04/29/2016 09:55 PM

Download (93.8 KB)

View differences:

benchmark/bm_hash_aref_dsym.rb
1 1
h = {}
2 2
syms = ('a'..'z').map { |s| s.to_sym }
3 3
syms.each { |s| h[s] = 1 }
4
200_000.times { syms.each { |s| h[s] } }
4
400_000.times { syms.each { |s| h[s] } }
benchmark/bm_hash_aref_dsym_long.rb
16 16
rng = Random.new(0)
17 17
symbol_sample_array = values.sample(sample_size, random: rng).map(&:to_sym)
18 18

  
19
3000.times do
19
1000.times do
20 20
  symbol_sample_array.each { |x| symbol_hash[x] }
21 21
end
benchmark/bm_hash_aref_fix.rb
1 1
h = {}
2 2
nums = (1..26).to_a
3 3
nums.each { |i| h[i] = i }
4
200_000.times { nums.each { |s| h[s] } }
4
800_000.times { nums.each { |s| h[s] } }
benchmark/bm_hash_aref_flo.rb
1 1
h = {}
2 2
strs = [*1..10000].map! {|i| i.fdiv(10)}
3 3
strs.each { |s| h[s] = s }
4
50.times { strs.each { |s| h[s] } }
4
500.times { strs.each { |s| h[s] } }
benchmark/bm_hash_aref_miss.rb
2 2
strs = ('a'..'z').to_a.map!(&:freeze)
3 3
strs.each { |s| h[s] = s }
4 4
strs = ('A'..'Z').to_a
5
200_000.times { strs.each { |s| h[s] } }
5
500_000.times { strs.each { |s| h[s] } }
benchmark/bm_hash_aref_str.rb
1 1
h = {}
2 2
strs = ('a'..'z').to_a.map!(&:freeze)
3 3
strs.each { |s| h[s] = s }
4
200_000.times { strs.each { |s| h[s] } }
4
500_000.times { strs.each { |s| h[s] } }
benchmark/bm_hash_aref_sym.rb
6 6
  syms.map!(&:to_sym)
7 7
end
8 8
syms.each { |s| h[s] = s }
9
200_000.times { syms.each { |s| h[s] } }
9
500_000.times { syms.each { |s| h[s] } }
benchmark/bm_hash_aref_sym_long.rb
10 10
  syms.map!(&:to_sym)
11 11
end
12 12
syms.each { |s| h[s] = s }
13
200_000.times { syms.each { |s| h[s] } }
13
500_000.times { syms.each { |s| h[s] } }
benchmark/bm_hash_flatten.rb
4 4
  h[i] = nil
5 5
end
6 6

  
7
1000.times do
7
2000.times do
8 8
  h.flatten
9 9
end
benchmark/bm_hash_ident_flo.rb
1 1
h = {}.compare_by_identity
2 2
strs = (1..10000).to_a.map!(&:to_f)
3 3
strs.each { |s| h[s] = s }
4
50.times { strs.each { |s| h[s] } }
4
500.times { strs.each { |s| h[s] } }
benchmark/bm_hash_ident_num.rb
1 1
h = {}.compare_by_identity
2 2
nums = (1..26).to_a
3 3
nums.each { |n| h[n] = n }
4
200_000.times { nums.each { |n| h[n] } }
4
500_000.times { nums.each { |n| h[n] } }
benchmark/bm_hash_ident_obj.rb
1 1
h = {}.compare_by_identity
2 2
objs = 26.times.map { Object.new }
3 3
objs.each { |o| h[o] = o }
4
200_000.times { objs.each { |o| h[o] } }
4
500_000.times { objs.each { |o| h[o] } }
benchmark/bm_hash_ident_str.rb
1 1
h = {}.compare_by_identity
2 2
strs = ('a'..'z').to_a
3 3
strs.each { |s| h[s] = s }
4
200_000.times { strs.each { |s| h[s] } }
4
500_000.times { strs.each { |s| h[s] } }
benchmark/bm_hash_ident_sym.rb
1 1
h = {}.compare_by_identity
2 2
syms = ('a'..'z').to_a.map(&:to_sym)
3 3
syms.each { |s| h[s] = s }
4
200_000.times { syms.each { |s| h[s] } }
4
500_000.times { syms.each { |s| h[s] } }
benchmark/bm_hash_keys.rb
4 4
  h[i] = nil
5 5
end
6 6

  
7
5000.times do
7
10000.times do
8 8
  h.keys
9 9
end
benchmark/bm_hash_shift.rb
4 4
  h[i] = nil
5 5
end
6 6

  
7
50000.times do
7
1000000.times do
8 8
  k, v = h.shift
9 9
  h[k] = v
10 10
end
benchmark/bm_hash_shift_u16.rb
4 4
  h[i] = nil
5 5
end
6 6

  
7
300000.times do
7
1000000.times do
8 8
  k, v = h.shift
9 9
  h[k] = v
10 10
end
benchmark/bm_hash_shift_u24.rb
4 4
  h[i] = nil
5 5
end
6 6

  
7
300000.times do
7
1000000.times do
8 8
  k, v = h.shift
9 9
  h[k] = v
10 10
end
benchmark/bm_hash_shift_u32.rb
4 4
  h[i] = nil
5 5
end
6 6

  
7
300000.times do
7
1000000.times do
8 8
  k, v = h.shift
9 9
  h[k] = v
10 10
end
benchmark/bm_hash_to_proc.rb
4 4
  h[i] = nil
5 5
end
6 6

  
7
5000.times do |i|
7
500000.times do |i|
8 8
  [i].map(&h)
9 9
end
benchmark/bm_hash_values.rb
4 4
  h[i] = nil
5 5
end
6 6

  
7
5000.times do
7
10000.times do
8 8
  h.values
9 9
end
ext/-test-/st/foreach/foreach.c
14 14
    if (c->nr == 0) {
15 15
	st_data_t i;
16 16

  
17
	if (!c->tbl->entries_packed) rb_bug("should be packed\n");
17
	if (c->tbl->bins != NULL) rb_bug("should be packed\n");
18 18

  
19 19
	/* force unpacking during iteration: */
20 20
	for (i = 1; i < expect_size; i++)
21 21
	    st_add_direct(c->tbl, i, i);
22 22

  
23
	if (c->tbl->entries_packed) rb_bug("should be unpacked\n");
23
	if (c->tbl->bins == NULL) rb_bug("should be unpacked\n");
24 24
    }
25 25

  
26 26
    if (key != c->nr) {
......
84 84

  
85 85
    st_add_direct(tbl, 0, 0);
86 86

  
87
    if (!tbl->entries_packed) rb_bug("should still be packed\n");
87
    if (tbl->bins != NULL) rb_bug("should still be packed\n");
88 88

  
89 89
    st_foreach_check(tbl, unp_fec_i, (st_data_t)&c, -1);
90 90

  
......
98 98
		(VALUE)c.nr, (VALUE)expect_size);
99 99
    }
100 100

  
101
    if (tbl->entries_packed) rb_bug("should be unpacked\n");
101
    if (tbl->bins == NULL) rb_bug("should be unpacked\n");
102 102

  
103 103
    st_free_table(tbl);
104 104

  
......
145 145

  
146 146
    st_add_direct(tbl, 0, 0);
147 147

  
148
    if (!tbl->entries_packed) rb_bug("should still be packed\n");
148
    if (tbl->bins != NULL) rb_bug("should still be packed\n");
149 149

  
150 150
    st_foreach(tbl, unp_fe_i, (st_data_t)&c);
151 151

  
......
159 159
		(VALUE)c.nr, (VALUE)expect_size);
160 160
    }
161 161

  
162
    if (tbl->entries_packed) rb_bug("should be unpacked\n");
162
    if (tbl->bins == NULL) rb_bug("should be unpacked\n");
163 163

  
164 164
    st_free_table(tbl);
165 165

  
include/ruby/st.h
1
/* This is a public domain general purpose hash table package written by Peter Moore @ UCB. */
1
/* This is a public domain general purpose hash table package
2
   originally written by Peter Moore @ UCB.
2 3

  
3
/* @(#) st.h 5.1 89/12/14 */
4
   The hash table data strutures were redesigned and the package was
5
   rewritten by Vladimir Makarov <vmakarov@redhat.com>.  */
4 6

  
5 7
#ifndef RUBY_ST_H
6 8
#define RUBY_ST_H 1
......
46 48
typedef struct st_table st_table;
47 49

  
48 50
typedef st_data_t st_index_t;
51

  
52
/* Maximal value of unsigned integer type st_index_t.  */
53
#define MAX_ST_INDEX_VAL (~(st_index_t) 0)
54
  
49 55
typedef int st_compare_func(st_data_t, st_data_t);
50 56
typedef st_index_t st_hash_func(st_data_t);
51 57

  
......
57 63
    st_index_t (*hash)(ANYARGS /*st_data_t*/);        /* st_hash_func* */
58 64
};
59 65

  
60
#define ST_INDEX_BITS (sizeof(st_index_t) * CHAR_BIT)
61

  
62 66
#if defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR) && defined(HAVE_BUILTIN___BUILTIN_TYPES_COMPATIBLE_P)
63 67
# define ST_DATA_COMPATIBLE_P(type) \
64 68
   __builtin_choose_expr(__builtin_types_compatible_p(type, st_data_t), 1, 0)
......
66 70
# define ST_DATA_COMPATIBLE_P(type) 0
67 71
#endif
68 72

  
73
typedef struct st_table_entry st_table_entry;
74

  
75
struct st_table_entry; /* defined in st.c */
76

  
69 77
struct st_table {
78
    /* Cached features of the table -- see st.c for more details.  */
79
    unsigned char entry_power, bin_power, size_ind;
80
    /* How many times the table was rebuilt.  */
81
    unsigned int rebuilds_num;
70 82
    const struct st_hash_type *type;
71
    st_index_t num_bins;
72
    unsigned int entries_packed : 1;
73
#ifdef __GNUC__
74
    /*
75
     * C spec says,
76
     *   A bit-field shall have a type that is a qualified or unqualified
77
     *   version of _Bool, signed int, unsigned int, or some other
78
     *   implementation-defined type. It is implementation-defined whether
79
     *   atomic types are permitted.
80
     * In short, long and long long bit-field are implementation-defined
81
     * feature. Therefore we want to suppress a warning explicitly.
82
     */
83
    __extension__
84
#endif
85
    st_index_t num_entries : ST_INDEX_BITS - 1;
86
    union {
87
	struct {
88
	    struct st_table_entry **bins;
89
	    void *private_list_head[2];
90
	} big;
91
	struct {
92
	    struct st_packed_entry *entries;
93
	    st_index_t real_entries;
94
	} packed;
95
    } as;
83
    /* Number of entries currently in the table.  */
84
    st_index_t num_entries;
85
    /* Array of bins used for access by keys.  */
86
    st_index_t *bins;
87
    /* Start and bound index of entries in array entries.
88
       entries_starts and entries_bound are in interval
89
       [0,allocated_entries].  */
90
    st_index_t entries_start, entries_bound;
91
    /* Array of size 2^entry_power.  */
92
    st_table_entry *entries;
96 93
};
97 94

  
98 95
#define st_is_member(table,key) st_lookup((table),(key),(st_data_t *)0)
......
121 118
int st_update(st_table *table, st_data_t key, st_update_callback_func *func, st_data_t arg);
122 119
int st_foreach(st_table *, int (*)(ANYARGS), st_data_t);
123 120
int st_foreach_check(st_table *, int (*)(ANYARGS), st_data_t, st_data_t);
124
int st_reverse_foreach(st_table *, int (*)(ANYARGS), st_data_t);
125 121
st_index_t st_keys(st_table *table, st_data_t *keys, st_index_t size);
126 122
st_index_t st_keys_check(st_table *table, st_data_t *keys, st_index_t size, st_data_t never);
127 123
st_index_t st_values(st_table *table, st_data_t *values, st_index_t size);
128 124
st_index_t st_values_check(st_table *table, st_data_t *values, st_index_t size, st_data_t never);
129 125
void st_add_direct(st_table *, st_data_t, st_data_t);
130 126
void st_free_table(st_table *);
127
size_t st_memsize(const st_table *);
131 128
void st_cleanup_safe(st_table *, st_data_t);
132 129
void st_clear(st_table *);
133 130
st_table *st_copy(st_table *);
......
137 134
int st_locale_insensitive_strncasecmp(const char *s1, const char *s2, size_t n);
138 135
#define st_strcasecmp st_locale_insensitive_strcasecmp
139 136
#define st_strncasecmp st_locale_insensitive_strncasecmp
140
size_t st_memsize(const st_table *);
141 137
st_index_t st_hash(const void *ptr, size_t len, st_index_t h);
142 138
st_index_t st_hash_uint32(st_index_t h, uint32_t i);
143 139
st_index_t st_hash_uint(st_index_t h, st_index_t i);
st.c
1
/* This is a public domain general purpose hash table package written by Peter Moore @ UCB. */
2

  
3
/* static	char	sccsid[] = "@(#) st.c 5.1 89/12/14 Crucible"; */
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
   This implementation speeds up the Ruby hash table benchmarks in
94
   average by more 40% on Intel Haswell CPU.
95

  
96
*/
4 97

  
5 98
#ifdef NOT_RUBY
6 99
#include "regint.h"
......
14 107
#include <stdlib.h>
15 108
#endif
16 109
#include <string.h>
17
#include "ccan/list/list.h"
110
#include <assert.h>
111

  
112
#ifdef __GNUC__
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))
116
#else
117
#define PREFETCH(addr, write_p)
118
#define EXPECT(expr, val) (expr)
119
#define ATTRIBUTE_UNUSED
120
#endif
121

  
122
#ifdef ST_DEBUG
123
#define st_assert(cond) assert(cond)
124
#else
125
#define st_assert(cond) ((void)(0 && (cond)))
126
#endif
18 127

  
19
typedef struct st_table_entry st_table_entry;
128
/* The type of hashes.  */
129
typedef st_index_t st_hash_t;
20 130

  
21 131
struct st_table_entry {
22
    st_index_t hash;
132
    st_hash_t hash;
23 133
    st_data_t key;
24 134
    st_data_t record;
25
    st_table_entry *next;
26
    struct list_node olist;
27 135
};
28 136

  
29
typedef struct st_packed_entry {
30
    st_index_t hash;
31
    st_data_t key, val;
32
} st_packed_entry;
33

  
34
#ifndef STATIC_ASSERT
35
#define STATIC_ASSERT(name, expr) typedef int static_assert_##name##_check[(expr) ? 1 : -1]
36
#endif
37

  
38
#define ST_DEFAULT_MAX_DENSITY 5
39
#define ST_DEFAULT_INIT_TABLE_SIZE 16
40
#define ST_DEFAULT_PACKED_TABLE_SIZE 18
41
#define PACKED_UNIT (int)(sizeof(st_packed_entry) / sizeof(st_table_entry*))
42
#define MAX_PACKED_HASH (int)(ST_DEFAULT_PACKED_TABLE_SIZE * sizeof(st_table_entry*) / sizeof(st_packed_entry))
43

  
44
STATIC_ASSERT(st_packed_entry, sizeof(st_packed_entry) == sizeof(st_table_entry*[PACKED_UNIT]));
45
STATIC_ASSERT(st_packed_bins, sizeof(st_packed_entry[MAX_PACKED_HASH]) <= sizeof(st_table_entry*[ST_DEFAULT_PACKED_TABLE_SIZE]));
46

  
47
    /*
48
     * DEFAULT_MAX_DENSITY is the default for the largest we allow the
49
     * average number of items per bin before increasing the number of
50
     * bins
51
     *
52
     * DEFAULT_INIT_TABLE_SIZE is the default for the number of bins
53
     * allocated initially
54
     *
55
     */
56

  
57 137
#define type_numhash st_hashtype_num
58 138
const struct st_hash_type st_hashtype_num = {
59 139
    st_numcmp,
......
73 153
    strcasehash,
74 154
};
75 155

  
76
static void rehash(st_table *);
156
/* Value used to catch uninitialized entries/bins during debugging.
157
   There is a possibility for a false alarm, but its probability is
158
   extremely small.  */
159
#define ST_INIT_VAL 0xafafafafafafafaf
160
#define ST_INIT_VAL_BYTE 0xafa
77 161

  
78 162
#ifdef RUBY
79 163
#undef malloc
80 164
#undef realloc
81 165
#undef calloc
82 166
#undef free
83
#define malloc xmalloc
84
#define calloc xcalloc
85
#define realloc xrealloc
86
#define free(x) xfree(x)
87
#endif
88

  
89
#define EQUAL(table,x,ent) ((x)==(ent)->key || (*(table)->type->compare)((x),(ent)->key) == 0)
90

  
91
#define do_hash(key,table) (st_index_t)(*(table)->type->hash)((key))
92
#define hash_pos(h,n) ((h) & (n - 1))
93

  
94
/* preparation for possible allocation improvements */
95
#define st_alloc_entry() (st_table_entry *)malloc(sizeof(st_table_entry))
96
#define st_free_entry(entry) free(entry)
97
#define st_alloc_table() (st_table *)malloc(sizeof(st_table))
98
#define st_dealloc_table(table) free(table)
99
#define st_alloc_bins(size) (st_table_entry **)calloc(size, sizeof(st_table_entry *))
100
#define st_free_bins(bins, size) free(bins)
101
static inline st_table_entry**
102
st_realloc_bins(st_table_entry **bins, st_index_t newsize, st_index_t oldsize)
103
{
104
    bins = (st_table_entry **)realloc(bins, newsize * sizeof(st_table_entry *));
105
    MEMZERO(bins, st_table_entry*, newsize);
106
    return bins;
107
}
108

  
109
/* Shortcut */
110
#define bins as.big.bins
111
#define real_entries as.packed.real_entries
112

  
113
/* preparation for possible packing improvements */
114
#define PACKED_BINS(table) ((table)->as.packed.entries)
115
#define PACKED_ENT(table, i) PACKED_BINS(table)[i]
116
#define PKEY(table, i) PACKED_ENT((table), (i)).key
117
#define PVAL(table, i) PACKED_ENT((table), (i)).val
118
#define PHASH(table, i) PACKED_ENT((table), (i)).hash
119
#define PKEY_SET(table, i, v) (PKEY((table), (i)) = (v))
120
#define PVAL_SET(table, i, v) (PVAL((table), (i)) = (v))
121
#define PHASH_SET(table, i, v) (PHASH((table), (i)) = (v))
122

  
123
/* this function depends much on packed layout, so that it placed here */
124
static inline void
125
remove_packed_entry(st_table *table, st_index_t i)
126
{
127
    table->real_entries--;
128
    table->num_entries--;
129
    if (i < table->real_entries) {
130
	MEMMOVE(&PACKED_ENT(table, i), &PACKED_ENT(table, i+1),
131
		st_packed_entry, table->real_entries - i);
132
    }
133
}
167
#define malloc ruby_xmalloc
168
#define calloc ruby_xcalloc
169
#define realloc ruby_xrealloc
170
#define free ruby_xfree
171
#endif
134 172

  
135
static inline void
136
remove_safe_packed_entry(st_table *table, st_index_t i, st_data_t never)
137
{
138
    table->num_entries--;
139
    PKEY_SET(table, i, never);
140
    PVAL_SET(table, i, never);
141
    PHASH_SET(table, i, 0);
142
}
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))
176

  
177
/* Features of a table.  */
178
struct st_features {
179
    /* Power of 2 used for number of allocated entries.  */
180
    unsigned char entry_power;
181
    /* Power of 2 used for number of allocated bins.  Depending on the
182
       table size, the number of bins is 2-4 times more than the
183
       number of entries.  */
184
    unsigned char bin_power;
185
    /* Enumeration of sizes of bins (8-bit, 16-bit etc).  */
186
    unsigned char size_ind;
187
    /* Bins are packed in words of type st_index_t.  The following is
188
       a size of bins counted by words.  */
189
    st_index_t bins_words;
190
};
143 191

  
144
static st_index_t
145
next_pow2(st_index_t x)
146
{
147
    x |= x >> 1;
148
    x |= x >> 2;
149
    x |= x >> 4;
150
    x |= x >> 8;
151
    x |= x >> 16;
192
/* Features of all possible size tables.  */
152 193
#if SIZEOF_ST_INDEX_T == 8
153
    x |= x >> 32;
194
#define MAX_POWER2 62
195
struct st_features features[] = {
196
    {0, 2, 0, 0x0},
197
    {1, 3, 0, 0x1},
198
    {2, 4, 0, 0x2},
199
    {3, 5, 0, 0x4},
200
    {4, 6, 0, 0x8},
201
    {5, 7, 0, 0x10},
202
    {6, 8, 0, 0x20},
203
    {7, 9, 0, 0x40},
204
    {8, 10, 1, 0x100},
205
    {9, 11, 1, 0x200},
206
    {10, 12, 1, 0x400},
207
    {11, 13, 1, 0x800},
208
    {12, 14, 1, 0x1000},
209
    {13, 15, 1, 0x2000},
210
    {14, 16, 1, 0x4000},
211
    {15, 17, 1, 0x8000},
212
    {16, 18, 2, 0x20000},
213
    {17, 19, 2, 0x40000},
214
    {18, 20, 2, 0x80000},
215
    {19, 21, 2, 0x100000},
216
    {20, 22, 2, 0x200000},
217
    {21, 23, 2, 0x400000},
218
    {22, 24, 2, 0x800000},
219
    {23, 25, 2, 0x1000000},
220
    {24, 26, 2, 0x2000000},
221
    {25, 27, 2, 0x4000000},
222
    {26, 28, 2, 0x8000000},
223
    {27, 29, 2, 0x10000000},
224
    {28, 30, 2, 0x20000000},
225
    {29, 31, 2, 0x40000000},
226
    {30, 32, 2, 0x80000000},
227
    {31, 33, 2, 0x100000000},
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},
259
};
260

  
261
#else
262
#define MAX_POWER2 30
263

  
264
struct st_features features[] = {
265
    {0, 2, 0, 0x1},
266
    {1, 3, 0, 0x2},
267
    {2, 4, 0, 0x4},
268
    {3, 5, 0, 0x8},
269
    {4, 6, 0, 0x10},
270
    {5, 7, 0, 0x20},
271
    {6, 8, 0, 0x40},
272
    {7, 9, 0, 0x80},
273
    {8, 10, 1, 0x200},
274
    {9, 11, 1, 0x400},
275
    {10, 12, 1, 0x800},
276
    {11, 13, 1, 0x1000},
277
    {12, 14, 1, 0x2000},
278
    {13, 15, 1, 0x4000},
279
    {14, 16, 1, 0x8000},
280
    {15, 17, 1, 0x10000},
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},
296
};
297

  
298
#endif
299

  
300
/* The reserved hash value and its substitution.  */
301
#define RESERVED_HASH_VAL (~(st_hash_t) 0)
302
#define RESERVED_HASH_SUBSTITUTION_VAL ((st_hash_t) 0)
303

  
304
/* Return hash value of KEY for table TAB.  */
305
static inline st_hash_t
306
do_hash(st_data_t key, st_table *tab) {
307
    st_index_t h = (st_index_t)(tab->type->hash)(key);
308
#if SIZEOF_INT == SIZEOF_VOIDP
309
    st_hash_t hash = h;
310
#else
311
    st_hash_t hash = h;
154 312
#endif
155
    return x + 1;
313

  
314
    /* RESERVED_HASH_VAL is used for a deleted entry.  Map it into
315
       another value.  Such mapping should be extremely rare.  */
316
    return hash == RESERVED_HASH_VAL ? RESERVED_HASH_SUBSTITUTION_VAL : hash;
156 317
}
157 318

  
158
static st_index_t
159
new_size(st_index_t size)
160
{
161
    st_index_t n;
319
/* Power of 2 defining the minimal number of allocated entries.  */
320
#define MINIMAL_POWER2 3
321

  
322
#if MINIMAL_POWER2 < 2
323
#error "MINIMAL_POWER2 should be >= 2"
324
#endif
325

  
326
/* If the power2 of the allocated `entries` is less than the following
327
   value, don't allocate bins and use a linear search.  */
328
#define MAX_POWER2_FOR_TABLES_WITHOUT_BINS 3
162 329

  
163
    if (size && (size & ~(size - 1)) == size) /* already a power-of-two? */
164
	return size;
330
/* Return smallest n >= MINIMAL_POWER2 such 2^n > SIZE.  */
331
static int
332
get_power2(st_index_t size) {
333
    unsigned int n;
165 334

  
166
    n = next_pow2(size);
167
    if (n > size)
168
	return n;
335
    for (n = 0; size != 0; n++)
336
        size >>= 1;
337
    if (n <= MAX_POWER2)
338
        return n < MINIMAL_POWER2 ? MINIMAL_POWER2 : n;
169 339
#ifndef NOT_RUBY
340
    /* Ran out of the table entries */
170 341
    rb_raise(rb_eRuntimeError, "st_table too big");
171 342
#endif
172
    return -1;			/* should raise exception */
343
    /* should raise exception */
344
    return -1;
345
}
346

  
347
/* Return value of N-th bin in array BINS of table with bins size
348
   index S.  */
349
static inline st_index_t
350
get_bin(st_index_t *bins, int s, st_index_t n) {
351
  return (s == 0 ? ((unsigned char *) bins)[n]
352
	  : s == 1 ? ((unsigned short *) bins)[n]
353
	  : s == 2 ? ((unsigned int *) bins)[n]
354
	  : ((st_index_t *) bins)[n]);
355
}
356

  
357
/* Set up N-th bin in array BINS of table with bins size index S to
358
   value V.  */
359
static inline void
360
set_bin(st_index_t *bins, int s, st_index_t n, st_index_t v) {
361
    if (s == 0) ((unsigned char *) bins)[n] = v;
362
    else if (s == 1) ((unsigned short *) bins)[n] = v;
363
    else if (s == 2) ((unsigned int *) bins)[n] = v;
364
    else ((st_index_t *) bins)[n] = v;
365
}
366

  
367
/* These macros define reserved values for empty table bin and table
368
   bin which contains a deleted entry.  We will never use such values
369
   for an entry index in bins.  */
370
#define EMPTY_BIN    0
371
#define DELETED_BIN  1
372
/* Base of a real entry index in the bins.  */
373
#define ENTRY_BASE 2
374

  
375
/* Mark I-th bin of table TAB as empty, in other words not
376
   corresponding to any entry.  */
377
#define MARK_BIN_EMPTY(tab, i) (set_bin((tab)->bins, get_size_ind(tab), i, EMPTY_BIN))
378

  
379
/* Values used for not found entry and bin with given
380
   characteristics.  */
381
#define UNDEFINED_ENTRY_IND (~(st_index_t) 0)
382
#define UNDEFINED_BIN_IND (~(st_index_t) 0)
383

  
384
/* Mark I-th bin of table TAB as corresponding to a deleted table
385
   entry.  Update number of entries in the table and number of bins
386
   corresponding to deleted entries. */
387
#define MARK_BIN_DELETED(tab, i)				\
388
    do {                                                        \
389
        st_assert(i != UNDEFINED_BIN_IND);			\
390
	st_assert(! IND_EMPTY_OR_DELETED_BIN_P(tab, i)); 	\
391
        set_bin((tab)->bins, get_size_ind(tab), i, DELETED_BIN); \
392
    } while (0)
393

  
394
/* Macros to check that value B is used empty bins and bins
395
   corresponding deleted entries.  */
396
#define EMPTY_BIN_P(b) ((b) == EMPTY_BIN)
397
#define DELETED_BIN_P(b) ((b) == DELETED_BIN)
398
#define EMPTY_OR_DELETED_BIN_P(b) ((b) <= DELETED_BIN)
399

  
400
/* Macros to check empty bins and bins corresponding to deleted
401
   entries.  Bins are given by their index I in table TAB.  */
402
#define IND_EMPTY_BIN_P(tab, i) (EMPTY_BIN_P(get_bin((tab)->bins, get_size_ind(tab), i)))
403
#define IND_DELETED_BIN_P(tab, i) (DELETED_BIN_P(get_bin((tab)->bins, get_size_ind(tab), i)))
404
#define IND_EMPTY_OR_DELETED_BIN_P(tab, i) (EMPTY_OR_DELETED_BIN_P(get_bin((tab)->bins, get_size_ind(tab), i)))
405

  
406
/* Macros for marking and checking deleted entries given by their
407
   pointer E_PTR.  */
408
#define MARK_ENTRY_DELETED(e_ptr) ((e_ptr)->hash = RESERVED_HASH_VAL)
409
#define DELETED_ENTRY_P(e_ptr) ((e_ptr)->hash == RESERVED_HASH_VAL)
410

  
411
/* Return bin size index of table TAB.  */
412
static inline st_index_t
413
get_size_ind(const st_table *tab) {
414
    return tab->size_ind;
415
}
416

  
417
/* Return the number of allocated bins of table TAB.  */
418
static inline st_index_t
419
get_bins_num(const st_table *tab) {
420
    return 1<<tab->bin_power;
421
}
422

  
423
/* Return mask for a bin index in table TAB.  */
424
static inline st_index_t
425
bins_mask(const st_table *tab) {
426
    return get_bins_num(tab) - 1;
427
}
428

  
429
/* Return the index of table TAB bin corresponding to
430
   HASH_VALUE.  */
431
static inline st_index_t
432
hash_bin(st_hash_t hash_value, st_table *tab) {
433
    return hash_value & bins_mask(tab);
434
}
435

  
436
/* Return the number of allocated entries of table TAB.  */
437
static inline st_index_t
438
get_allocated_entries(const st_table *tab) {
439
    return 1<<tab->entry_power;
440
}
441

  
442
/* Return size of the allocated bins of table TAB.  */
443
static inline st_index_t
444
bins_size(const st_table *tab) {
445
    return features[tab->entry_power].bins_words * sizeof (st_index_t);
446
}
447

  
448
/* Mark all bins of table TAB as empty.  */
449
static void
450
initialize_bins(st_table *tab) {
451
    memset(tab->bins, 0, bins_size(tab));
452
}
453

  
454
/* Make table TAB empty.  */
455
static void
456
make_tab_empty(st_table *tab)
457
{
458
    tab->num_entries = 0;
459
    tab->entries_start = tab->entries_bound = 0;
460
    if (tab->bins != NULL)
461
        initialize_bins(tab);
462
}
463

  
464
#ifdef ST_DEBUG
465
/* Check the table T consistency.  It can be extremely slow.  So use
466
   it only for debugging.  */
467
static void
468
st_check(st_table *tab) {
469
    st_index_t d, e, i, n, p;
470

  
471
    for (p = get_allocated_entries(tab), i = 0; p > 1; i++, p>>=1)
472
        ;
473
    p = i;
474
    assert(p >= MINIMAL_POWER2);
475
    assert(tab->entries_bound <= get_allocated_entries(tab)
476
	   && tab->entries_start <= tab->entries_bound);
477
    n = 0;
478
    return;
479
    if (tab->entries_bound != 0)
480
        for (i = tab->entries_start; i < tab->entries_bound; i++) {
481
  	    assert(tab->entries[i].hash != (st_hash_t) ST_INIT_VAL
482
		   && tab->entries[i].key != ST_INIT_VAL
483
		   && tab->entries[i].record != ST_INIT_VAL);
484
	    if (! DELETED_ENTRY_P(&tab->entries[i]))
485
	        n++;
486
	}
487
    assert(n == tab->num_entries);
488
    if (tab->bins == NULL)
489
        assert(p <= MAX_POWER2_FOR_TABLES_WITHOUT_BINS);
490
    else {
491
        assert(p > MAX_POWER2_FOR_TABLES_WITHOUT_BINS);
492
	for (n = d = i = 0; i < get_bins_num(tab); i++) {
493
  	    assert(get_bin(tab->bins, tab->size_ind, i) != ST_INIT_VAL);
494
	    if (IND_DELETED_BIN_P(tab, i)) {
495
	        d++;
496
		continue;
497
	    }
498
	    else if (IND_EMPTY_BIN_P(tab, i))
499
	        continue;
500
	    n++;
501
	    e = get_bin(tab->bins, tab->size_ind, i) - ENTRY_BASE;
502
	    assert(tab->entries_start <= e && e < tab->entries_bound);
503
	    assert(! DELETED_ENTRY_P(&tab->entries[e]));
504
	    assert(tab->entries[e].hash != (st_hash_t) ST_INIT_VAL
505
		   && tab->entries[e].key != ST_INIT_VAL
506
		   && tab->entries[e].record != ST_INIT_VAL);
507
	}
508
	assert(n == tab->num_entries);
509
	assert(n + d < get_bins_num(tab));
510
    }
173 511
}
512
#endif
174 513

  
175 514
#ifdef HASH_LOG
176 515
#ifdef HAVE_UNISTD_H
......
179 518
static struct {
180 519
    int all, total, num, str, strcase;
181 520
}  collision;
521

  
522
/* Flag switching off output of package statistics at the end of
523
   program.  */
182 524
static int init_st = 0;
183 525

  
526
/* Output overall number of table searches and collisions into a
527
   temporary file.  */
184 528
static void
185 529
stat_col(void)
186 530
{
......
189 533
    if (!collision.total) return;
190 534
    f = fopen((snprintf(fname, sizeof(fname), "/tmp/col%ld", (long)getpid()), fname), "w");
191 535
    fprintf(f, "collision: %d / %d (%6.2f)\n", collision.all, collision.total,
192
	    ((double)collision.all / (collision.total)) * 100);
536
            ((double)collision.all / (collision.total)) * 100);
193 537
    fprintf(f, "num: %d, str: %d, strcase: %d\n", collision.num, collision.str, collision.strcase);
194 538
    fclose(f);
195 539
}
196 540
#endif
197 541

  
198
static struct list_head *
199
st_head(const st_table *tbl)
200
{
201
    uintptr_t addr = (uintptr_t)&tbl->as.big.private_list_head;
202
    return (struct list_head *)addr;
203
}
204

  
205
st_table*
206
st_init_table_with_size(const struct st_hash_type *type, st_index_t size)
207
{
208
    st_table *tbl;
209

  
542
/* Create and return table with TYPE which can hold at least SIZE
543
   entries.  The real number of entries which the table can hold is
544
   the nearest power of two for SIZE.  */
545
st_table *
546
st_init_table_with_size(const struct st_hash_type *type, st_index_t size) {
547
    st_table *tab;
548
    int n;
549
    
210 550
#ifdef HASH_LOG
211
# if HASH_LOG+0 < 0
551
#if HASH_LOG+0 < 0
212 552
    {
213
	const char *e = getenv("ST_HASH_LOG");
214
	if (!e || !*e) init_st = 1;
553
        const char *e = getenv("ST_HASH_LOG");
554
        if (!e || !*e) init_st = 1;
215 555
    }
216
# endif
556
#endif
217 557
    if (init_st == 0) {
218
	init_st = 1;
219
	atexit(stat_col);
558
        init_st = 1;
559
        atexit(stat_col);
220 560
    }
221 561
#endif
222

  
223

  
224
    tbl = st_alloc_table();
225
    tbl->type = type;
226
    tbl->num_entries = 0;
227
    tbl->entries_packed = size <= MAX_PACKED_HASH;
228
    if (tbl->entries_packed) {
229
	size = ST_DEFAULT_PACKED_TABLE_SIZE;
230
	tbl->real_entries = 0;
231
    }
232
    else {
233
	size = new_size(size);	/* round up to power-of-two */
234
	list_head_init(st_head(tbl));
235
    }
236
    tbl->num_bins = size;
237
    tbl->bins = st_alloc_bins(size);
238

  
239
    return tbl;
562
    
563
    n = get_power2(size);
564
    tab = (st_table *) malloc(sizeof (st_table));
565
    tab->type = type;
566
    tab->entry_power = n;
567
    tab->bin_power = features[n].bin_power;
568
    tab->size_ind = features[n].size_ind;
569
    if (n <= MAX_POWER2_FOR_TABLES_WITHOUT_BINS)
570
        tab->bins = NULL;
571
    else
572
        tab->bins = (st_index_t *) malloc(bins_size(tab));
573
    tab->entries = (st_table_entry *) malloc(get_allocated_entries(tab)
574
					     * sizeof(st_table_entry));
575
#ifdef ST_DEBUG
576
    memset(tab->entries, ST_INIT_VAL_BYTE,
577
	   get_allocated_entries(tab) * sizeof(st_table_entry));
578
    if (tab->bins != NULL)
579
        memset(tab->bins, ST_INIT_VAL_BYTE, bins_size(tab));
580
#endif
581
    make_tab_empty(tab);
582
    tab->rebuilds_num = 0;
583
#ifdef ST_DEBUG
584
    st_check(tab);
585
#endif
586
    return tab;
240 587
}
241 588

  
242
st_table*
243
st_init_table(const struct st_hash_type *type)
244
{
589
/* Create and return table with TYPE which can hold a minimal number
590
   of entries (see comments for get_power2).  */
591
st_table *
592
st_init_table(const struct st_hash_type *type) {
245 593
    return st_init_table_with_size(type, 0);
246 594
}
247 595

  
248
st_table*
249
st_init_numtable(void)
250
{
596
/* Create and return table which can hold a minimal number of
597
   numbers.  */
598
st_table *
599
st_init_numtable(void) {
251 600
    return st_init_table(&type_numhash);
252 601
}
253 602

  
254
st_table*
255
st_init_numtable_with_size(st_index_t size)
256
{
603
/* Create and return table which can hold SIZE numbers.  */
604
st_table *
605
st_init_numtable_with_size(st_index_t size) {
257 606
    return st_init_table_with_size(&type_numhash, size);
258 607
}
259 608

  
260
st_table*
261
st_init_strtable(void)
262
{
609
/* Create and return table which can hold a minimal number of
610
   strings.  */
611
st_table *
612
st_init_strtable(void) {
263 613
    return st_init_table(&type_strhash);
264 614
}
265 615

  
266
st_table*
267
st_init_strtable_with_size(st_index_t size)
268
{
616
/* Create and return table which can hold SIZE strings.  */
617
st_table *
618
st_init_strtable_with_size(st_index_t size) {
269 619
    return st_init_table_with_size(&type_strhash, size);
270 620
}
271 621

  
272
st_table*
273
st_init_strcasetable(void)
274
{
622
/* Create and return table which can hold a minimal number of strings
623
   whose character case is ignored.  */
624
st_table *
625
st_init_strcasetable(void) {
275 626
    return st_init_table(&type_strcasehash);
276 627
}
277 628

  
278
st_table*
279
st_init_strcasetable_with_size(st_index_t size)
280
{
629
/* Create and return table which can hold SIZE strings whose character
630
   case is ignored.  */
631
st_table *
632
st_init_strcasetable_with_size(st_index_t size) {
281 633
    return st_init_table_with_size(&type_strcasehash, size);
282 634
}
283 635

  
636
/* Make table TAB empty.  */
284 637
void
285
st_clear(st_table *table)
286
{
287
    register st_table_entry *ptr = 0, *next;
288

  
289
    if (table->entries_packed) {
290
        table->num_entries = 0;
291
        table->real_entries = 0;
292
        return;
293
    }
294

  
295
    list_for_each_safe(st_head(table), ptr, next, olist) {
296
	/* list_del is not needed */
297
	st_free_entry(ptr);
298
    }
299
    table->num_entries = 0;
300
    MEMZERO(table->bins, st_table_entry*, table->num_bins);
301
    list_head_init(st_head(table));
638
st_clear(st_table *tab) {
639
    make_tab_empty(tab);
640
    tab->rebuilds_num++;
641
#ifdef ST_DEBUG
642
    st_check(tab);
643
#endif
302 644
}
303 645

  
646
/* Free table TAB space.  */
304 647
void
305
st_free_table(st_table *table)
306
{
307
    st_clear(table);
308
    st_free_bins(table->bins, table->num_bins);
309
    st_dealloc_table(table);
648
st_free_table(st_table *tab) {
649
    if (tab->bins != NULL)
650
        free(tab->bins);
651
    free(tab->entries);
652
    free(tab);
310 653
}
311 654

  
655
/* Return byte size of memory allocted for table TAB.  */
312 656
size_t
313
st_memsize(const st_table *table)
314
{
315
    if (table->entries_packed) {
316
	return table->num_bins * sizeof (void *) + sizeof(st_table);
317
    }
318
    else {
319
	return table->num_entries * sizeof(struct st_table_entry) + table->num_bins * sizeof (void *) + sizeof(st_table);
320
    }
657
st_memsize(const st_table *tab) {
658
    return(sizeof(st_table)
659
           + (tab->bins == NULL ? 0 : bins_size(tab))
660
           + get_allocated_entries(tab) * sizeof(st_table_entry));
321 661
}
322 662

  
323
#define PTR_NOT_EQUAL(table, ptr, hash_val, key) \
324
((ptr) != 0 && ((ptr)->hash != (hash_val) || !EQUAL((table), (key), (ptr))))
663
static st_index_t
664
find_table_entry_ind(st_table *tab, st_hash_t hash_value, st_data_t key);
665

  
666
static st_index_t
667
find_table_bin_ind(st_table *tab, st_hash_t hash_value, st_data_t key);
668

  
669
static st_index_t
670
find_table_bin_ind_direct(st_table *table, st_hash_t hash_value, st_data_t key);
671

  
672
static st_index_t
673
find_table_bin_ptr_and_reserve(st_table *tab, st_hash_t *hash_value,
674
			       st_data_t key, st_index_t *bin_ind);
325 675

  
326 676
#ifdef HASH_LOG
327 677
static void
328
count_collision(const struct st_hash_type *type)
329
{
678
count_collision(const struct st_hash_type *type) {
330 679
    collision.all++;
331 680
    if (type == &type_numhash) {
332
	collision.num++;
681
        collision.num++;
333 682
    }
334 683
    else if (type == &type_strhash) {
335
	collision.strcase++;
684
        collision.strcase++;
336 685
    }
337 686
    else if (type == &type_strcasehash) {
338
	collision.str++;
687
        collision.str++;
339 688
    }
340 689
}
341
#define COLLISION (collision_check ? count_collision(table->type) : (void)0)
342
#define FOUND_ENTRY (collision_check ? collision.total++ : (void)0)
690

  
691
#define COLLISION (collision_check ? count_collision(tab->type) : (void)0)
692
#define FOUND_BIN (collision_check ? collision.total++ : (void)0)
343 693
#define collision_check 0
344 694
#else
345 695
#define COLLISION
346
#define FOUND_ENTRY
696
#define FOUND_BIN
347 697
#endif
348 698

  
349
#define FIND_ENTRY(table, ptr, hash_val, bin_pos) \
350
    ((ptr) = find_entry((table), key, (hash_val), ((bin_pos) = hash_pos(hash_val, (table)->num_bins))))
699
/* If the number of entries in the table is at least REBUILD_THRESHOLD
700
   times less than the entry array length, decrease the table
701
   size.  */
702
#define REBUILD_THRESHOLD 4
351 703

  
352
static st_table_entry *
353
find_entry(const st_table *table, st_data_t key, st_index_t hash_val,
354
           st_index_t bin_pos)
355
{
356
    register st_table_entry *ptr = table->bins[bin_pos];
357
    FOUND_ENTRY;
358
    if (PTR_NOT_EQUAL(table, ptr, hash_val, key)) {
359
	COLLISION;
360
	while (PTR_NOT_EQUAL(table, ptr->next, hash_val, key)) {
361
	    ptr = ptr->next;
362
	}
363
	ptr = ptr->next;
364
    }
365
    return ptr;
366
}
704
#if REBUILD_THRESHOLD < 2
705
#error "REBUILD_THRESHOLD should be >= 2"
706
#endif
367 707

  
368
static inline st_index_t
369
find_packed_index_from(const st_table *table, st_index_t hash_val,
370
		       st_data_t key, st_index_t i)
371
{
372
    while (i < table->real_entries &&
373
	   (PHASH(table, i) != hash_val || !EQUAL(table, key, &PACKED_ENT(table, i)))) {
374
	i++;
708
/* Rebuild table TAB.  Rebuilding removes all deleted bins and entries
709
   and can change size of the table entries and bins arrays.
710
   Rebuilding is implemented by creation of a new table or by
711
   compaction of the existing one.  */
712
static void
713
rebuild_table(st_table *tab) {
714
    st_index_t i, ni, bound, size_ind;
715
    st_table *new_tab;
716
    st_table_entry *entries, *new_entries;
717
    st_table_entry *curr_entry_ptr;
718
    st_index_t *bins;
719
    st_index_t bin_ind;
720
    
721
    st_assert(tab != NULL);
722
    bound = tab->entries_bound;
723
    entries = tab->entries;
724
    if ((2 * tab->num_entries <= get_allocated_entries(tab)
725
	 && REBUILD_THRESHOLD * tab->num_entries > get_allocated_entries(tab))
726
	|| tab->num_entries < (1 << MINIMAL_POWER2)) {
727
        /* Compaction: */
728
        tab->num_entries = 0;
729
	if (tab->bins != NULL)
730
	    initialize_bins(tab);
731
	new_tab = tab;
732
	new_entries = entries;
375 733
    }
376
    return i;
377
}
378

  
379
static inline st_index_t
380
find_packed_index(const st_table *table, st_index_t hash_val, st_data_t key)
381
{
382
    return find_packed_index_from(table, hash_val, key, 0);
734
    else {
735
        new_tab = st_init_table_with_size(tab->type,
736
					  2 * tab->num_entries - 1);
737
	new_entries = new_tab->entries;
738
    }
739
    ni = 0;
740
    bins = new_tab->bins;
741
    size_ind = get_size_ind(new_tab);
742
    for (i = tab->entries_start; i < bound; i++) {
743
        curr_entry_ptr = &entries[i];
744
	PREFETCH(entries + i + 1, 0);
745
	if (EXPECT(DELETED_ENTRY_P(curr_entry_ptr), 0))
746
	    continue;
747
	if (&new_entries[ni] != curr_entry_ptr)
748
	    new_entries[ni] = *curr_entry_ptr;
749
	if (EXPECT(bins != NULL, 1)) {
750
	    bin_ind = find_table_bin_ind_direct(new_tab, curr_entry_ptr->hash,
751
						curr_entry_ptr->key);
752
	    st_assert(bin_ind != UNDEFINED_BIN_IND
753
		      && (tab == new_tab || new_tab->rebuilds_num == 0)
754
		      && IND_EMPTY_BIN_P(new_tab, bin_ind));
755
	    set_bin(bins, size_ind, bin_ind, ni + ENTRY_BASE);
756
	}
757
	new_tab->num_entries++;
758
	ni++;
759
    }
760
    if (new_tab != tab) {
761
        tab->entry_power = new_tab->entry_power;
762
	tab->bin_power = new_tab->bin_power;
763
	tab->size_ind = new_tab->size_ind;
764
	st_assert (tab->num_entries == ni && new_tab->num_entries == ni);
765
	if (tab->bins != NULL)
766
	    free(tab->bins);
767
	tab->bins = new_tab->bins;
768
	free(tab->entries);
769
	tab->entries = new_tab->entries;
770
	free(new_tab);
771
    }
772
    tab->entries_start = 0;
773
    tab->entries_bound = tab->num_entries;
774
    tab->rebuilds_num++;
775
#ifdef ST_DEBUG
776
    st_check(tab);
777
#endif
383 778
}
... This diff was truncated because it exceeds the maximum size that can be displayed.