diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-10-25 17:14:14 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-10-25 17:14:14 -0200 |
commit | 21aa7e55f2333e57b972aa4ef2c5e2785d609578 (patch) | |
tree | bdd6119f0fab0178979202bc5d0afbd6f4410469 | |
parent | fffb6f3814084cddd8a58e81ae1b73ed78ea0953 (diff) | |
download | lua-21aa7e55f2333e57b972aa4ef2c5e2785d609578.tar.gz lua-21aa7e55f2333e57b972aa4ef2c5e2785d609578.tar.bz2 lua-21aa7e55f2333e57b972aa4ef2c5e2785d609578.zip |
optimization for array part of a Table
-rw-r--r-- | lapi.c | 32 | ||||
-rw-r--r-- | ldebug.c | 14 | ||||
-rw-r--r-- | lgc.c | 50 | ||||
-rw-r--r-- | lobject.c | 30 | ||||
-rw-r--r-- | lobject.h | 26 | ||||
-rw-r--r-- | lopcodes.c | 4 | ||||
-rw-r--r-- | lopcodes.h | 4 | ||||
-rw-r--r-- | lparser.c | 36 | ||||
-rw-r--r-- | lstate.c | 10 | ||||
-rw-r--r-- | ltable.c | 342 | ||||
-rw-r--r-- | ltable.h | 24 | ||||
-rw-r--r-- | ltests.c | 47 | ||||
-rw-r--r-- | lvm.c | 17 |
13 files changed, 421 insertions, 215 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lapi.c,v 1.155 2001/10/17 21:12:57 roberto Exp roberto $ | 2 | ** $Id: lapi.c,v 1.156 2001/10/17 21:17:45 roberto Exp $ |
3 | ** Lua API | 3 | ** Lua API |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -391,7 +391,7 @@ LUA_API void lua_getglobals (lua_State *L) { | |||
391 | 391 | ||
392 | LUA_API void lua_newtable (lua_State *L) { | 392 | LUA_API void lua_newtable (lua_State *L) { |
393 | lua_lock(L); | 393 | lua_lock(L); |
394 | sethvalue(L->top, luaH_new(L, 0)); | 394 | sethvalue(L->top, luaH_new(L, 0, 0)); |
395 | api_incr_top(L); | 395 | api_incr_top(L); |
396 | lua_unlock(L); | 396 | lua_unlock(L); |
397 | } | 397 | } |
@@ -647,22 +647,17 @@ LUA_API void lua_unref (lua_State *L, int ref) { | |||
647 | 647 | ||
648 | LUA_API int lua_next (lua_State *L, int index) { | 648 | LUA_API int lua_next (lua_State *L, int index) { |
649 | StkId t; | 649 | StkId t; |
650 | Node *n; | ||
651 | int more; | 650 | int more; |
652 | lua_lock(L); | 651 | lua_lock(L); |
653 | t = luaA_index(L, index); | 652 | t = luaA_index(L, index); |
654 | api_check(L, ttype(t) == LUA_TTABLE); | 653 | api_check(L, ttype(t) == LUA_TTABLE); |
655 | n = luaH_next(L, hvalue(t), luaA_index(L, -1)); | 654 | more = luaH_index(L, hvalue(t), luaA_index(L, -1)); |
656 | if (n) { | 655 | more = (luaH_nexti(hvalue(t), more, L->top - 1) != -1); |
657 | setobj(L->top-1, key(n)); | 656 | if (more) { |
658 | setobj(L->top, val(n)); | ||
659 | api_incr_top(L); | 657 | api_incr_top(L); |
660 | more = 1; | ||
661 | } | 658 | } |
662 | else { /* no more elements */ | 659 | else /* no more elements */ |
663 | L->top -= 1; /* remove key */ | 660 | L->top -= 1; /* remove key */ |
664 | more = 0; | ||
665 | } | ||
666 | lua_unlock(L); | 661 | lua_unlock(L); |
667 | return more; | 662 | return more; |
668 | } | 663 | } |
@@ -679,9 +674,18 @@ LUA_API int lua_getn (lua_State *L, int index) { | |||
679 | if (ttype(value) == LUA_TNUMBER) | 674 | if (ttype(value) == LUA_TNUMBER) |
680 | n = cast(int, nvalue(value)); | 675 | n = cast(int, nvalue(value)); |
681 | else { | 676 | else { |
677 | Node *nd; | ||
678 | Table *a = hvalue(t); | ||
682 | lua_Number max = 0; | 679 | lua_Number max = 0; |
683 | int i = hvalue(t)->size; | 680 | int i; |
684 | Node *nd = hvalue(t)->node; | 681 | i = sizearray(a); |
682 | while (i--) { | ||
683 | if (ttype(&a->array[i]) != LUA_TNIL) | ||
684 | break; | ||
685 | } | ||
686 | max = i+1; | ||
687 | i = sizenode(a); | ||
688 | nd = a->node; | ||
685 | while (i--) { | 689 | while (i--) { |
686 | if (ttype(key(nd)) == LUA_TNUMBER && | 690 | if (ttype(key(nd)) == LUA_TNUMBER && |
687 | ttype(val(nd)) != LUA_TNIL && | 691 | ttype(val(nd)) != LUA_TNIL && |
@@ -756,7 +760,7 @@ LUA_API int lua_getweakmode (lua_State *L, int index) { | |||
756 | LUA_API void lua_setweakmode (lua_State *L, int mode) { | 760 | LUA_API void lua_setweakmode (lua_State *L, int mode) { |
757 | lua_lock(L); | 761 | lua_lock(L); |
758 | api_check(L, ttype(L->top-1) == LUA_TTABLE); | 762 | api_check(L, ttype(L->top-1) == LUA_TTABLE); |
759 | hvalue(L->top-1)->weakmode = mode; | 763 | hvalue(L->top-1)->weakmode = cast(lu_byte, mode); |
760 | lua_unlock(L); | 764 | lua_unlock(L); |
761 | } | 765 | } |
762 | 766 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldebug.c,v 1.88 2001/09/07 17:39:10 roberto Exp $ | 2 | ** $Id: ldebug.c,v 1.90 2001/10/02 16:45:03 roberto Exp $ |
3 | ** Debug Interface | 3 | ** Debug Interface |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -221,12 +221,12 @@ static const l_char *travtagmethods (global_State *G, const TObject *o) { | |||
221 | 221 | ||
222 | 222 | ||
223 | static const l_char *travglobals (lua_State *L, const TObject *o) { | 223 | static const l_char *travglobals (lua_State *L, const TObject *o) { |
224 | Hash *g = L->gt; | 224 | Table *g = L->gt; |
225 | int i; | 225 | int i = sizenode(g); |
226 | for (i=0; i<g->size; i++) { | 226 | while (i--) { |
227 | if (luaO_equalObj(o, val(node(g, i))) && | 227 | Node *n = node(g, i); |
228 | ttype(key(node(g, i))) == LUA_TSTRING) | 228 | if (luaO_equalObj(o, val(n)) && ttype(key(n)) == LUA_TSTRING) |
229 | return getstr(tsvalue(key(node(g, i)))); | 229 | return getstr(tsvalue(key(n))); |
230 | } | 230 | } |
231 | return NULL; | 231 | return NULL; |
232 | } | 232 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 1.112 2001/10/02 16:45:03 roberto Exp $ | 2 | ** $Id: lgc.c,v 1.113 2001/10/17 21:12:57 roberto Exp $ |
3 | ** Garbage Collector | 3 | ** Garbage Collector |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -21,7 +21,7 @@ | |||
21 | 21 | ||
22 | 22 | ||
23 | typedef struct GCState { | 23 | typedef struct GCState { |
24 | Hash *tmark; /* list of marked tables to be visited */ | 24 | Table *tmark; /* list of marked tables to be visited */ |
25 | } GCState; | 25 | } GCState; |
26 | 26 | ||
27 | 27 | ||
@@ -76,7 +76,7 @@ static void markclosure (GCState *st, Closure *cl) { | |||
76 | } | 76 | } |
77 | 77 | ||
78 | 78 | ||
79 | static void marktable (GCState *st, Hash *h) { | 79 | static void marktable (GCState *st, Table *h) { |
80 | if (!ismarked(h)) { | 80 | if (!ismarked(h)) { |
81 | h->mark = st->tmark; /* chain it for later traversal */ | 81 | h->mark = st->tmark; /* chain it for later traversal */ |
82 | st->tmark = h; | 82 | st->tmark = h; |
@@ -145,18 +145,20 @@ static void removekey (Node *n) { | |||
145 | } | 145 | } |
146 | 146 | ||
147 | 147 | ||
148 | static void traversetable (GCState *st, Hash *h) { | 148 | static void traversetable (GCState *st, Table *h) { |
149 | int i; | 149 | int i; |
150 | int mode = h->weakmode; | 150 | int mode = h->weakmode; |
151 | if (mode == (LUA_WEAK_KEY | LUA_WEAK_VALUE)) | 151 | if (!(mode & LUA_WEAK_VALUE)) { |
152 | return; /* avoid traversing if both keys and values are weak */ | 152 | i = sizearray(h); |
153 | for (i=0; i<h->size; i++) { | 153 | while (i--) |
154 | markobject(st, &h->array[i]); | ||
155 | } | ||
156 | i = sizenode(h); | ||
157 | while (i--) { | ||
154 | Node *n = node(h, i); | 158 | Node *n = node(h, i); |
155 | if (ttype(val(n)) == LUA_TNIL) | 159 | if (ttype(val(n)) != LUA_TNIL) { |
156 | removekey(n); | ||
157 | else { | ||
158 | lua_assert(ttype(key(n)) != LUA_TNIL); | 160 | lua_assert(ttype(key(n)) != LUA_TNIL); |
159 | if (ttype(key(n)) != LUA_TNUMBER && !(mode & LUA_WEAK_KEY)) | 161 | if (!(mode & LUA_WEAK_KEY)) |
160 | markobject(st, key(n)); | 162 | markobject(st, key(n)); |
161 | if (!(mode & LUA_WEAK_VALUE)) | 163 | if (!(mode & LUA_WEAK_VALUE)) |
162 | markobject(st, val(n)); | 164 | markobject(st, val(n)); |
@@ -173,7 +175,7 @@ static void markall (lua_State *L) { | |||
173 | marktable(&st, G(L)->type2tag); | 175 | marktable(&st, G(L)->type2tag); |
174 | markobject(&st, &G(L)->registry); | 176 | markobject(&st, &G(L)->registry); |
175 | while (st.tmark) { /* mark tables */ | 177 | while (st.tmark) { /* mark tables */ |
176 | Hash *h = st.tmark; /* get first table from list */ | 178 | Table *h = st.tmark; /* get first table from list */ |
177 | st.tmark = h->mark; /* remove it from list */ | 179 | st.tmark = h->mark; /* remove it from list */ |
178 | traversetable(&st, h); | 180 | traversetable(&st, h); |
179 | } | 181 | } |
@@ -196,21 +198,27 @@ static int hasmark (const TObject *o) { | |||
196 | } | 198 | } |
197 | 199 | ||
198 | 200 | ||
199 | static void cleardeadnodes (Hash *h) { | 201 | static void cleardeadnodes (Table *h) { |
200 | int i; | 202 | int i; |
201 | for (i=0; i<h->size; i++) { | 203 | i = sizearray(h); |
204 | while (i--) { | ||
205 | TObject *o = &h->array[i]; | ||
206 | if (!hasmark(o)) | ||
207 | setnilvalue(o); /* remove value */ | ||
208 | } | ||
209 | i = sizenode(h); | ||
210 | while (i--) { | ||
202 | Node *n = node(h, i); | 211 | Node *n = node(h, i); |
203 | if (ttype(val(n)) == LUA_TNIL) continue; /* empty node */ | ||
204 | if (!hasmark(val(n)) || !hasmark(key(n))) { | 212 | if (!hasmark(val(n)) || !hasmark(key(n))) { |
205 | setnilvalue(val(n)); /* remove value */ | 213 | setnilvalue(val(n)); /* remove value ... */ |
206 | removekey(n); | 214 | removekey(n); /* ... and key */ |
207 | } | 215 | } |
208 | } | 216 | } |
209 | } | 217 | } |
210 | 218 | ||
211 | 219 | ||
212 | static void cleartables (global_State *G) { | 220 | static void cleartables (global_State *G) { |
213 | Hash *h; | 221 | Table *h; |
214 | for (h = G->roottable; h; h = h->next) { | 222 | for (h = G->roottable; h; h = h->next) { |
215 | if (h->weakmode && ismarked(h)) | 223 | if (h->weakmode && ismarked(h)) |
216 | cleardeadnodes(h); | 224 | cleardeadnodes(h); |
@@ -260,8 +268,8 @@ static void collectclosures (lua_State *L) { | |||
260 | 268 | ||
261 | 269 | ||
262 | static void collecttable (lua_State *L) { | 270 | static void collecttable (lua_State *L) { |
263 | Hash **p = &G(L)->roottable; | 271 | Table **p = &G(L)->roottable; |
264 | Hash *curr; | 272 | Table *curr; |
265 | while ((curr = *p) != NULL) { | 273 | while ((curr = *p) != NULL) { |
266 | if (ismarked(curr)) { | 274 | if (ismarked(curr)) { |
267 | curr->mark = curr; /* unmark */ | 275 | curr->mark = curr; /* unmark */ |
@@ -333,7 +341,7 @@ static void collectstrings (lua_State *L, int all) { | |||
333 | } | 341 | } |
334 | } | 342 | } |
335 | if (G(L)->strt.nuse < cast(ls_nstr, G(L)->strt.size/4) && | 343 | if (G(L)->strt.nuse < cast(ls_nstr, G(L)->strt.size/4) && |
336 | G(L)->strt.size > MINPOWER2) | 344 | G(L)->strt.size > 4) |
337 | luaS_resize(L, G(L)->strt.size/2); /* table is too big */ | 345 | luaS_resize(L, G(L)->strt.size/2); /* table is too big */ |
338 | } | 346 | } |
339 | 347 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lobject.c,v 1.69 2001/03/07 12:27:06 roberto Exp roberto $ | 2 | ** $Id: lobject.c,v 1.70 2001/03/26 14:31:49 roberto Exp $ |
3 | ** Some generic functions over Lua objects | 3 | ** Some generic functions over Lua objects |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -23,6 +23,34 @@ | |||
23 | const TObject luaO_nilobject = {LUA_TNIL, {NULL}}; | 23 | const TObject luaO_nilobject = {LUA_TNIL, {NULL}}; |
24 | 24 | ||
25 | 25 | ||
26 | int luaO_log2 (unsigned int x) { | ||
27 | static const lu_byte log_8[255] = { | ||
28 | 0, | ||
29 | 1,1, | ||
30 | 2,2,2,2, | ||
31 | 3,3,3,3,3,3,3,3, | ||
32 | 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, | ||
33 | 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, | ||
34 | 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, | ||
35 | 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, | ||
36 | 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, | ||
37 | 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, | ||
38 | 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, | ||
39 | 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, | ||
40 | }; | ||
41 | if (x & 0xffff0000) { | ||
42 | if (x & 0xff000000) return log_8[((x>>24) & 0xff) - 1]+24; | ||
43 | else return log_8[((x>>16) & 0xff) - 1]+16; | ||
44 | } | ||
45 | else { | ||
46 | if (x & 0x0000ff00) return log_8[((x>>8) & 0xff) - 1]+8; | ||
47 | else if (x) return log_8[(x & 0xff) - 1]; | ||
48 | return -1; /* special `log' for 0 */ | ||
49 | } | ||
50 | } | ||
51 | |||
52 | |||
53 | |||
26 | int luaO_equalObj (const TObject *t1, const TObject *t2) { | 54 | int luaO_equalObj (const TObject *t1, const TObject *t2) { |
27 | if (ttype(t1) != ttype(t2)) return 0; | 55 | if (ttype(t1) != ttype(t2)) return 0; |
28 | switch (ttype(t1)) { | 56 | switch (ttype(t1)) { |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lobject.h,v 1.113 2001/09/25 17:08:46 roberto Exp $ | 2 | ** $Id: lobject.h,v 1.114 2001/10/02 16:45:03 roberto Exp $ |
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 | */ |
@@ -39,7 +39,7 @@ typedef union { | |||
39 | union TString *ts; | 39 | union TString *ts; |
40 | union Udata *u; | 40 | union Udata *u; |
41 | union Closure *cl; | 41 | union Closure *cl; |
42 | struct Hash *h; | 42 | struct Table *h; |
43 | struct UpVal *v; | 43 | struct UpVal *v; |
44 | lua_Number n; /* LUA_TNUMBER */ | 44 | lua_Number n; /* LUA_TNUMBER */ |
45 | } Value; | 45 | } Value; |
@@ -214,7 +214,7 @@ typedef union Closure { | |||
214 | 214 | ||
215 | 215 | ||
216 | /* | 216 | /* |
217 | ** Hash Tables | 217 | ** Tables |
218 | */ | 218 | */ |
219 | 219 | ||
220 | typedef struct Node { | 220 | typedef struct Node { |
@@ -224,15 +224,17 @@ typedef struct Node { | |||
224 | } Node; | 224 | } Node; |
225 | 225 | ||
226 | 226 | ||
227 | typedef struct Hash { | 227 | typedef struct Table { |
228 | TObject *array; /* array part */ | ||
228 | Node *node; | 229 | Node *node; |
229 | int htag; | 230 | int htag; |
230 | int size; | 231 | int sizearray; /* size of `array' array */ |
232 | lu_byte lsizenode; /* log2 of size of `node' array */ | ||
233 | lu_byte weakmode; | ||
231 | Node *firstfree; /* this position is free; all positions after it are full */ | 234 | Node *firstfree; /* this position is free; all positions after it are full */ |
232 | struct Hash *next; | 235 | struct Table *next; |
233 | struct Hash *mark; /* marked tables (point to itself when not marked) */ | 236 | struct Table *mark; /* marked tables (point to itself when not marked) */ |
234 | int weakmode; | 237 | } Table; |
235 | } Hash; | ||
236 | 238 | ||
237 | 239 | ||
238 | /* unmarked tables are represented by pointing `mark' to themselves */ | 240 | /* unmarked tables are represented by pointing `mark' to themselves */ |
@@ -245,6 +247,10 @@ typedef struct Hash { | |||
245 | #define lmod(s,size) (cast(int, (s) & ((size)-1))) | 247 | #define lmod(s,size) (cast(int, (s) & ((size)-1))) |
246 | 248 | ||
247 | 249 | ||
250 | #define twoto(x) (1<<(x)) | ||
251 | #define sizenode(t) (twoto((t)->lsizenode)) | ||
252 | #define sizearray(t) ((t)->sizearray) | ||
253 | |||
248 | /* | 254 | /* |
249 | ** informations about a call (for debugging) | 255 | ** informations about a call (for debugging) |
250 | */ | 256 | */ |
@@ -262,6 +268,8 @@ typedef struct CallInfo { | |||
262 | 268 | ||
263 | extern const TObject luaO_nilobject; | 269 | extern const TObject luaO_nilobject; |
264 | 270 | ||
271 | int luaO_log2 (unsigned int x); | ||
272 | |||
265 | 273 | ||
266 | #define luaO_openspace(L,n,t) cast(t *, luaO_openspaceaux(L,(n)*sizeof(t))) | 274 | #define luaO_openspace(L,n,t) cast(t *, luaO_openspaceaux(L,(n)*sizeof(t))) |
267 | void *luaO_openspaceaux (lua_State *L, size_t n); | 275 | void *luaO_openspaceaux (lua_State *L, size_t n); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lopcodes.c,v 1.3 2001/08/27 15:14:57 roberto Exp $ | 2 | ** $Id: lopcodes.c,v 1.5 2001/09/07 17:39:10 roberto Exp $ |
3 | ** extracted automatically from lopcodes.h by mkprint.lua | 3 | ** extracted automatically from lopcodes.h by mkprint.lua |
4 | ** DO NOT EDIT | 4 | ** DO NOT EDIT |
5 | ** See Copyright Notice in lua.h | 5 | ** See Copyright Notice in lua.h |
@@ -77,7 +77,7 @@ const lu_byte luaP_opmodes[NUM_OPCODES] = { | |||
77 | ,opmode(0,0,0,0, 0,1,iABc) /* OP_SETGLOBAL */ | 77 | ,opmode(0,0,0,0, 0,1,iABc) /* OP_SETGLOBAL */ |
78 | ,opmode(0,0,0,0, 0,0,iABC) /* OP_SETUPVAL */ | 78 | ,opmode(0,0,0,0, 0,0,iABC) /* OP_SETUPVAL */ |
79 | ,opmode(0,0,1,1, 0,0,iABC) /* OP_SETTABLE */ | 79 | ,opmode(0,0,1,1, 0,0,iABC) /* OP_SETTABLE */ |
80 | ,opmode(0,0,0,0, 1,0,iABc) /* OP_NEWTABLE */ | 80 | ,opmode(0,0,0,0, 1,0,iABC) /* OP_NEWTABLE */ |
81 | ,opmode(0,0,1,1, 1,0,iABC) /* OP_SELF */ | 81 | ,opmode(0,0,1,1, 1,0,iABC) /* OP_SELF */ |
82 | ,opmode(0,0,1,1, 1,0,iABC) /* OP_ADD */ | 82 | ,opmode(0,0,1,1, 1,0,iABC) /* OP_ADD */ |
83 | ,opmode(0,0,1,1, 1,0,iABC) /* OP_SUB */ | 83 | ,opmode(0,0,1,1, 1,0,iABC) /* OP_SUB */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lopcodes.h,v 1.79 2001/08/27 15:14:57 roberto Exp $ | 2 | ** $Id: lopcodes.h,v 1.81 2001/09/07 17:39:10 roberto Exp $ |
3 | ** Opcodes for Lua virtual machine | 3 | ** Opcodes for Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -140,7 +140,7 @@ OP_SETGLOBAL,/* A Bc Gbl[Kst(Bc)] := R(A) */ | |||
140 | OP_SETUPVAL,/* A B UpValue[B] := R(A) */ | 140 | OP_SETUPVAL,/* A B UpValue[B] := R(A) */ |
141 | OP_SETTABLE,/* A B C R(B)[R/K(C)] := R(A) */ | 141 | OP_SETTABLE,/* A B C R(B)[R/K(C)] := R(A) */ |
142 | 142 | ||
143 | OP_NEWTABLE,/* A Bc R(A) := {} (size = Bc) */ | 143 | OP_NEWTABLE,/* A B C R(A) := {} (size = B,C) */ |
144 | 144 | ||
145 | OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[R/K(C)] */ | 145 | OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[R/K(C)] */ |
146 | 146 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.c,v 1.157 2001/09/25 17:06:48 roberto Exp $ | 2 | ** $Id: lparser.c,v 1.159 2001/10/02 16:41:36 roberto Exp $ |
3 | ** Lua Parser | 3 | ** Lua Parser |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -30,7 +30,8 @@ | |||
30 | ** or empty (k = `;' or `}') | 30 | ** or empty (k = `;' or `}') |
31 | */ | 31 | */ |
32 | typedef struct Constdesc { | 32 | typedef struct Constdesc { |
33 | int n; | 33 | int narray; |
34 | int nhash; | ||
34 | int k; | 35 | int k; |
35 | } Constdesc; | 36 | } Constdesc; |
36 | 37 | ||
@@ -315,7 +316,7 @@ static void open_func (LexState *ls, FuncState *fs) { | |||
315 | fs->jlt = NO_JUMP; | 316 | fs->jlt = NO_JUMP; |
316 | fs->freereg = 0; | 317 | fs->freereg = 0; |
317 | fs->nk = 0; | 318 | fs->nk = 0; |
318 | fs->h = luaH_new(ls->L, 0); | 319 | fs->h = luaH_new(ls->L, 0, 0); |
319 | fs->np = 0; | 320 | fs->np = 0; |
320 | fs->nlineinfo = 0; | 321 | fs->nlineinfo = 0; |
321 | fs->nlocvars = 0; | 322 | fs->nlocvars = 0; |
@@ -507,6 +508,7 @@ static int recfields (LexState *ls, expdesc *t) { | |||
507 | int n = 0; | 508 | int n = 0; |
508 | do { /* at least one element */ | 509 | do { /* at least one element */ |
509 | recfield(ls, t); | 510 | recfield(ls, t); |
511 | luaX_checklimit(ls, n, MAX_INT, l_s("items in a constructor")); | ||
510 | n++; | 512 | n++; |
511 | } while (anotherfield(ls)); | 513 | } while (anotherfield(ls)); |
512 | return n; | 514 | return n; |
@@ -523,8 +525,7 @@ static int listfields (LexState *ls, expdesc *t) { | |||
523 | expr(ls, &v); | 525 | expr(ls, &v); |
524 | while (anotherfield(ls)) { | 526 | while (anotherfield(ls)) { |
525 | luaK_exp2nextreg(fs, &v); | 527 | luaK_exp2nextreg(fs, &v); |
526 | luaX_checklimit(ls, n, MAXARG_Bc, | 528 | luaX_checklimit(ls, n, MAXARG_Bc, l_s("items in a constructor")); |
527 | l_s("`item groups' in a list initializer")); | ||
528 | if (n%LFIELDS_PER_FLUSH == 0) { | 529 | if (n%LFIELDS_PER_FLUSH == 0) { |
529 | luaK_codeABc(fs, OP_SETLIST, t->u.i.info, n-1); /* flush */ | 530 | luaK_codeABc(fs, OP_SETLIST, t->u.i.info, n-1); /* flush */ |
530 | fs->freereg = reg; /* free registers */ | 531 | fs->freereg = reg; /* free registers */ |
@@ -548,7 +549,7 @@ static int listfields (LexState *ls, expdesc *t) { | |||
548 | static void constructor_part (LexState *ls, expdesc *t, Constdesc *cd) { | 549 | static void constructor_part (LexState *ls, expdesc *t, Constdesc *cd) { |
549 | switch (ls->t.token) { | 550 | switch (ls->t.token) { |
550 | case l_c(';'): case l_c('}'): { /* constructor_part -> empty */ | 551 | case l_c(';'): case l_c('}'): { /* constructor_part -> empty */ |
551 | cd->n = 0; | 552 | cd->narray = cd->nhash = 0; |
552 | cd->k = ls->t.token; | 553 | cd->k = ls->t.token; |
553 | break; | 554 | break; |
554 | } | 555 | } |
@@ -559,13 +560,15 @@ static void constructor_part (LexState *ls, expdesc *t, Constdesc *cd) { | |||
559 | /* else go through to recfields */ | 560 | /* else go through to recfields */ |
560 | } | 561 | } |
561 | case l_c('['): { /* constructor_part -> recfields */ | 562 | case l_c('['): { /* constructor_part -> recfields */ |
562 | cd->n = recfields(ls, t); | 563 | cd->nhash = recfields(ls, t); |
564 | cd->narray = 0; | ||
563 | cd->k = 1; /* record */ | 565 | cd->k = 1; /* record */ |
564 | break; | 566 | break; |
565 | } | 567 | } |
566 | default: { /* constructor_part -> listfields */ | 568 | default: { /* constructor_part -> listfields */ |
567 | case_default: | 569 | case_default: |
568 | cd->n = listfields(ls, t); | 570 | cd->narray = listfields(ls, t); |
571 | cd->nhash = 0; | ||
569 | cd->k = 0; /* list */ | 572 | cd->k = 0; /* list */ |
570 | break; | 573 | break; |
571 | } | 574 | } |
@@ -577,24 +580,27 @@ static void constructor (LexState *ls, expdesc *t) { | |||
577 | /* constructor -> `{' constructor_part [`;' constructor_part] `}' */ | 580 | /* constructor -> `{' constructor_part [`;' constructor_part] `}' */ |
578 | FuncState *fs = ls->fs; | 581 | FuncState *fs = ls->fs; |
579 | int line = ls->linenumber; | 582 | int line = ls->linenumber; |
580 | int n; | 583 | int na, nh; |
581 | int pc; | 584 | int pc; |
582 | Constdesc cd; | 585 | Constdesc cd; |
583 | pc = luaK_codeABc(fs, OP_NEWTABLE, 0, 0); | 586 | pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); |
584 | init_exp(t, VRELOCABLE, pc); | 587 | init_exp(t, VRELOCABLE, pc); |
585 | luaK_exp2nextreg(ls->fs, t); /* fix it at stack top (for gc) */ | 588 | luaK_exp2nextreg(ls->fs, t); /* fix it at stack top (for gc) */ |
586 | check(ls, l_c('{')); | 589 | check(ls, l_c('{')); |
587 | constructor_part(ls, t, &cd); | 590 | constructor_part(ls, t, &cd); |
588 | n = cd.n; | 591 | na = cd.narray; |
592 | nh = cd.nhash; | ||
589 | if (optional(ls, l_c(';'))) { | 593 | if (optional(ls, l_c(';'))) { |
590 | Constdesc other_cd; | 594 | Constdesc other_cd; |
591 | constructor_part(ls, t, &other_cd); | 595 | constructor_part(ls, t, &other_cd); |
592 | check_condition(ls, (cd.k != other_cd.k), l_s("invalid constructor syntax")); | 596 | check_condition(ls,(cd.k != other_cd.k), l_s("invalid constructor syntax")); |
593 | n += other_cd.n; | 597 | na += other_cd.narray; |
598 | nh += other_cd.nhash; | ||
594 | } | 599 | } |
595 | check_match(ls, l_c('}'), l_c('{'), line); | 600 | check_match(ls, l_c('}'), l_c('{'), line); |
596 | luaX_checklimit(ls, n, MAXARG_Bc, l_s("elements in a table constructor")); | 601 | if (na > 0) |
597 | SETARG_Bc(fs->f->code[pc], n); /* set initial table size */ | 602 | SETARG_B(fs->f->code[pc], luaO_log2(na-1)+2); /* set initial table size */ |
603 | SETARG_C(fs->f->code[pc], luaO_log2(nh)+1); /* set initial table size */ | ||
598 | } | 604 | } |
599 | 605 | ||
600 | /* }====================================================================== */ | 606 | /* }====================================================================== */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.c,v 1.68 2001/09/07 17:39:10 roberto Exp $ | 2 | ** $Id: lstate.c,v 1.69 2001/10/17 21:12:57 roberto Exp $ |
3 | ** Global State | 3 | ** Global State |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -64,10 +64,10 @@ static void f_luaopen (lua_State *L, void *ud) { | |||
64 | G(L)->ntag = 0; | 64 | G(L)->ntag = 0; |
65 | G(L)->nblocks = sizeof(lua_State) + sizeof(global_State); | 65 | G(L)->nblocks = sizeof(lua_State) + sizeof(global_State); |
66 | luaD_init(L, so->stacksize); /* init stack */ | 66 | luaD_init(L, so->stacksize); /* init stack */ |
67 | L->gt = luaH_new(L, 10); /* table of globals */ | 67 | L->gt = luaH_new(L, 0, 4); /* table of globals */ |
68 | G(L)->type2tag = luaH_new(L, 10); | 68 | G(L)->type2tag = luaH_new(L, 0, 3); |
69 | sethvalue(&G(L)->registry, luaH_new(L, 0)); | 69 | sethvalue(&G(L)->registry, luaH_new(L, 0, 0)); |
70 | luaS_resize(L, MINPOWER2); | 70 | luaS_resize(L, 4); /* initial size of string table */ |
71 | luaX_init(L); | 71 | luaX_init(L); |
72 | luaT_init(L); | 72 | luaT_init(L); |
73 | G(L)->GCthreshold = 4*G(L)->nblocks; | 73 | G(L)->GCthreshold = 4*G(L)->nblocks; |
@@ -1,13 +1,17 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltable.c,v 1.83 2001/07/05 20:31:14 roberto Exp roberto $ | 2 | ** $Id: ltable.c,v 1.86 2001/09/07 17:30:16 roberto Exp $ |
3 | ** Lua tables (hash) | 3 | ** Lua tables (hash) |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
6 | 6 | ||
7 | 7 | ||
8 | /* | 8 | /* |
9 | ** Implementation of tables (aka arrays, objects, or hash tables); | 9 | ** Implementation of tables (aka arrays, objects, or hash tables). |
10 | ** uses a mix of chained scatter table with Brent's variation. | 10 | ** Tables keep its elements in two parts: an array part and a hash part. |
11 | ** Non-negative integer keys are all candidates to be kept in the array | ||
12 | ** part. The actual size of the array is the largest `n' such that at | ||
13 | ** least half the slots between 0 and n are in use. | ||
14 | ** Hash uses a mix of chained scatter table with Brent's variation. | ||
11 | ** A main invariant of these tables is that, if an element is not | 15 | ** A main invariant of these tables is that, if an element is not |
12 | ** in its main position (i.e. the `original' position that its hash gives | 16 | ** in its main position (i.e. the `original' position that its hash gives |
13 | ** to it), then the colliding element is in its own main position. | 17 | ** to it), then the colliding element is in its own main position. |
@@ -18,6 +22,7 @@ | |||
18 | */ | 22 | */ |
19 | 23 | ||
20 | 24 | ||
25 | |||
21 | #define LUA_PRIVATE | 26 | #define LUA_PRIVATE |
22 | #include "lua.h" | 27 | #include "lua.h" |
23 | 28 | ||
@@ -28,20 +33,34 @@ | |||
28 | #include "ltable.h" | 33 | #include "ltable.h" |
29 | 34 | ||
30 | 35 | ||
36 | /* | ||
37 | ** max size of array part is 2^MAXBITS | ||
38 | */ | ||
39 | #if BITS_INT > 24 | ||
40 | #define MAXBITS 24 | ||
41 | #else | ||
42 | #define MAXBITS (BITS_INT-1) | ||
43 | #endif | ||
44 | |||
45 | /* check whether `x' < 2^MAXBITS */ | ||
46 | #define toobig(x) ((((x)-1) >> MAXBITS) != 0) | ||
47 | |||
48 | |||
31 | 49 | ||
32 | #define TagDefault LUA_TTABLE | 50 | #define TagDefault LUA_TTABLE |
33 | 51 | ||
34 | 52 | ||
35 | #define hashnum(t,n) (node(t, lmod(cast(lu_hash, cast(ls_hash, n)), t->size))) | 53 | #define hashnum(t,n) \ |
36 | #define hashstr(t,str) (node(t, lmod((str)->tsv.hash, t->size))) | 54 | (node(t, lmod(cast(lu_hash, cast(ls_hash, n)), sizenode(t)))) |
37 | #define hashpointer(t,p) (node(t, lmod(IntPoint(p), t->size))) | 55 | #define hashstr(t,str) (node(t, lmod((str)->tsv.hash, sizenode(t)))) |
56 | #define hashpointer(t,p) (node(t, lmod(IntPoint(p), sizenode(t)))) | ||
38 | 57 | ||
39 | 58 | ||
40 | /* | 59 | /* |
41 | ** returns the `main' position of an element in a table (that is, the index | 60 | ** returns the `main' position of an element in a table (that is, the index |
42 | ** of its hash value) | 61 | ** of its hash value) |
43 | */ | 62 | */ |
44 | Node *luaH_mainposition (const Hash *t, const TObject *key) { | 63 | Node *luaH_mainposition (const Table *t, const TObject *key) { |
45 | switch (ttype(key)) { | 64 | switch (ttype(key)) { |
46 | case LUA_TNUMBER: | 65 | case LUA_TNUMBER: |
47 | return hashnum(t, nvalue(key)); | 66 | return hashnum(t, nvalue(key)); |
@@ -53,119 +72,237 @@ Node *luaH_mainposition (const Hash *t, const TObject *key) { | |||
53 | } | 72 | } |
54 | 73 | ||
55 | 74 | ||
56 | Node *luaH_next (lua_State *L, Hash *t, const TObject *key) { | 75 | /* |
76 | ** returns the index for `key' if `key' is an appropriate key to live in | ||
77 | ** the array part of the table, -1 otherwise. | ||
78 | */ | ||
79 | static int arrayindex (const TObject *key) { | ||
80 | if (ttype(key) == LUA_TNUMBER) { | ||
81 | int k = cast(int, nvalue(key)); | ||
82 | if (cast(lua_Number, k) == nvalue(key) && k >= 1 && !toobig(k)) | ||
83 | return k; | ||
84 | } | ||
85 | return -1; /* `key' did not match some condition */ | ||
86 | } | ||
87 | |||
88 | |||
89 | /* | ||
90 | ** returns the index of a `key' for table traversals. First goes all | ||
91 | ** elements in the array part, then elements in the hash part. The | ||
92 | ** beginning and end of a traversal are signalled by -1. | ||
93 | */ | ||
94 | int luaH_index (lua_State *L, Table *t, const TObject *key) { | ||
57 | int i; | 95 | int i; |
58 | if (ttype(key) == LUA_TNIL) | 96 | if (ttype(key) == LUA_TNIL) return -1; /* first iteration */ |
59 | i = 0; /* first iteration */ | 97 | i = arrayindex(key); |
98 | if (0 <= i && i < t->sizearray) { /* is `key' inside array part? */ | ||
99 | return i; /* yes; that's the index */ | ||
100 | } | ||
60 | else { | 101 | else { |
61 | const TObject *v = luaH_get(t, key); | 102 | const TObject *v = luaH_get(t, key); |
62 | if (v == &luaO_nilobject) | 103 | if (v == &luaO_nilobject) |
63 | luaD_error(L, l_s("invalid key for `next'")); | 104 | luaD_error(L, l_s("invalid key for `next'")); |
64 | i = cast(int, (cast(const lu_byte *, v) - | 105 | i = cast(int, (cast(const lu_byte *, v) - |
65 | cast(const lu_byte *, val(node(t, 0)))) / sizeof(Node)) + 1; | 106 | cast(const lu_byte *, val(node(t, 0)))) / sizeof(Node)); |
66 | } | 107 | return i + t->sizearray; /* hash elements are numbered after array ones */ |
67 | for (; i<t->size; i++) { | ||
68 | Node *n = node(t, i); | ||
69 | if (ttype(val(n)) != LUA_TNIL) | ||
70 | return n; | ||
71 | } | 108 | } |
72 | return NULL; /* no more elements */ | ||
73 | } | 109 | } |
74 | 110 | ||
75 | 111 | ||
76 | int luaH_nexti (Hash *t, int i) { | 112 | int luaH_nexti (Table *t, int i, TObject *where) { |
77 | while ((++i)<t->size) { | 113 | for (i++; i < t->sizearray; i++) { /* try first array part */ |
78 | if (ttype(val(node(t, i))) != LUA_TNIL) /* a non-nil value? */ | 114 | if (ttype(&t->array[i]) != LUA_TNIL) { /* a non-nil value? */ |
115 | setnvalue(where, i+1); | ||
116 | setobj(where+1, &t->array[i]); | ||
79 | return i; | 117 | return i; |
118 | } | ||
119 | } | ||
120 | for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */ | ||
121 | if (ttype(val(node(t, i))) != LUA_TNIL) { /* a non-nil value? */ | ||
122 | setobj(where, key(node(t, i))); | ||
123 | setobj(where+1, val(node(t, i))); | ||
124 | return i + t->sizearray; | ||
125 | } | ||
80 | } | 126 | } |
81 | return -1; /* no more elements */ | 127 | return -1; /* no more elements */ |
82 | } | 128 | } |
83 | 129 | ||
84 | 130 | ||
85 | #define check_grow(L, p, n) \ | ||
86 | if ((p) >= MAX_INT/(n)) luaD_error(L, l_s("table overflow")); | ||
87 | |||
88 | /* | 131 | /* |
89 | ** returns smaller power of 2 larger than `n' (minimum is MINPOWER2) | 132 | ** {============================================================= |
133 | ** Rehash | ||
134 | ** ============================================================== | ||
90 | */ | 135 | */ |
91 | static int power2 (lua_State *L, int n) { | 136 | |
92 | int p = MINPOWER2; | 137 | |
93 | while (p <= n) { | 138 | static void computesizes (int nums[], int ntotal, int *narray, int *nhash) { |
94 | check_grow(L, p, 2); | 139 | int n = 0; /* optimal (log of) size for array part */ |
95 | p *= 2; | 140 | int na = 0; /* number of elements to go to array part */ |
141 | int a = nums[0]; /* accumulator */ | ||
142 | int i; | ||
143 | for (i=1; i<=MAXBITS; i++) { | ||
144 | if (nums[i] == 0) continue; /* ignore empty slices */ | ||
145 | a += nums[i]; /* number of elements smaller than 2^i */ | ||
146 | if (a >= (1<<(i-1))) { /* more than half elements in use? */ | ||
147 | n = i; | ||
148 | na = a; | ||
149 | } | ||
150 | } | ||
151 | *nhash = ntotal - na; | ||
152 | *narray = (n == 0) ? 0 : (1<<n); | ||
153 | } | ||
154 | |||
155 | |||
156 | static void numuse (const Table *t, int *narray, int *nhash) { | ||
157 | int nums[MAXBITS+1]; | ||
158 | int i; | ||
159 | int totaluse = 0; | ||
160 | for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* init `nums' */ | ||
161 | /* count elements in array part */ | ||
162 | i = luaO_log2(t->sizearray) + 1; /* number of `slices' */ | ||
163 | while (i--) { /* for each slice [2^(i-1) to 2^i) */ | ||
164 | int to = twoto(i); | ||
165 | int from = to/2; | ||
166 | if (to > t->sizearray) to = t->sizearray; | ||
167 | for (; from < to; from++) | ||
168 | if (ttype(&t->array[from]) != LUA_TNIL) { | ||
169 | nums[i]++; | ||
170 | totaluse++; | ||
171 | } | ||
172 | } | ||
173 | /* count elements in hash part */ | ||
174 | i = sizenode(t); | ||
175 | while (i--) { | ||
176 | if (ttype(&t->node[i].val) != LUA_TNIL) { | ||
177 | int k = arrayindex(&t->node[i].key); | ||
178 | if (k >= 0) /* is `key' an appropriate array index? */ | ||
179 | nums[luaO_log2(k-1)+1]++; /* count as such */ | ||
180 | totaluse++; | ||
181 | } | ||
96 | } | 182 | } |
97 | return p; | 183 | computesizes(nums, totaluse, narray, nhash); |
98 | } | 184 | } |
99 | 185 | ||
100 | 186 | ||
101 | static void setnodevector (lua_State *L, Hash *t, int size) { | 187 | /* |
188 | ** (log of) minimum size for hash part of a table | ||
189 | */ | ||
190 | #define MINHASHSIZE 1 | ||
191 | |||
192 | |||
193 | static void setarrayvector (lua_State *L, Table *t, int size) { | ||
194 | int i; | ||
195 | if (size > twoto(MAXBITS)) | ||
196 | luaD_error(L, l_s("table overflow")); | ||
197 | luaM_reallocvector(L, t->array, t->sizearray, size, TObject); | ||
198 | for (i=t->sizearray; i<size; i++) | ||
199 | setnilvalue(&t->array[i]); | ||
200 | t->sizearray = size; | ||
201 | } | ||
202 | |||
203 | |||
204 | static void setnodevector (lua_State *L, Table *t, int lsize) { | ||
102 | int i; | 205 | int i; |
206 | int size; | ||
207 | if (lsize < MINHASHSIZE) lsize = MINHASHSIZE; | ||
208 | else if (lsize > MAXBITS) | ||
209 | luaD_error(L, l_s("table overflow")); | ||
210 | size = twoto(lsize); | ||
103 | t->node = luaM_newvector(L, size, Node); | 211 | t->node = luaM_newvector(L, size, Node); |
104 | for (i=0; i<size; i++) { | 212 | for (i=0; i<size; i++) { |
105 | t->node[i].next = NULL; | 213 | t->node[i].next = NULL; |
106 | setnilvalue(key(node(t, i))); | 214 | setnilvalue(key(node(t, i))); |
107 | setnilvalue(val(node(t, i))); | 215 | setnilvalue(val(node(t, i))); |
108 | } | 216 | } |
109 | t->size = size; | 217 | t->lsizenode = cast(lu_byte, lsize); |
110 | t->firstfree = node(t, size-1); /* first free position to be used */ | 218 | t->firstfree = node(t, size-1); /* first free position to be used */ |
111 | } | 219 | } |
112 | 220 | ||
113 | 221 | ||
114 | Hash *luaH_new (lua_State *L, int size) { | 222 | static void rehash (lua_State *L, Table *t) { |
115 | Hash *t = luaM_new(L, Hash); | 223 | int i; |
224 | int oldasize, oldhsize, nasize, nhsize; | ||
225 | Node *nold; | ||
226 | numuse(t, &nasize, &nhsize); /* compute new sizes for array and hash parts */ | ||
227 | oldasize = t->sizearray; | ||
228 | if (nasize > oldasize) /* should grow array part? */ | ||
229 | setarrayvector(L, t, nasize); | ||
230 | /* create new hash part with appropriate size */ | ||
231 | nold = t->node; /* save old hash ... */ | ||
232 | oldhsize = t->lsizenode; /* ... and (log of) old size */ | ||
233 | setnodevector(L, t, luaO_log2(nhsize+nhsize/4)+1); | ||
234 | /* re-insert elements */ | ||
235 | if (nasize < oldasize) { /* array part must shrink? */ | ||
236 | t->sizearray = nasize; | ||
237 | /* re-insert elements from vanishing slice */ | ||
238 | for (i=nasize; i<oldasize; i++) { | ||
239 | if (ttype(&t->array[i]) != LUA_TNIL) | ||
240 | luaH_setnum(L, t, i+1, &t->array[i]); | ||
241 | } | ||
242 | /* shink array */ | ||
243 | luaM_reallocvector(L, t->array, oldasize, nasize, TObject); | ||
244 | } | ||
245 | /* re-insert elements in hash part */ | ||
246 | i = twoto(oldhsize); | ||
247 | while (i--) { | ||
248 | Node *old = nold+i; | ||
249 | if (ttype(val(old)) != LUA_TNIL) | ||
250 | luaH_set(L, t, key(old), val(old)); | ||
251 | } | ||
252 | luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */ | ||
253 | } | ||
254 | |||
255 | /* | ||
256 | ** }============================================================= | ||
257 | */ | ||
258 | |||
259 | |||
260 | Table *luaH_new (lua_State *L, int narray, int lnhash) { | ||
261 | Table *t = luaM_new(L, Table); | ||
116 | t->htag = TagDefault; | 262 | t->htag = TagDefault; |
117 | t->next = G(L)->roottable; | 263 | t->next = G(L)->roottable; |
118 | G(L)->roottable = t; | 264 | G(L)->roottable = t; |
119 | t->mark = t; | 265 | t->mark = t; |
120 | t->size = 0; | ||
121 | t->weakmode = 0; | 266 | t->weakmode = 0; |
267 | /* temporary values (kept only if some malloc fails) */ | ||
268 | t->array = NULL; | ||
269 | t->sizearray = 0; | ||
270 | t->lsizenode = 0; | ||
122 | t->node = NULL; | 271 | t->node = NULL; |
123 | setnodevector(L, t, power2(L, size)); | 272 | setarrayvector(L, t, narray); |
273 | setnodevector(L, t, lnhash); | ||
124 | return t; | 274 | return t; |
125 | } | 275 | } |
126 | 276 | ||
127 | 277 | ||
128 | void luaH_free (lua_State *L, Hash *t) { | 278 | void luaH_free (lua_State *L, Table *t) { |
129 | luaM_freearray(L, t->node, t->size, Node); | 279 | lua_assert(t->lsizenode > 0 || t->node == NULL); |
280 | if (t->lsizenode > 0) | ||
281 | luaM_freearray(L, t->node, sizenode(t), Node); | ||
282 | luaM_freearray(L, t->array, t->sizearray, TObject); | ||
130 | luaM_freelem(L, t); | 283 | luaM_freelem(L, t); |
131 | } | 284 | } |
132 | 285 | ||
133 | 286 | ||
134 | static int numuse (const Hash *t) { | 287 | #if 0 |
135 | Node *v = t->node; | 288 | /* |
136 | int size = t->size; | 289 | ** try to remove an element from a hash table; cannot move any element |
137 | int realuse = 0; | 290 | ** (because gc can call `remove' during a table traversal) |
138 | int i; | 291 | */ |
139 | for (i=0; i<size; i++) { | 292 | void luaH_remove (Table *t, Node *e) { |
140 | if (ttype(&v[i].val) != LUA_TNIL) | 293 | Node *mp = luaH_mainposition(t, key(e)); |
141 | realuse++; | 294 | if (e != mp) { /* element not in its main position? */ |
142 | } | 295 | while (mp->next != e) mp = mp->next; /* find previous */ |
143 | return realuse; | 296 | mp->next = e->next; /* remove `e' from its list */ |
144 | } | ||
145 | |||
146 | |||
147 | static void rehash (lua_State *L, Hash *t) { | ||
148 | int oldsize = t->size; | ||
149 | Node *nold = t->node; | ||
150 | int nelems = numuse(t); | ||
151 | int i; | ||
152 | lua_assert(nelems<=oldsize); | ||
153 | if (nelems >= oldsize-oldsize/4) { /* using more than 3/4? */ | ||
154 | check_grow(L, oldsize, 2); | ||
155 | setnodevector(L, t, oldsize*2); /* grow array */ | ||
156 | } | 297 | } |
157 | else if (nelems <= oldsize/4 && /* less than 1/4? */ | 298 | else { |
158 | oldsize > MINPOWER2) | 299 | if (e->next != NULL) ?? |
159 | setnodevector(L, t, oldsize/2); /* shrink array */ | ||
160 | else | ||
161 | setnodevector(L, t, oldsize); /* just rehash; keep the same size */ | ||
162 | for (i=0; i<oldsize; i++) { | ||
163 | Node *old = nold+i; | ||
164 | if (ttype(val(old)) != LUA_TNIL) | ||
165 | luaH_set(L, t, key(old), val(old)); | ||
166 | } | 300 | } |
167 | luaM_freearray(L, nold, oldsize, Node); /* free old array */ | 301 | lua_assert(ttype(val(node)) == LUA_TNIL); |
302 | setnilvalue(key(e)); /* clear node `e' */ | ||
303 | e->next = NULL; | ||
168 | } | 304 | } |
305 | #endif | ||
169 | 306 | ||
170 | 307 | ||
171 | /* | 308 | /* |
@@ -175,7 +312,8 @@ static void rehash (lua_State *L, Hash *t) { | |||
175 | ** put new key in its main position; otherwise (colliding node is in its main | 312 | ** put new key in its main position; otherwise (colliding node is in its main |
176 | ** position), new key goes to an empty position. | 313 | ** position), new key goes to an empty position. |
177 | */ | 314 | */ |
178 | static TObject *newkey (lua_State *L, Hash *t, const TObject *key) { | 315 | static void newkey (lua_State *L, Table *t, const TObject *key, |
316 | const TObject *val) { | ||
179 | Node *mp = luaH_mainposition(t, key); | 317 | Node *mp = luaH_mainposition(t, key); |
180 | if (ttype(val(mp)) != LUA_TNIL) { /* main position is not free? */ | 318 | if (ttype(val(mp)) != LUA_TNIL) { /* main position is not free? */ |
181 | Node *othern = luaH_mainposition(t, key(mp)); /* `mp' of colliding node */ | 319 | Node *othern = luaH_mainposition(t, key(mp)); /* `mp' of colliding node */ |
@@ -197,21 +335,21 @@ static TObject *newkey (lua_State *L, Hash *t, const TObject *key) { | |||
197 | } | 335 | } |
198 | setobj(key(mp), key); | 336 | setobj(key(mp), key); |
199 | lua_assert(ttype(val(mp)) == LUA_TNIL); | 337 | lua_assert(ttype(val(mp)) == LUA_TNIL); |
338 | settableval(val(mp), val); | ||
200 | for (;;) { /* correct `firstfree' */ | 339 | for (;;) { /* correct `firstfree' */ |
201 | if (ttype(key(t->firstfree)) == LUA_TNIL) | 340 | if (ttype(key(t->firstfree)) == LUA_TNIL) |
202 | return val(mp); /* OK; table still has a free place */ | 341 | return; /* OK; table still has a free place */ |
203 | else if (t->firstfree == t->node) break; /* cannot decrement from here */ | 342 | else if (t->firstfree == t->node) break; /* cannot decrement from here */ |
204 | else (t->firstfree)--; | 343 | else (t->firstfree)--; |
205 | } | 344 | } |
206 | rehash(L, t); /* no more free places */ | 345 | rehash(L, t); /* no more free places; must create one */ |
207 | return newkey(L, t, key); /* `rehash' invalidates this insertion */ | ||
208 | } | 346 | } |
209 | 347 | ||
210 | 348 | ||
211 | /* | 349 | /* |
212 | ** generic search function | 350 | ** generic search function |
213 | */ | 351 | */ |
214 | static const TObject *luaH_getany (Hash *t, const TObject *key) { | 352 | static const TObject *luaH_getany (Table *t, const TObject *key) { |
215 | if (ttype(key) == LUA_TNIL) return &luaO_nilobject; | 353 | if (ttype(key) == LUA_TNIL) return &luaO_nilobject; |
216 | else { | 354 | else { |
217 | Node *n = luaH_mainposition(t, key); | 355 | Node *n = luaH_mainposition(t, key); |
@@ -227,21 +365,25 @@ static const TObject *luaH_getany (Hash *t, const TObject *key) { | |||
227 | /* | 365 | /* |
228 | ** search function for integers | 366 | ** search function for integers |
229 | */ | 367 | */ |
230 | const TObject *luaH_getnum (Hash *t, int key) { | 368 | const TObject *luaH_getnum (Table *t, int key) { |
231 | Node *n = hashnum(t, key); | 369 | if (1 <= key && key <= t->sizearray) |
232 | do { /* check whether `key' is somewhere in the chain */ | 370 | return &t->array[key-1]; |
233 | if (ttype(key(n)) == LUA_TNUMBER && nvalue(key(n)) == (lua_Number)key) | 371 | else { |
234 | return val(n); /* that's it */ | 372 | Node *n = hashnum(t, key); |
235 | else n = n->next; | 373 | do { /* check whether `key' is somewhere in the chain */ |
236 | } while (n); | 374 | if (ttype(key(n)) == LUA_TNUMBER && nvalue(key(n)) == (lua_Number)key) |
237 | return &luaO_nilobject; | 375 | return val(n); /* that's it */ |
376 | else n = n->next; | ||
377 | } while (n); | ||
378 | return &luaO_nilobject; | ||
379 | } | ||
238 | } | 380 | } |
239 | 381 | ||
240 | 382 | ||
241 | /* | 383 | /* |
242 | ** search function for strings | 384 | ** search function for strings |
243 | */ | 385 | */ |
244 | const TObject *luaH_getstr (Hash *t, TString *key) { | 386 | const TObject *luaH_getstr (Table *t, TString *key) { |
245 | Node *n = hashstr(t, key); | 387 | Node *n = hashstr(t, key); |
246 | do { /* check whether `key' is somewhere in the chain */ | 388 | do { /* check whether `key' is somewhere in the chain */ |
247 | if (ttype(key(n)) == LUA_TSTRING && tsvalue(key(n)) == key) | 389 | if (ttype(key(n)) == LUA_TSTRING && tsvalue(key(n)) == key) |
@@ -255,7 +397,7 @@ const TObject *luaH_getstr (Hash *t, TString *key) { | |||
255 | /* | 397 | /* |
256 | ** main search function | 398 | ** main search function |
257 | */ | 399 | */ |
258 | const TObject *luaH_get (Hash *t, const TObject *key) { | 400 | const TObject *luaH_get (Table *t, const TObject *key) { |
259 | switch (ttype(key)) { | 401 | switch (ttype(key)) { |
260 | case LUA_TSTRING: return luaH_getstr(t, tsvalue(key)); | 402 | case LUA_TSTRING: return luaH_getstr(t, tsvalue(key)); |
261 | case LUA_TNUMBER: { | 403 | case LUA_TNUMBER: { |
@@ -269,34 +411,40 @@ const TObject *luaH_get (Hash *t, const TObject *key) { | |||
269 | } | 411 | } |
270 | 412 | ||
271 | 413 | ||
272 | void luaH_set (lua_State *L, Hash *t, const TObject *key, const TObject *val) { | 414 | void luaH_set (lua_State *L, Table *t, const TObject *key, const TObject *val) { |
273 | const TObject *p = luaH_get(t, key); | 415 | const TObject *p = luaH_get(t, key); |
274 | if (p == &luaO_nilobject) { | 416 | if (p != &luaO_nilobject) { |
417 | settableval(p, val); | ||
418 | } | ||
419 | else { | ||
275 | if (ttype(key) == LUA_TNIL) luaD_error(L, l_s("table index is nil")); | 420 | if (ttype(key) == LUA_TNIL) luaD_error(L, l_s("table index is nil")); |
276 | p = newkey(L, t, key); | 421 | newkey(L, t, key, val); |
277 | } | 422 | } |
278 | settableval(p, val); | ||
279 | } | 423 | } |
280 | 424 | ||
281 | 425 | ||
282 | void luaH_setstr (lua_State *L, Hash *t, TString *key, const TObject *val) { | 426 | void luaH_setstr (lua_State *L, Table *t, TString *key, const TObject *val) { |
283 | const TObject *p = luaH_getstr(t, key); | 427 | const TObject *p = luaH_getstr(t, key); |
284 | if (p == &luaO_nilobject) { | 428 | if (p != &luaO_nilobject) { |
429 | settableval(p, val); | ||
430 | } | ||
431 | else { | ||
285 | TObject k; | 432 | TObject k; |
286 | setsvalue(&k, key); | 433 | setsvalue(&k, key); |
287 | p = newkey(L, t, &k); | 434 | newkey(L, t, &k, val); |
288 | } | 435 | } |
289 | settableval(p, val); | ||
290 | } | 436 | } |
291 | 437 | ||
292 | 438 | ||
293 | void luaH_setnum (lua_State *L, Hash *t, int key, const TObject *val) { | 439 | void luaH_setnum (lua_State *L, Table *t, int key, const TObject *val) { |
294 | const TObject *p = luaH_getnum(t, key); | 440 | const TObject *p = luaH_getnum(t, key); |
295 | if (p == &luaO_nilobject) { | 441 | if (p != &luaO_nilobject) { |
442 | settableval(p, val); | ||
443 | } | ||
444 | else { | ||
296 | TObject k; | 445 | TObject k; |
297 | setnvalue(&k, key); | 446 | setnvalue(&k, key); |
298 | p = newkey(L, t, &k); | 447 | newkey(L, t, &k, val); |
299 | } | 448 | } |
300 | settableval(p, val); | ||
301 | } | 449 | } |
302 | 450 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltable.h,v 1.34 2001/07/05 20:31:14 roberto Exp roberto $ | 2 | ** $Id: ltable.h,v 1.36 2001/08/31 19:46:07 roberto Exp $ |
3 | ** Lua tables (hash) | 3 | ** Lua tables (hash) |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -17,19 +17,19 @@ | |||
17 | #define settableval(p,v) setobj(cast(TObject *, p), v) | 17 | #define settableval(p,v) setobj(cast(TObject *, p), v) |
18 | 18 | ||
19 | 19 | ||
20 | const TObject *luaH_getnum (Hash *t, int key); | 20 | const TObject *luaH_getnum (Table *t, int key); |
21 | void luaH_setnum (lua_State *L, Hash *t, int key, const TObject *val); | 21 | void luaH_setnum (lua_State *L, Table *t, int key, const TObject *val); |
22 | const TObject *luaH_getstr (Hash *t, TString *key); | 22 | const TObject *luaH_getstr (Table *t, TString *key); |
23 | void luaH_setstr (lua_State *L, Hash *t, TString *key, const TObject *val); | 23 | void luaH_setstr (lua_State *L, Table *t, TString *key, const TObject *val); |
24 | const TObject *luaH_get (Hash *t, const TObject *key); | 24 | const TObject *luaH_get (Table *t, const TObject *key); |
25 | void luaH_set (lua_State *L, Hash *t, const TObject *key, const TObject *val); | 25 | void luaH_set (lua_State *L, Table *t, const TObject *key, const TObject *val); |
26 | Hash *luaH_new (lua_State *L, int nhash); | 26 | Table *luaH_new (lua_State *L, int narray, int lnhash); |
27 | void luaH_free (lua_State *L, Hash *t); | 27 | void luaH_free (lua_State *L, Table *t); |
28 | Node *luaH_next (lua_State *L, Hash *t, const TObject *r); | 28 | int luaH_index (lua_State *L, Table *t, const TObject *key); |
29 | int luaH_nexti (Hash *t, int i); | 29 | int luaH_nexti (Table *t, int i, TObject *where); |
30 | 30 | ||
31 | /* exported only for debugging */ | 31 | /* exported only for debugging */ |
32 | Node *luaH_mainposition (const Hash *t, const TObject *key); | 32 | Node *luaH_mainposition (const Table *t, const TObject *key); |
33 | 33 | ||
34 | 34 | ||
35 | #endif | 35 | #endif |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltests.c,v 1.92 2001/10/02 16:45:03 roberto Exp $ | 2 | ** $Id: ltests.c,v 1.93 2001/10/17 21:12:57 roberto Exp $ |
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 | */ |
@@ -211,12 +211,6 @@ static int listlocals (lua_State *L) { | |||
211 | /* }====================================================== */ | 211 | /* }====================================================== */ |
212 | 212 | ||
213 | 213 | ||
214 | static int pushbool (lua_State *L, int b) { | ||
215 | if (b) lua_pushnumber(L, 1); | ||
216 | else lua_pushnil(L); | ||
217 | return 1; | ||
218 | } | ||
219 | |||
220 | 214 | ||
221 | 215 | ||
222 | static int get_limits (lua_State *L) { | 216 | static int get_limits (lua_State *L) { |
@@ -252,7 +246,7 @@ static int hash_query (lua_State *L) { | |||
252 | } | 246 | } |
253 | else { | 247 | else { |
254 | TObject *o = luaA_index(L, 1); | 248 | TObject *o = luaA_index(L, 1); |
255 | Hash *t; | 249 | Table *t; |
256 | luaL_checktype(L, 2, LUA_TTABLE); | 250 | luaL_checktype(L, 2, LUA_TTABLE); |
257 | t = hvalue(luaA_index(L, 2)); | 251 | t = hvalue(luaA_index(L, 2)); |
258 | lua_pushnumber(L, luaH_mainposition(t, o) - t->node); | 252 | lua_pushnumber(L, luaH_mainposition(t, o) - t->node); |
@@ -262,16 +256,21 @@ static int hash_query (lua_State *L) { | |||
262 | 256 | ||
263 | 257 | ||
264 | static int table_query (lua_State *L) { | 258 | static int table_query (lua_State *L) { |
265 | const Hash *t; | 259 | const Table *t; |
266 | int i = luaL_opt_int(L, 2, -1); | 260 | int i = luaL_opt_int(L, 2, -1); |
267 | luaL_checktype(L, 1, LUA_TTABLE); | 261 | luaL_checktype(L, 1, LUA_TTABLE); |
268 | t = hvalue(luaA_index(L, 1)); | 262 | t = hvalue(luaA_index(L, 1)); |
269 | if (i == -1) { | 263 | if (i == -1) { |
270 | lua_pushnumber(L, t->size); | 264 | lua_pushnumber(L, t->sizearray); |
265 | lua_pushnumber(L, sizenode(t)); | ||
271 | lua_pushnumber(L, t->firstfree - t->node); | 266 | lua_pushnumber(L, t->firstfree - t->node); |
272 | return 2; | ||
273 | } | 267 | } |
274 | else if (i < t->size) { | 268 | else if (i < t->sizearray) { |
269 | lua_pushnumber(L, i); | ||
270 | luaA_pushobject(L, &t->array[i]); | ||
271 | lua_pushnil(L); | ||
272 | } | ||
273 | else if ((i -= t->sizearray) < sizenode(t)) { | ||
275 | if (ttype(val(node(t, i))) != LUA_TNIL || | 274 | if (ttype(val(node(t, i))) != LUA_TNIL || |
276 | ttype(key(node(t, i))) == LUA_TNIL || | 275 | ttype(key(node(t, i))) == LUA_TNIL || |
277 | ttype(key(node(t, i))) == LUA_TNUMBER) { | 276 | ttype(key(node(t, i))) == LUA_TNUMBER) { |
@@ -280,14 +279,12 @@ static int table_query (lua_State *L) { | |||
280 | else | 279 | else |
281 | lua_pushstring(L, "<undef>"); | 280 | lua_pushstring(L, "<undef>"); |
282 | luaA_pushobject(L, &t->node[i].val); | 281 | luaA_pushobject(L, &t->node[i].val); |
283 | if (t->node[i].next) { | 282 | if (t->node[i].next) |
284 | lua_pushnumber(L, t->node[i].next - t->node); | 283 | lua_pushnumber(L, t->node[i].next - t->node); |
285 | return 3; | ||
286 | } | ||
287 | else | 284 | else |
288 | return 2; | 285 | lua_pushnil(L); |
289 | } | 286 | } |
290 | return 0; | 287 | return 3; |
291 | } | 288 | } |
292 | 289 | ||
293 | 290 | ||
@@ -448,11 +445,12 @@ static int settagmethod (lua_State *L) { | |||
448 | return 1; | 445 | return 1; |
449 | } | 446 | } |
450 | 447 | ||
451 | static int equal (lua_State *L) { | 448 | |
452 | return pushbool(L, lua_equal(L, 1, 2)); | 449 | static int log2_aux (lua_State *L) { |
450 | lua_pushnumber(L, luaO_log2(luaL_check_int(L, 1))); | ||
451 | return 1; | ||
453 | } | 452 | } |
454 | 453 | ||
455 | |||
456 | 454 | ||
457 | /* | 455 | /* |
458 | ** {====================================================== | 456 | ** {====================================================== |
@@ -596,6 +594,13 @@ static int testC (lua_State *L) { | |||
596 | else | 594 | else |
597 | lua_pushnil(L); | 595 | lua_pushnil(L); |
598 | } | 596 | } |
597 | else if EQ(l_s("equal")) { | ||
598 | int a = getnum; | ||
599 | if (lua_equal(L, a, getnum)) | ||
600 | lua_pushnumber(L, 1); | ||
601 | else | ||
602 | lua_pushnil(L); | ||
603 | } | ||
599 | else if EQ(l_s("rawcall")) { | 604 | else if EQ(l_s("rawcall")) { |
600 | int narg = getnum; | 605 | int narg = getnum; |
601 | int nres = getnum; | 606 | int nres = getnum; |
@@ -656,7 +661,7 @@ static const struct luaL_reg tests_funcs[] = { | |||
656 | {l_s("closestate"), closestate}, | 661 | {l_s("closestate"), closestate}, |
657 | {l_s("doremote"), doremote}, | 662 | {l_s("doremote"), doremote}, |
658 | {l_s("settagmethod"), settagmethod}, | 663 | {l_s("settagmethod"), settagmethod}, |
659 | {l_s("equal"), equal}, | 664 | {l_s("log2"), log2_aux}, |
660 | {l_s("totalmem"), mem_query} | 665 | {l_s("totalmem"), mem_query} |
661 | }; | 666 | }; |
662 | 667 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 1.193 2001/09/07 17:39:10 roberto Exp $ | 2 | ** $Id: lvm.c,v 1.195 2001/10/02 16:45:03 roberto Exp $ |
3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -295,7 +295,7 @@ void luaV_strconc (lua_State *L, int total, StkId top) { | |||
295 | 295 | ||
296 | static void luaV_pack (lua_State *L, StkId firstelem) { | 296 | static void luaV_pack (lua_State *L, StkId firstelem) { |
297 | int i; | 297 | int i; |
298 | Hash *htab = luaH_new(L, 0); | 298 | Table *htab = luaH_new(L, 0, 0); |
299 | TObject n; | 299 | TObject n; |
300 | for (i=0; firstelem+i<L->top; i++) | 300 | for (i=0; firstelem+i<L->top; i++) |
301 | luaH_setnum(L, htab, i+1, firstelem+i); | 301 | luaH_setnum(L, htab, i+1, firstelem+i); |
@@ -420,7 +420,9 @@ StkId luaV_execute (lua_State *L, const LClosure *cl, StkId base) { | |||
420 | break; | 420 | break; |
421 | } | 421 | } |
422 | case OP_NEWTABLE: { | 422 | case OP_NEWTABLE: { |
423 | sethvalue(ra, luaH_new(L, GETARG_Bc(i))); | 423 | int b = GETARG_B(i); |
424 | if (b > 0) b = twoto(b-1); | ||
425 | sethvalue(ra, luaH_new(L, b, GETARG_C(i))); | ||
424 | luaV_checkGC(L, ra+1); | 426 | luaV_checkGC(L, ra+1); |
425 | break; | 427 | break; |
426 | } | 428 | } |
@@ -599,18 +601,15 @@ StkId luaV_execute (lua_State *L, const LClosure *cl, StkId base) { | |||
599 | /* go through */ | 601 | /* go through */ |
600 | } | 602 | } |
601 | case OP_TFORLOOP: { | 603 | case OP_TFORLOOP: { |
602 | Hash *t; | 604 | Table *t; |
603 | int n; | 605 | int n; |
604 | runtime_check(L, ttype(ra) == LUA_TTABLE && | 606 | runtime_check(L, ttype(ra) == LUA_TTABLE && |
605 | ttype(ra+1) == LUA_TNUMBER); | 607 | ttype(ra+1) == LUA_TNUMBER); |
606 | t = hvalue(ra); | 608 | t = hvalue(ra); |
607 | n = cast(int, nvalue(ra+1)); | 609 | n = cast(int, nvalue(ra+1)); |
608 | n = luaH_nexti(t, n); | 610 | n = luaH_nexti(t, n, ra+2); |
609 | if (n != -1) { /* repeat loop? */ | 611 | if (n != -1) { /* repeat loop? */ |
610 | Node *node = node(t, n); | ||
611 | setnvalue(ra+1, n); /* index */ | 612 | setnvalue(ra+1, n); /* index */ |
612 | setobj(ra+2, key(node)); | ||
613 | setobj(ra+3, val(node)); | ||
614 | dojump(pc, i); /* repeat loop */ | 613 | dojump(pc, i); /* repeat loop */ |
615 | } | 614 | } |
616 | break; | 615 | break; |
@@ -619,7 +618,7 @@ StkId luaV_execute (lua_State *L, const LClosure *cl, StkId base) { | |||
619 | case OP_SETLISTO: { | 618 | case OP_SETLISTO: { |
620 | int bc; | 619 | int bc; |
621 | int n; | 620 | int n; |
622 | Hash *h; | 621 | Table *h; |
623 | runtime_check(L, ttype(ra) == LUA_TTABLE); | 622 | runtime_check(L, ttype(ra) == LUA_TTABLE); |
624 | h = hvalue(ra); | 623 | h = hvalue(ra); |
625 | bc = GETARG_Bc(i); | 624 | bc = GETARG_Bc(i); |