diff options
Diffstat (limited to '')
-rw-r--r-- | src/lj_record.c | 125 |
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. */ |
856 | static int32_t argv2int(jit_State *J, TValue *o) | 856 | static 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 | ||
1170 | static 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 | |||
1168 | static void recff_math_modf(jit_State *J, TRef *res, RecordFFData *rd) | 1176 | static 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 | ||
1188 | static void recff_math_pow(jit_State *J, TRef *res, RecordFFData *rd) | 1196 | static 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 | ||
1215 | static 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) | |||
1335 | static void recff_table_getn(jit_State *J, TRef *res, RecordFFData *rd) | 1370 | static 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 | */ | ||
1435 | static 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 | |||
1453 | static 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 | |||
1477 | static 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 { |