Beispiel #1
0
TEST(Region, all) {
	::testing::FLAGS_gtest_death_test_style = "threadsafe";

    RegionDB    region_db;
    region_db.add_region(0,".nothing_bc", 0);
    region_db.add_region(1,"nothing_bulk", 0);

    {
    Region r=region_db.add_region(1001,".top", 2);
    EXPECT_EQ(2, r.idx() );
    EXPECT_TRUE( r.is_boundary() );
    EXPECT_EQ(1, r.boundary_idx() );
    EXPECT_TRUE( r.is_valid() );
    EXPECT_EQ(1001, r.id());
    EXPECT_EQ(".top", r.label());
    EXPECT_EQ(2, r.dim());

    EXPECT_EQ(2, region_db.add_region(1001,".top", 2).idx() );

    // try to convert Region to RegionIdx
    RegionIdx r_idx = r;
    EXPECT_EQ(2, r_idx.idx());
    }

    {
    Region r=region_db.add_region(1002,"inside 1", 3);
    EXPECT_EQ(3, r.idx() );
    EXPECT_EQ(1, r.bulk_idx() );
    EXPECT_EQ("inside 1", r.label() );
    EXPECT_EQ(1002, r.id() );
    EXPECT_EQ(3, r.dim());
    }

    {
        Region a=region_db.find_label(".top");
        Region b=region_db.find_id(1001);
        EXPECT_EQ(a,b);
        Region c=region_db.find_id(1002);
        EXPECT_TRUE(a!=c);

        EXPECT_FALSE( region_db.find_id(1007).is_valid() );
    }

    {
    Region r=region_db.add_region(1003, region_db.create_label_from_id(1003), 3);
    EXPECT_EQ(5, r.idx() );
    EXPECT_EQ(2, r.bulk_idx() );
    EXPECT_EQ("region_1003", r.label() );
    }

    {
    Region r=region_db.add_region(1004,".bottom", 2);
    EXPECT_EQ(4, r.idx() );
    EXPECT_EQ(2, r.boundary_idx() );
    EXPECT_EQ(".bottom", r.label() );
    EXPECT_EQ(1004, r.id() );
    }

    region_db.add_region(1005,".side", 2);
    //EXPECT_THROW( region_db.add_region(1005,"new", 3, false) , RegionDB::ExcInconsistentAdd);
    EXPECT_THROW( region_db.add_region(1001,".bottom", 2) , RegionDB::ExcNonuniqueID);
    EXPECT_THROW( region_db.add_region(1101,".top", 2) , RegionDB::ExcNonuniqueLabel);
    EXPECT_THROW( region_db.add_region(1001,".top", 3) , RegionDB::ExcNonuniqueLabel);
    //EXPECT_THROW( region_db.add_region(1001,"top", 2) , RegionDB::ExcNonuniqueLabel);

    region_db.close(); // close should be called automatically at first call to any size method.

    EXPECT_EQ(8, region_db.size());
    EXPECT_EQ(4, region_db.boundary_size());
    EXPECT_EQ(3, region_db.bulk_size());

    RegionSet bulk = region_db.get_region_set("BULK");
    EXPECT_EQ(3,bulk.size());
    EXPECT_EQ(1, bulk[0].id());
    EXPECT_EQ(1002, bulk[1].id());
    EXPECT_EQ(1003, bulk[2].id());

    EXPECT_THROW_WHAT( { region_db.add_region(1006,".side_", 2);}, RegionDB::ExcAddingIntoClosed, "Can not add label='.side_'");
Beispiel #2
0
/**
 * Sorts the regions vector in a linear order to be used for
 * translation.  The goal is to obtain an order that improves locality
 * when the function is executed.
 */
static void sortRegion(RegionVec&                  regions,
                       const Func*                 func,
                       const TransCFG&             cfg,
                       const ProfData*             profData,
                       const TransIDToRegionMap&   headToRegion,
                       const RegionToTransIDsMap&  regionToTransIds) {
  RegionVec sorted;
  RegionSet selected;

  if (regions.size() == 0) return;

  // First, pick the region starting at the lowest bytecode offset.
  // This will normally correspond to the main function entry (for
  // normal, regular bytecode), but it may not be for irregular
  // functions written in hhas (like array_map and array_filter).  If
  // there multiple regions starting at the lowest bytecode offset,
  // pick the one with the largest profile weight.
  RegionDescPtr entryRegion = nullptr;
  int64_t    maxEntryWeight = -1;
  Offset     lowestOffset   = kInvalidOffset;
  for (const auto& pair : regionToTransIds) {
    auto  r    = pair.first;
    auto& tids = pair.second;
    TransID firstTid = tids[0];
    Offset firstOffset = profData->transSrcKey(firstTid).offset();
    int64_t weight = cfg.weight(firstTid);
    if (lowestOffset == kInvalidOffset || firstOffset < lowestOffset ||
        (firstOffset == lowestOffset && weight > maxEntryWeight)) {
      entryRegion    = r;
      maxEntryWeight = weight;
      lowestOffset   = firstOffset;
    }
  }

  assert(entryRegion);
  sorted.push_back(entryRegion);
  selected.insert(entryRegion);

  RegionDescPtr region = entryRegion;
  // Select the remaining regions, iteratively picking the most likely
  // region to execute next.
  for (auto i = 1; i < regions.size(); i++) {
    int64_t      maxWeight = -1;
    int64_t  maxHeadWeight = -1;
    RegionDescPtr bestNext = nullptr;
    auto    regionTransIds = getRegionTransIDVec(regionToTransIds, region);
    for (auto next : regions) {
      if (selected.count(next)) continue;
      auto nextTransIds = getRegionTransIDVec(regionToTransIds, next);
      int64_t weight = interRegionWeight(regionTransIds, nextTransIds[0], cfg);
      int64_t headWeight = cfg.weight(nextTransIds[0]);
      if ((weight >  maxWeight) ||
          (weight == maxWeight && headWeight > maxHeadWeight)) {
        maxWeight     = weight;
        maxHeadWeight = headWeight;
        bestNext      = next;
      }
    }
    assert(bestNext);
    sorted.push_back(bestNext);
    selected.insert(bestNext);
    region = bestNext;
  }

  assert(sorted.size() == regions.size());
  regions = sorted;

  if (debug && Trace::moduleEnabled(HPHP::Trace::pgo, 5)) {
    for (size_t i = 0; i < regions.size(); i++) {
      auto r = regions[i];
      auto tids = getRegionTransIDVec(regionToTransIds, r);
      std::string transIds = folly::join(", ", tids);
      FTRACE(6, "sortRegion: region[{}]: {}\n", i, transIds);
    }
  }
}
/**
 * Sorts the regions vector in a linear order to be used for
 * translation.  The goal is to obtain an order that improves locality
 * when the function is executed.
 */
static void sortRegion(RegionVec&                  regions,
                       const Func*                 func,
                       const TransCFG&             cfg,
                       const ProfData*             profData,
                       const TransIDToRegionMap&   headToRegion,
                       const RegionToTransIDsMap&  regionToTransIds) {
  RegionVec sorted;
  RegionSet selected;

  // First, pick the region for the function body entry.  There may be
  // multiple translations of the function body, so pick the one with
  // largest profile weight.
  RegionDescPtr entryRegion = nullptr;
  int64_t    maxEntryWeight = -1;
  for (const auto& pair : regionToTransIds) {
    auto  r    = pair.first;
    auto& tids = pair.second;
    for (auto tid : tids) {
      if (profData->transSrcKey(tid).offset() == func->base()) {
        int64_t weight = cfg.weight(tid);
        if (weight > maxEntryWeight) {
          entryRegion    = r;
          maxEntryWeight = weight;
        }
      }
    }
  }

  assert(entryRegion);
  sorted.push_back(entryRegion);
  selected.insert(entryRegion);

  RegionDescPtr region = entryRegion;
  // Select the remaining regions, iteratively picking the most likely
  // region to execute next.
  for (auto i = 1; i < regions.size(); i++) {
    int64_t      maxWeight = -1;
    int64_t  maxHeadWeight = -1;
    RegionDescPtr bestNext = nullptr;
    auto    regionTransIds = getRegionTransIDVec(regionToTransIds, region);
    for (auto next : regions) {
      if (setContains(selected, next)) continue;
      auto nextTransIds = getRegionTransIDVec(regionToTransIds, next);
      int64_t weight = interRegionWeight(regionTransIds, nextTransIds[0], cfg);
      int64_t headWeight = cfg.weight(nextTransIds[0]);
      if ((weight >  maxWeight) ||
          (weight == maxWeight && headWeight > maxHeadWeight)) {
        maxWeight     = weight;
        maxHeadWeight = headWeight;
        bestNext      = next;
      }
    }
    assert(bestNext);
    sorted.push_back(bestNext);
    selected.insert(bestNext);
    region = bestNext;
  }

  assert(sorted.size() == regions.size());
  regions = sorted;

  if (debug && Trace::moduleEnabled(HPHP::Trace::pgo, 5)) {
    for (size_t i = 0; i < regions.size(); i++) {
      auto r = regions[i];
      auto tids = getRegionTransIDVec(regionToTransIds, r);
      std::string transIds = folly::join(", ", tids);
      FTRACE(6, "sortRegion: region[{}]: {}\n", i, transIds);
    }
  }
}