-
Notifications
You must be signed in to change notification settings - Fork 50k
compiler: Use types to decide which scopes are eligible for merging #29157
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
In MergeReactiveScopesThatInvalidateTogether when deciding which scopes were eligible for mergin at all, we looked specifically at the instructions whose lvalue produces the declaration. So if a scope declaration was `t0`, we'd love for the instruction where `t0` was the lvalue and look at the instruction type to decide if it is eligible for merging. Here, we use the inferred type instead (now that the inferred types support the same set of types of instructions we looked at before). This allows us to find more cases where scopes can be merged. [ghstack-poisoned]
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
In MergeReactiveScopesThatInvalidateTogether when deciding which scopes were eligible for mergin at all, we looked specifically at the instructions whose lvalue produces the declaration. So if a scope declaration was `t0`, we'd love for the instruction where `t0` was the lvalue and look at the instruction type to decide if it is eligible for merging. Here, we use the inferred type instead (now that the inferred types support the same set of types of instructions we looked at before). This allows us to find more cases where scopes can be merged. ghstack-source-id: 22e4960 Pull Request resolved: #29157
|
Comparing: bf046e8...6d4f5c8 Critical size changesIncludes critical production bundles, as well as any change greater than 2%:
Significant size changesIncludes any change greater than 0.2%: Expand to show
|
…r merging" In MergeReactiveScopesThatInvalidateTogether when deciding which scopes were eligible for mergin at all, we looked specifically at the instructions whose lvalue produces the declaration. So if a scope declaration was `t0`, we'd love for the instruction where `t0` was the lvalue and look at the instruction type to decide if it is eligible for merging. Here, we use the inferred type instead (now that the inferred types support the same set of types of instructions we looked at before). This allows us to find more cases where scopes can be merged. [ghstack-poisoned]
In MergeReactiveScopesThatInvalidateTogether when deciding which scopes were eligible for mergin at all, we looked specifically at the instructions whose lvalue produces the declaration. So if a scope declaration was `t0`, we'd love for the instruction where `t0` was the lvalue and look at the instruction type to decide if it is eligible for merging. Here, we use the inferred type instead (now that the inferred types support the same set of types of instructions we looked at before). This allows us to find more cases where scopes can be merged. ghstack-source-id: 675de0f Pull Request resolved: #29157
…r merging" In MergeReactiveScopesThatInvalidateTogether when deciding which scopes were eligible for mergin at all, we looked specifically at the instructions whose lvalue produces the declaration. So if a scope declaration was `t0`, we'd love for the instruction where `t0` was the lvalue and look at the instruction type to decide if it is eligible for merging. Here, we use the inferred type instead (now that the inferred types support the same set of types of instructions we looked at before). This allows us to find more cases where scopes can be merged. [ghstack-poisoned]
In MergeReactiveScopesThatInvalidateTogether when deciding which scopes were eligible for mergin at all, we looked specifically at the instructions whose lvalue produces the declaration. So if a scope declaration was `t0`, we'd love for the instruction where `t0` was the lvalue and look at the instruction type to decide if it is eligible for merging. Here, we use the inferred type instead (now that the inferred types support the same set of types of instructions we looked at before). This allows us to find more cases where scopes can be merged. ghstack-source-id: 6085abe Pull Request resolved: #29157
…r merging" In MergeReactiveScopesThatInvalidateTogether when deciding which scopes were eligible for mergin at all, we looked specifically at the instructions whose lvalue produces the declaration. So if a scope declaration was `t0`, we'd love for the instruction where `t0` was the lvalue and look at the instruction type to decide if it is eligible for merging. Here, we use the inferred type instead (now that the inferred types support the same set of types of instructions we looked at before). This allows us to find more cases where scopes can be merged. [ghstack-poisoned]
In MergeReactiveScopesThatInvalidateTogether when deciding which scopes were eligible for mergin at all, we looked specifically at the instructions whose lvalue produces the declaration. So if a scope declaration was `t0`, we'd love for the instruction where `t0` was the lvalue and look at the instruction type to decide if it is eligible for merging. Here, we use the inferred type instead (now that the inferred types support the same set of types of instructions we looked at before). This allows us to find more cases where scopes can be merged. ghstack-source-id: ab46a9e Pull Request resolved: #29157
…r merging" In MergeReactiveScopesThatInvalidateTogether when deciding which scopes were eligible for mergin at all, we looked specifically at the instructions whose lvalue produces the declaration. So if a scope declaration was `t0`, we'd love for the instruction where `t0` was the lvalue and look at the instruction type to decide if it is eligible for merging. Here, we use the inferred type instead (now that the inferred types support the same set of types of instructions we looked at before). This allows us to find more cases where scopes can be merged. [ghstack-poisoned]
In MergeReactiveScopesThatInvalidateTogether when deciding which scopes were eligible for mergin at all, we looked specifically at the instructions whose lvalue produces the declaration. So if a scope declaration was `t0`, we'd love for the instruction where `t0` was the lvalue and look at the instruction type to decide if it is eligible for merging. Here, we use the inferred type instead (now that the inferred types support the same set of types of instructions we looked at before). This allows us to find more cases where scopes can be merged. ghstack-source-id: b2b2791 Pull Request resolved: #29157
…r merging" In MergeReactiveScopesThatInvalidateTogether when deciding which scopes were eligible for merging, we previously looked specifically at the type of the instruction whose lvalue is declaration. So if a scope declaration was `t0`, we'd look for the instruction where `t0` was the lvalue and look at the instruction type to decide if it is eligible for merging. Here, we use the inferred type instead (now that the inferred types support the same set of types of instructions we looked at before). This allows us to find more cases where scopes can be merged. NOTE: marking as draft because i have not yet verified all the fixtures changes (including checking that they are all have a snap fixture) [ghstack-poisoned]
In MergeReactiveScopesThatInvalidateTogether when deciding which scopes were eligible for mergin at all, we looked specifically at the instructions whose lvalue produces the declaration. So if a scope declaration was `t0`, we'd love for the instruction where `t0` was the lvalue and look at the instruction type to decide if it is eligible for merging. Here, we use the inferred type instead (now that the inferred types support the same set of types of instructions we looked at before). This allows us to find more cases where scopes can be merged. ghstack-source-id: f36a92a Pull Request resolved: #29157
…r merging" In MergeReactiveScopesThatInvalidateTogether when deciding which scopes were eligible for merging, we previously looked specifically at the type of the instruction whose lvalue is declaration. So if a scope declaration was `t0`, we'd look for the instruction where `t0` was the lvalue and look at the instruction type to decide if it is eligible for merging. Here, we use the inferred type instead (now that the inferred types support the same set of types of instructions we looked at before). This allows us to find more cases where scopes can be merged. [ghstack-poisoned]
In MergeReactiveScopesThatInvalidateTogether when deciding which scopes were eligible for mergin at all, we looked specifically at the instructions whose lvalue produces the declaration. So if a scope declaration was `t0`, we'd love for the instruction where `t0` was the lvalue and look at the instruction type to decide if it is eligible for merging. Here, we use the inferred type instead (now that the inferred types support the same set of types of instructions we looked at before). This allows us to find more cases where scopes can be merged. ghstack-source-id: 07d02d8 Pull Request resolved: #29157
| return [...scopeBlock.scope.declarations].some(([, decl]) => | ||
| isAlwaysInvalidatingType(decl.identifier.type) | ||
| ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haven't spent time trying to find a case in which this is an issue, but note that this also affects scopes that produce a "always-invalidating" type transitively, from a nested scope:
In this example, it seems that both scopes @0 and @1 are now "eligble for merging". It looks like the inner decl isn't always guaranteed to invalidate on outer_dep changes though. Maybe I'm missing something though
scope @0 deps=[inner_dep, outer_dep] decls=[inner, outer] {
outer = makeValue(outer_dep);
scope@1 deps=[inner_dep] decls=[inner] {
inner = {inner_dep};
}
maybeWrite(outer);
}There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting, i wasn't thinking about the nested case (more on that later) but about the transitive case. Something like: two values get merged into a single scope eg due to interleaving, x depends on a, y depends on b. Then some later value only depends on eg x, but that means it implicitly resets on changes to b as well:
scope @0 deps=[a, b] decls=[x, y] {
// imagine this
x = Array [ ]
y = Array [ ]
x.push( a )
y.push( b )
}
scope @1 deps=[y] decls=[z] {
z = makeValue( y )
}
With this PR we'd now merge these scopes, and z will reset on changes to a even though y doesn't strictly depend on a. But...even if we didn't merge the scopes, y would still reset on changes to a, which would invalidate z anyway. So merging doesn't change the reset.
For the case you pointed out: the only way to have a subsequent scope depend on a value produced by an inner scope (that i can think of) is something like this:
function Component({ a, b, c }) {
const x = [];
let y;
if (a) {
y = [b];
}
x.push(c);
const z = [y];
return [z, x];
}note y is declared outside the if, making it available for the subsequent z = [y] reference. That instruction sees the result of a phi node (due to the reassignment), and we don't currently infer types for phi nodes. So in practice, this case would not yet get merged.
I'll add this as a test case so we can find regressions.
…r merging" In MergeReactiveScopesThatInvalidateTogether when deciding which scopes were eligible for merging, we previously looked specifically at the type of the instruction whose lvalue is declaration. So if a scope declaration was `t0`, we'd look for the instruction where `t0` was the lvalue and look at the instruction type to decide if it is eligible for merging. Here, we use the inferred type instead (now that the inferred types support the same set of types of instructions we looked at before). This allows us to find more cases where scopes can be merged. [ghstack-poisoned]
|
Updated to add a test case confirming that the nested case memoizes as expected (ie does not inadvertently merge). I couldn't easily replicate that level of precision with useMemo, so i added a way to disable the non-forget execution in snap. This way we will get a test failure (not just a change to snapshot output) if we regress on the case you pointed out. |
In MergeReactiveScopesThatInvalidateTogether when deciding which scopes were eligible for mergin at all, we looked specifically at the instructions whose lvalue produces the declaration. So if a scope declaration was `t0`, we'd love for the instruction where `t0` was the lvalue and look at the instruction type to decide if it is eligible for merging. Here, we use the inferred type instead (now that the inferred types support the same set of types of instructions we looked at before). This allows us to find more cases where scopes can be merged. ghstack-source-id: 0e3e05f Pull Request resolved: #29157
Stack from ghstack (oldest at bottom):
In MergeReactiveScopesThatInvalidateTogether when deciding which scopes were eligible for merging, we previously looked specifically at the type of the instruction whose lvalue is declaration. So if a scope declaration was
t0, we'd look for the instruction wheret0was the lvalue and look at the instruction type to decide if it is eligible for merging.Here, we use the inferred type instead (now that the inferred types support the same set of types of instructions we looked at before). This allows us to find more cases where scopes can be merged.