diff options
-rw-r--r-- | src/jit/dump.lua | 1 | ||||
-rw-r--r-- | src/lj_asm.c | 19 | ||||
-rw-r--r-- | src/lj_asm_arm.h | 69 | ||||
-rw-r--r-- | src/lj_asm_arm64.h | 28 | ||||
-rw-r--r-- | src/lj_asm_mips.h | 82 | ||||
-rw-r--r-- | src/lj_asm_ppc.h | 71 | ||||
-rw-r--r-- | src/lj_asm_x86.h | 79 | ||||
-rw-r--r-- | src/lj_ir.h | 6 | ||||
-rw-r--r-- | src/lj_opt_fold.c | 1 | ||||
-rw-r--r-- | src/lj_opt_split.c | 2 | ||||
-rw-r--r-- | src/lj_record.c | 15 | ||||
-rw-r--r-- | src/lj_record.h | 1 |
12 files changed, 249 insertions, 125 deletions
diff --git a/src/jit/dump.lua b/src/jit/dump.lua index 34ced76d..4806f4c4 100644 --- a/src/jit/dump.lua +++ b/src/jit/dump.lua | |||
@@ -287,6 +287,7 @@ local litname = { | |||
287 | ["FLOAD "] = vmdef.irfield, | 287 | ["FLOAD "] = vmdef.irfield, |
288 | ["FREF "] = vmdef.irfield, | 288 | ["FREF "] = vmdef.irfield, |
289 | ["FPMATH"] = vmdef.irfpm, | 289 | ["FPMATH"] = vmdef.irfpm, |
290 | ["TMPREF"] = { [0] = "", "IN", "OUT", "INOUT", "", "", "OUT2", "INOUT2" }, | ||
290 | ["BUFHDR"] = { [0] = "RESET", "APPEND" }, | 291 | ["BUFHDR"] = { [0] = "RESET", "APPEND" }, |
291 | ["TOSTR "] = { [0] = "INT", "NUM", "CHAR" }, | 292 | ["TOSTR "] = { [0] = "INT", "NUM", "CHAR" }, |
292 | } | 293 | } |
diff --git a/src/lj_asm.c b/src/lj_asm.c index b613e6d3..ebcff43c 100644 --- a/src/lj_asm.c +++ b/src/lj_asm.c | |||
@@ -1144,7 +1144,7 @@ static void asm_gcstep(ASMState *as, IRIns *ir) | |||
1144 | 1144 | ||
1145 | /* -- Buffer operations --------------------------------------------------- */ | 1145 | /* -- Buffer operations --------------------------------------------------- */ |
1146 | 1146 | ||
1147 | static void asm_tvptr(ASMState *as, Reg dest, IRRef ref); | 1147 | static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode); |
1148 | 1148 | ||
1149 | static void asm_bufhdr(ASMState *as, IRIns *ir) | 1149 | static void asm_bufhdr(ASMState *as, IRIns *ir) |
1150 | { | 1150 | { |
@@ -1218,7 +1218,7 @@ static void asm_bufput(ASMState *as, IRIns *ir) | |||
1218 | if (args[1] == ASMREF_TMP1) { | 1218 | if (args[1] == ASMREF_TMP1) { |
1219 | Reg tmp = ra_releasetmp(as, ASMREF_TMP1); | 1219 | Reg tmp = ra_releasetmp(as, ASMREF_TMP1); |
1220 | if (kchar == -129) | 1220 | if (kchar == -129) |
1221 | asm_tvptr(as, tmp, irs->op1); | 1221 | asm_tvptr(as, tmp, irs->op1, IRTMPREF_IN1); |
1222 | else | 1222 | else |
1223 | ra_allockreg(as, kchar, tmp); | 1223 | ra_allockreg(as, kchar, tmp); |
1224 | } | 1224 | } |
@@ -1256,7 +1256,7 @@ static void asm_tostr(ASMState *as, IRIns *ir) | |||
1256 | asm_setupresult(as, ir, ci); /* GCstr * */ | 1256 | asm_setupresult(as, ir, ci); /* GCstr * */ |
1257 | asm_gencall(as, ci, args); | 1257 | asm_gencall(as, ci, args); |
1258 | if (ir->op2 == IRTOSTR_NUM) | 1258 | if (ir->op2 == IRTOSTR_NUM) |
1259 | asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op1); | 1259 | asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op1, IRTMPREF_IN1); |
1260 | } | 1260 | } |
1261 | 1261 | ||
1262 | #if LJ_32 && LJ_HASFFI && !LJ_SOFTFP && !LJ_TARGET_X86 | 1262 | #if LJ_32 && LJ_HASFFI && !LJ_SOFTFP && !LJ_TARGET_X86 |
@@ -1303,7 +1303,13 @@ static void asm_newref(ASMState *as, IRIns *ir) | |||
1303 | args[2] = ASMREF_TMP1; /* cTValue *key */ | 1303 | args[2] = ASMREF_TMP1; /* cTValue *key */ |
1304 | asm_setupresult(as, ir, ci); /* TValue * */ | 1304 | asm_setupresult(as, ir, ci); /* TValue * */ |
1305 | asm_gencall(as, ci, args); | 1305 | asm_gencall(as, ci, args); |
1306 | asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op2); | 1306 | asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op2, IRTMPREF_IN1); |
1307 | } | ||
1308 | |||
1309 | static void asm_tmpref(ASMState *as, IRIns *ir) | ||
1310 | { | ||
1311 | Reg r = ra_dest(as, ir, RSET_GPR); | ||
1312 | asm_tvptr(as, r, ir->op1, ir->op2); | ||
1307 | } | 1313 | } |
1308 | 1314 | ||
1309 | static void asm_lref(ASMState *as, IRIns *ir) | 1315 | static void asm_lref(ASMState *as, IRIns *ir) |
@@ -1785,6 +1791,7 @@ static void asm_ir(ASMState *as, IRIns *ir) | |||
1785 | case IR_NEWREF: asm_newref(as, ir); break; | 1791 | case IR_NEWREF: asm_newref(as, ir); break; |
1786 | case IR_UREFO: case IR_UREFC: asm_uref(as, ir); break; | 1792 | case IR_UREFO: case IR_UREFC: asm_uref(as, ir); break; |
1787 | case IR_FREF: asm_fref(as, ir); break; | 1793 | case IR_FREF: asm_fref(as, ir); break; |
1794 | case IR_TMPREF: asm_tmpref(as, ir); break; | ||
1788 | case IR_STRREF: asm_strref(as, ir); break; | 1795 | case IR_STRREF: asm_strref(as, ir); break; |
1789 | case IR_LREF: asm_lref(as, ir); break; | 1796 | case IR_LREF: asm_lref(as, ir); break; |
1790 | 1797 | ||
@@ -2192,6 +2199,10 @@ static void asm_setup_regsp(ASMState *as) | |||
2192 | ir->prev = (uint16_t)REGSP_HINT((rload & 15)); | 2199 | ir->prev = (uint16_t)REGSP_HINT((rload & 15)); |
2193 | rload = lj_ror(rload, 4); | 2200 | rload = lj_ror(rload, 4); |
2194 | continue; | 2201 | continue; |
2202 | case IR_TMPREF: | ||
2203 | if ((ir->op2 & IRTMPREF_OUT2) && as->evenspill < 4) | ||
2204 | as->evenspill = 4; /* TMPREF OUT2 needs two TValues on the stack. */ | ||
2205 | break; | ||
2195 | #endif | 2206 | #endif |
2196 | case IR_CALLXS: { | 2207 | case IR_CALLXS: { |
2197 | CCallInfo ci; | 2208 | CCallInfo ci; |
diff --git a/src/lj_asm_arm.h b/src/lj_asm_arm.h index c93c99c9..208c3203 100644 --- a/src/lj_asm_arm.h +++ b/src/lj_asm_arm.h | |||
@@ -185,6 +185,9 @@ static Reg asm_fuseahuref(ASMState *as, IRRef ref, int32_t *ofsp, RegSet allow, | |||
185 | *ofsp = (ofs & 255); /* Mask out less bits to allow LDRD. */ | 185 | *ofsp = (ofs & 255); /* Mask out less bits to allow LDRD. */ |
186 | return ra_allock(as, (ofs & ~255), allow); | 186 | return ra_allock(as, (ofs & ~255), allow); |
187 | } | 187 | } |
188 | } else if (ir->o == IR_TMPREF) { | ||
189 | *ofsp = 0; | ||
190 | return RID_SP; | ||
188 | } | 191 | } |
189 | } | 192 | } |
190 | *ofsp = 0; | 193 | *ofsp = 0; |
@@ -666,35 +669,55 @@ static void asm_strto(ASMState *as, IRIns *ir) | |||
666 | /* -- Memory references --------------------------------------------------- */ | 669 | /* -- Memory references --------------------------------------------------- */ |
667 | 670 | ||
668 | /* Get pointer to TValue. */ | 671 | /* Get pointer to TValue. */ |
669 | static void asm_tvptr(ASMState *as, Reg dest, IRRef ref) | 672 | static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode) |
670 | { | 673 | { |
671 | IRIns *ir = IR(ref); | 674 | if ((mode & IRTMPREF_IN1)) { |
672 | if (irt_isnum(ir->t)) { | 675 | IRIns *ir = IR(ref); |
673 | if (irref_isk(ref)) { | 676 | if (irt_isnum(ir->t)) { |
674 | /* Use the number constant itself as a TValue. */ | 677 | if ((mode & IRTMPREF_OUT1)) { |
675 | ra_allockreg(as, i32ptr(ir_knum(ir)), dest); | 678 | #if LJ_SOFTFP |
676 | } else { | 679 | lj_assertA(irref_isk(ref), "unsplit FP op"); |
680 | emit_dm(as, ARMI_MOV, dest, RID_SP); | ||
681 | emit_lso(as, ARMI_STR, | ||
682 | ra_allock(as, (int32_t)ir_knum(ir)->u32.lo, RSET_GPR), | ||
683 | RID_SP, 0); | ||
684 | emit_lso(as, ARMI_STR, | ||
685 | ra_allock(as, (int32_t)ir_knum(ir)->u32.hi, RSET_GPR), | ||
686 | RID_SP, 4); | ||
687 | #else | ||
688 | Reg src = ra_alloc1(as, ref, RSET_FPR); | ||
689 | emit_dm(as, ARMI_MOV, dest, RID_SP); | ||
690 | emit_vlso(as, ARMI_VSTR_D, src, RID_SP, 0); | ||
691 | #endif | ||
692 | } else if (irref_isk(ref)) { | ||
693 | /* Use the number constant itself as a TValue. */ | ||
694 | ra_allockreg(as, i32ptr(ir_knum(ir)), dest); | ||
695 | } else { | ||
677 | #if LJ_SOFTFP | 696 | #if LJ_SOFTFP |
678 | lj_assertA(0, "unsplit FP op"); | 697 | lj_assertA(0, "unsplit FP op"); |
679 | #else | 698 | #else |
680 | /* Otherwise force a spill and use the spill slot. */ | 699 | /* Otherwise force a spill and use the spill slot. */ |
681 | emit_opk(as, ARMI_ADD, dest, RID_SP, ra_spill(as, ir), RSET_GPR); | 700 | emit_opk(as, ARMI_ADD, dest, RID_SP, ra_spill(as, ir), RSET_GPR); |
682 | #endif | 701 | #endif |
702 | } | ||
703 | } else { | ||
704 | /* Otherwise use [sp] and [sp+4] to hold the TValue. | ||
705 | ** This assumes the following call has max. 4 args. | ||
706 | */ | ||
707 | Reg type; | ||
708 | emit_dm(as, ARMI_MOV, dest, RID_SP); | ||
709 | if (!irt_ispri(ir->t)) { | ||
710 | Reg src = ra_alloc1(as, ref, RSET_GPR); | ||
711 | emit_lso(as, ARMI_STR, src, RID_SP, 0); | ||
712 | } | ||
713 | if (LJ_SOFTFP && (ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t)) | ||
714 | type = ra_alloc1(as, ref+1, RSET_GPR); | ||
715 | else | ||
716 | type = ra_allock(as, irt_toitype(ir->t), RSET_GPR); | ||
717 | emit_lso(as, ARMI_STR, type, RID_SP, 4); | ||
683 | } | 718 | } |
684 | } else { | 719 | } else { |
685 | /* Otherwise use [sp] and [sp+4] to hold the TValue. */ | ||
686 | RegSet allow = rset_exclude(RSET_GPR, dest); | ||
687 | Reg type; | ||
688 | emit_dm(as, ARMI_MOV, dest, RID_SP); | 720 | emit_dm(as, ARMI_MOV, dest, RID_SP); |
689 | if (!irt_ispri(ir->t)) { | ||
690 | Reg src = ra_alloc1(as, ref, allow); | ||
691 | emit_lso(as, ARMI_STR, src, RID_SP, 0); | ||
692 | } | ||
693 | if (LJ_SOFTFP && (ir+1)->o == IR_HIOP) | ||
694 | type = ra_alloc1(as, ref+1, allow); | ||
695 | else | ||
696 | type = ra_allock(as, irt_toitype(ir->t), allow); | ||
697 | emit_lso(as, ARMI_STR, type, RID_SP, 4); | ||
698 | } | 721 | } |
699 | } | 722 | } |
700 | 723 | ||
@@ -1909,7 +1932,7 @@ static void asm_hiop(ASMState *as, IRIns *ir) | |||
1909 | ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */ | 1932 | ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */ |
1910 | break; | 1933 | break; |
1911 | #if LJ_SOFTFP | 1934 | #if LJ_SOFTFP |
1912 | case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR: | 1935 | case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR: case IR_TMPREF: |
1913 | #endif | 1936 | #endif |
1914 | case IR_CNEWI: | 1937 | case IR_CNEWI: |
1915 | /* Nothing to do here. Handled by lo op itself. */ | 1938 | /* Nothing to do here. Handled by lo op itself. */ |
diff --git a/src/lj_asm_arm64.h b/src/lj_asm_arm64.h index c9ba7b7b..5bd4e0d5 100644 --- a/src/lj_asm_arm64.h +++ b/src/lj_asm_arm64.h | |||
@@ -198,6 +198,9 @@ static Reg asm_fuseahuref(ASMState *as, IRRef ref, int32_t *ofsp, RegSet allow, | |||
198 | return RID_GL; | 198 | return RID_GL; |
199 | } | 199 | } |
200 | } | 200 | } |
201 | } else if (ir->o == IR_TMPREF) { | ||
202 | *ofsp = (int32_t)glofs(as, &J2G(as->J)->tmptv); | ||
203 | return RID_GL; | ||
201 | } | 204 | } |
202 | } | 205 | } |
203 | *ofsp = 0; | 206 | *ofsp = 0; |
@@ -675,22 +678,23 @@ static void asm_tvstore64(ASMState *as, Reg base, int32_t ofs, IRRef ref) | |||
675 | } | 678 | } |
676 | 679 | ||
677 | /* Get pointer to TValue. */ | 680 | /* Get pointer to TValue. */ |
678 | static void asm_tvptr(ASMState *as, Reg dest, IRRef ref) | 681 | static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode) |
679 | { | 682 | { |
680 | IRIns *ir = IR(ref); | 683 | if ((mode & IRTMPREF_IN1)) { |
681 | if (irt_isnum(ir->t)) { | 684 | IRIns *ir = IR(ref); |
682 | if (irref_isk(ref)) { | 685 | if (irt_isnum(ir->t)) { |
683 | /* Use the number constant itself as a TValue. */ | 686 | if (irref_isk(ref) && !(mode & IRTMPREF_OUT1)) { |
684 | ra_allockreg(as, i64ptr(ir_knum(ir)), dest); | 687 | /* Use the number constant itself as a TValue. */ |
688 | ra_allockreg(as, i64ptr(ir_knum(ir)), dest); | ||
689 | return; | ||
690 | } | ||
691 | emit_lso(as, A64I_STRd, (ra_alloc1(as, ref, RSET_FPR) & 31), dest, 0); | ||
685 | } else { | 692 | } else { |
686 | /* Otherwise force a spill and use the spill slot. */ | 693 | asm_tvstore64(as, dest, 0, ref); |
687 | emit_opk(as, A64I_ADDx, dest, RID_SP, ra_spill(as, ir), RSET_GPR); | ||
688 | } | 694 | } |
689 | } else { | ||
690 | /* Otherwise use g->tmptv to hold the TValue. */ | ||
691 | asm_tvstore64(as, dest, 0, ref); | ||
692 | emit_dn(as, A64I_ADDx^emit_isk12(glofs(as, &J2G(as->J)->tmptv)), dest, RID_GL); | ||
693 | } | 695 | } |
696 | /* g->tmptv holds the TValue(s). */ | ||
697 | emit_dn(as, A64I_ADDx^emit_isk12(glofs(as, &J2G(as->J)->tmptv)), dest, RID_GL); | ||
694 | } | 698 | } |
695 | 699 | ||
696 | static void asm_aref(ASMState *as, IRIns *ir) | 700 | static void asm_aref(ASMState *as, IRIns *ir) |
diff --git a/src/lj_asm_mips.h b/src/lj_asm_mips.h index f775d08b..058df8be 100644 --- a/src/lj_asm_mips.h +++ b/src/lj_asm_mips.h | |||
@@ -193,6 +193,9 @@ static Reg asm_fuseahuref(ASMState *as, IRRef ref, int32_t *ofsp, RegSet allow) | |||
193 | return ra_allock(as, ofs-(int16_t)ofs, allow); | 193 | return ra_allock(as, ofs-(int16_t)ofs, allow); |
194 | } | 194 | } |
195 | } | 195 | } |
196 | } else if (ir->o == IR_TMPREF) { | ||
197 | *ofsp = (int32_t)(offsetof(global_State, tmptv)-32768); | ||
198 | return RID_JGL; | ||
196 | } | 199 | } |
197 | } | 200 | } |
198 | *ofsp = 0; | 201 | *ofsp = 0; |
@@ -839,34 +842,63 @@ static void asm_tvstore64(ASMState *as, Reg base, int32_t ofs, IRRef ref) | |||
839 | #endif | 842 | #endif |
840 | 843 | ||
841 | /* Get pointer to TValue. */ | 844 | /* Get pointer to TValue. */ |
842 | static void asm_tvptr(ASMState *as, Reg dest, IRRef ref) | 845 | static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode) |
843 | { | 846 | { |
844 | IRIns *ir = IR(ref); | 847 | int32_t tmpofs = (int32_t)(offsetof(global_State, tmptv)-32768); |
845 | if (irt_isnum(ir->t)) { | 848 | if ((mode & IRTMPREF_IN1)) { |
846 | if (irref_isk(ref)) /* Use the number constant itself as a TValue. */ | 849 | IRIns *ir = IR(ref); |
847 | ra_allockreg(as, igcptr(ir_knum(ir)), dest); | 850 | if (irt_isnum(ir->t)) { |
848 | else /* Otherwise force a spill and use the spill slot. */ | 851 | if ((mode & IRTMPREF_OUT1)) { |
849 | emit_tsi(as, MIPSI_AADDIU, dest, RID_SP, ra_spill(as, ir)); | 852 | #if LJ_SOFTFP |
850 | } else { | 853 | emit_tsi(as, MIPSI_AADDIU, dest, RID_JGL, tmpofs); |
851 | /* Otherwise use g->tmptv to hold the TValue. */ | 854 | #if LJ_64 |
855 | emit_setgl(as, ra_alloc1(as, ref, RSET_GPR), tmptv.u64); | ||
856 | #else | ||
857 | lj_assertA(irref_isk(ref), "unsplit FP op"); | ||
858 | emit_setgl(as, | ||
859 | ra_allock(as, (int32_t)ir_knum(ir)->u32.lo, RSET_GPR), | ||
860 | tmptv.u32.lo); | ||
861 | emit_setgl(as, | ||
862 | ra_allock(as, (int32_t)ir_knum(ir)->u32.hi, RSET_GPR), | ||
863 | tmptv.u32.hi); | ||
864 | #endif | ||
865 | #else | ||
866 | Reg src = ra_alloc1(as, ref, RSET_FPR); | ||
867 | emit_tsi(as, MIPSI_AADDIU, dest, RID_JGL, tmpofs); | ||
868 | emit_tsi(as, MIPSI_SDC1, (src & 31), RID_JGL, tmpofs); | ||
869 | #endif | ||
870 | } else if (irref_isk(ref)) { | ||
871 | /* Use the number constant itself as a TValue. */ | ||
872 | ra_allockreg(as, igcptr(ir_knum(ir)), dest); | ||
873 | } else { | ||
874 | #if LJ_SOFTFP | ||
875 | lj_assertA(0, "unsplit FP op"); | ||
876 | #else | ||
877 | /* Otherwise force a spill and use the spill slot. */ | ||
878 | emit_tsi(as, MIPSI_AADDIU, dest, RID_SP, ra_spill(as, ir)); | ||
879 | #endif | ||
880 | } | ||
881 | } else { | ||
882 | /* Otherwise use g->tmptv to hold the TValue. */ | ||
852 | #if LJ_32 | 883 | #if LJ_32 |
853 | RegSet allow = rset_exclude(RSET_GPR, dest); | 884 | Reg type; |
854 | Reg type; | 885 | emit_tsi(as, MIPSI_ADDIU, dest, RID_JGL, tmpofs); |
855 | emit_tsi(as, MIPSI_ADDIU, dest, RID_JGL, (int32_t)(offsetof(global_State, tmptv)-32768)); | 886 | if (!irt_ispri(ir->t)) { |
856 | if (!irt_ispri(ir->t)) { | 887 | Reg src = ra_alloc1(as, ref, RSET_GPR); |
857 | Reg src = ra_alloc1(as, ref, allow); | 888 | emit_setgl(as, src, tmptv.gcr); |
858 | emit_setgl(as, src, tmptv.gcr); | 889 | } |
859 | } | 890 | if (LJ_SOFTFP && (ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t)) |
860 | if (LJ_SOFTFP && (ir+1)->o == IR_HIOP) | 891 | type = ra_alloc1(as, ref+1, RSET_GPR); |
861 | type = ra_alloc1(as, ref+1, allow); | 892 | else |
862 | else | 893 | type = ra_allock(as, (int32_t)irt_toitype(ir->t), RSET_GPR); |
863 | type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow); | 894 | emit_setgl(as, type, tmptv.it); |
864 | emit_setgl(as, type, tmptv.it); | ||
865 | #else | 895 | #else |
866 | asm_tvstore64(as, dest, 0, ref); | 896 | asm_tvstore64(as, dest, 0, ref); |
867 | emit_tsi(as, MIPSI_DADDIU, dest, RID_JGL, | 897 | emit_tsi(as, MIPSI_DADDIU, dest, RID_JGL, tmpofs); |
868 | (int32_t)(offsetof(global_State, tmptv)-32768)); | ||
869 | #endif | 898 | #endif |
899 | } | ||
900 | } else { | ||
901 | emit_tsi(as, MIPSI_AADDIU, dest, RID_JGL, tmpofs); | ||
870 | } | 902 | } |
871 | } | 903 | } |
872 | 904 | ||
@@ -2415,7 +2447,7 @@ static void asm_hiop(ASMState *as, IRIns *ir) | |||
2415 | ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */ | 2447 | ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */ |
2416 | break; | 2448 | break; |
2417 | #if LJ_SOFTFP | 2449 | #if LJ_SOFTFP |
2418 | case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR: | 2450 | case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR: case IR_TMPREF: |
2419 | #endif | 2451 | #endif |
2420 | case IR_CNEWI: | 2452 | case IR_CNEWI: |
2421 | /* Nothing to do here. Handled by lo op itself. */ | 2453 | /* Nothing to do here. Handled by lo op itself. */ |
diff --git a/src/lj_asm_ppc.h b/src/lj_asm_ppc.h index 88869d9d..caef8fd7 100644 --- a/src/lj_asm_ppc.h +++ b/src/lj_asm_ppc.h | |||
@@ -156,6 +156,9 @@ static Reg asm_fuseahuref(ASMState *as, IRRef ref, int32_t *ofsp, RegSet allow) | |||
156 | return ra_allock(as, ofs-(int16_t)ofs, allow); | 156 | return ra_allock(as, ofs-(int16_t)ofs, allow); |
157 | } | 157 | } |
158 | } | 158 | } |
159 | } else if (ir->o == IR_TMPREF) { | ||
160 | *ofsp = (int32_t)(offsetof(global_State, tmptv)-32768); | ||
161 | return RID_JGL; | ||
159 | } | 162 | } |
160 | } | 163 | } |
161 | *ofsp = 0; | 164 | *ofsp = 0; |
@@ -567,28 +570,54 @@ static void asm_strto(ASMState *as, IRIns *ir) | |||
567 | /* -- Memory references --------------------------------------------------- */ | 570 | /* -- Memory references --------------------------------------------------- */ |
568 | 571 | ||
569 | /* Get pointer to TValue. */ | 572 | /* Get pointer to TValue. */ |
570 | static void asm_tvptr(ASMState *as, Reg dest, IRRef ref) | 573 | static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode) |
571 | { | 574 | { |
572 | IRIns *ir = IR(ref); | 575 | int32_t tmpofs = (int32_t)(offsetof(global_State, tmptv)-32768); |
573 | if (irt_isnum(ir->t)) { | 576 | if ((mode & IRTMPREF_IN1)) { |
574 | if (irref_isk(ref)) /* Use the number constant itself as a TValue. */ | 577 | IRIns *ir = IR(ref); |
575 | ra_allockreg(as, i32ptr(ir_knum(ir)), dest); | 578 | if (irt_isnum(ir->t)) { |
576 | else /* Otherwise force a spill and use the spill slot. */ | 579 | if ((mode & IRTMPREF_OUT1)) { |
577 | emit_tai(as, PPCI_ADDI, dest, RID_SP, ra_spill(as, ir)); | 580 | #if LJ_SOFTFP |
578 | } else { | 581 | lj_assertA(irref_isk(ref), "unsplit FP op"); |
579 | /* Otherwise use g->tmptv to hold the TValue. */ | 582 | emit_tai(as, PPCI_ADDI, dest, RID_JGL, tmpofs); |
580 | RegSet allow = rset_exclude(RSET_GPR, dest); | 583 | emit_setgl(as, |
581 | Reg type; | 584 | ra_allock(as, (int32_t)ir_knum(ir)->u32.lo, RSET_GPR), |
582 | emit_tai(as, PPCI_ADDI, dest, RID_JGL, (int32_t)offsetof(global_State, tmptv)-32768); | 585 | tmptv.u32.lo); |
583 | if (!irt_ispri(ir->t)) { | 586 | emit_setgl(as, |
584 | Reg src = ra_alloc1(as, ref, allow); | 587 | ra_allock(as, (int32_t)ir_knum(ir)->u32.hi, RSET_GPR), |
585 | emit_setgl(as, src, tmptv.gcr); | 588 | tmptv.u32.hi); |
589 | #else | ||
590 | Reg src = ra_alloc1(as, ref, RSET_FPR); | ||
591 | emit_tai(as, PPCI_ADDI, dest, RID_JGL, tmpofs); | ||
592 | emit_fai(as, PPCI_STFD, src, RID_JGL, tmpofs); | ||
593 | #endif | ||
594 | } else if (irref_isk(ref)) { | ||
595 | /* Use the number constant itself as a TValue. */ | ||
596 | ra_allockreg(as, i32ptr(ir_knum(ir)), dest); | ||
597 | } else { | ||
598 | #if LJ_SOFTFP | ||
599 | lj_assertA(0, "unsplit FP op"); | ||
600 | #else | ||
601 | /* Otherwise force a spill and use the spill slot. */ | ||
602 | emit_tai(as, PPCI_ADDI, dest, RID_SP, ra_spill(as, ir)); | ||
603 | #endif | ||
604 | } | ||
605 | } else { | ||
606 | /* Otherwise use g->tmptv to hold the TValue. */ | ||
607 | Reg type; | ||
608 | emit_tai(as, PPCI_ADDI, dest, RID_JGL, tmpofs); | ||
609 | if (!irt_ispri(ir->t)) { | ||
610 | Reg src = ra_alloc1(as, ref, RSET_GPR); | ||
611 | emit_setgl(as, src, tmptv.gcr); | ||
612 | } | ||
613 | if (LJ_SOFTFP && (ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t)) | ||
614 | type = ra_alloc1(as, ref+1, RSET_GPR); | ||
615 | else | ||
616 | type = ra_allock(as, irt_toitype(ir->t), RSET_GPR); | ||
617 | emit_setgl(as, type, tmptv.it); | ||
586 | } | 618 | } |
587 | if (LJ_SOFTFP && (ir+1)->o == IR_HIOP) | 619 | } else { |
588 | type = ra_alloc1(as, ref+1, allow); | 620 | emit_tai(as, PPCI_ADDI, dest, RID_JGL, tmpofs); |
589 | else | ||
590 | type = ra_allock(as, irt_toitype(ir->t), allow); | ||
591 | emit_setgl(as, type, tmptv.it); | ||
592 | } | 621 | } |
593 | } | 622 | } |
594 | 623 | ||
@@ -1958,7 +1987,7 @@ static void asm_hiop(ASMState *as, IRIns *ir) | |||
1958 | ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */ | 1987 | ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */ |
1959 | break; | 1988 | break; |
1960 | #if LJ_SOFTFP | 1989 | #if LJ_SOFTFP |
1961 | case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR: | 1990 | case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR: case IR_TMPREF: |
1962 | #endif | 1991 | #endif |
1963 | case IR_CNEWI: | 1992 | case IR_CNEWI: |
1964 | /* Nothing to do here. Handled by lo op itself. */ | 1993 | /* Nothing to do here. Handled by lo op itself. */ |
diff --git a/src/lj_asm_x86.h b/src/lj_asm_x86.h index 715e1535..b8abf9d6 100644 --- a/src/lj_asm_x86.h +++ b/src/lj_asm_x86.h | |||
@@ -216,6 +216,16 @@ static void asm_fuseahuref(ASMState *as, IRRef ref, RegSet allow) | |||
216 | #endif | 216 | #endif |
217 | } | 217 | } |
218 | break; | 218 | break; |
219 | case IR_TMPREF: | ||
220 | #if LJ_GC64 | ||
221 | as->mrm.ofs = (int32_t)dispofs(as, &J2G(as->J)->tmptv); | ||
222 | as->mrm.base = RID_DISPATCH; | ||
223 | as->mrm.idx = RID_NONE; | ||
224 | #else | ||
225 | as->mrm.ofs = igcptr(&J2G(as->J)->tmptv); | ||
226 | as->mrm.base = as->mrm.idx = RID_NONE; | ||
227 | #endif | ||
228 | return; | ||
219 | default: | 229 | default: |
220 | lj_assertA(ir->o == IR_HREF || ir->o == IR_NEWREF || ir->o == IR_UREFO || | 230 | lj_assertA(ir->o == IR_HREF || ir->o == IR_NEWREF || ir->o == IR_UREFO || |
221 | ir->o == IR_KKPTR, | 231 | ir->o == IR_KKPTR, |
@@ -1050,47 +1060,48 @@ static void asm_strto(ASMState *as, IRIns *ir) | |||
1050 | /* -- Memory references --------------------------------------------------- */ | 1060 | /* -- Memory references --------------------------------------------------- */ |
1051 | 1061 | ||
1052 | /* Get pointer to TValue. */ | 1062 | /* Get pointer to TValue. */ |
1053 | static void asm_tvptr(ASMState *as, Reg dest, IRRef ref) | 1063 | static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode) |
1054 | { | 1064 | { |
1055 | IRIns *ir = IR(ref); | 1065 | if ((mode & IRTMPREF_IN1)) { |
1056 | if (irt_isnum(ir->t)) { | 1066 | IRIns *ir = IR(ref); |
1057 | /* For numbers use the constant itself or a spill slot as a TValue. */ | 1067 | if (irt_isnum(ir->t)) { |
1058 | if (irref_isk(ref)) | 1068 | if (irref_isk(ref) && !(mode & IRTMPREF_OUT1)) { |
1059 | emit_loada(as, dest, ir_knum(ir)); | 1069 | /* Use the number constant itself as a TValue. */ |
1060 | else | 1070 | emit_loada(as, dest, ir_knum(ir)); |
1061 | emit_rmro(as, XO_LEA, dest|REX_64, RID_ESP, ra_spill(as, ir)); | 1071 | return; |
1062 | } else { | 1072 | } |
1063 | /* Otherwise use g->tmptv to hold the TValue. */ | 1073 | emit_rmro(as, XO_MOVSDto, ra_alloc1(as, ref, RSET_FPR), dest, 0); |
1064 | #if LJ_GC64 | ||
1065 | if (irref_isk(ref)) { | ||
1066 | TValue k; | ||
1067 | lj_ir_kvalue(as->J->L, &k, ir); | ||
1068 | emit_movmroi(as, dest, 4, k.u32.hi); | ||
1069 | emit_movmroi(as, dest, 0, k.u32.lo); | ||
1070 | } else { | 1074 | } else { |
1071 | /* TODO: 64 bit store + 32 bit load-modify-store is suboptimal. */ | 1075 | #if LJ_GC64 |
1072 | Reg src = ra_alloc1(as, ref, rset_exclude(RSET_GPR, dest)); | 1076 | if (irref_isk(ref)) { |
1073 | if (irt_is64(ir->t)) { | 1077 | TValue k; |
1074 | emit_u32(as, irt_toitype(ir->t) << 15); | 1078 | lj_ir_kvalue(as->J->L, &k, ir); |
1075 | emit_rmro(as, XO_ARITHi, XOg_OR, dest, 4); | 1079 | emit_movmroi(as, dest, 4, k.u32.hi); |
1080 | emit_movmroi(as, dest, 0, k.u32.lo); | ||
1076 | } else { | 1081 | } else { |
1077 | /* Currently, no caller passes integers that might end up here. */ | 1082 | /* TODO: 64 bit store + 32 bit load-modify-store is suboptimal. */ |
1078 | emit_movmroi(as, dest, 4, (irt_toitype(ir->t) << 15)); | 1083 | Reg src = ra_alloc1(as, ref, rset_exclude(RSET_GPR, dest)); |
1084 | if (irt_is64(ir->t)) { | ||
1085 | emit_u32(as, irt_toitype(ir->t) << 15); | ||
1086 | emit_rmro(as, XO_ARITHi, XOg_OR, dest, 4); | ||
1087 | } else { | ||
1088 | emit_movmroi(as, dest, 4, (irt_toitype(ir->t) << 15)); | ||
1089 | } | ||
1090 | emit_movtomro(as, REX_64IR(ir, src), dest, 0); | ||
1079 | } | 1091 | } |
1080 | emit_movtomro(as, REX_64IR(ir, src), dest, 0); | ||
1081 | } | ||
1082 | #else | 1092 | #else |
1083 | if (!irref_isk(ref)) { | 1093 | if (!irref_isk(ref)) { |
1084 | Reg src = ra_alloc1(as, ref, rset_exclude(RSET_GPR, dest)); | 1094 | Reg src = ra_alloc1(as, ref, rset_exclude(RSET_GPR, dest)); |
1085 | emit_movtomro(as, REX_64IR(ir, src), dest, 0); | 1095 | emit_movtomro(as, REX_64IR(ir, src), dest, 0); |
1086 | } else if (!irt_ispri(ir->t)) { | 1096 | } else if (!irt_ispri(ir->t)) { |
1087 | emit_movmroi(as, dest, 0, ir->i); | 1097 | emit_movmroi(as, dest, 0, ir->i); |
1088 | } | 1098 | } |
1089 | if (!(LJ_64 && irt_islightud(ir->t))) | 1099 | if (!(LJ_64 && irt_islightud(ir->t))) |
1090 | emit_movmroi(as, dest, 4, irt_toitype(ir->t)); | 1100 | emit_movmroi(as, dest, 4, irt_toitype(ir->t)); |
1091 | #endif | 1101 | #endif |
1092 | emit_loada(as, dest, &J2G(as->J)->tmptv); | 1102 | } |
1093 | } | 1103 | } |
1104 | emit_loada(as, dest, &J2G(as->J)->tmptv); /* g->tmptv holds the TValue(s). */ | ||
1094 | } | 1105 | } |
1095 | 1106 | ||
1096 | static void asm_aref(ASMState *as, IRIns *ir) | 1107 | static void asm_aref(ASMState *as, IRIns *ir) |
diff --git a/src/lj_ir.h b/src/lj_ir.h index ea8616ec..22a3b79c 100644 --- a/src/lj_ir.h +++ b/src/lj_ir.h | |||
@@ -95,6 +95,7 @@ | |||
95 | _(UREFO, LW, ref, lit) \ | 95 | _(UREFO, LW, ref, lit) \ |
96 | _(UREFC, LW, ref, lit) \ | 96 | _(UREFC, LW, ref, lit) \ |
97 | _(FREF, R , ref, lit) \ | 97 | _(FREF, R , ref, lit) \ |
98 | _(TMPREF, S , ref, lit) \ | ||
98 | _(STRREF, N , ref, ref) \ | 99 | _(STRREF, N , ref, ref) \ |
99 | _(LREF, L , ___, ___) \ | 100 | _(LREF, L , ___, ___) \ |
100 | \ | 101 | \ |
@@ -218,6 +219,11 @@ IRFLDEF(FLENUM) | |||
218 | IRFL__MAX | 219 | IRFL__MAX |
219 | } IRFieldID; | 220 | } IRFieldID; |
220 | 221 | ||
222 | /* TMPREF mode bits, stored in op2. */ | ||
223 | #define IRTMPREF_IN1 0x01 /* First input value. */ | ||
224 | #define IRTMPREF_OUT1 0x02 /* First output value. */ | ||
225 | #define IRTMPREF_OUT2 0x04 /* Second output value. */ | ||
226 | |||
221 | /* SLOAD mode bits, stored in op2. */ | 227 | /* SLOAD mode bits, stored in op2. */ |
222 | #define IRSLOAD_PARENT 0x01 /* Coalesce with parent trace. */ | 228 | #define IRSLOAD_PARENT 0x01 /* Coalesce with parent trace. */ |
223 | #define IRSLOAD_FRAME 0x02 /* Load 32 bits of ftsz. */ | 229 | #define IRSLOAD_FRAME 0x02 /* Load 32 bits of ftsz. */ |
diff --git a/src/lj_opt_fold.c b/src/lj_opt_fold.c index 3cf448d6..9a41a5a4 100644 --- a/src/lj_opt_fold.c +++ b/src/lj_opt_fold.c | |||
@@ -2421,6 +2421,7 @@ LJFOLD(XSTORE any any) | |||
2421 | LJFOLDX(lj_opt_dse_xstore) | 2421 | LJFOLDX(lj_opt_dse_xstore) |
2422 | 2422 | ||
2423 | LJFOLD(NEWREF any any) /* Treated like a store. */ | 2423 | LJFOLD(NEWREF any any) /* Treated like a store. */ |
2424 | LJFOLD(TMPREF any any) | ||
2424 | LJFOLD(CALLA any any) | 2425 | LJFOLD(CALLA any any) |
2425 | LJFOLD(CALLL any any) /* Safeguard fallback. */ | 2426 | LJFOLD(CALLL any any) /* Safeguard fallback. */ |
2426 | LJFOLD(CALLS any any) | 2427 | LJFOLD(CALLS any any) |
diff --git a/src/lj_opt_split.c b/src/lj_opt_split.c index 3a02abd4..25c1c234 100644 --- a/src/lj_opt_split.c +++ b/src/lj_opt_split.c | |||
@@ -645,7 +645,7 @@ static void split_ir(jit_State *J) | |||
645 | tmp = split_emit(J, IRT(IR_CARG, IRT_NIL), hisubst[op1], oir[op1].prev); | 645 | tmp = split_emit(J, IRT(IR_CARG, IRT_NIL), hisubst[op1], oir[op1].prev); |
646 | #endif | 646 | #endif |
647 | ir->prev = split_emit(J, IRTI(IR_CALLN), tmp, IRCALL_lj_vm_tobit); | 647 | ir->prev = split_emit(J, IRTI(IR_CALLN), tmp, IRCALL_lj_vm_tobit); |
648 | } else if (ir->o == IR_TOSTR) { | 648 | } else if (ir->o == IR_TOSTR || ir->o == IR_TMPREF) { |
649 | if (hisubst[ir->op1]) { | 649 | if (hisubst[ir->op1]) { |
650 | if (irref_isk(ir->op1)) | 650 | if (irref_isk(ir->op1)) |
651 | nir->op1 = ir->op1; | 651 | nir->op1 = ir->op1; |
diff --git a/src/lj_record.c b/src/lj_record.c index 86f17abc..c0aea106 100644 --- a/src/lj_record.c +++ b/src/lj_record.c | |||
@@ -259,6 +259,14 @@ TRef lj_record_constify(jit_State *J, cTValue *o) | |||
259 | return 0; /* Can't represent lightuserdata (pointless). */ | 259 | return 0; /* Can't represent lightuserdata (pointless). */ |
260 | } | 260 | } |
261 | 261 | ||
262 | /* Emit a VLOAD with the correct type. */ | ||
263 | TRef lj_record_vload(jit_State *J, TRef ref, IRType t) | ||
264 | { | ||
265 | TRef tr = emitir(IRTG(IR_VLOAD, t), ref, 0); | ||
266 | if (irtype_ispri(t)) tr = TREF_PRI(t); /* Canonicalize primitives. */ | ||
267 | return tr; | ||
268 | } | ||
269 | |||
262 | /* -- Record loop ops ----------------------------------------------------- */ | 270 | /* -- Record loop ops ----------------------------------------------------- */ |
263 | 271 | ||
264 | /* Loop event. */ | 272 | /* Loop event. */ |
@@ -1832,9 +1840,7 @@ static void rec_varg(jit_State *J, BCReg dst, ptrdiff_t nresults) | |||
1832 | IRType t = itype2irt(&J->L->base[i-1-LJ_FR2-nvararg]); | 1840 | IRType t = itype2irt(&J->L->base[i-1-LJ_FR2-nvararg]); |
1833 | TRef aref = emitir(IRT(IR_AREF, IRT_PGC), | 1841 | TRef aref = emitir(IRT(IR_AREF, IRT_PGC), |
1834 | vbase, lj_ir_kint(J, (int32_t)i)); | 1842 | vbase, lj_ir_kint(J, (int32_t)i)); |
1835 | TRef tr = emitir(IRTG(IR_VLOAD, t), aref, 0); | 1843 | J->base[dst+i] = lj_record_vload(J, aref, t); |
1836 | if (irtype_ispri(t)) tr = TREF_PRI(t); /* Canonicalize primitives. */ | ||
1837 | J->base[dst+i] = tr; | ||
1838 | } | 1844 | } |
1839 | } else { | 1845 | } else { |
1840 | emitir(IRTGI(IR_LE), fr, lj_ir_kint(J, frofs)); | 1846 | emitir(IRTGI(IR_LE), fr, lj_ir_kint(J, frofs)); |
@@ -1881,8 +1887,7 @@ static void rec_varg(jit_State *J, BCReg dst, ptrdiff_t nresults) | |||
1881 | lj_ir_kint(J, frofs-(8<<LJ_FR2))); | 1887 | lj_ir_kint(J, frofs-(8<<LJ_FR2))); |
1882 | t = itype2irt(&J->L->base[idx-2-LJ_FR2-nvararg]); | 1888 | t = itype2irt(&J->L->base[idx-2-LJ_FR2-nvararg]); |
1883 | aref = emitir(IRT(IR_AREF, IRT_PGC), vbase, tridx); | 1889 | aref = emitir(IRT(IR_AREF, IRT_PGC), vbase, tridx); |
1884 | tr = emitir(IRTG(IR_VLOAD, t), aref, 0); | 1890 | tr = lj_record_vload(J, aref, t); |
1885 | if (irtype_ispri(t)) tr = TREF_PRI(t); /* Canonicalize primitives. */ | ||
1886 | } | 1891 | } |
1887 | J->base[dst-2-LJ_FR2] = tr; | 1892 | J->base[dst-2-LJ_FR2] = tr; |
1888 | J->maxslot = dst-1-LJ_FR2; | 1893 | J->maxslot = dst-1-LJ_FR2; |
diff --git a/src/lj_record.h b/src/lj_record.h index de74277e..03d84a71 100644 --- a/src/lj_record.h +++ b/src/lj_record.h | |||
@@ -30,6 +30,7 @@ LJ_FUNC int lj_record_objcmp(jit_State *J, TRef a, TRef b, | |||
30 | cTValue *av, cTValue *bv); | 30 | cTValue *av, cTValue *bv); |
31 | LJ_FUNC void lj_record_stop(jit_State *J, TraceLink linktype, TraceNo lnk); | 31 | LJ_FUNC void lj_record_stop(jit_State *J, TraceLink linktype, TraceNo lnk); |
32 | LJ_FUNC TRef lj_record_constify(jit_State *J, cTValue *o); | 32 | LJ_FUNC TRef lj_record_constify(jit_State *J, cTValue *o); |
33 | LJ_FUNC TRef lj_record_vload(jit_State *J, TRef ref, IRType t); | ||
33 | 34 | ||
34 | LJ_FUNC void lj_record_call(jit_State *J, BCReg func, ptrdiff_t nargs); | 35 | LJ_FUNC void lj_record_call(jit_State *J, BCReg func, ptrdiff_t nargs); |
35 | LJ_FUNC void lj_record_tailcall(jit_State *J, BCReg func, ptrdiff_t nargs); | 36 | LJ_FUNC void lj_record_tailcall(jit_State *J, BCReg func, ptrdiff_t nargs); |