mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-04-17 01:49:41 -05:00
More efficient scheme for caching flow node reachability
This commit is contained in:
@@ -6,6 +6,7 @@ namespace ts {
|
||||
let nextNodeId = 1;
|
||||
let nextMergeId = 1;
|
||||
let nextFlowId = 1;
|
||||
let nextCheckerId = 1;
|
||||
|
||||
const enum IterationUse {
|
||||
AllowsSyncIterablesFlag = 1 << 0,
|
||||
@@ -298,6 +299,7 @@ namespace ts {
|
||||
let instantiationDepth = 0;
|
||||
let constraintDepth = 0;
|
||||
let currentNode: Node | undefined;
|
||||
let checkerId: number;
|
||||
|
||||
const emptySymbols = createSymbolTable();
|
||||
const identityMapper: (type: Type) => Type = identity;
|
||||
@@ -842,7 +844,6 @@ namespace ts {
|
||||
const flowLoopTypes: Type[][] = [];
|
||||
const sharedFlowNodes: FlowNode[] = [];
|
||||
const sharedFlowTypes: FlowType[] = [];
|
||||
const flowNodeReachable: (boolean | undefined)[] = [];
|
||||
const potentialThisCollisions: Node[] = [];
|
||||
const potentialNewTargetCollisions: Node[] = [];
|
||||
const awaitedTypeStack: number[] = [];
|
||||
@@ -16993,17 +16994,21 @@ namespace ts {
|
||||
}
|
||||
|
||||
function isReachableFlowNode(flow: FlowNode) {
|
||||
return isReachableFlowNodeWorker(flow, /*skipCacheCheck*/ false);
|
||||
return isReachableFlowNodeWorker(flow, /*noCacheCheck*/ false);
|
||||
}
|
||||
|
||||
function isReachableFlowNodeWorker(flow: FlowNode, noCacheCheck: boolean): boolean {
|
||||
while (true) {
|
||||
const flags = flow.flags;
|
||||
if (flags & FlowFlags.Shared) {
|
||||
if (flags & (FlowFlags.Shared | FlowFlags.Assignment | FlowFlags.Label)) {
|
||||
if (!noCacheCheck) {
|
||||
const id = getFlowNodeId(flow);
|
||||
const reachable = flowNodeReachable[id];
|
||||
return reachable !== undefined ? reachable : (flowNodeReachable[id] = isReachableFlowNodeWorker(flow, /*skipCacheCheck*/ true));
|
||||
if (flow.checkerId === checkerId) {
|
||||
return !!(flow.flags & FlowFlags.Reachable);
|
||||
}
|
||||
const reachable = isReachableFlowNodeWorker(flow, /*noCacheCheck*/ true);
|
||||
flow.checkerId = checkerId;
|
||||
flow.flags = (flow.flags & ~FlowFlags.Reachable) | (reachable ? FlowFlags.Reachable : 0);
|
||||
return reachable;
|
||||
}
|
||||
noCacheCheck = false;
|
||||
}
|
||||
@@ -32287,6 +32292,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
function initializeTypeChecker() {
|
||||
checkerId = nextCheckerId;
|
||||
nextCheckerId++;
|
||||
|
||||
// Bind all source files and propagate errors
|
||||
for (const file of host.getSourceFiles()) {
|
||||
bindSourceFile(file, compilerOptions);
|
||||
|
||||
@@ -2582,6 +2582,8 @@ namespace ts {
|
||||
AfterFinally = 1 << 13, // Injected edge that links post-finally flow with the rest of the graph
|
||||
/** @internal */
|
||||
Cached = 1 << 14, // Indicates that at least one cross-call cache entry exists for this node, even if not a loop participant
|
||||
/** @internal */
|
||||
Reachable = 1 << 15, // Reachability as computed by isReachableFlowNode
|
||||
Label = BranchLabel | LoopLabel,
|
||||
Condition = TrueCondition | FalseCondition
|
||||
}
|
||||
@@ -2600,6 +2602,8 @@ namespace ts {
|
||||
export interface FlowNodeBase {
|
||||
flags: FlowFlags;
|
||||
id?: number; // Node id used by flow type cache in checker
|
||||
/** @internal */
|
||||
checkerId?: number; // Checker id for FlowFlags.Reachable
|
||||
}
|
||||
|
||||
export interface FlowLock {
|
||||
|
||||
Reference in New Issue
Block a user