Skip to content

Commit

Permalink
Optimize method calls w props receiver
Browse files Browse the repository at this point in the history
ghstack-source-id: 6a49070add645384c4b764db4749f829a1992f43
Pull Request resolved: #31771
  • Loading branch information
josephsavona committed Dec 13, 2024
1 parent 1520802 commit 32b81a3
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ import {validateNoSetStateInPassiveEffects} from '../Validation/ValidateNoSetSta
import {validateNoJSXInTryStatement} from '../Validation/ValidateNoJSXInTryStatement';
import {propagateScopeDependenciesHIR} from '../HIR/PropagateScopeDependenciesHIR';
import {outlineJSX} from '../Optimization/OutlineJsx';
import {optimizePropsMethodCalls} from '../Optimization/OptimizePropsMethodCalls';

export type CompilerPipelineValue =
| {kind: 'ast'; name: string; value: CodegenFunction}
Expand Down Expand Up @@ -209,6 +210,9 @@ function* runWithEnvironment(
lowerContextAccess(hir, env.config.lowerContextAccess);
}

optimizePropsMethodCalls(hir);
yield log({kind: 'hir', name: 'OptimizePropsMethodCalls', value: hir});

analyseFunctions(hir);
yield log({kind: 'hir', name: 'AnalyseFunctions', value: hir});

Expand Down
4 changes: 4 additions & 0 deletions compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1644,6 +1644,10 @@ export function isArrayType(id: Identifier): boolean {
return id.type.kind === 'Object' && id.type.shapeId === 'BuiltInArray';
}

export function isPropsType(id: Identifier): boolean {
return id.type.kind === 'Object' && id.type.shapeId === 'BuiltInProps';
}

export function isRefValueType(id: Identifier): boolean {
return id.type.kind === 'Object' && id.type.shapeId === 'BuiltInRefValue';
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import {HIRFunction, isPropsType} from '../HIR';

/**
* Converts method calls into regular calls where the receiver is the props object:
*
* Example:
*
* ```
* // INPUT
* props.foo();
*
* // OUTPUT
* const t0 = props.foo;
* t0();
* ```
*
* Counter example:
*
* Here the receiver is `props.foo`, not the props object, so we don't rewrite it:
*
* // INPUT
* props.foo.bar();
*
* // OUTPUT
* props.foo.bar();
* ```
*/
export function optimizePropsMethodCalls(fn: HIRFunction): void {
for (const [, block] of fn.body.blocks) {
for (let i = 0; i < block.instructions.length; i++) {
const instr = block.instructions[i]!;
if (
instr.value.kind === 'MethodCall' &&
isPropsType(instr.value.receiver.identifier)
) {
instr.value = {
kind: 'CallExpression',
callee: instr.value.property,
args: instr.value.args,
loc: instr.value.loc,
};
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,26 +50,35 @@ export const FIXTURE_ENTRYPOINT = {
```javascript
import { c as _c } from "react/compiler-runtime"; // @enableJsxOutlining
function Component(arr) {
const $ = _c(3);
const $ = _c(6);
const x = useX();
let t0;
if ($[0] !== arr || $[1] !== x) {
t0 = arr.map((i) => {
t0 = (i) => {
arr.map((i_0, id) => {
const T0 = _temp;
const child = <T0 i={i_0} x={x} />;

const jsx = <div>{child}</div>;
return jsx;
});
});
};
$[0] = arr;
$[1] = x;
$[2] = t0;
} else {
t0 = $[2];
}
return t0;
let t1;
if ($[3] !== arr.map || $[4] !== t0) {
t1 = arr.map(t0);
$[3] = arr.map;
$[4] = t0;
$[5] = t1;
} else {
t1 = $[5];
}
return t1;
}
function _temp(t0) {
const $ = _c(5);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@

## Input

```javascript
function Component(props) {
const x = props.x();
return <div>{x}</div>;
}

```

## Code

```javascript
import { c as _c } from "react/compiler-runtime";
function Component(props) {
const $ = _c(4);
let t0;
if ($[0] !== props.x) {
t0 = props.x();
$[0] = props.x;
$[1] = t0;
} else {
t0 = $[1];
}
const x = t0;
let t1;
if ($[2] !== x) {
t1 = <div>{x}</div>;
$[2] = x;
$[3] = t1;
} else {
t1 = $[3];
}
return t1;
}

```
### Eval output
(kind: exception) Fixture not implemented
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
function Component(props) {
const x = props.x();
return <div>{x}</div>;
}

0 comments on commit 32b81a3

Please sign in to comment.