aboutsummaryrefslogtreecommitdiff
path: root/src/lj_asm_arm64.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_asm_arm64.h')
-rw-r--r--src/lj_asm_arm64.h13
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. */
1798static void asm_gc_check(ASMState *as) 1802static 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);