summaryrefslogtreecommitdiff
path: root/src/lj_record.c
diff options
context:
space:
mode:
authorMike Pall <mike>2010-12-05 17:12:34 +0100
committerMike Pall <mike>2010-12-05 17:12:34 +0100
commite7f8cc964e036147f0303c2653a77dfe24473dcc (patch)
tree04710210a3280557a0528208440ba4b45341bebb /src/lj_record.c
parent559545eb6dc098594f957b09217ac3507b56eb3c (diff)
downloadluajit-e7f8cc964e036147f0303c2653a77dfe24473dcc.tar.gz
luajit-e7f8cc964e036147f0303c2653a77dfe24473dcc.tar.bz2
luajit-e7f8cc964e036147f0303c2653a77dfe24473dcc.zip
Split off fast function recording to lj_ffrecord.c.
Diffstat (limited to 'src/lj_record.c')
-rw-r--r--src/lj_record.c864
1 files changed, 38 insertions, 826 deletions
diff --git a/src/lj_record.c b/src/lj_record.c
index 621311c1..90c06218 100644
--- a/src/lj_record.c
+++ b/src/lj_record.c
@@ -10,11 +10,9 @@
10 10
11#if LJ_HASJIT 11#if LJ_HASJIT
12 12
13#include "lj_gc.h"
14#include "lj_err.h" 13#include "lj_err.h"
15#include "lj_str.h" 14#include "lj_str.h"
16#include "lj_tab.h" 15#include "lj_tab.h"
17#include "lj_state.h"
18#include "lj_frame.h" 16#include "lj_frame.h"
19#include "lj_bc.h" 17#include "lj_bc.h"
20#include "lj_ff.h" 18#include "lj_ff.h"
@@ -23,8 +21,8 @@
23#include "lj_iropt.h" 21#include "lj_iropt.h"
24#include "lj_trace.h" 22#include "lj_trace.h"
25#include "lj_record.h" 23#include "lj_record.h"
24#include "lj_ffrecord.h"
26#include "lj_snap.h" 25#include "lj_snap.h"
27#include "lj_asm.h"
28#include "lj_dispatch.h" 26#include "lj_dispatch.h"
29#include "lj_vm.h" 27#include "lj_vm.h"
30 28
@@ -37,26 +35,6 @@
37/* Emit raw IR without passing through optimizations. */ 35/* Emit raw IR without passing through optimizations. */
38#define emitir_raw(ot, a, b) (lj_ir_set(J, (ot), (a), (b)), lj_ir_emit(J)) 36#define emitir_raw(ot, a, b) (lj_ir_set(J, (ot), (a), (b)), lj_ir_emit(J))
39 37
40/* Context for recording an indexed load/store. */
41typedef struct RecordIndex {
42 TValue tabv; /* Runtime value of table (or indexed object). */
43 TValue keyv; /* Runtime value of key. */
44 TValue valv; /* Runtime value of stored value. */
45 TValue mobjv; /* Runtime value of metamethod object. */
46 GCtab *mtv; /* Runtime value of metatable object. */
47 cTValue *oldv; /* Runtime value of previously stored value. */
48 TRef tab; /* Table (or indexed object) reference. */
49 TRef key; /* Key reference. */
50 TRef val; /* Value reference for a store or 0 for a load. */
51 TRef mt; /* Metatable reference. */
52 TRef mobj; /* Metamethod object reference. */
53 int idxchain; /* Index indirections left or 0 for raw lookup. */
54} RecordIndex;
55
56/* Forward declarations. */
57static int rec_mm_lookup(jit_State *J, RecordIndex *ix, MMS mm);
58static TRef rec_idx(jit_State *J, RecordIndex *ix);
59
60/* -- Sanity checks ------------------------------------------------------- */ 38/* -- Sanity checks ------------------------------------------------------- */
61 39
62#ifdef LUA_USE_ASSERT 40#ifdef LUA_USE_ASSERT
@@ -182,7 +160,7 @@ static TRef getcurrf(jit_State *J)
182** Returns 2 for two different types. 160** Returns 2 for two different types.
183** Comparisons between primitives always return 1 -- no caller cares about it. 161** Comparisons between primitives always return 1 -- no caller cares about it.
184*/ 162*/
185static int rec_objcmp(jit_State *J, TRef a, TRef b, cTValue *av, cTValue *bv) 163int lj_record_objcmp(jit_State *J, TRef a, TRef b, cTValue *av, cTValue *bv)
186{ 164{
187 int diff = !lj_obj_equal(av, bv); 165 int diff = !lj_obj_equal(av, bv);
188 if (!tref_isk2(a, b)) { /* Shortcut, also handles primitives. */ 166 if (!tref_isk2(a, b)) { /* Shortcut, also handles primitives. */
@@ -492,7 +470,7 @@ static void rec_call_setup(jit_State *J, BCReg func, ptrdiff_t nargs)
492 if (!tref_isfunc(fbase[0])) { /* Resolve __call metamethod. */ 470 if (!tref_isfunc(fbase[0])) { /* Resolve __call metamethod. */
493 ix.tab = fbase[0]; 471 ix.tab = fbase[0];
494 copyTV(J->L, &ix.tabv, functv); 472 copyTV(J->L, &ix.tabv, functv);
495 if (!rec_mm_lookup(J, &ix, MM_call) || !tref_isfunc(ix.mobj)) 473 if (!lj_record_mm_lookup(J, &ix, MM_call) || !tref_isfunc(ix.mobj))
496 lj_trace_err(J, LJ_TRERR_NOMM); 474 lj_trace_err(J, LJ_TRERR_NOMM);
497 for (i = ++nargs; i > 0; i--) /* Shift arguments up. */ 475 for (i = ++nargs; i > 0; i--) /* Shift arguments up. */
498 fbase[i] = fbase[i-1]; 476 fbase[i] = fbase[i-1];
@@ -508,7 +486,7 @@ static void rec_call_setup(jit_State *J, BCReg func, ptrdiff_t nargs)
508} 486}
509 487
510/* Record call. */ 488/* Record call. */
511static void rec_call(jit_State *J, BCReg func, ptrdiff_t nargs) 489void lj_record_call(jit_State *J, BCReg func, ptrdiff_t nargs)
512{ 490{
513 rec_call_setup(J, func, nargs); 491 rec_call_setup(J, func, nargs);
514 /* Bump frame. */ 492 /* Bump frame. */
@@ -518,7 +496,7 @@ static void rec_call(jit_State *J, BCReg func, ptrdiff_t nargs)
518} 496}
519 497
520/* Record tail call. */ 498/* Record tail call. */
521static void rec_tailcall(jit_State *J, BCReg func, ptrdiff_t nargs) 499void lj_record_tailcall(jit_State *J, BCReg func, ptrdiff_t nargs)
522{ 500{
523 rec_call_setup(J, func, nargs); 501 rec_call_setup(J, func, nargs);
524 if (frame_isvarg(J->L->base - 1)) { 502 if (frame_isvarg(J->L->base - 1)) {
@@ -561,7 +539,7 @@ static int check_downrec_unroll(jit_State *J, GCproto *pt)
561} 539}
562 540
563/* Record return. */ 541/* Record return. */
564static void rec_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) 542void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults)
565{ 543{
566 TValue *frame = J->L->base - 1; 544 TValue *frame = J->L->base - 1;
567 ptrdiff_t i; 545 ptrdiff_t i;
@@ -672,7 +650,7 @@ static BCReg rec_mm_prep(jit_State *J, ASMFunction cont)
672} 650}
673 651
674/* Record metamethod lookup. */ 652/* Record metamethod lookup. */
675static int rec_mm_lookup(jit_State *J, RecordIndex *ix, MMS mm) 653int lj_record_mm_lookup(jit_State *J, RecordIndex *ix, MMS mm)
676{ 654{
677 RecordIndex mix; 655 RecordIndex mix;
678 GCtab *mt; 656 GCtab *mt;
@@ -706,7 +684,7 @@ nocheck:
706 mix.key = lj_ir_kstr(J, mmstr); 684 mix.key = lj_ir_kstr(J, mmstr);
707 mix.val = 0; 685 mix.val = 0;
708 mix.idxchain = 0; 686 mix.idxchain = 0;
709 ix->mobj = rec_idx(J, &mix); 687 ix->mobj = lj_record_idx(J, &mix);
710 return !tref_isnil(ix->mobj); /* 1 if metamethod found, 0 if not. */ 688 return !tref_isnil(ix->mobj); /* 1 if metamethod found, 0 if not. */
711 } 689 }
712 return 0; /* No metamethod. */ 690 return 0; /* No metamethod. */
@@ -722,11 +700,11 @@ static TRef rec_mm_arith(jit_State *J, RecordIndex *ix, MMS mm)
722 base[1] = ix->tab; base[2] = ix->key; 700 base[1] = ix->tab; base[2] = ix->key;
723 copyTV(J->L, basev+1, &ix->tabv); 701 copyTV(J->L, basev+1, &ix->tabv);
724 copyTV(J->L, basev+2, &ix->keyv); 702 copyTV(J->L, basev+2, &ix->keyv);
725 if (!rec_mm_lookup(J, ix, mm)) { /* Lookup metamethod on 1st operand. */ 703 if (!lj_record_mm_lookup(J, ix, mm)) { /* Lookup mm on 1st operand. */
726 if (mm != MM_len) { 704 if (mm != MM_len) {
727 ix->tab = ix->key; 705 ix->tab = ix->key;
728 copyTV(J->L, &ix->tabv, &ix->keyv); 706 copyTV(J->L, &ix->tabv, &ix->keyv);
729 if (rec_mm_lookup(J, ix, mm)) /* Lookup metamethod on 2nd operand. */ 707 if (lj_record_mm_lookup(J, ix, mm)) /* Lookup mm on 2nd operand. */
730 goto ok; 708 goto ok;
731 } 709 }
732 lj_trace_err(J, LJ_TRERR_NOMM); 710 lj_trace_err(J, LJ_TRERR_NOMM);
@@ -734,7 +712,7 @@ static TRef rec_mm_arith(jit_State *J, RecordIndex *ix, MMS mm)
734ok: 712ok:
735 base[0] = ix->mobj; 713 base[0] = ix->mobj;
736 copyTV(J->L, basev+0, &ix->mobjv); 714 copyTV(J->L, basev+0, &ix->mobjv);
737 rec_call(J, func, 2); 715 lj_record_call(J, func, 2);
738 return 0; /* No result yet. */ 716 return 0; /* No result yet. */
739} 717}
740 718
@@ -748,7 +726,7 @@ static void rec_mm_callcomp(jit_State *J, RecordIndex *ix, int op)
748 copyTV(J->L, tv+0, &ix->mobjv); 726 copyTV(J->L, tv+0, &ix->mobjv);
749 copyTV(J->L, tv+1, &ix->valv); 727 copyTV(J->L, tv+1, &ix->valv);
750 copyTV(J->L, tv+2, &ix->keyv); 728 copyTV(J->L, tv+2, &ix->keyv);
751 rec_call(J, func, 2); 729 lj_record_call(J, func, 2);
752} 730}
753 731
754/* Record call to equality comparison metamethod (for tab and udata only). */ 732/* Record call to equality comparison metamethod (for tab and udata only). */
@@ -756,7 +734,7 @@ static void rec_mm_equal(jit_State *J, RecordIndex *ix, int op)
756{ 734{
757 ix->tab = ix->val; 735 ix->tab = ix->val;
758 copyTV(J->L, &ix->tabv, &ix->valv); 736 copyTV(J->L, &ix->tabv, &ix->valv);
759 if (rec_mm_lookup(J, ix, MM_eq)) { /* Lookup metamethod on 1st operand. */ 737 if (lj_record_mm_lookup(J, ix, MM_eq)) { /* Lookup mm on 1st operand. */
760 cTValue *bv; 738 cTValue *bv;
761 TRef mo1 = ix->mobj; 739 TRef mo1 = ix->mobj;
762 TValue mo1v; 740 TValue mo1v;
@@ -772,8 +750,8 @@ static void rec_mm_equal(jit_State *J, RecordIndex *ix, int op)
772 } else { /* Lookup metamethod on 2nd operand and compare both. */ 750 } else { /* Lookup metamethod on 2nd operand and compare both. */
773 ix->tab = ix->key; 751 ix->tab = ix->key;
774 copyTV(J->L, &ix->tabv, bv); 752 copyTV(J->L, &ix->tabv, bv);
775 if (!rec_mm_lookup(J, ix, MM_eq) || 753 if (!lj_record_mm_lookup(J, ix, MM_eq) ||
776 rec_objcmp(J, mo1, ix->mobj, &mo1v, &ix->mobjv)) 754 lj_record_objcmp(J, mo1, ix->mobj, &mo1v, &ix->mobjv))
777 return; 755 return;
778 } 756 }
779 rec_mm_callcomp(J, ix, op); 757 rec_mm_callcomp(J, ix, op);
@@ -787,7 +765,7 @@ static void rec_mm_comp(jit_State *J, RecordIndex *ix, int op)
787 copyTV(J->L, &ix->tabv, &ix->valv); 765 copyTV(J->L, &ix->tabv, &ix->valv);
788 while (1) { 766 while (1) {
789 MMS mm = (op & 2) ? MM_le : MM_lt; /* Try __le + __lt or only __lt. */ 767 MMS mm = (op & 2) ? MM_le : MM_lt; /* Try __le + __lt or only __lt. */
790 if (rec_mm_lookup(J, ix, mm)) { /* Lookup metamethod on 1st operand. */ 768 if (lj_record_mm_lookup(J, ix, mm)) { /* Lookup mm on 1st operand. */
791 cTValue *bv; 769 cTValue *bv;
792 TRef mo1 = ix->mobj; 770 TRef mo1 = ix->mobj;
793 TValue mo1v; 771 TValue mo1v;
@@ -803,8 +781,8 @@ static void rec_mm_comp(jit_State *J, RecordIndex *ix, int op)
803 } else { /* Lookup metamethod on 2nd operand and compare both. */ 781 } else { /* Lookup metamethod on 2nd operand and compare both. */
804 ix->tab = ix->key; 782 ix->tab = ix->key;
805 copyTV(J->L, &ix->tabv, bv); 783 copyTV(J->L, &ix->tabv, bv);
806 if (!rec_mm_lookup(J, ix, mm) || 784 if (!lj_record_mm_lookup(J, ix, mm) ||
807 rec_objcmp(J, mo1, ix->mobj, &mo1v, &ix->mobjv)) 785 lj_record_objcmp(J, mo1, ix->mobj, &mo1v, &ix->mobjv))
808 goto nomatch; 786 goto nomatch;
809 } 787 }
810 rec_mm_callcomp(J, ix, op); 788 rec_mm_callcomp(J, ix, op);
@@ -943,15 +921,16 @@ static int nommstr(jit_State *J, TRef key)
943} 921}
944 922
945/* Record indexed load/store. */ 923/* Record indexed load/store. */
946static TRef rec_idx(jit_State *J, RecordIndex *ix) 924TRef lj_record_idx(jit_State *J, RecordIndex *ix)
947{ 925{
948 TRef xref; 926 TRef xref;
949 IROp xrefop, loadop; 927 IROp xrefop, loadop;
950 cTValue *oldv; 928 cTValue *oldv;
951 929
952 while (!tref_istab(ix->tab)) { /* Handle non-table lookup. */ 930 while (!tref_istab(ix->tab)) { /* Handle non-table lookup. */
953 lua_assert(ix->idxchain != 0); /* Never call raw rec_idx() on non-table. */ 931 /* Never call raw lj_record_idx() on non-table. */
954 if (!rec_mm_lookup(J, ix, ix->val ? MM_newindex : MM_index)) 932 lua_assert(ix->idxchain != 0);
933 if (!lj_record_mm_lookup(J, ix, ix->val ? MM_newindex : MM_index))
955 lj_trace_err(J, LJ_TRERR_NOMM); 934 lj_trace_err(J, LJ_TRERR_NOMM);
956 handlemm: 935 handlemm:
957 if (tref_isfunc(ix->mobj)) { /* Handle metamethod call. */ 936 if (tref_isfunc(ix->mobj)) { /* Handle metamethod call. */
@@ -965,10 +944,10 @@ static TRef rec_idx(jit_State *J, RecordIndex *ix)
965 if (ix->val) { 944 if (ix->val) {
966 base[3] = ix->val; 945 base[3] = ix->val;
967 copyTV(J->L, tv+3, &ix->valv); 946 copyTV(J->L, tv+3, &ix->valv);
968 rec_call(J, func, 3); /* mobj(tab, key, val) */ 947 lj_record_call(J, func, 3); /* mobj(tab, key, val) */
969 return 0; 948 return 0;
970 } else { 949 } else {
971 rec_call(J, func, 2); /* res = mobj(tab, key) */ 950 lj_record_call(J, func, 2); /* res = mobj(tab, key) */
972 return 0; /* No result yet. */ 951 return 0; /* No result yet. */
973 } 952 }
974 } 953 }
@@ -984,7 +963,7 @@ static TRef rec_idx(jit_State *J, RecordIndex *ix)
984 if (ix->val) /* Better fail early. */ 963 if (ix->val) /* Better fail early. */
985 lj_trace_err(J, LJ_TRERR_STORENN); 964 lj_trace_err(J, LJ_TRERR_STORENN);
986 if (tref_isk(ix->key)) { 965 if (tref_isk(ix->key)) {
987 if (ix->idxchain && rec_mm_lookup(J, ix, MM_index)) 966 if (ix->idxchain && lj_record_mm_lookup(J, ix, MM_index))
988 goto handlemm; 967 goto handlemm;
989 return TREF_NIL; 968 return TREF_NIL;
990 } 969 }
@@ -1005,7 +984,7 @@ static TRef rec_idx(jit_State *J, RecordIndex *ix)
1005 } else { 984 } else {
1006 res = emitir(IRTG(loadop, t), xref, 0); 985 res = emitir(IRTG(loadop, t), xref, 0);
1007 } 986 }
1008 if (t == IRT_NIL && ix->idxchain && rec_mm_lookup(J, ix, MM_index)) 987 if (t == IRT_NIL && ix->idxchain && lj_record_mm_lookup(J, ix, MM_index))
1009 goto handlemm; 988 goto handlemm;
1010 if (irtype_ispri(t)) res = TREF_PRI(t); /* Canonicalize primitives. */ 989 if (irtype_ispri(t)) res = TREF_PRI(t); /* Canonicalize primitives. */
1011 return res; 990 return res;
@@ -1024,7 +1003,7 @@ static TRef rec_idx(jit_State *J, RecordIndex *ix)
1024 else if (xrefop == IR_HREF) 1003 else if (xrefop == IR_HREF)
1025 emitir(IRTG(oldv == niltvg(J2G(J)) ? IR_EQ : IR_NE, IRT_PTR), 1004 emitir(IRTG(oldv == niltvg(J2G(J)) ? IR_EQ : IR_NE, IRT_PTR),
1026 xref, lj_ir_kptr(J, niltvg(J2G(J)))); 1005 xref, lj_ir_kptr(J, niltvg(J2G(J))));
1027 if (ix->idxchain && rec_mm_lookup(J, ix, MM_newindex)) { /* Metamethod? */ 1006 if (ix->idxchain && lj_record_mm_lookup(J, ix, MM_newindex)) {
1028 lua_assert(hasmm); 1007 lua_assert(hasmm);
1029 goto handlemm; 1008 goto handlemm;
1030 } 1009 }
@@ -1117,773 +1096,6 @@ static TRef rec_upvalue(jit_State *J, uint32_t uv, TRef val)
1117 } 1096 }
1118} 1097}
1119 1098
1120/* -- Fast function recording handlers ------------------------------------ */
1121
1122/* Conventions for fast function call handlers:
1123**
1124** The argument slots start at J->base[0]. All of them are guaranteed to be
1125** valid and type-specialized references. J->base[J->maxslot] is set to 0
1126** as a sentinel. The runtime argument values start at rd->argv[0].
1127**
1128** In general fast functions should check for presence of all of their
1129** arguments and for the correct argument types. Some simplifications
1130** are allowed if the interpreter throws instead. But even if recording
1131** is aborted, the generated IR must be consistent (no zero-refs).
1132**
1133** The number of results in rd->nres is set to 1. Handlers that return
1134** a different number of results need to override it. A negative value
1135** prevents return processing (e.g. for pending calls).
1136**
1137** Results need to be stored starting at J->base[0]. Return processing
1138** moves them to the right slots later.
1139**
1140** The per-ffid auxiliary data is the value of the 2nd part of the
1141** LJLIB_REC() annotation. This allows handling similar functionality
1142** in a common handler.
1143*/
1144
1145/* Data used by handlers to record a fast function. */
1146typedef struct RecordFFData {
1147 TValue *argv; /* Runtime argument values. */
1148 ptrdiff_t nres; /* Number of returned results (defaults to 1). */
1149 uint32_t data; /* Per-ffid auxiliary data (opcode, literal etc.). */
1150} RecordFFData;
1151
1152/* Type of handler to record a fast function. */
1153typedef void (LJ_FASTCALL *RecordFunc)(jit_State *J, RecordFFData *rd);
1154
1155/* Get runtime value of int argument. */
1156static int32_t argv2int(jit_State *J, TValue *o)
1157{
1158 if (!tvisnum(o) && !(tvisstr(o) && lj_str_tonum(strV(o), o)))
1159 lj_trace_err(J, LJ_TRERR_BADTYPE);
1160 return lj_num2bit(numV(o));
1161}
1162
1163/* Get runtime value of string argument. */
1164static GCstr *argv2str(jit_State *J, TValue *o)
1165{
1166 if (LJ_LIKELY(tvisstr(o))) {
1167 return strV(o);
1168 } else {
1169 GCstr *s;
1170 if (!tvisnum(o))
1171 lj_trace_err(J, LJ_TRERR_BADTYPE);
1172 s = lj_str_fromnum(J->L, &o->n);
1173 setstrV(J->L, o, s);
1174 return s;
1175 }
1176}
1177
1178/* Return number of results wanted by caller. */
1179static ptrdiff_t results_wanted(jit_State *J)
1180{
1181 TValue *frame = J->L->base-1;
1182 if (frame_islua(frame))
1183 return (ptrdiff_t)bc_b(frame_pc(frame)[-1]) - 1;
1184 else
1185 return -1;
1186}
1187
1188/* Throw error for unsupported variant of fast function. */
1189LJ_NORET static void recff_nyiu(jit_State *J)
1190{
1191 setfuncV(J->L, &J->errinfo, J->fn);
1192 lj_trace_err_info(J, LJ_TRERR_NYIFFU);
1193}
1194
1195/* Fallback handler for all fast functions that are not recorded (yet). */
1196static void LJ_FASTCALL recff_nyi(jit_State *J, RecordFFData *rd)
1197{
1198 setfuncV(J->L, &J->errinfo, J->fn);
1199 lj_trace_err_info(J, LJ_TRERR_NYIFF);
1200 UNUSED(rd);
1201}
1202
1203/* C functions can have arbitrary side-effects and are not recorded (yet). */
1204static void LJ_FASTCALL recff_c(jit_State *J, RecordFFData *rd)
1205{
1206 setfuncV(J->L, &J->errinfo, J->fn);
1207 lj_trace_err_info(J, LJ_TRERR_NYICF);
1208 UNUSED(rd);
1209}
1210
1211/* -- Base library fast functions ----------------------------------------- */
1212
1213static void LJ_FASTCALL recff_assert(jit_State *J, RecordFFData *rd)
1214{
1215 /* Arguments already specialized. The interpreter throws for nil/false. */
1216 rd->nres = J->maxslot; /* Pass through all arguments. */
1217}
1218
1219static void LJ_FASTCALL recff_type(jit_State *J, RecordFFData *rd)
1220{
1221 /* Arguments already specialized. Result is a constant string. Neat, huh? */
1222 IRType t = tref_isinteger(J->base[0]) ? IRT_NUM : tref_type(J->base[0]);
1223 J->base[0] = lj_ir_kstr(J, strV(&J->fn->c.upvalue[t]));
1224 UNUSED(rd);
1225}
1226
1227static void LJ_FASTCALL recff_getmetatable(jit_State *J, RecordFFData *rd)
1228{
1229 TRef tr = J->base[0];
1230 if (tr) {
1231 RecordIndex ix;
1232 ix.tab = tr;
1233 copyTV(J->L, &ix.tabv, &rd->argv[0]);
1234 if (rec_mm_lookup(J, &ix, MM_metatable))
1235 J->base[0] = ix.mobj;
1236 else
1237 J->base[0] = ix.mt;
1238 } /* else: Interpreter will throw. */
1239}
1240
1241static void LJ_FASTCALL recff_setmetatable(jit_State *J, RecordFFData *rd)
1242{
1243 TRef tr = J->base[0];
1244 TRef mt = J->base[1];
1245 if (tref_istab(tr) && (tref_istab(mt) || (mt && tref_isnil(mt)))) {
1246 TRef fref, mtref;
1247 RecordIndex ix;
1248 ix.tab = tr;
1249 copyTV(J->L, &ix.tabv, &rd->argv[0]);
1250 rec_mm_lookup(J, &ix, MM_metatable); /* Guard for no __metatable field. */
1251 fref = emitir(IRT(IR_FREF, IRT_PTR), tr, IRFL_TAB_META);
1252 mtref = tref_isnil(mt) ? lj_ir_knull(J, IRT_TAB) : mt;
1253 emitir(IRT(IR_FSTORE, IRT_TAB), fref, mtref);
1254 if (!tref_isnil(mt))
1255 emitir(IRT(IR_TBAR, IRT_TAB), tr, 0);
1256 J->base[0] = tr;
1257 J->needsnap = 1;
1258 } /* else: Interpreter will throw. */
1259}
1260
1261static void LJ_FASTCALL recff_rawget(jit_State *J, RecordFFData *rd)
1262{
1263 RecordIndex ix;
1264 ix.tab = J->base[0]; ix.key = J->base[1];
1265 if (tref_istab(ix.tab) && ix.key) {
1266 ix.val = 0; ix.idxchain = 0;
1267 settabV(J->L, &ix.tabv, tabV(&rd->argv[0]));
1268 copyTV(J->L, &ix.keyv, &rd->argv[1]);
1269 J->base[0] = rec_idx(J, &ix);
1270 } /* else: Interpreter will throw. */
1271}
1272
1273static void LJ_FASTCALL recff_rawset(jit_State *J, RecordFFData *rd)
1274{
1275 RecordIndex ix;
1276 ix.tab = J->base[0]; ix.key = J->base[1]; ix.val = J->base[2];
1277 if (tref_istab(ix.tab) && ix.key && ix.val) {
1278 ix.idxchain = 0;
1279 settabV(J->L, &ix.tabv, tabV(&rd->argv[0]));
1280 copyTV(J->L, &ix.keyv, &rd->argv[1]);
1281 copyTV(J->L, &ix.valv, &rd->argv[2]);
1282 rec_idx(J, &ix);
1283 /* Pass through table at J->base[0] as result. */
1284 } /* else: Interpreter will throw. */
1285}
1286
1287static void LJ_FASTCALL recff_rawequal(jit_State *J, RecordFFData *rd)
1288{
1289 TRef tra = J->base[0];
1290 TRef trb = J->base[1];
1291 if (tra && trb) {
1292 int diff = rec_objcmp(J, tra, trb, &rd->argv[0], &rd->argv[1]);
1293 J->base[0] = diff ? TREF_FALSE : TREF_TRUE;
1294 } /* else: Interpreter will throw. */
1295}
1296
1297/* Determine mode of select() call. */
1298static int32_t select_mode(jit_State *J, TRef tr, TValue *tv)
1299{
1300 if (tref_isstr(tr) && *strVdata(tv) == '#') { /* select('#', ...) */
1301 if (strV(tv)->len == 1) {
1302 emitir(IRT(IR_EQ, IRT_STR), tr, lj_ir_kstr(J, strV(tv)));
1303 } else {
1304 TRef trptr = emitir(IRT(IR_STRREF, IRT_PTR), tr, 0);
1305 TRef trchar = emitir(IRT(IR_XLOAD, IRT_U8), trptr, IRXLOAD_READONLY);
1306 emitir(IRT(IR_EQ, IRT_INT), trchar, lj_ir_kint(J, '#'));
1307 }
1308 return 0;
1309 } else { /* select(n, ...) */
1310 int32_t start = argv2int(J, tv);
1311 if (start == 0) lj_trace_err(J, LJ_TRERR_BADTYPE); /* A bit misleading. */
1312 return start;
1313 }
1314}
1315
1316static void LJ_FASTCALL recff_select(jit_State *J, RecordFFData *rd)
1317{
1318 TRef tr = J->base[0];
1319 if (tr) {
1320 ptrdiff_t start = select_mode(J, tr, &rd->argv[0]);
1321 if (start == 0) { /* select('#', ...) */
1322 J->base[0] = lj_ir_kint(J, J->maxslot - 1);
1323 } else if (tref_isk(tr)) { /* select(k, ...) */
1324 ptrdiff_t n = (ptrdiff_t)J->maxslot;
1325 if (start < 0) start += n;
1326 else if (start > n) start = n;
1327 rd->nres = n - start;
1328 if (start >= 1) {
1329 ptrdiff_t i;
1330 for (i = 0; i < n - start; i++)
1331 J->base[i] = J->base[start+i];
1332 } /* else: Interpreter will throw. */
1333 } else {
1334 recff_nyiu(J);
1335 }
1336 } /* else: Interpreter will throw. */
1337}
1338
1339static void LJ_FASTCALL recff_tonumber(jit_State *J, RecordFFData *rd)
1340{
1341 TRef tr = J->base[0];
1342 if (tref_isnumber_str(tr)) {
1343 TRef base = J->base[1];
1344 if (base) {
1345 base = lj_ir_toint(J, base);
1346 if (!tref_isk(base) || IR(tref_ref(base))->i != 10)
1347 recff_nyiu(J);
1348 }
1349 if (tref_isstr(tr)) {
1350 TValue tmp;
1351 if (!lj_str_tonum(strV(&rd->argv[0]), &tmp))
1352 recff_nyiu(J); /* Would need an inverted STRTO for this case. */
1353 tr = emitir(IRTG(IR_STRTO, IRT_NUM), tr, 0);
1354 }
1355 } else {
1356 tr = TREF_NIL;
1357 }
1358 J->base[0] = tr;
1359 UNUSED(rd);
1360}
1361
1362static TValue *recff_metacall_cp(lua_State *L, lua_CFunction dummy, void *ud)
1363{
1364 jit_State *J = (jit_State *)ud;
1365 rec_tailcall(J, 0, 1);
1366 UNUSED(L); UNUSED(dummy);
1367 return NULL;
1368}
1369
1370static int recff_metacall(jit_State *J, RecordFFData *rd, MMS mm)
1371{
1372 RecordIndex ix;
1373 ix.tab = J->base[0];
1374 copyTV(J->L, &ix.tabv, &rd->argv[0]);
1375 if (rec_mm_lookup(J, &ix, mm)) { /* Has metamethod? */
1376 int errcode;
1377 /* Temporarily insert metamethod below object. */
1378 J->base[1] = J->base[0];
1379 J->base[0] = ix.mobj;
1380 copyTV(J->L, &rd->argv[1], &rd->argv[0]);
1381 copyTV(J->L, &rd->argv[0], &ix.mobjv);
1382 /* Need to protect rec_tailcall because it may throw. */
1383 errcode = lj_vm_cpcall(J->L, NULL, J, recff_metacall_cp);
1384 /* Always undo Lua stack changes to avoid confusing the interpreter. */
1385 copyTV(J->L, &rd->argv[0], &rd->argv[1]);
1386 if (errcode)
1387 lj_err_throw(J->L, errcode); /* Propagate errors. */
1388 rd->nres = -1; /* Pending call. */
1389 return 1; /* Tailcalled to metamethod. */
1390 }
1391 return 0;
1392}
1393
1394static void LJ_FASTCALL recff_tostring(jit_State *J, RecordFFData *rd)
1395{
1396 TRef tr = J->base[0];
1397 if (tref_isstr(tr)) {
1398 /* Ignore __tostring in the string base metatable. */
1399 /* Pass on result in J->base[0]. */
1400 } else if (!recff_metacall(J, rd, MM_tostring)) {
1401 if (tref_isnumber(tr)) {
1402 J->base[0] = emitir(IRT(IR_TOSTR, IRT_STR), tr, 0);
1403 } else if (tref_ispri(tr)) {
1404 J->base[0] = lj_ir_kstr(J, strV(&J->fn->c.upvalue[tref_type(tr)]));
1405 } else {
1406 recff_nyiu(J);
1407 }
1408 }
1409}
1410
1411static void LJ_FASTCALL recff_ipairs_aux(jit_State *J, RecordFFData *rd)
1412{
1413 RecordIndex ix;
1414 ix.tab = J->base[0];
1415 if (tref_istab(ix.tab)) {
1416 if (!tvisnum(&rd->argv[1])) /* No support for string coercion. */
1417 lj_trace_err(J, LJ_TRERR_BADTYPE);
1418 setnumV(&ix.keyv, numV(&rd->argv[1])+(lua_Number)1);
1419 settabV(J->L, &ix.tabv, tabV(&rd->argv[0]));
1420 ix.val = 0; ix.idxchain = 0;
1421 ix.key = lj_ir_toint(J, J->base[1]);
1422 J->base[0] = ix.key = emitir(IRTI(IR_ADD), ix.key, lj_ir_kint(J, 1));
1423 J->base[1] = rec_idx(J, &ix);
1424 rd->nres = tref_isnil(J->base[1]) ? 0 : 2;
1425 } /* else: Interpreter will throw. */
1426}
1427
1428static void LJ_FASTCALL recff_ipairs(jit_State *J, RecordFFData *rd)
1429{
1430#ifdef LUAJIT_ENABLE_LUA52COMPAT
1431 if (!recff_metacall(J, rd, MM_ipairs))
1432#endif
1433 {
1434 TRef tab = J->base[0];
1435 if (tref_istab(tab)) {
1436 J->base[0] = lj_ir_kfunc(J, funcV(&J->fn->c.upvalue[0]));
1437 J->base[1] = tab;
1438 J->base[2] = lj_ir_kint(J, 0);
1439 rd->nres = 3;
1440 } /* else: Interpreter will throw. */
1441 }
1442}
1443
1444static void LJ_FASTCALL recff_pcall(jit_State *J, RecordFFData *rd)
1445{
1446 if (J->maxslot >= 1) {
1447 rec_call(J, 0, J->maxslot - 1);
1448 rd->nres = -1; /* Pending call. */
1449 } /* else: Interpreter will throw. */
1450}
1451
1452static TValue *recff_xpcall_cp(lua_State *L, lua_CFunction dummy, void *ud)
1453{
1454 jit_State *J = (jit_State *)ud;
1455 rec_call(J, 1, J->maxslot - 2);
1456 UNUSED(L); UNUSED(dummy);
1457 return NULL;
1458}
1459
1460static void LJ_FASTCALL recff_xpcall(jit_State *J, RecordFFData *rd)
1461{
1462 if (J->maxslot >= 2) {
1463 TValue argv0, argv1;
1464 TRef tmp;
1465 int errcode;
1466 /* Swap function and traceback. */
1467 tmp = J->base[0]; J->base[0] = J->base[1]; J->base[1] = tmp;
1468 copyTV(J->L, &argv0, &rd->argv[0]);
1469 copyTV(J->L, &argv1, &rd->argv[1]);
1470 copyTV(J->L, &rd->argv[0], &argv1);
1471 copyTV(J->L, &rd->argv[1], &argv0);
1472 /* Need to protect rec_call because it may throw. */
1473 errcode = lj_vm_cpcall(J->L, NULL, J, recff_xpcall_cp);
1474 /* Always undo Lua stack swap to avoid confusing the interpreter. */
1475 copyTV(J->L, &rd->argv[0], &argv0);
1476 copyTV(J->L, &rd->argv[1], &argv1);
1477 if (errcode)
1478 lj_err_throw(J->L, errcode); /* Propagate errors. */
1479 rd->nres = -1; /* Pending call. */
1480 } /* else: Interpreter will throw. */
1481}
1482
1483/* -- Math library fast functions ----------------------------------------- */
1484
1485static void LJ_FASTCALL recff_math_abs(jit_State *J, RecordFFData *rd)
1486{
1487 TRef tr = lj_ir_tonum(J, J->base[0]);
1488 J->base[0] = emitir(IRTN(IR_ABS), tr, lj_ir_knum_abs(J));
1489 UNUSED(rd);
1490}
1491
1492/* Record rounding functions math.floor and math.ceil. */
1493static void LJ_FASTCALL recff_math_round(jit_State *J, RecordFFData *rd)
1494{
1495 if (!tref_isinteger(J->base[0])) /* Pass through integers unmodified. */
1496 J->base[0] = emitir(IRTN(IR_FPMATH), lj_ir_tonum(J, J->base[0]), rd->data);
1497 /* Note: result is integral (or NaN/Inf), but may not fit into an integer. */
1498}
1499
1500/* Record unary math.* functions, mapped to IR_FPMATH opcode. */
1501static void LJ_FASTCALL recff_math_unary(jit_State *J, RecordFFData *rd)
1502{
1503 J->base[0] = emitir(IRTN(IR_FPMATH), lj_ir_tonum(J, J->base[0]), rd->data);
1504}
1505
1506/* Record binary math.* functions math.atan2 and math.ldexp. */
1507static void LJ_FASTCALL recff_math_binary(jit_State *J, RecordFFData *rd)
1508{
1509 TRef tr = lj_ir_tonum(J, J->base[0]);
1510 J->base[0] = emitir(IRTN(rd->data), tr, lj_ir_tonum(J, J->base[1]));
1511}
1512
1513/* Record math.asin, math.acos, math.atan. */
1514static void LJ_FASTCALL recff_math_atrig(jit_State *J, RecordFFData *rd)
1515{
1516 TRef y = lj_ir_tonum(J, J->base[0]);
1517 TRef x = lj_ir_knum_one(J);
1518 uint32_t ffid = rd->data;
1519 if (ffid != FF_math_atan) {
1520 TRef tmp = emitir(IRTN(IR_MUL), y, y);
1521 tmp = emitir(IRTN(IR_SUB), x, tmp);
1522 tmp = emitir(IRTN(IR_FPMATH), tmp, IRFPM_SQRT);
1523 if (ffid == FF_math_asin) { x = tmp; } else { x = y; y = tmp; }
1524 }
1525 J->base[0] = emitir(IRTN(IR_ATAN2), y, x);
1526}
1527
1528static void LJ_FASTCALL recff_math_htrig(jit_State *J, RecordFFData *rd)
1529{
1530 TRef tr = lj_ir_tonum(J, J->base[0]);
1531 J->base[0] = lj_ir_call(J, rd->data, tr);
1532}
1533
1534static void LJ_FASTCALL recff_math_modf(jit_State *J, RecordFFData *rd)
1535{
1536 TRef tr = J->base[0];
1537 if (tref_isinteger(tr)) {
1538 J->base[0] = tr;
1539 J->base[1] = lj_ir_kint(J, 0);
1540 } else {
1541 TRef trt;
1542 tr = lj_ir_tonum(J, tr);
1543 trt = emitir(IRTN(IR_FPMATH), tr, IRFPM_TRUNC);
1544 J->base[0] = trt;
1545 J->base[1] = emitir(IRTN(IR_SUB), tr, trt);
1546 }
1547 rd->nres = 2;
1548}
1549
1550static void LJ_FASTCALL recff_math_degrad(jit_State *J, RecordFFData *rd)
1551{
1552 TRef tr = lj_ir_tonum(J, J->base[0]);
1553 TRef trm = lj_ir_knum(J, numV(&J->fn->c.upvalue[0]));
1554 J->base[0] = emitir(IRTN(IR_MUL), tr, trm);
1555 UNUSED(rd);
1556}
1557
1558static void LJ_FASTCALL recff_math_pow(jit_State *J, RecordFFData *rd)
1559{
1560 TRef tr = lj_ir_tonum(J, J->base[0]);
1561 if (!tref_isnumber_str(J->base[1]))
1562 lj_trace_err(J, LJ_TRERR_BADTYPE);
1563 J->base[0] = lj_opt_narrow_pow(J, tr, J->base[1], &rd->argv[1]);
1564 UNUSED(rd);
1565}
1566
1567static void LJ_FASTCALL recff_math_minmax(jit_State *J, RecordFFData *rd)
1568{
1569 TRef tr = lj_ir_tonum(J, J->base[0]);
1570 uint32_t op = rd->data;
1571 BCReg i;
1572 for (i = 1; J->base[i] != 0; i++)
1573 tr = emitir(IRTN(op), tr, lj_ir_tonum(J, J->base[i]));
1574 J->base[0] = tr;
1575}
1576
1577static void LJ_FASTCALL recff_math_random(jit_State *J, RecordFFData *rd)
1578{
1579 GCudata *ud = udataV(&J->fn->c.upvalue[0]);
1580 TRef tr, one;
1581 lj_ir_kgc(J, obj2gco(ud), IRT_UDATA); /* Prevent collection. */
1582 tr = lj_ir_call(J, IRCALL_lj_math_random_step, lj_ir_kptr(J, uddata(ud)));
1583 one = lj_ir_knum_one(J);
1584 tr = emitir(IRTN(IR_SUB), tr, one);
1585 if (J->base[0]) {
1586 TRef tr1 = lj_ir_tonum(J, J->base[0]);
1587 if (J->base[1]) { /* d = floor(d*(r2-r1+1.0)) + r1 */
1588 TRef tr2 = lj_ir_tonum(J, J->base[1]);
1589 tr2 = emitir(IRTN(IR_SUB), tr2, tr1);
1590 tr2 = emitir(IRTN(IR_ADD), tr2, one);
1591 tr = emitir(IRTN(IR_MUL), tr, tr2);
1592 tr = emitir(IRTN(IR_FPMATH), tr, IRFPM_FLOOR);
1593 tr = emitir(IRTN(IR_ADD), tr, tr1);
1594 } else { /* d = floor(d*r1) + 1.0 */
1595 tr = emitir(IRTN(IR_MUL), tr, tr1);
1596 tr = emitir(IRTN(IR_FPMATH), tr, IRFPM_FLOOR);
1597 tr = emitir(IRTN(IR_ADD), tr, one);
1598 }
1599 }
1600 J->base[0] = tr;
1601 UNUSED(rd);
1602}
1603
1604/* -- Bit library fast functions ------------------------------------------ */
1605
1606/* Record unary bit.tobit, bit.bnot, bit.bswap. */
1607static void LJ_FASTCALL recff_bit_unary(jit_State *J, RecordFFData *rd)
1608{
1609 TRef tr = lj_ir_tobit(J, J->base[0]);
1610 J->base[0] = (rd->data == IR_TOBIT) ? tr : emitir(IRTI(rd->data), tr, 0);
1611}
1612
1613/* Record N-ary bit.band, bit.bor, bit.bxor. */
1614static void LJ_FASTCALL recff_bit_nary(jit_State *J, RecordFFData *rd)
1615{
1616 TRef tr = lj_ir_tobit(J, J->base[0]);
1617 uint32_t op = rd->data;
1618 BCReg i;
1619 for (i = 1; J->base[i] != 0; i++)
1620 tr = emitir(IRTI(op), tr, lj_ir_tobit(J, J->base[i]));
1621 J->base[0] = tr;
1622}
1623
1624/* Record bit shifts. */
1625static void LJ_FASTCALL recff_bit_shift(jit_State *J, RecordFFData *rd)
1626{
1627 TRef tr = lj_ir_tobit(J, J->base[0]);
1628 TRef tsh = lj_ir_tobit(J, J->base[1]);
1629 if (!(rd->data < IR_BROL ? LJ_TARGET_MASKSHIFT : LJ_TARGET_MASKROT) &&
1630 !tref_isk(tsh))
1631 tsh = emitir(IRTI(IR_BAND), tsh, lj_ir_kint(J, 31));
1632 J->base[0] = emitir(IRTI(rd->data), tr, tsh);
1633}
1634
1635/* -- String library fast functions --------------------------------------- */
1636
1637static void LJ_FASTCALL recff_string_len(jit_State *J, RecordFFData *rd)
1638{
1639 J->base[0] = emitir(IRTI(IR_FLOAD), lj_ir_tostr(J, J->base[0]), IRFL_STR_LEN);
1640 UNUSED(rd);
1641}
1642
1643/* Handle string.byte (rd->data = 0) and string.sub (rd->data = 1). */
1644static void LJ_FASTCALL recff_string_range(jit_State *J, RecordFFData *rd)
1645{
1646 TRef trstr = lj_ir_tostr(J, J->base[0]);
1647 TRef trlen = emitir(IRTI(IR_FLOAD), trstr, IRFL_STR_LEN);
1648 TRef tr0 = lj_ir_kint(J, 0);
1649 TRef trstart, trend;
1650 GCstr *str = argv2str(J, &rd->argv[0]);
1651 int32_t start, end;
1652 if (rd->data) { /* string.sub(str, start [,end]) */
1653 start = argv2int(J, &rd->argv[1]);
1654 trstart = lj_ir_toint(J, J->base[1]);
1655 trend = J->base[2];
1656 if (tref_isnil(trend)) {
1657 trend = lj_ir_kint(J, -1);
1658 end = -1;
1659 } else {
1660 trend = lj_ir_toint(J, trend);
1661 end = argv2int(J, &rd->argv[2]);
1662 }
1663 } else { /* string.byte(str, [,start [,end]]) */
1664 if (J->base[1]) {
1665 start = argv2int(J, &rd->argv[1]);
1666 trstart = lj_ir_toint(J, J->base[1]);
1667 trend = J->base[2];
1668 if (tref_isnil(trend)) {
1669 trend = trstart;
1670 end = start;
1671 } else {
1672 trend = lj_ir_toint(J, trend);
1673 end = argv2int(J, &rd->argv[2]);
1674 }
1675 } else {
1676 trend = trstart = lj_ir_kint(J, 1);
1677 end = start = 1;
1678 }
1679 }
1680 if (end < 0) {
1681 emitir(IRTGI(IR_LT), trend, tr0);
1682 trend = emitir(IRTI(IR_ADD), emitir(IRTI(IR_ADD), trlen, trend),
1683 lj_ir_kint(J, 1));
1684 end = end+(int32_t)str->len+1;
1685 } else if ((MSize)end <= str->len) {
1686 emitir(IRTGI(IR_ULE), trend, trlen);
1687 } else {
1688 emitir(IRTGI(IR_GT), trend, trlen);
1689 end = (int32_t)str->len;
1690 trend = trlen;
1691 }
1692 if (start < 0) {
1693 emitir(IRTGI(IR_LT), trstart, tr0);
1694 trstart = emitir(IRTI(IR_ADD), trlen, trstart);
1695 start = start+(int32_t)str->len;
1696 emitir(start < 0 ? IRTGI(IR_LT) : IRTGI(IR_GE), trstart, tr0);
1697 if (start < 0) {
1698 trstart = tr0;
1699 start = 0;
1700 }
1701 } else {
1702 if (start == 0) {
1703 emitir(IRTGI(IR_EQ), trstart, tr0);
1704 trstart = tr0;
1705 } else {
1706 trstart = emitir(IRTI(IR_ADD), trstart, lj_ir_kint(J, -1));
1707 emitir(IRTGI(IR_GE), trstart, tr0);
1708 start--;
1709 }
1710 }
1711 if (rd->data) { /* Return string.sub result. */
1712 if (end - start >= 0) {
1713 /* Also handle empty range here, to avoid extra traces. */
1714 TRef trptr, trslen = emitir(IRTI(IR_SUB), trend, trstart);
1715 emitir(IRTGI(IR_GE), trslen, tr0);
1716 trptr = emitir(IRT(IR_STRREF, IRT_PTR), trstr, trstart);
1717 J->base[0] = emitir(IRT(IR_SNEW, IRT_STR), trptr, trslen);
1718 } else { /* Range underflow: return empty string. */
1719 emitir(IRTGI(IR_LT), trend, trstart);
1720 J->base[0] = lj_ir_kstr(J, lj_str_new(J->L, strdata(str), 0));
1721 }
1722 } else { /* Return string.byte result(s). */
1723 ptrdiff_t i, len = end - start;
1724 if (len > 0) {
1725 TRef trslen = emitir(IRTI(IR_SUB), trend, trstart);
1726 emitir(IRTGI(IR_EQ), trslen, lj_ir_kint(J, (int32_t)len));
1727 if (J->baseslot + len > LJ_MAX_JSLOTS)
1728 lj_trace_err_info(J, LJ_TRERR_STACKOV);
1729 rd->nres = len;
1730 for (i = 0; i < len; i++) {
1731 TRef tmp = emitir(IRTI(IR_ADD), trstart, lj_ir_kint(J, (int32_t)i));
1732 tmp = emitir(IRT(IR_STRREF, IRT_PTR), trstr, tmp);
1733 J->base[i] = emitir(IRT(IR_XLOAD, IRT_U8), tmp, IRXLOAD_READONLY);
1734 }
1735 } else { /* Empty range or range underflow: return no results. */
1736 emitir(IRTGI(IR_LE), trend, trstart);
1737 rd->nres = 0;
1738 }
1739 }
1740}
1741
1742/* -- Table library fast functions ---------------------------------------- */
1743
1744static void LJ_FASTCALL recff_table_getn(jit_State *J, RecordFFData *rd)
1745{
1746 if (tref_istab(J->base[0]))
1747 J->base[0] = lj_ir_call(J, IRCALL_lj_tab_len, J->base[0]);
1748 /* else: Interpreter will throw. */
1749 UNUSED(rd);
1750}
1751
1752static void LJ_FASTCALL recff_table_remove(jit_State *J, RecordFFData *rd)
1753{
1754 TRef tab = J->base[0];
1755 rd->nres = 0;
1756 if (tref_istab(tab)) {
1757 if (!J->base[1] || tref_isnil(J->base[1])) { /* Simple pop: t[#t] = nil */
1758 TRef trlen = lj_ir_call(J, IRCALL_lj_tab_len, tab);
1759 GCtab *t = tabV(&rd->argv[0]);
1760 MSize len = lj_tab_len(t);
1761 emitir(IRTGI(len ? IR_NE : IR_EQ), trlen, lj_ir_kint(J, 0));
1762 if (len) {
1763 RecordIndex ix;
1764 ix.tab = tab;
1765 ix.key = trlen;
1766 settabV(J->L, &ix.tabv, t);
1767 setintV(&ix.keyv, len);
1768 ix.idxchain = 0;
1769 if (results_wanted(J) != 0) { /* Specialize load only if needed. */
1770 ix.val = 0;
1771 J->base[0] = rec_idx(J, &ix); /* Load previous value. */
1772 rd->nres = 1;
1773 /* Assumes ix.key/ix.tab is not modified for raw rec_idx(). */
1774 }
1775 ix.val = TREF_NIL;
1776 rec_idx(J, &ix); /* Remove value. */
1777 }
1778 } else { /* Complex case: remove in the middle. */
1779 recff_nyiu(J);
1780 }
1781 } /* else: Interpreter will throw. */
1782}
1783
1784static void LJ_FASTCALL recff_table_insert(jit_State *J, RecordFFData *rd)
1785{
1786 RecordIndex ix;
1787 ix.tab = J->base[0];
1788 ix.val = J->base[1];
1789 rd->nres = 0;
1790 if (tref_istab(ix.tab) && ix.val) {
1791 if (!J->base[2]) { /* Simple push: t[#t+1] = v */
1792 TRef trlen = lj_ir_call(J, IRCALL_lj_tab_len, ix.tab);
1793 GCtab *t = tabV(&rd->argv[0]);
1794 ix.key = emitir(IRTI(IR_ADD), trlen, lj_ir_kint(J, 1));
1795 settabV(J->L, &ix.tabv, t);
1796 setintV(&ix.keyv, lj_tab_len(t) + 1);
1797 ix.idxchain = 0;
1798 rec_idx(J, &ix); /* Set new value. */
1799 } else { /* Complex case: insert in the middle. */
1800 recff_nyiu(J);
1801 }
1802 } /* else: Interpreter will throw. */
1803}
1804
1805/* -- I/O library fast functions ------------------------------------------ */
1806
1807/* Get FILE* for I/O function. Any I/O error aborts recording, so there's
1808** no need to encode the alternate cases for any of the guards.
1809*/
1810static TRef recff_io_fp(jit_State *J, uint32_t id)
1811{
1812 TRef tr, ud, fp;
1813 if (id) { /* io.func() */
1814 tr = lj_ir_kptr(J, &J2G(J)->gcroot[id]);
1815 ud = emitir(IRT(IR_XLOAD, IRT_UDATA), tr, 0);
1816 } else { /* fp:method() */
1817 ud = J->base[0];
1818 if (!tref_isudata(ud))
1819 lj_trace_err(J, LJ_TRERR_BADTYPE);
1820 tr = emitir(IRT(IR_FLOAD, IRT_U8), ud, IRFL_UDATA_UDTYPE);
1821 emitir(IRTGI(IR_EQ), tr, lj_ir_kint(J, UDTYPE_IO_FILE));
1822 }
1823 fp = emitir(IRT(IR_FLOAD, IRT_LIGHTUD), ud, IRFL_UDATA_FILE);
1824 emitir(IRTG(IR_NE, IRT_LIGHTUD), fp, lj_ir_knull(J, IRT_LIGHTUD));
1825 return fp;
1826}
1827
1828static void LJ_FASTCALL recff_io_write(jit_State *J, RecordFFData *rd)
1829{
1830 TRef fp = recff_io_fp(J, rd->data);
1831 TRef zero = lj_ir_kint(J, 0);
1832 TRef one = lj_ir_kint(J, 1);
1833 ptrdiff_t i = rd->data == 0 ? 1 : 0;
1834 for (; J->base[i]; i++) {
1835 TRef str = lj_ir_tostr(J, J->base[i]);
1836 TRef buf = emitir(IRT(IR_STRREF, IRT_PTR), str, zero);
1837 TRef len = emitir(IRTI(IR_FLOAD), str, IRFL_STR_LEN);
1838 if (tref_isk(len) && IR(tref_ref(len))->i == 1) {
1839 TRef tr = emitir(IRT(IR_XLOAD, IRT_U8), buf, IRXLOAD_READONLY);
1840 tr = lj_ir_call(J, IRCALL_fputc, tr, fp);
1841 if (results_wanted(J) != 0) /* Check result only if not ignored. */
1842 emitir(IRTGI(IR_NE), tr, lj_ir_kint(J, -1));
1843 } else {
1844 TRef tr = lj_ir_call(J, IRCALL_fwrite, buf, one, len, fp);
1845 if (results_wanted(J) != 0) /* Check result only if not ignored. */
1846 emitir(IRTGI(IR_EQ), tr, len);
1847 }
1848 }
1849 J->base[0] = TREF_TRUE;
1850}
1851
1852static void LJ_FASTCALL recff_io_flush(jit_State *J, RecordFFData *rd)
1853{
1854 TRef fp = recff_io_fp(J, rd->data);
1855 TRef tr = lj_ir_call(J, IRCALL_fflush, fp);
1856 if (results_wanted(J) != 0) /* Check result only if not ignored. */
1857 emitir(IRTGI(IR_EQ), tr, lj_ir_kint(J, 0));
1858 J->base[0] = TREF_TRUE;
1859}
1860
1861/* -- Record calls to fast functions -------------------------------------- */
1862
1863#include "lj_recdef.h"
1864
1865static uint32_t recdef_lookup(GCfunc *fn)
1866{
1867 if (fn->c.ffid < sizeof(recff_idmap)/sizeof(recff_idmap[0]))
1868 return recff_idmap[fn->c.ffid];
1869 else
1870 return 0;
1871}
1872
1873/* Record entry to a fast function or C function. */
1874static void rec_func_ff(jit_State *J)
1875{
1876 RecordFFData rd;
1877 uint32_t m = recdef_lookup(J->fn);
1878 rd.data = m & 0xff;
1879 rd.nres = 1; /* Default is one result. */
1880 rd.argv = J->L->base;
1881 J->base[J->maxslot] = 0; /* Mark end of arguments. */
1882 (recff_func[m >> 8])(J, &rd); /* Call recff_* handler. */
1883 if (rd.nres >= 0)
1884 rec_ret(J, 0, rd.nres);
1885}
1886
1887/* -- Record calls to Lua functions --------------------------------------- */ 1099/* -- Record calls to Lua functions --------------------------------------- */
1888 1100
1889/* Check unroll limits for calls. */ 1101/* Check unroll limits for calls. */
@@ -2026,7 +1238,7 @@ static void rec_varg(jit_State *J, BCReg dst, ptrdiff_t nresults)
2026 } else if (select_detect(J)) { /* y = select(x, ...) */ 1238 } else if (select_detect(J)) { /* y = select(x, ...) */
2027 TRef tridx = J->base[dst-1]; 1239 TRef tridx = J->base[dst-1];
2028 TRef tr = TREF_NIL; 1240 TRef tr = TREF_NIL;
2029 ptrdiff_t idx = select_mode(J, tridx, &J->L->base[dst-1]); 1241 ptrdiff_t idx = lj_ffrecord_select_mode(J, tridx, &J->L->base[dst-1]);
2030 if (idx < 0) goto nyivarg; 1242 if (idx < 0) goto nyivarg;
2031 if (idx != 0 && !tref_isinteger(tridx)) 1243 if (idx != 0 && !tref_isinteger(tridx))
2032 tridx = emitir(IRTGI(IR_TOINT), tridx, IRTOINT_INDEX); 1244 tridx = emitir(IRTGI(IR_TOINT), tridx, IRTOINT_INDEX);
@@ -2231,7 +1443,7 @@ void lj_record_ins(jit_State *J)
2231 if (!(tref_isk2(ra, rc) && !(tref_istab(ra) || tref_isudata(ra)))) { 1443 if (!(tref_isk2(ra, rc) && !(tref_istab(ra) || tref_isudata(ra)))) {
2232 int diff; 1444 int diff;
2233 rec_comp_prep(J); 1445 rec_comp_prep(J);
2234 diff = rec_objcmp(J, ra, rc, rav, rcv); 1446 diff = lj_record_objcmp(J, ra, rc, rav, rcv);
2235 if (diff == 1 && (tref_istab(ra) || tref_isudata(ra))) { 1447 if (diff == 1 && (tref_istab(ra) || tref_isudata(ra))) {
2236 /* Only check __eq if different, but the same type (table or udata). */ 1448 /* Only check __eq if different, but the same type (table or udata). */
2237 rec_mm_equal(J, &ix, (int)op); 1449 rec_mm_equal(J, &ix, (int)op);
@@ -2354,7 +1566,7 @@ void lj_record_ins(jit_State *J)
2354 settabV(J->L, &ix.tabv, tabref(J->fn->l.env)); 1566 settabV(J->L, &ix.tabv, tabref(J->fn->l.env));
2355 ix.tab = emitir(IRT(IR_FLOAD, IRT_TAB), getcurrf(J), IRFL_FUNC_ENV); 1567 ix.tab = emitir(IRT(IR_FLOAD, IRT_TAB), getcurrf(J), IRFL_FUNC_ENV);
2356 ix.idxchain = LJ_MAX_IDXCHAIN; 1568 ix.idxchain = LJ_MAX_IDXCHAIN;
2357 rc = rec_idx(J, &ix); 1569 rc = lj_record_idx(J, &ix);
2358 break; 1570 break;
2359 1571
2360 case BC_TGETB: case BC_TSETB: 1572 case BC_TGETB: case BC_TSETB:
@@ -2363,7 +1575,7 @@ void lj_record_ins(jit_State *J)
2363 /* fallthrough */ 1575 /* fallthrough */
2364 case BC_TGETV: case BC_TGETS: case BC_TSETV: case BC_TSETS: 1576 case BC_TGETV: case BC_TGETS: case BC_TSETV: case BC_TSETS:
2365 ix.idxchain = LJ_MAX_IDXCHAIN; 1577 ix.idxchain = LJ_MAX_IDXCHAIN;
2366 rc = rec_idx(J, &ix); 1578 rc = lj_record_idx(J, &ix);
2367 break; 1579 break;
2368 1580
2369 case BC_TNEW: 1581 case BC_TNEW:
@@ -2380,13 +1592,13 @@ void lj_record_ins(jit_State *J)
2380 J->base[ra] = getslot(J, ra-3); 1592 J->base[ra] = getslot(J, ra-3);
2381 J->base[ra+1] = getslot(J, ra-2); 1593 J->base[ra+1] = getslot(J, ra-2);
2382 J->base[ra+2] = getslot(J, ra-1); 1594 J->base[ra+2] = getslot(J, ra-1);
2383 { /* Have to do the actual copy now because rec_call needs the values. */ 1595 { /* Do the actual copy now because lj_record_call needs the values. */
2384 TValue *b = &J->L->base[ra]; 1596 TValue *b = &J->L->base[ra];
2385 copyTV(J->L, b, b-3); 1597 copyTV(J->L, b, b-3);
2386 copyTV(J->L, b+1, b-2); 1598 copyTV(J->L, b+1, b-2);
2387 copyTV(J->L, b+2, b-1); 1599 copyTV(J->L, b+2, b-1);
2388 } 1600 }
2389 rec_call(J, ra, (ptrdiff_t)rc-1); 1601 lj_record_call(J, ra, (ptrdiff_t)rc-1);
2390 break; 1602 break;
2391 1603
2392 /* L->top is set to L->base+ra+rc+NARGS-1+1. See lj_dispatch_ins(). */ 1604 /* L->top is set to L->base+ra+rc+NARGS-1+1. See lj_dispatch_ins(). */
@@ -2394,14 +1606,14 @@ void lj_record_ins(jit_State *J)
2394 rc = (BCReg)(J->L->top - J->L->base) - ra; 1606 rc = (BCReg)(J->L->top - J->L->base) - ra;
2395 /* fallthrough */ 1607 /* fallthrough */
2396 case BC_CALL: 1608 case BC_CALL:
2397 rec_call(J, ra, (ptrdiff_t)rc-1); 1609 lj_record_call(J, ra, (ptrdiff_t)rc-1);
2398 break; 1610 break;
2399 1611
2400 case BC_CALLMT: 1612 case BC_CALLMT:
2401 rc = (BCReg)(J->L->top - J->L->base) - ra; 1613 rc = (BCReg)(J->L->top - J->L->base) - ra;
2402 /* fallthrough */ 1614 /* fallthrough */
2403 case BC_CALLT: 1615 case BC_CALLT:
2404 rec_tailcall(J, ra, (ptrdiff_t)rc-1); 1616 lj_record_tailcall(J, ra, (ptrdiff_t)rc-1);
2405 break; 1617 break;
2406 1618
2407 case BC_VARG: 1619 case BC_VARG:
@@ -2415,7 +1627,7 @@ void lj_record_ins(jit_State *J)
2415 rc = (BCReg)(J->L->top - J->L->base) - ra + 1; 1627 rc = (BCReg)(J->L->top - J->L->base) - ra + 1;
2416 /* fallthrough */ 1628 /* fallthrough */
2417 case BC_RET: case BC_RET0: case BC_RET1: 1629 case BC_RET: case BC_RET0: case BC_RET1:
2418 rec_ret(J, ra, (ptrdiff_t)rc-1); 1630 lj_record_ret(J, ra, (ptrdiff_t)rc-1);
2419 break; 1631 break;
2420 1632
2421 /* -- Loops and branches ------------------------------------------------ */ 1633 /* -- Loops and branches ------------------------------------------------ */
@@ -2483,12 +1695,12 @@ void lj_record_ins(jit_State *J)
2483 1695
2484 case BC_FUNCC: 1696 case BC_FUNCC:
2485 case BC_FUNCCW: 1697 case BC_FUNCCW:
2486 rec_func_ff(J); 1698 lj_ffrecord_func(J);
2487 break; 1699 break;
2488 1700
2489 default: 1701 default:
2490 if (op >= BC__MAX) { 1702 if (op >= BC__MAX) {
2491 rec_func_ff(J); 1703 lj_ffrecord_func(J);
2492 break; 1704 break;
2493 } 1705 }
2494 /* fallthrough */ 1706 /* fallthrough */