Inline-Lua
view release on metacpan or search on metacpan
ffi/target/release/build/mlua-sys-6a99a2ae50f12319/out/luajit-build/build/src/lj_asm_x86.h view on Meta::CPAN
/* Inlined hash lookup. Specialized for key type and for const keys.
** The equivalent C code is:
** Node *n = hashkey(t, key);
** do {
** if (lj_obj_equal(&n->key, key)) return &n->val;
** } while ((n = nextnode(n)));
** return niltv(L);
*/
static void asm_href(ASMState *as, IRIns *ir, IROp merge)
{
RegSet allow = RSET_GPR;
int destused = ra_used(ir);
Reg dest = ra_dest(as, ir, allow);
Reg tab = ra_alloc1(as, ir->op1, rset_clear(allow, dest));
Reg key = RID_NONE, tmp = RID_NONE;
IRIns *irkey = IR(ir->op2);
int isk = irref_isk(ir->op2);
IRType1 kt = irkey->t;
uint32_t khash;
MCLabel l_end, l_loop, l_next;
if (!isk) {
rset_clear(allow, tab);
key = ra_alloc1(as, ir->op2, irt_isnum(kt) ? RSET_FPR : allow);
if (LJ_GC64 || !irt_isstr(kt))
tmp = ra_scratch(as, rset_exclude(allow, key));
}
/* Key not found in chain: jump to exit (if merged) or load niltv. */
l_end = emit_label(as);
if (merge == IR_NE)
asm_guardcc(as, CC_E); /* XI_JMP is not found by lj_asm_patchexit. */
else if (destused)
emit_loada(as, dest, niltvg(J2G(as->J)));
/* Follow hash chain until the end. */
l_loop = emit_sjcc_label(as, CC_NZ);
emit_rr(as, XO_TEST, dest|REX_GC64, dest);
emit_rmro(as, XO_MOV, dest|REX_GC64, dest, offsetof(Node, next));
l_next = emit_label(as);
/* Type and value comparison. */
if (merge == IR_EQ)
asm_guardcc(as, CC_E);
else
emit_sjcc(as, CC_E, l_end);
checkmclim(as);
if (irt_isnum(kt)) {
if (isk) {
/* Assumes -0.0 is already canonicalized to +0.0. */
emit_gmroi(as, XG_ARITHi(XOg_CMP), dest, offsetof(Node, key.u32.lo),
(int32_t)ir_knum(irkey)->u32.lo);
emit_sjcc(as, CC_NE, l_next);
emit_gmroi(as, XG_ARITHi(XOg_CMP), dest, offsetof(Node, key.u32.hi),
(int32_t)ir_knum(irkey)->u32.hi);
} else {
emit_sjcc(as, CC_P, l_next);
emit_rmro(as, XO_UCOMISD, key, dest, offsetof(Node, key.n));
emit_sjcc(as, CC_AE, l_next);
/* The type check avoids NaN penalties and complaints from Valgrind. */
#if LJ_64 && !LJ_GC64
emit_u32(as, LJ_TISNUM);
emit_rmro(as, XO_ARITHi, XOg_CMP, dest, offsetof(Node, key.it));
#else
emit_i8(as, LJ_TISNUM);
emit_rmro(as, XO_ARITHi8, XOg_CMP, dest, offsetof(Node, key.it));
#endif
}
#if LJ_64 && !LJ_GC64
} else if (irt_islightud(kt)) {
emit_rmro(as, XO_CMP, key|REX_64, dest, offsetof(Node, key.u64));
#endif
#if LJ_GC64
} else if (irt_isaddr(kt)) {
if (isk) {
TValue k;
k.u64 = ((uint64_t)irt_toitype(irkey->t) << 47) | irkey[1].tv.u64;
emit_gmroi(as, XG_ARITHi(XOg_CMP), dest, offsetof(Node, key.u32.lo),
k.u32.lo);
emit_sjcc(as, CC_NE, l_next);
emit_gmroi(as, XG_ARITHi(XOg_CMP), dest, offsetof(Node, key.u32.hi),
k.u32.hi);
} else {
emit_rmro(as, XO_CMP, tmp|REX_64, dest, offsetof(Node, key.u64));
}
} else {
lj_assertA(irt_ispri(kt) && !irt_isnil(kt), "bad HREF key type");
emit_u32(as, (irt_toitype(kt)<<15)|0x7fff);
emit_rmro(as, XO_ARITHi, XOg_CMP, dest, offsetof(Node, key.it));
#else
} else {
if (!irt_ispri(kt)) {
lj_assertA(irt_isaddr(kt), "bad HREF key type");
if (isk)
emit_gmroi(as, XG_ARITHi(XOg_CMP), dest, offsetof(Node, key.gcr),
ptr2addr(ir_kgc(irkey)));
else
emit_rmro(as, XO_CMP, key, dest, offsetof(Node, key.gcr));
emit_sjcc(as, CC_NE, l_next);
}
lj_assertA(!irt_isnil(kt), "bad HREF key type");
emit_i8(as, irt_toitype(kt));
emit_rmro(as, XO_ARITHi8, XOg_CMP, dest, offsetof(Node, key.it));
#endif
}
emit_sfixup(as, l_loop);
#if LJ_GC64
if (!isk && irt_isaddr(kt)) {
emit_rr(as, XO_OR, tmp|REX_64, key);
emit_loadu64(as, tmp, (uint64_t)irt_toitype(kt) << 47);
}
#endif
/* Load main position relative to tab->node into dest. */
khash = isk ? ir_khash(as, irkey) : 1;
if (khash == 0) {
emit_rmro(as, XO_MOV, dest|REX_GC64, tab, offsetof(GCtab, node));
} else {
emit_rmro(as, XO_ARITH(XOg_ADD), dest|REX_GC64, tab, offsetof(GCtab,node));
emit_shifti(as, XOg_SHL, dest, 3);
( run in 1.107 second using v1.01-cache-2.11-cpan-ceb78f64989 )