std::unique_ptr computeDerivedOwnership()

in glean/rts/ownership/derived.cpp [143:215]


std::unique_ptr<ComputedOwnership> computeDerivedOwnership(
  Ownership& ownership,
  DerivedFactOwnershipIterator *iter) {
  auto t = makeAutoTimer("computeDerivedOwnership");
  VLOG(1) << "computing derived ownership";

  // Here we are identifying facts that were derived multiple
  // different ways.  e.g. if a fact was derived twice with owners A
  // and B, then its final ownership set will be A || B. That is, the
  // fact will be visibile (derivable) if either A or B are visible.

  std::map<uint64_t,UsetId> factOwners;
  folly::F14FastMap<int64_t,std::set<UsetId>> factOwnerSets;

  while (const auto owners = iter->get()) {
    for (uint32_t i = 0; i < owners->ids.size(); i++) {
      auto id = owners->ids[i].toWord();
      auto owner = owners->owners[i];
      const auto [it, inserted] = factOwners.insert({id, owner});
      if (!inserted) {
        const auto [it2, _] = factOwnerSets.insert({id, {it->second}});
        it2->second.insert(owner);
      }
    }
  }

  // Create all the new sets
  //   we are under the write lock here, so we can create canonical
  //   sets, no need to rebase them later.

  Usets usets(ownership.nextSetId());

  for (auto& pair : factOwnerSets) {
    if (pair.second.size() > 1) {
      SetU32 set = SetU32::from(pair.second);
      auto uset = std::make_unique<Uset>(std::move(set), Or, 0);
      auto usetid = ownership.lookupSet(uset.get());
      if (usetid == INVALID_USET) {
        auto p = usets.add(std::move(uset));
        usets.promote(p);
        usetid = p->id;
        VLOG(1) << "new set: " << usetid;
      } else {
        VLOG(1) << "existing set: " << usetid;
      }
      factOwners[pair.first] = usetid;
    }
  }

  auto sets = usets.toEliasFano();

  // convert factOwners into a vector of intervals
  std::vector<std::pair<Id,UsetId>> intervals;
  intervals.reserve(factOwners.size());
  UsetId current = INVALID_USET;
  for (auto& pair : factOwners) {
    auto usetid = pair.second;
    if (usetid != current) {
      intervals.push_back(std::make_pair(Id::fromWord(pair.first), usetid));
      current = usetid;
    }
  }

  VLOG(1) << "computing derived ownership: " <<
    intervals.size() << " intervals";

  // Now build a ComputedOwnership that we can return
  return std::make_unique<ComputedOwnership>(
      usets.getFirstId(),
      std::move(sets),
      std::move(intervals));

}