diff --git a/hphp/runtime/vm/jit/region_selection.cpp b/hphp/runtime/vm/jit/region_selection.cpp index 23736d88b..ea3db1f88 100644 --- a/hphp/runtime/vm/jit/region_selection.cpp +++ b/hphp/runtime/vm/jit/region_selection.cpp @@ -78,6 +78,12 @@ void RegionDesc::Block::addReffinessPred(SrcKey sk, const ReffinessPred& pred) { checkInvariants(); } +void RegionDesc::Block::setKnownFunc(SrcKey sk, const Func* func) { + assert(m_knownFuncs.find(sk) == m_knownFuncs.end()); + m_knownFuncs.insert(std::make_pair(sk, func)); + checkInvariants(); +} + /* * Check invariants on a RegionDesc::Block. * @@ -85,8 +91,8 @@ void RegionDesc::Block::addReffinessPred(SrcKey sk, const ReffinessPred& pred) { * non-fallthrough instructions mid-block and no control flow (not * counting calls as control flow). * - * 2. Each SrcKey in m_typePreds, m_byRefs, and m_refPreds is within the bounds - * of the block. + * 2. Each SrcKey in m_typePreds, m_byRefs, m_refPreds, and m_knownFuncs is + * within the bounds of the block. * * 3. Each local id referred to in the type prediction list is valid. * @@ -146,6 +152,9 @@ void RegionDesc::Block::checkInvariants() const { for (auto& refPred : m_refPreds) { rangeCheck("reffiness prediction", refPred.first); } + for (auto& func : m_knownFuncs) { + rangeCheck("known Func*", func.first); + } } ////////////////////////////////////////////////////////////////////// @@ -160,6 +169,7 @@ RegionDescPtr createRegion(const Transl::Tracelet& tlet) { assert(sk == tlet.m_instrStream.first->source); auto unit = tlet.m_instrStream.first->unit(); + const Func* topFunc = nullptr; Block* curBlock; auto newBlock = [&] { region->blocks.push_back( @@ -173,6 +183,11 @@ RegionDescPtr createRegion(const Transl::Tracelet& tlet) { assert(ni->unit() == unit); curBlock->addInstruction(); + + if (curBlock->length() == 1 || ni->funcd != topFunc) { + topFunc = ni->funcd; + curBlock->setKnownFunc(sk, topFunc); + } if (!ni->noOp && isFPassStar(ni->op())) { curBlock->setParamByRef( sk, ni->preppedByRef ? RegionDesc::ParamByRef::Yes @@ -349,8 +364,11 @@ std::string show(const RegionDesc::Block& b) { auto typePreds = makeMapWalker(b.typePreds()); auto byRefs = makeMapWalker(b.paramByRefs()); auto refPreds = makeMapWalker(b.reffinessPreds()); - + auto knownFuncs= makeMapWalker(b.knownFuncs()); auto skIter = b.start(); + + const Func* currentFunc = nullptr; + for (int i = 0; i < b.length(); ++i) { while (typePreds.hasNext(skIter)) { folly::toAppend(" predict: ", show(typePreds.next()), "\n", &ret); @@ -359,15 +377,27 @@ std::string show(const RegionDesc::Block& b) { folly::toAppend(" predict reffiness: ", show(refPreds.next()), "\n", &ret); } + + std::string knownFunc; + if (knownFuncs.hasNext(skIter)) { + currentFunc = knownFuncs.next(); + } + if (currentFunc) { + knownFunc = folly::format(" (top func: {})", + currentFunc->fullName()->data()).str(); + } + std::string byRef; if (byRefs.hasNext(skIter)) { byRef = folly::format(" (passed {})", show(byRefs.next())).str(); } + folly::toAppend( " ", skIter.offset(), " ", instrToString((Op*)b.unit()->at(skIter.offset()), b.unit()), + knownFunc, byRef, "\n", &ret diff --git a/hphp/runtime/vm/jit/region_selection.h b/hphp/runtime/vm/jit/region_selection.h index 7a914ceb5..e31697f99 100644 --- a/hphp/runtime/vm/jit/region_selection.h +++ b/hphp/runtime/vm/jit/region_selection.h @@ -140,6 +140,7 @@ class RegionDesc::Block { typedef flat_multimap TypePredMap; typedef flat_map ParamByRefMap; typedef flat_multimap RefPredMap; + typedef flat_map KnownFuncMap; public: explicit Block(const Func* func, Offset start, int length) @@ -187,6 +188,12 @@ public: */ void addReffinessPred(SrcKey, const ReffinessPred&); + /* + * Update the statically known Func*. It remains active until another is + * specified, so pass nullptr to indicate that there is no longer a known + * Func*. + */ + void setKnownFunc(SrcKey, const Func*); /* * The following getters return references to the metadata maps holding the @@ -197,6 +204,7 @@ public: const TypePredMap& typePreds() const { return m_typePreds; } const ParamByRefMap& paramByRefs() const { return m_byRefs; } const RefPredMap& reffinessPreds() const { return m_refPreds; } + const KnownFuncMap& knownFuncs() const { return m_knownFuncs; } private: void checkInvariants() const; @@ -208,6 +216,7 @@ private: TypePredMap m_typePreds; ParamByRefMap m_byRefs; RefPredMap m_refPreds; + KnownFuncMap m_knownFuncs; }; ////////////////////////////////////////////////////////////////////// diff --git a/hphp/runtime/vm/jit/translator.cpp b/hphp/runtime/vm/jit/translator.cpp index caa04f141..f493d4350 100644 --- a/hphp/runtime/vm/jit/translator.cpp +++ b/hphp/runtime/vm/jit/translator.cpp @@ -3785,9 +3785,11 @@ Translator::translateRegion(const RegionDesc& region, for (auto const& block : region.blocks) { SrcKey sk = block->start(); - auto typePreds = makeMapWalker(block->typePreds()); - auto byRefs = makeMapWalker(block->paramByRefs()); - auto refPreds = makeMapWalker(block->reffinessPreds()); + const Func* topFunc = nullptr; + auto typePreds = makeMapWalker(block->typePreds()); + auto byRefs = makeMapWalker(block->paramByRefs()); + auto refPreds = makeMapWalker(block->reffinessPreds()); + auto knownFuncs = makeMapWalker(block->knownFuncs()); for (unsigned i = 0; i < block->length(); ++i, sk.advance(block->unit())) { // Emit prediction guards. If this is the first instruction in the @@ -3811,6 +3813,11 @@ Translator::translateRegion(const RegionDesc& region, m_hhbcTrans->guardRefs(pred.arSpOffset, pred.mask, pred.vals); } + // Update the current funcd, if we have a new one. + if (knownFuncs.hasNext(sk)) { + topFunc = knownFuncs.next(); + } + // Create and initialize the instruction. NormalizedInstruction inst; inst.source = sk; @@ -3818,6 +3825,7 @@ Translator::translateRegion(const RegionDesc& region, inst.breaksTracelet = i == block->length() - 1 && block == region.blocks.back(); inst.changesPC = opcodeChangesPC(inst.op()); + inst.funcd = topFunc; populateImmediates(inst); // We can get a more precise output type for interpOne if we know all of @@ -3908,6 +3916,7 @@ Translator::translateRegion(const RegionDesc& region, assert(!typePreds.hasNext()); assert(!byRefs.hasNext()); assert(!refPreds.hasNext()); + assert(!knownFuncs.hasNext()); } traceEnd();