Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce TypeConversions allocations by caching them in AssemblySymbol #69040

Merged
merged 8 commits into from
Aug 16, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ protected ConversionsBase(AssemblySymbol corLibrary, int currentRecursionDepth,
Debug.Assert((object)corLibrary != null);
Debug.Assert(otherNullabilityOpt == null || includeNullability != otherNullabilityOpt.IncludeNullability);
Debug.Assert(otherNullabilityOpt == null || currentRecursionDepth == otherNullabilityOpt.currentRecursionDepth);
Debug.Assert(corLibrary == corLibrary.CorLibrary);

this.corLibrary = corLibrary;
this.currentRecursionDepth = currentRecursionDepth;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ private void Validate(CSharpCompilation compilation)
Debug.Assert(diagnostics.DependenciesBag is object);

var corLibrary = compilation.SourceAssembly.CorLibrary;
var conversions = new TypeConversions(corLibrary);
var conversions = corLibrary.TypeConversions;
foreach (var @using in UsingNamespacesOrTypes)
{
diagnostics.Clear();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ private BoundStatement WrapWithTryFinallyDispose(

idisposableTypeSymbol = disposeMethod.ContainingType;
Debug.Assert(_factory.CurrentFunction is { });
var conversions = new TypeConversions(_factory.CurrentFunction.ContainingAssembly.CorLibrary);
var conversions = _factory.CurrentFunction.ContainingAssembly.CorLibrary.TypeConversions;

CompoundUseSiteInfo<AssemblySymbol> useSiteInfo = GetNewCompoundUseSiteInfo();
isImplicit = conversions.ClassifyImplicitConversionFromType(enumeratorType, idisposableTypeSymbol, ref useSiteInfo).IsImplicit;
Expand Down
2 changes: 1 addition & 1 deletion src/Compilers/CSharp/Portable/Symbols/AliasSymbol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ internal void CheckConstraints(BindingDiagnosticBag diagnostics)
if ((object?)target != null && Locations.Length > 0)
{
var corLibrary = this.ContainingAssembly.CorLibrary;
var conversions = new TypeConversions(corLibrary);
var conversions = corLibrary.TypeConversions;
target.CheckAllConstraints(DeclaringCompilation, conversions, GetFirstLocation(), diagnostics);
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/Compilers/CSharp/Portable/Symbols/AssemblySymbol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ internal AssemblySymbol CorLibrary
}
}

internal abstract TypeConversions TypeConversions { get; }

/// <summary>
/// A helper method for ReferenceManager to set the system assembly, which provides primitive
/// types like Object, String, etc., e.g. mscorlib.dll.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ public static TypeParameterBounds ResolveBounds(
{
var constraintTypesBuilder = ArrayBuilder<TypeWithAnnotations>.GetInstance();
var interfacesBuilder = ArrayBuilder<NamedTypeSymbol>.GetInstance();
var conversions = new TypeConversions(corLibrary);
var conversions = corLibrary.TypeConversions;
var useSiteInfo = new CompoundUseSiteInfo<AssemblySymbol>(template);

// Resolve base types, determine the effective base class and
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -673,7 +673,7 @@ internal override bool IsCallerLineNumber
{
var discardedUseSiteInfo = CompoundUseSiteInfo<AssemblySymbol>.Discarded;
bool isCallerLineNumber = HasCallerLineNumberAttribute
&& new TypeConversions(ContainingAssembly).HasCallerLineNumberConversion(this.Type, ref discardedUseSiteInfo);
&& ContainingAssembly.TypeConversions.HasCallerLineNumberConversion(this.Type, ref discardedUseSiteInfo);

value = _packedFlags.SetWellKnownAttribute(flag, isCallerLineNumber);
}
Expand All @@ -693,7 +693,7 @@ internal override bool IsCallerFilePath
var discardedUseSiteInfo = CompoundUseSiteInfo<AssemblySymbol>.Discarded;
bool isCallerFilePath = !HasCallerLineNumberAttribute
&& HasCallerFilePathAttribute
&& new TypeConversions(ContainingAssembly).HasCallerInfoStringConversion(this.Type, ref discardedUseSiteInfo);
&& ContainingAssembly.TypeConversions.HasCallerInfoStringConversion(this.Type, ref discardedUseSiteInfo);

value = _packedFlags.SetWellKnownAttribute(flag, isCallerFilePath);
}
Expand All @@ -714,7 +714,7 @@ internal override bool IsCallerMemberName
bool isCallerMemberName = !HasCallerLineNumberAttribute
&& !HasCallerFilePathAttribute
&& HasCallerMemberNameAttribute
&& new TypeConversions(ContainingAssembly).HasCallerInfoStringConversion(this.Type, ref discardedUseSiteInfo);
&& ContainingAssembly.TypeConversions.HasCallerInfoStringConversion(this.Type, ref discardedUseSiteInfo);

value = _packedFlags.SetWellKnownAttribute(flag, isCallerMemberName);
}
Expand All @@ -737,7 +737,7 @@ internal override int CallerArgumentExpressionParameterIndex
&& !HasCallerLineNumberAttribute
&& !HasCallerFilePathAttribute
&& !HasCallerMemberNameAttribute
&& new TypeConversions(ContainingAssembly).HasCallerInfoStringConversion(this.Type, ref discardedUseSiteInfo);
&& ContainingAssembly.TypeConversions.HasCallerInfoStringConversion(this.Type, ref discardedUseSiteInfo);

if (isCallerArgumentExpression)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ internal abstract class MetadataOrSourceAssemblySymbol
/// </summary>
private NamedTypeSymbol[] _lazySpecialTypes;

private TypeConversions _lazyTypeConversions;

/// <summary>
/// How many Cor types have we cached so far.
/// </summary>
Expand Down Expand Up @@ -273,6 +275,24 @@ private ConcurrentDictionary<AssemblySymbol, IVTConclusion> AssembliesToWhichInt
}
}

