aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lj_asm_arm.h7
-rw-r--r--src/lj_asm_mips.h7
-rw-r--r--src/lj_asm_ppc.h13
-rw-r--r--src/lj_asm_x86.h11
4 files changed, 31 insertions, 7 deletions
diff --git a/src/lj_asm_arm.h b/src/lj_asm_arm.h
index 087530b2..e884df5e 100644
--- a/src/lj_asm_arm.h
+++ b/src/lj_asm_arm.h
@@ -2040,6 +2040,9 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
2040 2040
2041/* -- GC handling --------------------------------------------------------- */ 2041/* -- GC handling --------------------------------------------------------- */
2042 2042
2043/* Marker to prevent patching the GC check exit. */
2044#define ARM_NOPATCH_GC_CHECK (ARMI_BIC|ARMI_K12)
2045
2043/* Check GC threshold and do one or more GC steps. */ 2046/* Check GC threshold and do one or more GC steps. */
2044static void asm_gc_check(ASMState *as) 2047static void asm_gc_check(ASMState *as)
2045{ 2048{
@@ -2051,6 +2054,7 @@ static void asm_gc_check(ASMState *as)
2051 l_end = emit_label(as); 2054 l_end = emit_label(as);
2052 /* Exit trace if in GCSatomic or GCSfinalize. Avoids syncing GC objects. */ 2055 /* Exit trace if in GCSatomic or GCSfinalize. Avoids syncing GC objects. */
2053 asm_guardcc(as, CC_NE); /* Assumes asm_snap_prep() already done. */ 2056 asm_guardcc(as, CC_NE); /* Assumes asm_snap_prep() already done. */
2057 *--as->mcp = ARM_NOPATCH_GC_CHECK;
2054 emit_n(as, ARMI_CMP|ARMI_K12|0, RID_RET); 2058 emit_n(as, ARMI_CMP|ARMI_K12|0, RID_RET);
2055 args[0] = ASMREF_TMP1; /* global_State *g */ 2059 args[0] = ASMREF_TMP1; /* global_State *g */
2056 args[1] = ASMREF_TMP2; /* MSize steps */ 2060 args[1] = ASMREF_TMP2; /* MSize steps */
@@ -2349,7 +2353,8 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
2349 /* Look for bl_cc exitstub, replace with b_cc target. */ 2353 /* Look for bl_cc exitstub, replace with b_cc target. */
2350 uint32_t ins = *p; 2354 uint32_t ins = *p;
2351 if ((ins & 0x0f000000u) == 0x0b000000u && ins < 0xf0000000u && 2355 if ((ins & 0x0f000000u) == 0x0b000000u && ins < 0xf0000000u &&
2352 ((ins ^ (px-p)) & 0x00ffffffu) == 0) { 2356 ((ins ^ (px-p)) & 0x00ffffffu) == 0 &&
2357 p[-1] != ARM_NOPATCH_GC_CHECK) {
2353 *p = (ins & 0xfe000000u) | (((target-p)-2) & 0x00ffffffu); 2358 *p = (ins & 0xfe000000u) | (((target-p)-2) & 0x00ffffffu);
2354 cend = p+1; 2359 cend = p+1;
2355 if (!cstart) cstart = p; 2360 if (!cstart) cstart = p;
diff --git a/src/lj_asm_mips.h b/src/lj_asm_mips.h
index 190a55eb..22031d11 100644
--- a/src/lj_asm_mips.h
+++ b/src/lj_asm_mips.h
@@ -1665,6 +1665,9 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
1665 1665
1666/* -- GC handling --------------------------------------------------------- */ 1666/* -- GC handling --------------------------------------------------------- */
1667 1667
1668/* Marker to prevent patching the GC check exit. */
1669#define MIPS_NOPATCH_GC_CHECK MIPSI_OR
1670
1668/* Check GC threshold and do one or more GC steps. */ 1671/* Check GC threshold and do one or more GC steps. */
1669static void asm_gc_check(ASMState *as) 1672static void asm_gc_check(ASMState *as)
1670{ 1673{
@@ -1680,6 +1683,7 @@ static void asm_gc_check(ASMState *as)
1680 args[0] = ASMREF_TMP1; /* global_State *g */ 1683 args[0] = ASMREF_TMP1; /* global_State *g */
1681 args[1] = ASMREF_TMP2; /* MSize steps */ 1684 args[1] = ASMREF_TMP2; /* MSize steps */
1682 asm_gencall(as, ci, args); 1685 asm_gencall(as, ci, args);
1686 l_end[-3] = MIPS_NOPATCH_GC_CHECK; /* Replace the nop after the call. */
1683 emit_tsi(as, MIPSI_ADDIU, ra_releasetmp(as, ASMREF_TMP1), RID_JGL, -32768); 1687 emit_tsi(as, MIPSI_ADDIU, ra_releasetmp(as, ASMREF_TMP1), RID_JGL, -32768);
1684 tmp = ra_releasetmp(as, ASMREF_TMP2); 1688 tmp = ra_releasetmp(as, ASMREF_TMP2);
1685 emit_loadi(as, tmp, as->gcsteps); 1689 emit_loadi(as, tmp, as->gcsteps);
@@ -1936,7 +1940,8 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
1936 if (((p[-1] ^ (px-p)) & 0xffffu) == 0 && 1940 if (((p[-1] ^ (px-p)) & 0xffffu) == 0 &&
1937 ((p[-1] & 0xf0000000u) == MIPSI_BEQ || 1941 ((p[-1] & 0xf0000000u) == MIPSI_BEQ ||
1938 (p[-1] & 0xfc1e0000u) == MIPSI_BLTZ || 1942 (p[-1] & 0xfc1e0000u) == MIPSI_BLTZ ||
1939 (p[-1] & 0xffe00000u) == MIPSI_BC1F)) { 1943 (p[-1] & 0xffe00000u) == MIPSI_BC1F) &&
1944 p[-2] != MIPS_NOPATCH_GC_CHECK) {
1940 ptrdiff_t delta = target - p; 1945 ptrdiff_t delta = target - p;
1941 if (((delta + 0x8000) >> 16) == 0) { /* Patch in-range branch. */ 1946 if (((delta + 0x8000) >> 16) == 0) { /* Patch in-range branch. */
1942 patchbranch: 1947 patchbranch:
diff --git a/src/lj_asm_ppc.h b/src/lj_asm_ppc.h
index dc092db2..32546c78 100644
--- a/src/lj_asm_ppc.h
+++ b/src/lj_asm_ppc.h
@@ -1852,6 +1852,9 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
1852 1852
1853/* -- GC handling --------------------------------------------------------- */ 1853/* -- GC handling --------------------------------------------------------- */
1854 1854
1855/* Marker to prevent patching the GC check exit. */
1856#define PPC_NOPATCH_GC_CHECK PPCI_ORIS
1857
1855/* Check GC threshold and do one or more GC steps. */ 1858/* Check GC threshold and do one or more GC steps. */
1856static void asm_gc_check(ASMState *as) 1859static void asm_gc_check(ASMState *as)
1857{ 1860{
@@ -1863,6 +1866,7 @@ static void asm_gc_check(ASMState *as)
1863 l_end = emit_label(as); 1866 l_end = emit_label(as);
1864 /* Exit trace if in GCSatomic or GCSfinalize. Avoids syncing GC objects. */ 1867 /* Exit trace if in GCSatomic or GCSfinalize. Avoids syncing GC objects. */
1865 asm_guardcc(as, CC_NE); /* Assumes asm_snap_prep() already done. */ 1868 asm_guardcc(as, CC_NE); /* Assumes asm_snap_prep() already done. */
1869 *--as->mcp = PPC_NOPATCH_GC_CHECK;
1866 emit_ai(as, PPCI_CMPWI, RID_RET, 0); 1870 emit_ai(as, PPCI_CMPWI, RID_RET, 0);
1867 args[0] = ASMREF_TMP1; /* global_State *g */ 1871 args[0] = ASMREF_TMP1; /* global_State *g */
1868 args[1] = ASMREF_TMP2; /* MSize steps */ 1872 args[1] = ASMREF_TMP2; /* MSize steps */
@@ -2124,7 +2128,7 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
2124 MCode *px = exitstub_trace_addr(T, exitno); 2128 MCode *px = exitstub_trace_addr(T, exitno);
2125 MCode *cstart = NULL; 2129 MCode *cstart = NULL;
2126 MCode *mcarea = lj_mcode_patch(J, p, 0); 2130 MCode *mcarea = lj_mcode_patch(J, p, 0);
2127 int clearso = 0; 2131 int clearso = 0, patchlong = 1;
2128 for (; p < pe; p++) { 2132 for (; p < pe; p++) {
2129 /* Look for exitstub branch, try to replace with branch to target. */ 2133 /* Look for exitstub branch, try to replace with branch to target. */
2130 uint32_t ins = *p; 2134 uint32_t ins = *p;
@@ -2136,7 +2140,9 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
2136 delta -= sizeof(MCode); 2140 delta -= sizeof(MCode);
2137 } 2141 }
2138 /* Many, but not all short-range branches can be patched directly. */ 2142 /* Many, but not all short-range branches can be patched directly. */
2139 if (((delta + 0x8000) >> 16) == 0) { 2143 if (p[-1] == PPC_NOPATCH_GC_CHECK) {
2144 patchlong = 0;
2145 } else if (((delta + 0x8000) >> 16) == 0) {
2140 *p = (ins & 0xffdf0000u) | ((uint32_t)delta & 0xffffu) | 2146 *p = (ins & 0xffdf0000u) | ((uint32_t)delta & 0xffffu) |
2141 ((delta & 0x8000) * (PPCF_Y/0x8000)); 2147 ((delta & 0x8000) * (PPCF_Y/0x8000));
2142 if (!cstart) cstart = p; 2148 if (!cstart) cstart = p;
@@ -2149,7 +2155,8 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
2149 if (!cstart) cstart = p; 2155 if (!cstart) cstart = p;
2150 } 2156 }
2151 } 2157 }
2152 { /* Always patch long-range branch in exit stub itself. */ 2158 /* Always patch long-range branch in exit stub itself. Except, if we can't. */
2159 if (patchlong) {
2153 ptrdiff_t delta = (char *)target - (char *)px - clearso; 2160 ptrdiff_t delta = (char *)target - (char *)px - clearso;
2154 lua_assert(((delta + 0x02000000) >> 26) == 0); 2161 lua_assert(((delta + 0x02000000) >> 26) == 0);
2155 *px = PPCI_B | ((uint32_t)delta & 0x03ffffffu); 2162 *px = PPCI_B | ((uint32_t)delta & 0x03ffffffu);
diff --git a/src/lj_asm_x86.h b/src/lj_asm_x86.h
index 68b40b31..9b61b397 100644
--- a/src/lj_asm_x86.h
+++ b/src/lj_asm_x86.h
@@ -2884,6 +2884,7 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
2884 MSize len = T->szmcode; 2884 MSize len = T->szmcode;
2885 MCode *px = exitstub_addr(J, exitno) - 6; 2885 MCode *px = exitstub_addr(J, exitno) - 6;
2886 MCode *pe = p+len-6; 2886 MCode *pe = p+len-6;
2887 MCode *pgc = NULL;
2887 uint32_t stateaddr = u32ptr(&J2G(J)->vmstate); 2888 uint32_t stateaddr = u32ptr(&J2G(J)->vmstate);
2888 if (len > 5 && p[len-5] == XI_JMP && p+len-6 + *(int32_t *)(p+len-4) == px) 2889 if (len > 5 && p[len-5] == XI_JMP && p+len-6 + *(int32_t *)(p+len-4) == px)
2889 *(int32_t *)(p+len-4) = jmprel(p+len, target); 2890 *(int32_t *)(p+len-4) = jmprel(p+len, target);
@@ -2892,9 +2893,15 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
2892 if (*(uint32_t *)(p+(LJ_64 ? 3 : 2)) == stateaddr && p[0] == XI_MOVmi) 2893 if (*(uint32_t *)(p+(LJ_64 ? 3 : 2)) == stateaddr && p[0] == XI_MOVmi)
2893 break; 2894 break;
2894 lua_assert(p < pe); 2895 lua_assert(p < pe);
2895 for (; p < pe; p += asm_x86_inslen(p)) 2896 for (; p < pe; p += asm_x86_inslen(p)) {
2896 if ((*(uint16_t *)p & 0xf0ff) == 0x800f && p + *(int32_t *)(p+2) == px) 2897 if ((*(uint16_t *)p & 0xf0ff) == 0x800f && p + *(int32_t *)(p+2) == px &&
2898 p != pgc) {
2897 *(int32_t *)(p+2) = jmprel(p+6, target); 2899 *(int32_t *)(p+2) = jmprel(p+6, target);
2900 } else if (*p == XI_CALL &&
2901 (void *)(p+5+*(int32_t *)(p+1)) == (void *)lj_gc_step_jit) {
2902 pgc = p+7; /* Do not patch GC check exit. */
2903 }
2904 }
2898 lj_mcode_sync(T->mcode, T->mcode + T->szmcode); 2905 lj_mcode_sync(T->mcode, T->mcode + T->szmcode);
2899 lj_mcode_patch(J, mcarea, 1); 2906 lj_mcode_patch(J, mcarea, 1);
2900} 2907}