void cgGetCtxFwdCallDyn(IRLS& env, const IRInstruction* inst) { implGetCtxFwdCall(env, inst, [&] (Vout& v, Vreg rthis, Vreg dst) { auto const extra = inst->extra<ClsMethodData>(); auto const ch = StaticMethodFCache::alloc( extra->clsName, extra->methodName, ctxName(inst->marker()) ); // The StaticMethodFCache here is guaranteed to already be initialized in // RDS by the pre-conditions of this instruction. auto const sf = v.makeReg(); v << cmplim{1, rvmtl()[ch + offsetof(StaticMethodFCache, m_static)], sf}; return cond(v, CC_E, sf, dst, [&] (Vout& v) { // Load (this->m_cls | 0x1) into `dst'. auto cls = v.makeReg(); auto tmp = v.makeReg(); emitLdObjClass(v, rthis, cls); v << orqi{1, cls, tmp, v.makeReg()}; return tmp; }, [&] (Vout& v) { // Just incref $this. emitIncRef(v, rthis); return rthis; } ); }); }
void emitIncRefWork(Vout& v, Vreg data, Vreg type) { auto const sf = v.makeReg(); emitCmpTVType(v, sf, KindOfRefCountThreshold, type); // ifRefCountType ifThen(v, CC_G, sf, [&] (Vout& v) { auto const sf2 = v.makeReg(); // ifNonStatic v << cmplim{0, data[FAST_REFCOUNT_OFFSET], sf2}; ifThen(v, CC_GE, sf2, [&] (Vout& v) { emitIncRef(v, data); }); }); }
void cgGetCtxFwdCall(IRLS& env, const IRInstruction* inst) { implGetCtxFwdCall(env, inst, [&] (Vout& v, Vreg rthis, Vreg dst) { auto const callee = inst->src(1)->funcVal(); if (callee->isStatic()) { // Load (this->m_cls | 0x1) into `dst'. auto const cls = v.makeReg(); emitLdObjClass(v, rthis, cls); v << orqi{1, cls, dst, v.makeReg()}; } else { // Just incref $this. emitIncRef(v, rthis); v << copy{rthis, dst}; } return dst; }); }