From 538144f841288feac6ce6a34a61ee5d7a4943991 Mon Sep 17 00:00:00 2001 From: Austin Wise Date: Fri, 15 Mar 2024 20:19:45 -0700 Subject: [PATCH 1/3] Convert GetCurrentMethod to QCALL This has a similar structure to FailFast as converted in #98908. Contributes to #95695 --- .../src/System/RuntimeHandles.cs | 8 +++++--- src/coreclr/vm/ecalllist.h | 1 - src/coreclr/vm/qcallentrypoints.cpp | 1 + src/coreclr/vm/reflectioninvocation.cpp | 16 ++++++++++------ src/coreclr/vm/runtimehandles.h | 5 +++-- 5 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs index 244312cf59809c..06d1414c80a1ad 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs @@ -844,11 +844,13 @@ internal static partial Interop.BOOL IsCAVisibleFromDecoratedType( QCallTypeHandle sourceTypeHandle, QCallModule sourceModule); - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern IRuntimeMethodInfo? _GetCurrentMethod(ref StackCrawlMark stackMark); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "RuntimeMethodHandle_GetCurrentMethod")] + private static partial void _GetCurrentMethod(StackCrawlMarkHandle stackMark, ObjectHandleOnStack retMethod); internal static IRuntimeMethodInfo? GetCurrentMethod(ref StackCrawlMark stackMark) { - return _GetCurrentMethod(ref stackMark); + object? retMethod = null; + _GetCurrentMethod(new StackCrawlMarkHandle(ref stackMark), ObjectHandleOnStack.Create(ref retMethod)); + return (IRuntimeMethodInfo?)retMethod; } [MethodImpl(MethodImplOptions.InternalCall)] diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index e72f08ead0e6f1..fac53467d4c60c 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -196,7 +196,6 @@ FCFuncStart(gSignatureNative) FCFuncEnd() FCFuncStart(gRuntimeMethodHandle) - FCFuncElement("_GetCurrentMethod", RuntimeMethodHandle::GetCurrentMethod) FCFuncElement("InvokeMethod", RuntimeMethodHandle::InvokeMethod) FCFuncElement("ReboxFromNullable", RuntimeMethodHandle::ReboxFromNullable) FCFuncElement("ReboxToNullable", RuntimeMethodHandle::ReboxToNullable) diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index cddd522914f6a0..852ef1f1bac2c1 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -119,6 +119,7 @@ static const Entry s_QCall[] = DllImportEntry(RuntimeTypeHandle_AllocateTypeAssociatedMemory) DllImportEntry(RuntimeTypeHandle_RegisterCollectibleTypeDependency) DllImportEntry(RuntimeMethodHandle_ConstructInstantiation) + DllImportEntry(RuntimeMethodHandle_GetCurrentMethod) DllImportEntry(RuntimeMethodHandle_GetFunctionPointer) DllImportEntry(RuntimeMethodHandle_GetIsCollectible) DllImportEntry(RuntimeMethodHandle_GetMethodInstantiation) diff --git a/src/coreclr/vm/reflectioninvocation.cpp b/src/coreclr/vm/reflectioninvocation.cpp index 54e226bb0189a3..83f31510e64736 100644 --- a/src/coreclr/vm/reflectioninvocation.cpp +++ b/src/coreclr/vm/reflectioninvocation.cpp @@ -890,11 +890,16 @@ static StackWalkAction SkipMethods(CrawlFrame* frame, VOID* data) { } // Return the MethodInfo that represents the current method (two above this one) -FCIMPL1(ReflectMethodObject*, RuntimeMethodHandle::GetCurrentMethod, StackCrawlMark* stackMark) { - FCALL_CONTRACT; +extern "C" void QCALLTYPE RuntimeMethodHandle_GetCurrentMethod(QCall::StackCrawlMarkHandle stackMark, QCall::ObjectHandleOnStack retMethod) { + + QCALL_CONTRACT; + + BEGIN_QCALL; + + GCX_COOP(); + REFLECTMETHODREF pRet = NULL; - HELPER_METHOD_FRAME_BEGIN_RET_0(); SkipStruct skip; skip.pStackMark = stackMark; skip.pMeth = 0; @@ -909,11 +914,10 @@ FCIMPL1(ReflectMethodObject*, RuntimeMethodHandle::GetCurrentMethod, StackCrawlM else pRet = NULL; - HELPER_METHOD_FRAME_END(); + retMethod.Set(pRet); - return (ReflectMethodObject*)OBJECTREFToObject(pRet); + END_QCALL; } -FCIMPLEND static OBJECTREF DirectObjectFieldGet(FieldDesc *pField, TypeHandle fieldType, TypeHandle enclosingType, TypedByRef *pTarget, CLR_BOOL *pIsClassInitialized) { CONTRACTL diff --git a/src/coreclr/vm/runtimehandles.h b/src/coreclr/vm/runtimehandles.h index ec7864ad2bc499..498cea24699110 100644 --- a/src/coreclr/vm/runtimehandles.h +++ b/src/coreclr/vm/runtimehandles.h @@ -201,8 +201,6 @@ extern "C" void QCALLTYPE RuntimeTypeHandle_RegisterCollectibleTypeDependency(QC class RuntimeMethodHandle { public: - static FCDECL1(ReflectMethodObject*, GetCurrentMethod, StackCrawlMark* stackMark); - static FCDECL4(Object*, InvokeMethod, Object *target, PVOID* args, SignatureNative* pSig, CLR_BOOL fConstructor); static FCDECL2(Object*, ReboxToNullable, Object *pBoxedValUNSAFE, ReflectClassBaseObject *pDestUNSAFE); @@ -275,6 +273,9 @@ class RuntimeMethodHandle { static FCDECL1(Object*, GetLoaderAllocator, MethodDesc *pMethod); }; + +extern "C" void QCALLTYPE RuntimeMethodHandle_GetCurrentMethod(QCall::StackCrawlMarkHandle stackMark, QCall::ObjectHandleOnStack retMethod); + extern "C" BOOL QCALLTYPE RuntimeMethodHandle_IsCAVisibleFromDecoratedType( QCall::TypeHandle targetTypeHandle, MethodDesc * pTargetCtor, From d6f3fdbe3bfb46e4f98fa4898bdad76e15260eeb Mon Sep 17 00:00:00 2001 From: Austin Wise Date: Fri, 15 Mar 2024 20:58:41 -0700 Subject: [PATCH 2/3] Update RuntimeHandles.cs Co-authored-by: Jan Kotas --- .../System.Private.CoreLib/src/System/RuntimeHandles.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs index 06d1414c80a1ad..af1fa51702bb39 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs @@ -848,9 +848,9 @@ internal static partial Interop.BOOL IsCAVisibleFromDecoratedType( private static partial void _GetCurrentMethod(StackCrawlMarkHandle stackMark, ObjectHandleOnStack retMethod); internal static IRuntimeMethodInfo? GetCurrentMethod(ref StackCrawlMark stackMark) { - object? retMethod = null; + IRuntimeMethodInfo? retMethod = null; _GetCurrentMethod(new StackCrawlMarkHandle(ref stackMark), ObjectHandleOnStack.Create(ref retMethod)); - return (IRuntimeMethodInfo?)retMethod; + return retMethod; } [MethodImpl(MethodImplOptions.InternalCall)] From 1346957ec5e92862fe530d400c086bd1640e006c Mon Sep 17 00:00:00 2001 From: Austin Wise Date: Sun, 17 Mar 2024 11:08:57 -0700 Subject: [PATCH 3/3] Simplify code for QCALL Co-authored-by: Jan Kotas --- .../src/System/Reflection/MethodBase.CoreCLR.cs | 8 +++++++- .../Reflection/RuntimeMethodInfo.CoreCLR.cs | 12 ------------ .../src/System/RuntimeHandles.cs | 9 --------- src/coreclr/vm/qcallentrypoints.cpp | 2 +- src/coreclr/vm/reflectioninvocation.cpp | 16 ++++++---------- src/coreclr/vm/runtimehandles.h | 2 +- 6 files changed, 15 insertions(+), 34 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodBase.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodBase.CoreCLR.cs index 26383704e39277..8e8d7148b3974e 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodBase.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodBase.CoreCLR.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using System.Security; using System.Threading; @@ -34,12 +36,16 @@ public abstract partial class MethodBase : MemberInfo return RuntimeType.GetMethodBase(declaringType.GetRuntimeType(), handle.GetMethodInfo()); } + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "MethodBase_GetCurrentMethod")] + private static partial RuntimeMethodHandleInternal GetCurrentMethod(StackCrawlMarkHandle stackMark); + [RequiresUnreferencedCode("Metadata for the method might be incomplete or removed")] [DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod public static MethodBase? GetCurrentMethod() { StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return RuntimeMethodInfo.InternalGetCurrentMethod(ref stackMark); + RuntimeMethodHandleInternal methodHandle = GetCurrentMethod(new StackCrawlMarkHandle(ref stackMark)); + return methodHandle.IsNullHandle() ? null : RuntimeType.GetMethodBase(null, methodHandle); } #endregion diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs index de60e189ac918d..9c999912382a63 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs @@ -488,17 +488,5 @@ public override bool ContainsGenericParameters } } #endregion - - #region Legacy Internal - internal static MethodBase? InternalGetCurrentMethod(ref StackCrawlMark stackMark) - { - IRuntimeMethodInfo? method = RuntimeMethodHandle.GetCurrentMethod(ref stackMark); - - if (method == null) - return null; - - return RuntimeType.GetMethodBase(method); - } - #endregion } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs index af1fa51702bb39..c6c7b9a563b4da 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs @@ -844,15 +844,6 @@ internal static partial Interop.BOOL IsCAVisibleFromDecoratedType( QCallTypeHandle sourceTypeHandle, QCallModule sourceModule); - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "RuntimeMethodHandle_GetCurrentMethod")] - private static partial void _GetCurrentMethod(StackCrawlMarkHandle stackMark, ObjectHandleOnStack retMethod); - internal static IRuntimeMethodInfo? GetCurrentMethod(ref StackCrawlMark stackMark) - { - IRuntimeMethodInfo? retMethod = null; - _GetCurrentMethod(new StackCrawlMarkHandle(ref stackMark), ObjectHandleOnStack.Create(ref retMethod)); - return retMethod; - } - [MethodImpl(MethodImplOptions.InternalCall)] internal static extern MethodAttributes GetAttributes(RuntimeMethodHandleInternal method); diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index 852ef1f1bac2c1..8ff379f40f6e08 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -118,8 +118,8 @@ static const Entry s_QCall[] = DllImportEntry(RuntimeTypeHandle_GetActivationInfo) DllImportEntry(RuntimeTypeHandle_AllocateTypeAssociatedMemory) DllImportEntry(RuntimeTypeHandle_RegisterCollectibleTypeDependency) + DllImportEntry(MethodBase_GetCurrentMethod) DllImportEntry(RuntimeMethodHandle_ConstructInstantiation) - DllImportEntry(RuntimeMethodHandle_GetCurrentMethod) DllImportEntry(RuntimeMethodHandle_GetFunctionPointer) DllImportEntry(RuntimeMethodHandle_GetIsCollectible) DllImportEntry(RuntimeMethodHandle_GetMethodInstantiation) diff --git a/src/coreclr/vm/reflectioninvocation.cpp b/src/coreclr/vm/reflectioninvocation.cpp index 83f31510e64736..a7f88289d037a4 100644 --- a/src/coreclr/vm/reflectioninvocation.cpp +++ b/src/coreclr/vm/reflectioninvocation.cpp @@ -890,15 +890,13 @@ static StackWalkAction SkipMethods(CrawlFrame* frame, VOID* data) { } // Return the MethodInfo that represents the current method (two above this one) -extern "C" void QCALLTYPE RuntimeMethodHandle_GetCurrentMethod(QCall::StackCrawlMarkHandle stackMark, QCall::ObjectHandleOnStack retMethod) { +extern "C" MethodDesc* QCALLTYPE MethodBase_GetCurrentMethod(QCall::StackCrawlMarkHandle stackMark) { QCALL_CONTRACT; - BEGIN_QCALL; - - GCX_COOP(); + MethodDesc* pRet = nullptr; - REFLECTMETHODREF pRet = NULL; + BEGIN_QCALL; SkipStruct skip; skip.pStackMark = stackMark; @@ -910,13 +908,11 @@ extern "C" void QCALLTYPE RuntimeMethodHandle_GetCurrentMethod(QCall::StackCrawl // is to return C.m

