diff options
author | Michal Strehovský <MichalStrehovsky@users.noreply.github.com> | 2018-01-29 17:37:27 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-01-29 17:37:27 +0100 |
commit | 0be894732e08aec5265f7e4e93d2ca8c70e3c945 (patch) | |
tree | b9b20484eaba96e1212c9b67e79daf2a2933e936 /src | |
parent | 616fdb208aaff0f81e5ef0de189728795532de25 (diff) | |
download | coreclr-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.cs | 35 | ||||
-rw-r--r-- | src/mscorlib/src/System/RuntimeHandles.cs | 6 | ||||
-rw-r--r-- | src/vm/ecalllist.h | 2 | ||||
-rw-r--r-- | src/vm/runtimehandles.cpp | 8 | ||||
-rw-r--r-- | src/vm/runtimehandles.h | 2 |
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); |