mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Fix memoization of lambdas in @enableOptimizeFunctionExpr feature
This is a fix specifically for the `enableOptimizeFunctionExpression` feature (disabled by default). I tried running all of our fixtures with that flag on everywhere, and this was the only issue. It's actually extracted from another fixture which is more complicated, this is a distilled version. There were two bugs: * DCE was running after LeaveSSA when it needs to run before. Fixing the order means code inside the function expression stops getting removed. * In the feature flag, context variables share Identifier instances with the surrounding code, whereas they are distinct instances without the feature. This meant that mutable ranges from inside the function propagated outside the function, throwing off our inference. The fix was to reset the ranges of context variables after inferring the function expression's effects.
This commit is contained in:
+3
-1
@@ -17,7 +17,7 @@ import {
|
||||
Place,
|
||||
ReactiveScopeDependency,
|
||||
} from "../HIR";
|
||||
import { constantPropagation } from "../Optimization";
|
||||
import { constantPropagation, deadCodeElimination } from "../Optimization";
|
||||
import { inferReactiveScopeVariables } from "../ReactiveScopes";
|
||||
import { eliminateRedundantPhi, enterSSA, leaveSSA } from "../SSA";
|
||||
import { inferTypes } from "../TypeInference";
|
||||
@@ -113,6 +113,7 @@ function lower(func: HIRFunction): void {
|
||||
|
||||
analyseFunctions(func);
|
||||
inferReferenceEffects(func, { isFunctionExpression: true });
|
||||
deadCodeElimination(func);
|
||||
inferMutableRanges(func);
|
||||
leaveSSA(func);
|
||||
inferReactiveScopeVariables(func);
|
||||
@@ -133,6 +134,7 @@ function infer(
|
||||
) {
|
||||
mutations.set(operand.identifier.name, operand.effect);
|
||||
}
|
||||
operand.identifier.mutableRange.end = operand.identifier.mutableRange.start;
|
||||
}
|
||||
|
||||
for (const dep of value.dependencies) {
|
||||
|
||||
-2
@@ -31,7 +31,6 @@ import {
|
||||
} from "../HIR/HIR";
|
||||
import { printPlace } from "../HIR/PrintHIR";
|
||||
import { eachPatternOperand } from "../HIR/visitors";
|
||||
import { deadCodeElimination } from "../Optimization";
|
||||
import { Err, Ok, Result } from "../Utils/Result";
|
||||
import { assertExhaustive } from "../Utils/utils";
|
||||
import { buildReactiveFunction } from "./BuildReactiveFunction";
|
||||
@@ -962,7 +961,6 @@ function codegenInstructionValue(
|
||||
case "FunctionExpression": {
|
||||
if (cx.env.enableOptimizeFunctionExpressions) {
|
||||
const loweredFunc = instrValue.loweredFunc;
|
||||
deadCodeElimination(loweredFunc);
|
||||
const reactiveFunction = buildReactiveFunction(loweredFunc);
|
||||
pruneUnusedLabels(reactiveFunction);
|
||||
pruneUnusedLValues(reactiveFunction);
|
||||
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @enableOptimizeFunctionExpressions
|
||||
function Component(props) {
|
||||
return () => {
|
||||
let str;
|
||||
if (arguments.length) {
|
||||
str = arguments[0];
|
||||
} else {
|
||||
str = props.str;
|
||||
}
|
||||
global.log(str);
|
||||
};
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { unstable_useMemoCache as useMemoCache } from "react"; // @enableOptimizeFunctionExpressions
|
||||
function Component(props) {
|
||||
const $ = useMemoCache(2);
|
||||
const c_0 = $[0] !== props.str;
|
||||
let t0;
|
||||
if (c_0) {
|
||||
t0 = () => {
|
||||
let str = undefined;
|
||||
if (arguments.length) {
|
||||
str = arguments[0];
|
||||
} else {
|
||||
str = props.str;
|
||||
}
|
||||
|
||||
global.log(str);
|
||||
};
|
||||
$[0] = props.str;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
return t0;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
// @enableOptimizeFunctionExpressions
|
||||
function Component(props) {
|
||||
return () => {
|
||||
let str;
|
||||
if (arguments.length) {
|
||||
str = arguments[0];
|
||||
} else {
|
||||
str = props.str;
|
||||
}
|
||||
global.log(str);
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user