summaryrefslogtreecommitdiff
path: root/src/lj_record.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_record.c')
-rw-r--r--src/lj_record.c70
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));
452nocheck: 452nocheck:
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
883LJ_NORET static void recff_err_ffu(jit_State *J, RecordFFData *rd) 885LJ_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
1343static 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
1374static 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. */