Skip to content

Commit 45463ab

Browse files
authored
[compiler][be] Refactor similar CallExpression and MethodCall effect handling (#32696)
Simplify InferReferenceEffect function signature matching logic for next PRs in stack --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/32696). * #32698 * #32697 * __->__ #32696 * #32695
1 parent febc09b commit 45463ab

File tree

1 file changed

+113
-150
lines changed

1 file changed

+113
-150
lines changed

compiler/packages/babel-plugin-react-compiler/src/Inference/InferReferenceEffects.ts

Lines changed: 113 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
Phi,
2424
Place,
2525
SpreadPattern,
26+
TInstruction,
2627
Type,
2728
ValueKind,
2829
ValueReason,
@@ -1238,62 +1239,12 @@ function inferBlock(
12381239
break;
12391240
}
12401241
case 'CallExpression': {
1241-
const signature = getFunctionCallSignature(
1242-
env,
1243-
instrValue.callee.identifier.type,
1242+
inferCallEffects(
1243+
state,
1244+
instr as TInstruction<CallExpression>,
1245+
freezeActions,
1246+
getFunctionCallSignature(env, instrValue.callee.identifier.type),
12441247
);
1245-
1246-
const effects =
1247-
signature !== null ? getFunctionEffects(instrValue, signature) : null;
1248-
const returnValueKind: AbstractValue =
1249-
signature !== null
1250-
? {
1251-
kind: signature.returnValueKind,
1252-
reason: new Set([
1253-
signature.returnValueReason ??
1254-
ValueReason.KnownReturnSignature,
1255-
]),
1256-
context: new Set(),
1257-
}
1258-
: {
1259-
kind: ValueKind.Mutable,
1260-
reason: new Set([ValueReason.Other]),
1261-
context: new Set(),
1262-
};
1263-
let hasCaptureArgument = false;
1264-
for (let i = 0; i < instrValue.args.length; i++) {
1265-
const arg = instrValue.args[i];
1266-
const place = arg.kind === 'Identifier' ? arg : arg.place;
1267-
state.referenceAndRecordEffects(
1268-
freezeActions,
1269-
place,
1270-
getArgumentEffect(effects != null ? effects[i] : null, arg),
1271-
ValueReason.Other,
1272-
);
1273-
hasCaptureArgument ||= place.effect === Effect.Capture;
1274-
}
1275-
if (signature !== null) {
1276-
state.referenceAndRecordEffects(
1277-
freezeActions,
1278-
instrValue.callee,
1279-
signature.calleeEffect,
1280-
ValueReason.Other,
1281-
);
1282-
} else {
1283-
state.referenceAndRecordEffects(
1284-
freezeActions,
1285-
instrValue.callee,
1286-
Effect.ConditionallyMutate,
1287-
ValueReason.Other,
1288-
);
1289-
}
1290-
hasCaptureArgument ||= instrValue.callee.effect === Effect.Capture;
1291-
1292-
state.initialize(instrValue, returnValueKind);
1293-
state.define(instr.lvalue, instrValue);
1294-
instr.lvalue.effect = hasCaptureArgument
1295-
? Effect.Store
1296-
: Effect.ConditionallyMutate;
12971248
continuation = {kind: 'funeffects'};
12981249
break;
12991250
}
@@ -1311,102 +1262,12 @@ function inferBlock(
13111262
Effect.Read,
13121263
ValueReason.Other,
13131264
);
1314-
1315-
const signature = getFunctionCallSignature(
1316-
env,
1317-
instrValue.property.identifier.type,
1265+
inferCallEffects(
1266+
state,
1267+
instr as TInstruction<MethodCall>,
1268+
freezeActions,
1269+
getFunctionCallSignature(env, instrValue.property.identifier.type),
13181270
);
1319-
1320-
const returnValueKind: AbstractValue =
1321-
signature !== null
1322-
? {
1323-
kind: signature.returnValueKind,
1324-
reason: new Set([
1325-
signature.returnValueReason ??
1326-
ValueReason.KnownReturnSignature,
1327-
]),
1328-
context: new Set(),
1329-
}
1330-
: {
1331-
kind: ValueKind.Mutable,
1332-
reason: new Set([ValueReason.Other]),
1333-
context: new Set(),
1334-
};
1335-
1336-
if (
1337-
signature !== null &&
1338-
signature.mutableOnlyIfOperandsAreMutable &&
1339-
areArgumentsImmutableAndNonMutating(state, instrValue.args)
1340-
) {
1341-
/*
1342-
* None of the args are mutable or mutate their params, we can downgrade to
1343-
* treating as all reads (except that the receiver may be captured)
1344-
*/
1345-
for (const arg of instrValue.args) {
1346-
const place = arg.kind === 'Identifier' ? arg : arg.place;
1347-
state.referenceAndRecordEffects(
1348-
freezeActions,
1349-
place,
1350-
Effect.Read,
1351-
ValueReason.Other,
1352-
);
1353-
}
1354-
state.referenceAndRecordEffects(
1355-
freezeActions,
1356-
instrValue.receiver,
1357-
Effect.Capture,
1358-
ValueReason.Other,
1359-
);
1360-
state.initialize(instrValue, returnValueKind);
1361-
state.define(instr.lvalue, instrValue);
1362-
instr.lvalue.effect =
1363-
instrValue.receiver.effect === Effect.Capture
1364-
? Effect.Store
1365-
: Effect.ConditionallyMutate;
1366-
continuation = {kind: 'funeffects'};
1367-
break;
1368-
}
1369-
1370-
const effects =
1371-
signature !== null ? getFunctionEffects(instrValue, signature) : null;
1372-
let hasCaptureArgument = false;
1373-
for (let i = 0; i < instrValue.args.length; i++) {
1374-
const arg = instrValue.args[i];
1375-
const place = arg.kind === 'Identifier' ? arg : arg.place;
1376-
/*
1377-
* If effects are inferred for an argument, we should fail invalid
1378-
* mutating effects
1379-
*/
1380-
state.referenceAndRecordEffects(
1381-
freezeActions,
1382-
place,
1383-
getArgumentEffect(effects != null ? effects[i] : null, arg),
1384-
ValueReason.Other,
1385-
);
1386-
hasCaptureArgument ||= place.effect === Effect.Capture;
1387-
}
1388-
if (signature !== null) {
1389-
state.referenceAndRecordEffects(
1390-
freezeActions,
1391-
instrValue.receiver,
1392-
signature.calleeEffect,
1393-
ValueReason.Other,
1394-
);
1395-
} else {
1396-
state.referenceAndRecordEffects(
1397-
freezeActions,
1398-
instrValue.receiver,
1399-
Effect.ConditionallyMutate,
1400-
ValueReason.Other,
1401-
);
1402-
}
1403-
hasCaptureArgument ||= instrValue.receiver.effect === Effect.Capture;
1404-
1405-
state.initialize(instrValue, returnValueKind);
1406-
state.define(instr.lvalue, instrValue);
1407-
instr.lvalue.effect = hasCaptureArgument
1408-
? Effect.Store
1409-
: Effect.ConditionallyMutate;
14101271
continuation = {kind: 'funeffects'};
14111272
break;
14121273
}
@@ -2125,3 +1986,105 @@ function getArgumentEffect(
21251986
return Effect.ConditionallyMutate;
21261987
}
21271988
}
1989+
1990+
function inferCallEffects(
1991+
state: InferenceState,
1992+
instr: TInstruction<CallExpression> | TInstruction<MethodCall>,
1993+
freezeActions: Array<FreezeAction>,
1994+
signature: FunctionSignature | null,
1995+
): void {
1996+
const instrValue = instr.value;
1997+
const returnValueKind: AbstractValue =
1998+
signature !== null
1999+
? {
2000+
kind: signature.returnValueKind,
2001+
reason: new Set([
2002+
signature.returnValueReason ?? ValueReason.KnownReturnSignature,
2003+
]),
2004+
context: new Set(),
2005+
}
2006+
: {
2007+
kind: ValueKind.Mutable,
2008+
reason: new Set([ValueReason.Other]),
2009+
context: new Set(),
2010+
};
2011+
2012+
if (
2013+
instrValue.kind === 'MethodCall' &&
2014+
signature !== null &&
2015+
signature.mutableOnlyIfOperandsAreMutable &&
2016+
areArgumentsImmutableAndNonMutating(state, instrValue.args)
2017+
) {
2018+
/*
2019+
* None of the args are mutable or mutate their params, we can downgrade to
2020+
* treating as all reads (except that the receiver may be captured)
2021+
*/
2022+
for (const arg of instrValue.args) {
2023+
const place = arg.kind === 'Identifier' ? arg : arg.place;
2024+
state.referenceAndRecordEffects(
2025+
freezeActions,
2026+
place,
2027+
Effect.Read,
2028+
ValueReason.Other,
2029+
);
2030+
}
2031+
state.referenceAndRecordEffects(
2032+
freezeActions,
2033+
instrValue.receiver,
2034+
Effect.Capture,
2035+
ValueReason.Other,
2036+
);
2037+
state.initialize(instrValue, returnValueKind);
2038+
state.define(instr.lvalue, instrValue);
2039+
instr.lvalue.effect =
2040+
instrValue.receiver.effect === Effect.Capture
2041+
? Effect.Store
2042+
: Effect.ConditionallyMutate;
2043+
return;
2044+
}
2045+
2046+
const effects =
2047+
signature !== null ? getFunctionEffects(instrValue, signature) : null;
2048+
let hasCaptureArgument = false;
2049+
for (let i = 0; i < instrValue.args.length; i++) {
2050+
const arg = instrValue.args[i];
2051+
const place = arg.kind === 'Identifier' ? arg : arg.place;
2052+
/*
2053+
* If effects are inferred for an argument, we should fail invalid
2054+
* mutating effects
2055+
*/
2056+
state.referenceAndRecordEffects(
2057+
freezeActions,
2058+
place,
2059+
getArgumentEffect(effects != null ? effects[i] : null, arg),
2060+
ValueReason.Other,
2061+
);
2062+
hasCaptureArgument ||= place.effect === Effect.Capture;
2063+
}
2064+
const callee =
2065+
instrValue.kind === 'CallExpression'
2066+
? instrValue.callee
2067+
: instrValue.receiver;
2068+
if (signature !== null) {
2069+
state.referenceAndRecordEffects(
2070+
freezeActions,
2071+
callee,
2072+
signature.calleeEffect,
2073+
ValueReason.Other,
2074+
);
2075+
} else {
2076+
state.referenceAndRecordEffects(
2077+
freezeActions,
2078+
callee,
2079+
Effect.ConditionallyMutate,
2080+
ValueReason.Other,
2081+
);
2082+
}
2083+
hasCaptureArgument ||= callee.effect === Effect.Capture;
2084+
2085+
state.initialize(instrValue, returnValueKind);
2086+
state.define(instr.lvalue, instrValue);
2087+
instr.lvalue.effect = hasCaptureArgument
2088+
? Effect.Store
2089+
: Effect.ConditionallyMutate;
2090+
}

0 commit comments

Comments
 (0)