internal sealed override TypeConversions TypeConversions
{
get
{
if (this != CorLibrary)
{
return CorLibrary.TypeConversions;
}

if (_lazyTypeConversions is null)
{
Interlocked.CompareExchange(ref _lazyTypeConversions, new TypeConversions(this), null);
}

return _lazyTypeConversions;
}
}

internal virtual bool IsNetModule() => false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ public override bool MightContainExtensionMethods
}
}

internal override TypeConversions TypeConversions => CorLibrary.TypeConversions;

public override AssemblyMetadata GetMetadata() => null;

internal sealed override IEnumerable<NamedTypeSymbol> GetAllTopLevelForwardedTypes()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,29 @@ internal sealed class MissingCorLibrarySymbol : MissingAssemblySymbol
/// <remarks></remarks>
private NamedTypeSymbol[] _lazySpecialTypes;

private TypeConversions _lazyTypeConversions;

private MissingCorLibrarySymbol()
: base(new AssemblyIdentity("<Missing Core Assembly>"))
{
this.SetCorLibrary(this);
}

internal override TypeConversions TypeConversions
{
get
{
Debug.Assert(this == CorLibrary);

if (_lazyTypeConversions is null)
{
Interlocked.CompareExchange(ref _lazyTypeConversions, new TypeConversions(this), null);
}

return _lazyTypeConversions;
}
}

/// <summary>
/// Lookup declaration for predefined CorLib type in this Assembly. Only should be
/// called if it is know that this is the Cor Library (mscorlib).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public static MethodSymbol Create(MethodSymbol method, TypeSymbol receiverType,
return null;
}

