diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/DynamicallyAccessedMembersBinder.cs b/src/coreclr/tools/Common/Compiler/Dataflow/DynamicallyAccessedMembersBinder.cs
similarity index 100%
rename from src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/DynamicallyAccessedMembersBinder.cs
rename to src/coreclr/tools/Common/Compiler/Dataflow/DynamicallyAccessedMembersBinder.cs
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/EcmaExtensions.cs b/src/coreclr/tools/Common/Compiler/Dataflow/EcmaExtensions.cs
similarity index 100%
rename from src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/EcmaExtensions.cs
rename to src/coreclr/tools/Common/Compiler/Dataflow/EcmaExtensions.cs
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/GenericParameterProxy.cs b/src/coreclr/tools/Common/Compiler/Dataflow/GenericParameterProxy.cs
similarity index 100%
rename from src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/GenericParameterProxy.cs
rename to src/coreclr/tools/Common/Compiler/Dataflow/GenericParameterProxy.cs
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/MethodProxy.cs b/src/coreclr/tools/Common/Compiler/Dataflow/MethodProxy.cs
similarity index 100%
rename from src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/MethodProxy.cs
rename to src/coreclr/tools/Common/Compiler/Dataflow/MethodProxy.cs
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ParameterProxy.cs b/src/coreclr/tools/Common/Compiler/Dataflow/ParameterProxy.cs
similarity index 100%
rename from src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ParameterProxy.cs
rename to src/coreclr/tools/Common/Compiler/Dataflow/ParameterProxy.cs
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TypeExtensions.cs b/src/coreclr/tools/Common/Compiler/Dataflow/TypeExtensions.cs
similarity index 100%
rename from src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TypeExtensions.cs
rename to src/coreclr/tools/Common/Compiler/Dataflow/TypeExtensions.cs
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TypeProxy.cs b/src/coreclr/tools/Common/Compiler/Dataflow/TypeProxy.cs
similarity index 100%
rename from src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/TypeProxy.cs
rename to src/coreclr/tools/Common/Compiler/Dataflow/TypeProxy.cs
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/EventPseudoDesc.cs b/src/coreclr/tools/Common/Compiler/EventPseudoDesc.cs
similarity index 100%
rename from src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/EventPseudoDesc.cs
rename to src/coreclr/tools/Common/Compiler/EventPseudoDesc.cs
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/FeatureSettings.cs b/src/coreclr/tools/Common/Compiler/FeatureSettings.cs
similarity index 100%
rename from src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/FeatureSettings.cs
rename to src/coreclr/tools/Common/Compiler/FeatureSettings.cs
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ProcessLinkerXmlBase.cs b/src/coreclr/tools/Common/Compiler/ProcessLinkerXmlBase.cs
similarity index 100%
rename from src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ProcessLinkerXmlBase.cs
rename to src/coreclr/tools/Common/Compiler/ProcessLinkerXmlBase.cs
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/PropertyPseudoDesc.cs b/src/coreclr/tools/Common/Compiler/PropertyPseudoDesc.cs
similarity index 100%
rename from src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/PropertyPseudoDesc.cs
rename to src/coreclr/tools/Common/Compiler/PropertyPseudoDesc.cs
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/PseudoDescExtensions.cs b/src/coreclr/tools/Common/Compiler/PseudoDescExtensions.cs
similarity index 100%
rename from src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/PseudoDescExtensions.cs
rename to src/coreclr/tools/Common/Compiler/PseudoDescExtensions.cs
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/BodySubstitutionParser.cs b/src/coreclr/tools/Common/Compiler/ReferenceSource/BodySubstitutionParser.cs
similarity index 100%
rename from src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/BodySubstitutionParser.cs
rename to src/coreclr/tools/Common/Compiler/ReferenceSource/BodySubstitutionParser.cs
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/DescriptorMarker.cs b/src/coreclr/tools/Common/Compiler/ReferenceSource/DescriptorMarker.cs
similarity index 100%
rename from src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/DescriptorMarker.cs
rename to src/coreclr/tools/Common/Compiler/ReferenceSource/DescriptorMarker.cs
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/FeatureSettings.cs b/src/coreclr/tools/Common/Compiler/ReferenceSource/FeatureSettings.cs
similarity index 100%
rename from src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/FeatureSettings.cs
rename to src/coreclr/tools/Common/Compiler/ReferenceSource/FeatureSettings.cs
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/GenericParameterProxy.cs b/src/coreclr/tools/Common/Compiler/ReferenceSource/GenericParameterProxy.cs
similarity index 100%
rename from src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/GenericParameterProxy.cs
rename to src/coreclr/tools/Common/Compiler/ReferenceSource/GenericParameterProxy.cs
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/LinkAttributesParser.cs b/src/coreclr/tools/Common/Compiler/ReferenceSource/LinkAttributesParser.cs
similarity index 100%
rename from src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/LinkAttributesParser.cs
rename to src/coreclr/tools/Common/Compiler/ReferenceSource/LinkAttributesParser.cs
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/MethodProxy.cs b/src/coreclr/tools/Common/Compiler/ReferenceSource/MethodProxy.cs
similarity index 100%
rename from src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/MethodProxy.cs
rename to src/coreclr/tools/Common/Compiler/ReferenceSource/MethodProxy.cs
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/ParameterProxy.cs b/src/coreclr/tools/Common/Compiler/ReferenceSource/ParameterProxy.cs
similarity index 100%
rename from src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/ParameterProxy.cs
rename to src/coreclr/tools/Common/Compiler/ReferenceSource/ParameterProxy.cs
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/ProcessLinkerXmlBase.cs b/src/coreclr/tools/Common/Compiler/ReferenceSource/ProcessLinkerXmlBase.cs
similarity index 100%
rename from src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/ProcessLinkerXmlBase.cs
rename to src/coreclr/tools/Common/Compiler/ReferenceSource/ProcessLinkerXmlBase.cs
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/README.md b/src/coreclr/tools/Common/Compiler/ReferenceSource/README.md
similarity index 100%
rename from src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/README.md
rename to src/coreclr/tools/Common/Compiler/ReferenceSource/README.md
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/TypePreserve.cs b/src/coreclr/tools/Common/Compiler/ReferenceSource/TypePreserve.cs
similarity index 100%
rename from src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ReferenceSource/TypePreserve.cs
rename to src/coreclr/tools/Common/Compiler/ReferenceSource/TypePreserve.cs
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/TypeProxy.cs b/src/coreclr/tools/Common/Compiler/ReferenceSource/TypeProxy.cs
similarity index 100%
rename from src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReferenceSource/TypeProxy.cs
rename to src/coreclr/tools/Common/Compiler/ReferenceSource/TypeProxy.cs
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreserve.cs b/src/coreclr/tools/Common/Compiler/TypePreserve.cs
similarity index 100%
rename from src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreserve.cs
rename to src/coreclr/tools/Common/Compiler/TypePreserve.cs
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj b/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj
index 3069685c02fe6f..66fd2256b6d6cb 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj
@@ -265,6 +265,13 @@
+
+
+
+
+
+
+
@@ -303,6 +310,7 @@
+
@@ -310,8 +318,13 @@
+
+
+
+
+
@@ -319,7 +332,6 @@
-
@@ -341,13 +353,10 @@
-
-
-
@@ -356,10 +365,8 @@
-
-
@@ -369,8 +376,6 @@
-
-
@@ -409,9 +414,7 @@
-
-
@@ -569,7 +572,6 @@
-
@@ -578,10 +580,8 @@
-
-
diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/EffectiveVisibility.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/EffectiveVisibility.cs
new file mode 100644
index 00000000000000..92e2b234c0f13a
--- /dev/null
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/EffectiveVisibility.cs
@@ -0,0 +1,95 @@
+// 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
+ {
+ // PrivateScope == Compiler-Controlled in the ECMA spec. A member with this accessibility
+ // is only accessible through a MemberDef, not a MemberRef.
+ // As a result, it's only accessible within the current assembly, which is effectively the same rules as
+ // Family for our case.
+ MethodAttributes.PrivateScope => EffectiveVisibility.Assembly,
+ 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;
+ }
+ }
+}
diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunLibraryRootProvider.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunLibraryRootProvider.cs
index daacba4ef35f6d..838cf6e9df6c00 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunLibraryRootProvider.cs
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunLibraryRootProvider.cs
@@ -6,92 +6,39 @@
using Internal.TypeSystem.Ecma;
using Internal.TypeSystem;
using Internal.JitInterface;
+using System.Reflection.Metadata;
namespace ILCompiler
{
///
- /// Provides compilation group for a library that compiles everything in the input IL module.
+ /// Roots all methods in the input IL module.
///
- public class ReadyToRunRootProvider : ICompilationRootProvider
+ public class ReadyToRunLibraryRootProvider : ICompilationRootProvider
{
private EcmaModule _module;
- private IEnumerable _profileData;
- private readonly bool _profileDrivenPartialNGen;
- public ReadyToRunRootProvider(EcmaModule module, ProfileDataManager profileDataManager, bool profileDrivenPartialNGen)
+ public ReadyToRunLibraryRootProvider(EcmaModule module)
{
_module = module;
- _profileData = profileDataManager.GetMethodsForModuleDesc(module);
- _profileDrivenPartialNGen = profileDrivenPartialNGen;
}
public void AddCompilationRoots(IRootingServiceProvider rootProvider)
{
- foreach (var method in _profileData)
+ foreach (MetadataType type in _module.GetAllTypes())
{
- try
+ MetadataType typeWithMethods = type;
+ if (type.HasInstantiation)
{
- // Validate that this method is fully instantiated
- if (method.OwningType.IsGenericDefinition || method.OwningType.ContainsSignatureVariables())
- {
- continue;
- }
-
- if (method.IsGenericMethodDefinition)
- {
- continue;
- }
-
- bool containsSignatureVariables = false;
- foreach (TypeDesc t in method.Instantiation)
- {
- if (t.IsGenericDefinition)
- {
- containsSignatureVariables = true;
- break;
- }
-
- if (t.ContainsSignatureVariables())
- {
- containsSignatureVariables = true;
- break;
- }
- }
- if (containsSignatureVariables)
+ typeWithMethods = InstantiateIfPossible(type);
+ if (typeWithMethods == null)
continue;
-
- if (!CorInfoImpl.ShouldSkipCompilation(method))
- {
- CheckCanGenerateMethod(method);
- rootProvider.AddCompilationRoot(method, rootMinimalDependencies: true, reason: "Profile triggered method");
- }
- }
- catch (TypeSystemException)
- {
- // Individual methods can fail to load types referenced in their signatures.
- // Skip them in library mode since they're not going to be callable.
- continue;
}
- }
- if (!_profileDrivenPartialNGen)
- {
- foreach (MetadataType type in _module.GetAllTypes())
- {
- MetadataType typeWithMethods = type;
- if (type.HasInstantiation)
- {
- typeWithMethods = InstantiateIfPossible(type);
- if (typeWithMethods == null)
- continue;
- }
-
- RootMethods(typeWithMethods, "Library module method", rootProvider);
- }
+ RootMethods(typeWithMethods, "Library module method", rootProvider);
}
}
- private void RootMethods(TypeDesc type, string reason, IRootingServiceProvider rootProvider)
+ private void RootMethods(MetadataType type, string reason, IRootingServiceProvider rootProvider)
{
foreach (MethodDesc method in type.GetAllMethods())
{
@@ -192,7 +139,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)
@@ -203,7 +150,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)
diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunProfilingRootProvider.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunProfilingRootProvider.cs
new file mode 100644
index 00000000000000..bde2aa94d93ad3
--- /dev/null
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunProfilingRootProvider.cs
@@ -0,0 +1,79 @@
+// 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.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Internal.JitInterface;
+using Internal.TypeSystem.Ecma;
+using Internal.TypeSystem;
+
+namespace ILCompiler
+{
+ ///
+ /// Roots all methods in the profile data in the module.
+ ///
+ public class ReadyToRunProfilingRootProvider : ICompilationRootProvider
+ {
+ private EcmaModule _module;
+ private IEnumerable _profileData;
+
+ public ReadyToRunProfilingRootProvider(EcmaModule module, ProfileDataManager profileDataManager)
+ {
+ _module = module;
+ _profileData = profileDataManager.GetMethodsForModuleDesc(module);
+ }
+
+ public void AddCompilationRoots(IRootingServiceProvider rootProvider)
+ {
+ foreach (var method in _profileData)
+ {
+ try
+ {
+ // Validate that this method is fully instantiated
+ if (method.OwningType.IsGenericDefinition || method.OwningType.ContainsSignatureVariables())
+ {
+ continue;
+ }
+
+ if (method.IsGenericMethodDefinition)
+ {
+ continue;
+ }
+
+ bool containsSignatureVariables = false;
+ foreach (TypeDesc t in method.Instantiation)
+ {
+ if (t.IsGenericDefinition)
+ {
+ containsSignatureVariables = true;
+ break;
+ }
+
+ if (t.ContainsSignatureVariables())
+ {
+ containsSignatureVariables = true;
+ break;
+ }
+ }
+ if (containsSignatureVariables)
+ continue;
+
+ if (!CorInfoImpl.ShouldSkipCompilation(method))
+ {
+ ReadyToRunLibraryRootProvider.CheckCanGenerateMethod(method);
+ rootProvider.AddCompilationRoot(method, rootMinimalDependencies: true, reason: "Profile triggered method");
+ }
+ }
+ catch (TypeSystemException)
+ {
+ // Individual methods can fail to load types referenced in their signatures.
+ // Skip them in library mode since they're not going to be callable.
+ continue;
+ }
+ }
+ }
+ }
+}
diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunVisibilityRootProvider.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunVisibilityRootProvider.cs
new file mode 100644
index 00000000000000..4766937ce694b7
--- /dev/null
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunVisibilityRootProvider.cs
@@ -0,0 +1,162 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Collections.Generic;
+
+using Internal.TypeSystem.Ecma;
+using Internal.TypeSystem;
+using Internal.JitInterface;
+using System.Reflection.Metadata;
+
+namespace ILCompiler
+{
+ ///
+ /// Roots all possibly-visible methods in the input IL module.
+ ///
+ public class ReadyToRunVisibilityRootProvider : ICompilationRootProvider
+ {
+ private EcmaModule _module;
+
+ public ReadyToRunVisibilityRootProvider(EcmaModule module)
+ {
+ _module = module;
+ }
+
+ public void AddCompilationRoots(IRootingServiceProvider rootProvider)
+ {
+ foreach (MetadataType type in _module.GetAllTypes())
+ {
+ MetadataType typeWithMethods = type;
+ if (type.HasInstantiation)
+ {
+ typeWithMethods = ReadyToRunLibraryRootProvider.InstantiateIfPossible(type);
+ if (typeWithMethods == null)
+ continue;
+ }
+
+ RootMethods(typeWithMethods, "Library module method", rootProvider, ((EcmaAssembly)_module.Assembly).HasAssemblyCustomAttribute("System.Runtime.CompilerServices", "InternalsVisibleToAttribute"));
+ }
+
+ if (_module.EntryPoint is not null)
+ {
+ rootProvider.AddCompilationRoot(_module.EntryPoint, rootMinimalDependencies: false, $"{_module.Assembly.GetName()} Main Method");
+ }
+ }
+
+ private void RootMethods(MetadataType type, string reason, IRootingServiceProvider rootProvider, bool anyInternalsVisibleTo)
+ {
+ MethodImplRecord[] methodImplRecords = GetAllMethodImplRecordsForType((EcmaType)type.GetTypeDefinition());
+ foreach (MethodDesc method in type.GetAllMethods())
+ {
+ // Skip methods with no IL
+ if (method.IsAbstract)
+ continue;
+
+ if (method.IsInternalCall)
+ 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.
+ // Since instance method overriding does not always require a MethodImpl record (it can be omitted when both the name and signature match)
+ // we will also root any methods that are virtual and do not have any MethodImpl records as it is difficult to determine all methods a method
+ // overrides or implements and we don't need to be perfect here.
+ bool anyMethodImplRecordsForMethod = false;
+ bool implementsOrOverridesVisibleMethod = false;
+ foreach (var record in methodImplRecords)
+ {
+ if (record.Body == ecma)
+ {
+ anyMethodImplRecordsForMethod = true;
+ implementsOrOverridesVisibleMethod = record.Decl.GetTypicalMethodDefinition() is EcmaMethod decl
+ && decl.GetEffectiveVisibility().IsExposedOutsideOfThisAssembly(anyInternalsVisibleTo);
+ if (implementsOrOverridesVisibleMethod)
+ {
+ break;
+ }
+ }
+ }
+ if (anyMethodImplRecordsForMethod && !implementsOrOverridesVisibleMethod)
+ {
+ continue;
+ }
+ if (!anyMethodImplRecordsForMethod && !method.IsVirtual)
+ {
+ continue;
+ }
+ }
+
+ MethodDesc methodToRoot = method;
+ if (method.HasInstantiation)
+ {
+ methodToRoot = ReadyToRunLibraryRootProvider.InstantiateIfPossible(method);
+
+ if (methodToRoot == null)
+ continue;
+ }
+
+ try
+ {
+ if (!CorInfoImpl.ShouldSkipCompilation(method))
+ {
+ ReadyToRunLibraryRootProvider.CheckCanGenerateMethod(methodToRoot);
+ rootProvider.AddCompilationRoot(methodToRoot, rootMinimalDependencies: false, reason: reason);
+ }
+ }
+ catch (TypeSystemException)
+ {
+ // Individual methods can fail to load types referenced in their signatures.
+ // Skip them in library mode since they're not going to be callable.
+ continue;
+ }
+ }
+ }
+
+ private MethodImplRecord[] GetAllMethodImplRecordsForType(EcmaType type)
+ {
+ ArrayBuilder records = default;
+ MetadataReader metadataReader = type.MetadataReader;
+ TypeDefinition definition = metadataReader.GetTypeDefinition(type.Handle);
+
+ foreach (var methodImplHandle in definition.GetMethodImplementations())
+ {
+ MethodImplementation methodImpl = metadataReader.GetMethodImplementation(methodImplHandle);
+
+ records.Add(new MethodImplRecord(
+ _module.GetMethod(methodImpl.MethodDeclaration),
+ _module.GetMethod(methodImpl.MethodBody)
+ ));
+ }
+ return records.ToArray();
+ }
+
+ ///
+ /// Determine if the visibility-based root provider should be used for the given module.
+ ///
+ /// The module
+ /// true if the module should use the visibility-based root provider; otherwise, false.
+ ///
+ /// We will use a visibility-based root provider for modules that are marked as trimmable.
+ /// Trimmable assemblies are less likely to use private reflection, which the visibility-based root provider
+ /// doesn't track well.
+ ///
+ public static bool UseVisibilityBasedRootProvider(EcmaModule module)
+ {
+ EcmaAssembly assembly = (EcmaAssembly)module.Assembly;
+
+ foreach (var assemblyMetadata in assembly.GetDecodedCustomAttributes("System.Reflection", "AssemblyMetadataAttribute"))
+ {
+ if ((string)assemblyMetadata.FixedArguments[0].Value == "IsTrimmable")
+ {
+ return bool.TryParse((string)assemblyMetadata.FixedArguments[1].Value, out bool isTrimmable) && isTrimmable;
+ }
+ }
+ return false;
+ }
+ }
+}
diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunXmlRootProvider.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunXmlRootProvider.cs
new file mode 100644
index 00000000000000..13ba5a4aeaa029
--- /dev/null
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunXmlRootProvider.cs
@@ -0,0 +1,213 @@
+// 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.Collections.Generic;
+using System.Collections.Immutable;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Reflection.Metadata;
+using System.Reflection.PortableExecutable;
+using System.Text;
+using System.Threading.Tasks;
+using System.Xml.XPath;
+using Internal.JitInterface;
+using Internal.TypeSystem;
+using Internal.TypeSystem.Ecma;
+
+namespace ILCompiler
+{
+ public class ReadyToRunXmlRootProvider : ICompilationRootProvider
+ {
+ private readonly TypeSystemContext _context;
+ private readonly Stream _documentStream;
+ private readonly ManifestResource _resource;
+ private readonly ModuleDesc _owningModule;
+ private readonly string _xmlDocumentLocation;
+
+ public ReadyToRunXmlRootProvider(Stream documentStream, ManifestResource resource, ModuleDesc owningModule, string xmlDocumentLocation)
+ {
+ _context = owningModule.Context;
+ _documentStream = documentStream;
+ _resource = resource;
+ _owningModule = owningModule;
+ _xmlDocumentLocation = xmlDocumentLocation;
+ }
+
+ public void AddCompilationRoots(IRootingServiceProvider rootProvider)
+ {
+ CompilationRootProvider root = new CompilationRootProvider(rootProvider, _context, _documentStream, _resource, _owningModule, _xmlDocumentLocation);
+ root.ProcessXml();
+ }
+
+ public static bool TryCreateRootProviderFromEmbeddedDescriptorFile(EcmaModule module, out ReadyToRunXmlRootProvider provider)
+ {
+ PEMemoryBlock resourceDirectory = module.PEReader.GetSectionData(module.PEReader.PEHeaders.CorHeader.ResourcesDirectory.RelativeVirtualAddress);
+
+ foreach (var resourceHandle in module.MetadataReader.ManifestResources)
+ {
+ ManifestResource resource = module.MetadataReader.GetManifestResource(resourceHandle);
+
+ // Don't try to process linked resources or resources in other assemblies
+ if (!resource.Implementation.IsNil)
+ {
+ continue;
+ }
+
+ string resourceName = module.MetadataReader.GetString(resource.Name);
+ if (resourceName == "ILLink.Descriptors.xml")
+ {
+ BlobReader reader = resourceDirectory.GetReader((int)resource.Offset, resourceDirectory.Length - (int)resource.Offset);
+ int length = (int)reader.ReadUInt32();
+
+ UnmanagedMemoryStream ms;
+ unsafe
+ {
+ ms = new UnmanagedMemoryStream(reader.CurrentPointer, length);
+ }
+
+ provider = new ReadyToRunXmlRootProvider(ms, resource, module, "resource " + resourceName + " in " + module.ToString());
+ return true;
+ }
+ }
+ provider = null;
+ return false;
+ }
+
+ private class CompilationRootProvider : ProcessLinkerXmlBase
+ {
+ private const string NamespaceElementName = "namespace";
+ private const string _preserve = "preserve";
+ private readonly IRootingServiceProvider _rootingServiceProvider;
+
+ public CompilationRootProvider(IRootingServiceProvider provider, TypeSystemContext context, Stream documentStream, ManifestResource resource, ModuleDesc owningModule, string xmlDocumentLocation)
+ : base(context, documentStream, resource, owningModule, xmlDocumentLocation, ImmutableDictionary.Empty)
+ {
+ _rootingServiceProvider = provider;
+ }
+
+ public void ProcessXml() => ProcessXml(false);
+
+ protected override void ProcessAssembly(ModuleDesc assembly, XPathNavigator nav, bool warnOnUnresolvedTypes)
+ {
+ if (GetTypePreserve(nav) == TypePreserve.All)
+ {
+ foreach (var type in assembly.GetAllTypes())
+ {
+ PreserveMethodsOnType(type);
+ }
+ }
+ else
+ {
+ ProcessTypes(assembly, nav, warnOnUnresolvedTypes);
+ ProcessNamespaces(assembly, nav);
+ }
+ }
+
+ private void PreserveMethodsOnType(TypeDesc type)
+ {
+ MetadataType typeWithMethods = (MetadataType)type;
+ if (type.HasInstantiation)
+ {
+ typeWithMethods = ReadyToRunLibraryRootProvider.InstantiateIfPossible(typeWithMethods);
+ if (typeWithMethods == null)
+ return;
+ }
+
+ foreach (MethodDesc method in typeWithMethods.GetAllMethods())
+ {
+ RootMethod(method);
+ }
+ }
+
+ private void RootMethod(MethodDesc method)
+ {
+ // Skip methods with no IL
+ if (method.IsAbstract)
+ return;
+
+ if (method.IsInternalCall)
+ return;
+
+ MethodDesc methodToRoot = method;
+ if (method.HasInstantiation)
+ {
+ methodToRoot = ReadyToRunLibraryRootProvider.InstantiateIfPossible(method);
+
+ if (methodToRoot == null)
+ return;
+ }
+
+ try
+ {
+ if (!CorInfoImpl.ShouldSkipCompilation(method))
+ {
+ ReadyToRunLibraryRootProvider.CheckCanGenerateMethod(methodToRoot);
+ _rootingServiceProvider.AddCompilationRoot(methodToRoot, rootMinimalDependencies: false, reason: "Linker XML descriptor");
+ }
+ }
+ catch (TypeSystemException)
+ {
+ // Individual methods can fail to load types referenced in their signatures.
+ // Skip them in library mode since they're not going to be callable.
+ return;
+ }
+ }
+
+ private void ProcessNamespaces(ModuleDesc assembly, XPathNavigator nav)
+ {
+ foreach (XPathNavigator namespaceNav in nav.SelectChildren(NamespaceElementName, XmlNamespace))
+ {
+ if (!ShouldProcessElement(namespaceNav))
+ continue;
+
+ string fullname = GetFullName(namespaceNav);
+ foreach (DefType type in assembly.GetAllTypes())
+ {
+ if (type.Namespace != fullname)
+ continue;
+
+ ProcessType(type, nav);
+ }
+ }
+ }
+
+ protected override void ProcessType(TypeDesc type, XPathNavigator nav)
+ {
+ TypePreserve preserve = GetTypePreserve(nav);
+ if (preserve == TypePreserve.All || preserve == TypePreserve.Methods)
+ {
+ PreserveMethodsOnType(type);
+ }
+ else
+ {
+ ProcessTypeChildren(type, nav);
+ }
+ }
+
+ protected override void ProcessMethod(TypeDesc type, MethodDesc method, XPathNavigator nav, object customData)
+ {
+ MetadataType typeWithMethods = (MetadataType)type;
+ if (type.HasInstantiation)
+ {
+ InstantiatedType instantiated = ReadyToRunLibraryRootProvider.InstantiateIfPossible(typeWithMethods);
+ method = method.Context.GetMethodForInstantiatedType(method, instantiated);
+ }
+
+ RootMethod(method);
+ }
+
+ private static TypePreserve GetTypePreserve(XPathNavigator nav)
+ {
+ string attribute = GetAttribute(nav, _preserve);
+ if (string.IsNullOrEmpty(attribute))
+ return nav.HasChildren ? TypePreserve.Nothing : TypePreserve.All;
+
+ if (Enum.TryParse(attribute, true, out TypePreserve result))
+ return result;
+ return TypePreserve.Nothing;
+ }
+ }
+ }
+}
diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj
index ea9930f54e39f7..9d30f81815b9d8 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj
@@ -16,12 +16,18 @@
false
Debug;Release;Checked
false
+ $(NoWarn);CS8524
+
+
+ all
+ contentfiles
+
@@ -55,6 +61,13 @@
+
+
+
+
+
+
+
@@ -94,6 +107,7 @@
+
@@ -101,8 +115,13 @@
+
+
+
+
+
@@ -110,6 +129,16 @@
+
+
+
+
+
+
+
+
+
+
@@ -117,6 +146,8 @@
+
+
@@ -198,6 +229,7 @@
+
@@ -220,6 +252,7 @@
+
diff --git a/src/coreclr/tools/aot/crossgen2/Program.cs b/src/coreclr/tools/aot/crossgen2/Program.cs
index c09d42c7afd1ac..5c568c6d8b7cb4 100644
--- a/src/coreclr/tools/aot/crossgen2/Program.cs
+++ b/src/coreclr/tools/aot/crossgen2/Program.cs
@@ -513,10 +513,24 @@ private void RunSingleCompilation(Dictionary inFilePaths, Instru
// For normal compilations add compilation roots.
foreach (var module in rootingModules)
{
- compilationRoots.Add(new ReadyToRunRootProvider(
- module,
- profileDataManager,
- profileDrivenPartialNGen: partial));
+ compilationRoots.Add(new ReadyToRunProfilingRootProvider(module, profileDataManager));
+ // If we're doing partial precompilation, only use profile data.
+ if (!partial)
+ {
+ if (ReadyToRunVisibilityRootProvider.UseVisibilityBasedRootProvider(module))
+ {
+ compilationRoots.Add(new ReadyToRunVisibilityRootProvider(module));
+
+ if (ReadyToRunXmlRootProvider.TryCreateRootProviderFromEmbeddedDescriptorFile(module, out ReadyToRunXmlRootProvider xmlProvider))
+ {
+ compilationRoots.Add(xmlProvider);
+ }
+ }
+ else
+ {
+ compilationRoots.Add(new ReadyToRunLibraryRootProvider(module));
+ }
+ }
if (!_command.CompositeOrInputBubble)
{
diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Schema/DataTypeImplementation.cs b/src/libraries/System.Private.Xml/src/System/Xml/Schema/DataTypeImplementation.cs
index f4f3c6489b9398..f683cd5e35136b 100644
--- a/src/libraries/System.Private.Xml/src/System/Xml/Schema/DataTypeImplementation.cs
+++ b/src/libraries/System.Private.Xml/src/System/Xml/Schema/DataTypeImplementation.cs
@@ -1113,7 +1113,7 @@ internal override RestrictionFlags ValidRestrictionFlags
XsdSimpleValue simpleValue = (XsdSimpleValue)unionTypedValue;
values.Add(new XmlAtomicValue(simpleValue.XmlType, simpleValue.TypedValue, nsmgr));
}
- array = values.ToArray(typeof(XmlAtomicValue));
+ array = ToArray(values, typeof(XmlAtomicValue[]));
}
else
{ //Variety == List or Atomic