void annotate(NormalizedInstruction* i) { switch (i->op()) { case Op::FCallD: { auto const fpi = i->func()->findFPI(i->source.offset()); auto const pushOp = i->m_unit->getOpcode(fpi->m_fpushOff); auto const clsName = i->m_unit->lookupLitstrId(i->imm[1].u_SA); auto const funcName = i->m_unit->lookupLitstrId(i->imm[2].u_SA); auto const isStatic = pushOp == Op::FPushClsMethodD || pushOp == Op::FPushClsMethodF || pushOp == Op::FPushClsMethod; /* * Currently we don't attempt any of this for FPushClsMethod * because lookupImmutableMethod is only for situations that * don't involve LSB. */ auto const func = pushOp == Op::FPushClsMethod ? nullptr : lookupDirectFunc(i->source, funcName, clsName, isStatic); if (func) { FTRACE(1, "found direct func ({}) for FCallD\n", func->fullName()->data()); i->funcd = func; } } break; default: break; } }
static void recordActRecPush(const SrcKey sk, const StringData* name, const StringData* clsName, bool staticCall) { auto unit = sk.unit(); FTRACE(2, "annotation: recordActRecPush: {}@{} {}{}{} ({}static)\n", unit->filepath()->data(), sk.offset(), clsName ? clsName->data() : "", clsName ? "::" : "", name, !staticCall ? "non" : ""); SrcKey next(sk); next.advance(unit); const FPIEnt *fpi = sk.func()->findFPI(next.offset()); assert(fpi); assert(name->isStatic()); assert(sk.offset() == fpi->m_fpushOff); auto const fcall = SrcKey { sk.func(), fpi->m_fcallOff, sk.resumed() }; assert(isFCallStar(*reinterpret_cast<const Op*>(unit->at(fcall.offset())))); auto const func = lookupDirectFunc(sk, name, clsName, staticCall); if (func) { recordFunc(fcall, func); } }
void annotate(NormalizedInstruction* i) { switch(i->op()) { case OpFPushObjMethodD: case OpFPushClsMethodD: case OpFPushClsMethodF: case OpFPushCtorD: case OpFPushCtor: case OpFPushFuncD: { if (RuntimeOption::RepoAuthoritative && Repo::global().UsedHHBBC) { break; } // When we push predictable activation records, we can use a simpler // translation for their corresponding FCall. const StringData* className = nullptr; const StringData* funcName = nullptr; if (i->op() == OpFPushFuncD) { funcName = i->m_unit->lookupLitstrId(i->imm[1].u_SA); } else if (i->op() == OpFPushObjMethodD) { if (i->inputs[0]->valueType() != KindOfObject) break; const Class* cls = i->inputs[0]->rtt.valueClass(); if (!cls) break; funcName = i->m_unit->lookupLitstrId(i->imm[1].u_SA); className = cls->name(); } else if (i->op() == OpFPushClsMethodF) { if (!i->inputs[1]->isString() || i->inputs[1]->rtt.valueString() == nullptr || i->inputs[0]->valueType() != KindOfClass) { break; } const Class* cls = i->inputs[0]->rtt.valueClass(); if (!cls) break; funcName = i->inputs[1]->rtt.valueString(); className = cls->name(); } else if (i->op() == OpFPushClsMethodD) { funcName = i->m_unit->lookupLitstrId(i->imm[1].u_SA); className = i->m_unit->lookupLitstrId(i->imm[2].u_SA); } else if (i->op() == OpFPushCtorD) { className = i->m_unit->lookupLitstrId(i->imm[1].u_SA); const Class* cls = Unit::lookupUniqueClass(className); if (!cls) break; auto const ctor = cls->getCtor(); funcName = ctor->name(); className = ctor->cls()->name(); } else { assert(i->op() == OpFPushCtor); const Class* cls = i->inputs[0]->rtt.valueClass(); if (!cls) break; auto const ctor = cls->getCtor(); funcName = ctor->name(); className = ctor->cls()->name(); } assert(funcName->isStatic()); recordActRecPush(i->source, funcName, className, i->op() == OpFPushClsMethodD || i->op() == OpFPushClsMethodF); } break; case OpFCall: case OpFCallArray: { if (RuntimeOption::RepoAuthoritative && Repo::global().UsedHHBBC) { break; } if (auto const func = folly::get_ptr(s_callDB, i->source)) { i->funcd = *func; } } break; default: break; case Op::FCallD: { auto const fpi = i->func()->findFPI(i->source.offset()); auto const pushOp = i->m_unit->getOpcode(fpi->m_fpushOff); auto const clsName = i->m_unit->lookupLitstrId(i->imm[1].u_SA); auto const funcName = i->m_unit->lookupLitstrId(i->imm[2].u_SA); auto const isStatic = pushOp == Op::FPushClsMethodD || pushOp == Op::FPushClsMethodF || pushOp == Op::FPushClsMethod; /* * Currently we don't attempt any of this for FPushClsMethod * because lookupImmutableMethod is only for situations that * don't involve LSB. */ auto const func = pushOp == Op::FPushClsMethod ? nullptr : lookupDirectFunc(i->source, funcName, clsName, isStatic); if (func) { FTRACE(1, "found direct func (%s) for FCallD\n", func->fullName()->data()); i->funcd = func; } break; } } }