Skip to content

Commit

Permalink
Merge pull request #43 from igormunkin/imun/ffi-sandwich
Browse files Browse the repository at this point in the history
Imun/ffi sandwich
  • Loading branch information
Brugarolas authored Mar 19, 2024
2 parents 03195f7 + d969cb9 commit b935bda
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 21 deletions.
23 changes: 23 additions & 0 deletions src/lj_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,18 @@ static GCtab *getcurrenv(lua_State *L)
return fn->c.gct == ~LJ_TFUNC ? tabref(fn->c.env) : tabref(L->env);
}

static void check_vm_sandwich(lua_State *L)
{
global_State *g = G(L);
/* Forbid Lua world re-entry while running the trace */
if (tvref(g->jit_base)) {
setstrV(L, L->top++, lj_err_str(L, LJ_ERR_JITREVM));
if (g->panic) g->panic(L);
exit(EXIT_FAILURE);
}
lj_trace_abort(g); /* Never record across Lua VM entrance */
}

/* -- Miscellaneous API functions ----------------------------------------- */

LUA_API int lua_status(lua_State *L)
Expand Down Expand Up @@ -318,6 +330,7 @@ LUA_API int lua_equal(lua_State *L, int idx1, int idx2)
return (int)(uintptr_t)base;
} else {
L->top = base+2;
check_vm_sandwich(L);
lj_vm_call(L, base, 1+1);
L->top -= 2+LJ_FR2;
return tvistruecond(L->top+1+LJ_FR2);
Expand All @@ -341,6 +354,7 @@ LUA_API int lua_lessthan(lua_State *L, int idx1, int idx2)
return (int)(uintptr_t)base;
} else {
L->top = base+2;
check_vm_sandwich(L);
lj_vm_call(L, base, 1+1);
L->top -= 2+LJ_FR2;
return tvistruecond(L->top+1+LJ_FR2);
Expand Down Expand Up @@ -795,6 +809,7 @@ LUA_API void lua_concat(lua_State *L, int n)
}
n -= (int)(L->top - (top - 2*LJ_FR2));
L->top = top+2;
check_vm_sandwich(L);
lj_vm_call(L, top, 1+1);
L->top -= 1+LJ_FR2;
copyTV(L, L->top-1, L->top+LJ_FR2);
Expand All @@ -814,6 +829,7 @@ LUA_API void lua_gettable(lua_State *L, int idx)
cTValue *v = lj_meta_tget(L, t, L->top-1);
if (v == NULL) {
L->top += 2;
check_vm_sandwich(L);
lj_vm_call(L, L->top-2, 1+1);
L->top -= 2+LJ_FR2;
v = L->top+1+LJ_FR2;
Expand All @@ -829,6 +845,7 @@ LUA_API void lua_getfield(lua_State *L, int idx, const char *k)
v = lj_meta_tget(L, t, &key);
if (v == NULL) {
L->top += 2;
check_vm_sandwich(L);
lj_vm_call(L, L->top-2, 1+1);
L->top -= 2+LJ_FR2;
v = L->top+1+LJ_FR2;
Expand Down Expand Up @@ -1001,6 +1018,7 @@ LUA_API void lua_settable(lua_State *L, int idx)
TValue *base = L->top;
copyTV(L, base+2, base-3-2*LJ_FR2);
L->top = base+3;
check_vm_sandwich(L);
lj_vm_call(L, base, 0+1);
L->top -= 3+LJ_FR2;
}
Expand All @@ -1021,6 +1039,7 @@ LUA_API void lua_setfield(lua_State *L, int idx, const char *k)
TValue *base = L->top;
copyTV(L, base+2, base-3-2*LJ_FR2);
L->top = base+3;
check_vm_sandwich(L);
lj_vm_call(L, base, 0+1);
L->top -= 2+LJ_FR2;
}
Expand Down Expand Up @@ -1155,6 +1174,7 @@ LUA_API void lua_call(lua_State *L, int nargs, int nresults)
lj_checkapi(L->status == LUA_OK || L->status == LUA_ERRERR,
"thread called in wrong state %d", L->status);
lj_checkapi_slot(nargs+1);
check_vm_sandwich(L);
lj_vm_call(L, api_call_base(L, nargs), nresults+1);
}

