Memoize based on inferred return type, not signature
Joe Savona committed
May 22, 2023 at 09:20 UTC
d456e4a78ccf1cf607a46e802c67eb1442657300
3 files changed
+22
-58
compiler/forget/src/ReactiveScopes/InferReactiveScopeVariables.ts
+5
-23
@@ -10,7 +10,6 @@ import {
10
HIRFunction,
11
Identifier,
12
Instruction,
13
- InstructionValue,
13
makeInstructionId,
14
makeScopeId,
15
Place,
@@ -21,7 +20,6 @@ import {
20
eachInstructionOperand,
21
eachPatternOperand,
22
} from "../HIR/visitors";
24
-import { getFunctionCallSignature } from "../Inference/InferReferenceEffects";
23
import DisjointSet from "../Utils/DisjointSet";
24
import { assertExhaustive } from "../Utils/utils";
25
@@ -105,7 +103,7 @@ export function inferReactiveScopeVariables(fn: HIRFunction): void {
103
for (const instr of block.instructions) {
104
const operands: Array<Identifier> = [];
105
const range = instr.lvalue.identifier.mutableRange;
108
- if (range.end > range.start + 1 || mayAllocate(fn.env, instr.value)) {
106
+ if (range.end > range.start + 1 || mayAllocate(fn.env, instr)) {
107
operands.push(instr.lvalue!.identifier);
108
}
109
if (
@@ -219,7 +217,8 @@ function isMutable({ id }: Instruction, place: Place): boolean {
217
return id >= range.start && id < range.end;
218
}
219
222
-function mayAllocate(env: Environment, value: InstructionValue): boolean {
220
+function mayAllocate(env: Environment, instruction: Instruction): boolean {
221
+ const { value } = instruction;
222
switch (value.kind) {
223
case "Destructure": {
224
return doesPatternContainSpreadElement(value.lvalue.pattern);
@@ -247,27 +246,10 @@ function mayAllocate(env: Environment, value: InstructionValue): boolean {
246
case "Debugger": {
247
return false;
248
}
250
- case "CallExpression": {
251
- if (env.enableFunctionCallSignatureOptimizations) {
252
- const signature = getFunctionCallSignature(
253
- env,
254
- value.callee.identifier.type
255
- );
256
- if (signature !== null) {
257
- return signature.returnType.kind !== "Primitive";
258
- }
259
- }
260
- return true;
261
- }
249
+ case "CallExpression":
250
case "MethodCall": {
251
if (env.enableFunctionCallSignatureOptimizations) {
264
- const signature = getFunctionCallSignature(
265
- env,
266
- value.receiver.identifier.type
267
- );
268
- if (signature !== null) {
269
- return signature.returnType.kind !== "Primitive";
270
- }
252
+ return instruction.lvalue.identifier.type.kind !== "Primitive";
253
}
254
return true;
255
}
compiler/forget/src/__tests__/fixtures/compiler/infer-global-object.expect.md
+10
-21
@@ -24,7 +24,7 @@ function Component(props) {
24
import { unstable_useMemoCache as useMemoCache } from "react"; // Check that we correctly resolve type and effect lookups on the javascript
25
// global object.
26
function Component(props) {
27
- const $ = useMemoCache(7);
27
+ const $ = useMemoCache(4);
28
const c_0 = $[0] !== props.b;
29
let t0;
30
if (c_0) {
@@ -35,32 +35,21 @@ function Component(props) {
35
t0 = $[1];
36
}
37
const neverAliasedOrMutated = t0;
38
- const c_2 = $[2] !== props.a;
39
- const c_3 = $[3] !== neverAliasedOrMutated;
40
- let t1;
41
- if (c_2 || c_3) {
42
- t1 = Math.max(props.a, neverAliasedOrMutated);
43
- $[2] = props.a;
44
- $[3] = neverAliasedOrMutated;
45
- $[4] = t1;
46
- } else {
47
- t1 = $[4];
48
- }
49
- const primitiveVal1 = t1;
38
+ const primitiveVal1 = Math.max(props.a, neverAliasedOrMutated);
39
40
const primitiveVal3 = globaThis.globalThis.NaN;
41
42
foo(primitiveVal1, Infinity, primitiveVal3);
54
- const c_5 = $[5] !== primitiveVal1;
55
- let t2;
56
- if (c_5) {
57
- t2 = { primitiveVal1, primitiveVal2: Infinity, primitiveVal3 };
58
- $[5] = primitiveVal1;
59
- $[6] = t2;
43
+ const c_2 = $[2] !== primitiveVal1;
44
+ let t1;
45
+ if (c_2) {
46
+ t1 = { primitiveVal1, primitiveVal2: Infinity, primitiveVal3 };
47
+ $[2] = primitiveVal1;
48
+ $[3] = t1;
49
} else {
61
- t2 = $[6];
50
+ t1 = $[3];
51
}
63
- return t2;
52
+ return t1;
53
}
54
55
```
compiler/forget/src/__tests__/fixtures/compiler/type-test-polymorphic.expect.md
+7
-14
@@ -24,33 +24,26 @@ function component() {
24
```javascript
25
import { unstable_useMemoCache as useMemoCache } from "react";
26
function component() {
27
- const $ = useMemoCache(3);
27
+ const $ = useMemoCache(2);
28
+ const p = makePrimitive();
29
let t0;
30
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
30
- t0 = makePrimitive();
31
+ t0 = {};
32
$[0] = t0;
33
} else {
34
t0 = $[0];
35
}
35
- const p = t0;
36
- let t1;
37
- if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
38
- t1 = {};
39
- $[1] = t1;
40
- } else {
41
- t1 = $[1];
42
- }
43
- const o = t1;
36
+ const o = t0;
37
let x;
45
- if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
38
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
39
x = {};
40
41
x.t = p;
42
43
x.t = o;
51
- $[2] = x;
44
+ $[1] = x;
45
} else {
53
- x = $[2];
46
+ x = $[1];
47
}
48
const y = x.t;
49
return y;