Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFadi Hanna <fadim@microsoft.com>2018-06-27 20:26:31 +0300
committerFadi Hanna <fadim@microsoft.com>2018-06-27 20:26:31 +0300
commit8a67e171ceab76a4d23131e51bc13c84cb2479d8 (patch)
treefb9bdc5223bcfa15cea5525fdcca4d381a26686a /src/ILCompiler.Compiler
parentd6905df41a109b97c424a49eabbd8909f3a9d28d (diff)
Changing the interface method resolution logic used in building the sealed vtable and the interface dispatch map to work with type definitions instead of instantiated types, to correctly handle the cases where we get generic interface collapsing, and when the implementing method ends up in the sealed vtable (This was causing the interface resolution logic at runtime to fail).
This also fixes the cases of dynamic types, since we use fully canonical instantiations as templates, and these canonical instantiations can suffer from the same generic collapsing problem. [tfs-changeset: 1705787]
Diffstat (limited to 'src/ILCompiler.Compiler')
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs29
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/SealedVTableNode.cs25
2 files changed, 40 insertions, 14 deletions
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs
index b631efaff..57c4299af 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs
@@ -76,9 +76,9 @@ namespace ILCompiler.DependencyAnalysis
if (!type.IsArray && !type.IsDefType)
return false;
- DefType defType = type.GetClosestDefType();
+ TypeDesc declType = type.GetClosestDefType().GetTypeDefinition();
- foreach (DefType interfaceType in defType.RuntimeInterfaces)
+ foreach (DefType interfaceType in declType.RuntimeInterfaces)
{
IEnumerable<MethodDesc> slots;
@@ -96,7 +96,7 @@ namespace ILCompiler.DependencyAnalysis
if (declMethod.Signature.IsStatic)
continue;
- var implMethod = defType.ResolveInterfaceMethodToVirtualMethodOnType(declMethod);
+ var implMethod = declType.ResolveInterfaceMethodToVirtualMethodOnType(declMethod);
if (implMethod != null)
return true;
}
@@ -109,10 +109,15 @@ namespace ILCompiler.DependencyAnalysis
{
var entryCountReservation = builder.ReserveInt();
int entryCount = 0;
-
- for (int interfaceIndex = 0; interfaceIndex < _type.RuntimeInterfaces.Length; interfaceIndex++)
+
+ TypeDesc declType = _type.GetClosestDefType();
+
+ // Catch any runtime interface collapsing. We shouldn't have any
+ Debug.Assert(declType.RuntimeInterfaces.Length == declType.GetTypeDefinition().RuntimeInterfaces.Length);
+
+ for (int interfaceIndex = 0; interfaceIndex < declType.RuntimeInterfaces.Length; interfaceIndex++)
{
- var interfaceType = _type.RuntimeInterfaces[interfaceIndex];
+ var interfaceType = declType.GetTypeDefinition().RuntimeInterfaces[interfaceIndex];
Debug.Assert(interfaceType.IsInterface);
IReadOnlyList<MethodDesc> virtualSlots = factory.VTable(interfaceType).Slots;
@@ -120,15 +125,23 @@ namespace ILCompiler.DependencyAnalysis
for (int interfaceMethodSlot = 0; interfaceMethodSlot < virtualSlots.Count; interfaceMethodSlot++)
{
MethodDesc declMethod = virtualSlots[interfaceMethodSlot];
- var implMethod = _type.GetClosestDefType().ResolveInterfaceMethodToVirtualMethodOnType(declMethod);
+ var implMethod = declType.GetTypeDefinition().ResolveInterfaceMethodToVirtualMethodOnType(declMethod);
// Interface methods first implemented by a base type in the hierarchy will return null for the implMethod (runtime interface
// dispatch will walk the inheritance chain).
if (implMethod != null)
{
+ TypeDesc implType = declType;
+ while (!implType.HasSameTypeDefinition(implMethod.OwningType))
+ implType = implType.BaseType;
+
+ MethodDesc targetMethod = implMethod;
+ if (!implType.IsTypeDefinition)
+ targetMethod = factory.TypeSystemContext.GetMethodForInstantiatedType(implMethod.GetTypicalMethodDefinition(), (InstantiatedType)implType);
+
builder.EmitShort(checked((short)interfaceIndex));
builder.EmitShort(checked((short)(interfaceMethodSlot + (interfaceType.HasGenericDictionarySlot() ? 1 : 0))));
- builder.EmitShort(checked((short)VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, implMethod, _type.GetClosestDefType())));
+ builder.EmitShort(checked((short)VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, targetMethod, declType)));
entryCount++;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/SealedVTableNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/SealedVTableNode.cs
index ec1dca987..c2a792246 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/SealedVTableNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/SealedVTableNode.cs
@@ -98,27 +98,40 @@ namespace ILCompiler.DependencyAnalysis
for (int i = 0; i < virtualSlots.Count; i++)
{
- MethodDesc implMethod = _type.GetClosestDefType().FindVirtualFunctionTargetMethodOnObjectType(virtualSlots[i]);
+ MethodDesc implMethod = declType.FindVirtualFunctionTargetMethodOnObjectType(virtualSlots[i]);
if (implMethod.CanMethodBeInSealedVTable())
_sealedVTableEntries.Add(implMethod);
}
- for (int interfaceIndex = 0; interfaceIndex < _type.RuntimeInterfaces.Length; interfaceIndex++)
+ // Catch any runtime interface collapsing. We shouldn't have any
+ Debug.Assert(declType.RuntimeInterfaces.Length == declType.GetTypeDefinition().RuntimeInterfaces.Length);
+
+ for (int interfaceIndex = 0; interfaceIndex < declType.RuntimeInterfaces.Length; interfaceIndex++)
{
- var interfaceType = _type.RuntimeInterfaces[interfaceIndex];
+ var interfaceType = declType.GetTypeDefinition().RuntimeInterfaces[interfaceIndex];
virtualSlots = factory.VTable(interfaceType).Slots;
for (int interfaceMethodSlot = 0; interfaceMethodSlot < virtualSlots.Count; interfaceMethodSlot++)
{
MethodDesc declMethod = virtualSlots[interfaceMethodSlot];
- var implMethod = _type.GetClosestDefType().ResolveInterfaceMethodToVirtualMethodOnType(declMethod);
+ var implMethod = declType.GetTypeDefinition().ResolveInterfaceMethodToVirtualMethodOnType(declMethod);
// Interface methods first implemented by a base type in the hierarchy will return null for the implMethod (runtime interface
// dispatch will walk the inheritance chain).
- if (implMethod != null && implMethod.CanMethodBeInSealedVTable() && implMethod.OwningType != _type)
- _sealedVTableEntries.Add(implMethod);
+ if (implMethod != null && implMethod.CanMethodBeInSealedVTable() && !implMethod.OwningType.HasSameTypeDefinition(declType))
+ {
+ TypeDesc implType = declType;
+ while (!implType.HasSameTypeDefinition(implMethod.OwningType))
+ implType = implType.BaseType;
+
+ MethodDesc targetMethod = implMethod;
+ if (!implType.IsTypeDefinition)
+ targetMethod = factory.TypeSystemContext.GetMethodForInstantiatedType(implMethod.GetTypicalMethodDefinition(), (InstantiatedType)implType);
+
+ _sealedVTableEntries.Add(targetMethod);
+ }
}
}