Expand All @@ -1173,6 +1193,7 @@ LUA_API int lua_pcall(lua_State *L, int nargs, int nresults, int errfunc)
cTValue *o = index2adr_stack(L, errfunc);
ef = savestack(L, o);
}
check_vm_sandwich(L);
status = lj_vm_pcall(L, api_call_base(L, nargs), nresults+1, ef);
if (status) hook_restore(g, oldh);
return status;
Expand Down Expand Up @@ -1201,6 +1222,7 @@ LUA_API int lua_cpcall(lua_State *L, lua_CFunction func, void *ud)
int status;
lj_checkapi(L->status == LUA_OK || L->status == LUA_ERRERR,
"thread called in wrong state %d", L->status);
check_vm_sandwich(L);
status = lj_vm_cpcall(L, func, ud, cpcall);
if (status) hook_restore(g, oldh);
return status;
Expand All @@ -1213,6 +1235,7 @@ LUALIB_API int luaL_callmeta(lua_State *L, int idx, const char *field)
if (LJ_FR2) setnilV(top++);
copyTV(L, top++, index2adr(L, idx));
L->top = top;
check_vm_sandwich(L);
lj_vm_call(L, top-1, 1+1);
return 1;
}
Expand Down
1 change: 1 addition & 0 deletions src/lj_debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ static BCPos debug_framepc(lua_State *L, GCfunc *fn, cTValue *nextframe)
if (cf == NULL || (char *)cframe_pc(cf) == (char *)cframe_L(cf))
return NO_BCPOS;
ins = cframe_pc(cf); /* Only happens during error/hook handling. */
if (!ins) return NO_BCPOS;
} else {
if (frame_islua(nextframe)) {
ins = frame_pc(nextframe);
Expand Down
23 changes: 20 additions & 3 deletions src/lj_err.c
Original file line number Diff line number Diff line change
Expand Up @@ -818,7 +818,14 @@ LJ_NOINLINE void lj_err_mem(lua_State *L)
TValue *base = tvref(G(L)->jit_base);
if (base) L->base = base;
}
if (curr_funcisL(L)) L->top = curr_topL(L);
if (curr_funcisL(L)) {
L->top = curr_topL(L);
if (LJ_UNLIKELY(L->top > tvref(L->maxstack))) {
/* The current Lua frame violates the stack. Replace it with a dummy. */
L->top = L->base;
setframe_gc(L->base - 1 - LJ_FR2, obj2gco(L), LJ_TTHREAD);
}
}
setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRMEM));
lj_err_throw(L, LUA_ERRMEM);
}
Expand Down Expand Up @@ -879,9 +886,11 @@ LJ_NOINLINE void LJ_FASTCALL lj_err_run(lua_State *L)
{
ptrdiff_t ef = (LJ_HASJIT && tvref(G(L)->jit_base)) ? 0 : finderrfunc(L);
if (ef) {
TValue *errfunc = restorestack(L, ef);
TValue *top = L->top;
TValue *errfunc, *top;
lj_state_checkstack(L, LUA_MINSTACK * 2); /* Might raise new error. */
lj_trace_abort(G(L));
errfunc = restorestack(L, ef);
top = L->top;
if (!tvisfunc(errfunc) || L->status == LUA_ERRERR) {
setstrV(L, top-1, lj_err_str(L, LJ_ERR_ERRERR));
lj_err_throw(L, LUA_ERRERR);
Expand All @@ -896,7 +905,15 @@ LJ_NOINLINE void LJ_FASTCALL lj_err_run(lua_State *L)
lj_err_throw(L, LUA_ERRRUN);
}

/* Stack overflow error. */
void LJ_FASTCALL lj_err_stkov(lua_State *L)
{
lj_debug_addloc(L, err2msg(LJ_ERR_STKOV), L->base-1, NULL);
lj_err_run(L);
}

#if LJ_HASJIT
/* Rethrow error after doing a trace exit. */
LJ_NOINLINE void LJ_FASTCALL lj_err_trace(lua_State *L, int errcode)
{
if (errcode == LUA_ERRRUN)
Expand Down
1 change: 1 addition & 0 deletions src/lj_err.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ LJ_DATA const char *lj_err_allmsg;
LJ_FUNC GCstr *lj_err_str(lua_State *L, ErrMsg em);
LJ_FUNCA_NORET void LJ_FASTCALL lj_err_throw(lua_State *L, int errcode);
LJ_FUNC_NORET void lj_err_mem(lua_State *L);
LJ_FUNC_NORET void LJ_FASTCALL lj_err_stkov(lua_State *L);
LJ_FUNC_NORET void LJ_FASTCALL lj_err_run(lua_State *L);
#if LJ_HASJIT
LJ_FUNCA_NORET void LJ_FASTCALL lj_err_trace(lua_State *L, int errcode);
Expand Down
1 change: 1 addition & 0 deletions src/lj_errmsg.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ ERRDEF(NOJIT, "no JIT compiler for this architecture (yet)")
ERRDEF(NOJIT, "JIT compiler permanently disabled by build option")
#endif
ERRDEF(JITOPT, "unknown or malformed optimization flag " LUA_QS)
ERRDEF(JITREVM, "Lua VM re-entry is detected while executing the trace")

/* Lexer/parser errors. */
ERRDEF(XMODE, "attempt to load chunk with wrong mode")
Expand Down
58 changes: 40 additions & 18 deletions src/lj_state.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,27 +103,49 @@ void lj_state_shrinkstack(lua_State *L, MSize used)
/* Try to grow stack. */
void LJ_FASTCALL lj_state_growstack(lua_State *L, MSize need)
{
MSize n;
if (L->stacksize >= LJ_STACK_MAXEX) {
/* 4. Throw 'error in error handling' when we are _over_ the limit. */
if (L->stacksize > LJ_STACK_MAXEX)
MSize n = L->stacksize + need;
if (LJ_LIKELY(n < LJ_STACK_MAX)) { /* The stack can grow as requested. */
if (n < 2 * L->stacksize) { /* Try to double the size. */
n = 2 * L->stacksize;
if (n > LJ_STACK_MAX)
n = LJ_STACK_MAX;
}
resizestack(L, n);
} else { /* Request would overflow. Raise a stack overflow error. */
if (LJ_HASJIT) {
TValue *base = tvref(G(L)->jit_base);
if (base) L->base = base;
}
if (curr_funcisL(L)) {
L->top = curr_topL(L);
if (L->top > tvref(L->maxstack)) {
/* The current Lua frame violates the stack, so replace it with a
** dummy. This can happen when BC_IFUNCF is trying to grow the stack.
*/
L->top = L->base;
setframe_gc(L->base - 1 - LJ_FR2, obj2gco(L), LJ_TTHREAD);
}
}
if (L->stacksize <= LJ_STACK_MAXEX) {
/* An error handler might want to inspect the stack overflow error, but
** will need some stack space to run in. We give it a stack size beyond
** the normal limit in order to do so, then rely on lj_state_relimitstack
** calls during unwinding to bring us back to a convential stack size.
** The + 1 is space for the error message, and 2 * LUA_MINSTACK is for
** the lj_state_checkstack() call in lj_err_run().
*/
resizestack(L, LJ_STACK_MAX + 1 + 2 * LUA_MINSTACK);
lj_err_stkov(L); /* May invoke an error handler. */
} else {
/* If we're here, then the stack overflow error handler is requesting
** to grow the stack even further. We have no choice but to abort the
** error handler.
*/
GCstr *em = lj_err_str(L, LJ_ERR_STKOV); /* Might OOM. */
setstrV(L, L->top++, em); /* There is always space to push an error. */
lj_err_throw(L, LUA_ERRERR); /* Does not invoke an error handler. */
/* 1. We are _at_ the limit after the last growth. */
if (L->status < LUA_ERRRUN) { /* 2. Throw 'stack overflow'. */
L->status = LUA_ERRRUN; /* Prevent ending here again for pushed msg. */
lj_err_msg(L, LJ_ERR_STKOV); /* May invoke an error handler. */
}
/* 3. Add space (over the limit) for pushed message and error handler. */
}
n = L->stacksize + need;
if (n > LJ_STACK_MAX) {
n += 2*LUA_MINSTACK;
} else if (n < 2*L->stacksize) {
n = 2*L->stacksize;
if (n >= LJ_STACK_MAX)
n = LJ_STACK_MAX;
}
resizestack(L, n);
}

void LJ_FASTCALL lj_state_growstack1(lua_State *L)
Expand Down

0 comments on commit b935bda

Please sign in to comment.