Skip to content

Commit 6874d65

Browse files
committed
Cache flow label results the same way as flow loop results
1 parent 4791050 commit 6874d65

File tree

5 files changed

+964
-3
lines changed

5 files changed

+964
-3
lines changed

src/compiler/checker.ts

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -940,7 +940,7 @@ namespace ts {
940940
const mergedSymbols: Symbol[] = [];
941941
const symbolLinks: SymbolLinks[] = [];
942942
const nodeLinks: NodeLinks[] = [];
943-
const flowLoopCaches: ESMap<string, Type>[] = [];
943+
const flowLabelCaches: ESMap<string, Type>[] = [];
944944
const flowLoopNodes: FlowNode[] = [];
945945
const flowLoopKeys: string[] = [];
946946
const flowLoopTypes: Type[][] = [];
@@ -21656,6 +21656,7 @@ namespace ts {
2165621656
let key: string | undefined;
2165721657
let isKeySet = false;
2165821658
let flowDepth = 0;
21659+
let cacheableBranches = true;
2165921660
if (flowAnalysisDisabled) {
2166021661
return errorType;
2166121662
}
@@ -21747,9 +21748,14 @@ namespace ts {
2174721748
else if (flags & FlowFlags.ReduceLabel) {
2174821749
const target = (<FlowReduceLabel>flow).target;
2174921750
const saveAntecedents = target.antecedents;
21751+
// Modifying the antecedents of a node means we lose our ability to use the cross-invocation branch cache
21752+
// (since that may have follow-on effects on analysis returned by other nodes if the results get cached)
21753+
const oldCacheableBranches = cacheableBranches;
21754+
cacheableBranches = false;
2175021755
target.antecedents = (<FlowReduceLabel>flow).antecedents;
2175121756
type = getTypeAtFlowNode((<FlowReduceLabel>flow).antecedent);
2175221757
target.antecedents = saveAntecedents;
21758+
cacheableBranches = oldCacheableBranches;
2175321759
}
2175421760
else if (flags & FlowFlags.Start) {
2175521761
// Check if we should continue with the control flow of the containing function.
@@ -21955,6 +21961,17 @@ namespace ts {
2195521961
}
2195621962

2195721963
function getTypeAtFlowBranchLabel(flow: FlowLabel): FlowType {
21964+
const id = getFlowNodeId(flow);
21965+
const cache = flowLabelCaches[id] || (flowLabelCaches[id] = new Map<string, Type>());
21966+
const key = getOrSetCacheKey();
21967+
if (!key) {
21968+
// No cache key is generated when binding patterns are in unnarrowable situations
21969+
return declaredType;
21970+
}
21971+
const cached = cacheableBranches && cache.get(key);
21972+
if (cached) {
21973+
return cached;
21974+
}
2195821975
const antecedentTypes: Type[] = [];
2195921976
let subtypeReduction = false;
2196021977
let seenIncomplete = false;
@@ -22004,14 +22021,18 @@ namespace ts {
2200422021
}
2200522022
}
2200622023
}
22007-
return createFlowType(getUnionOrEvolvingArrayType(antecedentTypes, subtypeReduction ? UnionReduction.Subtype : UnionReduction.Literal), seenIncomplete);
22024+
const result = createFlowType(getUnionOrEvolvingArrayType(antecedentTypes, subtypeReduction ? UnionReduction.Subtype : UnionReduction.Literal), seenIncomplete);
22025+
if (!seenIncomplete && cacheableBranches) {
22026+
cache.set(key, result as Type);
22027+
}
22028+
return result;
2200822029
}
2200922030

2201022031
function getTypeAtFlowLoopLabel(flow: FlowLabel): FlowType {
2201122032
// If we have previously computed the control flow type for the reference at
2201222033
// this flow loop junction, return the cached type.
2201322034
const id = getFlowNodeId(flow);
22014-
const cache = flowLoopCaches[id] || (flowLoopCaches[id] = new Map<string, Type>());
22035+
const cache = flowLabelCaches[id] || (flowLabelCaches[id] = new Map<string, Type>());
2201522036
const key = getOrSetCacheKey();
2201622037
if (!key) {
2201722038
// No cache key is generated when binding patterns are in unnarrowable situations
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
//// [controlFlowManyCallExpressionStatementsPerf.ts]
2+
function test(x: boolean): boolean { return x; }
3+
4+
let state = true;
5+
6+
if (state) {
7+
test(state as any && state);
8+
test(state as any && state);
9+
test(state as any && state);
10+
test(state as any && state);
11+
test(state as any && state);
12+
test(state as any && state);
13+
test(state as any && state);
14+
test(state as any && state);
15+
test(state as any && state);
16+
test(state as any && state);
17+
test(state as any && state);
18+
test(state as any && state);
19+
test(state as any && state);
20+
test(state as any && state);
21+
test(state as any && state);
22+
test(state as any && state);
23+
test(state as any && state);
24+
test(state as any && state);
25+
test(state as any && state);
26+
test(state as any && state);
27+
test(state as any && state);
28+
test(state as any && state);
29+
test(state as any && state);
30+
test(state as any && state);
31+
test(state as any && state);
32+
test(state as any && state);
33+
test(state as any && state);
34+
test(state as any && state);
35+
test(state as any && state);
36+
test(state as any && state);
37+
test(state as any && state);
38+
test(state as any && state);
39+
test(state as any && state);
40+
test(state as any && state);
41+
test(state as any && state);
42+
test(state as any && state);
43+
test(state as any && state);
44+
test(state as any && state);
45+
test(state as any && state);
46+
test(state as any && state);
47+
test(state as any && state);
48+
test(state as any && state);
49+
test(state as any && state);
50+
test(state as any && state);
51+
test(state as any && state);
52+
test(state as any && state);
53+
test(state as any && state);
54+
test(state as any && state);
55+
test(state as any && state);
56+
test(state as any && state);
57+
test(state as any && state);
58+
test(state as any && state);
59+
test(state as any && state);
60+
test(state as any && state);
61+
test(state as any && state);
62+
test(state as any && state);
63+
}
64+
65+
//// [controlFlowManyCallExpressionStatementsPerf.js]
66+
function test(x) { return x; }
67+
var state = true;
68+
if (state) {
69+
test(state && state);
70+
test(state && state);
71+
test(state && state);
72+
test(state && state);
73+
test(state && state);
74+
test(state && state);
75+
test(state && state);
76+
test(state && state);
77+
test(state && state);
78+
test(state && state);
79+
test(state && state);
80+
test(state && state);
81+
test(state && state);
82+
test(state && state);
83+
test(state && state);
84+
test(state && state);
85+
test(state && state);
86+
test(state && state);
87+
test(state && state);
88+
test(state && state);
89+
test(state && state);
90+
test(state && state);
91+
test(state && state);
92+
test(state && state);
93+
test(state && state);
94+
test(state && state);
95+
test(state && state);
96+
test(state && state);
97+
test(state && state);
98+
test(state && state);
99+
test(state && state);
100+
test(state && state);
101+
test(state && state);
102+
test(state && state);
103+
test(state && state);
104+
test(state && state);
105+
test(state && state);
106+
test(state && state);
107+
test(state && state);
108+
test(state && state);
109+
test(state && state);
110+
test(state && state);
111+
test(state && state);
112+
test(state && state);
113+
test(state && state);
114+
test(state && state);
115+
test(state && state);
116+
test(state && state);
117+
test(state && state);
118+
test(state && state);
119+
test(state && state);
120+
test(state && state);
121+
test(state && state);
122+
test(state && state);
123+
test(state && state);
124+
test(state && state);
125+
}

0 commit comments

Comments
 (0)