diff --git a/src/lj_record.c b/src/lj_record.c index 48bbbb20..6666b3c6 100644 --- a/src/lj_record.c +++ b/src/lj_record.c @@ -1025,7 +1025,9 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) J->L->base = b + baseadj; copyTV(J->L, b-(2<= 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)); J->base[dst] = tr; if (dst >= J->maxslot) { @@ -2075,12 +2077,27 @@ static TRef rec_tnew(jit_State *J, uint32_t ah) /* -- 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) { TRef *top = &J->base[topslot]; TValue savetv[5+LJ_FR2]; BCReg s; RecordIndex ix; + RecCatDataCP rcd; + int errcode; lj_assertJ(baseslot < topslot, "bad CAT arg"); for (s = baseslot; s <= topslot; s++) (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.key = top[0]; 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. */ + if (errcode) return (TRef)(-errcode); return 0; /* No result yet. */ } @@ -2440,6 +2460,8 @@ void lj_record_ins(jit_State *J) case BC_CAT: rc = rec_cat(J, rb, rc); + if (rc >= 0xffffff00) + lj_err_throw(J->L, -(int32_t)rc); /* Propagate errors. */ break; /* -- Constant and move ops --------------------------------------------- */