aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2010-02-08 05:28:57 +0100
committerMike Pall <mike>2010-02-08 05:28:57 +0100
commit4424027844bdcdb76e90e0994efafeee7ea5cc1f (patch)
treec23e3595ae292e669cb39b8d377e790df57c9591 /src
parent48d93d8c84eb72e720d90ed7861f353a2c417470 (diff)
downloadluajit-4424027844bdcdb76e90e0994efafeee7ea5cc1f.tar.gz
luajit-4424027844bdcdb76e90e0994efafeee7ea5cc1f.tar.bz2
luajit-4424027844bdcdb76e90e0994efafeee7ea5cc1f.zip
Redesign of prototype generation, part 3: bc and lineinfo.
Use a growable, per-chunk bytecode instruction/line stack. Collect bc/lineinfo for prototype at the end.
Diffstat (limited to 'src')
-rw-r--r--src/lj_lex.c3
-rw-r--r--src/lj_lex.h8
-rw-r--r--src/lj_parse.c186
3 files changed, 109 insertions, 88 deletions
diff --git a/src/lj_lex.c b/src/lj_lex.c
index 6cb785b5..95adb212 100644
--- a/src/lj_lex.c
+++ b/src/lj_lex.c
@@ -311,6 +311,8 @@ void lj_lex_setup(lua_State *L, LexState *ls)
311 ls->vstack = NULL; 311 ls->vstack = NULL;
312 ls->sizevstack = 0; 312 ls->sizevstack = 0;
313 ls->vtop = 0; 313 ls->vtop = 0;
314 ls->bcstack = NULL;
315 ls->sizebcstack = 0;
314 ls->lookahead = TK_eof; /* No look-ahead token. */ 316 ls->lookahead = TK_eof; /* No look-ahead token. */
315 ls->linenumber = 1; 317 ls->linenumber = 1;
316 ls->lastline = 1; 318 ls->lastline = 1;
@@ -339,6 +341,7 @@ void lj_lex_setup(lua_State *L, LexState *ls)
339void lj_lex_cleanup(lua_State *L, LexState *ls) 341void lj_lex_cleanup(lua_State *L, LexState *ls)
340{ 342{
341 global_State *g = G(L); 343 global_State *g = G(L);
344 lj_mem_freevec(g, ls->bcstack, ls->sizebcstack, BCInsLine);
342 lj_mem_freevec(g, ls->vstack, ls->sizevstack, VarInfo); 345 lj_mem_freevec(g, ls->vstack, ls->sizevstack, VarInfo);
343 lj_str_freebuf(g, &ls->sb); 346 lj_str_freebuf(g, &ls->sb);
344} 347}
diff --git a/src/lj_lex.h b/src/lj_lex.h
index ee183b40..9bcd3cdb 100644
--- a/src/lj_lex.h
+++ b/src/lj_lex.h
@@ -32,6 +32,12 @@ TKDEF(TKENUM1, TKENUM2)
32 32
33typedef int LexToken; 33typedef int LexToken;
34 34
35/* Combined bytecode ins/line. Only used during bytecode generation. */
36typedef struct BCInsLine {
37 BCIns ins; /* Bytecode instruction. */
38 BCLine line; /* Line number for this bytecode. */
39} BCInsLine;
40
35/* Lua lexer state. */ 41/* Lua lexer state. */
36typedef struct LexState { 42typedef struct LexState {
37 struct FuncState *fs; /* Current FuncState. Defined in lj_parse.c. */ 43 struct FuncState *fs; /* Current FuncState. Defined in lj_parse.c. */
@@ -53,6 +59,8 @@ typedef struct LexState {
53 VarInfo *vstack; /* Stack for names and extents of local variables. */ 59 VarInfo *vstack; /* Stack for names and extents of local variables. */
54 MSize sizevstack; /* Size of variable stack. */ 60 MSize sizevstack; /* Size of variable stack. */
55 MSize vtop; /* Top of variable stack. */ 61 MSize vtop; /* Top of variable stack. */
62 BCInsLine *bcstack; /* Stack for bytecode instructions/line numbers. */
63 MSize sizebcstack; /* Size of bytecode stack. */
56 uint32_t level; /* Syntactical nesting level. */ 64 uint32_t level; /* Syntactical nesting level. */
57} LexState; 65} LexState;
58 66
diff --git a/src/lj_parse.c b/src/lj_parse.c
index c1fc5dd6..54ff6974 100644
--- a/src/lj_parse.c
+++ b/src/lj_parse.c
@@ -110,11 +110,14 @@ typedef struct FuncState {
110 BCPos lasttarget; /* Bytecode position of last jump target. */ 110 BCPos lasttarget; /* Bytecode position of last jump target. */
111 BCPos jpc; /* Pending jump list to next bytecode. */ 111 BCPos jpc; /* Pending jump list to next bytecode. */
112 BCReg freereg; /* First free register. */ 112 BCReg freereg; /* First free register. */
113 BCReg nactvar; /* Number of active local variables. */
113 BCReg nkn, nkgc; /* Number of lua_Number/GCobj constants */ 114 BCReg nkn, nkgc; /* Number of lua_Number/GCobj constants */
114 BCLine linedefined; /* First line of the function definition. */ 115 BCLine linedefined; /* First line of the function definition. */
116 BCInsLine *bcbase; /* Base of bytecode stack. */
117 BCPos bclim; /* Limit of bytecode stack. */
115 MSize vbase; /* Base of variable stack for this function. */ 118 MSize vbase; /* Base of variable stack for this function. */
116 uint8_t nactvar; /* Number of active local variables. */
117 uint8_t flags; /* Prototype flags. */ 119 uint8_t flags; /* Prototype flags. */
120 uint8_t numparams; /* Number of active local variables. */
118 uint8_t framesize; /* Fixed frame size. */ 121 uint8_t framesize; /* Fixed frame size. */
119 uint8_t nuv; /* Number of upvalues */ 122 uint8_t nuv; /* Number of upvalues */
120 VarIndex varmap[LJ_MAX_LOCVAR]; /* Map from register to variable idx. */ 123 VarIndex varmap[LJ_MAX_LOCVAR]; /* Map from register to variable idx. */
@@ -217,7 +220,7 @@ GCstr *lj_parse_keepstr(LexState *ls, const char *str, size_t len)
217/* Get next element in jump list. */ 220/* Get next element in jump list. */
218static BCPos jmp_next(FuncState *fs, BCPos pc) 221static BCPos jmp_next(FuncState *fs, BCPos pc)
219{ 222{
220 ptrdiff_t delta = bc_j(proto_ins(fs->pt, pc)); 223 ptrdiff_t delta = bc_j(fs->bcbase[pc].ins);
221 if ((BCPos)delta == NO_JMP) 224 if ((BCPos)delta == NO_JMP)
222 return NO_JMP; 225 return NO_JMP;
223 else 226 else
@@ -228,7 +231,7 @@ static BCPos jmp_next(FuncState *fs, BCPos pc)
228static int jmp_novalue(FuncState *fs, BCPos list) 231static int jmp_novalue(FuncState *fs, BCPos list)
229{ 232{
230 for (; list != NO_JMP; list = jmp_next(fs, list)) { 233 for (; list != NO_JMP; list = jmp_next(fs, list)) {
231 BCOp op = bc_op(proto_ins(fs->pt, list >= 1 ? list-1 : list)); 234 BCOp op = bc_op(fs->bcbase[list >= 1 ? list-1 : list].ins);
232 if (!(op == BC_ISTC || op == BC_ISFC)) return 1; 235 if (!(op == BC_ISTC || op == BC_ISFC)) return 1;
233 } 236 }
234 return 0; 237 return 0;
@@ -237,15 +240,15 @@ static int jmp_novalue(FuncState *fs, BCPos list)
237/* Patch register of test instructions. */ 240/* Patch register of test instructions. */
238static int jmp_patchtestreg(FuncState *fs, BCPos pc, BCReg reg) 241static int jmp_patchtestreg(FuncState *fs, BCPos pc, BCReg reg)
239{ 242{
240 BCIns *i = proto_insptr(fs->pt, pc >= 1 ? pc-1 : pc); 243 BCIns *ip = &fs->bcbase[pc >= 1 ? pc-1 : pc].ins;
241 BCOp op = bc_op(*i); 244 BCOp op = bc_op(*ip);
242 if (!(op == BC_ISTC || op == BC_ISFC)) 245 if (!(op == BC_ISTC || op == BC_ISFC))
243 return 0; /* Cannot patch other instructions. */ 246 return 0; /* Cannot patch other instructions. */
244 if (reg != NO_REG && reg != bc_d(*i)) { 247 if (reg != NO_REG && reg != bc_d(*ip)) {
245 setbc_a(i, reg); 248 setbc_a(ip, reg);
246 } else { /* Nothing to store or already in the right register. */ 249 } else { /* Nothing to store or already in the right register. */
247 setbc_op(i, op+(BC_IST-BC_ISTC)); 250 setbc_op(ip, op+(BC_IST-BC_ISTC));
248 setbc_a(i, 0); 251 setbc_a(ip, 0);
249 } 252 }
250 return 1; 253 return 1;
251} 254}
@@ -260,7 +263,7 @@ static void jmp_dropval(FuncState *fs, BCPos list)
260/* Patch jump instruction to target. */ 263/* Patch jump instruction to target. */
261static void jmp_patchins(FuncState *fs, BCPos pc, BCPos dest) 264static void jmp_patchins(FuncState *fs, BCPos pc, BCPos dest)
262{ 265{
263 BCIns *jmp = proto_insptr(fs->pt, pc); 266 BCIns *jmp = &fs->bcbase[pc].ins;
264 BCPos offset = dest-(pc+1)+BCBIAS_J; 267 BCPos offset = dest-(pc+1)+BCBIAS_J;
265 lua_assert(dest != NO_JMP); 268 lua_assert(dest != NO_JMP);
266 if (offset > BCMAX_D) 269 if (offset > BCMAX_D)
@@ -355,33 +358,30 @@ static void expr_free(FuncState *fs, ExpDesc *e)
355/* -- Bytecode emitter ---------------------------------------------------- */ 358/* -- Bytecode emitter ---------------------------------------------------- */
356 359
357/* Emit bytecode instruction. */ 360/* Emit bytecode instruction. */
358static BCPos bcemit_INS(FuncState *fs, BCIns i) 361static BCPos bcemit_INS(FuncState *fs, BCIns ins)
359{ 362{
360 GCproto *pt; 363 BCPos pc = fs->pc;
361 BCIns *bc; 364 LexState *ls = fs->ls;
362 BCLine *lineinfo; 365 jmp_patchval(fs, fs->jpc, pc, NO_REG, pc);
363 jmp_patchval(fs, fs->jpc, fs->pc, NO_REG, fs->pc);
364 fs->jpc = NO_JMP; 366 fs->jpc = NO_JMP;
365 pt = fs->pt; 367 if (LJ_UNLIKELY(pc >= fs->bclim)) {
366 bc = proto_bc(pt); 368 ptrdiff_t base = fs->bcbase - ls->bcstack;
367 lineinfo = proto_lineinfo(pt); 369 checklimit(fs, ls->sizebcstack, LJ_MAX_BCINS, "bytecode instructions");
368 if (LJ_UNLIKELY(fs->pc >= pt->sizebc)) { 370 lj_mem_growvec(fs->L, ls->bcstack, ls->sizebcstack, LJ_MAX_BCINS,BCInsLine);
369 checklimit(fs, fs->pc, LJ_MAX_BCINS, "bytecode instructions"); 371 fs->bclim = (BCPos)(ls->sizebcstack - base);
370 lj_mem_growvec(fs->L, bc, pt->sizebc, LJ_MAX_BCINS, BCIns); 372 fs->bcbase = ls->bcstack + base;
371 setmref(pt->bc, bc); 373 }
372 lj_mem_growvec(fs->L, lineinfo, pt->sizelineinfo, LJ_MAX_BCINS, BCLine); 374 fs->bcbase[pc].ins = ins;
373 setmref(pt->lineinfo, lineinfo); 375 fs->bcbase[pc].line = ls->lastline;
374 } 376 fs->pc = pc+1;
375 bc[fs->pc] = i; 377 return pc;
376 lineinfo[fs->pc] = fs->ls->lastline;
377 return fs->pc++;
378} 378}
379 379
380#define bcemit_ABC(fs, o, a, b, c) bcemit_INS(fs, BCINS_ABC(o, a, b, c)) 380#define bcemit_ABC(fs, o, a, b, c) bcemit_INS(fs, BCINS_ABC(o, a, b, c))
381#define bcemit_AD(fs, o, a, d) bcemit_INS(fs, BCINS_AD(o, a, d)) 381#define bcemit_AD(fs, o, a, d) bcemit_INS(fs, BCINS_AD(o, a, d))
382#define bcemit_AJ(fs, o, a, j) bcemit_INS(fs, BCINS_AJ(o, a, j)) 382#define bcemit_AJ(fs, o, a, j) bcemit_INS(fs, BCINS_AJ(o, a, j))
383 383
384#define bcptr(fs, e) (proto_insptr((fs)->pt, (e)->u.s.info)) 384#define bcptr(fs, e) (&(fs)->bcbase[(e)->u.s.info].ins)
385 385
386/* -- Bytecode emitter for expressions ------------------------------------ */ 386/* -- Bytecode emitter for expressions ------------------------------------ */
387 387
@@ -579,14 +579,12 @@ static void bcemit_method(FuncState *fs, ExpDesc *e, ExpDesc *key)
579/* Emit bytecode to set a range of registers to nil. */ 579/* Emit bytecode to set a range of registers to nil. */
580static void bcemit_nil(FuncState *fs, BCReg from, BCReg n) 580static void bcemit_nil(FuncState *fs, BCReg from, BCReg n)
581{ 581{
582 BCIns *pr;
583 if (fs->pc > fs->lasttarget) { /* No jumps to current position? */ 582 if (fs->pc > fs->lasttarget) { /* No jumps to current position? */
584 BCReg pfrom, pto; 583 BCIns *ip = &fs->bcbase[fs->pc-1].ins;
585 pr = proto_insptr(fs->pt, fs->pc-1); 584 BCReg pto, pfrom = bc_a(*ip);
586 pfrom = bc_a(*pr); 585 switch (bc_op(*ip)) { /* Try to merge with the previous instruction. */
587 switch (bc_op(*pr)) { /* Try to merge with the previous instruction. */
588 case BC_KPRI: 586 case BC_KPRI:
589 if (bc_d(*pr) != ~LJ_TNIL) break; 587 if (bc_d(*ip) != ~LJ_TNIL) break;
590 if (from == pfrom) { 588 if (from == pfrom) {
591 if (n == 1) return; 589 if (n == 1) return;
592 } else if (from == pfrom+1) { 590 } else if (from == pfrom+1) {
@@ -598,10 +596,10 @@ static void bcemit_nil(FuncState *fs, BCReg from, BCReg n)
598 fs->pc--; /* Drop KPRI. */ 596 fs->pc--; /* Drop KPRI. */
599 break; 597 break;
600 case BC_KNIL: 598 case BC_KNIL:
601 pto = bc_d(*pr); 599 pto = bc_d(*ip);
602 if (pfrom <= from && from <= pto+1) { /* Can we connect both ranges? */ 600 if (pfrom <= from && from <= pto+1) { /* Can we connect both ranges? */
603 if (from+n-1 > pto) 601 if (from+n-1 > pto)
604 setbc_d(pr, from+n-1); /* Patch previous instruction range. */ 602 setbc_d(ip, from+n-1); /* Patch previous instruction range. */
605 return; 603 return;
606 } 604 }
607 break; 605 break;
@@ -623,8 +621,8 @@ static BCPos bcemit_jmp(FuncState *fs)
623 BCPos j = fs->pc - 1; 621 BCPos j = fs->pc - 1;
624 fs->jpc = NO_JMP; 622 fs->jpc = NO_JMP;
625 if ((int32_t)j >= (int32_t)fs->lasttarget && 623 if ((int32_t)j >= (int32_t)fs->lasttarget &&
626 bc_op(proto_ins(fs->pt, j)) == BC_UCLO) 624 bc_op(fs->bcbase[j].ins) == BC_UCLO)
627 setbc_j(proto_insptr(fs->pt, j), NO_JMP); 625 setbc_j(&fs->bcbase[j].ins, NO_JMP);
628 else 626 else
629 j = bcemit_AJ(fs, BC_JMP, fs->freereg, NO_JMP); 627 j = bcemit_AJ(fs, BC_JMP, fs->freereg, NO_JMP);
630 jmp_append(fs, &j, jpc); 628 jmp_append(fs, &j, jpc);
@@ -634,8 +632,8 @@ static BCPos bcemit_jmp(FuncState *fs)
634/* Invert branch condition of bytecode instruction. */ 632/* Invert branch condition of bytecode instruction. */
635static void invertcond(FuncState *fs, ExpDesc *e) 633static void invertcond(FuncState *fs, ExpDesc *e)
636{ 634{
637 BCIns *i = bcptr(fs, e) - 1; 635 BCIns *ip = &fs->bcbase[e->u.s.info - 1].ins;
638 setbc_op(i, bc_op(*i)^1); 636 setbc_op(ip, bc_op(*ip)^1);
639} 637}
640 638
641/* Emit conditional branch. */ 639/* Emit conditional branch. */
@@ -643,9 +641,9 @@ static BCPos bcemit_branch(FuncState *fs, ExpDesc *e, int cond)
643{ 641{
644 BCPos pc; 642 BCPos pc;
645 if (e->k == VRELOCABLE) { 643 if (e->k == VRELOCABLE) {
646 BCIns *i = bcptr(fs, e); 644 BCIns *ip = bcptr(fs, e);
647 if (bc_op(*i) == BC_NOT) { 645 if (bc_op(*ip) == BC_NOT) {
648 *i = BCINS_AD(cond ? BC_ISF : BC_IST, 0, bc_d(*i)); 646 *ip = BCINS_AD(cond ? BC_ISF : BC_IST, 0, bc_d(*ip));
649 return bcemit_jmp(fs); 647 return bcemit_jmp(fs);
650 } 648 }
651 } 649 }
@@ -1094,10 +1092,10 @@ static int bcopisret(BCOp op)
1094} 1092}
1095 1093
1096/* Fixup return instruction for prototype. */ 1094/* Fixup return instruction for prototype. */
1097static void fs_fixup_ret(FuncState *fs, GCproto *pt) 1095static void fs_fixup_ret(FuncState *fs)
1098{ 1096{
1099 BCPos lastpc = fs->pc; 1097 BCPos lastpc = fs->pc;
1100 if (lastpc <= fs->lasttarget || !bcopisret(bc_op(proto_ins(pt, lastpc-1)))) { 1098 if (lastpc <= fs->lasttarget || !bcopisret(bc_op(fs->bcbase[lastpc-1].ins))) {
1101 if (fs->flags & PROTO_HAS_FNEW) 1099 if (fs->flags & PROTO_HAS_FNEW)
1102 bcemit_AJ(fs, BC_UCLO, 0, 0); 1100 bcemit_AJ(fs, BC_UCLO, 0, 0);
1103 bcemit_AD(fs, BC_RET0, 0, 1); /* Need final return. */ 1101 bcemit_AD(fs, BC_RET0, 0, 1); /* Need final return. */
@@ -1106,16 +1104,16 @@ static void fs_fixup_ret(FuncState *fs, GCproto *pt)
1106 if (fs->flags & PROTO_FIXUP_RETURN) { 1104 if (fs->flags & PROTO_FIXUP_RETURN) {
1107 BCPos pc; 1105 BCPos pc;
1108 for (pc = 0; pc < lastpc; pc++) { 1106 for (pc = 0; pc < lastpc; pc++) {
1109 BCIns i = proto_ins(pt, pc); 1107 BCIns ins = fs->bcbase[pc].ins;
1110 BCPos offset; 1108 BCPos offset;
1111 switch (bc_op(i)) { 1109 switch (bc_op(ins)) {
1112 case BC_CALLMT: case BC_CALLT: 1110 case BC_CALLMT: case BC_CALLT:
1113 case BC_RETM: case BC_RET: case BC_RET0: case BC_RET1: 1111 case BC_RETM: case BC_RET: case BC_RET0: case BC_RET1:
1114 offset = bcemit_INS(fs, i)-(pc+1)+BCBIAS_J; /* Copy return ins. */ 1112 offset = bcemit_INS(fs, ins)-(pc+1)+BCBIAS_J; /* Copy return ins. */
1115 if (offset > BCMAX_D) 1113 if (offset > BCMAX_D)
1116 err_syntax(fs->ls, LJ_ERR_XFIXUP); 1114 err_syntax(fs->ls, LJ_ERR_XFIXUP);
1117 /* Replace with UCLO plus branch. */ 1115 /* Replace with UCLO plus branch. */
1118 *proto_insptr(pt, pc) = BCINS_AD(BC_UCLO, 0, offset); 1116 fs->bcbase[pc].ins = BCINS_AD(BC_UCLO, 0, offset);
1119 break; 1117 break;
1120 case BC_UCLO: 1118 case BC_UCLO:
1121 return; /* We're done. */ 1119 return; /* We're done. */
@@ -1132,26 +1130,29 @@ static GCproto *fs_finish(LexState *ls, BCLine line)
1132 lua_State *L = ls->L; 1130 lua_State *L = ls->L;
1133 FuncState *fs = ls->fs; 1131 FuncState *fs = ls->fs;
1134 GCproto *pt = fs->pt; 1132 GCproto *pt = fs->pt;
1135 BCIns *bc;
1136 BCLine *lineinfo;
1137 1133
1138 /* Apply final fixups. */ 1134 /* Apply final fixups. */
1139 var_remove(ls, 0); 1135 var_remove(ls, 0);
1140 fs_fixup_ret(fs, pt); 1136 fs_fixup_ret(fs);
1141
1142 /* Reallocate arrays. */
1143 bc = proto_bc(pt);
1144 lj_mem_reallocvec(L, bc, pt->sizebc, fs->pc, BCIns);
1145 setmref(pt->bc, bc);
1146 pt->sizebc = fs->pc;
1147 1137
1148 fs_fixup_k(fs, pt); 1138 fs_fixup_k(fs, pt);
1149 fs_fixup_uv(fs, pt); 1139 fs_fixup_uv(fs, pt);
1150 1140
1151 lineinfo = proto_lineinfo(pt); 1141 {
1152 lj_mem_reallocvec(L, lineinfo, pt->sizelineinfo, fs->pc, BCLine); 1142 MSize i, n = fs->pc;
1153 setmref(pt->lineinfo, lineinfo); 1143 BCInsLine *base = fs->bcbase;
1154 pt->sizelineinfo = fs->pc; 1144 BCLine *lineinfo;
1145 BCIns *bc = lj_mem_newvec(L, n, BCIns);
1146 setmref(pt->bc, bc);
1147 pt->sizebc = fs->pc;
1148 lineinfo = lj_mem_newvec(L, n, BCLine);
1149 setmref(pt->lineinfo, lineinfo);
1150 pt->sizelineinfo = n;
1151 for (i = 0; i < n; i++) {
1152 bc[i] = base[i].ins;
1153 lineinfo[i] = base[i].line;
1154 }
1155 }
1155 1156
1156 { 1157 {
1157 MSize n = ls->vtop - fs->vbase; 1158 MSize n = ls->vtop - fs->vbase;
@@ -1173,6 +1174,7 @@ static GCproto *fs_finish(LexState *ls, BCLine line)
1173 /* Initialize prototype fields. */ 1174 /* Initialize prototype fields. */
1174 setgcref(pt->chunkname, obj2gco(ls->chunkname)); 1175 setgcref(pt->chunkname, obj2gco(ls->chunkname));
1175 pt->flags = fs->flags; 1176 pt->flags = fs->flags;
1177 pt->numparams = fs->numparams;
1176 pt->framesize = fs->framesize; 1178 pt->framesize = fs->framesize;
1177 pt->linedefined = fs->linedefined; 1179 pt->linedefined = fs->linedefined;
1178 pt->lastlinedefined = line; 1180 pt->lastlinedefined = line;
@@ -1196,7 +1198,7 @@ static GCproto *fs_finish(LexState *ls, BCLine line)
1196} 1198}
1197 1199
1198/* Initialize a new FuncState. */ 1200/* Initialize a new FuncState. */
1199static void fs_init(LexState *ls, FuncState *fs, BCLine line) 1201static void fs_init(LexState *ls, FuncState *fs)
1200{ 1202{
1201 lua_State *L = ls->L; 1203 lua_State *L = ls->L;
1202 GCproto *pt = lj_func_newproto(L); 1204 GCproto *pt = lj_func_newproto(L);
@@ -1216,7 +1218,6 @@ static void fs_init(LexState *ls, FuncState *fs, BCLine line)
1216 fs->bl = NULL; 1218 fs->bl = NULL;
1217 fs->flags = 0; 1219 fs->flags = 0;
1218 fs->framesize = 2; /* Minimum frame size. */ 1220 fs->framesize = 2; /* Minimum frame size. */
1219 fs->linedefined = line;
1220 fs->kt = lj_tab_new(L, 0, 0); 1221 fs->kt = lj_tab_new(L, 0, 0);
1221 /* Anchor table of constants and prototype (to avoid being collected). */ 1222 /* Anchor table of constants and prototype (to avoid being collected). */
1222 settabV(L, L->top, fs->kt); 1223 settabV(L, L->top, fs->kt);
@@ -1333,7 +1334,7 @@ static void expr_table(LexState *ls, ExpDesc *e)
1333 BCReg kidx; 1334 BCReg kidx;
1334 t = lj_tab_new(fs->L, 0, 0); 1335 t = lj_tab_new(fs->L, 0, 0);
1335 kidx = const_gc(fs, obj2gco(t), LJ_TTAB); 1336 kidx = const_gc(fs, obj2gco(t), LJ_TTAB);
1336 *proto_insptr(fs->pt, pc) = BCINS_AD(BC_TDUP, freg-1, kidx); 1337 fs->bcbase[pc].ins = BCINS_AD(BC_TDUP, freg-1, kidx);
1337 } 1338 }
1338 vcall = 0; 1339 vcall = 0;
1339 expr_kvalue(&k, &key); 1340 expr_kvalue(&k, &key);
@@ -1350,14 +1351,15 @@ static void expr_table(LexState *ls, ExpDesc *e)
1350 } 1351 }
1351 lex_match(ls, '}', '{', line); 1352 lex_match(ls, '}', '{', line);
1352 if (vcall) { 1353 if (vcall) {
1353 BCIns *i = proto_insptr(fs->pt, fs->pc-1); 1354 BCInsLine *ilp = &fs->bcbase[fs->pc-1];
1354 ExpDesc en; 1355 ExpDesc en;
1355 lua_assert(bc_a(*i)==freg && bc_op(*i) == (narr>256?BC_TSETV:BC_TSETB)); 1356 lua_assert(bc_a(ilp->ins) == freg &&
1357 bc_op(ilp->ins) == (narr > 256 ? BC_TSETV : BC_TSETB));
1356 expr_init(&en, VKNUM, 0); 1358 expr_init(&en, VKNUM, 0);
1357 setintV(&en.u.nval, narr-1); 1359 setintV(&en.u.nval, narr-1);
1358 if (narr > 256) { fs->pc--; i--; } 1360 if (narr > 256) { fs->pc--; ilp--; }
1359 *i = BCINS_AD(BC_TSETM, freg, const_num(fs, &en)); 1361 ilp->ins = BCINS_AD(BC_TSETM, freg, const_num(fs, &en));
1360 setbc_b(i-1, 0); 1362 setbc_b(&ilp[-1].ins, 0);
1361 } 1363 }
1362 if (pc == fs->pc-1) { /* Make expr relocable if possible. */ 1364 if (pc == fs->pc-1) { /* Make expr relocable if possible. */
1363 e->u.s.info = pc; 1365 e->u.s.info = pc;
@@ -1370,15 +1372,14 @@ static void expr_table(LexState *ls, ExpDesc *e)
1370 if (!needarr) narr = 0; 1372 if (!needarr) narr = 0;
1371 else if (narr < 3) narr = 3; 1373 else if (narr < 3) narr = 3;
1372 else if (narr > 0x7ff) narr = 0x7ff; 1374 else if (narr > 0x7ff) narr = 0x7ff;
1373 setbc_d(proto_insptr(fs->pt, pc), (uint32_t)narr|(hsize2hbits(nhash)<<11)); 1375 setbc_d(&fs->bcbase[pc].ins, (uint32_t)narr|(hsize2hbits(nhash)<<11));
1374 } 1376 }
1375} 1377}
1376 1378
1377/* Parse function parameters. */ 1379/* Parse function parameters. */
1378static void parse_params(LexState *ls, int needself) 1380static BCReg parse_params(LexState *ls, int needself)
1379{ 1381{
1380 FuncState *fs = ls->fs; 1382 FuncState *fs = ls->fs;
1381 GCproto *pt = fs->pt;
1382 BCReg nparams = 0; 1383 BCReg nparams = 0;
1383 lex_check(ls, '('); 1384 lex_check(ls, '(');
1384 if (needself) { 1385 if (needself) {
@@ -1399,9 +1400,9 @@ static void parse_params(LexState *ls, int needself)
1399 } while (lex_opt(ls, ',')); 1400 } while (lex_opt(ls, ','));
1400 } 1401 }
1401 var_add(ls, nparams); 1402 var_add(ls, nparams);
1402 pt->numparams = cast_byte(fs->nactvar);
1403 bcreg_reserve(fs, fs->nactvar); 1403 bcreg_reserve(fs, fs->nactvar);
1404 lex_check(ls, ')'); 1404 lex_check(ls, ')');
1405 return fs->nactvar;
1405} 1406}
1406 1407
1407/* Forward declaration. */ 1408/* Forward declaration. */
@@ -1410,18 +1411,23 @@ static void parse_chunk(LexState *ls);
1410/* Parse body of a function. */ 1411/* Parse body of a function. */
1411static void parse_body(LexState *ls, ExpDesc *e, int needself, BCLine line) 1412static void parse_body(LexState *ls, ExpDesc *e, int needself, BCLine line)
1412{ 1413{
1413 FuncState *fs, cfs; 1414 FuncState cfs, *fs = ls->fs;
1414 BCReg kidx; 1415 BCReg kidx;
1415 BCLine lastline; 1416 BCLine lastline;
1416 GCproto *pt; 1417 GCproto *pt;
1417 fs_init(ls, &cfs, line); 1418 ptrdiff_t oldbase = fs->bcbase - ls->bcstack;
1418 parse_params(ls, needself); 1419 fs_init(ls, &cfs);
1420 cfs.linedefined = line;
1421 cfs.numparams = (uint8_t)parse_params(ls, needself);
1422 cfs.bcbase = fs->bcbase + fs->pc;
1423 cfs.bclim = fs->bclim - fs->pc;
1419 parse_chunk(ls); 1424 parse_chunk(ls);
1420 lastline = ls->linenumber; 1425 lastline = ls->linenumber;
1421 lex_match(ls, TK_end, TK_function, line); 1426 lex_match(ls, TK_end, TK_function, line);
1422 pt = fs_finish(ls, lastline); 1427 pt = fs_finish(ls, lastline);
1428 fs->bcbase = ls->bcstack + oldbase; /* May have been reallocated. */
1429 fs->bclim = ls->sizebcstack - oldbase;
1423 /* Store new prototype in the constant array of the parent. */ 1430 /* Store new prototype in the constant array of the parent. */
1424 fs = ls->fs;
1425 kidx = const_gc(fs, obj2gco(pt), LJ_TPROTO); 1431 kidx = const_gc(fs, obj2gco(pt), LJ_TPROTO);
1426 expr_init(e, VRELOCABLE, bcemit_AD(fs, BC_FNEW, 0, kidx)); 1432 expr_init(e, VRELOCABLE, bcemit_AD(fs, BC_FNEW, 0, kidx));
1427 if (!(fs->flags & PROTO_HAS_FNEW)) { 1433 if (!(fs->flags & PROTO_HAS_FNEW)) {
@@ -1485,7 +1491,7 @@ static void parse_args(LexState *ls, ExpDesc *e)
1485 } 1491 }
1486 expr_init(e, VCALL, bcemit_INS(fs, ins)); 1492 expr_init(e, VCALL, bcemit_INS(fs, ins));
1487 e->u.s.aux = base; 1493 e->u.s.aux = base;
1488 proto_lineinfo(fs->pt)[fs->pc - 1] = line; 1494 fs->bcbase[fs->pc - 1].line = line;
1489 fs->freereg = base+1; /* Leave one result by default. */ 1495 fs->freereg = base+1; /* Leave one result by default. */
1490} 1496}
1491 1497
@@ -1693,7 +1699,7 @@ static void scope_begin(FuncState *fs, FuncScope *bl, int isbreakable)
1693{ 1699{
1694 bl->breaklist = NO_JMP; 1700 bl->breaklist = NO_JMP;
1695 bl->isbreakable = (uint8_t)isbreakable; 1701 bl->isbreakable = (uint8_t)isbreakable;
1696 bl->nactvar = fs->nactvar; 1702 bl->nactvar = (uint8_t)fs->nactvar;
1697 bl->upval = 0; 1703 bl->upval = 0;
1698 bl->prev = fs->bl; 1704 bl->prev = fs->bl;
1699 fs->bl = bl; 1705 fs->bl = bl;
@@ -1766,11 +1772,11 @@ static void parse_return(LexState *ls)
1766 BCReg nret = expr_list(ls, &e); 1772 BCReg nret = expr_list(ls, &e);
1767 if (nret == 1) { /* Return one result. */ 1773 if (nret == 1) { /* Return one result. */
1768 if (e.k == VCALL) { /* Check for tail call. */ 1774 if (e.k == VCALL) { /* Check for tail call. */
1769 BCIns *i = bcptr(fs, &e); 1775 BCIns *ip = bcptr(fs, &e);
1770 /* It doesn't pay off to add BC_VARGT just for 'return ...'. */ 1776 /* It doesn't pay off to add BC_VARGT just for 'return ...'. */
1771 if (bc_op(*i) == BC_VARG) goto notailcall; 1777 if (bc_op(*ip) == BC_VARG) goto notailcall;
1772 fs->pc--; 1778 fs->pc--;
1773 ins = BCINS_AD(bc_op(*i)-BC_CALL+BC_CALLT, bc_a(*i), bc_c(*i)); 1779 ins = BCINS_AD(bc_op(*ip)-BC_CALL+BC_CALLT, bc_a(*ip), bc_c(*ip));
1774 } else { /* Can return the result from any register. */ 1780 } else { /* Can return the result from any register. */
1775 ins = BCINS_AD(BC_RET1, expr_toanyreg(fs, &e), 2); 1781 ins = BCINS_AD(BC_RET1, expr_toanyreg(fs, &e), 2);
1776 } 1782 }
@@ -1957,7 +1963,7 @@ static void parse_func(LexState *ls, BCLine line)
1957 parse_body(ls, &b, needself, line); 1963 parse_body(ls, &b, needself, line);
1958 fs = ls->fs; 1964 fs = ls->fs;
1959 bcemit_store(fs, &v, &b); 1965 bcemit_store(fs, &v, &b);
1960 proto_lineinfo(fs->pt)[fs->pc - 1] = line; /* Set line for the store. */ 1966 fs->bcbase[fs->pc - 1].line = line; /* Set line for the store. */
1961} 1967}
1962 1968
1963/* -- Loop and conditional statements ------------------------------------- */ 1969/* -- Loop and conditional statements ------------------------------------- */
@@ -2033,9 +2039,9 @@ static void parse_for_body(LexState *ls, BCReg base, BCLine line,
2033 jmp_patchins(fs, loop, fs->pc); 2039 jmp_patchins(fs, loop, fs->pc);
2034 bcemit_ABC(fs, BC_ITERC, base+3, nvars+1, 2+1); 2040 bcemit_ABC(fs, BC_ITERC, base+3, nvars+1, 2+1);
2035 loopend = bcemit_AJ(fs, BC_ITERL, base+3, NO_JMP); 2041 loopend = bcemit_AJ(fs, BC_ITERL, base+3, NO_JMP);
2036 proto_lineinfo(fs->pt)[loopend-1] = line; 2042 fs->bcbase[loopend-1].line = line;
2037 } 2043 }
2038 proto_lineinfo(fs->pt)[loopend] = line; /* Fix line for control ins. */ 2044 fs->bcbase[loopend].line = line; /* Fix line for control ins. */
2039 jmp_patchins(fs, loopend, loop+1); 2045 jmp_patchins(fs, loopend, loop+1);
2040} 2046}
2041 2047
@@ -2210,7 +2216,11 @@ GCproto *lj_parse(LexState *ls)
2210 setstrV(L, L->top, ls->chunkname); /* Anchor chunkname string. */ 2216 setstrV(L, L->top, ls->chunkname); /* Anchor chunkname string. */
2211 incr_top(L); 2217 incr_top(L);
2212 ls->level = 0; 2218 ls->level = 0;
2213 fs_init(ls, &fs, 0); 2219 fs_init(ls, &fs);
2220 fs.linedefined = 0;
2221 fs.numparams = 0;
2222 fs.bcbase = NULL;
2223 fs.bclim = 0;
2214 fs.flags |= PROTO_IS_VARARG; /* Main chunk is always a vararg func. */ 2224 fs.flags |= PROTO_IS_VARARG; /* Main chunk is always a vararg func. */
2215 lj_lex_next(ls); /* Read-ahead first token. */ 2225 lj_lex_next(ls); /* Read-ahead first token. */
2216 parse_chunk(ls); 2226 parse_chunk(ls);