RegionDescPtr selectRegion(const RegionContext& context, TransKind kind) { auto const mode = regionMode(); FTRACE(1, "Select region: mode={} context:\n{}", static_cast<int>(mode), show(context) ); auto region = [&]{ try { switch (mode) { case RegionMode::None: return RegionDescPtr{nullptr}; case RegionMode::Method: return selectMethod(context); case RegionMode::Tracelet: return selectTracelet(context, kind == TransKind::Profile); } not_reached(); } catch (const std::exception& e) { FTRACE(1, "region selector threw: {}\n", e.what()); return RegionDescPtr{nullptr}; } }(); if (region) { FTRACE(3, "{}", show(*region)); always_assert(region->instrSize() <= RuntimeOption::EvalJitMaxRegionInstrs); } else { FTRACE(1, "no region selectable; using tracelet compiler\n"); } return region; }
RegionDescPtr selectRegion(const RegionContext& context, const Transl::Tracelet* t) { auto const mode = regionMode(); FTRACE(1, "Select region: mode={} context:\n{}", static_cast<int>(mode), show(context) ); auto region = [&] { try { switch (mode) { case RegionMode::None: return RegionDescPtr{nullptr}; case RegionMode::OneBC: return selectOneBC(context); case RegionMode::Method: return selectMethod(context); case RegionMode::Tracelet: return selectTracelet(context, 0); case RegionMode::Legacy: always_assert(t); return selectTraceletLegacy(*t); case RegionMode::HotBlock: case RegionMode::HotTrace: always_assert(0 && "unsupported region mode"); } not_reached(); } catch (const std::exception& e) { FTRACE(1, "region selector threw: {}\n", e.what()); return RegionDescPtr{nullptr}; } }(); if (region) { FTRACE(3, "{}", show(*region)); } else { FTRACE(1, "no region selectable; using tracelet compiler\n"); } return region; }
bool RegionFormer::tryInline(uint32_t& instrSize) { assertx(m_inst.source == m_sk); assertx(m_inst.func() == curFunc()); assertx(m_sk.resumed() == resumed()); instrSize = 0; if (!m_inl.canInlineAt(m_inst.source, m_inst.funcd, *m_region)) { return false; } auto refuse = [this](const std::string& str) { FTRACE(2, "selectTracelet not inlining {}: {}\n", m_inst.toString(), str); return false; }; auto callee = m_inst.funcd; // Make sure the FPushOp wasn't interpreted. if (m_irgs.fpiStack.empty()) { return refuse("fpistack empty; fpush was in a different region"); } auto spillFrame = m_irgs.fpiStack.top().spillFrame; if (!spillFrame) { return refuse("couldn't find SpillFrame for FPushOp"); } auto numArgs = m_inst.imm[0].u_IVA; auto numParams = callee->numParams(); // Set up the region context, mapping stack slots in the caller to locals in // the callee. RegionContext ctx; ctx.func = callee; ctx.bcOffset = callee->getEntryForNumArgs(numArgs); ctx.spOffset = FPInvOffset{safe_cast<int32_t>(callee->numSlotsInFrame())}; ctx.resumed = false; for (int i = 0; i < numArgs; ++i) { auto type = irgen::publicTopType(m_irgs, BCSPOffset{i}); uint32_t paramIdx = numArgs - 1 - i; ctx.liveTypes.push_back({RegionDesc::Location::Local{paramIdx}, type}); } for (unsigned i = numArgs; i < numParams; ++i) { // These locals will be populated by DV init funclets but they'll start // out as Uninit. ctx.liveTypes.push_back({RegionDesc::Location::Local{i}, TUninit}); } FTRACE(1, "selectTracelet analyzing callee {} with context:\n{}", callee->fullName()->data(), show(ctx)); auto region = selectTracelet(ctx, m_profiling, false /* noinline */); if (!region) { return refuse("failed to select region in callee"); } instrSize = region->instrSize(); auto newInstrSize = instrSize + m_numBCInstrs + m_pendingInlinedInstrs; if (newInstrSize > RuntimeOption::EvalJitMaxRegionInstrs) { return refuse("new region would be too large"); } if (!m_inl.shouldInline(callee, *region)) { return refuse("shouldIRInline failed"); } return true; }