@samitouri / QOS-React / commits / 22360089b5

[compiler] Add Identifier.declarationId

Adds `Identifier.declarationId` and the new `DeclarationId` (simulated) opaque type. DeclarationId allows uniquely identifying a variable in the original source, ie regardless of reassignments. This allows us to stay in SSA form throughout compilation (see next diff) while still being able to distinguish SSA versions (via IdentifierId) and non-SSA versions (DeclarationId). ghstack-source-id: f2547a58aa7b30cea29fcfe23d5cb45583858a4e Pull Request resolved: https://github.com/facebook/react/pull/30569

Joe Savona committed Aug 6, 2024 at 11:24 UTC 22360089b5e40ccfa5df26f1ec491b5c46e7ad61
4 files changed +39 -40
compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts
+29 -3
@@ -1174,11 +1174,19 @@ export type NonLocalBinding =
1174
1175 // Represents a user-defined variable (has a name) or a temporary variable (no name).
1176 export type Identifier = {
1177 - /*
1178 - * unique value to distinguish a variable, since name is not guaranteed to
1179 - * exist or be unique
1177 + /**
1178 + * After EnterSSA, `id` uniquely identifies an SSA instance of a variable.
1179 + * Before EnterSSA, `id` matches `declarationId`.
1180 */
1181 id: IdentifierId;
1182 +
1183 + /**
1184 + * Uniquely identifies a given variable in the original program. If a value is
1185 + * reassigned in the original program each reassigned value will have a distinct
1186 + * `id` (after EnterSSA), but they will still have the same `declarationId`.
1187 + */
1188 + declarationId: DeclarationId;
1189 +
1190 // null for temporaries. name is primarily used for debugging.
1191 name: IdentifierName | null;
1192 // The range for which this variable is mutable
@@ -1212,6 +1220,7 @@ export function makeTemporaryIdentifier(
1220 return {
1221 id,
1222 name: null,
1223 + declarationId: makeDeclarationId(id),
1224 mutableRange: {start: makeInstructionId(0), end: makeInstructionId(0)},
1225 scope: null,
1226 type: makeType(),
@@ -1508,6 +1517,23 @@ export function makeIdentifierId(id: number): IdentifierId {
1517 return id as IdentifierId;
1518 }
1519
1520 +/*
1521 + * Simulated opaque type for IdentifierId to prevent using normal numbers as ids
1522 + * accidentally.
1523 + */
1524 +const opageDeclarationId = Symbol();
1525 +export type DeclarationId = number & {[opageDeclarationId]: 'DeclarationId'};
1526 +
1527 +export function makeDeclarationId(id: number): DeclarationId {
1528 + CompilerError.invariant(id >= 0 && Number.isInteger(id), {
1529 + reason: 'Expected declaration id to be a non-negative integer',
1530 + description: null,
1531 + loc: null,
1532 + suggestions: null,
1533 + });
1534 + return id as DeclarationId;
1535 +}
1536 +
1537 /*
1538 * Simulated opaque type for InstructionId to prevent using normal numbers as ids
1539 * accidentally.
compiler/packages/babel-plugin-react-compiler/src/HIR/HIRBuilder.ts
+2
@@ -25,6 +25,7 @@ import {
25 Terminal,
26 VariableBinding,
27 makeBlockId,
28 + makeDeclarationId,
29 makeIdentifierName,
30 makeInstructionId,
31 makeTemporaryIdentifier,
@@ -320,6 +321,7 @@ export default class HIRBuilder {
321 const id = this.nextIdentifierId;
322 const identifier: Identifier = {
323 id,
324 + declarationId: makeDeclarationId(id),
325 name: makeIdentifierName(name),
326 mutableRange: {
327 start: makeInstructionId(0),
compiler/packages/babel-plugin-react-compiler/src/Inference/InlineImmediatelyInvokedFunctionExpressions.ts
+7 -37
@@ -8,7 +8,6 @@
8 import {
9 BasicBlock,
10 BlockId,
11 - Effect,
11 Environment,
12 FunctionExpression,
13 GeneratedSource,
@@ -19,11 +18,14 @@ import {
18 LabelTerminal,
19 Place,
20 makeInstructionId,
22 - makeType,
21 promoteTemporary,
22 reversePostorderBlocks,
23 } from '../HIR';
26 -import {markInstructionIds, markPredecessors} from '../HIR/HIRBuilder';
24 +import {
25 + createTemporaryPlace,
26 + markInstructionIds,
27 + markPredecessors,
28 +} from '../HIR/HIRBuilder';
29 import {eachInstructionValueOperand} from '../HIR/visitors';
30 import {retainWhere} from '../Utils/utils';
31
@@ -225,23 +227,7 @@ function rewriteBlock(
227 block.instructions.push({
228 id: makeInstructionId(0),
229 loc: terminal.loc,
228 - lvalue: {
229 - effect: Effect.Unknown,
230 - identifier: {
231 - id: env.nextIdentifierId,
232 - mutableRange: {
233 - start: makeInstructionId(0),
234 - end: makeInstructionId(0),
235 - },
236 - name: null,
237 - scope: null,
238 - type: makeType(),
239 - loc: terminal.loc,
240 - },
241 - kind: 'Identifier',
242 - reactive: false,
243 - loc: terminal.loc,
244 - },
230 + lvalue: createTemporaryPlace(env, terminal.loc),
231 value: {
232 kind: 'StoreLocal',
233 lvalue: {kind: InstructionKind.Reassign, place: {...returnValue}},
@@ -267,23 +253,7 @@ function declareTemporary(
253 block.instructions.push({
254 id: makeInstructionId(0),
255 loc: GeneratedSource,
270 - lvalue: {
271 - effect: Effect.Unknown,
272 - identifier: {
273 - id: env.nextIdentifierId,
274 - mutableRange: {
275 - start: makeInstructionId(0),
276 - end: makeInstructionId(0),
277 - },
278 - name: null,
279 - scope: null,
280 - type: makeType(),
281 - loc: result.loc,
282 - },
283 - kind: 'Identifier',
284 - reactive: false,
285 - loc: GeneratedSource,
286 - },
256 + lvalue: createTemporaryPlace(env, result.loc),
257 value: {
258 kind: 'DeclareLocal',
259 lvalue: {
compiler/packages/babel-plugin-react-compiler/src/SSA/EnterSSA.ts
+1
@@ -79,6 +79,7 @@ class SSABuilder {
79 makeId(oldId: Identifier): Identifier {
80 return {
81 id: this.nextSsaId,
82 + declarationId: oldId.declarationId,
83 name: oldId.name,
84 mutableRange: {
85 start: makeInstructionId(0),