From d7592d38c88ec8410fe66c2a6078af5363e0a157 Mon Sep 17 00:00:00 2001 From: Fredric Silberberg Date: Mon, 26 Nov 2018 16:20:28 -0800 Subject: [PATCH] Make a few nodes lazy where they weren't previously, and address a couple of other feedback items. --- .../Operations/CSharpOperationFactory.cs | 49 ++++++++++--------- .../Operations/CSharpOperationNodes.cs | 39 +++++++++++++++ 2 files changed, 66 insertions(+), 22 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs index f329ea46cb0..5f5d8099ca2 100644 --- a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs +++ b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs @@ -414,7 +414,7 @@ private IOperation CreateBoundCallOperation(BoundCall boundCall) return new CSharpLazyInvocationOperation(this, boundCall, targetMethod, isVirtual, _semanticModel, syntax, type, constantValue, isImplicit); } - private IOperation CreateBoundLocalOperation(BoundLocal boundLocal) + internal IOperation CreateBoundLocalOperation(BoundLocal boundLocal, bool createDeclaration = true) { ILocalSymbol local = boundLocal.LocalSymbol; bool isDeclaration = boundLocal.DeclarationKind != BoundLocalDeclarationKind.None; @@ -425,13 +425,15 @@ private IOperation CreateBoundLocalOperation(BoundLocal boundLocal) if (isDeclaration && syntax is DeclarationExpressionSyntax declarationExpressionSyntax) { syntax = declarationExpressionSyntax.Designation; - var localReference = new LocalReferenceOperation(local, isDeclaration, _semanticModel, syntax, type, constantValue, isImplicit); - return new DeclarationExpressionOperation(localReference, _semanticModel, declarationExpressionSyntax, type, constantValue: default, isImplicit: false); + if (createDeclaration) + { + return new CSharpLazyDeclarationExpressionOperation(this, boundLocal, _semanticModel, declarationExpressionSyntax, type, constantValue: default, isImplicit: false); + } } return new LocalReferenceOperation(local, isDeclaration, _semanticModel, syntax, type, constantValue, isImplicit); } - private IOperation CreateBoundFieldAccessOperation(BoundFieldAccess boundFieldAccess) + internal IOperation CreateBoundFieldAccessOperation(BoundFieldAccess boundFieldAccess, bool createDeclaration = true) { IFieldSymbol field = boundFieldAccess.FieldSymbol; bool isDeclaration = boundFieldAccess.IsDeclaration; @@ -443,8 +445,11 @@ private IOperation CreateBoundFieldAccessOperation(BoundFieldAccess boundFieldAc if (isDeclaration && syntax is DeclarationExpressionSyntax declarationExpressionSyntax) { syntax = declarationExpressionSyntax.Designation; - var fieldReference = new CSharpLazyFieldReferenceOperation(this, instance, field, isDeclaration, _semanticModel, syntax, type, constantValue, isImplicit); - return new DeclarationExpressionOperation(fieldReference, _semanticModel, declarationExpressionSyntax, type, constantValue: default, isImplicit: false); + + if (createDeclaration) + { + return new CSharpLazyDeclarationExpressionOperation(this, boundFieldAccess, _semanticModel, declarationExpressionSyntax, type, constantValue: default, isImplicit: false); + } } return new CSharpLazyFieldReferenceOperation(this, instance, field, isDeclaration, _semanticModel, syntax, type, constantValue, isImplicit); } @@ -520,7 +525,6 @@ private IOperation CreateBoundIndexerAccessOperation(BoundIndexerAccess boundInd return CreateInvalidExpressionForHasArgumentsExpression(boundIndexerAccess.ReceiverOpt, boundIndexerAccess.Arguments, null, syntax, type, constantValue, isImplicit); } - BoundNode instance = boundIndexerAccess.ReceiverOpt; return new CSharpLazyPropertyReferenceOperation(this, boundIndexerAccess, isObjectOrCollectionInitializer, property, _semanticModel, syntax, type, constantValue, isImplicit); } @@ -696,11 +700,6 @@ private IObjectOrCollectionInitializerOperation CreateBoundCollectionInitializer private IOperation CreateBoundObjectInitializerMemberOperation(BoundObjectInitializerMember boundObjectInitializerMember, bool isObjectOrCollectionInitializer = false) { Symbol memberSymbol = boundObjectInitializerMember.MemberSymbol; - - IOperation instance = memberSymbol?.IsStatic == true ? - null : - CreateImplicitReciever(boundObjectInitializerMember.Syntax, boundObjectInitializerMember.ReceiverType); - SyntaxNode syntax = boundObjectInitializerMember.Syntax; ITypeSymbol type = boundObjectInitializerMember.Type; Optional constantValue = ConvertToOptional(boundObjectInitializerMember.ConstantValue); @@ -720,10 +719,10 @@ private IOperation CreateBoundObjectInitializerMemberOperation(BoundObjectInitia case SymbolKind.Field: var field = (FieldSymbol)memberSymbol; bool isDeclaration = false; - return new FieldReferenceOperation(field, isDeclaration, instance, _semanticModel, syntax, type, constantValue, isImplicit); + return new FieldReferenceOperation(field, isDeclaration, createReceiver(), _semanticModel, syntax, type, constantValue, isImplicit); case SymbolKind.Event: var eventSymbol = (EventSymbol)memberSymbol; - return new EventReferenceOperation(eventSymbol, instance, _semanticModel, syntax, type, constantValue, isImplicit); + return new EventReferenceOperation(eventSymbol, createReceiver(), _semanticModel, syntax, type, constantValue, isImplicit); case SymbolKind.Property: var property = (PropertySymbol)memberSymbol; if (boundObjectInitializerMember.Arguments.Any()) @@ -742,6 +741,10 @@ private IOperation CreateBoundObjectInitializerMemberOperation(BoundObjectInitia default: throw ExceptionUtilities.Unreachable; } + + IOperation createReceiver() => memberSymbol?.IsStatic == true ? + null : + CreateImplicitReciever(boundObjectInitializerMember.Syntax, boundObjectInitializerMember.ReceiverType); } private IOperation CreateBoundDynamicObjectInitializerMemberOperation(BoundDynamicObjectInitializerMember boundDynamicObjectInitializerMember) @@ -1789,17 +1792,17 @@ private IExpressionStatementOperation CreateBoundExpressionStatementOperation(Bo return new CSharpLazyExpressionStatementOperation(this, expression, _semanticModel, syntax, type, constantValue, isImplicit); } - private IOperation CreateBoundTupleLiteralOperation(BoundTupleLiteral boundTupleLiteral) + internal IOperation CreateBoundTupleLiteralOperation(BoundTupleLiteral boundTupleLiteral, bool createDeclaration = true) { - return CreateTupleOperation(boundTupleLiteral, boundTupleLiteral.Type); + return CreateTupleOperation(boundTupleLiteral, boundTupleLiteral.Type, createDeclaration); } - private IOperation CreateBoundConvertedTupleLiteralOperation(BoundConvertedTupleLiteral boundConvertedTupleLiteral) + internal IOperation CreateBoundConvertedTupleLiteralOperation(BoundConvertedTupleLiteral boundConvertedTupleLiteral, bool createDeclaration = true) { - return CreateTupleOperation(boundConvertedTupleLiteral, boundConvertedTupleLiteral.NaturalTypeOpt); + return CreateTupleOperation(boundConvertedTupleLiteral, boundConvertedTupleLiteral.NaturalTypeOpt, createDeclaration); } - private IOperation CreateTupleOperation(BoundTupleExpression boundTupleExpression, ITypeSymbol naturalType) + internal IOperation CreateTupleOperation(BoundTupleExpression boundTupleExpression, ITypeSymbol naturalType, bool createDeclaration) { SyntaxNode syntax = boundTupleExpression.Syntax; bool isImplicit = boundTupleExpression.WasCompilerGenerated; @@ -1807,9 +1810,11 @@ private IOperation CreateTupleOperation(BoundTupleExpression boundTupleExpressio Optional constantValue = default; if (syntax is DeclarationExpressionSyntax declarationExpressionSyntax) { - var tupleSyntax = declarationExpressionSyntax.Designation; - var tuple = new CSharpLazyTupleOperation(this, boundTupleExpression, _semanticModel, tupleSyntax, type, naturalType, constantValue, isImplicit); - return new DeclarationExpressionOperation(tuple, _semanticModel, declarationExpressionSyntax, type, constantValue: default, isImplicit: false); + syntax = declarationExpressionSyntax.Designation; + if (createDeclaration) + { + return new CSharpLazyDeclarationExpressionOperation(this, boundTupleExpression, _semanticModel, declarationExpressionSyntax, type, constantValue: default, isImplicit: false); + } } return new CSharpLazyTupleOperation(this, boundTupleExpression, _semanticModel, syntax, type, naturalType, constantValue, isImplicit); diff --git a/src/Compilers/CSharp/Portable/Operations/CSharpOperationNodes.cs b/src/Compilers/CSharp/Portable/Operations/CSharpOperationNodes.cs index 2efe7d14e72..fb0d659c572 100644 --- a/src/Compilers/CSharp/Portable/Operations/CSharpOperationNodes.cs +++ b/src/Compilers/CSharp/Portable/Operations/CSharpOperationNodes.cs @@ -1,7 +1,10 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Collections.Immutable; +using System.Diagnostics; using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Operations { @@ -205,6 +208,42 @@ protected override IOperation CreateValue() } } + internal sealed class CSharpLazyDeclarationExpressionOperation : LazyDeclarationExpressionOperation + { + private readonly CSharpOperationFactory _operationFactory; + private readonly BoundExpression _underlyingReference; + + public CSharpLazyDeclarationExpressionOperation(CSharpOperationFactory operationFactory, BoundExpression underlyingReference, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(semanticModel, syntax, type, constantValue, isImplicit) + { + Debug.Assert(underlyingReference.Kind == BoundKind.Local || + underlyingReference.Kind == BoundKind.FieldAccess || + underlyingReference is BoundTupleExpression); + + _operationFactory = operationFactory; + _underlyingReference = underlyingReference; + } + + protected override IOperation CreateExpression() + { + SyntaxNode underlyingSyntax = ((DeclarationExpressionSyntax)_underlyingReference.Syntax).Designation; + + switch (_underlyingReference) + { + case BoundLocal local: + return _operationFactory.CreateBoundLocalOperation(local, createDeclaration: false); + case BoundTupleLiteral tupleLiteral: + return _operationFactory.CreateBoundTupleLiteralOperation(tupleLiteral, createDeclaration: false); + case BoundConvertedTupleLiteral convertedTupleLiteral: + return _operationFactory.CreateBoundConvertedTupleLiteralOperation(convertedTupleLiteral, createDeclaration: false); + case BoundFieldAccess fieldAccess: + return _operationFactory.CreateBoundFieldAccessOperation(fieldAccess, createDeclaration: false); + default: + throw ExceptionUtilities.UnexpectedValue(_underlyingReference.Kind); + } + } + } + internal sealed class CSharpLazyAwaitOperation : LazyAwaitOperation { private readonly CSharpOperationFactory _operationFactory; -- GitLab