提交 766e4386 编写于 作者: P Pharring

TranslationSyntaxReference allocations were showing up in typing scenario...

TranslationSyntaxReference allocations were showing up in typing scenario profiles (3.7% for C# and 1% for VB).

Fixes applied to both C# and VB:
1) Move the TranslationalSyntaxReference class down into the common layer and reduce its size by one field. Instead of storing the delegate, it's now an abstract base class. Implementations supply the "translate" method.
2) Size the ArrayBuilder instance exactly to avoid wastage. (changeset 1215193)
上级 a4c59ad6
......@@ -759,6 +759,7 @@
<Compile Include="Syntax\InternalSyntax\SyntaxVisitor.cs" />
<Compile Include="Syntax\MethodDeclarationSyntax.cs" />
<Compile Include="Syntax\NamespaceDeclarationSyntax.cs" />
<Compile Include="Syntax\NamespaceDeclarationSyntaxReference.cs" />
<Compile Include="Syntax\NameSyntax.cs" />
<Compile Include="Syntax\ParameterSyntax.cs" />
<Compile Include="Syntax\QualifiedNameSyntax.cs" />
......@@ -791,7 +792,6 @@
<Compile Include="Syntax\SyntaxTreeDiagnosticEnumerator.cs" />
<Compile Include="Syntax\SyntaxTriviaFunctions.cs" />
<Compile Include="Syntax\SyntaxTriviaListBuilder.cs" />
<Compile Include="Syntax\TranslationalSyntaxReference.cs" />
<Compile Include="Syntax\TypeDeclarationSyntax.cs" />
<Compile Include="Syntax\TypeSyntax.cs" />
<Compile Include="Syntax\XmlNameAttributeElementKind.cs" />
......
......@@ -106,21 +106,8 @@ public override ImmutableArray<Location> Locations
}
}
private static readonly Func<SyntaxReference, CSharpSyntaxNode> NamespaceDeclarationGetter = r =>
{
var node = (CSharpSyntaxNode)r.GetSyntax();
// If the node is a name syntax, it's something like "X" or "X.Y" in :
// namespace X.Y.Z
// We want to return the full NamespaceDeclarationSyntax.
while (node is NameSyntax)
{
node = node.Parent;
}
Debug.Assert(node is CompilationUnitSyntax || node is NamespaceDeclarationSyntax);
return node;
};
private static readonly Func<SingleNamespaceDeclaration, SyntaxReference> DeclaringSyntaxReferencesSelector = d =>
new NamespaceDeclarationSyntaxReference(d.SyntaxReference);
public override ImmutableArray<SyntaxReference> DeclaringSyntaxReferences
{
......@@ -129,14 +116,7 @@ public override ImmutableArray<SyntaxReference> DeclaringSyntaxReferences
// SyntaxReference in the namespace declaration points to the name node of the namespace decl node not
// namespace decl node we want to return. here we will wrap the original syntax reference in
// the translation syntax reference so that we can lazily manipulate a node return to the caller
ArrayBuilder<SyntaxReference> builder = ArrayBuilder<SyntaxReference>.GetInstance();
foreach (SingleNamespaceDeclaration decl in mergedDeclaration.Declarations)
{
builder.Add(new TranslationSyntaxReference(decl.SyntaxReference, NamespaceDeclarationGetter));
}
return builder.ToImmutableAndFree();
return mergedDeclaration.Declarations.SelectAsArray(DeclaringSyntaxReferencesSelector);
}
}
......
// Copyright (c) Microsoft Open Technologies, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Diagnostics;
using System.Threading;
using Microsoft.CodeAnalysis.Syntax;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Microsoft.CodeAnalysis.CSharp
{
/// <summary>
/// A SyntaxReference implementation that lazily translates the result (CSharpSyntaxNode) of the
/// original syntax reference to a syntax reference for its NamespaceDeclarationSyntax.
/// </summary>
internal sealed class NamespaceDeclarationSyntaxReference : TranslationSyntaxReference
{
public NamespaceDeclarationSyntaxReference(SyntaxReference reference)
: base(reference)
{
}
protected override SyntaxNode Translate(SyntaxReference reference, CancellationToken cancellationToken)
{
var node = (CSharpSyntaxNode)reference.GetSyntax();
// If the node is a name syntax, it's something like "X" or "X.Y" in :
// namespace X.Y.Z
// We want to return the full NamespaceDeclarationSyntax.
while (node is NameSyntax)
{
node = node.Parent;
}
Debug.Assert(node is CompilationUnitSyntax || node is NamespaceDeclarationSyntax);
return node;
}
}
}
\ No newline at end of file
......@@ -555,6 +555,7 @@
<Compile Include="Syntax\SyntaxTriviaList.Reversed.cs" />
<Compile Include="Syntax\SyntaxWalker.cs" />
<Compile Include="Syntax\SyntaxWalkerDepth.cs" />
<Compile Include="Syntax\TranslationSyntaxReference.cs" />
<Compile Include="Text\ChangedText.cs" />
<Compile Include="Text\CompositeText.cs" />
<Compile Include="Text\LinePosition.cs" />
......
// Copyright (c) Microsoft Open Technologies, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
using System.Diagnostics;
namespace Microsoft.CodeAnalysis.CSharp
namespace Microsoft.CodeAnalysis.Syntax
{
/// <summary>
/// this is a SyntaxReference implementation that lazily translates the result (CSharpSyntaxNode) of the original syntax reference
/// to other one.
/// This is a SyntaxReference implementation that lazily translates the result (SyntaxNode) of the
/// original syntax reference to another one.
/// </summary>
internal class TranslationSyntaxReference : SyntaxReference
internal abstract class TranslationSyntaxReference : SyntaxReference
{
private readonly SyntaxReference reference;
private readonly Func<SyntaxReference, SyntaxNode> nodeGetter;
public TranslationSyntaxReference(SyntaxReference reference, Func<SyntaxReference, SyntaxNode> nodeGetter)
protected TranslationSyntaxReference(SyntaxReference reference)
{
this.reference = reference;
this.nodeGetter = nodeGetter;
}
public override SyntaxNode GetSyntax(CancellationToken cancellationToken)
public sealed override TextSpan Span
{
var node = nodeGetter(this.reference);
Debug.Assert(node.SyntaxTree == this.reference.SyntaxTree);
return node;
get { return reference.Span; }
}
public override TextSpan Span
public sealed override SyntaxTree SyntaxTree
{
get { return this.reference.Span; }
get { return reference.SyntaxTree; }
}
public override SyntaxTree SyntaxTree
public sealed override SyntaxNode GetSyntax(CancellationToken cancellationToken = default(CancellationToken))
{
get { return this.reference.SyntaxTree; }
var node = Translate(reference, cancellationToken);
Debug.Assert(node.SyntaxTree == this.reference.SyntaxTree);
return node;
}
protected abstract SyntaxNode Translate(SyntaxReference reference, CancellationToken cancellationToken);
}
}
\ No newline at end of file
}
......@@ -832,6 +832,7 @@
<Compile Include="Symbols\WellKnownMembers.vb" />
<Compile Include="Syntax\ArrayRankSpecifierSyntax.vb" />
<Compile Include="Syntax\BaseSyntaxExtensions.vb" />
<Compile Include="Syntax\BeginOfBlockSyntaxReference.vb" />
<Compile Include="Syntax\CompilationUnitSyntax.vb" />
<Compile Include="Syntax\DirectiveTriviaSyntax.vb" />
<Compile Include="Syntax\InternalSyntax\BadTokenSyntax.vb" />
......@@ -855,6 +856,7 @@
<Compile Include="Syntax\InternalSyntax\SyntaxSubKind.vb" />
<Compile Include="Syntax\InternalSyntax\SyntaxToken.vb" />
<Compile Include="Syntax\InternalSyntax\SyntaxTrivia.vb" />
<Compile Include="Syntax\NamespaceDeclarationSyntaxReference.vb" />
<Compile Include="Syntax\NameSyntax.vb" />
<Compile Include="Syntax\SeparatedSyntaxListBuilder.vb" />
<Compile Include="Syntax\SimpleSyntaxReference.vb" />
......@@ -883,7 +885,6 @@
<Compile Include="Syntax\SyntaxTreeDiagnosticEnumerator.vb" />
<Compile Include="Syntax\SyntaxTriviaFunctions.vb" />
<Compile Include="Syntax\SyntaxTriviaListBuilder.vb" />
<Compile Include="Syntax\TranslationSyntaxReference.vb" />
<Compile Include="Syntax\TypeStatementSyntax.vb" />
<Compile Include="Syntax\VisualBasicLineDirectiveMap.vb" />
<Compile Include="Syntax\VisualBasicSyntaxNode.vb" />
......
......@@ -395,15 +395,17 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
Public Overrides ReadOnly Property DeclaringSyntaxReferences As ImmutableArray(Of SyntaxReference)
Get
Dim builder As ArrayBuilder(Of SyntaxReference) = ArrayBuilder(Of SyntaxReference).GetInstance()
Dim declarations As ImmutableArray(Of SingleNamespaceDeclaration) = m_declaration.Declarations
Dim builder As ArrayBuilder(Of SyntaxReference) = ArrayBuilder(Of SyntaxReference).GetInstance(declarations.Length)
' SyntaxReference in the namespace declaration points to the name node of the namespace decl node not
' namespace decl node we want to return. here we will wrap the original syntax reference in
' the translation syntax reference so that we can lazily manipulate a node return to the caller
For Each decl In m_declaration.Declarations
For Each decl In declarations
Dim reference = decl.SyntaxReference
If reference IsNot Nothing AndAlso Not reference.SyntaxTree.IsEmbeddedOrMyTemplateTree() Then
builder.Add(New TranslationSyntaxReference(reference, NamespaceDeclarationGetter))
builder.Add(New NamespaceDeclarationSyntaxReference(reference))
End If
Next
......@@ -411,21 +413,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
End Get
End Property
Private Shared ReadOnly NamespaceDeclarationGetter As Func(Of SyntaxReference, VisualBasicSyntaxNode) =
Function(r)
Dim node = r.GetSyntax()
' If the node is a name syntax, it's something like "X" or "X.Y" in :
' Namespace X.Y.Z
' We want to return the full NamespaceStatementSyntax.
While TypeOf node Is NameSyntax
node = node.Parent
End While
Debug.Assert(TypeOf node Is CompilationUnitSyntax OrElse TypeOf node Is NamespaceStatementSyntax)
Return DirectCast(node, VisualBasicSyntaxNode)
End Function
Friend Overrides Function IsDefinedInSourceTree(tree As SyntaxTree, definedWithinSpan As TextSpan?, Optional cancellationToken As CancellationToken = Nothing) As Boolean
If Me.IsGlobalNamespace Then
Return True
......
......@@ -329,8 +329,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
For Each reference In references
Dim tree = reference.SyntaxTree
If Not tree.IsEmbeddedOrMyTemplateTree() Then
builder.Add(New TranslationSyntaxReference(reference, Function(r) DirectCast(SyntaxFacts.BeginOfBlockStatementIfAny(r.GetSyntax()), VisualBasicSyntaxNode)))
builder.Add(New BeginOfBlockSyntaxReference(reference))
End If
Next
......@@ -341,8 +340,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
If reference IsNot Nothing Then
Dim tree = reference.SyntaxTree
If Not tree.IsEmbeddedOrMyTemplateTree() Then
Return ImmutableArray.Create(Of SyntaxReference)(New TranslationSyntaxReference(reference, Function(r) DirectCast(SyntaxFacts.BeginOfBlockStatementIfAny(r.GetSyntax()), VisualBasicSyntaxNode)))
Return ImmutableArray.Create(Of SyntaxReference)(New BeginOfBlockSyntaxReference(reference))
End If
End If
......
' Copyright (c) Microsoft Open Technologies, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Threading
Imports Microsoft.CodeAnalysis.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic
''' <summary>
''' This is a SyntaxReference implementation that lazily finds the beginning of the block (if any) of the original syntax reference
''' </summary>
Friend Class BeginOfBlockSyntaxReference
Inherits TranslationSyntaxReference
Public Sub New(reference As SyntaxReference)
MyBase.New(reference)
End Sub
Protected Overrides Function Translate(reference As SyntaxReference, cancellationToken As CancellationToken) As SyntaxNode
Return SyntaxFacts.BeginOfBlockStatementIfAny(reference.GetSyntax())
End Function
End Class
End Namespace
\ No newline at end of file
' Copyright (c) Microsoft Open Technologies, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Threading
Imports System.Threading.Tasks
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.Syntax
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic
''' <summary>
''' this is a SyntaxReference implementation that lazily translates the result (SyntaxNode) of the original syntax reference
''' to other one.
''' </summary>
Friend Class TranslationSyntaxReference
Inherits SyntaxReference
Friend Class NamespaceDeclarationSyntaxReference
Inherits TranslationSyntaxReference
Private ReadOnly _reference As SyntaxReference
Private ReadOnly _nodeGetter As Func(Of SyntaxReference, SyntaxNode)
Public Sub New(reference As SyntaxReference, nodeGetter As Func(Of SyntaxReference, SyntaxNode))
_reference = reference
_nodeGetter = nodeGetter
Public Sub New(reference As SyntaxReference)
MyBase.New(reference)
End Sub
Public Overrides Function GetSyntax(Optional cancellationToken As CancellationToken = Nothing) As SyntaxNode
Dim node = _nodeGetter(_reference)
Debug.Assert(node.SyntaxTree Is _reference.SyntaxTree)
Return node
End Function
Protected Overrides Function Translate(reference As SyntaxReference, cancellationToken As CancellationToken) As SyntaxNode
Dim node = reference.GetSyntax()
Public Overrides ReadOnly Property Span As TextSpan
Get
Return _reference.Span
End Get
End Property
' If the node is a name syntax, it's something like "X" or "X.Y" in :
' Namespace X.Y.Z
' We want to return the full NamespaceStatementSyntax.
While TypeOf node Is NameSyntax
node = node.Parent
End While
Public Overrides ReadOnly Property SyntaxTree As SyntaxTree
Get
Return _reference.SyntaxTree
End Get
End Property
Debug.Assert(TypeOf node Is CompilationUnitSyntax OrElse TypeOf node Is NamespaceStatementSyntax)
Return node
End Function
End Class
End Namespace
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册