diff options
Diffstat (limited to 'src/lj_record.c')
| -rw-r--r-- | src/lj_record.c | 70 |
1 files changed, 62 insertions, 8 deletions
diff --git a/src/lj_record.c b/src/lj_record.c index e101ba23..68a233b9 100644 --- a/src/lj_record.c +++ b/src/lj_record.c | |||
| @@ -168,8 +168,8 @@ static int rec_objcmp(jit_State *J, TRef a, TRef b, cTValue *av, cTValue *bv) | |||
| 168 | { | 168 | { |
| 169 | int diff = !lj_obj_equal(av, bv); | 169 | int diff = !lj_obj_equal(av, bv); |
| 170 | if (!tref_isk2(a, b)) { /* Shortcut, also handles primitives. */ | 170 | if (!tref_isk2(a, b)) { /* Shortcut, also handles primitives. */ |
| 171 | IRType ta = tref_type(a); | 171 | IRType ta = tref_isinteger(a) ? IRT_INT : tref_type(a); |
| 172 | IRType tb = tref_type(b); | 172 | IRType tb = tref_isinteger(b) ? IRT_INT : tref_type(b); |
| 173 | if (ta != tb) { | 173 | if (ta != tb) { |
| 174 | /* Widen mixed number/int comparisons to number/number comparison. */ | 174 | /* Widen mixed number/int comparisons to number/number comparison. */ |
| 175 | if (ta == IRT_INT && tb == IRT_NUM) { | 175 | if (ta == IRT_INT && tb == IRT_NUM) { |
| @@ -447,7 +447,7 @@ static int rec_mm_lookup(jit_State *J, RecordIndex *ix, MMS mm) | |||
| 447 | mix.tab = lj_ir_ktab(J, mt); | 447 | mix.tab = lj_ir_ktab(J, mt); |
| 448 | goto nocheck; | 448 | goto nocheck; |
| 449 | } | 449 | } |
| 450 | ix->mt = mix.tab; | 450 | ix->mt = mt ? mix.tab : TREF_NIL; |
| 451 | emitir(IRTG(mt ? IR_NE : IR_EQ, IRT_TAB), mix.tab, lj_ir_knull(J, IRT_TAB)); | 451 | emitir(IRTG(mt ? IR_NE : IR_EQ, IRT_TAB), mix.tab, lj_ir_knull(J, IRT_TAB)); |
| 452 | nocheck: | 452 | nocheck: |
| 453 | if (mt) { | 453 | if (mt) { |
| @@ -457,6 +457,8 @@ nocheck: | |||
| 457 | copyTV(J->L, &ix->mobjv, mo); | 457 | copyTV(J->L, &ix->mobjv, mo); |
| 458 | ix->mtv = mt; | 458 | ix->mtv = mt; |
| 459 | settabV(J->L, &mix.tabv, mt); | 459 | settabV(J->L, &mix.tabv, mt); |
| 460 | if (isdead(J2G(J), obj2gco(mmstr))) | ||
| 461 | flipwhite(obj2gco(mmstr)); /* Need same logic as lj_str_new(). */ | ||
| 460 | setstrV(J->L, &mix.keyv, mmstr); | 462 | setstrV(J->L, &mix.keyv, mmstr); |
| 461 | mix.key = lj_ir_kstr(J, mmstr); | 463 | mix.key = lj_ir_kstr(J, mmstr); |
| 462 | mix.val = 0; | 464 | mix.val = 0; |
| @@ -880,7 +882,7 @@ static void recff_nyi(jit_State *J, TRef *res, RecordFFData *rd) | |||
| 880 | lj_trace_err_info(J, LJ_TRERR_NYIFF); | 882 | lj_trace_err_info(J, LJ_TRERR_NYIFF); |
| 881 | } | 883 | } |
| 882 | 884 | ||
| 883 | LJ_NORET static void recff_err_ffu(jit_State *J, RecordFFData *rd) | 885 | LJ_NORET static void recff_err_nyi(jit_State *J, RecordFFData *rd) |
| 884 | { | 886 | { |
| 885 | setfuncV(J->L, &J->errinfo, rd->fn); | 887 | setfuncV(J->L, &J->errinfo, rd->fn); |
| 886 | lj_trace_err_info(J, LJ_TRERR_NYIFFU); | 888 | lj_trace_err_info(J, LJ_TRERR_NYIFFU); |
| @@ -986,7 +988,7 @@ static void recff_tonumber(jit_State *J, TRef *res, RecordFFData *rd) | |||
| 986 | if (arg[1]) { | 988 | if (arg[1]) { |
| 987 | TRef base = lj_ir_toint(J, arg[1]); | 989 | TRef base = lj_ir_toint(J, arg[1]); |
| 988 | if (!tref_isk(base) || IR(tref_ref(base))->i != 10) | 990 | if (!tref_isk(base) || IR(tref_ref(base))->i != 10) |
| 989 | recff_err_ffu(J, rd); | 991 | recff_err_nyi(J, rd); |
| 990 | } | 992 | } |
| 991 | if (tref_isstr(tr)) | 993 | if (tref_isstr(tr)) |
| 992 | tr = emitir(IRTG(IR_STRTO, IRT_NUM), tr, 0); | 994 | tr = emitir(IRTG(IR_STRTO, IRT_NUM), tr, 0); |
| @@ -1016,7 +1018,7 @@ static void recff_tostring(jit_State *J, TRef *res, RecordFFData *rd) | |||
| 1016 | } else if (tref_isnumber(tr)) { | 1018 | } else if (tref_isnumber(tr)) { |
| 1017 | res[0] = emitir(IRT(IR_TOSTR, IRT_STR), tr, 0); | 1019 | res[0] = emitir(IRT(IR_TOSTR, IRT_STR), tr, 0); |
| 1018 | } else { | 1020 | } else { |
| 1019 | recff_err_ffu(J, rd); | 1021 | recff_err_nyi(J, rd); |
| 1020 | } | 1022 | } |
| 1021 | } | 1023 | } |
| 1022 | } | 1024 | } |
| @@ -1338,6 +1340,58 @@ static void recff_table_getn(jit_State *J, TRef *res, RecordFFData *rd) | |||
| 1338 | UNUSED(rd); | 1340 | UNUSED(rd); |
| 1339 | } | 1341 | } |
| 1340 | 1342 | ||
| 1343 | static void recff_table_remove(jit_State *J, TRef *res, RecordFFData *rd) | ||
| 1344 | { | ||
| 1345 | if (tref_istab(arg[0])) { | ||
| 1346 | if (!arg[1] || tref_isnil(arg[1])) { /* Simple pop: t[#t] = nil */ | ||
| 1347 | TRef trlen = emitir(IRTI(IR_TLEN), arg[0], 0); | ||
| 1348 | GCtab *t = tabV(&rd->argv[0]); | ||
| 1349 | MSize len = lj_tab_len(t); | ||
| 1350 | emitir(IRTGI(len ? IR_NE : IR_EQ), trlen, lj_ir_kint(J, 0)); | ||
| 1351 | if (len) { | ||
| 1352 | RecordIndex ix; | ||
| 1353 | ix.tab = arg[0]; | ||
| 1354 | ix.key = trlen; | ||
| 1355 | settabV(J->L, &ix.tabv, t); | ||
| 1356 | setintV(&ix.keyv, len); | ||
| 1357 | ix.idxchain = 0; | ||
| 1358 | if (rd->cres != 0) { /* Specialize load only if result needed. */ | ||
| 1359 | ix.val = 0; | ||
| 1360 | res[0] = rec_idx(J, &ix); /* Load previous value. */ | ||
| 1361 | /* Assumes ix.key/ix.tab is not modified for raw rec_idx(). */ | ||
| 1362 | } | ||
| 1363 | ix.val = TREF_NIL; | ||
| 1364 | rec_idx(J, &ix); /* Remove value. */ | ||
| 1365 | } else { | ||
| 1366 | rd->nres = 0; | ||
| 1367 | } | ||
| 1368 | } else { /* Complex case: remove in the middle. */ | ||
| 1369 | recff_err_nyi(J, rd); | ||
| 1370 | } | ||
| 1371 | } /* else: Interpreter will throw. */ | ||
| 1372 | } | ||
| 1373 | |||
| 1374 | static void recff_table_insert(jit_State *J, TRef *res, RecordFFData *rd) | ||
| 1375 | { | ||
| 1376 | rd->nres = 0; | ||
| 1377 | if (tref_istab(arg[0]) && arg[1]) { | ||
| 1378 | if (!arg[2]) { /* Simple push: t[#t+1] = v */ | ||
| 1379 | TRef trlen = emitir(IRTI(IR_TLEN), arg[0], 0); | ||
| 1380 | GCtab *t = tabV(&rd->argv[0]); | ||
| 1381 | RecordIndex ix; | ||
| 1382 | ix.tab = arg[0]; | ||
| 1383 | ix.val = arg[1]; | ||
| 1384 | ix.key = emitir(IRTI(IR_ADD), trlen, lj_ir_kint(J, 1)); | ||
| 1385 | settabV(J->L, &ix.tabv, t); | ||
| 1386 | setintV(&ix.keyv, lj_tab_len(t) + 1); | ||
| 1387 | ix.idxchain = 0; | ||
| 1388 | rec_idx(J, &ix); /* Set new value. */ | ||
| 1389 | } else { /* Complex case: insert in the middle. */ | ||
| 1390 | recff_err_nyi(J, rd); | ||
| 1391 | } | ||
| 1392 | } /* else: Interpreter will throw. */ | ||
| 1393 | } | ||
| 1394 | |||
| 1341 | /* -- Record calls and returns -------------------------------------------- */ | 1395 | /* -- Record calls and returns -------------------------------------------- */ |
| 1342 | 1396 | ||
| 1343 | #undef arg | 1397 | #undef arg |
| @@ -1618,8 +1672,8 @@ void lj_record_ins(jit_State *J) | |||
| 1618 | case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT: | 1672 | case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT: |
| 1619 | /* Emit nothing for two numeric or string consts. */ | 1673 | /* Emit nothing for two numeric or string consts. */ |
| 1620 | if (!(tref_isk2(ra,rc) && tref_isnumber_str(ra) && tref_isnumber_str(rc))) { | 1674 | if (!(tref_isk2(ra,rc) && tref_isnumber_str(ra) && tref_isnumber_str(rc))) { |
| 1621 | IRType ta = tref_type(ra); | 1675 | IRType ta = tref_isinteger(ra) ? IRT_INT : tref_type(ra); |
| 1622 | IRType tc = tref_type(rc); | 1676 | IRType tc = tref_isinteger(rc) ? IRT_INT : tref_type(rc); |
| 1623 | int irop; | 1677 | int irop; |
| 1624 | if (ta != tc) { | 1678 | if (ta != tc) { |
| 1625 | /* Widen mixed number/int comparisons to number/number comparison. */ | 1679 | /* Widen mixed number/int comparisons to number/number comparison. */ |
