Inline-Lua
view release on metacpan or search on metacpan
ffi/target/release/build/mlua-sys-6a99a2ae50f12319/out/luajit-build/build/src/lj_parse.c view on Meta::CPAN
LJ_STATIC_ASSERT((int)BC_DIVVV-(int)BC_ADDVV == (int)OPR_DIV-(int)OPR_ADD);
LJ_STATIC_ASSERT((int)BC_MODVV-(int)BC_ADDVV == (int)OPR_MOD-(int)OPR_ADD);
#ifdef LUA_USE_ASSERT
#define lj_assertFS(c, ...) (lj_assertG_(G(fs->L), (c), __VA_ARGS__))
#else
#define lj_assertFS(c, ...) ((void)fs)
#endif
/* -- Error handling ------------------------------------------------------ */
LJ_NORET LJ_NOINLINE static void err_syntax(LexState *ls, ErrMsg em)
{
lj_lex_error(ls, ls->tok, em);
}
LJ_NORET LJ_NOINLINE static void err_token(LexState *ls, LexToken tok)
{
lj_lex_error(ls, ls->tok, LJ_ERR_XTOKEN, lj_lex_token2str(ls, tok));
}
LJ_NORET static void err_limit(FuncState *fs, uint32_t limit, const char *what)
{
if (fs->linedefined == 0)
lj_lex_error(fs->ls, 0, LJ_ERR_XLIMM, limit, what);
else
lj_lex_error(fs->ls, 0, LJ_ERR_XLIMF, fs->linedefined, limit, what);
}
#define checklimit(fs, v, l, m) if ((v) >= (l)) err_limit(fs, l, m)
#define checklimitgt(fs, v, l, m) if ((v) > (l)) err_limit(fs, l, m)
#define checkcond(ls, c, em) { if (!(c)) err_syntax(ls, em); }
/* -- Management of constants --------------------------------------------- */
/* Return bytecode encoding for primitive constant. */
#define const_pri(e) check_exp((e)->k <= VKTRUE, (e)->k)
#define tvhaskslot(o) ((o)->u32.hi == 0)
#define tvkslot(o) ((o)->u32.lo)
/* Add a number constant. */
static BCReg const_num(FuncState *fs, ExpDesc *e)
{
lua_State *L = fs->L;
TValue *o;
lj_assertFS(expr_isnumk(e), "bad usage");
o = lj_tab_set(L, fs->kt, &e->u.nval);
if (tvhaskslot(o))
return tvkslot(o);
o->u64 = fs->nkn;
return fs->nkn++;
}
/* Add a GC object constant. */
static BCReg const_gc(FuncState *fs, GCobj *gc, uint32_t itype)
{
lua_State *L = fs->L;
TValue key, *o;
setgcV(L, &key, gc, itype);
/* NOBARRIER: the key is new or kept alive. */
o = lj_tab_set(L, fs->kt, &key);
if (tvhaskslot(o))
return tvkslot(o);
o->u64 = fs->nkgc;
return fs->nkgc++;
}
/* Add a string constant. */
static BCReg const_str(FuncState *fs, ExpDesc *e)
{
lj_assertFS(expr_isstrk(e) || e->k == VGLOBAL, "bad usage");
return const_gc(fs, obj2gco(e->u.sval), LJ_TSTR);
}
/* Anchor string constant to avoid GC. */
GCstr *lj_parse_keepstr(LexState *ls, const char *str, size_t len)
{
/* NOBARRIER: the key is new or kept alive. */
lua_State *L = ls->L;
GCstr *s = lj_str_new(L, str, len);
TValue *tv = lj_tab_setstr(L, ls->fs->kt, s);
if (tvisnil(tv)) setboolV(tv, 1);
lj_gc_check(L);
return s;
}
#if LJ_HASFFI
/* Anchor cdata to avoid GC. */
void lj_parse_keepcdata(LexState *ls, TValue *tv, GCcdata *cd)
{
/* NOBARRIER: the key is new or kept alive. */
lua_State *L = ls->L;
setcdataV(L, tv, cd);
setboolV(lj_tab_set(L, ls->fs->kt, tv), 1);
}
#endif
/* -- Jump list handling -------------------------------------------------- */
/* Get next element in jump list. */
static BCPos jmp_next(FuncState *fs, BCPos pc)
{
ptrdiff_t delta = bc_j(fs->bcbase[pc].ins);
if ((BCPos)delta == NO_JMP)
return NO_JMP;
else
return (BCPos)(((ptrdiff_t)pc+1)+delta);
}
/* Check if any of the instructions on the jump list produce no value. */
static int jmp_novalue(FuncState *fs, BCPos list)
{
for (; list != NO_JMP; list = jmp_next(fs, list)) {
BCIns p = fs->bcbase[list >= 1 ? list-1 : list].ins;
if (!(bc_op(p) == BC_ISTC || bc_op(p) == BC_ISFC || bc_a(p) == NO_REG))
return 1;
}
return 0;
}
/* Patch register of test instructions. */
static int jmp_patchtestreg(FuncState *fs, BCPos pc, BCReg reg)
{
BCInsLine *ilp = &fs->bcbase[pc >= 1 ? pc-1 : pc];
BCOp op = bc_op(ilp->ins);
if (op == BC_ISTC || op == BC_ISFC) {
if (reg != NO_REG && reg != bc_d(ilp->ins)) {
setbc_a(&ilp->ins, reg);
} else { /* Nothing to store or already in the right register. */
setbc_op(&ilp->ins, op+(BC_IST-BC_ISTC));
setbc_a(&ilp->ins, 0);
}
} else if (bc_a(ilp->ins) == NO_REG) {
if (reg == NO_REG) {
ilp->ins = BCINS_AJ(BC_JMP, bc_a(fs->bcbase[pc].ins), 0);
} else {
setbc_a(&ilp->ins, reg);
if (reg >= bc_a(ilp[1].ins))
setbc_a(&ilp[1].ins, reg+1);
}
} else {
return 0; /* Cannot patch other instructions. */
}
return 1;
}
/* Drop values for all instructions on jump list. */
static void jmp_dropval(FuncState *fs, BCPos list)
{
for (; list != NO_JMP; list = jmp_next(fs, list))
jmp_patchtestreg(fs, list, NO_REG);
( run in 1.607 second using v1.01-cache-2.11-cpan-39bf76dae61 )