New instruction format for SETLIST/NEWTABLE

New instruction format 'ivABC' (a variant of iABC where parameter vC has
10 bits) allows constructors of up to 1024 elements to be coded without
EXTRAARG.
This commit is contained in:
Roberto Ierusalimschy 2024-06-28 11:18:14 -03:00
parent 6ac7219da3
commit c403e456b6
7 changed files with 97 additions and 47 deletions

59
lcode.c
View File

@ -390,32 +390,40 @@ int luaK_code (FuncState *fs, Instruction i) {
** Format and emit an 'iABC' instruction. (Assertions check consistency ** Format and emit an 'iABC' instruction. (Assertions check consistency
** of parameters versus opcode.) ** of parameters versus opcode.)
*/ */
int luaK_codeABCk (FuncState *fs, OpCode o, int a, int b, int c, int k) { int luaK_codeABCk (FuncState *fs, OpCode o, int A, int B, int C, int k) {
lua_assert(getOpMode(o) == iABC); lua_assert(getOpMode(o) == iABC);
lua_assert(a <= MAXARG_A && b <= MAXARG_B && lua_assert(A <= MAXARG_A && B <= MAXARG_B &&
c <= MAXARG_C && (k & ~1) == 0); C <= MAXARG_C && (k & ~1) == 0);
return luaK_code(fs, CREATE_ABCk(o, a, b, c, k)); return luaK_code(fs, CREATE_ABCk(o, A, B, C, k));
}
int luaK_codevABCk (FuncState *fs, OpCode o, int A, int B, int C, int k) {
lua_assert(getOpMode(o) == ivABC);
lua_assert(A <= MAXARG_A && B <= MAXARG_vB &&
C <= MAXARG_vC && (k & ~1) == 0);
return luaK_code(fs, CREATE_vABCk(o, A, B, C, k));
} }
/* /*
** Format and emit an 'iABx' instruction. ** Format and emit an 'iABx' instruction.
*/ */
int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bc) {
lua_assert(getOpMode(o) == iABx); lua_assert(getOpMode(o) == iABx);
lua_assert(a <= MAXARG_A && bc <= MAXARG_Bx); lua_assert(A <= MAXARG_A && Bc <= MAXARG_Bx);
return luaK_code(fs, CREATE_ABx(o, a, bc)); return luaK_code(fs, CREATE_ABx(o, A, Bc));
} }
/* /*
** Format and emit an 'iAsBx' instruction. ** Format and emit an 'iAsBx' instruction.
*/ */
static int codeAsBx (FuncState *fs, OpCode o, int a, int bc) { static int codeAsBx (FuncState *fs, OpCode o, int A, int Bc) {
unsigned int b = bc + OFFSET_sBx; unsigned int b = cast_uint(Bc) + OFFSET_sBx;
lua_assert(getOpMode(o) == iAsBx); lua_assert(getOpMode(o) == iAsBx);
lua_assert(a <= MAXARG_A && b <= MAXARG_Bx); lua_assert(A <= MAXARG_A && b <= MAXARG_Bx);
return luaK_code(fs, CREATE_ABx(o, a, b)); return luaK_code(fs, CREATE_ABx(o, A, b));
} }
@ -423,7 +431,7 @@ static int codeAsBx (FuncState *fs, OpCode o, int a, int bc) {
** Format and emit an 'isJ' instruction. ** Format and emit an 'isJ' instruction.
*/ */
static int codesJ (FuncState *fs, OpCode o, int sj, int k) { static int codesJ (FuncState *fs, OpCode o, int sj, int k) {
unsigned int j = sj + OFFSET_sJ; unsigned int j = cast_uint(sj) + OFFSET_sJ;
lua_assert(getOpMode(o) == isJ); lua_assert(getOpMode(o) == isJ);
lua_assert(j <= MAXARG_sJ && (k & ~1) == 0); lua_assert(j <= MAXARG_sJ && (k & ~1) == 0);
return luaK_code(fs, CREATE_sJ(o, j, k)); return luaK_code(fs, CREATE_sJ(o, j, k));
@ -433,9 +441,9 @@ static int codesJ (FuncState *fs, OpCode o, int sj, int k) {
/* /*
** Emit an "extra argument" instruction (format 'iAx') ** Emit an "extra argument" instruction (format 'iAx')
*/ */
static int codeextraarg (FuncState *fs, int a) { static int codeextraarg (FuncState *fs, int A) {
lua_assert(a <= MAXARG_Ax); lua_assert(A <= MAXARG_Ax);
return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, a)); return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, A));
} }
@ -1032,10 +1040,10 @@ static int exp2RK (FuncState *fs, expdesc *e) {
} }
static void codeABRK (FuncState *fs, OpCode o, int a, int b, static void codeABRK (FuncState *fs, OpCode o, int A, int B,
expdesc *ec) { expdesc *ec) {
int k = exp2RK(fs, ec); int k = exp2RK(fs, ec);
luaK_codeABCk(fs, o, a, b, ec->u.info, k); luaK_codeABCk(fs, o, A, B, ec->u.info, k);
} }
@ -1788,10 +1796,10 @@ void luaK_fixline (FuncState *fs, int line) {
void luaK_settablesize (FuncState *fs, int pc, int ra, int asize, int hsize) { void luaK_settablesize (FuncState *fs, int pc, int ra, int asize, int hsize) {
Instruction *inst = &fs->f->code[pc]; Instruction *inst = &fs->f->code[pc];
int rb = (hsize != 0) ? luaO_ceillog2(hsize) + 1 : 0; /* hash size */ int rb = (hsize != 0) ? luaO_ceillog2(hsize) + 1 : 0; /* hash size */
int extra = asize / (MAXARG_C + 1); /* higher bits of array size */ int extra = asize / (MAXARG_vC + 1); /* higher bits of array size */
int rc = asize % (MAXARG_C + 1); /* lower bits of array size */ int rc = asize % (MAXARG_vC + 1); /* lower bits of array size */
int k = (extra > 0); /* true iff needs extra argument */ int k = (extra > 0); /* true iff needs extra argument */
*inst = CREATE_ABCk(OP_NEWTABLE, ra, rb, rc, k); *inst = CREATE_vABCk(OP_NEWTABLE, ra, rb, rc, k);
*(inst + 1) = CREATE_Ax(OP_EXTRAARG, extra); *(inst + 1) = CREATE_Ax(OP_EXTRAARG, extra);
} }
@ -1807,12 +1815,12 @@ void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) {
lua_assert(tostore != 0); lua_assert(tostore != 0);
if (tostore == LUA_MULTRET) if (tostore == LUA_MULTRET)
tostore = 0; tostore = 0;
if (nelems <= MAXARG_C) if (nelems <= MAXARG_vC)
luaK_codeABC(fs, OP_SETLIST, base, tostore, nelems); luaK_codevABCk(fs, OP_SETLIST, base, tostore, nelems, 0);
else { else {
int extra = nelems / (MAXARG_C + 1); int extra = nelems / (MAXARG_vC + 1);
nelems %= (MAXARG_C + 1); nelems %= (MAXARG_vC + 1);
luaK_codeABCk(fs, OP_SETLIST, base, tostore, nelems, 1); luaK_codevABCk(fs, OP_SETLIST, base, tostore, nelems, 1);
codeextraarg(fs, extra); codeextraarg(fs, extra);
} }
fs->freereg = base + 1; /* free registers with list values */ fs->freereg = base + 1; /* free registers with list values */
@ -1839,6 +1847,7 @@ static int finaltarget (Instruction *code, int i) {
** Do a final pass over the code of a function, doing small peephole ** Do a final pass over the code of a function, doing small peephole
** optimizations and adjustments. ** optimizations and adjustments.
*/ */
#include "lopnames.h"
void luaK_finish (FuncState *fs) { void luaK_finish (FuncState *fs) {
int i; int i;
Proto *p = fs->f; Proto *p = fs->f;

View File

@ -61,8 +61,10 @@ typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;
LUAI_FUNC int luaK_code (FuncState *fs, Instruction i); LUAI_FUNC int luaK_code (FuncState *fs, Instruction i);
LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned Bx); LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned Bx);
LUAI_FUNC int luaK_codeABCk (FuncState *fs, OpCode o, int A, LUAI_FUNC int luaK_codeABCk (FuncState *fs, OpCode o, int A, int B, int C,
int B, int C, int k); int k);
LUAI_FUNC int luaK_codevABCk (FuncState *fs, OpCode o, int A, int B, int C,
int k);
LUAI_FUNC int luaK_exp2const (FuncState *fs, const expdesc *e, TValue *v); LUAI_FUNC int luaK_exp2const (FuncState *fs, const expdesc *e, TValue *v);
LUAI_FUNC void luaK_fixline (FuncState *fs, int line); LUAI_FUNC void luaK_fixline (FuncState *fs, int line);
LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n);

View File

@ -40,7 +40,7 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETTABLE */ ,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETTABLE */
,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETI */ ,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETI */
,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETFIELD */ ,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETFIELD */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_NEWTABLE */ ,opmode(0, 0, 0, 0, 1, ivABC) /* OP_NEWTABLE */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_SELF */ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SELF */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_ADDI */ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_ADDI */
,opmode(0, 0, 0, 0, 1, iABC) /* OP_ADDK */ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_ADDK */
@ -99,7 +99,7 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
,opmode(0, 0, 0, 0, 0, iABx) /* OP_TFORPREP */ ,opmode(0, 0, 0, 0, 0, iABx) /* OP_TFORPREP */
,opmode(0, 0, 0, 0, 0, iABC) /* OP_TFORCALL */ ,opmode(0, 0, 0, 0, 0, iABC) /* OP_TFORCALL */
,opmode(0, 0, 0, 0, 1, iABx) /* OP_TFORLOOP */ ,opmode(0, 0, 0, 0, 1, iABx) /* OP_TFORLOOP */
,opmode(0, 0, 1, 0, 0, iABC) /* OP_SETLIST */ ,opmode(0, 0, 1, 0, 0, ivABC) /* OP_SETLIST */
,opmode(0, 0, 0, 0, 1, iABx) /* OP_CLOSURE */ ,opmode(0, 0, 0, 0, 1, iABx) /* OP_CLOSURE */
,opmode(0, 1, 0, 0, 1, iABC) /* OP_VARARG */ ,opmode(0, 1, 0, 0, 1, iABC) /* OP_VARARG */
,opmode(0, 0, 1, 0, 1, iABC) /* OP_VARARGPREP */ ,opmode(0, 0, 1, 0, 1, iABC) /* OP_VARARGPREP */
@ -127,6 +127,12 @@ int luaP_isOT (Instruction i) {
** it accepts multiple results. ** it accepts multiple results.
*/ */
int luaP_isIT (Instruction i) { int luaP_isIT (Instruction i) {
return testITMode(GET_OPCODE(i)) && GETARG_B(i) == 0; OpCode op = GET_OPCODE(i);
switch (op) {
case OP_SETLIST:
return testITMode(GET_OPCODE(i)) && GETARG_vB(i) == 0;
default:
return testITMode(GET_OPCODE(i)) && GETARG_B(i) == 0;
}
} }

View File

@ -19,25 +19,30 @@
3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
iABC C(8) | B(8) |k| A(8) | Op(7) | iABC C(8) | B(8) |k| A(8) | Op(7) |
ivABC vC(10) | vB(6) |k| A(8) | Op(7) |
iABx Bx(17) | A(8) | Op(7) | iABx Bx(17) | A(8) | Op(7) |
iAsBx sBx (signed)(17) | A(8) | Op(7) | iAsBx sBx (signed)(17) | A(8) | Op(7) |
iAx Ax(25) | Op(7) | iAx Ax(25) | Op(7) |
isJ sJ (signed)(25) | Op(7) | isJ sJ (signed)(25) | Op(7) |
('v' stands for "variant", 's' for "signed", 'x' for "extended".)
A signed argument is represented in excess K: The represented value is A signed argument is represented in excess K: The represented value is
the written unsigned value minus K, where K is half (rounded down) the the written unsigned value minus K, where K is half (rounded down) the
maximum value for the corresponding unsigned argument. maximum value for the corresponding unsigned argument.
===========================================================================*/ ===========================================================================*/
enum OpMode {iABC, iABx, iAsBx, iAx, isJ}; /* basic instruction formats */ /* basic instruction formats */
enum OpMode {iABC, ivABC, iABx, iAsBx, iAx, isJ};
/* /*
** size and position of opcode arguments. ** size and position of opcode arguments.
*/ */
#define SIZE_C 8 #define SIZE_C 8
#define SIZE_vC 10
#define SIZE_B 8 #define SIZE_B 8
#define SIZE_vB 6
#define SIZE_Bx (SIZE_C + SIZE_B + 1) #define SIZE_Bx (SIZE_C + SIZE_B + 1)
#define SIZE_A 8 #define SIZE_A 8
#define SIZE_Ax (SIZE_Bx + SIZE_A) #define SIZE_Ax (SIZE_Bx + SIZE_A)
@ -50,7 +55,9 @@ enum OpMode {iABC, iABx, iAsBx, iAx, isJ}; /* basic instruction formats */
#define POS_A (POS_OP + SIZE_OP) #define POS_A (POS_OP + SIZE_OP)
#define POS_k (POS_A + SIZE_A) #define POS_k (POS_A + SIZE_A)
#define POS_B (POS_k + 1) #define POS_B (POS_k + 1)
#define POS_vB (POS_k + 1)
#define POS_C (POS_B + SIZE_B) #define POS_C (POS_B + SIZE_B)
#define POS_vC (POS_vB + SIZE_vB)
#define POS_Bx POS_k #define POS_Bx POS_k
@ -95,7 +102,9 @@ enum OpMode {iABC, iABx, iAsBx, iAx, isJ}; /* basic instruction formats */
#define MAXARG_A ((1<<SIZE_A)-1) #define MAXARG_A ((1<<SIZE_A)-1)
#define MAXARG_B ((1<<SIZE_B)-1) #define MAXARG_B ((1<<SIZE_B)-1)
#define MAXARG_vB ((1<<SIZE_vB)-1)
#define MAXARG_C ((1<<SIZE_C)-1) #define MAXARG_C ((1<<SIZE_C)-1)
#define MAXARG_vC ((1<<SIZE_vC)-1)
#define OFFSET_sC (MAXARG_C >> 1) #define OFFSET_sC (MAXARG_C >> 1)
#define int2sC(i) ((i) + OFFSET_sC) #define int2sC(i) ((i) + OFFSET_sC)
@ -126,16 +135,24 @@ enum OpMode {iABC, iABx, iAsBx, iAx, isJ}; /* basic instruction formats */
#define GETARG_A(i) getarg(i, POS_A, SIZE_A) #define GETARG_A(i) getarg(i, POS_A, SIZE_A)
#define SETARG_A(i,v) setarg(i, v, POS_A, SIZE_A) #define SETARG_A(i,v) setarg(i, v, POS_A, SIZE_A)
#define GETARG_B(i) check_exp(checkopm(i, iABC), getarg(i, POS_B, SIZE_B)) #define GETARG_B(i) \
check_exp(checkopm(i, iABC), getarg(i, POS_B, SIZE_B))
#define GETARG_vB(i) \
check_exp(checkopm(i, ivABC), getarg(i, POS_vB, SIZE_vB))
#define GETARG_sB(i) sC2int(GETARG_B(i)) #define GETARG_sB(i) sC2int(GETARG_B(i))
#define SETARG_B(i,v) setarg(i, v, POS_B, SIZE_B) #define SETARG_B(i,v) setarg(i, v, POS_B, SIZE_B)
#define SETARG_vB(i,v) setarg(i, v, POS_vB, SIZE_vB)
#define GETARG_C(i) check_exp(checkopm(i, iABC), getarg(i, POS_C, SIZE_C)) #define GETARG_C(i) \
check_exp(checkopm(i, iABC), getarg(i, POS_C, SIZE_C))
#define GETARG_vC(i) \
check_exp(checkopm(i, ivABC), getarg(i, POS_vC, SIZE_vC))
#define GETARG_sC(i) sC2int(GETARG_C(i)) #define GETARG_sC(i) sC2int(GETARG_C(i))
#define SETARG_C(i,v) setarg(i, v, POS_C, SIZE_C) #define SETARG_C(i,v) setarg(i, v, POS_C, SIZE_C)
#define SETARG_vC(i,v) setarg(i, v, POS_vC, SIZE_vC)
#define TESTARG_k(i) check_exp(checkopm(i, iABC), (cast_int(((i) & (1u << POS_k))))) #define TESTARG_k(i) (cast_int(((i) & (1u << POS_k))))
#define GETARG_k(i) check_exp(checkopm(i, iABC), getarg(i, POS_k, 1)) #define GETARG_k(i) getarg(i, POS_k, 1)
#define SETARG_k(i,v) setarg(i, v, POS_k, 1) #define SETARG_k(i,v) setarg(i, v, POS_k, 1)
#define GETARG_Bx(i) check_exp(checkopm(i, iABx), getarg(i, POS_Bx, SIZE_Bx)) #define GETARG_Bx(i) check_exp(checkopm(i, iABx), getarg(i, POS_Bx, SIZE_Bx))
@ -160,6 +177,12 @@ enum OpMode {iABC, iABx, iAsBx, iAx, isJ}; /* basic instruction formats */
| (cast(Instruction, c)<<POS_C) \ | (cast(Instruction, c)<<POS_C) \
| (cast(Instruction, k)<<POS_k)) | (cast(Instruction, k)<<POS_k))
#define CREATE_vABCk(o,a,b,c,k) ((cast(Instruction, o)<<POS_OP) \
| (cast(Instruction, a)<<POS_A) \
| (cast(Instruction, b)<<POS_vB) \
| (cast(Instruction, c)<<POS_vC) \
| (cast(Instruction, k)<<POS_k))
#define CREATE_ABx(o,a,bc) ((cast(Instruction, o)<<POS_OP) \ #define CREATE_ABx(o,a,bc) ((cast(Instruction, o)<<POS_OP) \
| (cast(Instruction, a)<<POS_A) \ | (cast(Instruction, a)<<POS_A) \
| (cast(Instruction, bc)<<POS_Bx)) | (cast(Instruction, bc)<<POS_Bx))
@ -306,7 +329,7 @@ OP_TFORPREP,/* A Bx create upvalue for R[A + 3]; pc+=Bx */
OP_TFORCALL,/* A C R[A+4], ... ,R[A+3+C] := R[A](R[A+1], R[A+2]); */ OP_TFORCALL,/* A C R[A+4], ... ,R[A+3+C] := R[A](R[A+1], R[A+2]); */
OP_TFORLOOP,/* A Bx if R[A+2] ~= nil then { R[A]=R[A+2]; pc -= Bx } */ OP_TFORLOOP,/* A Bx if R[A+2] ~= nil then { R[A]=R[A+2]; pc -= Bx } */
OP_SETLIST,/* A B C k R[A][C+i] := R[A+i], 1 <= i <= B */ OP_SETLIST,/* A vB vC k R[A][vC+i] := R[A+i], 1 <= i <= vB */
OP_CLOSURE,/* A Bx R[A] := closure(KPROTO[Bx]) */ OP_CLOSURE,/* A Bx R[A] := closure(KPROTO[Bx]) */

