Skip to content

Commit dc43aea

Browse files
committed
[compiler] Delete LoweredFunction.dependencies and hoisted instructions
1 parent 70fb3f6 commit dc43aea

File tree

34 files changed

+109
-325
lines changed

34 files changed

+109
-325
lines changed

compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts

Lines changed: 11 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
import {NodePath, Scope} from '@babel/traverse';
99
import * as t from '@babel/types';
10-
import {Expression} from '@babel/types';
1110
import invariant from 'invariant';
1211
import {
1312
CompilerError,
@@ -3365,7 +3364,7 @@ function lowerFunction(
33653364
>,
33663365
): LoweredFunction | null {
33673366
const componentScope: Scope = builder.parentFunction.scope;
3368-
const captured = gatherCapturedDeps(builder, expr, componentScope);
3367+
const capturedContext = gatherCapturedContext(expr, componentScope);
33693368

33703369
/*
33713370
* TODO(gsn): In the future, we could only pass in the context identifiers
@@ -3379,7 +3378,7 @@ function lowerFunction(
33793378
expr,
33803379
builder.environment,
33813380
builder.bindings,
3382-
[...builder.context, ...captured.identifiers],
3381+
[...builder.context, ...capturedContext],
33833382
builder.parentFunction,
33843383
);
33853384
let loweredFunc: HIRFunction;
@@ -3392,7 +3391,6 @@ function lowerFunction(
33923391
loweredFunc = lowering.unwrap();
33933392
return {
33943393
func: loweredFunc,
3395-
dependencies: captured.refs,
33963394
};
33973395
}
33983396

@@ -4066,14 +4064,6 @@ function lowerAssignment(
40664064
}
40674065
}
40684066

4069-
function isValidDependency(path: NodePath<t.MemberExpression>): boolean {
4070-
const parent: NodePath<t.Node> = path.parentPath;
4071-
return (
4072-
!path.node.computed &&
4073-
!(parent.isCallExpression() && parent.get('callee') === path)
4074-
);
4075-
}
4076-
40774067
function captureScopes({from, to}: {from: Scope; to: Scope}): Set<Scope> {
40784068
let scopes: Set<Scope> = new Set();
40794069
while (from) {
@@ -4088,19 +4078,16 @@ function captureScopes({from, to}: {from: Scope; to: Scope}): Set<Scope> {
40884078
return scopes;
40894079
}
40904080

4091-
function gatherCapturedDeps(
4092-
builder: HIRBuilder,
4081+
function gatherCapturedContext(
40934082
fn: NodePath<
40944083
| t.FunctionExpression
40954084
| t.ArrowFunctionExpression
40964085
| t.FunctionDeclaration
40974086
| t.ObjectMethod
40984087
>,
40994088
componentScope: Scope,
4100-
): {identifiers: Array<t.Identifier>; refs: Array<Place>} {
4101-
const capturedIds: Map<t.Identifier, number> = new Map();
4102-
const capturedRefs: Set<Place> = new Set();
4103-
const seenPaths: Set<string> = new Set();
4089+
): Array<t.Identifier> {
4090+
const capturedIds = new Set<t.Identifier>();
41044091

41054092
/*
41064093
* Capture all the scopes from the parent of this function up to and including
@@ -4111,33 +4098,11 @@ function gatherCapturedDeps(
41114098
to: componentScope,
41124099
});
41134100

4114-
function addCapturedId(bindingIdentifier: t.Identifier): number {
4115-
if (!capturedIds.has(bindingIdentifier)) {
4116-
const index = capturedIds.size;
4117-
capturedIds.set(bindingIdentifier, index);
4118-
return index;
4119-
} else {
4120-
return capturedIds.get(bindingIdentifier)!;
4121-
}
4122-
}
4123-
41244101
function handleMaybeDependency(
4125-
path:
4126-
| NodePath<t.MemberExpression>
4127-
| NodePath<t.Identifier>
4128-
| NodePath<t.JSXOpeningElement>,
4102+
path: NodePath<t.Identifier> | NodePath<t.JSXOpeningElement>,
41294103
): void {
41304104
// Base context variable to depend on
41314105
let baseIdentifier: NodePath<t.Identifier> | NodePath<t.JSXIdentifier>;
4132-
/*
4133-
* Base expression to depend on, which (for now) may contain non side-effectful
4134-
* member expressions
4135-
*/
4136-
let dependency:
4137-
| NodePath<t.MemberExpression>
4138-
| NodePath<t.JSXMemberExpression>
4139-
| NodePath<t.Identifier>
4140-
| NodePath<t.JSXIdentifier>;
41414106
if (path.isJSXOpeningElement()) {
41424107
const name = path.get('name');
41434108
if (!(name.isJSXMemberExpression() || name.isJSXIdentifier())) {
@@ -4153,115 +4118,20 @@ function gatherCapturedDeps(
41534118
'Invalid logic in gatherCapturedDeps',
41544119
);
41554120
baseIdentifier = current;
4156-
4157-
/*
4158-
* Get the expression to depend on, which may involve PropertyLoads
4159-
* for member expressions
4160-
*/
4161-
let currentDep:
4162-
| NodePath<t.JSXMemberExpression>
4163-
| NodePath<t.Identifier>
4164-
| NodePath<t.JSXIdentifier> = baseIdentifier;
4165-
4166-
while (true) {
4167-
const nextDep: null | NodePath<t.Node> = currentDep.parentPath;
4168-
if (nextDep && nextDep.isJSXMemberExpression()) {
4169-
currentDep = nextDep;
4170-
} else {
4171-
break;
4172-
}
4173-
}
4174-
dependency = currentDep;
4175-
} else if (path.isMemberExpression()) {
4176-
// Calculate baseIdentifier
4177-
let currentId: NodePath<Expression> = path;
4178-
while (currentId.isMemberExpression()) {
4179-
currentId = currentId.get('object');
4180-
}
4181-
if (!currentId.isIdentifier()) {
4182-
return;
4183-
}
4184-
baseIdentifier = currentId;
4185-
4186-
/*
4187-
* Get the expression to depend on, which may involve PropertyLoads
4188-
* for member expressions
4189-
*/
4190-
let currentDep:
4191-
| NodePath<t.MemberExpression>
4192-
| NodePath<t.Identifier>
4193-
| NodePath<t.JSXIdentifier> = baseIdentifier;
4194-
4195-
while (true) {
4196-
const nextDep: null | NodePath<t.Node> = currentDep.parentPath;
4197-
if (
4198-
nextDep &&
4199-
nextDep.isMemberExpression() &&
4200-
isValidDependency(nextDep)
4201-
) {
4202-
currentDep = nextDep;
4203-
} else {
4204-
break;
4205-
}
4206-
}
4207-
4208-
dependency = currentDep;
42094121
} else {
42104122
baseIdentifier = path;
4211-
dependency = path;
42124123
}
42134124

42144125
/*
42154126
* Skip dependency path, as we already tried to recursively add it (+ all subexpressions)
42164127
* as a dependency.
42174128
*/
4218-
dependency.skip();
4129+
path.skip();
42194130

42204131
// Add the base identifier binding as a dependency.
42214132
const binding = baseIdentifier.scope.getBinding(baseIdentifier.node.name);
4222-
if (binding === undefined || !pureScopes.has(binding.scope)) {
4223-
return;
4224-
}
4225-
const idKey = String(addCapturedId(binding.identifier));
4226-
4227-
// Add the expression (potentially a memberexpr path) as a dependency.
4228-
let exprKey = idKey;
4229-
if (dependency.isMemberExpression()) {
4230-
let pathTokens = [];
4231-
let current: NodePath<Expression> = dependency;
4232-
while (current.isMemberExpression()) {
4233-
const property = current.get('property') as NodePath<t.Identifier>;
4234-
pathTokens.push(property.node.name);
4235-
current = current.get('object');
4236-
}
4237-
4238-
exprKey += '.' + pathTokens.reverse().join('.');
4239-
} else if (dependency.isJSXMemberExpression()) {
4240-
let pathTokens = [];
4241-
let current: NodePath<t.JSXMemberExpression | t.JSXIdentifier> =
4242-
dependency;
4243-
while (current.isJSXMemberExpression()) {
4244-
const property = current.get('property');
4245-
pathTokens.push(property.node.name);
4246-
current = current.get('object');
4247-
}
4248-
}
4249-
4250-
if (!seenPaths.has(exprKey)) {
4251-
let loweredDep: Place;
4252-
if (dependency.isJSXIdentifier()) {
4253-
loweredDep = lowerValueToTemporary(builder, {
4254-
kind: 'LoadLocal',
4255-
place: lowerIdentifier(builder, dependency),
4256-
loc: path.node.loc ?? GeneratedSource,
4257-
});
4258-
} else if (dependency.isJSXMemberExpression()) {
4259-
loweredDep = lowerJsxMemberExpression(builder, dependency);
4260-
} else {
4261-
loweredDep = lowerExpressionToTemporary(builder, dependency);
4262-
}
4263-
capturedRefs.add(loweredDep);
4264-
seenPaths.add(exprKey);
4133+
if (binding !== undefined && pureScopes.has(binding.scope)) {
4134+
capturedIds.add(binding.identifier);
42654135
}
42664136
}
42674137

@@ -4292,13 +4162,13 @@ function gatherCapturedDeps(
42924162
return;
42934163
} else if (path.isJSXElement()) {
42944164
handleMaybeDependency(path.get('openingElement'));
4295-
} else if (path.isMemberExpression() || path.isIdentifier()) {
4165+
} else if (path.isIdentifier()) {
42964166
handleMaybeDependency(path);
42974167
}
42984168
},
42994169
});
43004170

