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;
  });
}