Dont memoize calls that produce primitive values
Teaches InferReactiveScopeVariables that calls can produce primitives that don't need a scope.
Joe Savona committed
May 18, 2023 at 16:05 UTC
94e2ae5893328ef2f7c5c2269413f545546ed350
5 files changed
+37
-38
compiler/forget/src/Inference/InferReferenceEffects.ts
+1
-1
@@ -1013,7 +1013,7 @@ function hasContextRefOperand(
1013
return false;
1014
}
1015
1016
-function getFunctionCallSignature(
1016
+export function getFunctionCallSignature(
1017
env: Environment,
1018
type: Type
1019
): FunctionSignature | null {
compiler/forget/src/ReactiveScopes/InferReactiveScopeVariables.ts
+24
-4
@@ -5,6 +5,7 @@
5
* LICENSE file in the root directory of this source tree.
6
*/
7
8
+import { Environment } from "../HIR";
9
import {
10
HIRFunction,
11
Identifier,
@@ -20,6 +21,7 @@ import {
21
eachInstructionOperand,
22
eachPatternOperand,
23
} from "../HIR/visitors";
24
+import { getFunctionCallSignature } from "../Inference/InferReferenceEffects";
25
import DisjointSet from "../Utils/DisjointSet";
26
import { assertExhaustive } from "../Utils/utils";
27
@@ -103,7 +105,7 @@ export function inferReactiveScopeVariables(fn: HIRFunction): void {
105
for (const instr of block.instructions) {
106
const operands: Array<Identifier> = [];
107
const range = instr.lvalue.identifier.mutableRange;
106
- if (range.end > range.start + 1 || mayAllocate(instr.value)) {
108
+ if (range.end > range.start + 1 || mayAllocate(fn.env, instr.value)) {
109
operands.push(instr.lvalue!.identifier);
110
}
111
if (
@@ -217,7 +219,7 @@ function isMutable({ id }: Instruction, place: Place): boolean {
219
return id >= range.start && id < range.end;
220
}
221
220
-function mayAllocate(value: InstructionValue): boolean {
222
+function mayAllocate(env: Environment, value: InstructionValue): boolean {
223
switch (value.kind) {
224
case "Destructure": {
225
return doesPatternContainSpreadElement(value.lvalue.pattern);
@@ -245,12 +247,30 @@ function mayAllocate(value: InstructionValue): boolean {
247
case "Debugger": {
248
return false;
249
}
250
+ case "CallExpression": {
251
+ const signature = getFunctionCallSignature(
252
+ env,
253
+ value.callee.identifier.type
254
+ );
255
+ if (signature !== null) {
256
+ return signature.returnType.kind !== "Primitive";
257
+ }
258
+ return true;
259
+ }
260
+ case "MethodCall": {
261
+ const signature = getFunctionCallSignature(
262
+ env,
263
+ value.receiver.identifier.type
264
+ );
265
+ if (signature !== null) {
266
+ return signature.returnType.kind !== "Primitive";
267
+ }
268
+ return true;
269
+ }
270
case "RegExpLiteral":
249
- case "MethodCall":
271
case "PropertyStore":
272
case "ComputedStore":
273
case "ArrayExpression":
253
- case "CallExpression":
274
case "JsxExpression":
275
case "JsxFragment":
276
case "NewExpression":
compiler/forget/src/__tests__/fixtures/compiler/globals-Boolean.expect.md
+4
-11
@@ -15,7 +15,7 @@ function Component(props) {
15
```javascript
16
import { unstable_useMemoCache as useMemoCache } from "react";
17
function Component(props) {
18
- const $ = useMemoCache(3);
18
+ const $ = useMemoCache(2);
19
let t0;
20
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
21
t0 = {};
@@ -24,22 +24,15 @@ function Component(props) {
24
t0 = $[0];
25
}
26
const x = t0;
27
+ const y = Boolean(x);
28
let t1;
29
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
29
- t1 = Boolean(x);
30
+ t1 = [x, y];
31
$[1] = t1;
32
} else {
33
t1 = $[1];
34
}
34
- const y = t1;
35
- let t2;
36
- if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
37
- t2 = [x, y];
38
- $[2] = t2;
39
- } else {
40
- t2 = $[2];
41
- }
42
- return t2;
35
+ return t1;
36
}
37
38
```
compiler/forget/src/__tests__/fixtures/compiler/globals-Number.expect.md
+4
-11
@@ -15,7 +15,7 @@ function Component(props) {
15
```javascript
16
import { unstable_useMemoCache as useMemoCache } from "react";
17
function Component(props) {
18
- const $ = useMemoCache(3);
18
+ const $ = useMemoCache(2);
19
let t0;
20
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
21
t0 = {};
@@ -24,22 +24,15 @@ function Component(props) {
24
t0 = $[0];
25
}
26
const x = t0;
27
+ const y = Number(x);
28
let t1;
29
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
29
- t1 = Number(x);
30
+ t1 = [x, y];
31
$[1] = t1;
32
} else {
33
t1 = $[1];
34
}
34
- const y = t1;
35
- let t2;
36
- if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
37
- t2 = [x, y];
38
- $[2] = t2;
39
- } else {
40
- t2 = $[2];
41
- }
42
- return t2;
35
+ return t1;
36
}
37
38
```
compiler/forget/src/__tests__/fixtures/compiler/globals-String.expect.md
+4
-11
@@ -15,7 +15,7 @@ function Component(props) {
15
```javascript
16
import { unstable_useMemoCache as useMemoCache } from "react";
17
function Component(props) {
18
- const $ = useMemoCache(3);
18
+ const $ = useMemoCache(2);
19
let t0;
20
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
21
t0 = {};
@@ -24,22 +24,15 @@ function Component(props) {
24
t0 = $[0];
25
}
26
const x = t0;
27
+ const y = String(x);
28
let t1;
29
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
29
- t1 = String(x);
30
+ t1 = [x, y];
31
$[1] = t1;
32
} else {
33
t1 = $[1];
34
}
34
- const y = t1;
35
- let t2;
36
- if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
37
- t2 = [x, y];
38
- $[2] = t2;
39
- } else {
40
- t2 = $[2];
41
- }
42
- return t2;
35
+ return t1;
36
}
37
38
```