From ede73f2226f9403441786887c525b163d4b7150e Mon Sep 17 00:00:00 2001 From: fsfod Date: Tue, 19 Sep 2017 13:57:25 +0100 Subject: [PATCH] Fixed LJ_GC64 builds breaking intrinsic interpreter wrappers in various ways. Fix wrappers truncating GCobj pointers in GC64 mode when loading them from the stack to store output registers in to cdata. Fix the stack for intrinsics not being adjusted correctly in there interpreter wrapper when it uses the RID_DISPATCH register on GC64 because RSET_GPR does not contain it --- src/lj_emit_x86.h | 29 ++++++++++++++++++++++++++--- src/lj_target_x86.h | 3 +++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/lj_emit_x86.h b/src/lj_emit_x86.h index b03b0796..aa6035f9 100644 --- a/src/lj_emit_x86.h +++ b/src/lj_emit_x86.h @@ -759,7 +759,7 @@ static int lj_popcnt(uint32_t i) #define align16(n) ((n + 16) & ~(16 - 1)) static int32_t alignsp(int32_t spadj, RegSet savereg) { - int32_t gprsave = lj_popcnt(savereg & RSET_GPR) * sizeof(intptr_t); + int32_t gprsave = lj_popcnt(savereg & RSET_GPR_DISPATCH) * sizeof(intptr_t); if (NEEDSFP && rset_test(savereg, RID_EBP)) { gprsave -= sizeof(intptr_t); @@ -898,6 +898,29 @@ static Reg intrinsic_scratch(ASMState *as, RegSet allow) return r; } +static void emit_tvload_gco(ASMState *as, Reg base, Reg temp, int32_t ofs) +{ +#if LJ_GC64 + emit_shifti(as, XOg_SHR|REX_64, temp, 17); + + as->mrm.base = base; + as->mrm.idx = RID_NONE; + as->mrm.ofs = ofs; + if ((as->flags & JIT_F_BMI2)) + { + emit_i8(as, 47); + emit_mrm(as, XV_RORX|VEX_64, temp, RID_MRM); + } + else + { + emit_shifti(as, XOg_ROR|REX_64, temp, 47); + emit_mrm(as, XO_MOV, temp|REX_64, RID_MRM); + } +#else + emit_rmro(as, XO_MOV, temp, base, ofs); +#endif +} + static void emit_savegpr(ASMState *as, Reg reg, Reg base, int ofs) { Reg temp, r = reg_rid(reg); @@ -924,7 +947,7 @@ static void emit_savegpr(ASMState *as, Reg reg, Reg base, int ofs) temp = intrinsic_scratch(as, RSET_GPR); /* Save the register into a cdata who's pointer is inside a TValue on the Lua stack */ emit_rmro(as, XO_MOVto, r, temp, sizeof(GCcdata)); - emit_rmro(as, XO_MOV, temp, base, ofs); + emit_tvload_gco(as, base, temp, ofs); } static void emit_loadfpr(ASMState *as, uint32_t reg, Reg base, int ofs) @@ -994,7 +1017,7 @@ static void emit_savefpr(ASMState *as, Reg reg, Reg base, int ofs) /* Save the register into a cdata who's pointer is inside a TValue on the Lua stack */ emit_rmro(as, op, r, temp, sizeof(GCcdata)); - emit_rmro(as, XO_MOV, temp, base, ofs); + emit_tvload_gco(as, base, temp, ofs); } } diff --git a/src/lj_target_x86.h b/src/lj_target_x86.h index 906bbb80..048fe699 100644 --- a/src/lj_target_x86.h +++ b/src/lj_target_x86.h @@ -85,6 +85,9 @@ enum { #define RSET_GPR (RSET_RANGE(RID_MIN_GPR, RID_MAX_GPR) \ - RID2RSET(RID_ESP) \ - LJ_GC64*RID2RSET(RID_DISPATCH)) +#define RSET_GPR_DISPATCH (RSET_RANGE(RID_MIN_GPR, RID_MAX_GPR) \ + - RID2RSET(RID_ESP)) + #define RSET_FPR (RSET_RANGE(RID_MIN_FPR, RID_MAX_FPR)) #define RSET_ALL (RSET_GPR|RSET_FPR) #define RSET_INIT RSET_ALL