public static MultiDictionary <Symbol, CSharpSyntaxNode> Analyze(CSharpCompilation compilation, MethodSymbol method, BoundNode node) { var emptyStructs = new CaptureWalkerEmptyStructTypeCache(); var initiallyAssignedVariables = UnassignedVariablesWalker.Analyze(compilation, method, node, emptyStructs); var walker = new IteratorAndAsyncCaptureWalker(compilation, method, node, emptyStructs, initiallyAssignedVariables); bool badRegion = false; walker.Analyze(ref badRegion); Debug.Assert(!badRegion); var result = walker.variablesCaptured; if (!method.IsStatic && method.ContainingType.TypeKind == TypeKind.Struct) { // It is possible that the enclosing method only *writes* to the enclosing struct, but in that // case it should be considered captured anyway so that we have a proxy for it to write to. result.Add(method.ThisParameter, node.Syntax); } foreach (var variable in result.Keys.ToArray()) // take a snapshot, as we are modifying the underlying multidictionary { var local = variable as LocalSymbol; if ((object)local != null && local.RefKind != RefKind.None) { walker.AddSpillsForRef(walker.refLocalInitializers[local], result[local]); } } walker.Free(); return(result); }
public static MultiDictionary<Symbol, CSharpSyntaxNode> Analyze(CSharpCompilation compilation, MethodSymbol method, BoundNode node) { var emptyStructs = new CaptureWalkerEmptyStructTypeCache(); var initiallyAssignedVariables = UnassignedVariablesWalker.Analyze(compilation, method, node, emptyStructs); var walker = new IteratorAndAsyncCaptureWalker(compilation, method, node, emptyStructs, initiallyAssignedVariables); bool badRegion = false; walker.Analyze(ref badRegion); Debug.Assert(!badRegion); var result = walker.variablesCaptured; if (!method.IsStatic && method.ContainingType.TypeKind == TypeKind.Struct) { // It is possible that the enclosing method only *writes* to the enclosing struct, but in that // case it should be considered captured anyway so that we have a proxy for it to write to. result.Add(method.ThisParameter, node.Syntax); } foreach (var variable in result.Keys.ToArray()) // take a snapshot, as we are modifying the underlying multidictionary { var local = variable as LocalSymbol; if ((object)local != null && local.RefKind != RefKind.None) { walker.AddSpillsForRef(walker.refLocalInitializers[local], result[local]); } } walker.Free(); return result; }
private IteratorAndAsyncCaptureWalker(CSharpCompilation compilation, MethodSymbol method, BoundNode node, CaptureWalkerEmptyStructTypeCache emptyStructCache, HashSet<Symbol> initiallyAssignedVariables) : base(compilation, method, node, emptyStructCache, trackUnassignments: true, initiallyAssignedVariables: initiallyAssignedVariables) { }
public static MultiDictionary<Symbol, CSharpSyntaxNode> Analyze(CSharpCompilation compilation, MethodSymbol method, BoundNode node) { var emptyStructs = new CaptureWalkerEmptyStructTypeCache(); var initiallyAssignedVariables = UnassignedVariablesWalker.Analyze(compilation, method, node, emptyStructs); var walker = new IteratorAndAsyncCaptureWalker(compilation, method, node, emptyStructs, initiallyAssignedVariables); bool badRegion = false; walker.Analyze(ref badRegion); Debug.Assert(!badRegion); var result = walker.variablesCaptured; if (!method.IsStatic && method.ContainingType.TypeKind == TypeKind.Struct) { // It is possible that the enclosing method only *writes* to the enclosing struct, but in that // case it should be considered captured anyway so that we have a proxy for it to write to. result.Add(method.ThisParameter, node.Syntax); } walker.Free(); return result; }
private IteratorAndAsyncCaptureWalker(CSharpCompilation compilation, MethodSymbol method, BoundNode node, CaptureWalkerEmptyStructTypeCache emptyStructCache, HashSet <Symbol> initiallyAssignedVariables) : base(compilation, method, node, emptyStructCache, trackUnassignments: true, initiallyAssignedVariables: initiallyAssignedVariables) { }