aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2005-01-05 16:20:51 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2005-01-05 16:20:51 -0200
commite2498e079e4636217e89f0b28844c4b5df4f8793 (patch)
treeda82e007f0e8153985323c2bdb190811f79e0c57
parent65726f3e2e226f6a350a5dba643c13c8edd34965 (diff)
downloadlua-e2498e079e4636217e89f0b28844c4b5df4f8793.tar.gz
lua-e2498e079e4636217e89f0b28844c4b5df4f8793.tar.bz2
lua-e2498e079e4636217e89f0b28844c4b5df4f8793.zip
change in hash algorithm so that it does not need empty slot
(tables can be 100% full)
-rw-r--r--lgc.c9
-rw-r--r--lobject.h6
-rw-r--r--lparser.c4
-rw-r--r--lstate.c5
-rw-r--r--lstate.h3
-rw-r--r--ltable.c191
-rw-r--r--ltable.h4
-rw-r--r--ltests.c7
-rw-r--r--lvm.c4
9 files changed, 125 insertions, 108 deletions
diff --git a/lgc.c b/lgc.c
index f401505c..0d76d2b1 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 2.18 2004/12/06 17:53:42 roberto Exp roberto $ 2** $Id: lgc.c,v 2.19 2004/12/13 12:15:11 roberto Exp roberto $
3** Garbage Collector 3** Garbage Collector
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -63,7 +63,7 @@
63 63
64 64
65static void removeentry (Node *n) { 65static void removeentry (Node *n) {
66 setnilvalue(gval(n)); /* remove corresponding value ... */ 66 lua_assert(ttisnil(gval(n)));
67 if (iscollectable(gkey(n))) 67 if (iscollectable(gkey(n)))
68 setttype(gkey(n), LUA_TDEADKEY); /* dead key; remove it */ 68 setttype(gkey(n), LUA_TDEADKEY); /* dead key; remove it */
69} 69}
@@ -162,7 +162,6 @@ static int traversetable (global_State *g, Table *h) {
162 const TValue *mode; 162 const TValue *mode;
163 if (h->metatable) 163 if (h->metatable)
164 markobject(g, h->metatable); 164 markobject(g, h->metatable);
165 lua_assert(h->lsizenode || h->node == g->dummynode);
166 mode = gfasttm(g, h->metatable, TM_MODE); 165 mode = gfasttm(g, h->metatable, TM_MODE);
167 if (mode && ttisstring(mode)) { /* is there a weak mode? */ 166 if (mode && ttisstring(mode)) { /* is there a weak mode? */
168 weakkey = (strchr(svalue(mode), 'k') != NULL); 167 weakkey = (strchr(svalue(mode), 'k') != NULL);
@@ -368,8 +367,10 @@ static void cleartable (GCObject *l) {
368 while (i--) { 367 while (i--) {
369 Node *n = gnode(h, i); 368 Node *n = gnode(h, i);
370 if (!ttisnil(gval(n)) && /* non-empty entry? */ 369 if (!ttisnil(gval(n)) && /* non-empty entry? */
371 (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) 370 (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) {
371 setnilvalue(gval(n)); /* remove value ... */
372 removeentry(n); /* remove entry from table */ 372 removeentry(n); /* remove entry from table */
373 }
373 } 374 }
374 l = h->gclist; 375 l = h->gclist;
375 } 376 }
diff --git a/lobject.h b/lobject.h
index 259bdac5..2c0a5d26 100644
--- a/lobject.h
+++ b/lobject.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lobject.h,v 2.7 2004/11/01 15:06:50 roberto Exp roberto $ 2** $Id: lobject.h,v 2.8 2004/12/04 18:10:22 roberto Exp roberto $
3** Type definitions for Lua objects 3** Type definitions for Lua objects
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -330,7 +330,7 @@ typedef struct Table {
330 struct Table *metatable; 330 struct Table *metatable;
331 TValue *array; /* array part */ 331 TValue *array; /* array part */
332 Node *node; 332 Node *node;
333 Node *firstfree; /* this position is free; all positions after it are full */ 333 Node *lastfree; /* any free position is before this position */
334 GCObject *gclist; 334 GCObject *gclist;
335 int sizearray; /* size of `array' array */ 335 int sizearray; /* size of `array' array */
336} Table; 336} Table;
@@ -351,6 +351,8 @@ typedef struct Table {
351 351
352extern const TValue luaO_nilobject; 352extern const TValue luaO_nilobject;
353 353
354#define ceillog2(x) (luaO_log2((x)-1) + 1)
355
354int luaO_log2 (unsigned int x); 356int luaO_log2 (unsigned int x);
355int luaO_int2fb (unsigned int x); 357int luaO_int2fb (unsigned int x);
356int luaO_fb2int (int x); 358int luaO_fb2int (int x);
diff --git a/lparser.c b/lparser.c
index d131e5e0..cb348c40 100644
--- a/lparser.c
+++ b/lparser.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lparser.c,v 2.11 2004/12/07 18:31:16 roberto Exp $ 2** $Id: lparser.c,v 2.12 2005/01/04 15:55:12 roberto Exp roberto $
3** Lua Parser 3** Lua Parser
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -547,7 +547,7 @@ static void constructor (LexState *ls, expdesc *t) {
547 check_match(ls, '}', '{', line); 547 check_match(ls, '}', '{', line);
548 lastlistfield(fs, &cc); 548 lastlistfield(fs, &cc);
549 SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */ 549 SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */
550 SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh+1)); /* set initial table size */ 550 SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */
551} 551}
552 552
553/* }====================================================================== */ 553/* }====================================================================== */
diff --git a/lstate.c b/lstate.c
index 1645eccf..54917649 100644
--- a/lstate.c
+++ b/lstate.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.c,v 2.19 2004/12/13 12:15:11 roberto Exp $ 2** $Id: lstate.c,v 2.20 2005/01/04 15:55:12 roberto Exp roberto $
3** Global State 3** Global State
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -189,9 +189,6 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
189 g->grayagain = NULL; 189 g->grayagain = NULL;
190 g->weak = NULL; 190 g->weak = NULL;
191 g->tmudata = NULL; 191 g->tmudata = NULL;
192 setnilvalue(gkey(g->dummynode));
193 setnilvalue(gval(g->dummynode));
194 gnext(g->dummynode) = NULL;
195 g->totalbytes = sizeof(LG); 192 g->totalbytes = sizeof(LG);
196 g->gcpace = GCDIV; 193 g->gcpace = GCDIV;
197 g->incgc = 1; 194 g->incgc = 1;
diff --git a/lstate.h b/lstate.h
index 06a5c5dc..26a94082 100644
--- a/lstate.h
+++ b/lstate.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.h,v 2.9 2004/12/06 17:53:42 roberto Exp roberto $ 2** $Id: lstate.h,v 2.10 2004/12/13 12:15:11 roberto Exp roberto $
3** Global State 3** Global State
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -90,7 +90,6 @@ typedef struct global_State {
90 lua_CFunction panic; /* to be called in unprotected errors */ 90 lua_CFunction panic; /* to be called in unprotected errors */
91 TValue _registry; 91 TValue _registry;
92 struct lua_State *mainthread; 92 struct lua_State *mainthread;
93 Node dummynode[1]; /* common node array for all empty tables */
94 TString *tmname[TM_N]; /* array with tag-method names */ 93 TString *tmname[TM_N]; /* array with tag-method names */
95} global_State; 94} global_State;
96 95
diff --git a/ltable.c b/ltable.c
index d9a1ee20..a3a169b7 100644
--- a/ltable.c
+++ b/ltable.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltable.c,v 2.12 2004/12/04 18:10:22 roberto Exp $ 2** $Id: ltable.c,v 2.13 2005/01/04 15:55:12 roberto Exp roberto $
3** Lua tables (hash) 3** Lua tables (hash)
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -68,6 +68,13 @@
68#define numints cast(int, sizeof(lua_Number)/sizeof(int)) 68#define numints cast(int, sizeof(lua_Number)/sizeof(int))
69 69
70 70
71
72const Node luaH_dummynode = {
73 {{NULL}, LUA_TNIL}, /* value */
74 {{NULL}, LUA_TNIL, NULL} /* key */
75};
76
77
71/* 78/*
72** hash for lua_Numbers 79** hash for lua_Numbers
73*/ 80*/
@@ -176,31 +183,32 @@ int luaH_next (lua_State *L, Table *t, StkId key) {
176*/ 183*/
177 184
178 185
179static void computesizes (int nums[], int ntotal, int *narray, int *nhash) { 186static int computesizes (int nums[], int *narray) {
180 int i; 187 int i;
181 int a = nums[0]; /* number of elements smaller than 2^i */ 188 int twotoi; /* 2^i */
182 int na = a; /* number of elements to go to array part */ 189 int a = 0; /* number of elements smaller than 2^i */
183 int n = (na == 0) ? -1 : 0; /* (log of) optimal size for array part */ 190 int na = 0; /* number of elements to go to array part */
184 for (i = 1; a < *narray && *narray >= twoto(i-1); i++) { 191 int n = 0; /* optimal size for array part */
192 for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) {
185 if (nums[i] > 0) { 193 if (nums[i] > 0) {
186 a += nums[i]; 194 a += nums[i];
187 if (a >= twoto(i-1)) { /* more than half elements in use? */ 195 if (a > twotoi/2) { /* more than half elements present? */
188 n = i; 196 n = twotoi; /* optimal size (till now) */
189 na = a; 197 na = a; /* all elements smaller than n will go to array part */
190 } 198 }
191 } 199 }
200 if (a == *narray) break; /* all elements already counted */
192 } 201 }
193 lua_assert(na <= *narray && *narray <= ntotal); 202 *narray = n;
194 *nhash = ntotal - na; 203 lua_assert(*narray/2 <= na && na <= *narray);
195 *narray = (n == -1) ? 0 : twoto(n); 204 return na;
196 lua_assert(na <= *narray && na >= *narray/2);
197} 205}
198 206
199 207
200static int countint (const TValue *key, int *nums) { 208static int countint (const TValue *key, int *nums) {
201 int k = arrayindex(key); 209 int k = arrayindex(key);
202 if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */ 210 if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */
203 nums[luaO_log2(k-1)+1]++; /* count as such */ 211 nums[ceillog2(k)]++; /* count as such */
204 return 1; 212 return 1;
205 } 213 }
206 else 214 else
@@ -208,40 +216,44 @@ static int countint (const TValue *key, int *nums) {
208} 216}
209 217
210 218
211static void numuse (const Table *t, int *narray, int *nhash, const TValue *ek) { 219static int numusearray (const Table *t, int *nums) {
212 int nums[MAXBITS+1]; 220 int lg;
213 int i, lg; 221 int ttlg; /* 2^lg */
214 int totaluse = 0; 222 int ause = 0; /* summation of `nums' */
215 /* count elements in array part */ 223 int i = 1; /* count to traverse all array keys */
216 for (i=0, lg=0; lg<=MAXBITS; lg++) { /* for each slice [2^(lg-1) to 2^lg) */ 224 for (lg=0, ttlg=1; lg<=MAXBITS; lg++, ttlg*=2) { /* for each slice */
217 int ttlg = twoto(lg); /* 2^lg */ 225 int lc = 0; /* counter */
218 if (ttlg > t->sizearray) { 226 int lim = ttlg;
219 ttlg = t->sizearray; 227 if (lim > t->sizearray) {
220 if (i >= ttlg) break; 228 lim = t->sizearray; /* adjust upper limit */
229 if (i > lim)
230 break; /* no more elements to count */
221 } 231 }
222 nums[lg] = 0; 232 /* count elements in range (2^(lg-1), 2^lg] */
223 for (; i<ttlg; i++) { 233 for (; i <= lim; i++) {
224 if (!ttisnil(&t->array[i])) { 234 if (!ttisnil(&t->array[i-1]))
225 nums[lg]++; 235 lc++;
226 totaluse++;
227 }
228 } 236 }
237 nums[lg] += lc;
238 ause += lc;
229 } 239 }
230 for (; lg<=MAXBITS; lg++) nums[lg] = 0; /* reset other counts */ 240 return ause;
231 *narray = totaluse; /* all previous uses were in array part */ 241}
232 /* count elements in hash part */ 242
233 i = sizenode(t); 243
244static int numusehash (const Table *t, int *nums, int *pnasize) {
245 int totaluse = 0; /* total number of elements */
246 int ause = 0; /* summation of `nums' */
247 int i = sizenode(t);
234 while (i--) { 248 while (i--) {
235 Node *n = &t->node[i]; 249 Node *n = &t->node[i];
236 if (!ttisnil(gval(n))) { 250 if (!ttisnil(gval(n))) {
237 *narray += countint(key2tval(n), nums); 251 ause += countint(key2tval(n), nums);
238 totaluse++; 252 totaluse++;
239 } 253 }
240 } 254 }
241 /* count extra key */ 255 *pnasize += ause;
242 *narray += countint(ek, nums); 256 return totaluse;
243 totaluse++;
244 computesizes(nums, totaluse, narray, nhash);
245} 257}
246 258
247 259
@@ -254,18 +266,18 @@ static void setarrayvector (lua_State *L, Table *t, int size) {
254} 266}
255 267
256 268
257static void setnodevector (lua_State *L, Table *t, int lsize) { 269static void setnodevector (lua_State *L, Table *t, int size) {
258 int i; 270 int lsize;
259 int size = twoto(lsize); 271 if (size == 0) { /* no elements to hash part? */
260 if (lsize > MAXBITS) 272 t->node = cast(Node *, &luaH_dummynode); /* use common `dummynode' */
261 luaG_runerror(L, "table overflow"); 273 lsize = 0;
262 if (lsize == 0) { /* no elements to hash part? */
263 t->node = G(L)->dummynode; /* use common `dummynode' */
264 lua_assert(ttisnil(gkey(t->node))); /* assert invariants: */
265 lua_assert(ttisnil(gval(t->node)));
266 lua_assert(gnext(t->node) == NULL); /* (`dummynode' must be empty) */
267 } 274 }
268 else { 275 else {
276 int i;
277 lsize = ceillog2(size);
278 if (lsize > MAXBITS)
279 luaG_runerror(L, "table overflow");
280 size = twoto(lsize);
269 t->node = luaM_newvector(L, size, Node); 281 t->node = luaM_newvector(L, size, Node);
270 for (i=0; i<size; i++) { 282 for (i=0; i<size; i++) {
271 gnext(&t->node[i]) = NULL; 283 gnext(&t->node[i]) = NULL;
@@ -274,31 +286,19 @@ static void setnodevector (lua_State *L, Table *t, int lsize) {
274 } 286 }
275 } 287 }
276 t->lsizenode = cast(lu_byte, lsize); 288 t->lsizenode = cast(lu_byte, lsize);
277 t->firstfree = gnode(t, size-1); /* first free position to be used */ 289 t->lastfree = gnode(t, size); /* all positions are free */
278} 290}
279 291
280 292
281static void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize) { 293static void resize (lua_State *L, Table *t, int nasize, int nhsize) {
282 int i; 294 int i;
283 int oldasize = t->sizearray; 295 int oldasize = t->sizearray;
284 int oldhsize = t->lsizenode; 296 int oldhsize = t->lsizenode;
285 Node *nold; 297 Node *nold = t->node; /* save old hash ... */
286 Node temp[1];
287 if (oldhsize)
288 nold = t->node; /* save old hash ... */
289 else { /* old hash is `dummynode' */
290 lua_assert(t->node == G(L)->dummynode);
291 temp[0] = t->node[0]; /* copy it to `temp' */
292 nold = temp;
293 setnilvalue(gkey(G(L)->dummynode)); /* restate invariant */
294 setnilvalue(gval(G(L)->dummynode));
295 lua_assert(gnext(G(L)->dummynode) == NULL);
296 }
297 if (nasize > oldasize) /* array part must grow? */ 298 if (nasize > oldasize) /* array part must grow? */
298 setarrayvector(L, t, nasize); 299 setarrayvector(L, t, nasize);
299 /* create new hash part with appropriate size */ 300 /* create new hash part with appropriate size */
300 setnodevector(L, t, nhsize); 301 setnodevector(L, t, nhsize);
301 /* re-insert elements */
302 if (nasize < oldasize) { /* array part must shrink? */ 302 if (nasize < oldasize) { /* array part must shrink? */
303 t->sizearray = nasize; 303 t->sizearray = nasize;
304 /* re-insert elements from vanishing slice */ 304 /* re-insert elements from vanishing slice */
@@ -309,28 +309,39 @@ static void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize) {
309 /* shrink array */ 309 /* shrink array */
310 luaM_reallocvector(L, t->array, oldasize, nasize, TValue); 310 luaM_reallocvector(L, t->array, oldasize, nasize, TValue);
311 } 311 }
312 /* re-insert elements in hash part */ 312 /* re-insert elements from hash part */
313 for (i = twoto(oldhsize) - 1; i >= 0; i--) { 313 for (i = twoto(oldhsize) - 1; i >= 0; i--) {
314 Node *old = nold+i; 314 Node *old = nold+i;
315 if (!ttisnil(gval(old))) 315 if (!ttisnil(gval(old)))
316 setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old)); 316 setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old));
317 } 317 }
318 if (oldhsize) 318 if (nold != &luaH_dummynode)
319 luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */ 319 luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */
320} 320}
321 321
322 322
323void luaH_resizearray (lua_State *L, Table *t, int nasize) { 323void luaH_resizearray (lua_State *L, Table *t, int nasize) {
324 luaH_resize(L, t, nasize, t->lsizenode); 324 int nsize = (t->node == &luaH_dummynode) ? 0 : sizenode(t);
325 resize(L, t, nasize, nsize);
325} 326}
326 327
327 328
328static void rehash (lua_State *L, Table *t, const TValue *ek) { 329static void rehash (lua_State *L, Table *t, const TValue *ek) {
329 int nasize, nhsize; 330 int nasize, na;
330 /* compute new sizes for array and hash parts */ 331 int nums[MAXBITS+1]; /* nums[i] = number of keys between 2^(i-1) and 2^i */
331 numuse(t, &nasize, &nhsize, ek); 332 int i;
333 int totaluse;
334 for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* reset counts */
335 nasize = numusearray(t, nums); /* count keys in array part */
336 totaluse = nasize; /* all those keys are integer keys */
337 totaluse += numusehash(t, nums, &nasize); /* count keys in hash part */
338 /* count extra key */
339 nasize += countint(ek, nums);
340 totaluse++;
341 /* compute new size for array part */
342 na = computesizes(nums, &nasize);
332 /* resize the table to new computed sizes */ 343 /* resize the table to new computed sizes */
333 luaH_resize(L, t, nasize, luaO_log2(nhsize)+1); 344 resize(L, t, nasize, totaluse - na);
334} 345}
335 346
336 347
@@ -349,21 +360,30 @@ Table *luaH_new (lua_State *L, int narray, int nhash) {
349 t->array = NULL; 360 t->array = NULL;
350 t->sizearray = 0; 361 t->sizearray = 0;
351 t->lsizenode = 0; 362 t->lsizenode = 0;
352 t->node = NULL; 363 t->node = cast(Node *, &luaH_dummynode);
353 setarrayvector(L, t, narray); 364 setarrayvector(L, t, narray);
354 setnodevector(L, t, luaO_log2(nhash)+1); 365 setnodevector(L, t, nhash);
355 return t; 366 return t;
356} 367}
357 368
358 369
359void luaH_free (lua_State *L, Table *t) { 370void luaH_free (lua_State *L, Table *t) {
360 if (t->lsizenode) 371 if (t->node != &luaH_dummynode)
361 luaM_freearray(L, t->node, sizenode(t), Node); 372 luaM_freearray(L, t->node, sizenode(t), Node);
362 luaM_freearray(L, t->array, t->sizearray, TValue); 373 luaM_freearray(L, t->array, t->sizearray, TValue);
363 luaM_free(L, t); 374 luaM_free(L, t);
364} 375}
365 376
366 377
378static Node *getfreepos (lua_State *L, Table *t) {
379 while (t->lastfree-- > t->node) {
380 if (ttisnil(gkey(t->lastfree)))
381 return t->lastfree;
382 }
383 return NULL; /* could not find a free place */
384}
385
386
367 387
368/* 388/*
369** inserts a new key into a hash table; first, check whether key's main 389** inserts a new key into a hash table; first, check whether key's main
@@ -374,10 +394,15 @@ void luaH_free (lua_State *L, Table *t) {
374*/ 394*/
375static TValue *newkey (lua_State *L, Table *t, const TValue *key) { 395static TValue *newkey (lua_State *L, Table *t, const TValue *key) {
376 Node *mp = luaH_mainposition(t, key); 396 Node *mp = luaH_mainposition(t, key);
377 if (!ttisnil(gval(mp))) { /* main position is not free? */ 397 if (!ttisnil(gval(mp)) || mp == &luaH_dummynode) {
378 /* `mp' of colliding node */ 398 Node *othern;
379 Node *othern = luaH_mainposition(t, key2tval(mp)); 399 Node *n = getfreepos(L, t); /* get a free place */
380 Node *n = t->firstfree; /* get a free place */ 400 if (n == NULL) { /* cannot find a free place? */
401 rehash(L, t, key); /* grow table */
402 return luaH_set(L, t, key); /* re-insert key into grown table */
403 }
404 lua_assert(n != &luaH_dummynode);
405 othern = luaH_mainposition(t, key2tval(mp));
381 if (othern != mp) { /* is colliding node out of its main position? */ 406 if (othern != mp) { /* is colliding node out of its main position? */
382 /* yes; move colliding node into free position */ 407 /* yes; move colliding node into free position */
383 while (gnext(othern) != mp) othern = gnext(othern); /* find previous */ 408 while (gnext(othern) != mp) othern = gnext(othern); /* find previous */
@@ -396,15 +421,7 @@ static TValue *newkey (lua_State *L, Table *t, const TValue *key) {
396 gkey(mp)->value = key->value; gkey(mp)->tt = key->tt; 421 gkey(mp)->value = key->value; gkey(mp)->tt = key->tt;
397 luaC_barriert(L, t, key); 422 luaC_barriert(L, t, key);
398 lua_assert(ttisnil(gval(mp))); 423 lua_assert(ttisnil(gval(mp)));
399 for (;;) { /* correct `firstfree' */ 424 return gval(mp);
400 if (ttisnil(gkey(t->firstfree)))
401 return gval(mp); /* OK; table still has a free place */
402 else if (t->firstfree == t->node) break; /* cannot decrement from here */
403 else (t->firstfree)--;
404 }
405 /* no more free places; must create one */
406 rehash(L, t, key); /* grow table */
407 return luaH_set(L, t, key); /* re-insert in new table */
408} 425}
409 426
410 427
diff --git a/ltable.h b/ltable.h
index 3927f088..d8ba8c8a 100644
--- a/ltable.h
+++ b/ltable.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltable.h,v 2.3 2004/10/06 18:34:16 roberto Exp roberto $ 2** $Id: ltable.h,v 2.4 2005/01/04 15:55:12 roberto Exp roberto $
3** Lua tables (hash) 3** Lua tables (hash)
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -18,6 +18,8 @@
18#define key2tval(n) (cast(const TValue *, gkey(n))) 18#define key2tval(n) (cast(const TValue *, gkey(n)))
19 19
20 20
21extern const Node luaH_dummynode;
22
21const TValue *luaH_getnum (Table *t, int key); 23const TValue *luaH_getnum (Table *t, int key);
22TValue *luaH_setnum (lua_State *L, Table *t, int key); 24TValue *luaH_setnum (lua_State *L, Table *t, int key);
23const TValue *luaH_getstr (Table *t, TString *key); 25const TValue *luaH_getstr (Table *t, TString *key);
diff --git a/ltests.c b/ltests.c
index 37720a26..6139106c 100644
--- a/ltests.c
+++ b/ltests.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltests.c,v 2.14 2004/10/06 18:34:16 roberto Exp $ 2** $Id: ltests.c,v 2.15 2004/11/01 15:06:50 roberto Exp roberto $
3** Internal Module for Debugging of the Lua Implementation 3** Internal Module for Debugging of the Lua Implementation
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -200,7 +200,6 @@ static void checktable (global_State *g, Table *h) {
200 GCObject *hgc = obj2gco(h); 200 GCObject *hgc = obj2gco(h);
201 if (h->metatable) 201 if (h->metatable)
202 checkobjref(g, hgc, h->metatable); 202 checkobjref(g, hgc, h->metatable);
203 lua_assert(h->lsizenode || h->node == g->dummynode);
204 mode = gfasttm(g, h->metatable, TM_MODE); 203 mode = gfasttm(g, h->metatable, TM_MODE);
205 if (mode && ttisstring(mode)) { /* is there a weak mode? */ 204 if (mode && ttisstring(mode)) { /* is there a weak mode? */
206 weakkey = (strchr(svalue(mode), 'k') != NULL); 205 weakkey = (strchr(svalue(mode), 'k') != NULL);
@@ -542,8 +541,8 @@ static int table_query (lua_State *L) {
542 t = hvalue(obj_at(L, 1)); 541 t = hvalue(obj_at(L, 1));
543 if (i == -1) { 542 if (i == -1) {
544 lua_pushinteger(L, t->sizearray); 543 lua_pushinteger(L, t->sizearray);
545 lua_pushinteger(L, sizenode(t)); 544 lua_pushinteger(L, t->node == &luaH_dummynode ? 0 : sizenode(t));
546 lua_pushinteger(L, t->firstfree - t->node); 545 lua_pushinteger(L, t->lastfree - t->node);
547 } 546 }
548 else if (i < t->sizearray) { 547 else if (i < t->sizearray) {
549 lua_pushinteger(L, i); 548 lua_pushinteger(L, i);
diff --git a/lvm.c b/lvm.c
index 52c5b4c1..2f9612c4 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.c,v 2.18 2004/12/03 20:35:33 roberto Exp $ 2** $Id: lvm.c,v 2.19 2005/01/04 15:55:12 roberto Exp roberto $
3** Lua virtual machine 3** Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -462,7 +462,7 @@ StkId luaV_execute (lua_State *L, int nexeccalls) {
462 case OP_NEWTABLE: { 462 case OP_NEWTABLE: {
463 int b = GETARG_B(i); 463 int b = GETARG_B(i);
464 int c = GETARG_C(i); 464 int c = GETARG_C(i);
465 sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c) - 1)); 465 sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c)));
466 L->ci->savedpc = pc; 466 L->ci->savedpc = pc;
467 luaC_checkGC(L); /***/ 467 luaC_checkGC(L); /***/
468 base = L->base; 468 base = L->base;