View File

@ -952,7 +952,7 @@ static void constructor (LexState *ls, expdesc *t) {
sep -> ',' | ';' */ sep -> ',' | ';' */
FuncState *fs = ls->fs; FuncState *fs = ls->fs;
int line = ls->linenumber; int line = ls->linenumber;
int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); int pc = luaK_codevABCk(fs, OP_NEWTABLE, 0, 0, 0, 0);
ConsControl cc; ConsControl cc;
luaK_code(fs, 0); /* space for extra arg. */ luaK_code(fs, 0); /* space for extra arg. */
cc.na = cc.nh = cc.tostore = 0; cc.na = cc.nh = cc.tostore = 0;

View File

@ -697,6 +697,11 @@ static char *buildop (Proto *p, int pc, char *buff) {
GETARG_A(i), GETARG_B(i), GETARG_C(i), GETARG_A(i), GETARG_B(i), GETARG_C(i),
GETARG_k(i) ? " (k)" : ""); GETARG_k(i) ? " (k)" : "");
break; break;
case ivABC:
sprintf(buff, "%-12s%4d %4d %4d%s", name,
GETARG_A(i), GETARG_vB(i), GETARG_vC(i),
GETARG_k(i) ? " (k)" : "");
break;
case iABx: case iABx:
sprintf(buff, "%-12s%4d %4d", name, GETARG_A(i), GETARG_Bx(i)); sprintf(buff, "%-12s%4d %4d", name, GETARG_A(i), GETARG_Bx(i));
break; break;

