Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Only R2R methods that are either publicly exposed or (to make sure we…
… cover all of the methods in CoreLib used by the runtime) any embedded linker xml root files.
  • Loading branch information
jkoritzinsky committed Oct 4, 2022
commit d583b6c982f5bb873752fd449a83b83b8bedf722
26 changes: 26 additions & 0 deletions src/coreclr/tools/Common/TypeSystem/Ecma/EcmaType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public sealed partial class EcmaType : MetadataType, EcmaModule.IEntityHandleObj
private TypeDesc[] _genericParameters;
private MetadataType _baseType;
private int _hashcode;
private MethodImplRecord[] _allMethodImplsForType;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should inline this logic to where it's needed (or into an extension method). It doesn't look like we need to cache this and metadata reader + handle is available as a public API on EcmaType.


internal EcmaType(EcmaModule module, TypeDefinitionHandle handle)
{
Expand Down Expand Up @@ -151,6 +152,31 @@ public TypeDefinitionHandle Handle
}
}

public MethodImplRecord[] AllMethodImplsForType
{
get
{
return _allMethodImplsForType ??= GetAllMethodImplRecordsForType();
}
}

public MethodImplRecord[] GetAllMethodImplRecordsForType()
{
ArrayBuilder<MethodImplRecord> records = default;
MetadataReader metadataReader = _module.MetadataReader;

foreach (var methodImplHandle in _typeDefinition.GetMethodImplementations())
{
MethodImplementation methodImpl = metadataReader.GetMethodImplementation(methodImplHandle);

records.Add(new MethodImplRecord(
_module.GetMethod(methodImpl.MethodDeclaration),
_module.GetMethod(methodImpl.MethodBody)
));
}
return records.ToArray();
}

