diff --git a/src/Test/Utilities/Portable/Compilation/FlowAnalysis/BasicBlockReachabilityDataFlowAnalyzer.cs b/src/Test/Utilities/Portable/Compilation/FlowAnalysis/BasicBlockReachabilityDataFlowAnalyzer.cs index 89e4e9b3761f258c2a1307ccc6cce64b961bae22..718897391da4320d50e33f27644d9089f552b4a8 100644 --- a/src/Test/Utilities/Portable/Compilation/FlowAnalysis/BasicBlockReachabilityDataFlowAnalyzer.cs +++ b/src/Test/Utilities/Portable/Compilation/FlowAnalysis/BasicBlockReachabilityDataFlowAnalyzer.cs @@ -24,7 +24,7 @@ public static BitVector Run(ControlFlowGraph controlFlowGraph) public override bool AnalyzeBlock(BasicBlock basicBlock, CancellationToken cancellationToken) { - SetCurrentAnalysisData(basicBlock, isReachable: true); + SetCurrentAnalysisData(basicBlock, isReachable: true, cancellationToken); return true; } @@ -54,7 +54,7 @@ public override bool AnalyzeNonConditionalBranch(BasicBlock basicBlock, bool cur return (currentIsReachable, currentIsReachable); } - public override void SetCurrentAnalysisData(BasicBlock basicBlock, bool isReachable) + public override void SetCurrentAnalysisData(BasicBlock basicBlock, bool isReachable, CancellationToken cancellationToken) { _visited[basicBlock.Ordinal] = isReachable; } diff --git a/src/Workspaces/Core/Portable/FlowAnalysis/CustomDataFlowAnalysis.cs b/src/Workspaces/Core/Portable/FlowAnalysis/CustomDataFlowAnalysis.cs index 8bf9f3a5931e4e0c752afa605562a019fb5d22ac..c876ff60511cd1c157bbc640ba68c006a8aa31ef 100644 --- a/src/Workspaces/Core/Portable/FlowAnalysis/CustomDataFlowAnalysis.cs +++ b/src/Workspaces/Core/Portable/FlowAnalysis/CustomDataFlowAnalysis.cs @@ -79,7 +79,7 @@ public static TBlockAnalysisData Run(ControlFlowGraph controlFlowGraph, DataFlow var toVisit = new SortedSet(); var firstBlock = blocks[firstBlockOrdinal]; - analyzer.SetCurrentAnalysisData(firstBlock, initialAnalysisData); + analyzer.SetCurrentAnalysisData(firstBlock, initialAnalysisData, cancellationToken); toVisit.Add(firstBlock.Ordinal); var processedBlocks = PooledHashSet.GetInstance(); @@ -122,7 +122,7 @@ public static TBlockAnalysisData Run(ControlFlowGraph controlFlowGraph, DataFlow continue; } - analyzer.SetCurrentAnalysisData(current, analyzer.GetEmptyAnalysisData()); + analyzer.SetCurrentAnalysisData(current, analyzer.GetEmptyAnalysisData(), cancellationToken); } if (current.Ordinal < firstBlockOrdinal || current.Ordinal > lastBlockOrdinal) @@ -238,7 +238,7 @@ void FollowBranch(BasicBlock current, ControlFlowBranch branch, TBlockAnalysisDa if ((current.IsReachable || !destination.IsReachable) && (!analyzer.IsEqual(currentDestinationData, mergedAnalysisData) || !processedBlocks.Contains(destination))) { - analyzer.SetCurrentAnalysisData(destination, mergedAnalysisData); + analyzer.SetCurrentAnalysisData(destination, mergedAnalysisData, cancellationToken); toVisit.Add(branch.Destination.Ordinal); } } diff --git a/src/Workspaces/Core/Portable/FlowAnalysis/DataFlowAnalyzer.cs b/src/Workspaces/Core/Portable/FlowAnalysis/DataFlowAnalyzer.cs index a30869d7a2d37d4766fab563c30a4473c075dac9..382f738d7577bb8b00f84704f80b0f2206120117 100644 --- a/src/Workspaces/Core/Portable/FlowAnalysis/DataFlowAnalyzer.cs +++ b/src/Workspaces/Core/Portable/FlowAnalysis/DataFlowAnalyzer.cs @@ -24,7 +24,7 @@ internal abstract class DataFlowAnalyzer : IDisposable /// /// Updates the current analysis data for the given basic block. /// - public abstract void SetCurrentAnalysisData(BasicBlock basicBlock, TBlockAnalysisData data); + public abstract void SetCurrentAnalysisData(BasicBlock basicBlock, TBlockAnalysisData data, CancellationToken cancellationToken); /// /// Analyze the given basic block and return the block analysis data at the end of the block for its successors. diff --git a/src/Workspaces/Core/Portable/FlowAnalysis/SymbolUsageAnalysis/SymbolUsageAnalysis.DataFlowAnalyzer.FlowGraphAnalysisData.cs b/src/Workspaces/Core/Portable/FlowAnalysis/SymbolUsageAnalysis/SymbolUsageAnalysis.DataFlowAnalyzer.FlowGraphAnalysisData.cs index 4d1c125cef072f9180e9ac85f1597341b6bc20cb..b8c3f9f5957ba1ecb4919bbfcc42dda26ac2cc93 100644 --- a/src/Workspaces/Core/Portable/FlowAnalysis/SymbolUsageAnalysis/SymbolUsageAnalysis.DataFlowAnalyzer.FlowGraphAnalysisData.cs +++ b/src/Workspaces/Core/Portable/FlowAnalysis/SymbolUsageAnalysis/SymbolUsageAnalysis.DataFlowAnalyzer.FlowGraphAnalysisData.cs @@ -156,24 +156,24 @@ private sealed class FlowGraphAnalysisData : AnalysisData public BasicBlockAnalysisData GetBlockAnalysisData(BasicBlock basicBlock) => _analysisDataByBasicBlockMap[basicBlock]; - public BasicBlockAnalysisData GetOrCreateBlockAnalysisData(BasicBlock basicBlock) + public BasicBlockAnalysisData GetOrCreateBlockAnalysisData(BasicBlock basicBlock, CancellationToken cancellationToken) { if (_analysisDataByBasicBlockMap[basicBlock] == null) { _analysisDataByBasicBlockMap[basicBlock] = CreateBlockAnalysisData(); } - HandleCatchOrFilterOrFinallyInitialization(basicBlock); + HandleCatchOrFilterOrFinallyInitialization(basicBlock, cancellationToken); return _analysisDataByBasicBlockMap[basicBlock]; } - private PooledHashSet<(ISymbol, IOperation)> GetOrCreateSymbolWritesInBlockRange(int firstBlockOrdinal, int lastBlockOrdinal) + private PooledHashSet<(ISymbol, IOperation)> GetOrCreateSymbolWritesInBlockRange(int firstBlockOrdinal, int lastBlockOrdinal, CancellationToken cancellationToken) { if (!_symbolWritesInsideBlockRangeMap.TryGetValue((firstBlockOrdinal, lastBlockOrdinal), out var writesInBlockRange)) { // Compute all descendant operations in basic block range. var operations = PooledHashSet.GetInstance(); - AddOperationsInRange(ControlFlowGraph, firstBlockOrdinal, lastBlockOrdinal, operations); + AddDescendantOperationsInRange(ControlFlowGraph, firstBlockOrdinal, lastBlockOrdinal, operations, cancellationToken); // Filter down the operations to writes within this block range. writesInBlockRange = PooledHashSet<(ISymbol, IOperation)>.GetInstance(); @@ -189,15 +189,17 @@ private PooledHashSet<(ISymbol, IOperation)> GetOrCreateSymbolWritesInBlockRange return writesInBlockRange; } - private void AddOperationsInRange( + private void AddDescendantOperationsInRange( ControlFlowGraph cfg, int firstBlockOrdinal, int lastBlockOrdinal, - PooledHashSet operationsBuilder) + PooledHashSet operationsBuilder, + CancellationToken cancellationToken) { // Compute all descendant operations in basic block range. for (int i = firstBlockOrdinal; i <= lastBlockOrdinal; i++) { + cancellationToken.ThrowIfCancellationRequested(); foreach (var operation in cfg.Blocks[i].DescendantOperations()) { var added = operationsBuilder.Add(operation); @@ -206,14 +208,14 @@ private PooledHashSet<(ISymbol, IOperation)> GetOrCreateSymbolWritesInBlockRange if (invocation.Instance != null && _reachingDelegateCreationTargets.TryGetValue(invocation.Instance, out var targets)) { - AddOperationsFromDelegateCreationTargets(targets); + AddDescendantOperationsFromDelegateCreationTargets(targets); } else if (invocation.TargetMethod.IsLocalFunction()) { var localFunctionGraph = cfg.GetLocalFunctionControlFlowGraphInScope(invocation.TargetMethod); if (localFunctionGraph != null) { - AddOperationsInLambdaOrLocalFunctionGraph(localFunctionGraph); + AddDescendantOperationsInLambdaOrLocalFunctionGraph(localFunctionGraph); } } } @@ -223,7 +225,7 @@ private PooledHashSet<(ISymbol, IOperation)> GetOrCreateSymbolWritesInBlockRange return; // Local functions. - void AddOperationsFromDelegateCreationTargets(PooledHashSet targets) + void AddDescendantOperationsFromDelegateCreationTargets(PooledHashSet targets) { foreach (var target in targets) { @@ -246,15 +248,16 @@ void AddOperationsFromDelegateCreationTargets(PooledHashSet targets) if (lambdaOrLocalFunctionCfgOpt != null && operationsBuilder.Add(target)) { - AddOperationsInLambdaOrLocalFunctionGraph(lambdaOrLocalFunctionCfgOpt); + AddDescendantOperationsInLambdaOrLocalFunctionGraph(lambdaOrLocalFunctionCfgOpt); } } } - void AddOperationsInLambdaOrLocalFunctionGraph(ControlFlowGraph lambdaOrLocalFunctionCfg) + void AddDescendantOperationsInLambdaOrLocalFunctionGraph(ControlFlowGraph lambdaOrLocalFunctionCfg) { Debug.Assert(lambdaOrLocalFunctionCfg != null); - AddOperationsInRange(lambdaOrLocalFunctionCfg, firstBlockOrdinal: 0, lastBlockOrdinal: lambdaOrLocalFunctionCfg.Blocks.Length - 1, operationsBuilder); + AddDescendantOperationsInRange(lambdaOrLocalFunctionCfg, firstBlockOrdinal: 0, + lastBlockOrdinal: lambdaOrLocalFunctionCfg.Blocks.Length - 1, operationsBuilder, cancellationToken); } ControlFlowGraph TryGetAnonymousFunctionControlFlowGraphInScope(IFlowAnonymousFunctionOperation flowAnonymousFunctionOperation) @@ -289,7 +292,7 @@ ControlFlowGraph TryGetLocalFunctionControlFlowGraphInScope(IMethodSymbol localF /// catch/filter/finally region. /// /// - private void HandleCatchOrFilterOrFinallyInitialization(BasicBlock basicBlock) + private void HandleCatchOrFilterOrFinallyInitialization(BasicBlock basicBlock, CancellationToken cancellationToken) { Debug.Assert(_analysisDataByBasicBlockMap[basicBlock] != null); @@ -347,7 +350,7 @@ private void HandleCatchOrFilterOrFinallyInitialization(BasicBlock basicBlock) mergedAnalysisData.SetAnalysisDataFrom(GetBlockAnalysisData(firstBasicBlockInOutermostRegion)); // All symbol writes within the try region are considered reachable at start of catch/finally region. - foreach (var (symbol, write) in GetOrCreateSymbolWritesInBlockRange(containingTryCatchFinallyRegion.FirstBlockOrdinal, basicBlock.Ordinal - 1)) + foreach (var (symbol, write) in GetOrCreateSymbolWritesInBlockRange(containingTryCatchFinallyRegion.FirstBlockOrdinal, basicBlock.Ordinal - 1, cancellationToken)) { mergedAnalysisData.OnWriteReferenceFound(symbol, write, maybeWritten: true); SymbolsWriteBuilder[(symbol, write)] = true; @@ -357,8 +360,8 @@ private void HandleCatchOrFilterOrFinallyInitialization(BasicBlock basicBlock) SetBlockAnalysisData(basicBlock, mergedAnalysisData); } - public void SetCurrentBlockAnalysisDataFrom(BasicBlock basicBlock) - => SetCurrentBlockAnalysisDataFrom(GetOrCreateBlockAnalysisData(basicBlock)); + public void SetCurrentBlockAnalysisDataFrom(BasicBlock basicBlock, CancellationToken cancellationToken) + => SetCurrentBlockAnalysisDataFrom(GetOrCreateBlockAnalysisData(basicBlock, cancellationToken)); public void SetAnalysisDataOnEntryBlockStart() { @@ -372,8 +375,8 @@ public void SetAnalysisDataOnEntryBlockStart() public void SetBlockAnalysisData(BasicBlock basicBlock, BasicBlockAnalysisData data) => _analysisDataByBasicBlockMap[basicBlock] = data; - public void SetBlockAnalysisDataFrom(BasicBlock basicBlock, BasicBlockAnalysisData data) - => GetOrCreateBlockAnalysisData(basicBlock).SetAnalysisDataFrom(data); + public void SetBlockAnalysisDataFrom(BasicBlock basicBlock, BasicBlockAnalysisData data, CancellationToken cancellationToken) + => GetOrCreateBlockAnalysisData(basicBlock, cancellationToken).SetAnalysisDataFrom(data); public void SetAnalysisDataOnExitBlockEnd() { diff --git a/src/Workspaces/Core/Portable/FlowAnalysis/SymbolUsageAnalysis/SymbolUsageAnalysis.DataFlowAnalyzer.cs b/src/Workspaces/Core/Portable/FlowAnalysis/SymbolUsageAnalysis/SymbolUsageAnalysis.DataFlowAnalyzer.cs index 4047d6c3e3971056482d4a7c7bb3b196f37ae6dd..83659491fedbe084b6ee4f7041a62799ff6eee4a 100644 --- a/src/Workspaces/Core/Portable/FlowAnalysis/SymbolUsageAnalysis/SymbolUsageAnalysis.DataFlowAnalyzer.cs +++ b/src/Workspaces/Core/Portable/FlowAnalysis/SymbolUsageAnalysis/SymbolUsageAnalysis.DataFlowAnalyzer.cs @@ -17,22 +17,18 @@ internal static partial class SymbolUsageAnalysis private sealed partial class DataFlowAnalyzer : DataFlowAnalyzer { private readonly FlowGraphAnalysisData _analysisData; - private readonly CancellationToken _cancellationToken; - private DataFlowAnalyzer(ControlFlowGraph cfg, ISymbol owningSymbol, CancellationToken cancellationToken) + private DataFlowAnalyzer(ControlFlowGraph cfg, ISymbol owningSymbol) { _analysisData = FlowGraphAnalysisData.Create(cfg, owningSymbol, AnalyzeLocalFunctionOrLambdaInvocation); - _cancellationToken = cancellationToken; } private DataFlowAnalyzer( ControlFlowGraph cfg, IMethodSymbol lambdaOrLocalFunction, - FlowGraphAnalysisData parentAnalysisData, - CancellationToken cancellationToken) + FlowGraphAnalysisData parentAnalysisData) { _analysisData = FlowGraphAnalysisData.Create(cfg, lambdaOrLocalFunction, parentAnalysisData); - _cancellationToken = cancellationToken; var entryBlockAnalysisData = GetEmptyAnalysisData(); entryBlockAnalysisData.SetAnalysisDataFrom(parentAnalysisData.CurrentBlockAnalysisData); @@ -42,7 +38,7 @@ private DataFlowAnalyzer(ControlFlowGraph cfg, ISymbol owningSymbol, Cancellatio public static SymbolUsageResult RunAnalysis(ControlFlowGraph cfg, ISymbol owningSymbol, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); - using (var analyzer = new DataFlowAnalyzer(cfg, owningSymbol, cancellationToken)) + using (var analyzer = new DataFlowAnalyzer(cfg, owningSymbol)) { _ = CustomDataFlowAnalysis.Run(cfg, analyzer, cancellationToken); return analyzer._analysisData.ToResult(); @@ -61,7 +57,7 @@ public override void Dispose() Debug.Assert(localFunctionOrLambda.IsLocalFunction() || localFunctionOrLambda.IsAnonymousFunction()); cancellationToken.ThrowIfCancellationRequested(); - using (var analyzer = new DataFlowAnalyzer(cfg, localFunctionOrLambda, (FlowGraphAnalysisData)parentAnalysisData, cancellationToken)) + using (var analyzer = new DataFlowAnalyzer(cfg, localFunctionOrLambda, (FlowGraphAnalysisData)parentAnalysisData)) { var resultBlockAnalysisData = CustomDataFlowAnalysis.Run(cfg, analyzer, cancellationToken); if (resultBlockAnalysisData == null) @@ -101,7 +97,7 @@ public override BasicBlockAnalysisData AnalyzeBlock(BasicBlock basicBlock, Cance void BeforeBlockAnalysis() { // Initialize current block analysis data. - _analysisData.SetCurrentBlockAnalysisDataFrom(basicBlock); + _analysisData.SetCurrentBlockAnalysisDataFrom(basicBlock, cancellationToken); // At start of entry block, handle parameter definitions from method declaration. if (basicBlock.Kind == BasicBlockKind.Entry) @@ -155,8 +151,8 @@ public override BasicBlockAnalysisData GetCurrentAnalysisData(BasicBlock basicBl public override BasicBlockAnalysisData GetEmptyAnalysisData() => _analysisData.CreateBlockAnalysisData(); - public override void SetCurrentAnalysisData(BasicBlock basicBlock, BasicBlockAnalysisData data) - => _analysisData.SetBlockAnalysisDataFrom(basicBlock, data); + public override void SetCurrentAnalysisData(BasicBlock basicBlock, BasicBlockAnalysisData data, CancellationToken cancellationToken) + => _analysisData.SetBlockAnalysisDataFrom(basicBlock, data, cancellationToken); public override bool IsEqual(BasicBlockAnalysisData analysisData1, BasicBlockAnalysisData analysisData2) => analysisData1 == null ? analysisData2 == null : analysisData1.Equals(analysisData2); diff --git a/src/Workspaces/Core/Portable/FlowAnalysis/SymbolUsageAnalysis/SymbolUsageAnalysis.Walker.cs b/src/Workspaces/Core/Portable/FlowAnalysis/SymbolUsageAnalysis/SymbolUsageAnalysis.Walker.cs index 67de3565a15795571b83ed6d9ce5aa913936f8e2..9bc5bdfbc0cf152a7b3b2d7b45e5ae194b992c36 100644 --- a/src/Workspaces/Core/Portable/FlowAnalysis/SymbolUsageAnalysis/SymbolUsageAnalysis.Walker.cs +++ b/src/Workspaces/Core/Portable/FlowAnalysis/SymbolUsageAnalysis/SymbolUsageAnalysis.Walker.cs @@ -173,6 +173,7 @@ private bool MakePendingWrite(IOperation operation, ISymbol symbolOpt) return false; } + private void ProcessPendingWritesForAssignmentTarget(IAssignmentOperation operation) { if (_pendingWritesMap.TryGetValue(operation, out var pendingWrites))