var conversions = new TypeConversions(method.ContainingAssembly.CorLibrary);
var conversions = method.ContainingAssembly.CorLibrary.TypeConversions;
var conversion = conversions.ConvertExtensionMethodThisArg(method.Parameters[0].Type, receiverType, ref useSiteInfo);
if (!conversion.Exists)
{
Expand Down Expand Up @@ -127,7 +127,7 @@ private static MethodSymbol InferExtensionMethodTypeArguments(MethodSymbol metho

var containingAssembly = method.ContainingAssembly;
var errorNamespace = containingAssembly.GlobalNamespace;
var conversions = new TypeConversions(containingAssembly.CorLibrary);
var conversions = containingAssembly.CorLibrary.TypeConversions;

// There is absolutely no plausible syntax/tree that we could use for these
// synthesized literals. We could be speculatively binding a call to a PE method.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,8 @@ public override bool MightContainExtensionMethods
get { return null; }
}

internal override TypeConversions TypeConversions => CorLibrary.TypeConversions;

internal override bool GetGuidString(out string guidString)
{
return _underlyingAssembly.GetGuidString(out guidString);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2225,7 +2225,7 @@ private void CheckIndexerSignatureCollisions(

private void CheckSpecialMemberErrors(BindingDiagnosticBag diagnostics)
{
var conversions = new TypeConversions(this.ContainingAssembly.CorLibrary);
var conversions = this.ContainingAssembly.CorLibrary.TypeConversions;
foreach (var member in this.GetMembersUnordered())
{
member.AfterAddingTypeMembersChecks(conversions, diagnostics);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ protected override void CheckBase(BindingDiagnosticBag diagnostics)
if (singleDeclaration != null)
{
var corLibrary = this.ContainingAssembly.CorLibrary;
var conversions = new TypeConversions(corLibrary);
var conversions = corLibrary.TypeConversions;
var location = singleDeclaration.NameLocation;

localBase.CheckAllConstraints(DeclaringCompilation, conversions, location, diagnostics);
Expand Down Expand Up @@ -159,7 +159,7 @@ protected override void CheckInterfaces(BindingDiagnosticBag diagnostics)
if (singleDeclaration != null)
{
var corLibrary = this.ContainingAssembly.CorLibrary;
var conversions = new TypeConversions(corLibrary);
var conversions = corLibrary.TypeConversions;
var location = singleDeclaration.NameLocation;

foreach (var pair in interfaces)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -997,7 +997,7 @@ private static void Validate(SourceNamespaceSymbol declaringSymbol, SyntaxRefere
}

var corLibrary = compilation.SourceAssembly.CorLibrary;
var conversions = new TypeConversions(corLibrary);
var conversions = corLibrary.TypeConversions;
foreach (var @using in usingsAndDiagnostics.UsingNamespacesOrTypes)
{
if (@using.UsingDirectiveReference!.SyntaxTree != declarationSyntax.SyntaxTree)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1460,7 +1460,7 @@ internal override void ForceComplete(SourceLocation locationOpt, CancellationTok
if (parameters.Length > 0)
{
var diagnostics = BindingDiagnosticBag.GetInstance();
var conversions = new TypeConversions(this.ContainingAssembly.CorLibrary);
var conversions = this.ContainingAssembly.CorLibrary.TypeConversions;
foreach (var parameter in this.Parameters)
{
parameter.ForceComplete(locationOpt, cancellationToken);
Expand Down Expand Up @@ -1489,7 +1489,7 @@ internal override void ForceComplete(SourceLocation locationOpt, CancellationTok
if (_state.NotePartComplete(CompletionPart.StartPropertyType))
{
var diagnostics = BindingDiagnosticBag.GetInstance();
var conversions = new TypeConversions(this.ContainingAssembly.CorLibrary);
var conversions = this.ContainingAssembly.CorLibrary.TypeConversions;
this.Type.CheckAllConstraints(DeclaringCompilation, conversions, Location, diagnostics);

ValidatePropertyType(diagnostics);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ private void CheckConstraintTypeConstraints(BindingDiagnosticBag diagnostics)
}

var args = ConstraintsHelper.CheckConstraintsArgsBoxed.Allocate(
DeclaringCompilation, new TypeConversions(ContainingAssembly.CorLibrary), _locations[0], diagnostics);
DeclaringCompilation, ContainingAssembly.CorLibrary.TypeConversions, _locations[0], diagnostics);
foreach (var constraintType in constraintTypes)
{
if (!diagnostics.ReportUseSite(constraintType.Type, args.Args.Location))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ internal override ImmutableArray<byte> PublicKey
get { throw new NotImplementedException(); }
}

internal override TypeConversions TypeConversions
{
get { throw new NotImplementedException(); }
}

public override ImmutableArray<ModuleSymbol> Modules
{
get { return ImmutableArray.Create<ModuleSymbol>(); }
Expand Down