From eae4f37d6e3de95ca787530fe0f53a6e8d23d0f5 Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Tue, 3 Dec 2024 13:45:19 -0800 Subject: [PATCH] Remove Helper Method Frames (HMF) from Reflection (#110211) Create general purpose RuntimeTypeHandle.InternalAlloc() and RuntimeTypeHandle.InternalAllocNoChecks(). Convert RuntimeMethodHandle::ReboxToNullable() to managed. Convert RuntimeMethodHandle::ReboxFromNullable() to managed. Convert RuntimeMethodHandle::InvokeMethod() to QCall. --- .../src/System/Delegate.CoreCLR.cs | 17 +-- .../src/System/MulticastDelegate.CoreCLR.cs | 2 +- .../Runtime/CompilerServices/CastHelpers.cs | 26 ++++ .../src/System/RuntimeHandles.cs | 87 +++++++++++- src/coreclr/vm/comdelegate.cpp | 30 ---- src/coreclr/vm/comdelegate.h | 4 - src/coreclr/vm/ecalllist.h | 3 - src/coreclr/vm/methodtable.cpp | 15 +- src/coreclr/vm/methodtable.h | 7 +- src/coreclr/vm/methodtable.inl | 3 +- src/coreclr/vm/qcallentrypoints.cpp | 5 +- src/coreclr/vm/reflectioninvocation.cpp | 132 +++++++----------- src/coreclr/vm/runtimehandles.h | 45 ++---- .../Reflection/InvokeInterpretedTests.cs | 12 +- 14 files changed, 188 insertions(+), 200 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs index 0a7431072e3fa0..358dab7f43674d 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs @@ -434,23 +434,10 @@ private bool BindToMethodInfo(object? target, IRuntimeMethodInfo method, Runtime private static MulticastDelegate InternalAlloc(RuntimeType type) { - MulticastDelegate? d = null; - InternalAlloc(new QCallTypeHandle(ref type), ObjectHandleOnStack.Create(ref d)); - return d!; + Debug.Assert(type.IsAssignableTo(typeof(MulticastDelegate))); + return Unsafe.As(RuntimeTypeHandle.InternalAlloc(type)); } - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "Delegate_InternalAlloc")] - private static partial void InternalAlloc(QCallTypeHandle type, ObjectHandleOnStack d); - - internal static MulticastDelegate InternalAllocLike(MulticastDelegate d) - { - InternalAllocLike(ObjectHandleOnStack.Create(ref d)); - return d; - } - - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "Delegate_InternalAllocLike")] - private static partial void InternalAllocLike(ObjectHandleOnStack d); - [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static unsafe bool InternalEqualTypes(object a, object b) { diff --git a/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.CoreCLR.cs index 0a850691d68678..0846f7060ce38f 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.CoreCLR.cs @@ -167,7 +167,7 @@ private static bool TrySetSlot(object?[] a, int index, object o) private MulticastDelegate NewMulticastDelegate(object[] invocationList, int invocationCount, bool thisIsMultiCastAlready) { // First, allocate a new multicast delegate just like this one, i.e. same type as the this object - MulticastDelegate result = InternalAllocLike(this); + MulticastDelegate result = Unsafe.As(RuntimeTypeHandle.InternalAllocNoChecks((RuntimeType)GetType())); // Performance optimization - if this already points to a true multicast delegate, // copy _methodPtr and _methodPtrAux fields rather than calling into the EE to get them diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs index 202a339b680251..ba42162dd03478 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs @@ -596,6 +596,32 @@ internal static void Unbox_Nullable(ref byte destPtr, MethodTable* typeMT, objec } } + [DebuggerHidden] + internal static object? ReboxFromNullable(MethodTable* srcMT, object src) + { + Debug.Assert(srcMT->IsNullable); + + ref byte nullableData = ref src.GetRawData(); + + // If 'hasValue' is false, return null. + if (!Unsafe.As(ref nullableData)) + return null; + + // Allocate a new instance of the T in Nullable. + MethodTable* dstMT = srcMT->InstantiationArg0(); + object dst = RuntimeTypeHandle.InternalAlloc(dstMT); + + // Copy data from the Nullable. + ref byte srcData = ref Unsafe.Add(ref nullableData, srcMT->NullableValueAddrOffset); + ref byte dstData = ref RuntimeHelpers.GetRawData(dst); + if (dstMT->ContainsGCPointers) + Buffer.BulkMoveWithWriteBarrier(ref dstData, ref srcData, dstMT->GetNumInstanceFieldBytesIfContainsGCPointers()); + else + SpanHelpers.Memmove(ref dstData, ref srcData, dstMT->GetNumInstanceFieldBytes()); + + return dst; + } + [DebuggerHidden] [MethodImpl(MethodImplOptions.NoInlining)] private static ref byte Unbox_Helper(MethodTable* pMT1, object obj) diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs index 17e034811d79c1..b8da46a4bcdc14 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs @@ -269,6 +269,36 @@ private static partial void CreateInstanceForAnotherGenericParameter( int cTypeHandles, ObjectHandleOnStack instantiatedObject); + internal static unsafe object InternalAlloc(MethodTable* pMT) + { + object? result = null; + InternalAlloc(pMT, ObjectHandleOnStack.Create(ref result)); + return result!; + } + + internal static object InternalAlloc(RuntimeType type) + { + Debug.Assert(!type.GetNativeTypeHandle().IsTypeDesc); + object result = InternalAlloc(type.GetNativeTypeHandle().AsMethodTable()); + GC.KeepAlive(type); + return result; + } + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "RuntimeTypeHandle_InternalAlloc")] + private static unsafe partial void InternalAlloc(MethodTable* pMT, ObjectHandleOnStack result); + + internal static object InternalAllocNoChecks(RuntimeType type) + { + Debug.Assert(!type.GetNativeTypeHandle().IsTypeDesc); + object? result = null; + InternalAllocNoChecks(type.GetNativeTypeHandle().AsMethodTable(), ObjectHandleOnStack.Create(ref result)); + GC.KeepAlive(type); + return result!; + } + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "RuntimeTypeHandle_InternalAllocNoChecks")] + private static unsafe partial void InternalAllocNoChecks(MethodTable* pMT, ObjectHandleOnStack result); + /// /// Given a RuntimeType, returns information about how to activate it via calli /// semantics. This method will ensure the type object is fully initialized within @@ -1026,14 +1056,59 @@ internal static MdUtf8String GetUtf8Name(RuntimeMethodHandleInternal method) [DebuggerStepThrough] [DebuggerHidden] - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern object? InvokeMethod(object? target, void** arguments, Signature sig, bool isConstructor); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "RuntimeMethodHandle_InvokeMethod")] + private static partial void InvokeMethod(ObjectHandleOnStack target, void** arguments, ObjectHandleOnStack sig, Interop.BOOL isConstructor, ObjectHandleOnStack result); - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern object? ReboxFromNullable(object? src); + [DebuggerStepThrough] + [DebuggerHidden] + internal static object? InvokeMethod(object? target, void** arguments, Signature sig, bool isConstructor) + { + object? result = null; + InvokeMethod( + ObjectHandleOnStack.Create(ref target), + arguments, + ObjectHandleOnStack.Create(ref sig), + isConstructor ? Interop.BOOL.TRUE : Interop.BOOL.FALSE, + ObjectHandleOnStack.Create(ref result)); + return result; + } - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern object ReboxToNullable(object? src, RuntimeType destNullableType); + /// + /// For a true boxed Nullable{T}, re-box to a boxed {T} or null, otherwise just return the input. + /// + internal static object? ReboxFromNullable(object? src) + { + // If src is null or not NullableOfT, just return that state. + if (src is null) + { + return null; + } + + MethodTable* pMT = RuntimeHelpers.GetMethodTable(src); + if (!pMT->IsNullable) + { + return src; + } + + return CastHelpers.ReboxFromNullable(pMT, src); + } + + /// + /// Convert a boxed value of {T} (which is either {T} or null) to a true boxed Nullable{T}. + /// + internal static object ReboxToNullable(object? src, RuntimeType destNullableType) + { + Debug.Assert(destNullableType.IsNullableOfT); + MethodTable* pMT = destNullableType.GetNativeTypeHandle().AsMethodTable(); + object obj = RuntimeTypeHandle.InternalAlloc(pMT); + GC.KeepAlive(destNullableType); // The obj instance will keep the type alive. + + CastHelpers.Unbox_Nullable( + ref obj.GetRawData(), + pMT, + src); + return obj; + } [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "RuntimeMethodHandle_GetMethodInstantiation")] private static partial void GetMethodInstantiation(RuntimeMethodHandleInternal method, ObjectHandleOnStack types, Interop.BOOL fAsRuntimeTypeArray); diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index 205c5105d5a2d8..f13e28fc3cd147 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -2024,36 +2024,6 @@ Stub* COMDelegate::GetInvokeMethodStub(EEImplMethodDesc* pMD) } } -extern "C" void QCALLTYPE Delegate_InternalAlloc(QCall::TypeHandle pType, QCall::ObjectHandleOnStack d) -{ - QCALL_CONTRACT; - - BEGIN_QCALL; - - GCX_COOP(); - - _ASSERTE(pType.AsTypeHandle().AsMethodTable()->IsDelegate()); - - d.Set(pType.AsTypeHandle().AsMethodTable()->Allocate()); - - END_QCALL; -} - -extern "C" void QCALLTYPE Delegate_InternalAllocLike(QCall::ObjectHandleOnStack d) -{ - QCALL_CONTRACT; - - BEGIN_QCALL; - - GCX_COOP(); - - _ASSERTE(d.Get()->GetMethodTable()->IsDelegate()); - - d.Set(d.Get()->GetMethodTable()->AllocateNoChecks()); - - END_QCALL; -} - void COMDelegate::ThrowIfInvalidUnmanagedCallersOnlyUsage(MethodDesc* pMD) { CONTRACTL diff --git a/src/coreclr/vm/comdelegate.h b/src/coreclr/vm/comdelegate.h index be68b5ef40dd47..064d6d0177b843 100644 --- a/src/coreclr/vm/comdelegate.h +++ b/src/coreclr/vm/comdelegate.h @@ -123,10 +123,6 @@ extern "C" BOOL QCALLTYPE Delegate_BindToMethodName(QCall::ObjectHandleOnStack d extern "C" BOOL QCALLTYPE Delegate_BindToMethodInfo(QCall::ObjectHandleOnStack d, QCall::ObjectHandleOnStack target, MethodDesc * method, QCall::TypeHandle pMethodType, DelegateBindingFlags flags); -extern "C" void QCALLTYPE Delegate_InternalAlloc(QCall::TypeHandle pType, QCall::ObjectHandleOnStack d); - -extern "C" void QCALLTYPE Delegate_InternalAllocLike(QCall::ObjectHandleOnStack d); - extern "C" void QCALLTYPE Delegate_FindMethodHandle(QCall::ObjectHandleOnStack d, QCall::ObjectHandleOnStack retMethodInfo); extern "C" BOOL QCALLTYPE Delegate_InternalEqualMethodHandles(QCall::ObjectHandleOnStack left, QCall::ObjectHandleOnStack right); diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index 723aa5ac02a420..d3e196cfe61bb8 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -146,9 +146,6 @@ FCFuncStart(gSignatureNative) FCFuncEnd() FCFuncStart(gRuntimeMethodHandle) - FCFuncElement("InvokeMethod", RuntimeMethodHandle::InvokeMethod) - FCFuncElement("ReboxFromNullable", RuntimeMethodHandle::ReboxFromNullable) - FCFuncElement("ReboxToNullable", RuntimeMethodHandle::ReboxToNullable) FCFuncElement("GetImplAttributes", RuntimeMethodHandle::GetImplAttributes) FCFuncElement("GetAttributes", RuntimeMethodHandle::GetAttributes) FCFuncElement("GetMethodTable", RuntimeMethodHandle::GetMethodTable) diff --git a/src/coreclr/vm/methodtable.cpp b/src/coreclr/vm/methodtable.cpp index 2fbd4b04d86d47..e5070194507277 100644 --- a/src/coreclr/vm/methodtable.cpp +++ b/src/coreclr/vm/methodtable.cpp @@ -3940,18 +3940,17 @@ void MethodTable::CheckRunClassInitAsIfConstructingThrowing() THROWS; GC_TRIGGERS; MODE_ANY; + PRECONDITION(HasPreciseInitCctors()); } CONTRACTL_END; - if (HasPreciseInitCctors()) + + MethodTable *pMTCur = this; + while (pMTCur != NULL) { - MethodTable *pMTCur = this; - while (pMTCur != NULL) - { - if (!pMTCur->GetClass()->IsBeforeFieldInit()) - pMTCur->CheckRunClassInitThrowing(); + if (!pMTCur->GetClass()->IsBeforeFieldInit()) + pMTCur->CheckRunClassInitThrowing(); - pMTCur = pMTCur->GetParentMethodTable(); - } + pMTCur = pMTCur->GetParentMethodTable(); } } diff --git a/src/coreclr/vm/methodtable.h b/src/coreclr/vm/methodtable.h index 47ac585be717b3..ee2d60f6f947b5 100644 --- a/src/coreclr/vm/methodtable.h +++ b/src/coreclr/vm/methodtable.h @@ -2676,8 +2676,8 @@ class MethodTable // This flavor of Allocate is more efficient, but can only be used // if CheckInstanceActivated(), IsClassInited() are known to be true. // A sufficient condition is that another instance of the exact same type already - // exists in the same appdomain. It's currently called only from Delegate.Combine - // via COMDelegate::InternalAllocLike. + // exists in the same ALC. It's currently called only from Delegate.Combine + // via RuntimeTypeHandle_InternalAllocNoChecks. OBJECTREF AllocateNoChecks(); OBJECTREF Box(void* data); @@ -3921,12 +3921,11 @@ public : TADDR m_ElementTypeHnd; }; public: - union + union { PTR_InterfaceInfo m_pInterfaceMap; TADDR m_encodedNullableUnboxData; // Used for Nullable to represent the offset to the value field, and the size of the value field }; - // VTable slots go here diff --git a/src/coreclr/vm/methodtable.inl b/src/coreclr/vm/methodtable.inl index 4bcad99e482f73..f6aa4746666839 100644 --- a/src/coreclr/vm/methodtable.inl +++ b/src/coreclr/vm/methodtable.inl @@ -1230,7 +1230,7 @@ inline OBJECTREF MethodTable::AllocateNoChecks() } CONTRACTL_END; - // we know an instance of this class already exists in the same appdomain + // We know an instance of this class already exists // therefore, some checks become redundant. // this currently only happens for Delegate.Combine @@ -1239,7 +1239,6 @@ inline OBJECTREF MethodTable::AllocateNoChecks() return AllocateObject(this); } - #ifndef DACCESS_COMPILE //========================================================================================== // unbox src into dest, No checks are done diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index bc6a4a12b3d781..d65f6a838b63b2 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -96,8 +96,6 @@ static const Entry s_QCall[] = DllImportEntry(Delegate_GetMulticastInvokeSlow) DllImportEntry(Delegate_AdjustTarget) DllImportEntry(Delegate_Construct) - DllImportEntry(Delegate_InternalAlloc) - DllImportEntry(Delegate_InternalAllocLike) DllImportEntry(Delegate_FindMethodHandle) DllImportEntry(Delegate_InternalEqualMethodHandles) DllImportEntry(Environment_Exit) @@ -140,9 +138,12 @@ static const Entry s_QCall[] = #endif // FEATURE_COMINTEROP DllImportEntry(RuntimeTypeHandle_GetRuntimeTypeFromHandleSlow) DllImportEntry(RuntimeTypeHandle_CreateInstanceForAnotherGenericParameter) + DllImportEntry(RuntimeTypeHandle_InternalAlloc) + DllImportEntry(RuntimeTypeHandle_InternalAllocNoChecks) DllImportEntry(RuntimeTypeHandle_AllocateTypeAssociatedMemory) DllImportEntry(RuntimeTypeHandle_RegisterCollectibleTypeDependency) DllImportEntry(MethodBase_GetCurrentMethod) + DllImportEntry(RuntimeMethodHandle_InvokeMethod) DllImportEntry(RuntimeMethodHandle_ConstructInstantiation) DllImportEntry(RuntimeMethodHandle_GetFunctionPointer) DllImportEntry(RuntimeMethodHandle_GetIsCollectible) diff --git a/src/coreclr/vm/reflectioninvocation.cpp b/src/coreclr/vm/reflectioninvocation.cpp index c681e2b9763666..6e93b1b179583c 100644 --- a/src/coreclr/vm/reflectioninvocation.cpp +++ b/src/coreclr/vm/reflectioninvocation.cpp @@ -116,6 +116,36 @@ extern "C" void QCALLTYPE RuntimeTypeHandle_CreateInstanceForAnotherGenericParam END_QCALL; } +extern "C" void QCALLTYPE RuntimeTypeHandle_InternalAlloc(MethodTable* pMT, QCall::ObjectHandleOnStack allocated) +{ + QCALL_CONTRACT; + + _ASSERTE(pMT != NULL); + + BEGIN_QCALL; + + GCX_COOP(); + + allocated.Set(pMT->Allocate()); + + END_QCALL; +} + +extern "C" void QCALLTYPE RuntimeTypeHandle_InternalAllocNoChecks(MethodTable* pMT, QCall::ObjectHandleOnStack allocated) +{ + QCALL_CONTRACT; + + _ASSERTE(pMT != NULL); + + BEGIN_QCALL; + + GCX_COOP(); + + allocated.Set(pMT->AllocateNoChecks()); + + END_QCALL; +} + static OBJECTREF InvokeArrayConstructor(TypeHandle th, PVOID* args, int argCnt) { CONTRACTL @@ -279,29 +309,35 @@ class ArgIteratorForMethodInvoke : public ArgIteratorTemplateGetMethod(); TypeHandle ownerType = gc.pSig->GetDeclaringType(); - HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc); - if (ownerType.IsSharedByGenericInstantiations()) { COMPlusThrow(kNotSupportedException, W("NotSupported_Type")); @@ -316,7 +352,7 @@ FCIMPL4(Object*, RuntimeMethodHandle::InvokeMethod, BOOL fCtorOfVariableSizedObject = FALSE; - if (FC_ACCESS_BOOL(fConstructor)) + if (fConstructor) { // If we are invoking a constructor on an array then we must // handle this specially. @@ -423,7 +459,7 @@ FCIMPL4(Object*, RuntimeMethodHandle::InvokeMethod, if (!pMeth->IsStatic() && !fCtorOfVariableSizedObject) { PVOID pThisPtr; - if (FC_ACCESS_BOOL(fConstructor)) + if (fConstructor) { // Copy "this" pointer: only unbox if type is value type and method is not unboxing stub if (ownerType.IsValueType() && !pMeth->IsUnboxingStub()) { @@ -545,7 +581,7 @@ FCIMPL4(Object*, RuntimeMethodHandle::InvokeMethod, CallDescrWorkerWithHandler(&callDescrData); // It is still illegal to do a GC here. The return type might have/contain GC pointers. - if (FC_ACCESS_BOOL(fConstructor)) + if (fConstructor) { // We have a special case for Strings...The object is returned... if (fCtorOfVariableSizedObject) { @@ -618,74 +654,12 @@ FCIMPL4(Object*, RuntimeMethodHandle::InvokeMethod, } Done: - ; - HELPER_METHOD_FRAME_END(); - - return OBJECTREFToObject(gc.retVal); -} -FCIMPLEND - -/// -/// Convert a boxed value of {T} (which is either {T} or null) to a true boxed Nullable{T}. -/// -FCIMPL2(Object*, RuntimeMethodHandle::ReboxToNullable, Object* pBoxedValUNSAFE, ReflectClassBaseObject *pDestUNSAFE) -{ - FCALL_CONTRACT; - - struct { - OBJECTREF pBoxed; - REFLECTCLASSBASEREF destType; - OBJECTREF retVal; - } gc; - - gc.pBoxed = ObjectToOBJECTREF(pBoxedValUNSAFE); - gc.destType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pDestUNSAFE); - gc.retVal = NULL; - - HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc); - - MethodTable* destMT = gc.destType->GetType().AsMethodTable(); - - gc.retVal = destMT->Allocate(); - void* buffer = gc.retVal->GetData(); - BOOL result = Nullable::UnBox(buffer, gc.pBoxed, destMT); - _ASSERTE(result == TRUE); + result.Set(gc.retVal); - HELPER_METHOD_FRAME_END(); - - return OBJECTREFToObject(gc.retVal); -} -FCIMPLEND - -/// -/// For a true boxed Nullable{T}, re-box to a boxed {T} or null, otherwise just return the input. -/// -FCIMPL1(Object*, RuntimeMethodHandle::ReboxFromNullable, Object* pBoxedValUNSAFE) -{ - FCALL_CONTRACT; - - struct { - OBJECTREF pBoxed; - OBJECTREF retVal; - } gc; - - if (pBoxedValUNSAFE == NULL) - return NULL; - - gc.pBoxed = ObjectToOBJECTREF(pBoxedValUNSAFE); - MethodTable* retMT = gc.pBoxed->GetMethodTable(); - if (!Nullable::IsNullableType(retMT)) - return pBoxedValUNSAFE; - - gc.retVal = NULL; - - HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc); - gc.retVal = Nullable::Box(gc.pBoxed->GetData(), retMT); - HELPER_METHOD_FRAME_END(); + GCPROTECT_END(); - return OBJECTREFToObject(gc.retVal); + END_QCALL; } -FCIMPLEND struct SkipStruct { StackCrawlMark* pStackMark; diff --git a/src/coreclr/vm/runtimehandles.h b/src/coreclr/vm/runtimehandles.h index ddd6554d23babf..3cd538c67781e6 100644 --- a/src/coreclr/vm/runtimehandles.h +++ b/src/coreclr/vm/runtimehandles.h @@ -158,6 +158,8 @@ class RuntimeTypeHandle extern "C" void QCALLTYPE RuntimeTypeHandle_GetRuntimeTypeFromHandleSlow(void* typeHandleRaw, QCall::ObjectHandleOnStack result); extern "C" void QCALLTYPE RuntimeTypeHandle_CreateInstanceForAnotherGenericParameter(QCall::TypeHandle pTypeHandle, TypeHandle *pInstArray, INT32 cInstArray, QCall::ObjectHandleOnStack pInstantiatedObject); +extern "C" void QCALLTYPE RuntimeTypeHandle_InternalAlloc(MethodTable* pMT, QCall::ObjectHandleOnStack allocated); +extern "C" void QCALLTYPE RuntimeTypeHandle_InternalAllocNoChecks(MethodTable* pMT, QCall::ObjectHandleOnStack allocated); extern "C" void* QCALLTYPE RuntimeTypeHandle_AllocateTypeAssociatedMemory(QCall::TypeHandle type, uint32_t size); extern "C" PVOID QCALLTYPE QCall_GetGCHandleForTypeHandle(QCall::TypeHandle pTypeHandle, INT32 handleType); @@ -197,41 +199,6 @@ extern "C" void QCALLTYPE RuntimeTypeHandle_RegisterCollectibleTypeDependency(QC class RuntimeMethodHandle { public: - static FCDECL4(Object*, InvokeMethod, Object *target, PVOID* args, SignatureNative* pSig, FC_BOOL_ARG fConstructor); - - static FCDECL2(Object*, ReboxToNullable, Object *pBoxedValUNSAFE, ReflectClassBaseObject *pDestUNSAFE); - static FCDECL1(Object*, ReboxFromNullable, Object *pBoxedValUNSAFE); - - struct StreamingContextData { - Object * additionalContext; // additionalContex was changed from OBJECTREF to Object to avoid having a - INT32 contextStates; // constructor in this struct. GCC doesn't allow structs with constructors to be - }; - - // ******************************************************************************************* - // Keep these in sync with the version in bcl\system\runtime\serialization\streamingcontext.cs - // ******************************************************************************************* - enum StreamingContextStates - { - CONTEXTSTATE_CrossProcess = 0x01, - CONTEXTSTATE_CrossMachine = 0x02, - CONTEXTSTATE_File = 0x04, - CONTEXTSTATE_Persistence = 0x08, - CONTEXTSTATE_Remoting = 0x10, - CONTEXTSTATE_Other = 0x20, - CONTEXTSTATE_Clone = 0x40, - CONTEXTSTATE_CrossAppDomain = 0x80, - CONTEXTSTATE_All = 0xFF - }; - - // passed by value - // STATIC IMPLEMENTATION - static OBJECTREF InvokeMethod_Internal( - MethodDesc *pMethod, OBJECTREF targetUNSAFE, INT32 attrs, OBJECTREF binderUNSAFE, PTRARRAYREF objsUNSAFE, OBJECTREF localeUNSAFE, - BOOL isBinderDefault, Assembly *caller, Assembly *reflectedClassAssembly, TypeHandle declaringType, SignatureNative* pSig, BOOL verifyAccess); - - static FCDECL4(void, SerializationInvoke, ReflectMethodObject *pMethodUNSAFE, Object* targetUNSAFE, - Object* serializationInfoUNSAFE, struct StreamingContextData * pContext); - static FCDECL1(INT32, GetAttributes, MethodDesc *pMethod); static FCDECL1(INT32, GetImplAttributes, ReflectMethodObject *pMethodUNSAFE); static FCDECL1(MethodTable*, GetMethodTable, MethodDesc *pMethod); @@ -268,7 +235,6 @@ class RuntimeMethodHandle static FCDECL1(Object*, GetLoaderAllocator, MethodDesc *pMethod); }; - extern "C" MethodDesc* QCALLTYPE MethodBase_GetCurrentMethod(QCall::StackCrawlMarkHandle stackMark); extern "C" BOOL QCALLTYPE RuntimeMethodHandle_IsCAVisibleFromDecoratedType( @@ -279,6 +245,13 @@ extern "C" BOOL QCALLTYPE RuntimeMethodHandle_IsCAVisibleFromDecoratedType( extern "C" void QCALLTYPE RuntimeMethodHandle_GetMethodInstantiation(MethodDesc * pMethod, QCall::ObjectHandleOnStack retTypes, BOOL fAsRuntimeTypeArray); +extern "C" void QCALLTYPE RuntimeMethodHandle_InvokeMethod( + QCall::ObjectHandleOnStack target, + PVOID* args, + QCall::ObjectHandleOnStack pSigUNSAFE, + BOOL fConstructor, + QCall::ObjectHandleOnStack result); + extern "C" void QCALLTYPE RuntimeMethodHandle_ConstructInstantiation(MethodDesc * pMethod, DWORD format, QCall::StringHandleOnStack retString); extern "C" void* QCALLTYPE RuntimeMethodHandle_GetFunctionPointer(MethodDesc * pMethod); extern "C" BOOL QCALLTYPE RuntimeMethodHandle_GetIsCollectible(MethodDesc * pMethod); diff --git a/src/libraries/Common/tests/System/Reflection/InvokeInterpretedTests.cs b/src/libraries/Common/tests/System/Reflection/InvokeInterpretedTests.cs index 573211876b0fb7..6370e83d41c8f6 100644 --- a/src/libraries/Common/tests/System/Reflection/InvokeInterpretedTests.cs +++ b/src/libraries/Common/tests/System/Reflection/InvokeInterpretedTests.cs @@ -16,7 +16,7 @@ public static void VerifyInvokeIsUsingInterpreter_Method() Exception exInner = ex.InnerException; Assert.Contains("Here", exInner.ToString()); - Assert.Contains(InterpretedMethodName, exInner.ToString()); + Assert.Contains("InterpretedInvoke_Method", exInner.ToString()); Assert.DoesNotContain("InvokeStub_TestClassThatThrows", exInner.ToString()); } @@ -29,18 +29,10 @@ public static void VerifyInvokeIsUsingInterpreter_Constructor() Exception exInner = ex.InnerException; Assert.Contains("Here", exInner.ToString()); - Assert.Contains(InterpretedConstructorName, exInner.ToString()); + Assert.Contains("InterpretedInvoke_Constructor", exInner.ToString()); Assert.DoesNotContain("InvokeStub_TestClassThatThrows", exInner.ToString()); } - private static string InterpretedConstructorName => PlatformDetection.IsMonoRuntime ? - "InterpretedInvoke_Constructor" : - "System.RuntimeMethodHandle.InvokeMethod"; - - private static string InterpretedMethodName => PlatformDetection.IsMonoRuntime ? - "InterpretedInvoke_Method" : - "System.RuntimeMethodHandle.InvokeMethod"; - private class TestClassThatThrows { public TestClassThatThrows()