diff options
-rw-r--r-- | src/lj_asm_arm.h | 7 | ||||
-rw-r--r-- | src/lj_asm_mips.h | 7 | ||||
-rw-r--r-- | src/lj_asm_ppc.h | 13 | ||||
-rw-r--r-- | src/lj_asm_x86.h | 11 |
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. */ |
2044 | static void asm_gc_check(ASMState *as) | 2047 | static 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. */ |
1669 | static void asm_gc_check(ASMState *as) | 1672 | static 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. */ |
1856 | static void asm_gc_check(ASMState *as) | 1859 | static 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 | } |