コード例 #1
0
ファイル: srcdb.cpp プロジェクト: DoomCircus/hhvm
void SrcRec::replaceOldTranslations() {
  // Everyone needs to give up on old translations; send them to the anchor,
  // which is a REQ_RETRANSLATE.
  m_translations.clear();
  m_tailFallbackJumps.clear();
  m_topTranslation.store(nullptr, std::memory_order_release);

  /*
   * It may seem a little weird that we're about to point every
   * incoming branch at the anchor, since that's going to just
   * unconditionally retranslate this SrcKey and never patch the
   * incoming branch to do something else.
   *
   * The reason this is ok is this mechanism is only used in
   * non-RepoAuthoritative mode, and the granularity of code
   * invalidation there is such that we'll only have incoming branches
   * like this basically within the same file since we don't have
   * whole program analysis.
   *
   * This means all these incoming branches are about to go away
   * anyway ...
   *
   * If we ever change that we'll have to change this to patch to
   * some sort of rebind requests.
   */
  assert(!RuntimeOption::RepoAuthoritative || RuntimeOption::EvalJitPGO);
  patchIncomingBranches(m_anchorTranslation);
}
コード例 #2
0
ファイル: srcdb.cpp プロジェクト: Bathrisyah/hiphop-php
void SrcRec::replaceOldTranslations(Asm& a, Asm& astubs) {
  // Everyone needs to give up on old translations; send them to the anchor,
  // which is a REQ_RETRANSLATE
  m_translations.clear();
  m_tailFallbackJumps.clear();
  atomic_release_store(&m_topTranslation, static_cast<TCA>(0));
  patchIncomingBranches(a, astubs, m_anchorTranslation);
}
コード例 #3
0
ファイル: srcdb.cpp プロジェクト: shantanusharma/hhvm
void SrcRec::addDebuggerGuard(TCA dbgGuard, TCA dbgBranchGuardSrc) {
  assertx(!m_dbgBranchGuardSrc);

  TRACE(1, "SrcRec(%p)::addDebuggerGuard @%p, "
        "%zd incoming branches to rechain\n",
        this, dbgGuard, m_incomingBranches.size());

  patchIncomingBranches(dbgGuard);

  // Set m_dbgBranchGuardSrc after patching, so we don't try to patch
  // the debug guard.
  m_dbgBranchGuardSrc = dbgBranchGuardSrc;
  m_topTranslation = dbgGuard;
}
コード例 #4
0
ファイル: srcdb.cpp プロジェクト: Bathrisyah/hiphop-php
void SrcRec::addDebuggerGuard(Asm& a, Asm &astubs, TCA dbgGuard,
                              TCA dbgBranchGuardSrc) {
  ASSERT(!m_dbgBranchGuardSrc);

  TRACE(1, "SrcRec(%p)::addDebuggerGuard @%p, "
        "%zd incoming branches to rechain\n",
        this, dbgGuard, m_incomingBranches.size());

  patchIncomingBranches(a, astubs, dbgGuard);

  // Set m_dbgBranchGuardSrc after patching, so we don't try to patch
  // the debug guard.
  m_dbgBranchGuardSrc = dbgBranchGuardSrc;
  atomic_release_store(&m_topTranslation, dbgGuard);
}
コード例 #5
0
ファイル: srcdb.cpp プロジェクト: hchaog/hhvm
void SrcRec::replaceOldTranslations() {
  // Everyone needs to give up on old translations; send them to the anchor,
  // which is a REQ_RETRANSLATE.
  auto translations = std::move(m_translations);
  m_tailFallbackJumps.clear();
  m_topTranslation = nullptr;

  /*
   * It may seem a little weird that we're about to point every
   * incoming branch at the anchor, since that's going to just
   * unconditionally retranslate this SrcKey and never patch the
   * incoming branch to do something else.
   *
   * The reason this is ok is this mechanism is only used in
   * non-RepoAuthoritative mode, and the granularity of code
   * invalidation there is such that we'll only have incoming branches
   * like this basically within the same file since we don't have
   * whole program analysis.
   *
   * This means all these incoming branches are about to go away
   * anyway ...
   *
   * If we ever change that we'll have to change this to patch to
   * some sort of rebind requests.
   */
  assertx(!RuntimeOption::RepoAuthoritative || RuntimeOption::EvalJitPGO);
  patchIncomingBranches(m_anchorTranslation);

  // Now that we've smashed all the IBs for these translations they should be
  // unreachable-- to prevent a race we treadmill here and then reclaim their
  // associated TC space
  if (RuntimeOption::EvalEnableReusableTC) {
    auto trans = folly::makeMoveWrapper(std::move(translations));
    Treadmill::enqueue([trans]() mutable {
      for (auto& loc : *trans) {
        reclaimTranslation(loc);
      }
      trans->clear();
    });
    return;
  }

  translations.clear();
}
コード例 #6
0
ファイル: srcdb.cpp プロジェクト: shantanusharma/hhvm
void SrcRec::newTranslation(TransLoc loc,
                            GrowableVector<IncomingBranch>& tailBranches) {
  // When translation punts due to hitting limit, will generate one
  // more translation that will call the interpreter.
  assertx(m_translations.size() <=
          std::max(RuntimeOption::EvalJitMaxProfileTranslations,
                   RuntimeOption::EvalJitMaxTranslations));

  TRACE(1, "SrcRec(%p)::newTranslation @%p, ", this, loc.mainStart());

  m_translations.push_back(loc);
  if (!m_topTranslation.get()) {
    m_topTranslation = loc.mainStart();
    patchIncomingBranches(loc.mainStart());
  }

  /*
   * Link all the jumps from the current tail translation to this new
   * guy.
   *
   * It's (mostly) ok if someone is running in this code while we do
   * this: we hold the write lease, they'll instead jump to the anchor
   * and do REQ_RETRANSLATE and failing to get the write lease they'll
   * interp.  FIXME: Unfortunately, right now, in an unlikely race
   * another thread could create another translation with the same
   * type specialization that we just created in this case.  (If we
   * happen to release the write lease after they jump but before they
   * get into REQ_RETRANSLATE, they'll acquire it and generate a
   * translation possibly for this same situation.)
   */
  for (auto& br : m_tailFallbackJumps) {
    br.patch(loc.mainStart());
  }

  // This is the new tail translation, so store the fallback jump list
  // in case we translate this again.
  m_tailFallbackJumps.swap(tailBranches);
}
コード例 #7
0
ファイル: srcdb.cpp プロジェクト: Bathrisyah/hiphop-php
void SrcRec::newTranslation(Asm& a, Asm &astubs, TCA newStart) {
  // When translation punts due to hitting limit, will generate one
  // more translation that will call the interpreter.
  ASSERT(m_translations.size() <= kMaxTranslations);

  TRACE(1, "SrcRec(%p)::newTranslation @%p, ", this, newStart);

  m_translations.push_back(newStart);
  if (!m_topTranslation) {
    atomic_release_store(&m_topTranslation, newStart);
    patchIncomingBranches(a, astubs, newStart);
  }

  /*
   * Link all the jumps from the current tail translation to this new
   * guy.
   *
   * It's (mostly) ok if someone is running in this code while we do
   * this: we hold the write lease, they'll instead jump to the anchor
   * and do REQ_RETRANSLATE and failing to get the write lease they'll
   * interp.  FIXME: Unfortunately, right now, in an unlikely race
   * another thread could create another translation with the same
   * type specialization that we just created in this case.  (If we
   * happen to release the write lease after they jump but before they
   * get into REQ_RETRANSLATE, they'll acquire it and generate a
   * translation possibly for this same situation.)
   */
  for (size_t i = 0; i < m_tailFallbackJumps.size(); ++i) {
    Asm& as = Asm::Choose(a, astubs, m_tailFallbackJumps[i].m_src);
    patch(&as, m_tailFallbackJumps[i], newStart);
  }

  // This is the new tail translation, so store the fallback jump list
  // in case we translate this again.
  m_tailFallbackJumps.swap(m_inProgressTailJumps);
  m_inProgressTailJumps.clear();
}