Check for non-numeric string operands when recording arithmetic operations.

Non-numeric operands cause a fall through into the corresponding metamethod.
This commit is contained in:
Vyacheslav Egorov 2016-04-20 18:29:33 +02:00
parent ac9193cfeb
commit a9d583b937
2 changed files with 24 additions and 4 deletions

View File

@ -31,6 +31,7 @@
#include "lj_record.h"
#include "lj_ffrecord.h"
#include "lj_snap.h"
#include "lj_strscan.h"
#include "lj_dispatch.h"
#include "lj_vm.h"
@ -962,6 +963,23 @@ nocheck:
return 0; /* No metamethod. */
}
/* Check if no metamethod call is required for the given arguments. */
static int rec_isnumericarith(jit_State *J,
TRef rb, TValue *rbv,
TRef rc, TValue *rcv) {
if (tref_isnumber_str(rb) && tref_isnumber_str(rc)) {
TValue tmp;
if ((tref_isstr(rb) && !lj_strscan_num(strV(rbv), &tmp)) ||
(tref_isstr(rb) && !lj_strscan_num(strV(rbv), &tmp))) {
/* Would need an inverted STRTO for this case. */
lj_trace_err_info(J, LJ_TRERR_NYIMM);
}
return 1;
} else {
return 0;
}
}
/* Record call to arithmetic metamethod. */
static TRef rec_mm_arith(jit_State *J, RecordIndex *ix, MMS mm)
{
@ -2127,7 +2145,7 @@ void lj_record_ins(jit_State *J)
/* -- Arithmetic ops ---------------------------------------------------- */
case BC_UNM:
if (tref_isnumber_str(rc)) {
if (rec_isnumericarith(J, rc, rcv, rc, rcv)) {
rc = lj_opt_narrow_unm(J, rc, rcv);
} else {
ix.tab = rc;
@ -2148,9 +2166,10 @@ void lj_record_ins(jit_State *J)
case BC_ADDVN: case BC_SUBVN: case BC_MULVN: case BC_DIVVN:
case BC_ADDVV: case BC_SUBVV: case BC_MULVV: case BC_DIVVV: {
MMS mm = bcmode_mm(op);
if (tref_isnumber_str(rb) && tref_isnumber_str(rc))
if (rec_isnumericarith(J, rb, rbv, rc, rcv)) {
rc = lj_opt_narrow_arith(J, rb, rc, rbv, rcv,
(int)mm - (int)MM_add + (int)IR_ADD);
}
else
rc = rec_mm_arith(J, &ix, mm);
break;
@ -2158,14 +2177,14 @@ void lj_record_ins(jit_State *J)
case BC_MODVN: case BC_MODVV:
recmod:
if (tref_isnumber_str(rb) && tref_isnumber_str(rc))
if (rec_isnumericarith(J, rb, rbv, rc, rcv))
rc = lj_opt_narrow_mod(J, rb, rc, rcv);
else
rc = rec_mm_arith(J, &ix, MM_mod);
break;
case BC_POW:
if (tref_isnumber_str(rb) && tref_isnumber_str(rc))
if (rec_isnumericarith(J, rb, rbv, rc, rcv))
rc = lj_opt_narrow_pow(J, lj_ir_tonum(J, rb), rc, rcv);
else
rc = rec_mm_arith(J, &ix, MM_pow);

View File

@ -14,6 +14,7 @@ TREDEF(SNAPOV, "too many snapshots")
TREDEF(BLACKL, "blacklisted")
TREDEF(RETRY, "retry recording")
TREDEF(NYIBC, "NYI: bytecode %d")
TREDEF(NYIMM, "NYI: arithmetic metamethod on non-numeric strings")
/* Recording loop ops. */
TREDEF(LLEAVE, "leaving loop in root trace")