mirror of
https://github.com/LuaJIT/LuaJIT.git
synced 2025-02-07 15:14:08 +00:00
Restore state when recording __concat metamethod throws an error.
Thanks to Sergey Kaplun. #1234
This commit is contained in:
parent
510f88d468
commit
7421a1b33c
@ -1025,7 +1025,9 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults)
|
|||||||
J->L->base = b + baseadj;
|
J->L->base = b + baseadj;
|
||||||
copyTV(J->L, b-(2<<LJ_FR2), &save);
|
copyTV(J->L, b-(2<<LJ_FR2), &save);
|
||||||
}
|
}
|
||||||
if (tr) { /* Store final result. */
|
if (tr >= 0xffffff00) {
|
||||||
|
lj_err_throw(J->L, -(int32_t)tr); /* Propagate errors. */
|
||||||
|
} else if (tr) { /* Store final result. */
|
||||||
BCReg dst = bc_a(*(frame_contpc(frame)-1));
|
BCReg dst = bc_a(*(frame_contpc(frame)-1));
|
||||||
J->base[dst] = tr;
|
J->base[dst] = tr;
|
||||||
if (dst >= J->maxslot) {
|
if (dst >= J->maxslot) {
|
||||||
@ -2075,12 +2077,27 @@ static TRef rec_tnew(jit_State *J, uint32_t ah)
|
|||||||
|
|
||||||
/* -- Concatenation ------------------------------------------------------- */
|
/* -- Concatenation ------------------------------------------------------- */
|
||||||
|
|
||||||
|
typedef struct RecCatDataCP {
|
||||||
|
jit_State *J;
|
||||||
|
RecordIndex *ix;
|
||||||
|
} RecCatDataCP;
|
||||||
|
|
||||||
|
static TValue *rec_mm_concat_cp(lua_State *L, lua_CFunction dummy, void *ud)
|
||||||
|
{
|
||||||
|
RecCatDataCP *rcd = (RecCatDataCP *)ud;
|
||||||
|
UNUSED(L); UNUSED(dummy);
|
||||||
|
rec_mm_arith(rcd->J, rcd->ix, MM_concat); /* Call __concat metamethod. */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot)
|
static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot)
|
||||||
{
|
{
|
||||||
TRef *top = &J->base[topslot];
|
TRef *top = &J->base[topslot];
|
||||||
TValue savetv[5+LJ_FR2];
|
TValue savetv[5+LJ_FR2];
|
||||||
BCReg s;
|
BCReg s;
|
||||||
RecordIndex ix;
|
RecordIndex ix;
|
||||||
|
RecCatDataCP rcd;
|
||||||
|
int errcode;
|
||||||
lj_assertJ(baseslot < topslot, "bad CAT arg");
|
lj_assertJ(baseslot < topslot, "bad CAT arg");
|
||||||
for (s = baseslot; s <= topslot; s++)
|
for (s = baseslot; s <= topslot; s++)
|
||||||
(void)getslot(J, s); /* Ensure all arguments have a reference. */
|
(void)getslot(J, s); /* Ensure all arguments have a reference. */
|
||||||
@ -2116,8 +2133,11 @@ static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot)
|
|||||||
ix.tab = top[-1];
|
ix.tab = top[-1];
|
||||||
ix.key = top[0];
|
ix.key = top[0];
|
||||||
memcpy(savetv, &J->L->base[topslot-1], sizeof(savetv)); /* Save slots. */
|
memcpy(savetv, &J->L->base[topslot-1], sizeof(savetv)); /* Save slots. */
|
||||||
rec_mm_arith(J, &ix, MM_concat); /* Call __concat metamethod. */
|
rcd.J = J;
|
||||||
|
rcd.ix = &ix;
|
||||||
|
errcode = lj_vm_cpcall(J->L, NULL, &rcd, rec_mm_concat_cp);
|
||||||
memcpy(&J->L->base[topslot-1], savetv, sizeof(savetv)); /* Restore slots. */
|
memcpy(&J->L->base[topslot-1], savetv, sizeof(savetv)); /* Restore slots. */
|
||||||
|
if (errcode) return (TRef)(-errcode);
|
||||||
return 0; /* No result yet. */
|
return 0; /* No result yet. */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2440,6 +2460,8 @@ void lj_record_ins(jit_State *J)
|
|||||||
|
|
||||||
case BC_CAT:
|
case BC_CAT:
|
||||||
rc = rec_cat(J, rb, rc);
|
rc = rec_cat(J, rb, rc);
|
||||||
|
if (rc >= 0xffffff00)
|
||||||
|
lj_err_throw(J->L, -(int32_t)rc); /* Propagate errors. */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* -- Constant and move ops --------------------------------------------- */
|
/* -- Constant and move ops --------------------------------------------- */
|
||||||
|
Loading…
Reference in New Issue
Block a user