ProfTransRec::ProfTransRec(Offset lastBcOff, SrcKey sk, RegionDescPtr region) : m_kind(TransKind::Profile) , m_lastBcOff(lastBcOff) , m_sk(sk) , m_region(region) { assertx(region != nullptr && !region->empty() && region->start() == sk); }
ProfTransRec::ProfTransRec(TransID id, TransKind kind, Offset lastBcOff, SrcKey sk, RegionDescPtr region) : m_id(id) , m_kind(kind) , m_lastBcOff(lastBcOff) , m_region(region) , m_sk(sk) { assertx(region == nullptr || (!region->empty() && region->start() == sk)); }
/* * Returns the last BC offset in the region that corresponds to the * function where the region starts. This will normally be the offset * of the last instruction in the last block, except if the function * ends with an inlined call. In this case, the offset of the * corresponding FCall* in the function that starts the region is * returned. */ static Offset findLastBcOffset(const RegionDescPtr region) { assert(!region->empty()); auto& blocks = region->blocks(); FuncId startFuncId = blocks[0]->start().getFuncId(); for (int i = blocks.size() - 1; i >= 0; i--) { SrcKey sk = blocks[i]->last(); if (sk.getFuncId() == startFuncId) { return sk.offset(); } } not_reached(); }
RegionDescPtr selectHotRegion(TransID transId, MCGenerator* mcg) { auto const profData = jit::profData(); assertx(profData); auto const& func = *profData->transRec(transId)->func(); FuncId funcId = func.getFuncId(); TransCFG cfg(funcId, profData, mcg->srcDB()); assertx(regionMode() != RegionMode::Method); RegionDescPtr region; HotTransContext ctx; ctx.cfg = &cfg; ctx.profData = profData; ctx.tid = transId; ctx.maxBCInstrs = RuntimeOption::EvalJitMaxRegionInstrs; switch (pgoRegionMode(func)) { case PGORegionMode::Hottrace: region = selectHotTrace(ctx); break; case PGORegionMode::Hotblock: region = selectHotBlock(transId, profData, cfg); break; case PGORegionMode::WholeCFG: case PGORegionMode::HotCFG: region = selectHotCFG(ctx); break; } assertx(region); if (Trace::moduleEnabled(HPHP::Trace::pgo, 5)) { std::string dotFileName = std::string("/tmp/trans-cfg-") + folly::to<std::string>(transId) + ".dot"; std::ofstream outFile(dotFileName); if (outFile.is_open()) { cfg.print(outFile, funcId, profData); outFile.close(); } FTRACE(5, "selectHotRegion: New Translation (file: {}) {}\n", dotFileName, region ? show(*region) : std::string("empty region")); } always_assert(region->instrSize() <= RuntimeOption::EvalJitMaxRegionInstrs); if (region->empty()) return nullptr; return region; }
/** * Add to sets coveredNodes and coveredArcs the cfg arcs that are now * covered given the new region containing the translations in * selectedVec. */ static void markCovered(const TransCFG& cfg, const RegionDescPtr region, const TransIDVec& selectedVec, const TransIDSet heads, TransIDSet& coveredNodes, TransCFG::ArcPtrSet& coveredArcs) { assert(selectedVec.size() > 0); TransID newHead = selectedVec[0]; assert(!region->empty()); assert(newHead == getTransId(region->entry()->id())); // Mark all region's nodes as covered. coveredNodes.insert(selectedVec.begin(), selectedVec.end()); // Mark all incoming arcs into newHead from covered nodes as covered. for (auto arc : cfg.inArcs(newHead)) { TransID src = arc->src(); if (coveredNodes.count(src)) { coveredArcs.insert(arc); } } // Mark all CFG arcs within the region as covered. region->forEachArc([&](RegionDesc::BlockId src, RegionDesc::BlockId dst) { if (!hasTransId(src) || !hasTransId(dst)) return; TransID srcTid = getTransId(src); TransID dstTid = getTransId(dst); assert(cfg.hasArc(srcTid, dstTid)); bool foundArc = false; for (auto arc : cfg.outArcs(srcTid)) { if (arc->dst() == dstTid) { coveredArcs.insert(arc); foundArc = true; } } always_assert(foundArc); }); // Mark all outgoing arcs from the region to a head node as covered. for (auto node : selectedVec) { for (auto arc : cfg.outArcs(node)) { if (heads.count(arc->dst())) { coveredArcs.insert(arc); } } } }
TransRec::TransRec(SrcKey _src, TransID transID, TransKind _kind, TCA _aStart, uint32_t _aLen, TCA _acoldStart, uint32_t _acoldLen, TCA _afrozenStart, uint32_t _afrozenLen, RegionDescPtr region, std::vector<TransBCMapping> _bcMapping, Annotations&& _annotations, bool _hasLoop) : bcMapping(_bcMapping) , annotations(std::move(_annotations)) , funcName(_src.func()->fullName()->data()) , src(_src) , md5(_src.func()->unit()->md5()) , aStart(_aStart) , acoldStart(_acoldStart) , afrozenStart(_afrozenStart) , aLen(_aLen) , acoldLen(_acoldLen) , afrozenLen(_afrozenLen) , bcStart(_src.offset()) , id(transID) , kind(_kind) , hasLoop(_hasLoop) { if (funcName.empty()) funcName = "Pseudo-main"; if (!region) return; assertx(!region->empty()); for (auto& block : region->blocks()) { auto sk = block->start(); blocks.emplace_back(Block{sk.unit()->md5(), sk.offset(), block->last().advanced().offset()}); } auto& firstBlock = *region->blocks().front(); for (auto const& pred : firstBlock.typePreConditions()) { guards.emplace_back(show(pred)); } }
TransRec::TransRec(SrcKey _src, TransKind _kind, TCA _aStart, uint32_t _aLen, TCA _acoldStart, uint32_t _acoldLen, TCA _afrozenStart, uint32_t _afrozenLen, RegionDescPtr region, std::vector<TransBCMapping> _bcMapping, bool _isLLVM) : bcMapping(_bcMapping) , funcName(_src.func()->fullName()->data()) , src(_src) , md5(_src.func()->unit()->md5()) , aStart(_aStart) , acoldStart(_acoldStart) , afrozenStart(_afrozenStart) , aLen(_aLen) , acoldLen(_acoldLen) , afrozenLen(_afrozenLen) , bcStart(_src.offset()) , id(0) , kind(_kind) , isLLVM(_isLLVM) { if (funcName.empty()) funcName = "Pseudo-main"; if (!region) return; assertx(!region->empty()); for (auto& block : region->blocks()) { auto sk = block->start(); blocks.emplace_back(Block{sk.unit()->md5(), sk.offset(), block->last().advanced().offset()}); } auto& firstBlock = *region->blocks().front(); auto guardRange = firstBlock.typePreds().equal_range(firstBlock.start()); for (; guardRange.first != guardRange.second; ++guardRange.first) { guards.emplace_back(show(guardRange.first->second)); } }