TransCFG::TransCFG(FuncId funcId, const ProfData* profData, const SrcDB& srcDB, const TcaTransIDMap& jmpToTransID) { assertx(profData); // add nodes for (auto tid : profData->funcProfTransIDs(funcId)) { assertx(profData->transRegion(tid) != nullptr); // This will skip DV Funclets if they were already // retranslated w/ the prologues: if (!profData->optimized(profData->transSrcKey(tid))) { int64_t weight = profData->absTransCounter(tid); addNode(tid, weight); } } // add arcs for (TransID dstId : nodes()) { SrcKey dstSK = profData->transSrcKey(dstId); RegionDesc::BlockPtr dstBlock = profData->transRegion(dstId)->entry(); FTRACE(5, "TransCFG: adding incoming arcs in dstId = {}\n", dstId); TransIDSet predIDs = findPredTrans(dstId, profData, srcDB, jmpToTransID); for (auto predId : predIDs) { if (hasNode(predId)) { auto predPostConds = profData->transRegion(predId)->blocks().back()->postConds(); SrcKey predSK = profData->transSrcKey(predId); if (preCondsAreSatisfied(dstBlock, predPostConds) && predSK.resumed() == dstSK.resumed()) { FTRACE(5, "TransCFG: adding arc {} -> {} ({} -> {})\n", predId, dstId, showShort(predSK), showShort(dstSK)); addArc(predId, dstId, TransCFG::Arc::kUnknownWeight); } } } } // infer arc weights bool changed; do { changed = false; for (TransID tid : nodes()) { int64_t nodeWeight = weight(tid); if (inferredArcWeight(inArcs(tid), nodeWeight)) changed = true; if (inferredArcWeight(outArcs(tid), nodeWeight)) changed = true; } } while (changed); // guess weight for non-inferred arcs for (TransID tid : nodes()) { for (auto arc : outArcs(tid)) { if (arc->weight() == Arc::kUnknownWeight) { arc->setGuessed(); int64_t arcWgt = std::min(weight(arc->src()), weight(arc->dst())) / 2; arc->setWeight(arcWgt); } } } }
Block* findMainExitBlock(const IRUnit& unit, SrcKey lastSk) { Block* mainExit = nullptr; FTRACE(5, "findMainExitBlock: starting on unit:\n{}\n", show(unit)); for (auto block : rpoSortCfg(unit)) { if (endsUnitAtSrcKey(block, lastSk)) { if (mainExit == nullptr) { mainExit = block; continue; } always_assert_flog( mainExit->hint() == Block::Hint::Unlikely || block->hint() == Block::Hint::Unlikely, "findMainExit: 2 likely exits found: B{} and B{}\nlastSk = {}", mainExit->id(), block->id(), showShort(lastSk)); if (mainExit->hint() == Block::Hint::Unlikely) mainExit = block; } } always_assert_flog(mainExit, "findMainExit: no exit found for lastSk = {}", showShort(lastSk)); FTRACE(5, "findMainExitBlock: mainExit = B{}\n", mainExit->id()); return mainExit; }
void RegionDesc::Block::setKnownFunc(SrcKey sk, const Func* func) { FTRACE(2, "Block::setKnownFunc({}, {})\n", showShort(sk), func ? func->fullName()->data() : "nullptr"); assert(m_knownFuncs.find(sk) == m_knownFuncs.end()); assert(contains(sk)); auto it = m_knownFuncs.lower_bound(sk); if (it != m_knownFuncs.begin() && (--it)->second == func) { // Adding func at this sk won't add any new information. FTRACE(2, " func exists at {}, not adding\n", showShort(it->first)); return; } m_knownFuncs.insert(std::make_pair(sk, func)); }
void RegionDesc::Block::setParamByRef(SrcKey sk, bool byRef) { FTRACE(2, "Block::setParamByRef({}, {})\n", showShort(sk), byRef ? "by ref" : "by val"); assertx(m_byRefs.find(sk) == m_byRefs.end()); assertx(contains(sk)); m_byRefs.insert(std::make_pair(sk, byRef)); }
void RegionDesc::Block::setKnownFunc(SrcKey sk, const Func* func) { FTRACE(2, "Block::setKnownFunc({}, {})\n", showShort(sk), func ? func->fullName()->data() : "nullptr"); assertx(m_knownFuncs.find(sk) == m_knownFuncs.end()); assertx(contains(sk)); m_knownFuncs.insert(std::make_pair(sk, func)); }
void dumpEntry(const RingBufferEntry* e) { if (e->m_type == RBTypeUninit) return; std::cerr << folly::format("{:#x} {:10} {:20}", e->m_threadId, e->m_seq, ringbufferName(e->m_type)); switch (e->m_type) { case RBTypeUninit: return; case RBTypeMsg: case RBTypeFuncPrologue: { // The strings in thread-private ring buffers are not null-terminated; // we also can't trust their length, since they might wrap around. auto len = std::min(size_t(e->m_len), strlen(e->m_msg)); // We append our own newline so ignore any newlines in the msg. while (len > 0 && e->m_msg[len - 1] == '\n') --len; fwrite(e->m_msg, len, 1, stderr); fprintf(stderr, "\n"); break; } case RBTypeFuncEntry: case RBTypeFuncExit: { static __thread int indentDepth = 0; // Quick and dirty attempt at dtrace -F style function nesting. // Looks like: // // ... FuncEntry caller // ... FuncEntry callee // ... FuncExit callee // ... FuncExit caller // // Take this indentation with a grain of salt; it's only reliable // within a single thread, and since we still miss some function // entries and exits can get confused. indentDepth -= e->m_type == RBTypeFuncExit; if (indentDepth < 0) indentDepth = 0; std::cerr << folly::format("{}{}\n", std::string(indentDepth * 4, ' '), e->m_msg); indentDepth += e->m_type == RBTypeFuncEntry; break; } default: { std::cerr << folly::format("{:50} {:#16x}\n", showShort(SrcKey::fromAtomicInt(e->m_sk)), e->m_data); break; } } }
Block* findMainExitBlock(const IRUnit& unit, SrcKey lastSk) { bool unreachable = false; Block* mainExit = nullptr; FTRACE(5, "findMainExitBlock: looking for exit at {} in unit:\n{}\n", showShort(lastSk), show(unit)); for (auto block : rpoSortCfg(unit)) { if (block->back().is(Unreachable)) unreachable = true; if (endsUnitAtSrcKey(block, lastSk)) { if (mainExit == nullptr) { mainExit = block; continue; } always_assert_flog( mainExit->hint() == Block::Hint::Unlikely || block->hint() == Block::Hint::Unlikely, "findMainExit: 2 likely exits found: B{} and B{}\nlastSk = {}", mainExit->id(), block->id(), showShort(lastSk) ); if (mainExit->hint() == Block::Hint::Unlikely) mainExit = block; } } always_assert_flog( mainExit || unreachable, "findMainExit: no exit found for lastSk = {}", showShort(lastSk) ); FTRACE(5, "findMainExitBlock: mainExit = B{}\n", mainExit->id()); return mainExit; }
void RegionDesc::Block::addReffinessPred(SrcKey sk, const ReffinessPred& pred) { FTRACE(2, "Block::addReffinessPred({}, {})\n", showShort(sk), show(pred)); assertx(contains(sk)); m_refPreds.insert(std::make_pair(sk, pred)); }
void RegionDesc::Block::addPredicted(SrcKey sk, TypePred pred) { FTRACE(2, "Block::addPredicted({}, {})\n", showShort(sk), show(pred)); assertx(pred.type <= TStkElem); assertx(contains(sk)); m_typePreds.insert(std::make_pair(sk, pred)); }
TransCFG::TransCFG(FuncId funcId, const ProfData* profData, bool inlining /* = false */) { assertx(profData); // add nodes for (auto const tid : profData->funcProfTransIDs(funcId)) { auto const rec = profData->transRec(tid); assertx(rec->region() != nullptr); // This will skip DV Funclets if they were already // retranslated w/ the prologues: if (inlining || !profData->optimized(rec->srcKey())) { int64_t weight = profData->transCounter(tid); addNode(tid, weight); } } // add arcs for (auto const dstId : nodes()) { auto const rec = profData->transRec(dstId); auto const dstSK = rec->srcKey(); auto const dstBlock = rec->region()->entry(); FTRACE(5, "TransCFG: adding incoming arcs in dstId = {}\n", dstId); TransIDSet predIDs = findPredTrans(dstId, profData); for (auto predId : predIDs) { if (hasNode(predId)) { auto const predRec = profData->transRec(predId); auto const predBlock = predRec->region()->blocks().back(); auto const& postConds = predBlock->postConds(); auto predPostConds = postConds.changed; predPostConds.insert(predPostConds.end(), postConds.refined.begin(), postConds.refined.end()); auto const predSK = predRec->srcKey(); if (preCondsAreSatisfied(dstBlock, predPostConds) && predSK.resumed() == dstSK.resumed()) { FTRACE(5, "TransCFG: adding arc {} -> {} ({} -> {})\n", predId, dstId, showShort(predSK), showShort(dstSK)); addArc(predId, dstId, TransCFG::Arc::kUnknownWeight); } } } } // infer arc weights bool changed; do { changed = false; for (auto const tid : nodes()) { auto const nodeWeight = weight(tid); if (inferredArcWeight(inArcs(tid), nodeWeight)) changed = true; if (inferredArcWeight(outArcs(tid), nodeWeight)) changed = true; } } while (changed); // guess weight for non-inferred arcs for (auto const tid : nodes()) { for (auto arc : outArcs(tid)) { if (arc->weight() == Arc::kUnknownWeight) { arc->setGuessed(); auto arcWgt = std::min(weight(arc->src()), weight(arc->dst())) / 2; arc->setWeight(arcWgt); } } } }
void RegionDesc::Block::addPredicted(SrcKey sk, TypePred pred) { FTRACE(2, "Block::addPredicted({}, {})\n", showShort(sk), show(pred)); assert(pred.type.subtypeOf(Type::Gen | Type::Cls)); assert(contains(sk)); m_typePreds.insert(std::make_pair(sk, pred)); }