aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pall <mike>2020-09-27 17:20:37 +0200
committerMike Pall <mike>2020-09-27 17:20:37 +0200
commit2e55a42c07f97fe535123675f24a4f5315a66d7c (patch)
tree9a71145e6619b422b9e16447a5096161b67164ce
parent03a7ebca4f6819658cdaa12ba3af54a17b8035e9 (diff)
parente8ec6fe996cf48ef23755581dafe372eb71ad75c (diff)
downloadluajit-2e55a42c07f97fe535123675f24a4f5315a66d7c.tar.gz
luajit-2e55a42c07f97fe535123675f24a4f5315a66d7c.tar.bz2
luajit-2e55a42c07f97fe535123675f24a4f5315a66d7c.zip
Merge branch 'master' into v2.1
-rw-r--r--src/lj_asm_arm.h7
-rw-r--r--src/lj_asm_arm64.h13
-rw-r--r--src/lj_asm_mips.h6
-rw-r--r--src/lj_asm_ppc.h13
-rw-r--r--src/lj_asm_x86.h11
5 files changed, 41 insertions, 9 deletions
diff --git a/src/lj_asm_arm.h b/src/lj_asm_arm.h
index e7d2bf17..44dc02e4 100644
--- a/src/lj_asm_arm.h
+++ b/src/lj_asm_arm.h
@@ -2033,6 +2033,9 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
2033 2033
2034/* -- GC handling --------------------------------------------------------- */ 2034/* -- GC handling --------------------------------------------------------- */
2035 2035
2036/* Marker to prevent patching the GC check exit. */
2037#define ARM_NOPATCH_GC_CHECK (ARMI_BIC|ARMI_K12)
2038
2036/* Check GC threshold and do one or more GC steps. */ 2039/* Check GC threshold and do one or more GC steps. */
2037static void asm_gc_check(ASMState *as) 2040static void asm_gc_check(ASMState *as)
2038{ 2041{
@@ -2044,6 +2047,7 @@ static void asm_gc_check(ASMState *as)
2044 l_end = emit_label(as); 2047 l_end = emit_label(as);
2045 /* Exit trace if in GCSatomic or GCSfinalize. Avoids syncing GC objects. */ 2048 /* Exit trace if in GCSatomic or GCSfinalize. Avoids syncing GC objects. */
2046 asm_guardcc(as, CC_NE); /* Assumes asm_snap_prep() already done. */ 2049 asm_guardcc(as, CC_NE); /* Assumes asm_snap_prep() already done. */
2050 *--as->mcp = ARM_NOPATCH_GC_CHECK;
2047 emit_n(as, ARMI_CMP|ARMI_K12|0, RID_RET); 2051 emit_n(as, ARMI_CMP|ARMI_K12|0, RID_RET);
2048 args[0] = ASMREF_TMP1; /* global_State *g */ 2052 args[0] = ASMREF_TMP1; /* global_State *g */
2049 args[1] = ASMREF_TMP2; /* MSize steps */ 2053 args[1] = ASMREF_TMP2; /* MSize steps */
@@ -2212,7 +2216,8 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
2212 /* Look for bl_cc exitstub, replace with b_cc target. */ 2216 /* Look for bl_cc exitstub, replace with b_cc target. */
2213 uint32_t ins = *p; 2217 uint32_t ins = *p;
2214 if ((ins & 0x0f000000u) == 0x0b000000u && ins < 0xf0000000u && 2218 if ((ins & 0x0f000000u) == 0x0b000000u && ins < 0xf0000000u &&
2215 ((ins ^ (px-p)) & 0x00ffffffu) == 0) { 2219 ((ins ^ (px-p)) & 0x00ffffffu) == 0 &&
2220 p[-1] != ARM_NOPATCH_GC_CHECK) {
2216 *p = (ins & 0xfe000000u) | (((target-p)-2) & 0x00ffffffu); 2221 *p = (ins & 0xfe000000u) | (((target-p)-2) & 0x00ffffffu);
2217 cend = p+1; 2222 cend = p+1;
2218 if (!cstart) cstart = p; 2223 if (!cstart) cstart = p;
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);
diff --git a/src/lj_asm_mips.h b/src/lj_asm_mips.h
index 513bd5ca..8abb2544 100644
--- a/src/lj_asm_mips.h
+++ b/src/lj_asm_mips.h
@@ -2528,6 +2528,9 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
2528 2528
2529/* -- GC handling --------------------------------------------------------- */ 2529/* -- GC handling --------------------------------------------------------- */
2530 2530
2531/* Marker to prevent patching the GC check exit. */
2532#define MIPS_NOPATCH_GC_CHECK MIPSI_OR
2533
2531/* Check GC threshold and do one or more GC steps. */ 2534/* Check GC threshold and do one or more GC steps. */
2532static void asm_gc_check(ASMState *as) 2535static void asm_gc_check(ASMState *as)
2533{ 2536{
@@ -2543,6 +2546,7 @@ static void asm_gc_check(ASMState *as)
2543 args[0] = ASMREF_TMP1; /* global_State *g */ 2546 args[0] = ASMREF_TMP1; /* global_State *g */
2544 args[1] = ASMREF_TMP2; /* MSize steps */ 2547 args[1] = ASMREF_TMP2; /* MSize steps */
2545 asm_gencall(as, ci, args); 2548 asm_gencall(as, ci, args);
2549 l_end[-3] = MIPS_NOPATCH_GC_CHECK; /* Replace the nop after the call. */
2546 emit_tsi(as, MIPSI_AADDIU, ra_releasetmp(as, ASMREF_TMP1), RID_JGL, -32768); 2550 emit_tsi(as, MIPSI_AADDIU, ra_releasetmp(as, ASMREF_TMP1), RID_JGL, -32768);
2547 tmp = ra_releasetmp(as, ASMREF_TMP2); 2551 tmp = ra_releasetmp(as, ASMREF_TMP2);
2548 emit_loadi(as, tmp, as->gcsteps); 2552 emit_loadi(as, tmp, as->gcsteps);
@@ -2694,7 +2698,7 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
2694#else 2698#else
2695 (p[-1] & 0xff600000u) == MIPSI_BC1EQZ 2699 (p[-1] & 0xff600000u) == MIPSI_BC1EQZ
2696#endif 2700#endif
2697 )) { 2701 ) && p[-2] != MIPS_NOPATCH_GC_CHECK) {
2698 ptrdiff_t delta = target - p; 2702 ptrdiff_t delta = target - p;
2699 if (((delta + 0x8000) >> 16) == 0) { /* Patch in-range branch. */ 2703 if (((delta + 0x8000) >> 16) == 0) { /* Patch in-range branch. */
2700 patchbranch: 2704 patchbranch:
diff --git a/src/lj_asm_ppc.h b/src/lj_asm_ppc.h
index 77ab09d6..0952ca26 100644
--- a/src/lj_asm_ppc.h
+++ b/src/lj_asm_ppc.h
@@ -2067,6 +2067,9 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
2067 2067
2068/* -- GC handling --------------------------------------------------------- */ 2068/* -- GC handling --------------------------------------------------------- */
2069 2069
2070/* Marker to prevent patching the GC check exit. */
2071#define PPC_NOPATCH_GC_CHECK PPCI_ORIS
2072
2070/* Check GC threshold and do one or more GC steps. */ 2073/* Check GC threshold and do one or more GC steps. */
2071static void asm_gc_check(ASMState *as) 2074static void asm_gc_check(ASMState *as)
2072{ 2075{
@@ -2078,6 +2081,7 @@ static void asm_gc_check(ASMState *as)
2078 l_end = emit_label(as); 2081 l_end = emit_label(as);
2079 /* Exit trace if in GCSatomic or GCSfinalize. Avoids syncing GC objects. */ 2082 /* Exit trace if in GCSatomic or GCSfinalize. Avoids syncing GC objects. */
2080 asm_guardcc(as, CC_NE); /* Assumes asm_snap_prep() already done. */ 2083 asm_guardcc(as, CC_NE); /* Assumes asm_snap_prep() already done. */
2084 *--as->mcp = PPC_NOPATCH_GC_CHECK;
2081 emit_ai(as, PPCI_CMPWI, RID_RET, 0); 2085 emit_ai(as, PPCI_CMPWI, RID_RET, 0);
2082 args[0] = ASMREF_TMP1; /* global_State *g */ 2086 args[0] = ASMREF_TMP1; /* global_State *g */
2083 args[1] = ASMREF_TMP2; /* MSize steps */ 2087 args[1] = ASMREF_TMP2; /* MSize steps */
@@ -2217,7 +2221,7 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
2217 MCode *px = exitstub_trace_addr(T, exitno); 2221 MCode *px = exitstub_trace_addr(T, exitno);
2218 MCode *cstart = NULL; 2222 MCode *cstart = NULL;
2219 MCode *mcarea = lj_mcode_patch(J, p, 0); 2223 MCode *mcarea = lj_mcode_patch(J, p, 0);
2220 int clearso = 0; 2224 int clearso = 0, patchlong = 1;
2221 for (; p < pe; p++) { 2225 for (; p < pe; p++) {
2222 /* Look for exitstub branch, try to replace with branch to target. */ 2226 /* Look for exitstub branch, try to replace with branch to target. */
2223 uint32_t ins = *p; 2227 uint32_t ins = *p;
@@ -2229,7 +2233,9 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
2229 delta -= sizeof(MCode); 2233 delta -= sizeof(MCode);
2230 } 2234 }
2231 /* Many, but not all short-range branches can be patched directly. */ 2235 /* Many, but not all short-range branches can be patched directly. */
2232 if (((delta + 0x8000) >> 16) == 0) { 2236 if (p[-1] == PPC_NOPATCH_GC_CHECK) {
2237 patchlong = 0;
2238 } else if (((delta + 0x8000) >> 16) == 0) {
2233 *p = (ins & 0xffdf0000u) | ((uint32_t)delta & 0xffffu) | 2239 *p = (ins & 0xffdf0000u) | ((uint32_t)delta & 0xffffu) |
2234 ((delta & 0x8000) * (PPCF_Y/0x8000)); 2240 ((delta & 0x8000) * (PPCF_Y/0x8000));
2235 if (!cstart) cstart = p; 2241 if (!cstart) cstart = p;
@@ -2243,7 +2249,8 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
2243 if (!cstart) cstart = p; 2249 if (!cstart) cstart = p;
2244 } 2250 }
2245 } 2251 }
2246 { /* Always patch long-range branch in exit stub itself. */ 2252 /* Always patch long-range branch in exit stub itself. Except, if we can't. */
2253 if (patchlong) {
2247 ptrdiff_t delta = (char *)target - (char *)px - clearso; 2254 ptrdiff_t delta = (char *)target - (char *)px - clearso;
2248 lj_assertJ(((delta + 0x02000000) >> 26) == 0, 2255 lj_assertJ(((delta + 0x02000000) >> 26) == 0,
2249 "branch target out of range"); 2256 "branch target out of range");
diff --git a/src/lj_asm_x86.h b/src/lj_asm_x86.h
index 146371c1..4d1c85b3 100644
--- a/src/lj_asm_x86.h
+++ b/src/lj_asm_x86.h
@@ -3072,6 +3072,7 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
3072 MSize len = T->szmcode; 3072 MSize len = T->szmcode;
3073 MCode *px = exitstub_addr(J, exitno) - 6; 3073 MCode *px = exitstub_addr(J, exitno) - 6;
3074 MCode *pe = p+len-6; 3074 MCode *pe = p+len-6;
3075 MCode *pgc = NULL;
3075#if LJ_GC64 3076#if LJ_GC64
3076 uint32_t statei = (uint32_t)(GG_OFS(g.vmstate) - GG_OFS(dispatch)); 3077 uint32_t statei = (uint32_t)(GG_OFS(g.vmstate) - GG_OFS(dispatch));
3077#else 3078#else
@@ -3086,9 +3087,15 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
3086 break; 3087 break;
3087 } 3088 }
3088 lj_assertJ(p < pe, "instruction length decoder failed"); 3089 lj_assertJ(p < pe, "instruction length decoder failed");
3089 for (; p < pe; p += asm_x86_inslen(p)) 3090 for (; p < pe; p += asm_x86_inslen(p)) {
3090 if ((*(uint16_t *)p & 0xf0ff) == 0x800f && p + *(int32_t *)(p+2) == px) 3091 if ((*(uint16_t *)p & 0xf0ff) == 0x800f && p + *(int32_t *)(p+2) == px &&
3092 p != pgc) {
3091 *(int32_t *)(p+2) = jmprel(J, p+6, target); 3093 *(int32_t *)(p+2) = jmprel(J, p+6, target);
3094 } else if (*p == XI_CALL &&
3095 (void *)(p+5+*(int32_t *)(p+1)) == (void *)lj_gc_step_jit) {
3096 pgc = p+7; /* Do not patch GC check exit. */
3097 }
3098 }
3092 lj_mcode_sync(T->mcode, T->mcode + T->szmcode); 3099 lj_mcode_sync(T->mcode, T->mcode + T->szmcode);
3093 lj_mcode_patch(J, mcarea, 1); 3100 lj_mcode_patch(J, mcarea, 1);
3094} 3101}