and that's what LoadTypicalMethodDefinition will do for us. if (skip.pMeth != NULL) - pRet = skip.pMeth->LoadTypicalMethodDefinition()->GetStubMethodInfo(); - else - pRet = NULL; - - retMethod.Set(pRet); + pRet = skip.pMeth->LoadTypicalMethodDefinition(); END_QCALL; + + return pRet; } static OBJECTREF DirectObjectFieldGet(FieldDesc *pField, TypeHandle fieldType, TypeHandle enclosingType, TypedByRef *pTarget, CLR_BOOL *pIsClassInitialized) { diff --git a/src/coreclr/vm/runtimehandles.h b/src/coreclr/vm/runtimehandles.h index 498cea24699110..6b0d995977c654 100644 --- a/src/coreclr/vm/runtimehandles.h +++ b/src/coreclr/vm/runtimehandles.h @@ -274,7 +274,7 @@ class RuntimeMethodHandle { }; -extern "C" void QCALLTYPE RuntimeMethodHandle_GetCurrentMethod(QCall::StackCrawlMarkHandle stackMark, QCall::ObjectHandleOnStack retMethod); +extern "C" MethodDesc* QCALLTYPE MethodBase_GetCurrentMethod(QCall::StackCrawlMarkHandle stackMark); extern "C" BOOL QCALLTYPE RuntimeMethodHandle_IsCAVisibleFromDecoratedType( QCall::TypeHandle targetTypeHandle,