Skip to content

Commit

Permalink
Add test case, cache similarly to loop cache, reuse loop cache key (n…
Browse files Browse the repository at this point in the history
…ow corrected)
  • Loading branch information
weswigham committed Apr 26, 2019
1 parent 1074ddd commit 11d9a60
Show file tree
Hide file tree
Showing 6 changed files with 28,166 additions and 4 deletions.
36 changes: 32 additions & 4 deletions src/compiler/checker.ts
Expand Up @@ -561,6 +561,7 @@ namespace ts {
const symbolLinks: SymbolLinks[] = [];
const nodeLinks: NodeLinks[] = [];
const flowLoopCaches: Map<Type>[] = [];
const flowAssignmentCaches: Map<Type>[] = [];
const flowLoopNodes: FlowNode[] = [];
const flowLoopKeys: string[] = [];
const flowLoopTypes: Type[][] = [];
Expand Down Expand Up @@ -16093,6 +16094,7 @@ namespace ts {

function getFlowTypeOfReference(reference: Node, declaredType: Type, initialType = declaredType, flowContainer?: Node, couldBeUninitialized?: boolean) {
let key: string | undefined;
let keySet = false;
let flowDepth = 0;
if (flowAnalysisDisabled) {
return errorType;
Expand All @@ -16113,6 +16115,14 @@ namespace ts {
}
return resultType;

function getOrSetCacheKey() {
if (keySet) {
return key;
}
keySet = true;
return key = getFlowCacheKey(reference, declaredType, initialType, flowContainer);
}

function getTypeAtFlowNode(flow: FlowNode): FlowType {
if (flowDepth === 2000) {
// We have made 2000 recursive invocations. To avoid overflowing the call stack we report an error
Expand All @@ -16124,6 +16134,17 @@ namespace ts {
flowDepth++;
while (true) {
const flags = flow.flags;
if (flags & FlowFlags.Cached) {
const key = getOrSetCacheKey();
if (key) {
const id = getFlowNodeId(flow);
const cache = flowAssignmentCaches[id] || (flowAssignmentCaches[id] = createMap<Type>());
const cached = cache.get(key);
if (cached) {
return cached;
}
}
}
if (flags & FlowFlags.Shared) {
// We cache results of flow type resolution for shared nodes that were previously visited in
// the same getFlowTypeOfReference invocation. A node is considered shared when it is the
Expand Down Expand Up @@ -16154,6 +16175,15 @@ namespace ts {
flow = (<FlowAssignment>flow).antecedent;
continue;
}
else if (flowLoopCount === flowLoopStart) { // Only cache assignments when not within loop analysis
const key = getOrSetCacheKey();
if (key && !isIncomplete(type)) {
flow.flags |= FlowFlags.Cached;
const id = getFlowNodeId(flow);
const cache = flowAssignmentCaches[id] || (flowAssignmentCaches[id] = createMap<Type>());
cache.set(key, type as Type);
}
}
}
else if (flags & FlowFlags.Condition) {
type = getTypeAtFlowCondition(<FlowCondition>flow);
Expand Down Expand Up @@ -16366,12 +16396,10 @@ namespace ts {
// this flow loop junction, return the cached type.
const id = getFlowNodeId(flow);
const cache = flowLoopCaches[id] || (flowLoopCaches[id] = createMap<Type>());
const key = getOrSetCacheKey();
if (!key) {
key = getFlowCacheKey(reference, declaredType, initialType, flowContainer);
// No cache key is generated when binding patterns are in unnarrowable situations
if (!key) {
return declaredType;
}
return declaredType;
}
const cached = cache.get(key);
if (cached) {
Expand Down
2 changes: 2 additions & 0 deletions src/compiler/types.ts
Expand Up @@ -2546,6 +2546,8 @@ namespace ts {
Shared = 1 << 10, // Referenced as antecedent more than once
PreFinally = 1 << 11, // Injected edge that links pre-finally label and pre-try flow
AfterFinally = 1 << 12, // Injected edge that links post-finally flow with the rest of the graph
/** @internal */
Cached = 1 << 13, // Indicates that at least one cross-call cache entry exists for this node, even if not a loop participant
Label = BranchLabel | LoopLabel,
Condition = TrueCondition | FalseCondition
}
Expand Down

0 comments on commit 11d9a60

Please sign in to comment.