Skip to content

Commit

Permalink
[compiler] Option to always take the non-memo branch
Browse files Browse the repository at this point in the history
Summary: This adds a debugging mode to the compiler that simply adds a `|| true` to the guard on all memoization blocks, which results in the generated code never using memoized values and always recomputing them. This is designed as a validation tool for the compiler's correctness--every program *should* behave exactly the same with this option enabled as it would with it disabled, and so any difference in behavior should be investigated as either a compiler bug or a pipeline issue.

(We add `|| true` rather than dropping the conditional block entirely because we still want to exercise the guard tests, in case the guards themselves are the source of an error, like reading a property from undefined in a guard.)

ghstack-source-id: 955a47ec1689842da82552225a19a1008c57fe2c
Pull Request resolved: #29655
  • Loading branch information
mvitousek committed May 31, 2024
1 parent 28fe581 commit 8b01a2e
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,10 @@ function* runWithEnvironment(
validateContextVariableLValues(hir);
validateUseMemo(hir);

if (!env.config.enablePreserveExistingManualUseMemo) {
if (
!env.config.enablePreserveExistingManualUseMemo &&
!env.config.disableMemoizationForDebugging
) {
dropManualMemoization(hir);
yield log({ kind: "hir", name: "DropManualMemoization", value: hir });
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,15 @@ const EnvironmentConfigSchema = z.object({
*/
enableTreatFunctionDepsAsConditional: z.boolean().default(false),

/**
* When true, always act as though the dependencies of a memoized value
* have changed. This makes the compiler not actually perform any optimizations,
* but is useful for debugging. Implicitly also sets
* @enablePreserveExistingManualUseMemo, because otherwise memoization in the
* original source will be disabled as well.
*/
disableMemoizationForDebugging: z.boolean().default(false),

/**
* The react native re-animated library uses custom Babel transforms that
* requires the calls to library API remain unmodified.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,14 @@ function codegenReactiveScope(
);
}

if (cx.env.config.disableMemoizationForDebugging) {
testCondition = t.logicalExpression(
"||",
testCondition,
t.booleanLiteral(true)
);
}

let computationBlock = codegenBlock(cx, block);
computationBlock.body.push(...cacheStoreStatements);
const memoBlock = t.blockStatement(cacheLoadStatements);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@

## Input

```javascript
// @disableMemoizationForDebugging
import { useMemo } from "react";

function Component({ a }) {
let x = useMemo(() => [a], []);
return <div>{x}</div>;
}

export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{ a: 42 }],
isComponent: true,
};

```

## Code

```javascript
import { c as _c } from "react/compiler-runtime"; // @disableMemoizationForDebugging
import { useMemo } from "react";

function Component(t0) {
const $ = _c(5);
const { a } = t0;
let t1;
if ($[0] !== a || true) {
t1 = () => [a];
$[0] = a;
$[1] = t1;
} else {
t1 = $[1];
}
let t2;
if ($[2] === Symbol.for("react.memo_cache_sentinel") || true) {
t2 = [];
$[2] = t2;
} else {
t2 = $[2];
}
const x = useMemo(t1, t2);
let t3;
if ($[3] !== x || true) {
t3 = <div>{x}</div>;
$[3] = x;
$[4] = t3;
} else {
t3 = $[4];
}
return t3;
}

export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{ a: 42 }],
isComponent: true,
};

```
### Eval output
(kind: ok) <div>42</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// @disableMemoizationForDebugging
import { useMemo } from "react";

function Component({ a }) {
let x = useMemo(() => [a], []);
return <div>{x}</div>;
}

export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{ a: 42 }],
isComponent: true,
};

0 comments on commit 8b01a2e

Please sign in to comment.