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 | } |
