mirror of
https://github.com/oxc-project/oxc.git
synced 2026-11-04 10:29:58 +00:00
perf(react_compiler): compare value set pointers before probing in state merge (#24805)
## Context Value sets in the aliasing inference state are `Rc<FxHashSet<ValueId>>`, shared between states rather than copied (#24117). When two states meet at a join, the merge still walks every variable and probes one set against the other looking for a value the current state doesn't have. Most of the time both sides point at the same `Rc`, so that probe is comparing a set to itself. ## This PR Check `Rc::ptr_eq` before probing. If the pointers match there is nothing to add, so we skip the scan. Both merge paths did this check in slightly different ways, so I pulled it into one helper. The sets are never mutated in place, which is what makes the pointer check safe. ### Performance | workload | main | this PR | delta | | ----------------------------------------------------- | -------: | -------: | ------: | | 3.6k-line control-flow heavy component, instructions | 23.762 B | 22.034 B | -7.3% | | same file, wall time | 4.55 s | 4.13 s | -9% | | 16.5k-file real corpus, instructions (1 thread) | 50.135 B | 49.697 B | -0.87% | This PR was assisted by Claude Code.
This commit is contained in:
1 parent
23b904ff09
commit
98f2ecbb10
1 file changed
+13
-16
+13
-16
@@ -562,20 +562,12 @@ impl InferenceState {
|
||||
|
||||
// Merge variables present in both
|
||||
for (id, this_values) in &self.variables {
|
||||
if let Some(other_values) = other.variables.get(id) {
|
||||
let mut has_new = false;
|
||||
for ov in other_values.iter() {
|
||||
if !this_values.contains(ov) {
|
||||
has_new = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if has_new {
|
||||
let nvars = next_variables.get_or_insert_with(|| self.variables.clone());
|
||||
let merged: FxHashSet<ValueId> =
|
||||
this_values.union(other_values).copied().collect();
|
||||
nvars.insert(*id, Rc::new(merged));
|
||||
}
|
||||
if let Some(other_values) = other.variables.get(id)
|
||||
&& contributes_new_value(this_values, other_values)
|
||||
{
|
||||
let nvars = next_variables.get_or_insert_with(|| self.variables.clone());
|
||||
let merged: FxHashSet<ValueId> = this_values.union(other_values).copied().collect();
|
||||
nvars.insert(*id, Rc::new(merged));
|
||||
}
|
||||
}
|
||||
// Add variables only in other
|
||||
@@ -625,8 +617,7 @@ impl InferenceState {
|
||||
for (id, other_values) in &other.variables {
|
||||
match self.variables.get(id) {
|
||||
Some(this_values) => {
|
||||
let has_new = other_values.iter().any(|ov| !this_values.contains(ov));
|
||||
if has_new {
|
||||
if contributes_new_value(this_values, other_values) {
|
||||
// Build the union as a fresh set exactly like `merge`, so
|
||||
// the resulting iteration order matches.
|
||||
let merged: FxHashSet<ValueId> =
|
||||
@@ -665,6 +656,12 @@ fn is_superset(a: &ReasonSet, b: &ReasonSet) -> bool {
|
||||
a.0 & b.0 == b.0
|
||||
}
|
||||
|
||||
/// Whether `other` holds a value that `this` lacks. The sets are immutable and
|
||||
/// shared, so an identical allocation can contribute nothing new.
|
||||
fn contributes_new_value(this: &Rc<FxHashSet<ValueId>>, other: &Rc<FxHashSet<ValueId>>) -> bool {
|
||||
!Rc::ptr_eq(this, other) && other.iter().any(|value| !this.contains(value))
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
enum MutateVariant {
|
||||
Mutate,
|
||||
|
||||
Reference in new issue
Block a user