Skip to content

Commit

Permalink
Refactor the "TraverseState" out to make it easier to review future C…
Browse files Browse the repository at this point in the history
…L for performance improvement. This is (almost) a no-op change.

PiperOrigin-RevId: 707050510
  • Loading branch information
h-joo authored and copybara-github committed Dec 17, 2024
1 parent 4047709 commit 1c9ce50
Showing 1 changed file with 28 additions and 27 deletions.
55 changes: 28 additions & 27 deletions pytype/typegraph/solver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,13 @@ namespace internal {
struct RemoveResult {
const GoalSet removed_goals;
const GoalSet new_goals;
RemoveResult(const GoalSet& removed_goals, const GoalSet& new_goals):
removed_goals(removed_goals), new_goals(new_goals) {}
};

struct TraverseState {
GoalSet goals_to_remove;
GoalSet seen_goals;
GoalSet removed_goals;
GoalSet new_goals;
};

// Remove all goals that can be fulfilled at the current CFG node.
Expand All @@ -39,51 +44,47 @@ struct RemoveResult {
// avoiding bugs related to transmitting state information across calls.
static std::vector<RemoveResult> remove_finished_goals(const CFGNode* pos,
const GoalSet& goals) {
GoalSet goals_to_remove;
TraverseState state;
// We can't use set_intersection here because pos->bindings() is a vector.
for (const auto* goal : pos->bindings()) {
if (goals.count(goal)) {
goals_to_remove.insert(goal);
state.goals_to_remove.insert(goal);
}
}
GoalSet seen_goals;
GoalSet removed_goals;
GoalSet new_goals;
std::set_difference(goals.begin(), goals.end(),
goals_to_remove.begin(), goals_to_remove.end(),
std::inserter(new_goals, new_goals.begin()),
std::set_difference(goals.begin(), goals.end(), state.goals_to_remove.begin(),
state.goals_to_remove.end(),
std::inserter(state.new_goals, state.new_goals.begin()),
pointer_less<Binding>());
std::deque<std::tuple<GoalSet, GoalSet, GoalSet, GoalSet>> queue;
queue.emplace_back(goals_to_remove, seen_goals, removed_goals, new_goals);
std::deque<TraverseState> queue;
queue.emplace_back(state);
std::vector<RemoveResult> results;
while (!queue.empty()) {
std::tie(goals_to_remove, seen_goals, removed_goals, new_goals) =
queue.front();
state = std::move(queue.front());
queue.pop_front();
if (goals_to_remove.empty()) {
results.push_back(RemoveResult(removed_goals, new_goals));
if (state.goals_to_remove.empty()) {
results.push_back(RemoveResult(state.removed_goals, state.new_goals));
continue;
}
const auto* goal = *goals_to_remove.begin();
goals_to_remove.erase(goals_to_remove.begin());
if (seen_goals.count(goal)) {
const auto* goal = *state.goals_to_remove.begin();
state.goals_to_remove.erase(state.goals_to_remove.begin());
if (state.seen_goals.count(goal)) {
// Only process a goal once, to prevent infinite loops.
queue.emplace_back(goals_to_remove, seen_goals, removed_goals, new_goals);
queue.emplace_back(std::move(state));
continue;
}
seen_goals.insert(goal);
state.seen_goals.insert(goal);
const auto* origin = goal->FindOrigin(pos);
if (!origin) {
new_goals.insert(goal);
queue.emplace_back(goals_to_remove, seen_goals, removed_goals, new_goals);
state.new_goals.insert(goal);
queue.emplace_back(std::move(state));
continue;
}
removed_goals.insert(goal);
state.removed_goals.insert(goal);
for (const auto& source_set : origin->source_sets) {
GoalSet next_goals_to_remove(goals_to_remove);
GoalSet next_goals_to_remove(state.goals_to_remove);
next_goals_to_remove.insert(source_set.begin(), source_set.end());
queue.emplace_back(std::move(next_goals_to_remove), seen_goals,
removed_goals, new_goals);
queue.emplace_back(std::move(next_goals_to_remove), state.seen_goals,
state.removed_goals, state.new_goals);
}
}
return results;
Expand Down

0 comments on commit 1c9ce50

Please sign in to comment.