mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
[hir] Add alias analysis for lvalue aggregates
This adds a field sensitive, flow-insensitive, context-insensitive alias analysis for lvalue aggregates. In the future, InferMutableLifetimes can refine it's analysis using these field sensitive alias sets.
This commit is contained in:
@@ -16,6 +16,10 @@ type AbstractPrimitive = {
|
||||
export type AliasSet = Set<Identifier>;
|
||||
class AbstractState {
|
||||
aliases = new DisjointSet<Identifier>();
|
||||
// NOTE(gsn): Should this be a part of AbstractObject? No, because this has
|
||||
// nothing to do with values in the object.
|
||||
objectAliases = new Map<Identifier, Map<string, AliasSet>>();
|
||||
|
||||
#values = new Map<Identifier, AbstractValue>();
|
||||
|
||||
read(alias: Place): AbstractValue {
|
||||
@@ -90,8 +94,45 @@ class AbstractState {
|
||||
}
|
||||
|
||||
alias(lvalue: LValue, alias: Place) {
|
||||
// TODO(gsn): Handle aliasing for complex lvalue
|
||||
// Complex lvalue:
|
||||
// lvalue.memberPath = alias;
|
||||
// lvalue.memberPath = alias.someMemberPath;
|
||||
if (lvalue.place.memberPath !== null) {
|
||||
// TODO(gsn): Handle nested memberPaths in lvalue.
|
||||
if (lvalue.place.memberPath.length > 1) {
|
||||
return;
|
||||
}
|
||||
let memberPath = lvalue.place.memberPath[0];
|
||||
|
||||
// Consider the case of:
|
||||
// lvalue.memberPath = alias;
|
||||
// mutate(lvalue); <-- `alias` should be considered mutable
|
||||
// here.
|
||||
//
|
||||
// Similarly for this case,
|
||||
// mutate(lvalue.memberPath); <-- `alias` should be considered mutable
|
||||
// here as well.
|
||||
//
|
||||
// But what about this case:
|
||||
// mutate(lvalue.foo); <-- Do we consider `alias` mutable here?
|
||||
// No!
|
||||
//
|
||||
// To distinguish between these different cases, we need to build separate
|
||||
// alias sets for each memberPath of `lvalue`.
|
||||
let objectAlias = this.objectAliases.get(lvalue.place.identifier);
|
||||
if (objectAlias === undefined) {
|
||||
objectAlias = new Map<string, AliasSet>();
|
||||
this.objectAliases.set(lvalue.place.identifier, objectAlias);
|
||||
}
|
||||
|
||||
let memberAlias = objectAlias.get(memberPath);
|
||||
if (memberAlias === undefined) {
|
||||
memberAlias = new Set<Identifier>();
|
||||
objectAlias.set(memberPath, memberAlias);
|
||||
}
|
||||
|
||||
memberAlias.add(alias.identifier);
|
||||
this.aliases.union([lvalue.place.identifier, alias.identifier]);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+19
-20
@@ -67,12 +67,12 @@ function mutate$0(x$1, y$2) {}
|
||||
```
|
||||
bb0:
|
||||
[1] Const mutate a$11_@0 = Object { }
|
||||
[2] Const mutate b$12_@1 = Array [read a$11_@0]
|
||||
[2] Const mutate b$12_@1[0:15] = Array [read a$11_@0]
|
||||
[3] Const mutate c$13_@2 = Object { }
|
||||
[4] Const mutate d$14_@3[0:15] = Object { c: read c$13_@2 }
|
||||
[5] Const mutate x$15_@3[0:15] = Object { }
|
||||
[6] Reassign mutate x$15_@3.b[0:15] = read b$12_@1
|
||||
[7] Const mutate y$16_@3[0:15] = Call mutate mutate$8_@3(mutate x$15_@3, mutate d$14_@3)
|
||||
[4] Const mutate d$14_@1[0:15] = Object { c: read c$13_@2 }
|
||||
[5] Const mutate x$15_@1[0:15] = Object { }
|
||||
[6] Reassign mutate x$15_@1.b[0:15] = read b$12_@1
|
||||
[7] Const mutate y$16_@1[0:15] = Call mutate mutate$8_@1(mutate x$15_@1, mutate d$14_@1)
|
||||
[8] If (read a$11_@0) then:bb1 else:bb1
|
||||
bb1:
|
||||
predecessor blocks: bb0
|
||||
@@ -82,17 +82,16 @@ bb3:
|
||||
[10] If (read c$13_@2) then:bb5 else:bb5
|
||||
bb5:
|
||||
predecessor blocks: bb3
|
||||
[11] If (read d$14_@3) then:bb7 else:bb7
|
||||
[11] If (read d$14_@1) then:bb7 else:bb7
|
||||
bb7:
|
||||
predecessor blocks: bb5
|
||||
[12] If (read y$16_@3) then:bb9 else:bb9
|
||||
[12] If (read y$16_@1) then:bb9 else:bb9
|
||||
bb9:
|
||||
predecessor blocks: bb7
|
||||
[13] Const mutate $17_@4 = null
|
||||
[14] Call mutate mutate$8_@3(mutate x$15_@3, read $17_@4)
|
||||
[13] Const mutate $17_@3 = null
|
||||
[14] Call mutate mutate$8_@1(mutate x$15_@1, read $17_@3)
|
||||
[15] Return
|
||||
scope1 [2:3]:
|
||||
- read a$11_@0
|
||||
|
||||
```
|
||||
|
||||
### CFG
|
||||
@@ -103,12 +102,12 @@ flowchart TB
|
||||
subgraph bb0
|
||||
bb0_instrs["
|
||||
[1] Const mutate a$11_@0 = Object { }
|
||||
[2] Const mutate b$12_@1 = Array [read a$11_@0]
|
||||
[2] Const mutate b$12_@1[0:15] = Array [read a$11_@0]
|
||||
[3] Const mutate c$13_@2 = Object { }
|
||||
[4] Const mutate d$14_@3[0:15] = Object { c: read c$13_@2 }
|
||||
[5] Const mutate x$15_@3[0:15] = Object { }
|
||||
[6] Reassign mutate x$15_@3.b[0:15] = read b$12_@1
|
||||
[7] Const mutate y$16_@3[0:15] = Call mutate mutate$8_@3(mutate x$15_@3, mutate d$14_@3)
|
||||
[4] Const mutate d$14_@1[0:15] = Object { c: read c$13_@2 }
|
||||
[5] Const mutate x$15_@1[0:15] = Object { }
|
||||
[6] Reassign mutate x$15_@1.b[0:15] = read b$12_@1
|
||||
[7] Const mutate y$16_@1[0:15] = Call mutate mutate$8_@1(mutate x$15_@1, mutate d$14_@1)
|
||||
"]
|
||||
bb0_instrs --> bb0_terminal(["If (read a$11_@0)"])
|
||||
end
|
||||
@@ -119,15 +118,15 @@ flowchart TB
|
||||
bb3_terminal(["If (read c$13_@2)"])
|
||||
end
|
||||
subgraph bb5
|
||||
bb5_terminal(["If (read d$14_@3)"])
|
||||
bb5_terminal(["If (read d$14_@1)"])
|
||||
end
|
||||
subgraph bb7
|
||||
bb7_terminal(["If (read y$16_@3)"])
|
||||
bb7_terminal(["If (read y$16_@1)"])
|
||||
end
|
||||
subgraph bb9
|
||||
bb9_instrs["
|
||||
[13] Const mutate $17_@4 = null
|
||||
[14] Call mutate mutate$8_@3(mutate x$15_@3, read $17_@4)
|
||||
[13] Const mutate $17_@3 = null
|
||||
[14] Call mutate mutate$8_@1(mutate x$15_@1, read $17_@3)
|
||||
"]
|
||||
bb9_instrs --> bb9_terminal(["Return"])
|
||||
end
|
||||
|
||||
@@ -18,22 +18,19 @@ function Component(props) {
|
||||
```
|
||||
bb0:
|
||||
[1] Const mutate x$7_@0[1:6] = Object { }
|
||||
[2] Const mutate y$8_@1 = Array []
|
||||
[3] Reassign mutate x$7_@0.y[1:6] = read y$8_@1
|
||||
[4] Const mutate child$9_@2 = JSX <read Component$0 data={freeze y$8_@1} ></read Component$0>
|
||||
[2] Const mutate y$8_@0[1:6] = Array []
|
||||
[3] Reassign mutate x$7_@0.y[1:6] = read y$8_@0
|
||||
[4] Const mutate child$9_@0[1:6] = JSX <read Component$0 data={freeze y$8_@0} ></read Component$0>
|
||||
[5] Call mutate x$7_@0.y.push(read props$6.p0)
|
||||
[6] Const mutate $10_@3 = JSX <read Component$0 data={freeze x$7_@0} >{read child$9_@2}</read Component$0>
|
||||
[7] Return read $10_@3
|
||||
scope1 [2:3]:
|
||||
- mutate x$7_@0.y
|
||||
scope2 [4:5]:
|
||||
[6] Const mutate $10_@1 = JSX <read Component$0 data={freeze x$7_@0} >{read child$9_@0}</read Component$0>
|
||||
[7] Return read $10_@1
|
||||
scope0 [1:6]:
|
||||
- read Component$0
|
||||
- freeze y$8_@1
|
||||
- read props$6.p0
|
||||
scope3 [6:7]:
|
||||
scope1 [6:7]:
|
||||
- read Component$0
|
||||
- freeze x$7_@0
|
||||
- read child$9_@2
|
||||
- read child$9_@0
|
||||
```
|
||||
|
||||
### CFG
|
||||
@@ -44,13 +41,13 @@ flowchart TB
|
||||
subgraph bb0
|
||||
bb0_instrs["
|
||||
[1] Const mutate x$7_@0[1:6] = Object { }
|
||||
[2] Const mutate y$8_@1 = Array []
|
||||
[3] Reassign mutate x$7_@0.y[1:6] = read y$8_@1
|
||||
[4] Const mutate child$9_@2 = JSX <read Component$0 data={freeze y$8_@1} ></read Component$0>
|
||||
[2] Const mutate y$8_@0[1:6] = Array []
|
||||
[3] Reassign mutate x$7_@0.y[1:6] = read y$8_@0
|
||||
[4] Const mutate child$9_@0[1:6] = JSX <read Component$0 data={freeze y$8_@0} ></read Component$0>
|
||||
[5] Call mutate x$7_@0.y.push(read props$6.p0)
|
||||
[6] Const mutate $10_@3 = JSX <read Component$0 data={freeze x$7_@0} >{read child$9_@2}</read Component$0>
|
||||
[6] Const mutate $10_@1 = JSX <read Component$0 data={freeze x$7_@0} >{read child$9_@0}</read Component$0>
|
||||
"]
|
||||
bb0_instrs --> bb0_terminal(["Return read $10_@3"])
|
||||
bb0_instrs --> bb0_terminal(["Return read $10_@1"])
|
||||
end
|
||||
|
||||
%% Jumps
|
||||
|
||||
@@ -19,13 +19,12 @@ function foo() {
|
||||
```
|
||||
bb0:
|
||||
[1] Let mutate x$4_@0[1:6] = Object { }
|
||||
[2] Let mutate y$5_@1[2:5] = Array []
|
||||
[3] Let mutate z$6_@1[2:5] = Object { }
|
||||
[4] Call mutate y$5_@1.push(mutate z$6_@1)
|
||||
[5] Reassign mutate x$4_@0.y[1:6] = read y$5_@1
|
||||
[2] Let mutate y$5_@0[1:6] = Array []
|
||||
[3] Let mutate z$6_@0[1:6] = Object { }
|
||||
[4] Call mutate y$5_@0.push(mutate z$6_@0)
|
||||
[5] Reassign mutate x$4_@0.y[1:6] = read y$5_@0
|
||||
[6] Return freeze x$4_@0
|
||||
scope1 [2:5]:
|
||||
- mutate x$4_@0.y
|
||||
|
||||
```
|
||||
|
||||
### CFG
|
||||
@@ -36,10 +35,10 @@ flowchart TB
|
||||
subgraph bb0
|
||||
bb0_instrs["
|
||||
[1] Let mutate x$4_@0[1:6] = Object { }
|
||||
[2] Let mutate y$5_@1[2:5] = Array []
|
||||
[3] Let mutate z$6_@1[2:5] = Object { }
|
||||
[4] Call mutate y$5_@1.push(mutate z$6_@1)
|
||||
[5] Reassign mutate x$4_@0.y[1:6] = read y$5_@1
|
||||
[2] Let mutate y$5_@0[1:6] = Array []
|
||||
[3] Let mutate z$6_@0[1:6] = Object { }
|
||||
[4] Call mutate y$5_@0.push(mutate z$6_@0)
|
||||
[5] Reassign mutate x$4_@0.y[1:6] = read y$5_@0
|
||||
"]
|
||||
bb0_instrs --> bb0_terminal(["Return freeze x$4_@0"])
|
||||
end
|
||||
|
||||
@@ -15,12 +15,11 @@ function foo() {
|
||||
|
||||
```
|
||||
bb0:
|
||||
[1] Const mutate x$3_@0 = Array []
|
||||
[2] Const mutate y$4_@1[2:4] = Object { }
|
||||
[3] Reassign mutate y$4_@1.x[2:4] = read x$3_@0
|
||||
[4] Return freeze y$4_@1
|
||||
scope1 [2:4]:
|
||||
- read x$3_@0
|
||||
[1] Const mutate x$3_@0[1:4] = Array []
|
||||
[2] Const mutate y$4_@0[1:4] = Object { }
|
||||
[3] Reassign mutate y$4_@0.x[1:4] = read x$3_@0
|
||||
[4] Return freeze y$4_@0
|
||||
|
||||
```
|
||||
|
||||
### CFG
|
||||
@@ -30,11 +29,11 @@ flowchart TB
|
||||
%% Basic Blocks
|
||||
subgraph bb0
|
||||
bb0_instrs["
|
||||
[1] Const mutate x$3_@0 = Array []
|
||||
[2] Const mutate y$4_@1[2:4] = Object { }
|
||||
[3] Reassign mutate y$4_@1.x[2:4] = read x$3_@0
|
||||
[1] Const mutate x$3_@0[1:4] = Array []
|
||||
[2] Const mutate y$4_@0[1:4] = Object { }
|
||||
[3] Reassign mutate y$4_@0.x[1:4] = read x$3_@0
|
||||
"]
|
||||
bb0_instrs --> bb0_terminal(["Return freeze y$4_@1"])
|
||||
bb0_instrs --> bb0_terminal(["Return freeze y$4_@0"])
|
||||
end
|
||||
|
||||
%% Jumps
|
||||
|
||||
Reference in New Issue
Block a user