diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/CachedInterfaceDispatch.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/CachedInterfaceDispatch.cs
index d8ae1363c73af2..22e8b674b57f95 100644
--- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/CachedInterfaceDispatch.cs
+++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/CachedInterfaceDispatch.cs
@@ -113,6 +113,10 @@ private static IntPtr RhResolveDynamicInterfaceCastableDispatchOnType(MethodTabl
return result;
}
+ [Intrinsic]
+ [AnalysisCharacteristic]
+ private static extern bool DynamicInterfaceCastablePresent();
+
private static unsafe IntPtr RhResolveDispatchWorker(object pObject, void* cell, ref DispatchCellInfo cellInfo)
{
// Type of object we're dispatching on.
@@ -125,7 +129,7 @@ private static unsafe IntPtr RhResolveDispatchWorker(object pObject, void* cell,
cellInfo.InterfaceSlot,
flags: default,
ppGenericContext: null);
- if (pTargetCode == IntPtr.Zero && pInstanceType->IsIDynamicInterfaceCastable)
+ if (DynamicInterfaceCastablePresent() && pTargetCode == IntPtr.Zero && pInstanceType->IsIDynamicInterfaceCastable)
{
// Dispatch not resolved through normal dispatch map, try using the IDynamicInterfaceCastable
// This will either give us the appropriate result, or throw.
diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/ThrowHelpers.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/ThrowHelpers.cs
index 3ee1884b129af7..e52c8a598ace00 100644
--- a/src/coreclr/nativeaot/Runtime.Base/src/System/ThrowHelpers.cs
+++ b/src/coreclr/nativeaot/Runtime.Base/src/System/ThrowHelpers.cs
@@ -57,10 +57,5 @@ private static void ThrowArgumentOutOfRangeException()
// exception doesn't exist in MRT: throw PlatformNotSupportedException() instead
throw new PlatformNotSupportedException();
}
-
- private static void ThrowFeatureBodyRemoved()
- {
- throw new NotSupportedException();
- }
}
}
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj
index 6db8c5a1c5bf98..e9e3462effb868 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj
@@ -240,6 +240,7 @@
+
diff --git a/src/coreclr/nativeaot/Test.CoreLib/src/Test.CoreLib.csproj b/src/coreclr/nativeaot/Test.CoreLib/src/Test.CoreLib.csproj
index 0b82467b1a942e..9801d32020121b 100644
--- a/src/coreclr/nativeaot/Test.CoreLib/src/Test.CoreLib.csproj
+++ b/src/coreclr/nativeaot/Test.CoreLib/src/Test.CoreLib.csproj
@@ -212,6 +212,7 @@
Common\System\Runtime\InteropServices\IDynamicInterfaceCastable.cs
+
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs
index 20a0a0ebd5a3f7..a73ef4a1fbefc9 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs
@@ -28,6 +28,11 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact
{
DependencyList dependencyList = base.ComputeNonRelocationBasedDependencies(factory);
+ if (_type.IsIDynamicInterfaceCastable)
+ {
+ dependencyList.Add(factory.AnalysisCharacteristic("DynamicInterfaceCastablePresent"), "Implements IDynamicInterfaceCastable");
+ }
+
// Ensure that we track the metadata type symbol if we are working with a constructed type symbol.
// The emitter will ensure we don't emit both, but this allows us assert that we only generate
// relocs to nodes we emit.
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ILScanner.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ILScanner.cs
index 18fdd2f65550eb..adca2e9baa475c 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ILScanner.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ILScanner.cs
@@ -150,7 +150,6 @@ ILScanResults IILScanner.Scan()
_dependencyGraph.AddRoot(GetHelperEntrypoint(ReadyToRunHelper.CheckInstanceInterface), "Not tracked by scanner");
_dependencyGraph.AddRoot(GetHelperEntrypoint(ReadyToRunHelper.CheckInstanceClass), "Not tracked by scanner");
_dependencyGraph.AddRoot(GetHelperEntrypoint(ReadyToRunHelper.IsInstanceOfException), "Not tracked by scanner");
- _dependencyGraph.AddRoot(_nodeFactory.MethodEntrypoint(_nodeFactory.TypeSystemContext.GetHelperEntryPoint("ThrowHelpers", "ThrowFeatureBodyRemoved")), "Substitution for methods removed based on scanning");
_dependencyGraph.ComputeMarkedNodes();
@@ -277,34 +276,6 @@ public ReadOnlyFieldPolicy GetReadOnlyFieldPolicy()
return new ScannedReadOnlyPolicy(MarkedNodes);
}
- public BodyAndFieldSubstitutions GetBodyAndFieldSubstitutions()
- {
- Dictionary bodySubstitutions = [];
-
- bool hasIDynamicInterfaceCastableType = false;
-
- foreach (var type in ConstructedEETypes)
- {
- if (type.IsIDynamicInterfaceCastable)
- {
- hasIDynamicInterfaceCastableType = true;
- break;
- }
- }
-
- if (!hasIDynamicInterfaceCastableType)
- {
- // We can't easily trim out some of the IDynamicInterfaceCastable infrastructure because
- // the callers do type checks based on flags on the MethodTable instead of an actual type cast.
- // Trim out the logic that we can't do easily here.
- TypeDesc iDynamicInterfaceCastableType = _factory.TypeSystemContext.SystemModule.GetKnownType("System.Runtime.InteropServices", "IDynamicInterfaceCastable");
- MethodDesc getDynamicInterfaceImplementationMethod = iDynamicInterfaceCastableType.GetKnownMethod("GetDynamicInterfaceImplementation", null);
- bodySubstitutions.Add(getDynamicInterfaceImplementationMethod, BodySubstitution.ThrowingBody);
- }
-
- return new BodyAndFieldSubstitutions(bodySubstitutions, []);
- }
-
public TypeMapManager GetTypeMapManager()
{
return new ScannedTypeMapManager(_factory);
diff --git a/src/coreclr/tools/aot/ILCompiler/Program.cs b/src/coreclr/tools/aot/ILCompiler/Program.cs
index 04795875d6d071..73330f1384842e 100644
--- a/src/coreclr/tools/aot/ILCompiler/Program.cs
+++ b/src/coreclr/tools/aot/ILCompiler/Program.cs
@@ -530,10 +530,6 @@ void RunScanner()
interopStubManager = scanResults.GetInteropStubManager(interopStateManager, pinvokePolicy);
- substitutions.AppendFrom(scanResults.GetBodyAndFieldSubstitutions());
-
- substitutionProvider = new SubstitutionProvider(logger, featureSwitches, substitutions);
-
ilProvider = new SubstitutedILProvider(unsubstitutedILProvider, substitutionProvider, devirtualizationManager, metadataManager, scanResults.GetAnalysisCharacteristics());
// Use a more precise IL provider that uses whole program analysis for dead branch elimination