diff options
author | Mike Pall <mike> | 2020-09-27 16:44:13 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2020-09-27 16:44:13 +0200 |
commit | e8ec6fe996cf48ef23755581dafe372eb71ad75c (patch) | |
tree | 69e0d40f53cf99bfa9f12e8dbd09a7badccacba7 /src/lj_asm_ppc.h | |
parent | 881d02d3117838acaf4fb844332c8e33cc95c8c5 (diff) | |
download | luajit2-e8ec6fe996cf48ef23755581dafe372eb71ad75c.tar.gz |
Prevent patching of the GC exit check branch.
Reported by Arseny Vakhrushev.
Diffstat (limited to 'src/lj_asm_ppc.h')
-rw-r--r-- | src/lj_asm_ppc.h | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/src/lj_asm_ppc.h b/src/lj_asm_ppc.h index dc092db2..32546c78 100644 --- a/src/lj_asm_ppc.h +++ b/src/lj_asm_ppc.h @@ -1852,6 +1852,9 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap) /* -- GC handling --------------------------------------------------------- */ +/* Marker to prevent patching the GC check exit. */ +#define PPC_NOPATCH_GC_CHECK PPCI_ORIS + /* Check GC threshold and do one or more GC steps. */ static void asm_gc_check(ASMState *as) { @@ -1863,6 +1866,7 @@ static void asm_gc_check(ASMState *as) l_end = emit_label(as); /* Exit trace if in GCSatomic or GCSfinalize. Avoids syncing GC objects. */ asm_guardcc(as, CC_NE); /* Assumes asm_snap_prep() already done. */ + *--as->mcp = PPC_NOPATCH_GC_CHECK; emit_ai(as, PPCI_CMPWI, RID_RET, 0); args[0] = ASMREF_TMP1; /* global_State *g */ args[1] = ASMREF_TMP2; /* MSize steps */ @@ -2124,7 +2128,7 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target) MCode *px = exitstub_trace_addr(T, exitno); MCode *cstart = NULL; MCode *mcarea = lj_mcode_patch(J, p, 0); - int clearso = 0; + int clearso = 0, patchlong = 1; for (; p < pe; p++) { /* Look for exitstub branch, try to replace with branch to target. */ uint32_t ins = *p; @@ -2136,7 +2140,9 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target) delta -= sizeof(MCode); } /* Many, but not all short-range branches can be patched directly. */ - if (((delta + 0x8000) >> 16) == 0) { + if (p[-1] == PPC_NOPATCH_GC_CHECK) { + patchlong = 0; + } else if (((delta + 0x8000) >> 16) == 0) { *p = (ins & 0xffdf0000u) | ((uint32_t)delta & 0xffffu) | ((delta & 0x8000) * (PPCF_Y/0x8000)); if (!cstart) cstart = p; @@ -2149,7 +2155,8 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target) if (!cstart) cstart = p; } } - { /* Always patch long-range branch in exit stub itself. */ + /* Always patch long-range branch in exit stub itself. Except, if we can't. */ + if (patchlong) { ptrdiff_t delta = (char *)target - (char *)px - clearso; lua_assert(((delta + 0x02000000) >> 26) == 0); *px = PPCI_B | ((uint32_t)delta & 0x03ffffffu); |