aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>1999-01-04 11:37:29 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>1999-01-04 11:37:29 -0200
commitd7294c6de8e8e2e5d124cfc20ff2ad1a1c2a84f5 (patch)
tree4ec288f0f552a65cb5ceb2f80bb4386f8a9418a1
parent63a752f961dc8b6ced4f398c7d4cafdfc2a6b9f0 (diff)
downloadlua-d7294c6de8e8e2e5d124cfc20ff2ad1a1c2a84f5.tar.gz
lua-d7294c6de8e8e2e5d124cfc20ff2ad1a1c2a84f5.tar.bz2
lua-d7294c6de8e8e2e5d124cfc20ff2ad1a1c2a84f5.zip
double hashing for string tables.
-rw-r--r--lstring.c97
1 files changed, 40 insertions, 57 deletions
diff --git a/lstring.c b/lstring.c
index 80103a28..e47fbee8 100644
--- a/lstring.c
+++ b/lstring.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstring.c,v 1.14 1998/07/27 17:06:17 roberto Exp roberto $ 2** $Id: lstring.c,v 1.15 1998/08/10 21:36:32 roberto Exp roberto $
3** String table (keeps all strings handled by Lua) 3** String table (keeps all strings handled by Lua)
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -25,8 +25,7 @@ static TaggedString EMPTY = {{NULL, 2}, 0L, 0,
25 {{{LUA_T_NIL, {NULL}}, 0L}}, {0}}; 25 {{{LUA_T_NIL, {NULL}}, 0L}}, {0}};
26 26
27 27
28void luaS_init (void) 28void luaS_init (void) {
29{
30 int i; 29 int i;
31 L->string_root = luaM_newvector(NUM_HASHS, stringtable); 30 L->string_root = luaM_newvector(NUM_HASHS, stringtable);
32 for (i=0; i<NUM_HASHS; i++) { 31 for (i=0; i<NUM_HASHS; i++) {
@@ -37,8 +36,7 @@ void luaS_init (void)
37} 36}
38 37
39 38
40static unsigned long hash_s (char *s, long l) 39static unsigned long hash_s (char *s, long l) {
41{
42 unsigned long h = 0; /* seed */ 40 unsigned long h = 0; /* seed */
43 while (l--) 41 while (l--)
44 h = h ^ ((h<<5)+(h>>2)+(unsigned char)*(s++)); 42 h = h ^ ((h<<5)+(h>>2)+(unsigned char)*(s++));
@@ -53,13 +51,12 @@ static int newsize (stringtable *tb) {
53 for (i=0; i<size; i++) 51 for (i=0; i<size; i++)
54 if (tb->hash[i] != NULL && tb->hash[i] != &EMPTY) 52 if (tb->hash[i] != NULL && tb->hash[i] != &EMPTY)
55 realuse++; 53 realuse++;
56 return luaO_redimension((realuse+1)*2); /* +1 is the new element */ 54 return luaO_redimension((realuse+1)*2+6); /* +1 is the new element, +6 to
55 ensure minimum size of 8 (for double hashing) */
57} 56}
58 57
59 58
60static void grow (stringtable *tb) 59static void grow (stringtable *tb) {
61{
62
63 int ns = newsize(tb); 60 int ns = newsize(tb);
64 TaggedString **newhash = luaM_newvector(ns, TaggedString *); 61 TaggedString **newhash = luaM_newvector(ns, TaggedString *);
65 int i; 62 int i;
@@ -69,10 +66,12 @@ static void grow (stringtable *tb)
69 tb->nuse = 0; 66 tb->nuse = 0;
70 for (i=0; i<tb->size; i++) { 67 for (i=0; i<tb->size; i++) {
71 if (tb->hash[i] != NULL && tb->hash[i] != &EMPTY) { 68 if (tb->hash[i] != NULL && tb->hash[i] != &EMPTY) {
72 int h = tb->hash[i]->hash%ns; 69 unsigned long h = tb->hash[i]->hash;
73 while (newhash[h]) 70 int h1 = h%ns;
74 h = (h+1)%ns; 71 int h2 = 8-(h&7);
75 newhash[h] = tb->hash[i]; 72 while (newhash[h1])
73 h1 = (h1+h2)%ns;
74 newhash[h1] = tb->hash[i];
76 tb->nuse++; 75 tb->nuse++;
77 } 76 }
78 } 77 }
@@ -82,8 +81,7 @@ static void grow (stringtable *tb)
82} 81}
83 82
84 83
85static TaggedString *newone_s (char *str, long l, unsigned long h) 84static TaggedString *newone_s (char *str, long l, unsigned long h) {
86{
87 TaggedString *ts = (TaggedString *)luaM_malloc(sizeof(TaggedString)+l); 85 TaggedString *ts = (TaggedString *)luaM_malloc(sizeof(TaggedString)+l);
88 memcpy(ts->str, str, l); 86 memcpy(ts->str, str, l);
89 ts->str[l] = 0; /* ending 0 */ 87 ts->str[l] = 0; /* ending 0 */
@@ -97,8 +95,7 @@ static TaggedString *newone_s (char *str, long l, unsigned long h)
97 return ts; 95 return ts;
98} 96}
99 97
100static TaggedString *newone_u (char *buff, int tag, unsigned long h) 98static TaggedString *newone_u (char *buff, int tag, unsigned long h) {
101{
102 TaggedString *ts = luaM_new(TaggedString); 99 TaggedString *ts = luaM_new(TaggedString);
103 ts->u.d.v = buff; 100 ts->u.d.v = buff;
104 ts->u.d.tag = (tag == LUA_ANYTAG) ? 0 : tag; 101 ts->u.d.tag = (tag == LUA_ANYTAG) ? 0 : tag;
@@ -110,82 +107,76 @@ static TaggedString *newone_u (char *buff, int tag, unsigned long h)
110 return ts; 107 return ts;
111} 108}
112 109
113static TaggedString *insert_s (char *str, long l, stringtable *tb) 110static TaggedString *insert_s (char *str, long l, stringtable *tb) {
114{
115 TaggedString *ts; 111 TaggedString *ts;
116 unsigned long h = hash_s(str, l); 112 unsigned long h = hash_s(str, l);
117 int size = tb->size; 113 int size = tb->size;
118 int i;
119 int j = -1; 114 int j = -1;
115 int h1;
116 int h2 = 8-(h&7); /* for double hashing */
120 if ((long)tb->nuse*3 >= (long)size*2) { 117 if ((long)tb->nuse*3 >= (long)size*2) {
121 grow(tb); 118 grow(tb);
122 size = tb->size; 119 size = tb->size;
123 } 120 }
124 for (i = h%size; (ts = tb->hash[i]) != NULL; ) { 121 for (h1 = h%size; (ts = tb->hash[h1]) != NULL; h1 = (h1+h2)%size) {
125 if (ts == &EMPTY) 122 if (ts == &EMPTY)
126 j = i; 123 j = h1;
127 else if (ts->constindex >= 0 && 124 else if (ts->constindex >= 0 &&
128 ts->u.s.len == l && 125 ts->u.s.len == l &&
129 (memcmp(str, ts->str, l) == 0)) 126 (memcmp(str, ts->str, l) == 0))
130 return ts; 127 return ts;
131 if (++i == size) i=0;
132 } 128 }
133 /* not found */ 129 /* not found */
134 if (j != -1) /* is there an EMPTY space? */ 130 if (j != -1) /* is there an EMPTY space? */
135 i = j; 131 h1 = j;
136 else 132 else
137 tb->nuse++; 133 tb->nuse++;
138 ts = tb->hash[i] = newone_s(str, l, h); 134 ts = tb->hash[h1] = newone_s(str, l, h);
139 return ts; 135 return ts;
140} 136}
141 137
142static TaggedString *insert_u (void *buff, int tag, stringtable *tb) 138static TaggedString *insert_u (void *buff, int tag, stringtable *tb) {
143{
144 TaggedString *ts; 139 TaggedString *ts;
145 unsigned long h = (unsigned long)buff; 140 unsigned long h = (unsigned long)buff;
146 int size = tb->size; 141 int size = tb->size;
147 int i;
148 int j = -1; 142 int j = -1;
143 int h1;
144 int h2 = 8-(h&7); /* for double hashing */
149 if ((long)tb->nuse*3 >= (long)size*2) { 145 if ((long)tb->nuse*3 >= (long)size*2) {
150 grow(tb); 146 grow(tb);
151 size = tb->size; 147 size = tb->size;
152 } 148 }
153 for (i = h%size; (ts = tb->hash[i]) != NULL; ) { 149 for (h1 = h%size; (ts = tb->hash[h1]) != NULL; h1 = (h1+h2)%size) {
154 if (ts == &EMPTY) 150 if (ts == &EMPTY)
155 j = i; 151 j = h1;
156 else if (ts->constindex < 0 && /* is a udata? */ 152 else if (ts->constindex < 0 && /* is a udata? */
157 (tag == ts->u.d.tag || tag == LUA_ANYTAG) && 153 (tag == ts->u.d.tag || tag == LUA_ANYTAG) &&
158 buff == ts->u.d.v) 154 buff == ts->u.d.v)
159 return ts; 155 return ts;
160 if (++i == size) i=0;
161 } 156 }
162 /* not found */ 157 /* not found */
163 if (j != -1) /* is there an EMPTY space? */ 158 if (j != -1) /* is there an EMPTY space? */
164 i = j; 159 h1 = j;
165 else 160 else
166 tb->nuse++; 161 tb->nuse++;
167 ts = tb->hash[i] = newone_u(buff, tag, h); 162 ts = tb->hash[h1] = newone_u(buff, tag, h);
168 return ts; 163 return ts;
169} 164}
170 165
171TaggedString *luaS_createudata (void *udata, int tag) 166TaggedString *luaS_createudata (void *udata, int tag) {
172{
173 return insert_u(udata, tag, &L->string_root[(unsigned)udata%NUM_HASHS]); 167 return insert_u(udata, tag, &L->string_root[(unsigned)udata%NUM_HASHS]);
174} 168}
175 169
176TaggedString *luaS_newlstr (char *str, long l) 170TaggedString *luaS_newlstr (char *str, long l) {
177{
178 int i = (l==0)?0:(unsigned char)str[0]; 171 int i = (l==0)?0:(unsigned char)str[0];
179 return insert_s(str, l, &L->string_root[i%NUM_HASHS]); 172 return insert_s(str, l, &L->string_root[i%NUM_HASHS]);
180} 173}
181 174
182TaggedString *luaS_new (char *str) 175TaggedString *luaS_new (char *str) {
183{
184 return luaS_newlstr(str, strlen(str)); 176 return luaS_newlstr(str, strlen(str));
185} 177}
186 178
187TaggedString *luaS_newfixedstring (char *str) 179TaggedString *luaS_newfixedstring (char *str) {
188{
189 TaggedString *ts = luaS_new(str); 180 TaggedString *ts = luaS_new(str);
190 if (ts->head.marked == 0) 181 if (ts->head.marked == 0)
191 ts->head.marked = 2; /* avoid GC */ 182 ts->head.marked = 2; /* avoid GC */
@@ -193,8 +184,7 @@ TaggedString *luaS_newfixedstring (char *str)
193} 184}
194 185
195 186
196void luaS_free (TaggedString *l) 187void luaS_free (TaggedString *l) {
197{
198 while (l) { 188 while (l) {
199 TaggedString *next = (TaggedString *)l->head.next; 189 TaggedString *next = (TaggedString *)l->head.next;
200 L->nblocks -= (l->constindex == -1) ? 1 : gcsizestring(l->u.s.len); 190 L->nblocks -= (l->constindex == -1) ? 1 : gcsizestring(l->u.s.len);
@@ -208,8 +198,7 @@ void luaS_free (TaggedString *l)
208** Garbage collection functions. 198** Garbage collection functions.
209*/ 199*/
210 200
211static void remove_from_list (GCnode *l) 201static void remove_from_list (GCnode *l) {
212{
213 while (l) { 202 while (l) {
214 GCnode *next = l->next; 203 GCnode *next = l->next;
215 while (next && !next->marked) 204 while (next && !next->marked)
@@ -219,8 +208,7 @@ static void remove_from_list (GCnode *l)
219} 208}
220 209
221 210
222TaggedString *luaS_collector (void) 211TaggedString *luaS_collector (void) {
223{
224 TaggedString *frees = NULL; 212 TaggedString *frees = NULL;
225 int i; 213 int i;
226 remove_from_list(&(L->rootglobal)); 214 remove_from_list(&(L->rootglobal));
@@ -243,8 +231,7 @@ TaggedString *luaS_collector (void)
243} 231}
244 232
245 233
246TaggedString *luaS_collectudata (void) 234TaggedString *luaS_collectudata (void) {
247{
248 TaggedString *frees = NULL; 235 TaggedString *frees = NULL;
249 int i; 236 int i;
250 L->rootglobal.next = NULL; /* empty list of globals */ 237 L->rootglobal.next = NULL; /* empty list of globals */
@@ -264,8 +251,7 @@ TaggedString *luaS_collectudata (void)
264} 251}
265 252
266 253
267void luaS_freeall (void) 254void luaS_freeall (void) {
268{
269 int i; 255 int i;
270 for (i=0; i<NUM_HASHS; i++) { 256 for (i=0; i<NUM_HASHS; i++) {
271 stringtable *tb = &L->string_root[i]; 257 stringtable *tb = &L->string_root[i];
@@ -281,8 +267,7 @@ void luaS_freeall (void)
281} 267}
282 268
283 269
284void luaS_rawsetglobal (TaggedString *ts, TObject *newval) 270void luaS_rawsetglobal (TaggedString *ts, TObject *newval) {
285{
286 ts->u.s.globalval = *newval; 271 ts->u.s.globalval = *newval;
287 if (ts->head.next == (GCnode *)ts) { /* is not in list? */ 272 if (ts->head.next == (GCnode *)ts) { /* is not in list? */
288 ts->head.next = L->rootglobal.next; 273 ts->head.next = L->rootglobal.next;
@@ -291,8 +276,7 @@ void luaS_rawsetglobal (TaggedString *ts, TObject *newval)
291} 276}
292 277
293 278
294char *luaS_travsymbol (int (*fn)(TObject *)) 279char *luaS_travsymbol (int (*fn)(TObject *)) {
295{
296 TaggedString *g; 280 TaggedString *g;
297 for (g=(TaggedString *)L->rootglobal.next; g; g=(TaggedString *)g->head.next) 281 for (g=(TaggedString *)L->rootglobal.next; g; g=(TaggedString *)g->head.next)
298 if (fn(&g->u.s.globalval)) 282 if (fn(&g->u.s.globalval))
@@ -301,8 +285,7 @@ char *luaS_travsymbol (int (*fn)(TObject *))
301} 285}
302 286
303 287
304int luaS_globaldefined (char *name) 288int luaS_globaldefined (char *name) {
305{
306 TaggedString *ts = luaS_new(name); 289 TaggedString *ts = luaS_new(name);
307 return ts->u.s.globalval.ttype != LUA_T_NIL; 290 return ts->u.s.globalval.ttype != LUA_T_NIL;
308} 291}