Skip to content
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

[compiler][hir-rewrite] Check mutability of base identifier when hoisting #31032

Merged
merged 14 commits into from
Oct 3, 2024

Conversation

mofeiZ
Copy link
Contributor

@mofeiZ mofeiZ commented Sep 23, 2024

Stack from ghstack (oldest at bottom):

Prior to this PR, we check whether the property load source (e.g. the evaluation of <base> in <base>.property) is mutable + scoped to determine whether the property load itself is eligible for hoisting. This changes to check the base identifier of the load.

  • This is needed for the next PR [compiler][hir] Only hoist always-accessed PropertyLoads from function decls #31066. We want to evaluate whether the base identifier is mutable within the context of the outermost function. This is because all LoadLocals and PropertyLoads within a nested function declaration have mutable-ranges within the context of the function, but the base identifier is a context variable.
  • A side effect is that we no longer infer loads from props / other function arguments as mutable in edge cases (e.g. props escaping out of try-blocks or being assigned to context variables)

[ghstack-poisoned]
[ghstack-poisoned]
Copy link

vercel bot commented Sep 23, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
react-compiler-playground ✅ Ready (Inspect) Visit Preview 💬 Add feedback Oct 2, 2024 8:20pm

[ghstack-poisoned]
[ghstack-poisoned]
mofeiZ added a commit that referenced this pull request Sep 30, 2024
Followup from #30894 , not sure how these got missed. Note that this PR just copies the fixtures without adding `@enablePropagateDepsInHIR`. #31032 follows and actually enables the HIR-version of propagateScopeDeps to run. I split this out into two PRs to make snapshot differences easier to review, but also happy to merge

Fixtures found from locally setting snap test runner to default to `enablePropagateDepsInHIR: 'enabled_baseline'` and forking fixtures files with different output.

ghstack-source-id: 7d7cf41aa923d83ad49f89079171b0411923ce6b
Pull Request resolved: #31030
[ghstack-poisoned]
[ghstack-poisoned]
[ghstack-poisoned]
[ghstack-poisoned]
Comment on lines +3 to +16
/**
* Not safe to hoist read of maybeNullObject.value.inner outside of the
* try-catch block, as that might throw
*/
function useFoo(maybeNullObject: {value: {inner: number}} | null) {
const y = [];
try {
y.push(identity(maybeNullObject.value.inner));
} catch {
y.push('null');
}

return y;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug repro is unrelated to this fix

let x;
if ($[0] !== props) {
if ($[0] !== props.y || $[1] !== props.e) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that we're now inferring props as non-mutable. Previously, props.y was not marked hoistable because the evaluation of LoadLocal props had a mutable range (due to the try-catch).

@mofeiZ mofeiZ marked this pull request as ready for review October 1, 2024 15:41
[ghstack-poisoned]
[ghstack-poisoned]
[ghstack-poisoned]
[ghstack-poisoned]
[ghstack-poisoned]
[ghstack-poisoned]
@mofeiZ mofeiZ changed the base branch from gh/mofeiZ/17/base to main October 3, 2024 17:55
@mofeiZ mofeiZ merged commit edacbde into main Oct 3, 2024
19 checks passed
mofeiZ added a commit that referenced this pull request Oct 3, 2024
…n decls (#31066)

Stack from [ghstack](https://github.com/ezyang/ghstack) (oldest at
bottom):
* __->__ #31066
* #31032

Prior to this PR, we consider all of a nested function's accessed paths
as 'hoistable' (to the basic block in which the function was defined).
Now, we traverse nested functions and find all paths hoistable to their
*entry block*.

Note that this only replaces the *hoisting* part of function
declarations, not dependencies. This realistically only affects optional
chains within functions, which always get truncated to its inner
non-optional path (see
[todo-infer-function-uncond-optionals-hoisted.tsx](https://github.com/facebook/react/blob/576f3c0aa898cb99da1b7bf15317756e25c13708/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/reduce-reactive-deps/todo-infer-function-uncond-optionals-hoisted.tsx))

See newly added test fixtures for details

Update: Note that toggling `enableTreatFunctionDepsAsConditional` makes
a non-trivial impact on granularity of inferred deps (i.e. we find that
function declarations uniquely identify some paths as hoistable).
Snapshot comparison of internal code shows ~2.5% of files get worse
dependencies ([internal
link](https://www.internalfb.com/phabricator/paste/view/P1625792186))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed React Core Team Opened by a member of the React Core Team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants