diff options
Diffstat (limited to 'src/lj_asm_ppc.h')
-rw-r--r-- | src/lj_asm_ppc.h | 13 |
1 files changed, 10 insertions, 3 deletions
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); |