summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichal Strehovský <MichalStrehovsky@users.noreply.github.com>2018-01-29 17:37:27 +0100
committerGitHub <noreply@github.com>2018-01-29 17:37:27 +0100
commit0be894732e08aec5265f7e4e93d2ca8c70e3c945 (patch)
treeb9b20484eaba96e1212c9b67e79daf2a2933e936 /src
parent616fdb208aaff0f81e5ef0de189728795532de25 (diff)
downloadcoreclr-0be894732e08aec5265f7e4e93d2ca8c70e3c945.tar.gz
coreclr-0be894732e08aec5265f7e4e93d2ca8c70e3c945.tar.bz2
coreclr-0be894732e08aec5265f7e4e93d2ca8c70e3c945.zip
Fix reflection to work with default interface methods (#16034)
Fixes #15645. Fixes #15644.
Diffstat (limited to 'src')
-rw-r--r--src/mscorlib/src/System/RtType.cs35
-rw-r--r--src/mscorlib/src/System/RuntimeHandles.cs6
-rw-r--r--src/vm/ecalllist.h2
-rw-r--r--src/vm/runtimehandles.cpp8
-rw-r--r--src/vm/runtimehandles.h2
5 files changed, 28 insertions, 25 deletions
diff --git a/src/mscorlib/src/System/RtType.cs b/src/mscorlib/src/System/RtType.cs
index 6873dd1b89..611e11d6bc 100644
--- a/src/mscorlib/src/System/RtType.cs
+++ b/src/mscorlib/src/System/RtType.cs
@@ -580,26 +580,25 @@ namespace System
#region Loop through all methods on the interface
Debug.Assert(!methodHandle.IsNullHandle());
- // Except for .ctor, .cctor, IL_STUB*, and static methods, all interface methods should be abstract, virtual, and non-RTSpecialName.
- // Note that this assumption will become invalid when we add support for non-abstract or static methods on interfaces.
+
+ MethodAttributes methodAttributes = RuntimeMethodHandle.GetAttributes(methodHandle);
+
+ #region Continue if this is a constructor
Debug.Assert(
- (RuntimeMethodHandle.GetAttributes(methodHandle) & (MethodAttributes.RTSpecialName | MethodAttributes.Abstract | MethodAttributes.Virtual)) == (MethodAttributes.Abstract | MethodAttributes.Virtual) ||
- (RuntimeMethodHandle.GetAttributes(methodHandle) & MethodAttributes.Static) == MethodAttributes.Static ||
- RuntimeMethodHandle.GetName(methodHandle).Equals(".ctor") ||
- RuntimeMethodHandle.GetName(methodHandle).Equals(".cctor") ||
- RuntimeMethodHandle.GetName(methodHandle).StartsWith("IL_STUB", StringComparison.Ordinal));
+ (RuntimeMethodHandle.GetAttributes(methodHandle) & MethodAttributes.RTSpecialName) == 0 ||
+ RuntimeMethodHandle.GetName(methodHandle).Equals(".cctor"));
+
+ if ((methodAttributes & MethodAttributes.RTSpecialName) != 0)
+ continue;
+ #endregion
#region Calculate Binding Flags
- MethodAttributes methodAttributes = RuntimeMethodHandle.GetAttributes(methodHandle);
bool isPublic = (methodAttributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public;
bool isStatic = (methodAttributes & MethodAttributes.Static) != 0;
bool isInherited = false;
BindingFlags bindingFlags = RuntimeType.FilterPreCalculate(isPublic, isInherited, isStatic);
#endregion
- if ((methodAttributes & MethodAttributes.RTSpecialName) != 0)
- continue;
-
// get the unboxing stub or instantiating stub if needed
RuntimeMethodHandleInternal instantiatedHandle = RuntimeMethodHandle.GetStubIfNeeded(methodHandle, declaringType, null);
@@ -2747,15 +2746,19 @@ namespace System
Debug.Assert(ifaceMethodBase is RuntimeMethodInfo);
im.InterfaceMethods[i] = (MethodInfo)ifaceMethodBase;
- // If the slot is -1, then virtual stub dispatch is active.
- int slot = GetTypeHandleInternal().GetInterfaceMethodImplementationSlot(ifaceRtTypeHandle, ifaceRtMethodHandle);
+ // If the impl is null, then virtual stub dispatch is active.
+ RuntimeMethodHandleInternal classRtMethodHandle = GetTypeHandleInternal().GetInterfaceMethodImplementation(ifaceRtTypeHandle, ifaceRtMethodHandle);
- if (slot == -1) continue;
+ if (classRtMethodHandle.IsNullHandle())
+ continue;
- RuntimeMethodHandleInternal classRtMethodHandle = RuntimeTypeHandle.GetMethodAt(this, slot);
+ // If we resolved to an interface method, use the interface type as reflected type. Otherwise use `this`.
+ RuntimeType reflectedType = RuntimeMethodHandle.GetDeclaringType(classRtMethodHandle);
+ if (!reflectedType.IsInterface)
+ reflectedType = this;
// GetMethodBase will convert this to the instantiating/unboxing stub if necessary
- MethodBase rtTypeMethodBase = RuntimeType.GetMethodBase(this, classRtMethodHandle);
+ MethodBase rtTypeMethodBase = RuntimeType.GetMethodBase(reflectedType, classRtMethodHandle);
// a class may not implement all the methods of an interface (abstract class) so null is a valid value
Debug.Assert(rtTypeMethodBase == null || rtTypeMethodBase is RuntimeMethodInfo);
im.TargetMethods[i] = (MethodInfo)rtTypeMethodBase;
diff --git a/src/mscorlib/src/System/RuntimeHandles.cs b/src/mscorlib/src/System/RuntimeHandles.cs
index dc84976fe9..8dca7fd3f6 100644
--- a/src/mscorlib/src/System/RuntimeHandles.cs
+++ b/src/mscorlib/src/System/RuntimeHandles.cs
@@ -358,11 +358,11 @@ namespace System
}
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
- private extern static int GetInterfaceMethodImplementationSlot(RuntimeTypeHandle handle, RuntimeTypeHandle interfaceHandle, RuntimeMethodHandleInternal interfaceMethodHandle);
+ private extern static RuntimeMethodHandleInternal GetInterfaceMethodImplementation(RuntimeTypeHandle handle, RuntimeTypeHandle interfaceHandle, RuntimeMethodHandleInternal interfaceMethodHandle);
- internal int GetInterfaceMethodImplementationSlot(RuntimeTypeHandle interfaceHandle, RuntimeMethodHandleInternal interfaceMethodHandle)
+ internal RuntimeMethodHandleInternal GetInterfaceMethodImplementation(RuntimeTypeHandle interfaceHandle, RuntimeMethodHandleInternal interfaceMethodHandle)
{
- return GetInterfaceMethodImplementationSlot(GetNativeHandle(), interfaceHandle.GetNativeHandle(), interfaceMethodHandle);
+ return GetInterfaceMethodImplementation(GetNativeHandle(), interfaceHandle.GetNativeHandle(), interfaceMethodHandle);
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
diff --git a/src/vm/ecalllist.h b/src/vm/ecalllist.h
index 525227b7c3..8fbfd206e5 100644
--- a/src/vm/ecalllist.h
+++ b/src/vm/ecalllist.h
@@ -267,7 +267,7 @@ FCFuncStart(gCOMTypeHandleFuncs)
FCFuncElement("_GetMetadataImport", RuntimeTypeHandle::GetMetadataImport)
FCFuncElement("GetNumVirtuals", RuntimeTypeHandle::GetNumVirtuals)
QCFuncElement("VerifyInterfaceIsImplemented", RuntimeTypeHandle::VerifyInterfaceIsImplemented)
- QCFuncElement("GetInterfaceMethodImplementationSlot", RuntimeTypeHandle::GetInterfaceMethodImplementationSlot)
+ QCFuncElement("GetInterfaceMethodImplementation", RuntimeTypeHandle::GetInterfaceMethodImplementation)
FCFuncElement("IsComObject", RuntimeTypeHandle::IsComObject)
FCFuncElement("IsValueType", RuntimeTypeHandle::IsValueType)
FCFuncElement("IsInterface", RuntimeTypeHandle::IsInterface)
diff --git a/src/vm/runtimehandles.cpp b/src/vm/runtimehandles.cpp
index 952be6206e..723222e55b 100644
--- a/src/vm/runtimehandles.cpp
+++ b/src/vm/runtimehandles.cpp
@@ -1181,11 +1181,11 @@ void QCALLTYPE RuntimeTypeHandle::VerifyInterfaceIsImplemented(EnregisteredTypeH
END_QCALL;
}
-INT32 QCALLTYPE RuntimeTypeHandle::GetInterfaceMethodImplementationSlot(EnregisteredTypeHandle pTypeHandle, EnregisteredTypeHandle pOwner, MethodDesc * pMD)
+MethodDesc* QCALLTYPE RuntimeTypeHandle::GetInterfaceMethodImplementation(EnregisteredTypeHandle pTypeHandle, EnregisteredTypeHandle pOwner, MethodDesc * pMD)
{
QCALL_CONTRACT;
- INT32 slotNumber = -1;
+ MethodDesc* pResult = nullptr;
BEGIN_QCALL;
@@ -1199,11 +1199,11 @@ INT32 QCALLTYPE RuntimeTypeHandle::GetInterfaceMethodImplementationSlot(Enregist
//@TODO: be done faster - just need to make a function FindDispatchDecl.
DispatchSlot slot(typeHandle.GetMethodTable()->FindDispatchSlotForInterfaceMD(thOwnerOfMD, pMD));
if (!slot.IsNull())
- slotNumber = slot.GetMethodDesc()->GetSlot();
+ pResult = slot.GetMethodDesc();
END_QCALL;
- return slotNumber;
+ return pResult;
}
void QCALLTYPE RuntimeTypeHandle::GetDefaultConstructor(EnregisteredTypeHandle pTypeHandle, QCall::ObjectHandleOnStack retMethod)
diff --git a/src/vm/runtimehandles.h b/src/vm/runtimehandles.h
index 8978e20946..7a637e65bc 100644
--- a/src/vm/runtimehandles.h
+++ b/src/vm/runtimehandles.h
@@ -248,7 +248,7 @@ public:
void QCALLTYPE VerifyInterfaceIsImplemented(EnregisteredTypeHandle pTypeHandle, EnregisteredTypeHandle pIFaceHandle);
static
- INT32 QCALLTYPE GetInterfaceMethodImplementationSlot(EnregisteredTypeHandle pTypeHandle, EnregisteredTypeHandle pOwner, MethodDesc * pMD);
+ MethodDesc* QCALLTYPE GetInterfaceMethodImplementation(EnregisteredTypeHandle pTypeHandle, EnregisteredTypeHandle pOwner, MethodDesc * pMD);
static FCDECL3(FC_BOOL_RET, GetFields, ReflectClassBaseObject *pType, INT32 **result, INT32 *pCount);