TCA emitFuncBodyDispatch(Func* func, const DVFuncletsVec& dvs) { auto codeLock = lockCode(); auto metaLock = lockMetadata(); auto const& view = code().view(); auto const tca = genFuncBodyDispatch(func, dvs, view); func->setFuncBody(tca); if (!RuntimeOption::EvalJitNoGdb) { Debug::DebugInfo::Get()->recordStub( Debug::TCRange(tca, view.main().frontier(), false), Debug::lookupFunction(func, false, false, true)); } if (RuntimeOption::EvalJitUseVtuneAPI) { reportHelperToVtune(func->fullName()->data(), tca, view.main().frontier()); } if (RuntimeOption::EvalPerfPidMap) { Debug::DebugInfo::Get()->recordPerfMap( Debug::TCRange(tca, view.main().frontier(), false), SrcKey{}, func, false, false); } return tca; }
void processInit() { auto codeLock = lockCode(); auto metaLock = lockMetadata(); s_code = new CodeCache(); s_ustubs.emitAll(*s_code, *Debug::DebugInfo::Get()); // Write an .eh_frame section that covers the whole TC. initUnwinder(s_code->base(), s_code->codeSize()); }
void freeTCStub(TCA stub) { // We need to lock the code because s_freeStubs.push() writes to the stub and // the metadata to protect s_freeStubs itself. auto codeLock = lockCode(); auto metaLock = lockMetadata(); assertx(code().frozen().contains(stub)); Debug::DebugInfo::Get()->recordRelocMap(stub, 0, "FreeStub"); markStubFreed(stub); }
void processInit() { auto codeLock = lockCode(); auto metaLock = lockMetadata(); g_code = new(low_malloc_data(sizeof(CodeCache))) CodeCache(); g_ustubs.emitAll(*g_code, *Debug::DebugInfo::Get()); // Write an .eh_frame section that covers the whole TC. initUnwinder(g_code->base(), g_code->codeSize()); Disasm::ExcludedAddressRange(g_code->base(), g_code->codeSize()); }
void bindCall(TCA toSmash, TCA start, Func* callee, int nArgs, bool immutable) { auto codeLock = lockCode(); if (!start || smashableCallTarget(toSmash) == start) return; assertx(smashableCallTarget(toSmash)); TRACE(2, "bindCall smash %p -> %p\n", toSmash, start); smashCall(toSmash, start); bool is_profiled = false; // For functions to be PGO'ed, if their current prologues are still // profiling ones (living in code.prof()), then save toSmash as a // caller to the prologue, so that it can later be smashed to call a // new prologue when it's generated. int calleeNumParams = callee->numNonVariadicParams(); int calledPrologNumArgs = (nArgs <= calleeNumParams ? nArgs : calleeNumParams + 1); auto const profData = jit::profData(); if (profData != nullptr && code().prof().contains(start)) { auto rec = profData->prologueTransRec( callee, calledPrologNumArgs ); if (immutable) { rec->addMainCaller(toSmash); } else { rec->addGuardCaller(toSmash); } is_profiled = true; } // We need to be able to reclaim the function prologues once the unit // associated with this function is treadmilled-- so record all of the // callers that will need to be re-smashed // // Additionally for profiled calls we need to remove them from the main // and guard caller maps. if (RuntimeOption::EvalEnableReusableTC) { if (debug || is_profiled || !immutable) { auto metaLock = lockMetadata(); recordFuncCaller(callee, toSmash, immutable, is_profiled, calledPrologNumArgs); } } }
static TCA emitFuncPrologueImpl(Func* func, int argc, TransKind kind) { if (!newTranslation()) { return nullptr; } const int nparams = func->numNonVariadicParams(); const int paramIndex = argc <= nparams ? argc : nparams + 1; auto const funcBody = SrcKey{func, func->getEntryForNumArgs(argc), false}; profileSetHotFuncAttr(); auto codeLock = lockCode(); auto codeView = code().view(kind); TCA mainOrig = codeView.main().frontier(); CGMeta fixups; // If we're close to a cache line boundary, just burn some space to // try to keep the func and its body on fewer total lines. align(codeView.main(), &fixups, Alignment::CacheLineRoundUp, AlignContext::Dead); TransLocMaker maker(codeView); maker.markStart(); // Careful: this isn't necessarily the real entry point. For funcIsMagic // prologues, this is just a possible prologue. TCA aStart = codeView.main().frontier(); // Give the prologue a TransID if we have profiling data. auto const transID = [&]{ if (kind == TransKind::ProfPrologue) { auto const profData = jit::profData(); auto const id = profData->allocTransID(); profData->addTransProfPrologue(id, funcBody, paramIndex); return id; } if (profData() && transdb::enabled()) { return profData()->allocTransID(); } return kInvalidTransID; }(); TCA start = genFuncPrologue(transID, kind, func, argc, codeView, fixups); auto loc = maker.markEnd(); auto metaLock = lockMetadata(); if (RuntimeOption::EvalEnableReusableTC) { TCA UNUSED ms = loc.mainStart(), me = loc.mainEnd(), cs = loc.coldStart(), ce = loc.coldEnd(), fs = loc.frozenStart(), fe = loc.frozenEnd(), oldStart = start; auto const did_relocate = relocateNewTranslation(loc, codeView, fixups, &start); if (did_relocate) { FTRACE_MOD(Trace::reusetc, 1, "Relocated prologue for func {} (id = {}) " "from M[{}, {}], C[{}, {}], F[{}, {}] to M[{}, {}] " "C[{}, {}] F[{}, {}] orig start @ {} new start @ {}\n", func->fullName()->data(), func->getFuncId(), ms, me, cs, ce, fs, fe, loc.mainStart(), loc.mainEnd(), loc.coldStart(), loc.coldEnd(), loc.frozenStart(), loc.frozenEnd(), oldStart, start); } else { FTRACE_MOD(Trace::reusetc, 1, "Created prologue for func {} (id = {}) at " "M[{}, {}], C[{}, {}], F[{}, {}] start @ {}\n", func->fullName()->data(), func->getFuncId(), ms, me, cs, ce, fs, fe, oldStart); } recordFuncPrologue(func, loc); if (loc.mainStart() != aStart) { codeView.main().setFrontier(mainOrig); // we may have shifted to align } } if (RuntimeOption::EvalPerfRelocate) { GrowableVector<IncomingBranch> incomingBranches; recordPerfRelocMap(loc.mainStart(), loc.mainEnd(), loc.coldCodeStart(), loc.coldEnd(), funcBody, paramIndex, incomingBranches, fixups); } fixups.process(nullptr); assertx(funcGuardMatches(funcGuardFromPrologue(start, func), func)); assertx(code().isValidCodeAddress(start)); TRACE(2, "funcPrologue %s(%d) setting prologue %p\n", func->fullName()->data(), argc, start); func->setPrologue(paramIndex, start); assertx(kind == TransKind::LivePrologue || kind == TransKind::ProfPrologue || kind == TransKind::OptPrologue); auto tr = maker.rec(funcBody, transID, kind); transdb::addTranslation(tr); if (RuntimeOption::EvalJitUseVtuneAPI) { reportTraceletToVtune(func->unit(), func, tr); } recordGdbTranslation(funcBody, func, codeView.main(), loc.mainStart(), false, true); recordBCInstr(OpFuncPrologue, loc.mainStart(), loc.mainEnd(), false); return start; }