diff options
author | Mike Pall <mike> | 2020-09-27 17:20:37 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2020-09-27 17:20:37 +0200 |
commit | 2e55a42c07f97fe535123675f24a4f5315a66d7c (patch) | |
tree | 9a71145e6619b422b9e16447a5096161b67164ce | |
parent | 03a7ebca4f6819658cdaa12ba3af54a17b8035e9 (diff) | |
parent | e8ec6fe996cf48ef23755581dafe372eb71ad75c (diff) | |
download | luajit-2e55a42c07f97fe535123675f24a4f5315a66d7c.tar.gz luajit-2e55a42c07f97fe535123675f24a4f5315a66d7c.tar.bz2 luajit-2e55a42c07f97fe535123675f24a4f5315a66d7c.zip |
Merge branch 'master' into v2.1
-rw-r--r-- | src/lj_asm_arm.h | 7 | ||||
-rw-r--r-- | src/lj_asm_arm64.h | 13 | ||||
-rw-r--r-- | src/lj_asm_mips.h | 6 | ||||
-rw-r--r-- | src/lj_asm_ppc.h | 13 | ||||
-rw-r--r-- | src/lj_asm_x86.h | 11 |
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. */ |
2037 | static void asm_gc_check(ASMState *as) | 2040 | static 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. */ |
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); |
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. */ |
2532 | static void asm_gc_check(ASMState *as) | 2535 | static 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. */ |
2071 | static void asm_gc_check(ASMState *as) | 2074 | static 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 | } |