private MetadataType InitializeBaseType()
{
var baseTypeHandle = _typeDefinition.BaseType;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,8 @@
<Compile Include="..\..\Common\Compiler\CompilerTypeSystemContext.cs" Link="Compiler\CompilerTypeSystemContext.cs" />
<Compile Include="..\..\Common\Compiler\CompilerTypeSystemContext.Validation.cs" Link="Compiler\CompilerTypeSystemContext.Validation.cs" />
<Compile Include="..\..\Common\Compiler\NativeAotNameMangler.cs" Link="Compiler\NativeAotNameMangler.cs" />
<Compile Include="..\..\Common\Compiler\Dataflow\DynamicallyAccessedMembersBinder.cs" Link="Compiler\Dataflow\DynamicallyAccessedMembersBinder.cs" />
<Compile Include="..\..\Common\Compiler\Dataflow\EcmaExtensions.cs" Link="Compiler\Dataflow\EcmaExtensions.cs" />
<Compile Include="..\..\Common\Compiler\DependencyAnalysis\AssemblyStubNode.cs" Link="Compiler\DependencyAnalysis\AssemblyStubNode.cs" />
<Compile Include="..\..\Common\Compiler\DependencyAnalysis\CompilerComparer.cs" Link="Compiler\DependencyAnalysis\CompilerComparer.cs" />
<Compile Include="..\..\Common\Compiler\DependencyAnalysis\EmbeddedDataContainerNode.cs" Link="Compiler\DependencyAnalysis\EmbeddedDataContainerNode.cs" />
Expand Down Expand Up @@ -304,23 +306,28 @@
<Compile Include="..\..\Common\Compiler\DependencyAnalysis\Target_X86\X86Emitter.cs" Link="Compiler\DependencyAnalysis\Target_X86\X86Emitter.cs" />
<Compile Include="..\..\Common\Compiler\DependencyTrackingLevel.cs" Link="Compiler\DependencyTrackingLevel.cs" />
<Compile Include="..\..\Common\Compiler\DevirtualizationManager.cs" Link="Compiler\DevirtualizationManager.cs" />
<Compile Include="..\..\Common\Compiler\FeatureSettings.cs" Link="Compiler\FeatureSettings.cs" />
<Compile Include="..\..\Common\Compiler\HardwareIntrinsicHelpers.cs" Link="Compiler\HardwareIntrinsicHelpers.cs" />
<Compile Include="..\..\Common\Compiler\ICompilationRootProvider.cs" Link="Compiler\ICompilationRootProvider.cs" />
<Compile Include="..\..\Common\Compiler\InstructionSetSupport.cs" Link="Compiler\InstructionSetSupport.cs" />
<Compile Include="..\..\Common\Compiler\Int128FieldLayoutAlgorithm.cs" Link="Compiler\Int128FieldLayoutAlgorithm.cs" />
<Compile Include="..\..\Common\Compiler\InternalCompilerErrorException.cs" Link="Compiler\InternalCompilerErrorException.cs" />
<Compile Include="..\..\Common\Compiler\MethodExtensions.cs" Link="Compiler\MethodExtensions.cs" />
<Compile Include="..\..\Common\Compiler\NameMangler.cs" Link="Compiler\NameMangler.cs" />
<Compile Include="..\..\Common\Compiler\ProcessLinkerXmlBase.cs" Link="Compiler\ProcessLinkerXmlBase.cs" />
<Compile Include="..\..\Common\Compiler\PropertyPseudoDesc.cs" Link="Compiler\PropertyPseudoDesc.cs" />
<Compile Include="..\..\Common\Compiler\EventPseudoDesc.cs" Link="Compiler\EventPseudoDesc.cs" />
<Compile Include="..\..\Common\Compiler\PseudoDescExtensions.cs" Link="Compiler\PseudoDescExtensions.cs" />
<Compile Include="..\..\Common\Compiler\SingleMethodRootProvider.cs" Link="Compiler\SingleMethodRootProvider.cs" />
<Compile Include="..\..\Common\Compiler\TypeExtensions.cs" Link="Compiler\TypeExtensions.cs" />
<Compile Include="..\..\Common\Compiler\TypePreserve.cs" Link="Compiler\TypePreserve.cs" />
<Compile Include="..\..\Common\Compiler\VectorFieldLayoutAlgorithm.cs" Link="Compiler\VectorFieldLayoutAlgorithm.cs" />

<Compile Include="Compiler\AnalysisBasedInteropStubManager.cs" />
<Compile Include="Compiler\AnalysisBasedMetadataManager.cs" />
<Compile Include="Compiler\BlockedInternalsBlockingPolicy.cs" />
<Compile Include="Compiler\BodySubstitution.cs" />
<Compile Include="Compiler\BodySubstitutionParser.cs" />
<Compile Include="Compiler\PseudoDescExtensions.cs" />
<Compile Include="Compiler\CompilationBuilder.Aot.cs" />
<Compile Include="Compiler\CompilationModuleGroup.Aot.cs" />
<Compile Include="Compiler\CompilerTypeSystemContext.Aot.cs" />
Expand All @@ -342,8 +349,6 @@
<Compile Include="Compiler\Dataflow\CompilerGeneratedState.cs" />
<Compile Include="Compiler\Dataflow\DiagnosticContext.cs" />
<Compile Include="Compiler\Dataflow\DiagnosticUtilities.cs" />
<Compile Include="Compiler\Dataflow\DynamicallyAccessedMembersBinder.cs" />
<Compile Include="Compiler\Dataflow\EcmaExtensions.cs" />
<Compile Include="Compiler\Dataflow\FieldReferenceValue.cs" />
<Compile Include="Compiler\Dataflow\FieldValue.cs" />
<Compile Include="Compiler\Dataflow\FlowAnnotations.cs" />
Expand Down Expand Up @@ -410,9 +415,7 @@
<Compile Include="Compiler\EmptyInteropStubManager.cs" />
<Compile Include="Compiler\DependencyAnalysis\ImportedNodeProvider.cs" />
<Compile Include="Compiler\ExpectedIsaFeaturesRootProvider.cs" />
<Compile Include="Compiler\EventPseudoDesc.cs" />
<Compile Include="Compiler\ExternSymbolMappedField.cs" />
<Compile Include="Compiler\FeatureSettings.cs" />
<Compile Include="Compiler\FeatureSwitchManager.cs" />
<Compile Include="Compiler\GeneratingMetadataManager.cs" />
<Compile Include="Compiler\GenericRootProvider.cs" />
Expand Down Expand Up @@ -570,7 +573,6 @@
<Compile Include="Compiler\NodeMangler.cs" />
<Compile Include="Compiler\ObjectDumper.cs" />
<Compile Include="Compiler\ExportsFileWriter.cs" />
<Compile Include="Compiler\ProcessLinkerXmlBase.cs" />
<Compile Include="Compiler\ProcessXmlBase.cs" />
<Compile Include="Compiler\RootingHelpers.cs" />
<Compile Include="Compiler\RootingServiceProvider.cs" />
Expand All @@ -579,10 +581,8 @@
<Compile Include="Compiler\SingleMethodCompilationModuleGroup.cs" />
<Compile Include="Compiler\ILAssemblyGeneratingMethodDebugInfoProvider.cs" />
<Compile Include="Compiler\StackTraceEmissionPolicy.cs" />
<Compile Include="Compiler\PropertyPseudoDesc.cs" />
<Compile Include="Compiler\PreinitializationManager.cs" />
<Compile Include="Compiler\TypePreinit.cs" />
<Compile Include="Compiler\TypePreserve.cs" />
<Compile Include="Compiler\UsageBasedInteropStubManager.cs" />
<Compile Include="Compiler\UsageBasedMetadataManager.cs" />
<Compile Include="Compiler\UserDefinedTypeDescriptor.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Diagnostics;
using System.Reflection;
using Internal.TypeSystem;
using Internal.TypeSystem.Ecma;

namespace ILCompiler
{
public enum EffectiveVisibility
{
Private,
Public,
Family,
Assembly,
FamilyAndAssembly,
FamilyOrAssembly,
}

public static class EffectiveVisibilityExtensions
{
private static EffectiveVisibility ToEffectiveVisibility(this TypeAttributes typeAttributes)
{
return (typeAttributes & TypeAttributes.VisibilityMask) switch
{
TypeAttributes.Public or TypeAttributes.NestedPublic => EffectiveVisibility.Public,
TypeAttributes.NotPublic => EffectiveVisibility.Assembly,
TypeAttributes.NestedPrivate => EffectiveVisibility.Private,
TypeAttributes.NestedAssembly => EffectiveVisibility.Assembly,
TypeAttributes.NestedFamily => EffectiveVisibility.Family,
TypeAttributes.NestedFamANDAssem => EffectiveVisibility.FamilyAndAssembly,
TypeAttributes.NestedFamORAssem => EffectiveVisibility.FamilyOrAssembly,
_ => throw new UnreachableException()
};
}
private static EffectiveVisibility ToEffectiveVisibility(this MethodAttributes typeAttributes)
{
return (typeAttributes & MethodAttributes.MemberAccessMask) switch
{
MethodAttributes.Public => EffectiveVisibility.Public,
MethodAttributes.Private => EffectiveVisibility.Private,
MethodAttributes.Assembly => EffectiveVisibility.Assembly,
MethodAttributes.Family => EffectiveVisibility.Family,
MethodAttributes.FamANDAssem => EffectiveVisibility.FamilyAndAssembly,
MethodAttributes.FamORAssem => EffectiveVisibility.FamilyOrAssembly,
_ => throw new UnreachableException()
};
}

private static EffectiveVisibility ConstrainToVisibility(this EffectiveVisibility visibility, EffectiveVisibility enclosingVisibility)
{
return (visibility, enclosingVisibility) switch
{
(_, _) when visibility == enclosingVisibility => visibility,
(_, EffectiveVisibility.Private) => EffectiveVisibility.Private,
(EffectiveVisibility.Private, _) => EffectiveVisibility.Private,
(EffectiveVisibility.Public, _) => enclosingVisibility,
(_, EffectiveVisibility.Public) => visibility,
(EffectiveVisibility.FamilyOrAssembly, _) => enclosingVisibility,
(_, EffectiveVisibility.FamilyOrAssembly) => visibility,
(EffectiveVisibility.Family, EffectiveVisibility.Assembly) => EffectiveVisibility.FamilyAndAssembly,
(EffectiveVisibility.Family, EffectiveVisibility.FamilyAndAssembly) => EffectiveVisibility.FamilyAndAssembly,
(EffectiveVisibility.Assembly, EffectiveVisibility.Family) => EffectiveVisibility.FamilyAndAssembly,
(EffectiveVisibility.Assembly, EffectiveVisibility.FamilyAndAssembly) => EffectiveVisibility.FamilyAndAssembly,
(EffectiveVisibility.FamilyAndAssembly, EffectiveVisibility.Family) => EffectiveVisibility.FamilyAndAssembly,
(EffectiveVisibility.FamilyAndAssembly, EffectiveVisibility.Assembly) => EffectiveVisibility.FamilyAndAssembly,
_ => throw new UnreachableException(),
};
}

public static bool IsExposedOutsideOfThisAssembly(this EffectiveVisibility visibility, bool anyInternalsVisibleTo)
{
return visibility is EffectiveVisibility.Public or EffectiveVisibility.Family
|| (anyInternalsVisibleTo && visibility is EffectiveVisibility.Assembly or EffectiveVisibility.FamilyOrAssembly);
}

public static EffectiveVisibility GetEffectiveVisibility(this EcmaMethod method)
{
EffectiveVisibility visibility = method.Attributes.ToEffectiveVisibility();

for (EcmaType type = (EcmaType)method.OwningType; type is not null; type = (EcmaType)type.ContainingType)
{
visibility = visibility.ConstrainToVisibility(type.Attributes.ToEffectiveVisibility());
}
return visibility;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,14 @@ public void AddCompilationRoots(IRootingServiceProvider rootProvider)
continue;
}

RootMethods(typeWithMethods, "Library module method", rootProvider);
RootMethods(typeWithMethods, "Library module method", rootProvider, ((EcmaAssembly)_module.Assembly).HasAssemblyCustomAttribute("System.Runtime.CompilerServices", "InternalsVisibleToAttribute"));
}
}
}