4301-
return {identifiers: [...capturedIds.keys()], refs: [...capturedRefs]};
4171+
return [...capturedIds.keys()];
43024172
}
43034173

43044174
function notNull<T>(value: T | null): value is T {

compiler/packages/babel-plugin-react-compiler/src/HIR/CollectHoistablePropertyLoads.ts

Lines changed: 1 addition & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,6 @@ export function collectHoistablePropertyLoads(
8888
): ReadonlyMap<BlockId, BlockInfo> {
8989
const registry = new PropertyPathRegistry();
9090

91-
const functionExpressionLoads = collectFunctionExpressionFakeLoads(fn);
92-
const actuallyEvaluatedTemporaries = new Map(
93-
[...temporaries].filter(([id]) => !functionExpressionLoads.has(id)),
94-
);
95-
9691
/**
9792
* Due to current limitations of mutable range inference, there are edge cases in
9893
* which we infer known-immutable values (e.g. props or hook params) to have a
@@ -110,7 +105,7 @@ export function collectHoistablePropertyLoads(
110105
}
111106
}
112107
const nodes = collectNonNullsInBlocks(fn, {
113-
temporaries: actuallyEvaluatedTemporaries,
108+
temporaries,
114109
knownImmutableIdentifiers,
115110
hoistableFromOptionals,
116111
registry,
@@ -576,30 +571,3 @@ function reduceMaybeOptionalChains(
576571
}
577572
} while (changed);
578573
}
579-
580-
function collectFunctionExpressionFakeLoads(
581-
fn: HIRFunction,
582-
): Set<IdentifierId> {
583-
const sources = new Map<IdentifierId, IdentifierId>();
584-
const functionExpressionReferences = new Set<IdentifierId>();
585-
586-
for (const [_, block] of fn.body.blocks) {
587-
for (const {lvalue, value} of block.instructions) {
588-
if (
589-
value.kind === 'FunctionExpression' ||
590-
value.kind === 'ObjectMethod'
591-
) {
592-
for (const reference of value.loweredFunc.dependencies) {
593-
let curr: IdentifierId | undefined = reference.identifier.id;
594-
while (curr != null) {
595-
functionExpressionReferences.add(curr);
596-
curr = sources.get(curr);
597-
}
598-
}
599-
} else if (value.kind === 'PropertyLoad') {
600-
sources.set(lvalue.identifier.id, value.object.identifier.id);
601-
}
602-
}
603-
}
604-
return functionExpressionReferences;
605-
}

compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -722,7 +722,6 @@ export type ObjectProperty = {
722722
};
723723

724724
export type LoweredFunction = {
725-
dependencies: Array<Place>;
726725
func: HIRFunction;
727726
};
728727

compiler/packages/babel-plugin-react-compiler/src/HIR/PrintHIR.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -538,9 +538,6 @@ export function printInstructionValue(instrValue: ReactiveValue): string {
538538
.split('\n')
539539
.map(line => ` ${line}`)
540540
.join('\n');
541-
const deps = instrValue.loweredFunc.dependencies
542-
.map(dep => printPlace(dep))
543-
.join(',');
544541
const context = instrValue.loweredFunc.func.context
545542
.map(dep => printPlace(dep))
546543
.join(',');
@@ -557,7 +554,7 @@ export function printInstructionValue(instrValue: ReactiveValue): string {
557554
})
558555
.join(', ') ?? '';
559556
const type = printType(instrValue.loweredFunc.func.returnType).trim();
560-
value = `${kind} ${name} @deps[${deps}] @context[${context}] @effects[${effects}]${type !== '' ? ` return${type}` : ''}:\n${fn}`;
557+
value = `${kind} ${name} @context[${context}] @effects[${effects}]${type !== '' ? ` return${type}` : ''}:\n${fn}`;
561558
break;
562559
}
563560
case 'TaggedTemplateExpression': {

compiler/packages/babel-plugin-react-compiler/src/HIR/visitors.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ export function* eachInstructionValueOperand(
193193
}
194194
case 'ObjectMethod':
195195
case 'FunctionExpression': {
196-
yield* instrValue.loweredFunc.dependencies;
196+
yield* instrValue.loweredFunc.func.context;
197197
break;
198198
}
199199
case 'TaggedTemplateExpression': {
@@ -517,8 +517,9 @@ export function mapInstructionValueOperands(
517517
}
518518
case 'ObjectMethod':
519519
case 'FunctionExpression': {
520-
instrValue.loweredFunc.dependencies =
521-
instrValue.loweredFunc.dependencies.map(d => fn(d));
520+
instrValue.loweredFunc.func.context =
521+
instrValue.loweredFunc.func.context.map(d => fn(d));
522+
522523
break;
523524
}
524525
case 'TaggedTemplateExpression': {

0 commit comments

Comments
 (0)