diff options
Diffstat (limited to 'src/lj_asm_arm64.h')
-rw-r--r-- | src/lj_asm_arm64.h | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/src/lj_asm_arm64.h b/src/lj_asm_arm64.h index b1fd3acc..37b79cde 100644 --- a/src/lj_asm_arm64.h +++ b/src/lj_asm_arm64.h | |||
@@ -1794,6 +1794,10 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap) | |||
1794 | 1794 | ||
1795 | /* -- GC handling --------------------------------------------------------- */ | 1795 | /* -- GC handling --------------------------------------------------------- */ |
1796 | 1796 | ||
1797 | /* Marker to prevent patching the GC check exit. */ | ||
1798 | #define ARM64_NOPATCH_GC_CHECK \ | ||
1799 | (A64I_ORRx|A64F_D(RID_TMP)|A64F_M(RID_TMP)|A64F_N(RID_TMP)) | ||
1800 | |||
1797 | /* Check GC threshold and do one or more GC steps. */ | 1801 | /* Check GC threshold and do one or more GC steps. */ |
1798 | static void asm_gc_check(ASMState *as) | 1802 | static void asm_gc_check(ASMState *as) |
1799 | { | 1803 | { |
@@ -1805,6 +1809,7 @@ static void asm_gc_check(ASMState *as) | |||
1805 | l_end = emit_label(as); | 1809 | l_end = emit_label(as); |
1806 | /* Exit trace if in GCSatomic or GCSfinalize. Avoids syncing GC objects. */ | 1810 | /* Exit trace if in GCSatomic or GCSfinalize. Avoids syncing GC objects. */ |
1807 | asm_guardcnb(as, A64I_CBNZ, RID_RET); /* Assumes asm_snap_prep() is done. */ | 1811 | asm_guardcnb(as, A64I_CBNZ, RID_RET); /* Assumes asm_snap_prep() is done. */ |
1812 | *--as->mcp = ARM64_NOPATCH_GC_CHECK; | ||
1808 | args[0] = ASMREF_TMP1; /* global_State *g */ | 1813 | args[0] = ASMREF_TMP1; /* global_State *g */ |
1809 | args[1] = ASMREF_TMP2; /* MSize steps */ | 1814 | args[1] = ASMREF_TMP2; /* MSize steps */ |
1810 | asm_gencall(as, ci, args); | 1815 | asm_gencall(as, ci, args); |
@@ -1972,6 +1977,7 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target) | |||
1972 | MCode *cstart = NULL; | 1977 | MCode *cstart = NULL; |
1973 | MCode *mcarea = lj_mcode_patch(J, p, 0); | 1978 | MCode *mcarea = lj_mcode_patch(J, p, 0); |
1974 | MCode *px = exitstub_trace_addr(T, exitno); | 1979 | MCode *px = exitstub_trace_addr(T, exitno); |
1980 | int patchlong = 1; | ||
1975 | /* Note: this assumes a trace exit is only ever patched once. */ | 1981 | /* Note: this assumes a trace exit is only ever patched once. */ |
1976 | for (; p < pe; p++) { | 1982 | for (; p < pe; p++) { |
1977 | /* Look for exitstub branch, replace with branch to target. */ | 1983 | /* Look for exitstub branch, replace with branch to target. */ |
@@ -1993,7 +1999,9 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target) | |||
1993 | } else if ((ins & 0x7e000000u) == 0x34000000u && | 1999 | } else if ((ins & 0x7e000000u) == 0x34000000u && |
1994 | ((ins ^ ((px-p)<<5)) & 0x00ffffe0u) == 0) { | 2000 | ((ins ^ ((px-p)<<5)) & 0x00ffffe0u) == 0) { |
1995 | /* Patch cbz/cbnz, if within range. */ | 2001 | /* Patch cbz/cbnz, if within range. */ |
1996 | if (A64F_S_OK(delta, 19)) { | 2002 | if (p[-1] == ARM64_NOPATCH_GC_CHECK) { |
2003 | patchlong = 0; | ||
2004 | } else if (A64F_S_OK(delta, 19)) { | ||
1997 | *p = A64I_LE((ins & 0xff00001fu) | A64F_S19(delta)); | 2005 | *p = A64I_LE((ins & 0xff00001fu) | A64F_S19(delta)); |
1998 | if (!cstart) cstart = p; | 2006 | if (!cstart) cstart = p; |
1999 | } | 2007 | } |
@@ -2006,7 +2014,8 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target) | |||
2006 | } | 2014 | } |
2007 | } | 2015 | } |
2008 | } | 2016 | } |
2009 | { /* Always patch long-range branch in exit stub itself. */ | 2017 | /* Always patch long-range branch in exit stub itself. Except, if we can't. */ |
2018 | if (patchlong) { | ||
2010 | ptrdiff_t delta = target - px; | 2019 | ptrdiff_t delta = target - px; |
2011 | lj_assertJ(A64F_S_OK(delta, 26), "branch target out of range"); | 2020 | lj_assertJ(A64F_S_OK(delta, 26), "branch target out of range"); |
2012 | *px = A64I_B | A64F_S26(delta); | 2021 | *px = A64I_B | A64F_S26(delta); |