Dont memoize calls that produce primitive values

Teaches InferReactiveScopeVariables that calls can produce primitives that don't 
need a scope.
This commit is contained in:
Joe Savona
2023-05-18 16:05:32 -07:00
parent 5008448d74
commit 94e2ae5893
5 changed files with 37 additions and 38 deletions
@@ -1013,7 +1013,7 @@ function hasContextRefOperand(
return false;
}
function getFunctionCallSignature(
export function getFunctionCallSignature(
env: Environment,
type: Type
): FunctionSignature | null {
@@ -5,6 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/
import { Environment } from "../HIR";
import {
HIRFunction,
Identifier,
@@ -20,6 +21,7 @@ import {
eachInstructionOperand,
eachPatternOperand,
} from "../HIR/visitors";
import { getFunctionCallSignature } from "../Inference/InferReferenceEffects";
import DisjointSet from "../Utils/DisjointSet";
import { assertExhaustive } from "../Utils/utils";
@@ -103,7 +105,7 @@ export function inferReactiveScopeVariables(fn: HIRFunction): void {
for (const instr of block.instructions) {
const operands: Array<Identifier> = [];
const range = instr.lvalue.identifier.mutableRange;
if (range.end > range.start + 1 || mayAllocate(instr.value)) {
if (range.end > range.start + 1 || mayAllocate(fn.env, instr.value)) {
operands.push(instr.lvalue!.identifier);
}
if (
@@ -217,7 +219,7 @@ function isMutable({ id }: Instruction, place: Place): boolean {
return id >= range.start && id < range.end;
}
function mayAllocate(value: InstructionValue): boolean {
function mayAllocate(env: Environment, value: InstructionValue): boolean {
switch (value.kind) {
case "Destructure": {
return doesPatternContainSpreadElement(value.lvalue.pattern);
@@ -245,12 +247,30 @@ function mayAllocate(value: InstructionValue): boolean {
case "Debugger": {
return false;
}
case "CallExpression": {
const signature = getFunctionCallSignature(
env,
value.callee.identifier.type
);
if (signature !== null) {
return signature.returnType.kind !== "Primitive";
}
return true;
}
case "MethodCall": {
const signature = getFunctionCallSignature(
env,
value.receiver.identifier.type
);
if (signature !== null) {
return signature.returnType.kind !== "Primitive";
}
return true;
}
case "RegExpLiteral":
case "MethodCall":
case "PropertyStore":
case "ComputedStore":
case "ArrayExpression":
case "CallExpression":
case "JsxExpression":
case "JsxFragment":
case "NewExpression":
@@ -15,7 +15,7 @@ function Component(props) {
```javascript
import { unstable_useMemoCache as useMemoCache } from "react";
function Component(props) {
const $ = useMemoCache(3);
const $ = useMemoCache(2);
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t0 = {};
@@ -24,22 +24,15 @@ function Component(props) {
t0 = $[0];
}
const x = t0;
const y = Boolean(x);
let t1;
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
t1 = Boolean(x);
t1 = [x, y];
$[1] = t1;
} else {
t1 = $[1];
}
const y = t1;
let t2;
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
t2 = [x, y];
$[2] = t2;
} else {
t2 = $[2];
}
return t2;
return t1;
}
```
@@ -15,7 +15,7 @@ function Component(props) {
```javascript
import { unstable_useMemoCache as useMemoCache } from "react";
function Component(props) {
const $ = useMemoCache(3);
const $ = useMemoCache(2);
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t0 = {};
@@ -24,22 +24,15 @@ function Component(props) {
t0 = $[0];
}
const x = t0;
const y = Number(x);
let t1;
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
t1 = Number(x);
t1 = [x, y];
$[1] = t1;
} else {
t1 = $[1];
}
const y = t1;
let t2;
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
t2 = [x, y];
$[2] = t2;
} else {
t2 = $[2];
}
return t2;
return t1;
}
```
@@ -15,7 +15,7 @@ function Component(props) {
```javascript
import { unstable_useMemoCache as useMemoCache } from "react";
function Component(props) {
const $ = useMemoCache(3);
const $ = useMemoCache(2);
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t0 = {};
@@ -24,22 +24,15 @@ function Component(props) {
t0 = $[0];
}
const x = t0;
const y = String(x);
let t1;
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
t1 = String(x);
t1 = [x, y];
$[1] = t1;
} else {
t1 = $[1];
}
const y = t1;
let t2;
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
t2 = [x, y];
$[2] = t2;
} else {
t2 = $[2];
}
return t2;
return t1;
}
```