private void RootMethods(TypeDesc type, string reason, IRootingServiceProvider rootProvider)
private void RootMethods(MetadataType type, string reason, IRootingServiceProvider rootProvider, bool anyInternalsVisibleTo)
{
MethodImplRecord[] methodImplRecords = ((EcmaType)type.GetTypeDefinition()).AllMethodImplsForType;
foreach (MethodDesc method in type.GetAllMethods())
{
// Skip methods with no IL
Expand All @@ -102,10 +103,32 @@ private void RootMethods(TypeDesc type, string reason, IRootingServiceProvider r
if (method.IsInternalCall)
continue;

// We will not root P/Invokes. We'll only compile them for ReadyToRun if
// they have a use where they are not inlined.
if (method.IsPInvoke)
continue;
// If the method is not visible outside the assembly, then do not root the method.
// It will be rooted by any callers that require it and do not inline it.
if (!method.IsStaticConstructor
&& method.GetTypicalMethodDefinition() is EcmaMethod ecma
&& !ecma.GetEffectiveVisibility().IsExposedOutsideOfThisAssembly(anyInternalsVisibleTo))
{
// If a method itself is not visible outside the assembly, but it implements a method that is,
// we want to root it as it could be called from outside the assembly.
bool implementsOrOverridesVisibleMethod = false;
foreach (var record in methodImplRecords)
{
if (record.Body == ecma)
{
implementsOrOverridesVisibleMethod = record.Decl.GetTypicalMethodDefinition() is EcmaMethod decl
&& decl.GetEffectiveVisibility().IsExposedOutsideOfThisAssembly(anyInternalsVisibleTo);
if (implementsOrOverridesVisibleMethod)
{
break;
}
}
}
if (!implementsOrOverridesVisibleMethod)
{
continue;
}
}

MethodDesc methodToRoot = method;
if (method.HasInstantiation)
Expand Down Expand Up @@ -197,7 +220,7 @@ private static Instantiation GetInstantiationThatMeetsConstraints(Instantiation
return new Instantiation(args);
}

private static InstantiatedType InstantiateIfPossible(MetadataType type)
public static InstantiatedType InstantiateIfPossible(MetadataType type)
{
Instantiation inst = GetInstantiationThatMeetsConstraints(type.Instantiation);
if (inst.IsNull)
Expand All @@ -208,7 +231,7 @@ private static InstantiatedType InstantiateIfPossible(MetadataType type)
return type.MakeInstantiatedType(inst);
}

private static MethodDesc InstantiateIfPossible(MethodDesc method)
public static MethodDesc InstantiateIfPossible(MethodDesc method)
{
Instantiation inst = GetInstantiationThatMeetsConstraints(method.Instantiation);
if (inst.IsNull)
Expand Down
Loading