diff options
author | Mike Pall <mike> | 2010-12-05 17:12:34 +0100 |
---|---|---|
committer | Mike Pall <mike> | 2010-12-05 17:12:34 +0100 |
commit | e7f8cc964e036147f0303c2653a77dfe24473dcc (patch) | |
tree | 04710210a3280557a0528208440ba4b45341bebb /src/lj_record.c | |
parent | 559545eb6dc098594f957b09217ac3507b56eb3c (diff) | |
download | luajit-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.c | 864 |
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. */ | ||
41 | typedef 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. */ | ||
57 | static int rec_mm_lookup(jit_State *J, RecordIndex *ix, MMS mm); | ||
58 | static 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 | */ |
185 | static int rec_objcmp(jit_State *J, TRef a, TRef b, cTValue *av, cTValue *bv) | 163 | int 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. */ |
511 | static void rec_call(jit_State *J, BCReg func, ptrdiff_t nargs) | 489 | void 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. */ |
521 | static void rec_tailcall(jit_State *J, BCReg func, ptrdiff_t nargs) | 499 | void 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. */ |
564 | static void rec_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) | 542 | void 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. */ |
675 | static int rec_mm_lookup(jit_State *J, RecordIndex *ix, MMS mm) | 653 | int 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) | |||
734 | ok: | 712 | ok: |
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. */ |
946 | static TRef rec_idx(jit_State *J, RecordIndex *ix) | 924 | TRef 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. */ | ||
1146 | typedef 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. */ | ||
1153 | typedef void (LJ_FASTCALL *RecordFunc)(jit_State *J, RecordFFData *rd); | ||
1154 | |||
1155 | /* Get runtime value of int argument. */ | ||
1156 | static 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. */ | ||
1164 | static 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. */ | ||
1179 | static 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. */ | ||
1189 | LJ_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). */ | ||
1196 | static 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). */ | ||
1204 | static 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 | |||
1213 | static 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 | |||
1219 | static 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 | |||
1227 | static 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 | |||
1241 | static 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 | |||
1261 | static 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 | |||
1273 | static 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 | |||
1287 | static 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. */ | ||
1298 | static 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 | |||
1316 | static 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 | |||
1339 | static 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 | |||
1362 | static 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 | |||
1370 | static 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 | |||
1394 | static 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 | |||
1411 | static 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 | |||
1428 | static 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 | |||
1444 | static 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 | |||
1452 | static 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 | |||
1460 | static 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 | |||
1485 | static 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. */ | ||
1493 | static 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. */ | ||
1501 | static 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. */ | ||
1507 | static 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. */ | ||
1514 | static 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 | |||
1528 | static 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 | |||
1534 | static 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 | |||
1550 | static 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 | |||
1558 | static 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 | |||
1567 | static 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 | |||
1577 | static 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. */ | ||
1607 | static 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. */ | ||
1614 | static 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. */ | ||
1625 | static 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 | |||
1637 | static 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). */ | ||
1644 | static 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 | |||
1744 | static 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 | |||
1752 | static 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 | |||
1784 | static 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 | */ | ||
1810 | static 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 | |||
1828 | static 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 | |||
1852 | static 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 | |||
1865 | static 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. */ | ||
1874 | static 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 */ |