From 3c976a24b3eb25557e69448416015486dd75c0b8 Mon Sep 17 00:00:00 2001 From: Sathya Gunasekaran Date: Mon, 12 Dec 2022 20:35:23 +0000 Subject: [PATCH] [hir] Run mutable range analysis for aliases to fix point --- compiler/forget/src/HIR/DisjointSet.ts | 4 + compiler/forget/src/HIR/InferMutableRanges.ts | 17 +++-- .../alias-nested-member-path-mutate.expect.md | 64 ++++++++++++++++ .../hir/alias-nested-member-path-mutate.js | 8 ++ .../hir/alias-nested-member-path.expect.md | 65 ++++++++++++++++ .../fixtures/hir/alias-nested-member-path.js | 8 ++ .../hir/transitive-alias-fields.expect.md | 74 +++++++++++++++++++ .../fixtures/hir/transitive-alias-fields.js | 12 +++ 8 files changed, 245 insertions(+), 7 deletions(-) create mode 100644 compiler/forget/src/__tests__/fixtures/hir/alias-nested-member-path-mutate.expect.md create mode 100644 compiler/forget/src/__tests__/fixtures/hir/alias-nested-member-path-mutate.js create mode 100644 compiler/forget/src/__tests__/fixtures/hir/alias-nested-member-path.expect.md create mode 100644 compiler/forget/src/__tests__/fixtures/hir/alias-nested-member-path.js create mode 100644 compiler/forget/src/__tests__/fixtures/hir/transitive-alias-fields.expect.md create mode 100644 compiler/forget/src/__tests__/fixtures/hir/transitive-alias-fields.js diff --git a/compiler/forget/src/HIR/DisjointSet.ts b/compiler/forget/src/HIR/DisjointSet.ts index 9ced0bd61c..6710777232 100644 --- a/compiler/forget/src/HIR/DisjointSet.ts +++ b/compiler/forget/src/HIR/DisjointSet.ts @@ -83,4 +83,8 @@ export default class DisjointSet { fn(item, group); } } + + get size(): number { + return this.#entries.size; + } } diff --git a/compiler/forget/src/HIR/InferMutableRanges.ts b/compiler/forget/src/HIR/InferMutableRanges.ts index b38b354b5f..fadadf5913 100644 --- a/compiler/forget/src/HIR/InferMutableRanges.ts +++ b/compiler/forget/src/HIR/InferMutableRanges.ts @@ -5,17 +5,20 @@ import { inferMutableLifetimes } from "./InferMutableLifetimes"; import { inferMutableRangesForAlias } from "./InferMutableRangesForAlias"; export function inferMutableRanges(ir: HIRFunction) { - // Calculate aliases - const aliases = inferAliases(ir); - // Infer mutable ranges for non fields inferMutableLifetimes(ir, false); - // Infer mutable ranges for aliases that are not fields - inferMutableRangesForAlias(aliases); + // Calculate aliases + const aliases = inferAliases(ir); + let size = aliases.size; + do { + size = aliases.size; + // Infer mutable ranges for aliases that are not fields + inferMutableRangesForAlias(aliases); - // Update aliasing information of fields - inferAliasForFields(ir, aliases); + // Update aliasing information of fields + inferAliasForFields(ir, aliases); + } while (aliases.size > size); // Re-infer mutable ranges for all values inferMutableLifetimes(ir, true); diff --git a/compiler/forget/src/__tests__/fixtures/hir/alias-nested-member-path-mutate.expect.md b/compiler/forget/src/__tests__/fixtures/hir/alias-nested-member-path-mutate.expect.md new file mode 100644 index 0000000000..4dacc57104 --- /dev/null +++ b/compiler/forget/src/__tests__/fixtures/hir/alias-nested-member-path-mutate.expect.md @@ -0,0 +1,64 @@ + +## Input + +```javascript +function component() { + let z = []; + let y = {}; + y.z = z; + let x = {}; + x.y = y; + mutate(x.y.z); +} + +``` + +## HIR + +``` +bb0: + [1] Const mutate z$5_@0[0:7] = Array [] + [2] Const mutate y$6_@0[0:7] = Object { } + [3] Reassign mutate y$6_@0.z[0:7] = read z$5_@0 + [4] Const mutate x$7_@0[0:7] = Object { } + [5] Reassign mutate x$7_@0.y[0:7] = read y$6_@0 + [6] Call mutate mutate$4_@0(mutate x$7_@0.y.z) + [7] Return + +``` + +### CFG + +```mermaid +flowchart TB + %% Basic Blocks + subgraph bb0 + bb0_instrs[" + [1] Const mutate z$5_@0[0:7] = Array [] + [2] Const mutate y$6_@0[0:7] = Object { } + [3] Reassign mutate y$6_@0.z[0:7] = read z$5_@0 + [4] Const mutate x$7_@0[0:7] = Object { } + [5] Reassign mutate x$7_@0.y[0:7] = read y$6_@0 + [6] Call mutate mutate$4_@0(mutate x$7_@0.y.z) + "] + bb0_instrs --> bb0_terminal(["Return"]) + end + + %% Jumps + %% empty +``` + +## Code + +```javascript +function component$0() { + const z$5 = []; + const y$6 = {}; + y$6.z = z$5; + const x$7 = {}; + x$7.y = y$6; + mutate$4(x$7.y.z); +} + +``` + \ No newline at end of file diff --git a/compiler/forget/src/__tests__/fixtures/hir/alias-nested-member-path-mutate.js b/compiler/forget/src/__tests__/fixtures/hir/alias-nested-member-path-mutate.js new file mode 100644 index 0000000000..d7cc5710b2 --- /dev/null +++ b/compiler/forget/src/__tests__/fixtures/hir/alias-nested-member-path-mutate.js @@ -0,0 +1,8 @@ +function component() { + let z = []; + let y = {}; + y.z = z; + let x = {}; + x.y = y; + mutate(x.y.z); +} diff --git a/compiler/forget/src/__tests__/fixtures/hir/alias-nested-member-path.expect.md b/compiler/forget/src/__tests__/fixtures/hir/alias-nested-member-path.expect.md new file mode 100644 index 0000000000..0059fc662e --- /dev/null +++ b/compiler/forget/src/__tests__/fixtures/hir/alias-nested-member-path.expect.md @@ -0,0 +1,65 @@ + +## Input + +```javascript +function component() { + let z = []; + let y = {}; + y.z = z; + let x = {}; + x.y = y; + return x; +} + +``` + +## HIR + +``` +bb0: + [1] Const mutate z$4_@0 = Array [] + [2] Const mutate y$5_@1[2:4] = Object { } + [3] Reassign mutate y$5_@1.z[2:4] = read z$4_@0 + [4] Const mutate x$6_@2[4:6] = Object { } + [5] Reassign mutate x$6_@2.y[4:6] = read y$5_@1 + [6] Return freeze x$6_@2 +scope1 [2:4]: + - dependency: read z$4_@0 +scope2 [4:6]: + - dependency: read y$5_@1 +``` + +### CFG + +```mermaid +flowchart TB + %% Basic Blocks + subgraph bb0 + bb0_instrs[" + [1] Const mutate z$4_@0 = Array [] + [2] Const mutate y$5_@1[2:4] = Object { } + [3] Reassign mutate y$5_@1.z[2:4] = read z$4_@0 + [4] Const mutate x$6_@2[4:6] = Object { } + [5] Reassign mutate x$6_@2.y[4:6] = read y$5_@1 + "] + bb0_instrs --> bb0_terminal(["Return freeze x$6_@2"]) + end + + %% Jumps + %% empty +``` + +## Code + +```javascript +function component$0() { + const z$4 = []; + const y$5 = {}; + y$5.z = z$4; + const x$6 = {}; + x$6.y = y$5; + return x$6; +} + +``` + \ No newline at end of file diff --git a/compiler/forget/src/__tests__/fixtures/hir/alias-nested-member-path.js b/compiler/forget/src/__tests__/fixtures/hir/alias-nested-member-path.js new file mode 100644 index 0000000000..11ab613cb7 --- /dev/null +++ b/compiler/forget/src/__tests__/fixtures/hir/alias-nested-member-path.js @@ -0,0 +1,8 @@ +function component() { + let z = []; + let y = {}; + y.z = z; + let x = {}; + x.y = y; + return x; +} diff --git a/compiler/forget/src/__tests__/fixtures/hir/transitive-alias-fields.expect.md b/compiler/forget/src/__tests__/fixtures/hir/transitive-alias-fields.expect.md new file mode 100644 index 0000000000..4766d851df --- /dev/null +++ b/compiler/forget/src/__tests__/fixtures/hir/transitive-alias-fields.expect.md @@ -0,0 +1,74 @@ + +## Input + +```javascript +function component() { + let x = {}; + let p = {}; + let q = {}; + let y = {}; + + x.y = y; + p.y = x.y; + q.y = p.y; + + mutate(q); +} + +``` + +## HIR + +``` +bb0: + [1] Const mutate x$6_@0[0:9] = Object { } + [2] Const mutate p$7_@0[0:9] = Object { } + [3] Const mutate q$8_@0[0:9] = Object { } + [4] Const mutate y$9_@0[0:9] = Object { } + [5] Reassign mutate x$6_@0.y[0:9] = read y$9_@0 + [6] Reassign mutate p$7_@0.y[0:9] = read x$6_@0.y + [7] Reassign mutate q$8_@0.y[0:9] = read p$7_@0.y + [8] Call mutate mutate$5_@0(mutate q$8_@0) + [9] Return + +``` + +### CFG + +```mermaid +flowchart TB + %% Basic Blocks + subgraph bb0 + bb0_instrs[" + [1] Const mutate x$6_@0[0:9] = Object { } + [2] Const mutate p$7_@0[0:9] = Object { } + [3] Const mutate q$8_@0[0:9] = Object { } + [4] Const mutate y$9_@0[0:9] = Object { } + [5] Reassign mutate x$6_@0.y[0:9] = read y$9_@0 + [6] Reassign mutate p$7_@0.y[0:9] = read x$6_@0.y + [7] Reassign mutate q$8_@0.y[0:9] = read p$7_@0.y + [8] Call mutate mutate$5_@0(mutate q$8_@0) + "] + bb0_instrs --> bb0_terminal(["Return"]) + end + + %% Jumps + %% empty +``` + +## Code + +```javascript +function component$0() { + const x$6 = {}; + const p$7 = {}; + const q$8 = {}; + const y$9 = {}; + x$6.y = y$9; + p$7.y = x$6.y; + q$8.y = p$7.y; + mutate$5(q$8); +} + +``` + \ No newline at end of file diff --git a/compiler/forget/src/__tests__/fixtures/hir/transitive-alias-fields.js b/compiler/forget/src/__tests__/fixtures/hir/transitive-alias-fields.js new file mode 100644 index 0000000000..a06e29f867 --- /dev/null +++ b/compiler/forget/src/__tests__/fixtures/hir/transitive-alias-fields.js @@ -0,0 +1,12 @@ +function component() { + let x = {}; + let p = {}; + let q = {}; + let y = {}; + + x.y = y; + p.y = x.y; + q.y = p.y; + + mutate(q); +}