aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lcode.c40
-rw-r--r--lcode.h4
-rw-r--r--lopcodes.h23
-rw-r--r--lparser.c29
-rw-r--r--lvm.c28
-rw-r--r--testes/nextvar.lua28
6 files changed, 80 insertions, 72 deletions
diff --git a/lcode.c b/lcode.c
index 1ff32ed7..a0d7757a 100644
--- a/lcode.c
+++ b/lcode.c
@@ -372,7 +372,7 @@ static void removelastinstruction (FuncState *fs) {
372** Emit instruction 'i', checking for array sizes and saving also its 372** Emit instruction 'i', checking for array sizes and saving also its
373** line information. Return 'i' position. 373** line information. Return 'i' position.
374*/ 374*/
375static int luaK_code (FuncState *fs, Instruction i) { 375int luaK_code (FuncState *fs, Instruction i) {
376 Proto *f = fs->f; 376 Proto *f = fs->f;
377 /* put new instruction in code array */ 377 /* put new instruction in code array */
378 luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction, 378 luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction,
@@ -430,7 +430,7 @@ static int codesJ (FuncState *fs, OpCode o, int sj, int k) {
430/* 430/*
431** Emit an "extra argument" instruction (format 'iAx') 431** Emit an "extra argument" instruction (format 'iAx')
432*/ 432*/
433int luaK_codeextraarg (FuncState *fs, int a) { 433static int codeextraarg (FuncState *fs, int a) {
434 lua_assert(a <= MAXARG_Ax); 434 lua_assert(a <= MAXARG_Ax);
435 return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, a)); 435 return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, a));
436} 436}
@@ -446,7 +446,7 @@ static int luaK_codek (FuncState *fs, int reg, int k) {
446 return luaK_codeABx(fs, OP_LOADK, reg, k); 446 return luaK_codeABx(fs, OP_LOADK, reg, k);
447 else { 447 else {
448 int p = luaK_codeABx(fs, OP_LOADKX, reg, 0); 448 int p = luaK_codeABx(fs, OP_LOADKX, reg, 0);
449 luaK_codeextraarg(fs, k); 449 codeextraarg(fs, k);
450 return p; 450 return p;
451 } 451 }
452} 452}
@@ -1672,6 +1672,22 @@ void luaK_fixline (FuncState *fs, int line) {
1672} 1672}
1673 1673
1674 1674
1675void luaK_settablesize (FuncState *fs, int pc, int ra, int rc, int rb) {
1676 Instruction *inst = &fs->f->code[pc];
1677 int extra = 0;
1678 int k = 0;
1679 if (rb != 0)
1680 rb = luaO_ceillog2(rb) + 1; /* hash size */
1681 if (rc > MAXARG_C) { /* does it need the extra argument? */
1682 extra = rc / (MAXARG_C + 1);
1683 rc %= (MAXARG_C + 1);
1684 k = 1;
1685 }
1686 *inst = CREATE_ABCk(OP_NEWTABLE, ra, rb, rc, k);
1687 *(inst + 1) = CREATE_Ax(OP_EXTRAARG, extra);
1688}
1689
1690
1675/* 1691/*
1676** Emit a SETLIST instruction. 1692** Emit a SETLIST instruction.
1677** 'base' is register that keeps table; 1693** 'base' is register that keeps table;
@@ -1680,17 +1696,17 @@ void luaK_fixline (FuncState *fs, int line) {
1680** table (or LUA_MULTRET to add up to stack top). 1696** table (or LUA_MULTRET to add up to stack top).
1681*/ 1697*/
1682void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { 1698void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) {
1683 int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1;
1684 int b = (tostore == LUA_MULTRET) ? 0 : tostore;
1685 lua_assert(tostore != 0 && tostore <= LFIELDS_PER_FLUSH); 1699 lua_assert(tostore != 0 && tostore <= LFIELDS_PER_FLUSH);
1686 if (c <= MAXARG_C) 1700 if (tostore == LUA_MULTRET)
1687 luaK_codeABC(fs, OP_SETLIST, base, b, c); 1701 tostore = 0;
1688 else if (c <= MAXARG_Ax) { 1702 if (nelems <= MAXARG_C)
1689 luaK_codeABC(fs, OP_SETLIST, base, b, 0); 1703 luaK_codeABC(fs, OP_SETLIST, base, tostore, nelems);
1690 luaK_codeextraarg(fs, c); 1704 else {
1705 int extra = nelems / (MAXARG_C + 1);
1706 nelems %= (MAXARG_C + 1);
1707 luaK_codeABCk(fs, OP_SETLIST, base, tostore, nelems, 1);
1708 codeextraarg(fs, extra);
1691 } 1709 }
1692 else
1693 luaX_syntaxerror(fs->ls, "constructor too long");
1694 fs->freereg = base + 1; /* free registers with list values */ 1710 fs->freereg = base + 1; /* free registers with list values */
1695} 1711}
1696 1712
diff --git a/lcode.h b/lcode.h
index a924722c..0c12bb64 100644
--- a/lcode.h
+++ b/lcode.h
@@ -51,11 +51,11 @@ typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;
51 51
52#define luaK_jumpto(fs,t) luaK_patchlist(fs, luaK_jump(fs), t) 52#define luaK_jumpto(fs,t) luaK_patchlist(fs, luaK_jump(fs), t)
53 53
54LUAI_FUNC int luaK_code (FuncState *fs, Instruction i);
54LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); 55LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx);
55LUAI_FUNC int luaK_codeAsBx (FuncState *fs, OpCode o, int A, int Bx); 56LUAI_FUNC int luaK_codeAsBx (FuncState *fs, OpCode o, int A, int Bx);
56LUAI_FUNC int luaK_codeABCk (FuncState *fs, OpCode o, int A, 57LUAI_FUNC int luaK_codeABCk (FuncState *fs, OpCode o, int A,
57 int B, int C, int k); 58 int B, int C, int k);
58LUAI_FUNC int luaK_codeextraarg (FuncState *fs, int a);
59LUAI_FUNC int luaK_isKint (expdesc *e); 59LUAI_FUNC int luaK_isKint (expdesc *e);
60LUAI_FUNC int luaK_exp2const (FuncState *fs, const expdesc *e, TValue *v); 60LUAI_FUNC int luaK_exp2const (FuncState *fs, const expdesc *e, TValue *v);
61LUAI_FUNC void luaK_fixline (FuncState *fs, int line); 61LUAI_FUNC void luaK_fixline (FuncState *fs, int line);
@@ -87,6 +87,8 @@ LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v, int line);
87LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); 87LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v);
88LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, 88LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1,
89 expdesc *v2, int line); 89 expdesc *v2, int line);
90LUAI_FUNC void luaK_settablesize (FuncState *fs, int pc,
91 int ra, int rb, int rc);
90LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); 92LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore);
91LUAI_FUNC void luaK_finish (FuncState *fs); 93LUAI_FUNC void luaK_finish (FuncState *fs);
92LUAI_FUNC l_noret luaK_semerror (LexState *ls, const char *msg); 94LUAI_FUNC l_noret luaK_semerror (LexState *ls, const char *msg);
diff --git a/lopcodes.h b/lopcodes.h
index 0b23fa6f..371cb3ae 100644
--- a/lopcodes.h
+++ b/lopcodes.h
@@ -214,7 +214,7 @@ OP_SETTABLE,/* A B C R(A)[R(B)] := RK(C) */
214OP_SETI,/* A B C R(A)[B] := RK(C) */ 214OP_SETI,/* A B C R(A)[B] := RK(C) */
215OP_SETFIELD,/* A B C R(A)[K(B):string] := RK(C) */ 215OP_SETFIELD,/* A B C R(A)[K(B):string] := RK(C) */
216 216
217OP_NEWTABLE,/* A B C R(A) := {} (size = B,C) */ 217OP_NEWTABLE,/* A B C R(A) := {} */
218 218
219OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C):string] */ 219OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C):string] */
220 220
@@ -321,12 +321,17 @@ OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */
321 321
322 (*) In OP_RETURN, if (B == 0) then return up to 'top'. 322 (*) In OP_RETURN, if (B == 0) then return up to 'top'.
323 323
324 (*) In OP_SETLIST, if (B == 0) then real B = 'top'; if (C == 0) then 324 (*) In OP_LOADKX and OP_NEWTABLE, the next instruction is always
325 next 'instruction' is EXTRAARG(real C).
326
327 (*) In OP_LOADKX and OP_NEWTABLE, the next 'instruction' is always
328 EXTRAARG. 325 EXTRAARG.
329 326
327 (*) In OP_SETLIST, if (B == 0) then real B = 'top'; if k, then
328 real C = EXTRAARG _ C (the bits of EXTRAARG concatenated with the
329 bits of C).
330
331 (*) In OP_NEWTABLE, B is log2 of the hash size (which is always a
332 power of 2) plus 1, or zero for size zero. If not k, the array size
333 is C. Otherwise, the array size is EXTRAARG _ C.
334
330 (*) For comparisons, k specifies what condition the test should accept 335 (*) For comparisons, k specifies what condition the test should accept
331 (true or false). 336 (true or false).
332 337
@@ -375,12 +380,4 @@ LUAI_DDEC(const lu_byte luaP_opmodes[NUM_OPCODES];)
375/* number of list items to accumulate before a SETLIST instruction */ 380/* number of list items to accumulate before a SETLIST instruction */
376#define LFIELDS_PER_FLUSH 50 381#define LFIELDS_PER_FLUSH 50
377 382
378
379/*
380** In OP_NEWTABLE, array sizes smaller than LIMTABSZ are represented
381** directly in R(B). Otherwise, array size is given by
382** (R(B) - LIMTABSZ) + EXTRAARG * LFIELDS_PER_FLUSH
383*/
384#define LIMTABSZ (MAXARG_B - LFIELDS_PER_FLUSH)
385
386#endif 383#endif
diff --git a/lparser.c b/lparser.c
index 193e50f1..ea810006 100644
--- a/lparser.c
+++ b/lparser.c
@@ -815,7 +815,7 @@ typedef struct ConsControl {
815 expdesc v; /* last list item read */ 815 expdesc v; /* last list item read */
816 expdesc *t; /* table descriptor */ 816 expdesc *t; /* table descriptor */
817 int nh; /* total number of 'record' elements */ 817 int nh; /* total number of 'record' elements */
818 int na; /* total number of array elements */ 818 int na; /* number of array elements already stored */
819 int tostore; /* number of array elements pending to be stored */ 819 int tostore; /* number of array elements pending to be stored */
820} ConsControl; 820} ConsControl;
821 821
@@ -847,6 +847,7 @@ static void closelistfield (FuncState *fs, ConsControl *cc) {
847 cc->v.k = VVOID; 847 cc->v.k = VVOID;
848 if (cc->tostore == LFIELDS_PER_FLUSH) { 848 if (cc->tostore == LFIELDS_PER_FLUSH) {
849 luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); /* flush */ 849 luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); /* flush */
850 cc->na += cc->tostore;
850 cc->tostore = 0; /* no more items pending */ 851 cc->tostore = 0; /* no more items pending */
851 } 852 }
852} 853}
@@ -864,13 +865,13 @@ static void lastlistfield (FuncState *fs, ConsControl *cc) {
864 luaK_exp2nextreg(fs, &cc->v); 865 luaK_exp2nextreg(fs, &cc->v);
865 luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); 866 luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore);
866 } 867 }
868 cc->na += cc->tostore;
867} 869}
868 870
869 871
870static void listfield (LexState *ls, ConsControl *cc) { 872static void listfield (LexState *ls, ConsControl *cc) {
871 /* listfield -> exp */ 873 /* listfield -> exp */
872 expr(ls, &cc->v); 874 expr(ls, &cc->v);
873 cc->na++;
874 cc->tostore++; 875 cc->tostore++;
875} 876}
876 877
@@ -897,22 +898,6 @@ static void field (LexState *ls, ConsControl *cc) {
897} 898}
898 899
899 900
900static void settablesize (FuncState *fs, ConsControl *cc, int pc) {
901 Instruction *inst = &fs->f->code[pc];
902 int rc = (cc->nh == 0) ? 0 : luaO_ceillog2(cc->nh) + 1;
903 int rb = cc->na;
904 int extra = 0;
905 if (rb >= LIMTABSZ) {
906 extra = rb / LFIELDS_PER_FLUSH;
907 rb = rb % LFIELDS_PER_FLUSH + LIMTABSZ;
908 checklimit(fs, extra, MAXARG_Ax, "items in a constructor");
909 }
910 SETARG_C(*inst, rc); /* set initial table size */
911 SETARG_B(*inst, rb); /* set initial array size */
912 SETARG_Ax(*(inst + 1), extra);
913}
914
915
916static void constructor (LexState *ls, expdesc *t) { 901static void constructor (LexState *ls, expdesc *t) {
917 /* constructor -> '{' [ field { sep field } [sep] ] '}' 902 /* constructor -> '{' [ field { sep field } [sep] ] '}'
918 sep -> ',' | ';' */ 903 sep -> ',' | ';' */
@@ -920,12 +905,12 @@ static void constructor (LexState *ls, expdesc *t) {
920 int line = ls->linenumber; 905 int line = ls->linenumber;
921 int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); 906 int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0);
922 ConsControl cc; 907 ConsControl cc;
923 luaK_codeextraarg(fs, 0); 908 luaK_code(fs, 0); /* space for extra arg. */
924 cc.na = cc.nh = cc.tostore = 0; 909 cc.na = cc.nh = cc.tostore = 0;
925 cc.t = t; 910 cc.t = t;
926 init_exp(t, VRELOC, pc); 911 init_exp(t, VNONRELOC, fs->freereg); /* table will be at stack top */
912 luaK_reserveregs(fs, 1);
927 init_exp(&cc.v, VVOID, 0); /* no value (yet) */ 913 init_exp(&cc.v, VVOID, 0); /* no value (yet) */
928 luaK_exp2nextreg(ls->fs, t); /* fix it at stack top */
929 checknext(ls, '{'); 914 checknext(ls, '{');
930 do { 915 do {
931 lua_assert(cc.v.k == VVOID || cc.tostore > 0); 916 lua_assert(cc.v.k == VVOID || cc.tostore > 0);
@@ -935,7 +920,7 @@ static void constructor (LexState *ls, expdesc *t) {
935 } while (testnext(ls, ',') || testnext(ls, ';')); 920 } while (testnext(ls, ',') || testnext(ls, ';'));
936 check_match(ls, '}', '{', line); 921 check_match(ls, '}', '{', line);
937 lastlistfield(fs, &cc); 922 lastlistfield(fs, &cc);
938 settablesize(fs, &cc, pc); 923 luaK_settablesize(fs, pc, t->u.info, cc.na, cc.nh);
939} 924}
940 925
941/* }====================================================================== */ 926/* }====================================================================== */
diff --git a/lvm.c b/lvm.c
index ec65ea78..d365bcdd 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1247,18 +1247,19 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1247 vmbreak; 1247 vmbreak;
1248 } 1248 }
1249 vmcase(OP_NEWTABLE) { 1249 vmcase(OP_NEWTABLE) {
1250 int b = GETARG_B(i); 1250 int b = GETARG_B(i); /* log2(hash size) + 1 */
1251 int c = GETARG_C(i); 1251 int c = GETARG_C(i); /* array size */
1252 Table *t; 1252 Table *t;
1253 c = (c == 0) ? 0 : 1 << (c - 1); /* size is 2^c */ 1253 if (b > 0)
1254 if (b >= LIMTABSZ) 1254 b = 1 << (b - 1); /* size is 2^(b - 1) */
1255 b += LFIELDS_PER_FLUSH * GETARG_Ax(*pc) - LIMTABSZ; 1255 if (TESTARG_k(i))
1256 c += GETARG_Ax(*pc) * (MAXARG_C + 1);
1256 pc++; /* skip extra argument */ 1257 pc++; /* skip extra argument */
1257 L->top = ci->top; /* correct top in case of GC */ 1258 L->top = ci->top; /* correct top in case of GC */
1258 t = luaH_new(L); /* memory allocation */ 1259 t = luaH_new(L); /* memory allocation */
1259 sethvalue2s(L, ra, t); 1260 sethvalue2s(L, ra, t);
1260 if (b != 0 || c != 0) 1261 if (b != 0 || c != 0)
1261 luaH_resize(L, t, b, c); /* idem */ 1262 luaH_resize(L, t, c, b); /* idem */
1262 checkGC(L, ra + 1); 1263 checkGC(L, ra + 1);
1263 vmbreak; 1264 vmbreak;
1264 } 1265 }
@@ -1763,18 +1764,17 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1763 } 1764 }
1764 vmcase(OP_SETLIST) { 1765 vmcase(OP_SETLIST) {
1765 int n = GETARG_B(i); 1766 int n = GETARG_B(i);
1766 int c = GETARG_C(i); 1767 unsigned int last = GETARG_C(i);
1767 unsigned int last; 1768 Table *h = hvalue(s2v(ra));
1768 Table *h;
1769 if (n == 0) 1769 if (n == 0)
1770 n = cast_int(L->top - ra) - 1; 1770 n = cast_int(L->top - ra) - 1; /* get up to the top */
1771 else 1771 else
1772 L->top = ci->top; /* correct top in case of GC */ 1772 L->top = ci->top; /* correct top in case of GC */
1773 if (c == 0) { 1773 last += n;
1774 c = GETARG_Ax(*pc); pc++; 1774 if (TESTARG_k(i)) {
1775 last += GETARG_Ax(*pc) * (MAXARG_C + 1);
1776 pc++;
1775 } 1777 }
1776 h = hvalue(s2v(ra));
1777 last = ((c-1)*LFIELDS_PER_FLUSH) + n;
1778 if (last > luaH_realasize(h)) /* needs more space? */ 1778 if (last > luaH_realasize(h)) /* needs more space? */
1779 luaH_resizearray(L, h, last); /* preallocate it at once */ 1779 luaH_resizearray(L, h, last); /* preallocate it at once */
1780 for (; n > 0; n--) { 1780 for (; n > 0; n--) {
diff --git a/testes/nextvar.lua b/testes/nextvar.lua
index bdc9fc29..a7fe625e 100644
--- a/testes/nextvar.lua
+++ b/testes/nextvar.lua
@@ -80,15 +80,23 @@ local sizes = {0, 1, 2, 3, 4, 5, 7, 8, 9, 15, 16, 17,
80 80
81for _, sa in ipairs(sizes) do -- 'sa' is size of the array part 81for _, sa in ipairs(sizes) do -- 'sa' is size of the array part
82 local arr = {"return {"} 82 local arr = {"return {"}
83 -- array part 83 for i = 1, sa do arr[1 + i] = "1," end -- build array part
84 for i = 1, sa do arr[1 + i] = "1," end
85 for _, sh in ipairs(sizes) do -- 'sh' is size of the hash part 84 for _, sh in ipairs(sizes) do -- 'sh' is size of the hash part
86 for j = 1, sh do -- hash part 85 for j = 1, sh do -- build hash part
87 arr[1 + sa + j] = string.format('k%x=%d,', j, j) 86 arr[1 + sa + j] = string.format('k%x=%d,', j, j)
88 end 87 end
89 arr[1 + sa + sh + 1] = "}" 88 arr[1 + sa + sh + 1] = "}"
90 local prog = table.concat(arr) 89 local prog = table.concat(arr)
91 local t = assert(load(prog))() 90 local f = assert(load(prog))
91 f() -- call once to ensure stack space
92 -- make sure table is not resized after being created
93 if sa == 0 or sh == 0 then
94 T.alloccount(2); -- header + array or hash part
95 else
96 T.alloccount(3); -- header + array part + hash part
97 end
98 local t = f()
99 T.alloccount();
92 assert(#t == sa) 100 assert(#t == sa)
93 check(t, sa, mp2(sh)) 101 check(t, sa, mp2(sh))
94 end 102 end
@@ -99,12 +107,12 @@ end
99local a = {} 107local a = {}
100for i=1,sizes[#sizes] do a[i] = i end -- build auxiliary table 108for i=1,sizes[#sizes] do a[i] = i end -- build auxiliary table
101for k in ipairs(sizes) do 109for k in ipairs(sizes) do
102 local a = {table.unpack(a,1,k)} 110 local t = {table.unpack(a,1,k)}
103 assert(#a == k) 111 assert(#t == k)
104 check(a, k, 0) 112 check(t, k, 0)
105 a = {1,2,3,table.unpack(a,1,k)} 113 t = {1,2,3,table.unpack(a,1,k)}
106 check(a, k+3, 0) 114 check(t, k+3, 0)
107 assert(#a == k + 3) 115 assert(#t == k + 3)
108end 116end
109 117
110 118