From 389822d606045a953bd30e14ebc50ff97bce8a59 Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Thu, 4 Apr 2013 17:19:31 +0200 Subject: [PATCH] Fix spurious red zone overflows in machine code generation. --- src/lj_asm.c | 30 ++++++++++++++++++++++++++++-- src/lj_asm_mips.h | 1 + src/lj_asm_ppc.h | 1 + src/lj_asm_x86.h | 1 + 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/lj_asm.c b/src/lj_asm.c index c7365404..038f4d1c 100644 --- a/src/lj_asm.c +++ b/src/lj_asm.c @@ -30,6 +30,10 @@ #include "lj_vm.h" #include "lj_target.h" +#ifdef LUA_USE_ASSERT +#include +#endif + /* -- Assembler state and common macros ----------------------------------- */ /* Assembler state. */ @@ -38,6 +42,9 @@ typedef struct ASMState { MCode *mcp; /* Current MCode pointer (grows down). */ MCode *mclim; /* Lower limit for MCode memory + red zone. */ +#ifdef LUA_USE_ASSERT + MCode *mcp_prev; /* Red zone overflow check. */ +#endif IRIns *ir; /* Copy of pointer to IR instructions/constants. */ jit_State *J; /* JIT compiler state. */ @@ -110,14 +117,28 @@ typedef struct ASMState { /* Sparse limit checks using a red zone before the actual limit. */ #define MCLIM_REDZONE 64 -#define checkmclim(as) \ - if (LJ_UNLIKELY(as->mcp < as->mclim)) asm_mclimit(as) static LJ_NORET LJ_NOINLINE void asm_mclimit(ASMState *as) { lj_mcode_limiterr(as->J, (size_t)(as->mctop - as->mcp + 4*MCLIM_REDZONE)); } +static LJ_AINLINE void checkmclim(ASMState *as) +{ +#ifdef LUA_USE_ASSERT + if (as->mcp + MCLIM_REDZONE < as->mcp_prev) { + IRIns *ir = IR(as->curins+1); + fprintf(stderr, "RED ZONE OVERFLOW: %p IR %04d %02d %04d %04d\n", as->mcp, + as->curins+1-REF_BIAS, ir->o, ir->op1-REF_BIAS, ir->op2-REF_BIAS); + lua_assert(0); + } +#endif + if (LJ_UNLIKELY(as->mcp < as->mclim)) asm_mclimit(as); +#ifdef LUA_USE_ASSERT + as->mcp_prev = as->mcp; +#endif +} + #ifdef RID_NUM_KREF #define ra_iskref(ref) ((ref) < RID_NUM_KREF) #define ra_krefreg(ref) ((Reg)(RID_MIN_KREF + (Reg)(ref))) @@ -1181,6 +1202,7 @@ static void asm_phi_copyspill(ASMState *as) if (ra_hasspill(irl->s) && !irt_isfp(ir->t)) { emit_spstore(as, irl, r, sps_scale(irl->s)); emit_spload(as, ir, r, sps_scale(ir->s)); + checkmclim(as); } } } @@ -1206,6 +1228,7 @@ static void asm_phi_copyspill(ASMState *as) if (ra_hasspill(irl->s) && irt_isfp(ir->t)) { emit_spstore(as, irl, r, sps_scale(irl->s)); emit_spload(as, ir, r, sps_scale(ir->s)); + checkmclim(as); } } } @@ -1822,6 +1845,9 @@ void lj_asm_trace(jit_State *J, GCtrace *T) do { as->mcp = as->mctop; +#ifdef LUA_USE_ASSERT + as->mcp_prev = as->mcp; +#endif as->curins = T->nins; RA_DBG_START(); RA_DBGX((as, "===== STOP =====")); diff --git a/src/lj_asm_mips.h b/src/lj_asm_mips.h index e80f7582..7d1a8c68 100644 --- a/src/lj_asm_mips.h +++ b/src/lj_asm_mips.h @@ -283,6 +283,7 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args) else ofs += 4; } + checkmclim(as); } } diff --git a/src/lj_asm_ppc.h b/src/lj_asm_ppc.h index 7637f6a6..34bd721f 100644 --- a/src/lj_asm_ppc.h +++ b/src/lj_asm_ppc.h @@ -286,6 +286,7 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args) else ofs += 4; } + checkmclim(as); } if ((ci->flags & CCI_VARARG)) /* Vararg calls need to know about FPR use. */ emit_tab(as, fpr == REGARG_FIRSTFPR ? PPCI_CRXOR : PPCI_CREQV, 6, 6, 6); diff --git a/src/lj_asm_x86.h b/src/lj_asm_x86.h index 28aa2791..8bae1789 100644 --- a/src/lj_asm_x86.h +++ b/src/lj_asm_x86.h @@ -512,6 +512,7 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args) } ofs += sizeof(intptr_t); } + checkmclim(as); } #if LJ_64 && !LJ_ABI_WIN if (patchnfpr) *patchnfpr = fpr - REGARG_FIRSTFPR;