From bbec2d4760f6e3823935777ceb46ea7aeddf7341 Mon Sep 17 00:00:00 2001 From: Demi Obenour Date: Sat, 1 Apr 2017 12:04:13 -0400 Subject: [PATCH] JIT-compile bitfield stores MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit implements compilation of bitfield stores. The generated IR is not good – in fact, it’s downright terrible – but it is certainly a big improvement over these operations being banished to the interpreter. --- src/lj_crecord.c | 63 ++++++++++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/src/lj_crecord.c b/src/lj_crecord.c index ed117612..4a3ba31b 100644 --- a/src/lj_crecord.c +++ b/src/lj_crecord.c @@ -401,8 +401,20 @@ static int crec_isnonzero(CType *s, void *p) } } -static TRef crec_ct_ct(jit_State *J, CType *d, CType *s, TRef dp, TRef sp, - void *svisnz) +/* Load a C type from a bitfield ------------------------------------------ */ +static TRef crec_bitfield_load(jit_State *J, CTypeID sid, TRef tr) { + uint32_t pos = ctype_bitpos(sid); + uint32_t bsz = ctype_bitbsz(sid); + CTSize shift = 32 - bsz; + lua_assert(ctype_isbitfield(sid)); + lua_assert(bsz > 0 && "Zero sized bitfield is invalid"); + tr = emitir(IRT(IR_BSHL, IRT_INT), tr, lj_ir_kint(J, shift - pos)); + return emitir(IRT(IR_BSHR, IRT_INT), tr, lj_ir_kint(J, shift)); + /* if crosses container boundary: interpreter will throw */ +} + +static TRef crec_ct_ct(jit_State *J, CType *d, CTypeID bitfield_val, + CType *s, TRef dp, TRef sp, void *svisnz) { IRType dt = crec_ct2irt(ctype_ctsG(J2G(J)), d); IRType st = crec_ct2irt(ctype_ctsG(J2G(J)), s); @@ -449,6 +461,23 @@ static TRef crec_ct_ct(jit_State *J, CType *d, CType *s, TRef dp, TRef sp, else if (st == IRT_INT) sp = lj_opt_narrow_toint(J, sp); xstore: + if (bitfield_val) { + CTSize bsz, pos; + TRef target; + CTSize shift; + TRef k, loaded; + lua_assert(ctype_isbitfield(bitfield_val)); + bsz = ctype_bitbsz(bitfield_val); + pos = ctype_bitpos(bitfield_val); + k = lj_ir_kint(J, 8*pos); + target = emitir(IRT(IR_XLOAD, IRT_INT), dp, k); + shift = ~(((uint32_t)-1 >> (32 - bsz)) << pos); + lua_assert(bsz && "Zero sized bitfield is invalid!"); + loaded = emitir(IRT(IR_BAND, IRT_INT), target, lj_ir_kint(J, shift)); + sp = emitir(IRT(IR_BSHL, IRT_INT), sp, lj_ir_kint(J, pos)); + sp = emitir(IRT(IR_BAND, IRT_INT), sp, lj_ir_kint(J, ~shift)); + sp = emitir(IRT(IR_BOR, IRT_INT), sp, loaded); + } if (dt == IRT_I64 || dt == IRT_U64) lj_needsplit(J); if (dp == 0) return sp; emitir(IRT(IR_XSTORE, dt), dp, sp); @@ -558,22 +587,6 @@ static TRef crec_ct_ct(jit_State *J, CType *d, CType *s, TRef dp, TRef sp, return 0; } -/* Load a C type from a bitfield ------------------------------------------ */ -static TRef crec_bitfield_load(jit_State *J, CTypeID sid, TRef tr) { - uint32_t pos = ctype_bitpos(sid); - uint32_t bsz = ctype_bitbsz(sid); - lua_assert(ctype_isbitfield(sid)); - lua_assert(bsz > 0 && "Zero sized bitfield is invalid"); - if (!(sid & CTF_BOOL)) { - CTSize shift = 32 - bsz; - tr = emitir(IRT(IR_BSHL, IRT_INT), tr, lj_ir_kint(J, shift - pos)); - return emitir(IRT(IR_BSHR, IRT_INT), tr, lj_ir_kint(J, shift)); - /* if crosses container boundary: interpreter will throw */ - } else { - lj_trace_err(J, LJ_TRERR_NYICONV); - } -} - /* -- Convert C type to TValue (load) ------------------------------------- */ static TRef crec_tv_ct(jit_State *J, CType *s, CTypeID sid, TRef sp) @@ -633,8 +646,8 @@ boolfield: } /* -- Convert TValue to C type (store) ------------------------------------ */ - -static TRef crec_ct_tv(jit_State *J, CType *d, TRef dp, TRef sp, cTValue *sval) +static TRef crec_ct_tv_(jit_State *J, CType *d, CTypeID bitfield_val, TRef dp, + TRef sp, cTValue *sval) { CTState *cts = ctype_ctsG(J2G(J)); CTypeID sid = CTID_P_VOID; @@ -725,7 +738,11 @@ static TRef crec_ct_tv(jit_State *J, CType *d, TRef dp, TRef sp, cTValue *sval) s = ctype_get(cts, sid); doconv: if (ctype_isenum(d->info)) d = ctype_child(cts, d); - return crec_ct_ct(J, d, s, dp, sp, svisnz); + return crec_ct_ct(J, d, bitfield_val, s, dp, sp, svisnz); +} + +static TRef crec_ct_tv(jit_State *J, CType *d, TRef dp, TRef sp, cTValue *sval) { + return crec_ct_tv_(J, d, 0, dp, sp, sval); } /* -- C data metamethods -------------------------------------------------- */ @@ -876,8 +893,6 @@ again: J->base[0] = lj_ir_kint(J, (int32_t)fct->size); return; /* Interpreter will throw for newindex. */ } else if (ctype_isbitfield(fct->info)) { - if (rd->data != 0) - lj_trace_err(J, LJ_TRERR_NYICONV); isbitfield = 1; bitfield_val = fct->info; sid = ctype_underlying_type(bitfield_val); @@ -930,7 +945,7 @@ again: } else { /* __newindex metamethod. */ rd->nres = 0; J->needsnap = 1; - crec_ct_tv(J, ct, ptr, J->base[2], &rd->argv[2]); + crec_ct_tv_(J, ct, bitfield_val, ptr, J->base[2], &rd->argv[2]); } }