25
lvm.c
View File

@ -1359,14 +1359,15 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
} }
vmcase(OP_NEWTABLE) { vmcase(OP_NEWTABLE) {
StkId ra = RA(i); StkId ra = RA(i);
int b = GETARG_B(i); /* log2(hash size) + 1 */ int b = GETARG_vB(i); /* log2(hash size) + 1 */
int c = GETARG_C(i); /* array size */ int c = GETARG_vC(i); /* array size */
Table *t; Table *t;
if (b > 0) if (b > 0)
b = 1 << (b - 1); /* size is 2^(b - 1) */ b = 1 << (b - 1); /* hash size is 2^(b - 1) */
lua_assert((!TESTARG_k(i)) == (GETARG_Ax(*pc) == 0)); if (TESTARG_k(i)) { /* non-zero extra argument? */
if (TESTARG_k(i)) /* non-zero extra argument? */ lua_assert(GETARG_Ax(*pc) != 0);
c += GETARG_Ax(*pc) * (MAXARG_C + 1); /* add it to size */ c += GETARG_Ax(*pc) * (MAXARG_vC + 1); /* add it to array size */
}
pc++; /* skip extra argument */ pc++; /* skip extra argument */
L->top.p = ra + 1; /* correct top in case of emergency GC */ L->top.p = ra + 1; /* correct top in case of emergency GC */
t = luaH_new(L); /* memory allocation */ t = luaH_new(L); /* memory allocation */
@ -1850,8 +1851,8 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
}} }}
vmcase(OP_SETLIST) { vmcase(OP_SETLIST) {
StkId ra = RA(i); StkId ra = RA(i);
int n = GETARG_B(i); int n = GETARG_vB(i);
unsigned int last = GETARG_C(i); unsigned int last = GETARG_vC(i);
Table *h = hvalue(s2v(ra)); Table *h = hvalue(s2v(ra));
if (n == 0) if (n == 0)
n = cast_int(L->top.p - ra) - 1; /* get up to the top */ n = cast_int(L->top.p - ra) - 1; /* get up to the top */
@ -1859,11 +1860,15 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
L->top.p = ci->top.p; /* correct top in case of emergency GC */ L->top.p = ci->top.p; /* correct top in case of emergency GC */
last += n; last += n;
if (TESTARG_k(i)) { if (TESTARG_k(i)) {
last += GETARG_Ax(*pc) * (MAXARG_C + 1); last += GETARG_Ax(*pc) * (MAXARG_vC + 1);
pc++; pc++;
} }
if (last > luaH_realasize(h)) /* needs more space? */ /* when 'n' is known, table should have proper size */
if (last > luaH_realasize(h)) { /* needs more space? */
/* fixed-size sets should have space preallocated */
lua_assert(GETARG_vB(i) == 0);
luaH_resizearray(L, h, last); /* preallocate it at once */ luaH_resizearray(L, h, last); /* preallocate it at once */
}
for (; n > 0; n--) { for (; n > 0; n--) {
TValue *val = s2v(ra + n); TValue *val = s2v(ra + n);
obj2arr(h, last - 1, val); obj2arr(h, last - 1, val);