mirror of
https://github.com/LuaJIT/LuaJIT.git
synced 2025-02-07 23:24:09 +00:00
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.
This commit is contained in:
parent
48d93d8c84
commit
4424027844
@ -311,6 +311,8 @@ void lj_lex_setup(lua_State *L, LexState *ls)
|
|||||||
ls->vstack = NULL;
|
ls->vstack = NULL;
|
||||||
ls->sizevstack = 0;
|
ls->sizevstack = 0;
|
||||||
ls->vtop = 0;
|
ls->vtop = 0;
|
||||||
|
ls->bcstack = NULL;
|
||||||
|
ls->sizebcstack = 0;
|
||||||
ls->lookahead = TK_eof; /* No look-ahead token. */
|
ls->lookahead = TK_eof; /* No look-ahead token. */
|
||||||
ls->linenumber = 1;
|
ls->linenumber = 1;
|
||||||
ls->lastline = 1;
|
ls->lastline = 1;
|
||||||
@ -339,6 +341,7 @@ void lj_lex_setup(lua_State *L, LexState *ls)
|
|||||||
void lj_lex_cleanup(lua_State *L, LexState *ls)
|
void lj_lex_cleanup(lua_State *L, LexState *ls)
|
||||||
{
|
{
|
||||||
global_State *g = G(L);
|
global_State *g = G(L);
|
||||||
|
lj_mem_freevec(g, ls->bcstack, ls->sizebcstack, BCInsLine);
|
||||||
lj_mem_freevec(g, ls->vstack, ls->sizevstack, VarInfo);
|
lj_mem_freevec(g, ls->vstack, ls->sizevstack, VarInfo);
|
||||||
lj_str_freebuf(g, &ls->sb);
|
lj_str_freebuf(g, &ls->sb);
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,12 @@ TKDEF(TKENUM1, TKENUM2)
|
|||||||
|
|
||||||
typedef int LexToken;
|
typedef int LexToken;
|
||||||
|
|
||||||
|
/* Combined bytecode ins/line. Only used during bytecode generation. */
|
||||||
|
typedef struct BCInsLine {
|
||||||
|
BCIns ins; /* Bytecode instruction. */
|
||||||
|
BCLine line; /* Line number for this bytecode. */
|
||||||
|
} BCInsLine;
|
||||||
|
|
||||||
/* Lua lexer state. */
|
/* Lua lexer state. */
|
||||||
typedef struct LexState {
|
typedef struct LexState {
|
||||||
struct FuncState *fs; /* Current FuncState. Defined in lj_parse.c. */
|
struct FuncState *fs; /* Current FuncState. Defined in lj_parse.c. */
|
||||||
@ -53,6 +59,8 @@ typedef struct LexState {
|
|||||||
VarInfo *vstack; /* Stack for names and extents of local variables. */
|
VarInfo *vstack; /* Stack for names and extents of local variables. */
|
||||||
MSize sizevstack; /* Size of variable stack. */
|
MSize sizevstack; /* Size of variable stack. */
|
||||||
MSize vtop; /* Top of variable stack. */
|
MSize vtop; /* Top of variable stack. */
|
||||||
|
BCInsLine *bcstack; /* Stack for bytecode instructions/line numbers. */
|
||||||
|
MSize sizebcstack; /* Size of bytecode stack. */
|
||||||
uint32_t level; /* Syntactical nesting level. */
|
uint32_t level; /* Syntactical nesting level. */
|
||||||
} LexState;
|
} LexState;
|
||||||
|
|
||||||
|
184
src/lj_parse.c
184
src/lj_parse.c
@ -110,11 +110,14 @@ typedef struct FuncState {
|
|||||||
BCPos lasttarget; /* Bytecode position of last jump target. */
|
BCPos lasttarget; /* Bytecode position of last jump target. */
|
||||||
BCPos jpc; /* Pending jump list to next bytecode. */
|
BCPos jpc; /* Pending jump list to next bytecode. */
|
||||||
BCReg freereg; /* First free register. */
|
BCReg freereg; /* First free register. */
|
||||||
|
BCReg nactvar; /* Number of active local variables. */
|
||||||
BCReg nkn, nkgc; /* Number of lua_Number/GCobj constants */
|
BCReg nkn, nkgc; /* Number of lua_Number/GCobj constants */
|
||||||
BCLine linedefined; /* First line of the function definition. */
|
BCLine linedefined; /* First line of the function definition. */
|
||||||
|
BCInsLine *bcbase; /* Base of bytecode stack. */
|
||||||
|
BCPos bclim; /* Limit of bytecode stack. */
|
||||||
MSize vbase; /* Base of variable stack for this function. */
|
MSize vbase; /* Base of variable stack for this function. */
|
||||||
uint8_t nactvar; /* Number of active local variables. */
|
|
||||||
uint8_t flags; /* Prototype flags. */
|
uint8_t flags; /* Prototype flags. */
|
||||||
|
uint8_t numparams; /* Number of active local variables. */
|
||||||
uint8_t framesize; /* Fixed frame size. */
|
uint8_t framesize; /* Fixed frame size. */
|
||||||
uint8_t nuv; /* Number of upvalues */
|
uint8_t nuv; /* Number of upvalues */
|
||||||
VarIndex varmap[LJ_MAX_LOCVAR]; /* Map from register to variable idx. */
|
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)
|
|||||||
/* Get next element in jump list. */
|
/* Get next element in jump list. */
|
||||||
static BCPos jmp_next(FuncState *fs, BCPos pc)
|
static BCPos jmp_next(FuncState *fs, BCPos pc)
|
||||||
{
|
{
|
||||||
ptrdiff_t delta = bc_j(proto_ins(fs->pt, pc));
|
ptrdiff_t delta = bc_j(fs->bcbase[pc].ins);
|
||||||
if ((BCPos)delta == NO_JMP)
|
if ((BCPos)delta == NO_JMP)
|
||||||
return NO_JMP;
|
return NO_JMP;
|
||||||
else
|
else
|
||||||
@ -228,7 +231,7 @@ static BCPos jmp_next(FuncState *fs, BCPos pc)
|
|||||||
static int jmp_novalue(FuncState *fs, BCPos list)
|
static int jmp_novalue(FuncState *fs, BCPos list)
|
||||||
{
|
{
|
||||||
for (; list != NO_JMP; list = jmp_next(fs, list)) {
|
for (; list != NO_JMP; list = jmp_next(fs, list)) {
|
||||||
BCOp op = bc_op(proto_ins(fs->pt, list >= 1 ? list-1 : list));
|
BCOp op = bc_op(fs->bcbase[list >= 1 ? list-1 : list].ins);
|
||||||
if (!(op == BC_ISTC || op == BC_ISFC)) return 1;
|
if (!(op == BC_ISTC || op == BC_ISFC)) return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -237,15 +240,15 @@ static int jmp_novalue(FuncState *fs, BCPos list)
|
|||||||
/* Patch register of test instructions. */
|
/* Patch register of test instructions. */
|
||||||
static int jmp_patchtestreg(FuncState *fs, BCPos pc, BCReg reg)
|
static int jmp_patchtestreg(FuncState *fs, BCPos pc, BCReg reg)
|
||||||
{
|
{
|
||||||
BCIns *i = proto_insptr(fs->pt, pc >= 1 ? pc-1 : pc);
|
BCIns *ip = &fs->bcbase[pc >= 1 ? pc-1 : pc].ins;
|
||||||
BCOp op = bc_op(*i);
|
BCOp op = bc_op(*ip);
|
||||||
if (!(op == BC_ISTC || op == BC_ISFC))
|
if (!(op == BC_ISTC || op == BC_ISFC))
|
||||||
return 0; /* Cannot patch other instructions. */
|
return 0; /* Cannot patch other instructions. */
|
||||||
if (reg != NO_REG && reg != bc_d(*i)) {
|
if (reg != NO_REG && reg != bc_d(*ip)) {
|
||||||
setbc_a(i, reg);
|
setbc_a(ip, reg);
|
||||||
} else { /* Nothing to store or already in the right register. */
|
} else { /* Nothing to store or already in the right register. */
|
||||||
setbc_op(i, op+(BC_IST-BC_ISTC));
|
setbc_op(ip, op+(BC_IST-BC_ISTC));
|
||||||
setbc_a(i, 0);
|
setbc_a(ip, 0);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -260,7 +263,7 @@ static void jmp_dropval(FuncState *fs, BCPos list)
|
|||||||
/* Patch jump instruction to target. */
|
/* Patch jump instruction to target. */
|
||||||
static void jmp_patchins(FuncState *fs, BCPos pc, BCPos dest)
|
static void jmp_patchins(FuncState *fs, BCPos pc, BCPos dest)
|
||||||
{
|
{
|
||||||
BCIns *jmp = proto_insptr(fs->pt, pc);
|
BCIns *jmp = &fs->bcbase[pc].ins;
|
||||||
BCPos offset = dest-(pc+1)+BCBIAS_J;
|
BCPos offset = dest-(pc+1)+BCBIAS_J;
|
||||||
lua_assert(dest != NO_JMP);
|
lua_assert(dest != NO_JMP);
|
||||||
if (offset > BCMAX_D)
|
if (offset > BCMAX_D)
|
||||||
@ -355,33 +358,30 @@ static void expr_free(FuncState *fs, ExpDesc *e)
|
|||||||
/* -- Bytecode emitter ---------------------------------------------------- */
|
/* -- Bytecode emitter ---------------------------------------------------- */
|
||||||
|
|
||||||
/* Emit bytecode instruction. */
|
/* Emit bytecode instruction. */
|
||||||
static BCPos bcemit_INS(FuncState *fs, BCIns i)
|
static BCPos bcemit_INS(FuncState *fs, BCIns ins)
|
||||||
{
|
{
|
||||||
GCproto *pt;
|
BCPos pc = fs->pc;
|
||||||
BCIns *bc;
|
LexState *ls = fs->ls;
|
||||||
BCLine *lineinfo;
|
jmp_patchval(fs, fs->jpc, pc, NO_REG, pc);
|
||||||
jmp_patchval(fs, fs->jpc, fs->pc, NO_REG, fs->pc);
|
|
||||||
fs->jpc = NO_JMP;
|
fs->jpc = NO_JMP;
|
||||||
pt = fs->pt;
|
if (LJ_UNLIKELY(pc >= fs->bclim)) {
|
||||||
bc = proto_bc(pt);
|
ptrdiff_t base = fs->bcbase - ls->bcstack;
|
||||||
lineinfo = proto_lineinfo(pt);
|
checklimit(fs, ls->sizebcstack, LJ_MAX_BCINS, "bytecode instructions");
|
||||||
if (LJ_UNLIKELY(fs->pc >= pt->sizebc)) {
|
lj_mem_growvec(fs->L, ls->bcstack, ls->sizebcstack, LJ_MAX_BCINS,BCInsLine);
|
||||||
checklimit(fs, fs->pc, LJ_MAX_BCINS, "bytecode instructions");
|
fs->bclim = (BCPos)(ls->sizebcstack - base);
|
||||||
lj_mem_growvec(fs->L, bc, pt->sizebc, LJ_MAX_BCINS, BCIns);
|
fs->bcbase = ls->bcstack + base;
|
||||||
setmref(pt->bc, bc);
|
|
||||||
lj_mem_growvec(fs->L, lineinfo, pt->sizelineinfo, LJ_MAX_BCINS, BCLine);
|
|
||||||
setmref(pt->lineinfo, lineinfo);
|
|
||||||
}
|
}
|
||||||
bc[fs->pc] = i;
|
fs->bcbase[pc].ins = ins;
|
||||||
lineinfo[fs->pc] = fs->ls->lastline;
|
fs->bcbase[pc].line = ls->lastline;
|
||||||
return fs->pc++;
|
fs->pc = pc+1;
|
||||||
|
return pc;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define bcemit_ABC(fs, o, a, b, c) bcemit_INS(fs, BCINS_ABC(o, a, b, c))
|
#define bcemit_ABC(fs, o, a, b, c) bcemit_INS(fs, BCINS_ABC(o, a, b, c))
|
||||||
#define bcemit_AD(fs, o, a, d) bcemit_INS(fs, BCINS_AD(o, a, d))
|
#define bcemit_AD(fs, o, a, d) bcemit_INS(fs, BCINS_AD(o, a, d))
|
||||||
#define bcemit_AJ(fs, o, a, j) bcemit_INS(fs, BCINS_AJ(o, a, j))
|
#define bcemit_AJ(fs, o, a, j) bcemit_INS(fs, BCINS_AJ(o, a, j))
|
||||||
|
|
||||||
#define bcptr(fs, e) (proto_insptr((fs)->pt, (e)->u.s.info))
|
#define bcptr(fs, e) (&(fs)->bcbase[(e)->u.s.info].ins)
|
||||||
|
|
||||||
/* -- Bytecode emitter for expressions ------------------------------------ */
|
/* -- Bytecode emitter for expressions ------------------------------------ */
|
||||||
|
|
||||||
@ -579,14 +579,12 @@ static void bcemit_method(FuncState *fs, ExpDesc *e, ExpDesc *key)
|
|||||||
/* Emit bytecode to set a range of registers to nil. */
|
/* Emit bytecode to set a range of registers to nil. */
|
||||||
static void bcemit_nil(FuncState *fs, BCReg from, BCReg n)
|
static void bcemit_nil(FuncState *fs, BCReg from, BCReg n)
|
||||||
{
|
{
|
||||||
BCIns *pr;
|
|
||||||
if (fs->pc > fs->lasttarget) { /* No jumps to current position? */
|
if (fs->pc > fs->lasttarget) { /* No jumps to current position? */
|
||||||
BCReg pfrom, pto;
|
BCIns *ip = &fs->bcbase[fs->pc-1].ins;
|
||||||
pr = proto_insptr(fs->pt, fs->pc-1);
|
BCReg pto, pfrom = bc_a(*ip);
|
||||||
pfrom = bc_a(*pr);
|
switch (bc_op(*ip)) { /* Try to merge with the previous instruction. */
|
||||||
switch (bc_op(*pr)) { /* Try to merge with the previous instruction. */
|
|
||||||
case BC_KPRI:
|
case BC_KPRI:
|
||||||
if (bc_d(*pr) != ~LJ_TNIL) break;
|
if (bc_d(*ip) != ~LJ_TNIL) break;
|
||||||
if (from == pfrom) {
|
if (from == pfrom) {
|
||||||
if (n == 1) return;
|
if (n == 1) return;
|
||||||
} else if (from == pfrom+1) {
|
} else if (from == pfrom+1) {
|
||||||
@ -598,10 +596,10 @@ static void bcemit_nil(FuncState *fs, BCReg from, BCReg n)
|
|||||||
fs->pc--; /* Drop KPRI. */
|
fs->pc--; /* Drop KPRI. */
|
||||||
break;
|
break;
|
||||||
case BC_KNIL:
|
case BC_KNIL:
|
||||||
pto = bc_d(*pr);
|
pto = bc_d(*ip);
|
||||||
if (pfrom <= from && from <= pto+1) { /* Can we connect both ranges? */
|
if (pfrom <= from && from <= pto+1) { /* Can we connect both ranges? */
|
||||||
if (from+n-1 > pto)
|
if (from+n-1 > pto)
|
||||||
setbc_d(pr, from+n-1); /* Patch previous instruction range. */
|
setbc_d(ip, from+n-1); /* Patch previous instruction range. */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -623,8 +621,8 @@ static BCPos bcemit_jmp(FuncState *fs)
|
|||||||
BCPos j = fs->pc - 1;
|
BCPos j = fs->pc - 1;
|
||||||
fs->jpc = NO_JMP;
|
fs->jpc = NO_JMP;
|
||||||
if ((int32_t)j >= (int32_t)fs->lasttarget &&
|
if ((int32_t)j >= (int32_t)fs->lasttarget &&
|
||||||
bc_op(proto_ins(fs->pt, j)) == BC_UCLO)
|
bc_op(fs->bcbase[j].ins) == BC_UCLO)
|
||||||
setbc_j(proto_insptr(fs->pt, j), NO_JMP);
|
setbc_j(&fs->bcbase[j].ins, NO_JMP);
|
||||||
else
|
else
|
||||||
j = bcemit_AJ(fs, BC_JMP, fs->freereg, NO_JMP);
|
j = bcemit_AJ(fs, BC_JMP, fs->freereg, NO_JMP);
|
||||||
jmp_append(fs, &j, jpc);
|
jmp_append(fs, &j, jpc);
|
||||||
@ -634,8 +632,8 @@ static BCPos bcemit_jmp(FuncState *fs)
|
|||||||
/* Invert branch condition of bytecode instruction. */
|
/* Invert branch condition of bytecode instruction. */
|
||||||
static void invertcond(FuncState *fs, ExpDesc *e)
|
static void invertcond(FuncState *fs, ExpDesc *e)
|
||||||
{
|
{
|
||||||
BCIns *i = bcptr(fs, e) - 1;
|
BCIns *ip = &fs->bcbase[e->u.s.info - 1].ins;
|
||||||
setbc_op(i, bc_op(*i)^1);
|
setbc_op(ip, bc_op(*ip)^1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Emit conditional branch. */
|
/* Emit conditional branch. */
|
||||||
@ -643,9 +641,9 @@ static BCPos bcemit_branch(FuncState *fs, ExpDesc *e, int cond)
|
|||||||
{
|
{
|
||||||
BCPos pc;
|
BCPos pc;
|
||||||
if (e->k == VRELOCABLE) {
|
if (e->k == VRELOCABLE) {
|
||||||
BCIns *i = bcptr(fs, e);
|
BCIns *ip = bcptr(fs, e);
|
||||||
if (bc_op(*i) == BC_NOT) {
|
if (bc_op(*ip) == BC_NOT) {
|
||||||
*i = BCINS_AD(cond ? BC_ISF : BC_IST, 0, bc_d(*i));
|
*ip = BCINS_AD(cond ? BC_ISF : BC_IST, 0, bc_d(*ip));
|
||||||
return bcemit_jmp(fs);
|
return bcemit_jmp(fs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1094,10 +1092,10 @@ static int bcopisret(BCOp op)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Fixup return instruction for prototype. */
|
/* Fixup return instruction for prototype. */
|
||||||
static void fs_fixup_ret(FuncState *fs, GCproto *pt)
|
static void fs_fixup_ret(FuncState *fs)
|
||||||
{
|
{
|
||||||
BCPos lastpc = fs->pc;
|
BCPos lastpc = fs->pc;
|
||||||
if (lastpc <= fs->lasttarget || !bcopisret(bc_op(proto_ins(pt, lastpc-1)))) {
|
if (lastpc <= fs->lasttarget || !bcopisret(bc_op(fs->bcbase[lastpc-1].ins))) {
|
||||||
if (fs->flags & PROTO_HAS_FNEW)
|
if (fs->flags & PROTO_HAS_FNEW)
|
||||||
bcemit_AJ(fs, BC_UCLO, 0, 0);
|
bcemit_AJ(fs, BC_UCLO, 0, 0);
|
||||||
bcemit_AD(fs, BC_RET0, 0, 1); /* Need final return. */
|
bcemit_AD(fs, BC_RET0, 0, 1); /* Need final return. */
|
||||||
@ -1106,16 +1104,16 @@ static void fs_fixup_ret(FuncState *fs, GCproto *pt)
|
|||||||
if (fs->flags & PROTO_FIXUP_RETURN) {
|
if (fs->flags & PROTO_FIXUP_RETURN) {
|
||||||
BCPos pc;
|
BCPos pc;
|
||||||
for (pc = 0; pc < lastpc; pc++) {
|
for (pc = 0; pc < lastpc; pc++) {
|
||||||
BCIns i = proto_ins(pt, pc);
|
BCIns ins = fs->bcbase[pc].ins;
|
||||||
BCPos offset;
|
BCPos offset;
|
||||||
switch (bc_op(i)) {
|
switch (bc_op(ins)) {
|
||||||
case BC_CALLMT: case BC_CALLT:
|
case BC_CALLMT: case BC_CALLT:
|
||||||
case BC_RETM: case BC_RET: case BC_RET0: case BC_RET1:
|
case BC_RETM: case BC_RET: case BC_RET0: case BC_RET1:
|
||||||
offset = bcemit_INS(fs, i)-(pc+1)+BCBIAS_J; /* Copy return ins. */
|
offset = bcemit_INS(fs, ins)-(pc+1)+BCBIAS_J; /* Copy return ins. */
|
||||||
if (offset > BCMAX_D)
|
if (offset > BCMAX_D)
|
||||||
err_syntax(fs->ls, LJ_ERR_XFIXUP);
|
err_syntax(fs->ls, LJ_ERR_XFIXUP);
|
||||||
/* Replace with UCLO plus branch. */
|
/* Replace with UCLO plus branch. */
|
||||||
*proto_insptr(pt, pc) = BCINS_AD(BC_UCLO, 0, offset);
|
fs->bcbase[pc].ins = BCINS_AD(BC_UCLO, 0, offset);
|
||||||
break;
|
break;
|
||||||
case BC_UCLO:
|
case BC_UCLO:
|
||||||
return; /* We're done. */
|
return; /* We're done. */
|
||||||
@ -1132,26 +1130,29 @@ static GCproto *fs_finish(LexState *ls, BCLine line)
|
|||||||
lua_State *L = ls->L;
|
lua_State *L = ls->L;
|
||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
GCproto *pt = fs->pt;
|
GCproto *pt = fs->pt;
|
||||||
BCIns *bc;
|
|
||||||
BCLine *lineinfo;
|
|
||||||
|
|
||||||
/* Apply final fixups. */
|
/* Apply final fixups. */
|
||||||
var_remove(ls, 0);
|
var_remove(ls, 0);
|
||||||
fs_fixup_ret(fs, pt);
|
fs_fixup_ret(fs);
|
||||||
|
|
||||||
/* Reallocate arrays. */
|
|
||||||
bc = proto_bc(pt);
|
|
||||||
lj_mem_reallocvec(L, bc, pt->sizebc, fs->pc, BCIns);
|
|
||||||
setmref(pt->bc, bc);
|
|
||||||
pt->sizebc = fs->pc;
|
|
||||||
|
|
||||||
fs_fixup_k(fs, pt);
|
fs_fixup_k(fs, pt);
|
||||||
fs_fixup_uv(fs, pt);
|
fs_fixup_uv(fs, pt);
|
||||||
|
|
||||||
lineinfo = proto_lineinfo(pt);
|
{
|
||||||
lj_mem_reallocvec(L, lineinfo, pt->sizelineinfo, fs->pc, BCLine);
|
MSize i, n = fs->pc;
|
||||||
setmref(pt->lineinfo, lineinfo);
|
BCInsLine *base = fs->bcbase;
|
||||||
pt->sizelineinfo = fs->pc;
|
BCLine *lineinfo;
|
||||||
|
BCIns *bc = lj_mem_newvec(L, n, BCIns);
|
||||||
|
setmref(pt->bc, bc);
|
||||||
|
pt->sizebc = fs->pc;
|
||||||
|
lineinfo = lj_mem_newvec(L, n, BCLine);
|
||||||
|
setmref(pt->lineinfo, lineinfo);
|
||||||
|
pt->sizelineinfo = n;
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
bc[i] = base[i].ins;
|
||||||
|
lineinfo[i] = base[i].line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
MSize n = ls->vtop - fs->vbase;
|
MSize n = ls->vtop - fs->vbase;
|
||||||
@ -1173,6 +1174,7 @@ static GCproto *fs_finish(LexState *ls, BCLine line)
|
|||||||
/* Initialize prototype fields. */
|
/* Initialize prototype fields. */
|
||||||
setgcref(pt->chunkname, obj2gco(ls->chunkname));
|
setgcref(pt->chunkname, obj2gco(ls->chunkname));
|
||||||
pt->flags = fs->flags;
|
pt->flags = fs->flags;
|
||||||
|
pt->numparams = fs->numparams;
|
||||||
pt->framesize = fs->framesize;
|
pt->framesize = fs->framesize;
|
||||||
pt->linedefined = fs->linedefined;
|
pt->linedefined = fs->linedefined;
|
||||||
pt->lastlinedefined = line;
|
pt->lastlinedefined = line;
|
||||||
@ -1196,7 +1198,7 @@ static GCproto *fs_finish(LexState *ls, BCLine line)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize a new FuncState. */
|
/* Initialize a new FuncState. */
|
||||||
static void fs_init(LexState *ls, FuncState *fs, BCLine line)
|
static void fs_init(LexState *ls, FuncState *fs)
|
||||||
{
|
{
|
||||||
lua_State *L = ls->L;
|
lua_State *L = ls->L;
|
||||||
GCproto *pt = lj_func_newproto(L);
|
GCproto *pt = lj_func_newproto(L);
|
||||||
@ -1216,7 +1218,6 @@ static void fs_init(LexState *ls, FuncState *fs, BCLine line)
|
|||||||
fs->bl = NULL;
|
fs->bl = NULL;
|
||||||
fs->flags = 0;
|
fs->flags = 0;
|
||||||
fs->framesize = 2; /* Minimum frame size. */
|
fs->framesize = 2; /* Minimum frame size. */
|
||||||
fs->linedefined = line;
|
|
||||||
fs->kt = lj_tab_new(L, 0, 0);
|
fs->kt = lj_tab_new(L, 0, 0);
|
||||||
/* Anchor table of constants and prototype (to avoid being collected). */
|
/* Anchor table of constants and prototype (to avoid being collected). */
|
||||||
settabV(L, L->top, fs->kt);
|
settabV(L, L->top, fs->kt);
|
||||||
@ -1333,7 +1334,7 @@ static void expr_table(LexState *ls, ExpDesc *e)
|
|||||||
BCReg kidx;
|
BCReg kidx;
|
||||||
t = lj_tab_new(fs->L, 0, 0);
|
t = lj_tab_new(fs->L, 0, 0);
|
||||||
kidx = const_gc(fs, obj2gco(t), LJ_TTAB);
|
kidx = const_gc(fs, obj2gco(t), LJ_TTAB);
|
||||||
*proto_insptr(fs->pt, pc) = BCINS_AD(BC_TDUP, freg-1, kidx);
|
fs->bcbase[pc].ins = BCINS_AD(BC_TDUP, freg-1, kidx);
|
||||||
}
|
}
|
||||||
vcall = 0;
|
vcall = 0;
|
||||||
expr_kvalue(&k, &key);
|
expr_kvalue(&k, &key);
|
||||||
@ -1350,14 +1351,15 @@ static void expr_table(LexState *ls, ExpDesc *e)
|
|||||||
}
|
}
|
||||||
lex_match(ls, '}', '{', line);
|
lex_match(ls, '}', '{', line);
|
||||||
if (vcall) {
|
if (vcall) {
|
||||||
BCIns *i = proto_insptr(fs->pt, fs->pc-1);
|
BCInsLine *ilp = &fs->bcbase[fs->pc-1];
|
||||||
ExpDesc en;
|
ExpDesc en;
|
||||||
lua_assert(bc_a(*i)==freg && bc_op(*i) == (narr>256?BC_TSETV:BC_TSETB));
|
lua_assert(bc_a(ilp->ins) == freg &&
|
||||||
|
bc_op(ilp->ins) == (narr > 256 ? BC_TSETV : BC_TSETB));
|
||||||
expr_init(&en, VKNUM, 0);
|
expr_init(&en, VKNUM, 0);
|
||||||
setintV(&en.u.nval, narr-1);
|
setintV(&en.u.nval, narr-1);
|
||||||
if (narr > 256) { fs->pc--; i--; }
|
if (narr > 256) { fs->pc--; ilp--; }
|
||||||
*i = BCINS_AD(BC_TSETM, freg, const_num(fs, &en));
|
ilp->ins = BCINS_AD(BC_TSETM, freg, const_num(fs, &en));
|
||||||
setbc_b(i-1, 0);
|
setbc_b(&ilp[-1].ins, 0);
|
||||||
}
|
}
|
||||||
if (pc == fs->pc-1) { /* Make expr relocable if possible. */
|
if (pc == fs->pc-1) { /* Make expr relocable if possible. */
|
||||||
e->u.s.info = pc;
|
e->u.s.info = pc;
|
||||||
@ -1370,15 +1372,14 @@ static void expr_table(LexState *ls, ExpDesc *e)
|
|||||||
if (!needarr) narr = 0;
|
if (!needarr) narr = 0;
|
||||||
else if (narr < 3) narr = 3;
|
else if (narr < 3) narr = 3;
|
||||||
else if (narr > 0x7ff) narr = 0x7ff;
|
else if (narr > 0x7ff) narr = 0x7ff;
|
||||||
setbc_d(proto_insptr(fs->pt, pc), (uint32_t)narr|(hsize2hbits(nhash)<<11));
|
setbc_d(&fs->bcbase[pc].ins, (uint32_t)narr|(hsize2hbits(nhash)<<11));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse function parameters. */
|
/* Parse function parameters. */
|
||||||
static void parse_params(LexState *ls, int needself)
|
static BCReg parse_params(LexState *ls, int needself)
|
||||||
{
|
{
|
||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
GCproto *pt = fs->pt;
|
|
||||||
BCReg nparams = 0;
|
BCReg nparams = 0;
|
||||||
lex_check(ls, '(');
|
lex_check(ls, '(');
|
||||||
if (needself) {
|
if (needself) {
|
||||||
@ -1399,9 +1400,9 @@ static void parse_params(LexState *ls, int needself)
|
|||||||
} while (lex_opt(ls, ','));
|
} while (lex_opt(ls, ','));
|
||||||
}
|
}
|
||||||
var_add(ls, nparams);
|
var_add(ls, nparams);
|
||||||
pt->numparams = cast_byte(fs->nactvar);
|
|
||||||
bcreg_reserve(fs, fs->nactvar);
|
bcreg_reserve(fs, fs->nactvar);
|
||||||
lex_check(ls, ')');
|
lex_check(ls, ')');
|
||||||
|
return fs->nactvar;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Forward declaration. */
|
/* Forward declaration. */
|
||||||
@ -1410,18 +1411,23 @@ static void parse_chunk(LexState *ls);
|
|||||||
/* Parse body of a function. */
|
/* Parse body of a function. */
|
||||||
static void parse_body(LexState *ls, ExpDesc *e, int needself, BCLine line)
|
static void parse_body(LexState *ls, ExpDesc *e, int needself, BCLine line)
|
||||||
{
|
{
|
||||||
FuncState *fs, cfs;
|
FuncState cfs, *fs = ls->fs;
|
||||||
BCReg kidx;
|
BCReg kidx;
|
||||||
BCLine lastline;
|
BCLine lastline;
|
||||||
GCproto *pt;
|
GCproto *pt;
|
||||||
fs_init(ls, &cfs, line);
|
ptrdiff_t oldbase = fs->bcbase - ls->bcstack;
|
||||||
parse_params(ls, needself);
|
fs_init(ls, &cfs);
|
||||||
|
cfs.linedefined = line;
|
||||||
|
cfs.numparams = (uint8_t)parse_params(ls, needself);
|
||||||
|
cfs.bcbase = fs->bcbase + fs->pc;
|
||||||
|
cfs.bclim = fs->bclim - fs->pc;
|
||||||
parse_chunk(ls);
|
parse_chunk(ls);
|
||||||
lastline = ls->linenumber;
|
lastline = ls->linenumber;
|
||||||
lex_match(ls, TK_end, TK_function, line);
|
lex_match(ls, TK_end, TK_function, line);
|
||||||
pt = fs_finish(ls, lastline);
|
pt = fs_finish(ls, lastline);
|
||||||
|
fs->bcbase = ls->bcstack + oldbase; /* May have been reallocated. */
|
||||||
|
fs->bclim = ls->sizebcstack - oldbase;
|
||||||
/* Store new prototype in the constant array of the parent. */
|
/* Store new prototype in the constant array of the parent. */
|
||||||
fs = ls->fs;
|
|
||||||
kidx = const_gc(fs, obj2gco(pt), LJ_TPROTO);
|
kidx = const_gc(fs, obj2gco(pt), LJ_TPROTO);
|
||||||
expr_init(e, VRELOCABLE, bcemit_AD(fs, BC_FNEW, 0, kidx));
|
expr_init(e, VRELOCABLE, bcemit_AD(fs, BC_FNEW, 0, kidx));
|
||||||
if (!(fs->flags & PROTO_HAS_FNEW)) {
|
if (!(fs->flags & PROTO_HAS_FNEW)) {
|
||||||
@ -1485,7 +1491,7 @@ static void parse_args(LexState *ls, ExpDesc *e)
|
|||||||
}
|
}
|
||||||
expr_init(e, VCALL, bcemit_INS(fs, ins));
|
expr_init(e, VCALL, bcemit_INS(fs, ins));
|
||||||
e->u.s.aux = base;
|
e->u.s.aux = base;
|
||||||
proto_lineinfo(fs->pt)[fs->pc - 1] = line;
|
fs->bcbase[fs->pc - 1].line = line;
|
||||||
fs->freereg = base+1; /* Leave one result by default. */
|
fs->freereg = base+1; /* Leave one result by default. */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1693,7 +1699,7 @@ static void scope_begin(FuncState *fs, FuncScope *bl, int isbreakable)
|
|||||||
{
|
{
|
||||||
bl->breaklist = NO_JMP;
|
bl->breaklist = NO_JMP;
|
||||||
bl->isbreakable = (uint8_t)isbreakable;
|
bl->isbreakable = (uint8_t)isbreakable;
|
||||||
bl->nactvar = fs->nactvar;
|
bl->nactvar = (uint8_t)fs->nactvar;
|
||||||
bl->upval = 0;
|
bl->upval = 0;
|
||||||
bl->prev = fs->bl;
|
bl->prev = fs->bl;
|
||||||
fs->bl = bl;
|
fs->bl = bl;
|
||||||
@ -1766,11 +1772,11 @@ static void parse_return(LexState *ls)
|
|||||||
BCReg nret = expr_list(ls, &e);
|
BCReg nret = expr_list(ls, &e);
|
||||||
if (nret == 1) { /* Return one result. */
|
if (nret == 1) { /* Return one result. */
|
||||||
if (e.k == VCALL) { /* Check for tail call. */
|
if (e.k == VCALL) { /* Check for tail call. */
|
||||||
BCIns *i = bcptr(fs, &e);
|
BCIns *ip = bcptr(fs, &e);
|
||||||
/* It doesn't pay off to add BC_VARGT just for 'return ...'. */
|
/* It doesn't pay off to add BC_VARGT just for 'return ...'. */
|
||||||
if (bc_op(*i) == BC_VARG) goto notailcall;
|
if (bc_op(*ip) == BC_VARG) goto notailcall;
|
||||||
fs->pc--;
|
fs->pc--;
|
||||||
ins = BCINS_AD(bc_op(*i)-BC_CALL+BC_CALLT, bc_a(*i), bc_c(*i));
|
ins = BCINS_AD(bc_op(*ip)-BC_CALL+BC_CALLT, bc_a(*ip), bc_c(*ip));
|
||||||
} else { /* Can return the result from any register. */
|
} else { /* Can return the result from any register. */
|
||||||
ins = BCINS_AD(BC_RET1, expr_toanyreg(fs, &e), 2);
|
ins = BCINS_AD(BC_RET1, expr_toanyreg(fs, &e), 2);
|
||||||
}
|
}
|
||||||
@ -1957,7 +1963,7 @@ static void parse_func(LexState *ls, BCLine line)
|
|||||||
parse_body(ls, &b, needself, line);
|
parse_body(ls, &b, needself, line);
|
||||||
fs = ls->fs;
|
fs = ls->fs;
|
||||||
bcemit_store(fs, &v, &b);
|
bcemit_store(fs, &v, &b);
|
||||||
proto_lineinfo(fs->pt)[fs->pc - 1] = line; /* Set line for the store. */
|
fs->bcbase[fs->pc - 1].line = line; /* Set line for the store. */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -- Loop and conditional statements ------------------------------------- */
|
/* -- Loop and conditional statements ------------------------------------- */
|
||||||
@ -2033,9 +2039,9 @@ static void parse_for_body(LexState *ls, BCReg base, BCLine line,
|
|||||||
jmp_patchins(fs, loop, fs->pc);
|
jmp_patchins(fs, loop, fs->pc);
|
||||||
bcemit_ABC(fs, BC_ITERC, base+3, nvars+1, 2+1);
|
bcemit_ABC(fs, BC_ITERC, base+3, nvars+1, 2+1);
|
||||||
loopend = bcemit_AJ(fs, BC_ITERL, base+3, NO_JMP);
|
loopend = bcemit_AJ(fs, BC_ITERL, base+3, NO_JMP);
|
||||||
proto_lineinfo(fs->pt)[loopend-1] = line;
|
fs->bcbase[loopend-1].line = line;
|
||||||
}
|
}
|
||||||
proto_lineinfo(fs->pt)[loopend] = line; /* Fix line for control ins. */
|
fs->bcbase[loopend].line = line; /* Fix line for control ins. */
|
||||||
jmp_patchins(fs, loopend, loop+1);
|
jmp_patchins(fs, loopend, loop+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2210,7 +2216,11 @@ GCproto *lj_parse(LexState *ls)
|
|||||||
setstrV(L, L->top, ls->chunkname); /* Anchor chunkname string. */
|
setstrV(L, L->top, ls->chunkname); /* Anchor chunkname string. */
|
||||||
incr_top(L);
|
incr_top(L);
|
||||||
ls->level = 0;
|
ls->level = 0;
|
||||||
fs_init(ls, &fs, 0);
|
fs_init(ls, &fs);
|
||||||
|
fs.linedefined = 0;
|
||||||
|
fs.numparams = 0;
|
||||||
|
fs.bcbase = NULL;
|
||||||
|
fs.bclim = 0;
|
||||||
fs.flags |= PROTO_IS_VARARG; /* Main chunk is always a vararg func. */
|
fs.flags |= PROTO_IS_VARARG; /* Main chunk is always a vararg func. */
|
||||||
lj_lex_next(ls); /* Read-ahead first token. */
|
lj_lex_next(ls); /* Read-ahead first token. */
|
||||||
parse_chunk(ls);
|
parse_chunk(ls);
|
||||||
|
Loading…
Reference in New Issue
Block a user