Пример #1
0
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;
}
Пример #2
0
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());
}
Пример #3
0
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);
}
Пример #4
0
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());
}
Пример #5
0
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);
    }
  }
}
Пример #6
0
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;
}