void cgFwdCtxStaticCall(IRLS& env, const IRInstruction* inst) {
  auto const dstCtx = dstLoc(env, inst, 0).reg();
  auto const srcCtx = srcLoc(env, inst, 0).reg();
  auto const ty = inst->src(0)->type();

  auto& v = vmain(env);

  auto ctx_from_this =  [] (Vout& v, Vreg rthis, Vreg dst) {
    // Load (this->m_cls | 0x1) into `dst'.
    auto const cls = emitLdObjClass(v, rthis, v.makeReg());
    v << orqi{ActRec::kHasClassBit, cls, dst, v.makeReg()};
    return dst;
  };

  if (ty <= TCctx) {
    v << copy{srcCtx, dstCtx};
  } else if (ty <= TObj) {
    ctx_from_this(v, srcCtx, dstCtx);
  } else {
    // If we don't know whether we have a $this, we need to check dynamically.
    auto const sf = v.makeReg();
    v << testqi{ActRec::kHasClassBit, srcCtx, sf};
    unlikelyCond(v, vcold(env), CC_NZ, sf, dstCtx,
         [&] (Vout& v) { return srcCtx; },
         [&] (Vout& v) { return ctx_from_this(v, srcCtx, v.makeReg()); }
        );
  }
}
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;
      }
    );
  });
}
Exemple #3
0
void cgLdClsCtx(IRLS& env, const IRInstruction* inst) {
  auto dst = dstLoc(env, inst, 0).reg();
  auto ctx = srcLoc(env, inst, 0).reg();
  auto& v = vmain(env);

  auto const sf = v.makeReg();
  v << testqi{ActRec::kHasClassBit, ctx, sf};

  cond(v, CC_NZ, sf, dst,
    [&] (Vout& v) { return emitLdClsCctx(v, ctx, v.makeReg()); }, // Cctx
    [&] (Vout& v) { return emitLdObjClass(v, ctx, v.makeReg()); } // This
  );
}
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;
  });
}
Exemple #5
0
void cgLdObjClass(IRLS& env, const IRInstruction* inst) {
  auto dst = dstLoc(env, inst, 0).reg();
  auto obj = srcLoc(env, inst, 0).reg();
  emitLdObjClass(vmain(env), obj, dst);
}