aboutsummaryrefslogtreecommitdiff
path: root/src/lj_record.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lj_record.c125
1 files changed, 111 insertions, 14 deletions
diff --git a/src/lj_record.c b/src/lj_record.c
index 68a233b9..9b223ff6 100644
--- a/src/lj_record.c
+++ b/src/lj_record.c
@@ -441,7 +441,7 @@ static int rec_mm_lookup(jit_State *J, RecordIndex *ix, MMS mm)
441 mix.tab = emitir(IRT(IR_FLOAD, IRT_TAB), ix->tab, IRFL_UDATA_META); 441 mix.tab = emitir(IRT(IR_FLOAD, IRT_TAB), ix->tab, IRFL_UDATA_META);
442 } else { 442 } else {
443 /* Specialize to base metatable. Must flush mcode in lua_setmetatable(). */ 443 /* Specialize to base metatable. Must flush mcode in lua_setmetatable(). */
444 mt = tabref(J2G(J)->basemt[itypemap(&ix->tabv)]); 444 mt = tabref(basemt_obj(J2G(J), &ix->tabv));
445 if (mt == NULL) 445 if (mt == NULL)
446 return 0; /* No metamethod. */ 446 return 0; /* No metamethod. */
447 mix.tab = lj_ir_ktab(J, mt); 447 mix.tab = lj_ir_ktab(J, mt);
@@ -855,7 +855,7 @@ typedef void (*RecordFunc)(jit_State *J, TRef *res, RecordFFData *rd);
855/* Get runtime value of int argument. */ 855/* Get runtime value of int argument. */
856static int32_t argv2int(jit_State *J, TValue *o) 856static int32_t argv2int(jit_State *J, TValue *o)
857{ 857{
858 if (tvisstr(o) && !lj_str_numconv(strVdata(o), o)) 858 if (tvisstr(o) && !lj_str_tonum(strV(o), o))
859 lj_trace_err(J, LJ_TRERR_BADTYPE); 859 lj_trace_err(J, LJ_TRERR_BADTYPE);
860 return lj_num2bit(numV(o)); 860 return lj_num2bit(numV(o));
861} 861}
@@ -1017,6 +1017,8 @@ static void recff_tostring(jit_State *J, TRef *res, RecordFFData *rd)
1017 /* Otherwise res[0] already contains the result. */ 1017 /* Otherwise res[0] already contains the result. */
1018 } else if (tref_isnumber(tr)) { 1018 } else if (tref_isnumber(tr)) {
1019 res[0] = emitir(IRT(IR_TOSTR, IRT_STR), tr, 0); 1019 res[0] = emitir(IRT(IR_TOSTR, IRT_STR), tr, 0);
1020 } else if (tref_ispri(tr)) {
1021 res[0] = lj_ir_kstr(J, strV(&rd->fn->c.upvalue[tref_type(tr)]));
1020 } else { 1022 } else {
1021 recff_err_nyi(J, rd); 1023 recff_err_nyi(J, rd);
1022 } 1024 }
@@ -1165,10 +1167,16 @@ static void recff_math_atrig(jit_State *J, TRef *res, RecordFFData *rd)
1165 res[0] = emitir(IRTN(IR_ATAN2), y, x); 1167 res[0] = emitir(IRTN(IR_ATAN2), y, x);
1166} 1168}
1167 1169
1170static void recff_math_htrig(jit_State *J, TRef *res, RecordFFData *rd)
1171{
1172 TRef tr = lj_ir_tonum(J, arg[0]);
1173 res[0] = lj_ir_call(J, rd->data, tr);
1174}
1175
1168static void recff_math_modf(jit_State *J, TRef *res, RecordFFData *rd) 1176static void recff_math_modf(jit_State *J, TRef *res, RecordFFData *rd)
1169{ 1177{
1170 TRef tr = arg[0]; 1178 TRef tr = arg[0];
1171 if (tref_isinteger(arg[0])) { 1179 if (tref_isinteger(tr)) {
1172 res[0] = tr; 1180 res[0] = tr;
1173 res[1] = lj_ir_kint(J, 0); 1181 res[1] = lj_ir_kint(J, 0);
1174 } else { 1182 } else {
@@ -1187,9 +1195,10 @@ static void recff_math_degrad(jit_State *J, TRef *res, RecordFFData *rd)
1187 1195
1188static void recff_math_pow(jit_State *J, TRef *res, RecordFFData *rd) 1196static void recff_math_pow(jit_State *J, TRef *res, RecordFFData *rd)
1189{ 1197{
1198 TRef tr = lj_ir_tonum(J, arg[0]);
1190 if (!tref_isnumber_str(arg[1])) 1199 if (!tref_isnumber_str(arg[1]))
1191 lj_trace_err(J, LJ_TRERR_BADTYPE); 1200 lj_trace_err(J, LJ_TRERR_BADTYPE);
1192 res[0] = lj_opt_narrow_pow(J, lj_ir_tonum(J, arg[0]), arg[1], &rd->argv[1]); 1201 res[0] = lj_opt_narrow_pow(J, tr, arg[1], &rd->argv[1]);
1193 UNUSED(rd); 1202 UNUSED(rd);
1194} 1203}
1195 1204
@@ -1203,6 +1212,32 @@ static void recff_math_minmax(jit_State *J, TRef *res, RecordFFData *rd)
1203 res[0] = tr; 1212 res[0] = tr;
1204} 1213}
1205 1214
1215static void recff_math_random(jit_State *J, TRef *res, RecordFFData *rd)
1216{
1217 GCudata *ud = udataV(&rd->fn->c.upvalue[0]);
1218 TRef tr, one;
1219 lj_ir_kgc(J, obj2gco(ud), IRT_UDATA); /* Prevent collection. */
1220 tr = lj_ir_call(J, IRCALL_lj_math_random_step, lj_ir_kptr(J, uddata(ud)));
1221 one = lj_ir_knum_one(J);
1222 tr = emitir(IRTN(IR_SUB), tr, one);
1223 if (arg[0]) {
1224 TRef tr1 = lj_ir_tonum(J, arg[0]);
1225 if (arg[1]) { /* d = floor(d*(r2-r1+1.0)) + r1 */
1226 TRef tr2 = lj_ir_tonum(J, arg[1]);
1227 tr2 = emitir(IRTN(IR_SUB), tr2, tr1);
1228 tr2 = emitir(IRTN(IR_ADD), tr2, one);
1229 tr = emitir(IRTN(IR_MUL), tr, tr2);
1230 tr = emitir(IRTN(IR_FPMATH), tr, IRFPM_FLOOR);
1231 tr = emitir(IRTN(IR_ADD), tr, tr1);
1232 } else { /* d = floor(d*r1) + 1.0 */
1233 tr = emitir(IRTN(IR_MUL), tr, tr1);
1234 tr = emitir(IRTN(IR_FPMATH), tr, IRFPM_FLOOR);
1235 tr = emitir(IRTN(IR_ADD), tr, one);
1236 }
1237 }
1238 res[0] = tr;
1239}
1240
1206/* -- Bit library fast functions ------------------------------------------ */ 1241/* -- Bit library fast functions ------------------------------------------ */
1207 1242
1208/* Record unary bit.tobit, bit.bnot, bit.bswap. */ 1243/* Record unary bit.tobit, bit.bnot, bit.bswap. */
@@ -1321,7 +1356,7 @@ static void recff_string_range(jit_State *J, TRef *res, RecordFFData *rd)
1321 for (i = 0; i < len; i++) { 1356 for (i = 0; i < len; i++) {
1322 TRef tmp = emitir(IRTI(IR_ADD), trstart, lj_ir_kint(J, i)); 1357 TRef tmp = emitir(IRTI(IR_ADD), trstart, lj_ir_kint(J, i));
1323 tmp = emitir(IRT(IR_STRREF, IRT_PTR), trstr, tmp); 1358 tmp = emitir(IRT(IR_STRREF, IRT_PTR), trstr, tmp);
1324 res[i] = emitir(IRT(IR_XLOAD, IRT_U8), tmp, 0); 1359 res[i] = emitir(IRT(IR_XLOAD, IRT_U8), tmp, IRXLOAD_READONLY);
1325 } 1360 }
1326 } else { /* Empty range or range underflow: return no results. */ 1361 } else { /* Empty range or range underflow: return no results. */
1327 emitir(IRTGI(IR_LE), trend, trstart); 1362 emitir(IRTGI(IR_LE), trend, trstart);
@@ -1335,7 +1370,7 @@ static void recff_string_range(jit_State *J, TRef *res, RecordFFData *rd)
1335static void recff_table_getn(jit_State *J, TRef *res, RecordFFData *rd) 1370static void recff_table_getn(jit_State *J, TRef *res, RecordFFData *rd)
1336{ 1371{
1337 if (tref_istab(arg[0])) { 1372 if (tref_istab(arg[0])) {
1338 res[0] = emitir(IRTI(IR_TLEN), arg[0], 0); 1373 res[0] = lj_ir_call(J, IRCALL_lj_tab_len, arg[0]);
1339 } /* else: Interpreter will throw. */ 1374 } /* else: Interpreter will throw. */
1340 UNUSED(rd); 1375 UNUSED(rd);
1341} 1376}
@@ -1344,7 +1379,7 @@ static void recff_table_remove(jit_State *J, TRef *res, RecordFFData *rd)
1344{ 1379{
1345 if (tref_istab(arg[0])) { 1380 if (tref_istab(arg[0])) {
1346 if (!arg[1] || tref_isnil(arg[1])) { /* Simple pop: t[#t] = nil */ 1381 if (!arg[1] || tref_isnil(arg[1])) { /* Simple pop: t[#t] = nil */
1347 TRef trlen = emitir(IRTI(IR_TLEN), arg[0], 0); 1382 TRef trlen = lj_ir_call(J, IRCALL_lj_tab_len, arg[0]);
1348 GCtab *t = tabV(&rd->argv[0]); 1383 GCtab *t = tabV(&rd->argv[0]);
1349 MSize len = lj_tab_len(t); 1384 MSize len = lj_tab_len(t);
1350 emitir(IRTGI(len ? IR_NE : IR_EQ), trlen, lj_ir_kint(J, 0)); 1385 emitir(IRTGI(len ? IR_NE : IR_EQ), trlen, lj_ir_kint(J, 0));
@@ -1376,7 +1411,7 @@ static void recff_table_insert(jit_State *J, TRef *res, RecordFFData *rd)
1376 rd->nres = 0; 1411 rd->nres = 0;
1377 if (tref_istab(arg[0]) && arg[1]) { 1412 if (tref_istab(arg[0]) && arg[1]) {
1378 if (!arg[2]) { /* Simple push: t[#t+1] = v */ 1413 if (!arg[2]) { /* Simple push: t[#t+1] = v */
1379 TRef trlen = emitir(IRTI(IR_TLEN), arg[0], 0); 1414 TRef trlen = lj_ir_call(J, IRCALL_lj_tab_len, arg[0]);
1380 GCtab *t = tabV(&rd->argv[0]); 1415 GCtab *t = tabV(&rd->argv[0]);
1381 RecordIndex ix; 1416 RecordIndex ix;
1382 ix.tab = arg[0]; 1417 ix.tab = arg[0];
@@ -1392,6 +1427,62 @@ static void recff_table_insert(jit_State *J, TRef *res, RecordFFData *rd)
1392 } /* else: Interpreter will throw. */ 1427 } /* else: Interpreter will throw. */
1393} 1428}
1394 1429
1430/* -- I/O library fast functions ------------------------------------------ */
1431
1432/* Get FILE* for I/O function. Any I/O error aborts recording, so there's
1433** no need to encode the alternate cases for any of the guards.
1434*/
1435static TRef recff_io_fp(jit_State *J, TRef *res, uint32_t id)
1436{
1437 TRef tr, ud, fp;
1438 if (id) { /* io.func() */
1439 tr = lj_ir_kptr(J, &J2G(J)->gcroot[id]);
1440 ud = emitir(IRT(IR_XLOAD, IRT_UDATA), tr, 0);
1441 } else { /* fp:method() */
1442 ud = arg[0];
1443 if (!tref_isudata(ud))
1444 lj_trace_err(J, LJ_TRERR_BADTYPE);
1445 tr = emitir(IRT(IR_FLOAD, IRT_U8), ud, IRFL_UDATA_UDTYPE);
1446 emitir(IRTGI(IR_EQ), tr, lj_ir_kint(J, UDTYPE_IO_FILE));
1447 }
1448 fp = emitir(IRT(IR_FLOAD, IRT_LIGHTUD), ud, IRFL_UDATA_FILE);
1449 emitir(IRTG(IR_NE, IRT_LIGHTUD), fp, lj_ir_knull(J, IRT_LIGHTUD));
1450 return fp;
1451}
1452
1453static void recff_io_write(jit_State *J, TRef *res, RecordFFData *rd)
1454{
1455 TRef fp = recff_io_fp(J, res, rd->data);
1456 TRef zero = lj_ir_kint(J, 0);
1457 TRef one = lj_ir_kint(J, 1);
1458 ptrdiff_t i = rd->data == 0 ? 1 : 0;
1459 for (; arg[i]; i++) {
1460 TRef str = lj_ir_tostr(J, arg[i]);
1461 TRef buf = emitir(IRT(IR_STRREF, IRT_PTR), str, zero);
1462 TRef len = emitir(IRTI(IR_FLOAD), str, IRFL_STR_LEN);
1463 if (tref_isk(len) && IR(tref_ref(len))->i == 1) {
1464 TRef tr = emitir(IRT(IR_XLOAD, IRT_U8), buf, IRXLOAD_READONLY);
1465 tr = lj_ir_call(J, IRCALL_fputc, tr, fp);
1466 if (rd->cres != 0) /* Check result only if requested. */
1467 emitir(IRTGI(IR_NE), tr, lj_ir_kint(J, -1));
1468 } else {
1469 TRef tr = lj_ir_call(J, IRCALL_fwrite, buf, one, len, fp);
1470 if (rd->cres != 0) /* Check result only if requested. */
1471 emitir(IRTGI(IR_EQ), tr, len);
1472 }
1473 }
1474 res[0] = TREF_TRUE;
1475}
1476
1477static void recff_io_flush(jit_State *J, TRef *res, RecordFFData *rd)
1478{
1479 TRef fp = recff_io_fp(J, res, rd->data);
1480 TRef tr = lj_ir_call(J, IRCALL_fflush, fp);
1481 if (rd->cres != 0) /* Check result only if requested. */
1482 emitir(IRTGI(IR_EQ), tr, lj_ir_kint(J, 0));
1483 res[0] = TREF_TRUE;
1484}
1485
1395/* -- Record calls and returns -------------------------------------------- */ 1486/* -- Record calls and returns -------------------------------------------- */
1396 1487
1397#undef arg 1488#undef arg
@@ -1696,6 +1787,9 @@ void lj_record_ins(jit_State *J)
1696 if (!lj_ir_numcmp(numV(rav), numV(rcv), (IROp)irop)) irop ^= 1; 1787 if (!lj_ir_numcmp(numV(rav), numV(rcv), (IROp)irop)) irop ^= 1;
1697 } else if (ta == IRT_STR) { 1788 } else if (ta == IRT_STR) {
1698 if (!lj_ir_strcmp(strV(rav), strV(rcv), (IROp)irop)) irop ^= 1; 1789 if (!lj_ir_strcmp(strV(rav), strV(rcv), (IROp)irop)) irop ^= 1;
1790 ra = lj_ir_call(J, IRCALL_lj_str_cmp, ra, rc);
1791 rc = lj_ir_kint(J, 0);
1792 ta = IRT_INT;
1699 } else { 1793 } else {
1700 rec_mm_comp(J, &ix, (int)op); 1794 rec_mm_comp(J, &ix, (int)op);
1701 break; 1795 break;
@@ -1745,7 +1839,7 @@ void lj_record_ins(jit_State *J)
1745 if (tref_isstr(rc)) { 1839 if (tref_isstr(rc)) {
1746 rc = emitir(IRTI(IR_FLOAD), rc, IRFL_STR_LEN); 1840 rc = emitir(IRTI(IR_FLOAD), rc, IRFL_STR_LEN);
1747 } else if (tref_istab(rc)) { 1841 } else if (tref_istab(rc)) {
1748 rc = emitir(IRTI(IR_TLEN), rc, 0); 1842 rc = lj_ir_call(J, IRCALL_lj_tab_len, rc);
1749 } else { 1843 } else {
1750 ix.tab = rc; 1844 ix.tab = rc;
1751 copyTV(J->L, &ix.tabv, &ix.keyv); 1845 copyTV(J->L, &ix.tabv, &ix.keyv);
@@ -1879,8 +1973,6 @@ void lj_record_ins(jit_State *J)
1879 /* fallthrough */ 1973 /* fallthrough */
1880 case BC_CALL: 1974 case BC_CALL:
1881 callop: 1975 callop:
1882 if (rb == (TRef)(CALLRES_TAILCALL+1)) { /* Tail call. */
1883 }
1884 rec_call(J, ra, (int)(rb-1), (int)(rc-1)); 1976 rec_call(J, ra, (int)(rb-1), (int)(rc-1));
1885 break; 1977 break;
1886 1978
@@ -2064,8 +2156,11 @@ static void rec_setup_side(jit_State *J, Trace *T)
2064 BCReg j; 2156 BCReg j;
2065 for (j = 0; j < s; j++) 2157 for (j = 0; j < s; j++)
2066 if (snap_ref(map[j]) == ref) { 2158 if (snap_ref(map[j]) == ref) {
2067 if (ir->o == IR_FRAME && irt_isfunc(ir->t)) 2159 if (ir->o == IR_FRAME && irt_isfunc(ir->t)) {
2160 lua_assert(s != 0);
2068 J->baseslot = s+1; 2161 J->baseslot = s+1;
2162 J->framedepth++;
2163 }
2069 tr = J->slot[j]; 2164 tr = J->slot[j];
2070 goto dupslot; 2165 goto dupslot;
2071 } 2166 }
@@ -2078,8 +2173,10 @@ static void rec_setup_side(jit_State *J, Trace *T)
2078 case IR_KNUM: tr = lj_ir_knum_addr(J, ir_knum(ir)); break; 2173 case IR_KNUM: tr = lj_ir_knum_addr(J, ir_knum(ir)); break;
2079 case IR_FRAME: /* Placeholder FRAMEs don't need a guard. */ 2174 case IR_FRAME: /* Placeholder FRAMEs don't need a guard. */
2080 if (irt_isfunc(ir->t)) { 2175 if (irt_isfunc(ir->t)) {
2081 J->baseslot = s+1; 2176 if (s != 0) {
2082 J->framedepth++; 2177 J->baseslot = s+1;
2178 J->framedepth++;
2179 }
2083 tr = lj_ir_kfunc(J, ir_kfunc(&T->ir[ir->op2])); 2180 tr = lj_ir_kfunc(J, ir_kfunc(&T->ir[ir->op2]));
2084 tr = emitir_raw(IRT(IR_FRAME, IRT_FUNC), tr, tr); 2181 tr = emitir_raw(IRT(IR_FRAME, IRT_FUNC), tr, tr);
2085 } else { 2182 } else {