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

TypeProvider Optimizations #322

Merged
merged 7 commits into from
Sep 28, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/Draco.Compiler/Api/Compilation.cs
Binto86 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@ public static Compilation Create(
/// </summary>
internal WellKnownTypes WellKnownTypes { get; }

/// <summary>
/// The type provider used for metadata references.
/// </summary>
internal TypeProvider TypeProvider { get; }

/// <summary>
/// Intrinsicly defined symbols for the compilation.
/// </summary>
Expand All @@ -153,6 +158,7 @@ private Compilation(
ModuleSymbol? sourceModule = null,
DeclarationTable? declarationTable = null,
WellKnownTypes? wellKnownTypes = null,
TypeProvider? typeProvider = null,
IntrinsicSymbols? intrinsicSymbols = null,
BinderCache? binderCache = null)
{
Expand All @@ -166,6 +172,7 @@ private Compilation(
this.sourceModule = sourceModule;
this.declarationTable = declarationTable;
this.WellKnownTypes = wellKnownTypes ?? new WellKnownTypes(this);
this.TypeProvider = typeProvider ?? new TypeProvider(this);
this.IntrinsicSymbols = intrinsicSymbols ?? new IntrinsicSymbols(this);
this.binderCache = binderCache ?? new BinderCache(this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,7 @@ public MetadataFieldSymbol(Symbol containingSymbol, FieldDefinition fieldDefinit
private TypeSymbol BuildType()
{
// Decode signature
var decoder = new TypeProvider(this.Assembly.Compilation);
return this.fieldDefinition.DecodeSignature(decoder, this);
return this.fieldDefinition.DecodeSignature(this.Assembly.Compilation.TypeProvider, this);
}
Binto86 marked this conversation as resolved.
Show resolved Hide resolved

private object? BuildDefaultValue()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,7 @@ private ImmutableArray<TypeParameterSymbol> BuildGenericParameters()
private void BuildSignature()
{
// Decode signature
var decoder = new TypeProvider(this.Assembly.Compilation);
var signature = this.methodDefinition.DecodeSignature(decoder, this);
var signature = this.methodDefinition.DecodeSignature(this.Assembly.Compilation.TypeProvider, this);

// Build parameters
var parameters = ImmutableArray.CreateBuilder<ParameterSymbol>();
Expand Down Expand Up @@ -194,7 +193,7 @@ private void BuildOverride()
{
var definition = this.MetadataReader.GetMethodDefinition(methodDef);
var name = this.MetadataReader.GetString(definition.Name);
var provider = new TypeProvider(this.Assembly.Compilation);
var provider = this.Assembly.Compilation.TypeProvider;
var signature = definition.DecodeSignature(provider, this);
var containingType = provider.GetTypeFromDefinition(this.MetadataReader, definition.GetDeclaringType(), 0);
return GetFunctionWithSignature(containingType, name, signature);
Expand All @@ -204,7 +203,7 @@ private void BuildOverride()
{
var reference = this.MetadataReader.GetMemberReference(methodRef);
var name = this.MetadataReader.GetString(reference.Name);
var provider = new TypeProvider(this.Assembly.Compilation);
var provider = this.Assembly.Compilation.TypeProvider;
var signature = reference.DecodeMethodSignature(provider, this);
var containingType = provider.GetTypeFromReference(this.MetadataReader, (TypeReferenceHandle)reference.Parent, 0);
return GetFunctionWithSignature(containingType, name, signature);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public static IEnumerable<Symbol> ToSymbol(
foreach (var attributeHandle in typeDefinition.GetCustomAttributes())
{
var attribute = reader.GetCustomAttribute(attributeHandle);
var typeProvider = new TypeProvider(compilation!);
var typeProvider = compilation.TypeProvider;
switch (attribute.Constructor.Kind)
{
case HandleKind.MethodDefinition:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ private ImmutableArray<TypeParameterSymbol> BuildGenericParameters()
private ImmutableArray<TypeSymbol> BuildBaseTypes()
{
var builder = ImmutableArray.CreateBuilder<TypeSymbol>();
var typeProvider = new TypeProvider(this.Assembly.Compilation);
var typeProvider = this.Assembly.Compilation.TypeProvider;
if (!this.typeDefinition.BaseType.IsNil)
{
builder.Add(GetTypeFromMetadata(this.typeDefinition.BaseType));
Expand Down
22 changes: 19 additions & 3 deletions src/Draco.Compiler/Internal/Symbols/Metadata/TypeProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ internal sealed class TypeProvider : ISignatureTypeProvider<TypeSymbol, Symbol>,
private IntrinsicSymbols IntrinsicSymbols => this.compilation.IntrinsicSymbols;

private readonly Compilation compilation;
private readonly Dictionary<EntityHandle, TypeSymbol> cache = new();

public TypeProvider(Compilation compilation)
{
Expand All @@ -36,6 +37,7 @@ public TypeSymbol GetGenericInstantiation(TypeSymbol genericType, ImmutableArray
if (ReferenceEquals(genericType, UnknownType)) return UnknownType;
return genericType.GenericInstantiate(genericType.ContainingSymbol, typeArguments);
}

public TypeSymbol GetGenericMethodParameter(Symbol genericContext, int index)
{
var methodAncestor = genericContext.AncestorChain
Expand All @@ -46,6 +48,7 @@ public TypeSymbol GetGenericMethodParameter(Symbol genericContext, int index)
? methodAncestor.GenericParameters[index]
: methodAncestor.GenericDefinition!.GenericParameters[index];
}

public TypeSymbol GetGenericTypeParameter(Symbol genericContext, int index)
{
var typeAncestor = genericContext.AncestorChain
Expand All @@ -56,6 +59,7 @@ public TypeSymbol GetGenericTypeParameter(Symbol genericContext, int index)
? typeAncestor.GenericParameters[index]
: typeAncestor.GenericDefinition!.GenericParameters[index];
}

public TypeSymbol GetModifiedType(TypeSymbol modifier, TypeSymbol unmodifiedType, bool isRequired) => UnknownType;
public TypeSymbol GetPinnedType(TypeSymbol elementType) => UnknownType;
public TypeSymbol GetPointerType(TypeSymbol elementType) => UnknownType;
Expand Down Expand Up @@ -84,8 +88,10 @@ public TypeSymbol GetGenericTypeParameter(Symbol genericContext, int index)

_ => UnknownType,
};

public TypeSymbol GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind)
{
if (this.cache.ContainsKey(handle)) return this.cache[handle];
var definition = reader.GetTypeDefinition(handle);
if (definition.IsNested)
{
Expand All @@ -101,6 +107,7 @@ public TypeSymbol GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHan
.OfType<TypeSymbol>()
.Where(t => t.Name == nestedName && t.GenericParameters.Length == nestedGenericArgc)
.Single();
this.cache[handle] = nestedSymbol;
return nestedSymbol;
}

Expand All @@ -114,10 +121,14 @@ public TypeSymbol GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHan
var fullName = string.IsNullOrWhiteSpace(@namespace) ? name : $"{@namespace}.{name}";
var path = fullName.Split('.').ToImmutableArray();

return this.WellKnownTypes.GetTypeFromAssembly(assemblyName, path);
var result = this.WellKnownTypes.GetTypeFromAssembly(assemblyName, path);
this.cache[handle] = result;
return result;
}

public TypeSymbol GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind)
{
if (this.cache.ContainsKey(handle)) return this.cache[handle];
var parts = new List<string>();
var reference = reader.GetTypeReference(handle);
parts.Add(reader.GetString(reference.Name));
Expand All @@ -134,12 +145,17 @@ public TypeSymbol GetTypeFromReference(MetadataReader reader, TypeReferenceHandl
// TODO: If we don't have the assembly report error
var assemblyName = reader.GetAssemblyReference((AssemblyReferenceHandle)resolutionScope).GetAssemblyName();
var assembly = this.compilation.MetadataAssemblies.Values.Single(x => x.AssemblyName.FullName == assemblyName.FullName);
return assembly.RootNamespace.Lookup(parts.ToImmutableArray()).OfType<TypeSymbol>().Single();
var result = assembly.RootNamespace.Lookup(parts.ToImmutableArray()).OfType<TypeSymbol>().Single();
this.cache[handle] = result;
return result;
}

// TODO: Should we cache this as well? doesn't seem to have any effect
public TypeSymbol GetTypeFromSpecification(MetadataReader reader, Symbol genericContext, TypeSpecificationHandle handle, byte rawTypeKind)
{
var specification = reader.GetTypeSpecification(handle);
return specification.DecodeSignature(this, genericContext);
var result = specification.DecodeSignature(this, genericContext);
return result;
Binto86 marked this conversation as resolved.
Show resolved Hide resolved
}

public TypeSymbol GetSystemType() => this.WellKnownTypes.SystemType;
Expand Down
Loading