Esempio n. 1
0
TransCFG::TransCFG(FuncId funcId,
                   const ProfData* profData,
                   const SrcDB& srcDB,
                   const TcaTransIDMap& jmpToTransID) {
  assertx(profData);

  // add nodes
  for (auto tid : profData->funcProfTransIDs(funcId)) {
    assertx(profData->transRegion(tid) != nullptr);
    // This will skip DV Funclets if they were already
    // retranslated w/ the prologues:
    if (!profData->optimized(profData->transSrcKey(tid))) {
      int64_t weight = profData->absTransCounter(tid);
      addNode(tid, weight);
    }
  }

  // add arcs
  for (TransID dstId : nodes()) {
    SrcKey dstSK = profData->transSrcKey(dstId);
    RegionDesc::BlockPtr dstBlock = profData->transRegion(dstId)->entry();
    FTRACE(5, "TransCFG: adding incoming arcs in dstId = {}\n", dstId);
    TransIDSet predIDs = findPredTrans(dstId, profData, srcDB, jmpToTransID);
    for (auto predId : predIDs) {
      if (hasNode(predId)) {
        auto predPostConds =
          profData->transRegion(predId)->blocks().back()->postConds();
        SrcKey predSK = profData->transSrcKey(predId);
        if (preCondsAreSatisfied(dstBlock, predPostConds) &&
            predSK.resumed() == dstSK.resumed()) {
          FTRACE(5, "TransCFG: adding arc {} -> {} ({} -> {})\n",
                 predId, dstId, showShort(predSK), showShort(dstSK));
          addArc(predId, dstId, TransCFG::Arc::kUnknownWeight);
        }
      }
    }
  }

  // infer arc weights
  bool changed;
  do {
    changed = false;
    for (TransID tid : nodes()) {
      int64_t nodeWeight = weight(tid);
      if (inferredArcWeight(inArcs(tid),  nodeWeight)) changed = true;
      if (inferredArcWeight(outArcs(tid), nodeWeight)) changed = true;
    }
  } while (changed);

  // guess weight for non-inferred arcs
  for (TransID tid : nodes()) {
    for (auto arc : outArcs(tid)) {
      if (arc->weight() == Arc::kUnknownWeight) {
        arc->setGuessed();
        int64_t arcWgt = std::min(weight(arc->src()), weight(arc->dst())) / 2;
        arc->setWeight(arcWgt);
      }
    }
  }
}
Esempio n. 2
0
Block* findMainExitBlock(const IRUnit& unit, SrcKey lastSk) {
  Block* mainExit = nullptr;

  FTRACE(5, "findMainExitBlock: starting on unit:\n{}\n", show(unit));

  for (auto block : rpoSortCfg(unit)) {
    if (endsUnitAtSrcKey(block, lastSk)) {
      if (mainExit == nullptr) {
        mainExit = block;
        continue;
      }

      always_assert_flog(
        mainExit->hint() == Block::Hint::Unlikely ||
        block->hint() == Block::Hint::Unlikely,
        "findMainExit: 2 likely exits found: B{} and B{}\nlastSk = {}",
        mainExit->id(), block->id(), showShort(lastSk));

      if (mainExit->hint() == Block::Hint::Unlikely) mainExit = block;
    }
  }

  always_assert_flog(mainExit, "findMainExit: no exit found for lastSk = {}",
                     showShort(lastSk));

  FTRACE(5, "findMainExitBlock: mainExit = B{}\n", mainExit->id());

  return mainExit;
}
Esempio n. 3
0
void RegionDesc::Block::setKnownFunc(SrcKey sk, const Func* func) {
  FTRACE(2, "Block::setKnownFunc({}, {})\n", showShort(sk),
         func ? func->fullName()->data() : "nullptr");
  assert(m_knownFuncs.find(sk) == m_knownFuncs.end());
  assert(contains(sk));
  auto it = m_knownFuncs.lower_bound(sk);
  if (it != m_knownFuncs.begin() && (--it)->second == func) {
    // Adding func at this sk won't add any new information.
    FTRACE(2, "  func exists at {}, not adding\n", showShort(it->first));
    return;
  }

  m_knownFuncs.insert(std::make_pair(sk, func));
}
Esempio n. 4
0
void RegionDesc::Block::setParamByRef(SrcKey sk, bool byRef) {
  FTRACE(2, "Block::setParamByRef({}, {})\n", showShort(sk),
         byRef ? "by ref" : "by val");
  assertx(m_byRefs.find(sk) == m_byRefs.end());
  assertx(contains(sk));
  m_byRefs.insert(std::make_pair(sk, byRef));
}
Esempio n. 5
0
void RegionDesc::Block::setKnownFunc(SrcKey sk, const Func* func) {
  FTRACE(2, "Block::setKnownFunc({}, {})\n", showShort(sk),
         func ? func->fullName()->data() : "nullptr");
  assertx(m_knownFuncs.find(sk) == m_knownFuncs.end());
  assertx(contains(sk));
  m_knownFuncs.insert(std::make_pair(sk, func));
}
Esempio n. 6
0
void dumpEntry(const RingBufferEntry* e) {
  if (e->m_type == RBTypeUninit) return;

  std::cerr <<
    folly::format("{:#x} {:10} {:20}",
                  e->m_threadId, e->m_seq, ringbufferName(e->m_type));

  switch (e->m_type) {
    case RBTypeUninit: return;
    case RBTypeMsg:
    case RBTypeFuncPrologue: {
      // The strings in thread-private ring buffers are not null-terminated;
      // we also can't trust their length, since they might wrap around.
      auto len = std::min(size_t(e->m_len), strlen(e->m_msg));

      // We append our own newline so ignore any newlines in the msg.
      while (len > 0 && e->m_msg[len - 1] == '\n') --len;
      fwrite(e->m_msg, len, 1, stderr);
      fprintf(stderr, "\n");
      break;
    }
    case RBTypeFuncEntry:
    case RBTypeFuncExit: {
      static __thread int indentDepth = 0;
      // Quick and dirty attempt at dtrace -F style function nesting.
      // Looks like:
      //
      //    ... FuncEntry    caller
      //    ... FuncEntry        callee
      //    ... FuncExit         callee
      //    ... FuncExit     caller
      //
      // Take this indentation with a grain of salt; it's only reliable
      // within a single thread, and since we still miss some function
      // entries and exits can get confused.
      indentDepth -= e->m_type == RBTypeFuncExit;
      if (indentDepth < 0) indentDepth = 0;
      std::cerr << folly::format("{}{}\n",
                                 std::string(indentDepth * 4, ' '), e->m_msg);
      indentDepth += e->m_type == RBTypeFuncEntry;
      break;
    }
    default: {
      std::cerr <<
        folly::format("{:50} {:#16x}\n",
                      showShort(SrcKey::fromAtomicInt(e->m_sk)),
                      e->m_data);
      break;
    }
  }
}
Esempio n. 7
0
Block* findMainExitBlock(const IRUnit& unit, SrcKey lastSk) {
  bool unreachable = false;
  Block* mainExit = nullptr;

  FTRACE(5, "findMainExitBlock: looking for exit at {} in unit:\n{}\n",
         showShort(lastSk), show(unit));

  for (auto block : rpoSortCfg(unit)) {
    if (block->back().is(Unreachable)) unreachable = true;

    if (endsUnitAtSrcKey(block, lastSk)) {
      if (mainExit == nullptr) {
        mainExit = block;
        continue;
      }

      always_assert_flog(
        mainExit->hint() == Block::Hint::Unlikely ||
        block->hint() == Block::Hint::Unlikely,
        "findMainExit: 2 likely exits found: B{} and B{}\nlastSk = {}",
        mainExit->id(), block->id(), showShort(lastSk)
      );

      if (mainExit->hint() == Block::Hint::Unlikely) mainExit = block;
    }
  }

  always_assert_flog(
    mainExit || unreachable,
    "findMainExit: no exit found for lastSk = {}",
    showShort(lastSk)
  );

  FTRACE(5, "findMainExitBlock: mainExit = B{}\n", mainExit->id());

  return mainExit;
}
Esempio n. 8
0
void RegionDesc::Block::addReffinessPred(SrcKey sk, const ReffinessPred& pred) {
  FTRACE(2, "Block::addReffinessPred({}, {})\n", showShort(sk), show(pred));
  assertx(contains(sk));
  m_refPreds.insert(std::make_pair(sk, pred));
}
Esempio n. 9
0
void RegionDesc::Block::addPredicted(SrcKey sk, TypePred pred) {
  FTRACE(2, "Block::addPredicted({}, {})\n", showShort(sk), show(pred));
  assertx(pred.type <= TStkElem);
  assertx(contains(sk));
  m_typePreds.insert(std::make_pair(sk, pred));
}
Esempio n. 10
0
TransCFG::TransCFG(FuncId funcId,
                   const ProfData* profData,
                   bool inlining /* = false */) {
  assertx(profData);

  // add nodes
  for (auto const tid : profData->funcProfTransIDs(funcId)) {
    auto const rec = profData->transRec(tid);
    assertx(rec->region() != nullptr);
    // This will skip DV Funclets if they were already
    // retranslated w/ the prologues:
    if (inlining || !profData->optimized(rec->srcKey())) {
      int64_t weight = profData->transCounter(tid);
      addNode(tid, weight);
    }
  }

  // add arcs
  for (auto const dstId : nodes()) {
    auto const rec = profData->transRec(dstId);
    auto const dstSK = rec->srcKey();
    auto const dstBlock = rec->region()->entry();
    FTRACE(5, "TransCFG: adding incoming arcs in dstId = {}\n", dstId);
    TransIDSet predIDs = findPredTrans(dstId, profData);
    for (auto predId : predIDs) {
      if (hasNode(predId)) {
        auto const predRec = profData->transRec(predId);
        auto const predBlock = predRec->region()->blocks().back();
        auto const& postConds = predBlock->postConds();
        auto predPostConds = postConds.changed;
        predPostConds.insert(predPostConds.end(), postConds.refined.begin(),
                             postConds.refined.end());
        auto const predSK = predRec->srcKey();
        if (preCondsAreSatisfied(dstBlock, predPostConds) &&
            predSK.resumed() == dstSK.resumed()) {
          FTRACE(5, "TransCFG: adding arc {} -> {} ({} -> {})\n",
                 predId, dstId, showShort(predSK), showShort(dstSK));
          addArc(predId, dstId, TransCFG::Arc::kUnknownWeight);
        }
      }
    }
  }

  // infer arc weights
  bool changed;
  do {
    changed = false;
    for (auto const tid : nodes()) {
      auto const nodeWeight = weight(tid);
      if (inferredArcWeight(inArcs(tid),  nodeWeight)) changed = true;
      if (inferredArcWeight(outArcs(tid), nodeWeight)) changed = true;
    }
  } while (changed);

  // guess weight for non-inferred arcs
  for (auto const tid : nodes()) {
    for (auto arc : outArcs(tid)) {
      if (arc->weight() == Arc::kUnknownWeight) {
        arc->setGuessed();
        auto arcWgt = std::min(weight(arc->src()), weight(arc->dst())) / 2;
        arc->setWeight(arcWgt);
      }
    }
  }
}
void RegionDesc::Block::addPredicted(SrcKey sk, TypePred pred) {
    FTRACE(2, "Block::addPredicted({}, {})\n", showShort(sk), show(pred));
    assert(pred.type.subtypeOf(Type::Gen | Type::Cls));
    assert(contains(sk));
    m_typePreds.insert(std::make_pair(sk, pred));
}