[hir] Use a stable identity for undefined value

InferReferenceEffects uses object identity to merge states, which breaks when we 
create a new object to model `undefined`. 

Two value objects representing `undefined` are not equal due to referential 
equality. 

Instead, let's use a singleton to represent `undefined` value.
This commit is contained in:
Sathya Gunasekaran
2023-10-04 12:11:35 +05:30
parent b7a14ecc8d
commit 3aaf8be25c
6 changed files with 97 additions and 5 deletions
@@ -12,6 +12,7 @@ import {
BlockId,
CallExpression,
Effect,
GeneratedSource,
HIRFunction,
IdentifierId,
InstructionKind,
@@ -39,6 +40,12 @@ import {
} from "../HIR/visitors";
import { assertExhaustive } from "../Utils/utils";
const UndefinedValue: InstructionValue = {
kind: "Primitive",
loc: GeneratedSource,
value: undefined,
};
/**
* For every usage of a value in the given function, infers the effect or action
* taken at that reference. Each reference is inferred as exactly one of:
@@ -933,11 +940,7 @@ function inferBlock(
continue;
}
case "DeclareLocal": {
const value: InstructionValue = {
kind: "Primitive",
loc: instrValue.loc,
value: undefined,
};
const value = UndefinedValue;
state.initialize(
value,
// Catch params may be aliased to mutable values
@@ -0,0 +1,46 @@
## Input
```javascript
function useFoo() {
for (let i = 0; i <= 5; i++) {
let color;
if (isSelected) {
color = isCurrent ? "#FFCC22" : "#FF5050";
} else {
color = isCurrent ? "#CCFF03" : "#CCCCCC";
}
console.log(color);
}
}
export const FIXTURE_ENTRYPOINT = {
params: [],
fn: useFoo,
};
```
## Code
```javascript
function useFoo() {
for (let i = 0; i <= 5; i++) {
let color = undefined;
if (isSelected) {
color = isCurrent ? "#FFCC22" : "#FF5050";
} else {
color = isCurrent ? "#CCFF03" : "#CCCCCC";
}
console.log(color);
}
}
export const FIXTURE_ENTRYPOINT = {
params: [],
fn: useFoo,
};
```
@@ -0,0 +1,16 @@
function useFoo() {
for (let i = 0; i <= 5; i++) {
let color;
if (isSelected) {
color = isCurrent ? "#FFCC22" : "#FF5050";
} else {
color = isCurrent ? "#CCFF03" : "#CCCCCC";
}
console.log(color);
}
}
export const FIXTURE_ENTRYPOINT = {
params: [],
fn: useFoo,
};
@@ -0,0 +1,21 @@
## Input
```javascript
function useFoo() {
while (1) {
let foo;
}
}
```
## Code
```javascript
function useFoo() {
while (1) {}
}
```
@@ -0,0 +1,5 @@
function useFoo() {
while (1) {
let foo;
}
}
@@ -461,6 +461,7 @@ const skipFilter = new Set([
"fbtparam-with-jsx-fragment-value",
"fbt-preserve-jsxtext",
"useContext-mutable-value",
"loop-unused-let",
]);
export default skipFilter;