Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Convert RuntimeMethodHandle.GetMethodBody() to QCall.
Browse files Browse the repository at this point in the history
AaronRobinsonMSFT committed Dec 11, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent f9ff74a commit fffc08e
Showing 5 changed files with 120 additions and 123 deletions.
13 changes: 11 additions & 2 deletions src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs
Original file line number Diff line number Diff line change
@@ -1321,8 +1321,17 @@ internal static IRuntimeMethodInfo StripMethodInstantiation(IRuntimeMethodInfo m
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern Resolver GetResolver(RuntimeMethodHandleInternal method);

[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern RuntimeMethodBody? GetMethodBody(IRuntimeMethodInfo method, RuntimeType declaringType);
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "RuntimeMethodHandle_GetMethodBody")]
private static partial void GetMethodBody(RuntimeMethodHandleInternal method, nint declaringType, ObjectHandleOnStack result);

internal static RuntimeMethodBody? GetMethodBody(IRuntimeMethodInfo method, RuntimeType declaringType)
{
RuntimeMethodBody? result = null;
GetMethodBody(method.Value, declaringType.GetUnderlyingNativeHandle(), ObjectHandleOnStack.Create(ref result));
GC.KeepAlive(method);
GC.KeepAlive(declaringType);
return result;
}

[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern bool IsConstructor(RuntimeMethodHandleInternal method);
1 change: 0 additions & 1 deletion src/coreclr/vm/ecalllist.h
Original file line number Diff line number Diff line change
@@ -149,7 +149,6 @@ FCFuncStart(gRuntimeMethodHandle)
FCFuncElement("GetStubIfNeededInternal", RuntimeMethodHandle::GetStubIfNeededInternal)
FCFuncElement("GetMethodFromCanonical", RuntimeMethodHandle::GetMethodFromCanonical)
FCFuncElement("IsDynamicMethod", RuntimeMethodHandle::IsDynamicMethod)
FCFuncElement("GetMethodBody", RuntimeMethodHandle::GetMethodBody)
FCFuncElement("IsConstructor", RuntimeMethodHandle::IsConstructor)
FCFuncElement("GetResolver", RuntimeMethodHandle::GetResolver)
FCFuncElement("GetLoaderAllocatorInternal", RuntimeMethodHandle::GetLoaderAllocatorInternal)
1 change: 1 addition & 0 deletions src/coreclr/vm/qcallentrypoints.cpp
Original file line number Diff line number Diff line change
@@ -163,6 +163,7 @@ static const Entry s_QCall[] =
DllImportEntry(RuntimeMethodHandle_IsCAVisibleFromDecoratedType)
DllImportEntry(RuntimeMethodHandle_Destroy)
DllImportEntry(RuntimeMethodHandle_GetStubIfNeededSlow)
DllImportEntry(RuntimeMethodHandle_GetMethodBody)
DllImportEntry(RuntimeModule_GetScopeName)
DllImportEntry(RuntimeModule_GetFullyQualifiedName)
DllImportEntry(RuntimeModule_GetTypes)
224 changes: 107 additions & 117 deletions src/coreclr/vm/runtimehandles.cpp
Original file line number Diff line number Diff line change
@@ -2039,170 +2039,160 @@ FCIMPL2(MethodDesc*, RuntimeMethodHandle::GetMethodFromCanonical, MethodDesc *pM
}
FCIMPLEND


FCIMPL2(RuntimeMethodBody *, RuntimeMethodHandle::GetMethodBody, ReflectMethodObject *pMethodUNSAFE, ReflectClassBaseObject *pDeclaringTypeUNSAFE)
extern "C" void QCALLTYPE RuntimeMethodHandle_GetMethodBody(MethodDesc* pMethod, EnregisteredTypeHandle pDeclaringType, QCall::ObjectHandleOnStack result)
{
CONTRACTL
{
FCALL_CHECK;
}
CONTRACTL_END;
QCALL_CONTRACT;

struct _gc
_ASSERTE(pMethod != NULL);

BEGIN_QCALL;

GCX_COOP();

struct
{
RUNTIMEMETHODBODYREF MethodBodyObj;
RUNTIMEEXCEPTIONHANDLINGCLAUSEREF EHClauseObj;
RUNTIMELOCALVARIABLEINFOREF RuntimeLocalVariableInfoObj;
U1ARRAYREF U1Array;
BASEARRAYREF TempArray;
REFLECTCLASSBASEREF declaringType;
REFLECTMETHODREF refMethod;
U1ARRAYREF U1Array;
BASEARRAYREF TempArray;
} gc;

gc.MethodBodyObj = NULL;
gc.EHClauseObj = NULL;
gc.RuntimeLocalVariableInfoObj = NULL;
gc.U1Array = NULL;
gc.TempArray = NULL;
gc.declaringType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pDeclaringTypeUNSAFE);
gc.refMethod = (REFLECTMETHODREF)ObjectToOBJECTREF(pMethodUNSAFE);


if (!gc.refMethod)
FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));

MethodDesc* pMethod = gc.refMethod->GetMethod();
GCPROTECT_BEGIN(gc);

TypeHandle declaringType = gc.declaringType == NULL ? TypeHandle() : gc.declaringType->GetType();
TypeHandle declaringType = TypeHandle::FromPtr(pDeclaringType);

if (!pMethod->IsIL())
return NULL;

HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
COR_ILMETHOD* pILHeader = NULL;
if (pMethod->IsIL())
{
MethodDesc *pMethodIL = pMethod;
MethodDesc* pMethodIL = pMethod;
if (pMethod->IsWrapperStub())
pMethodIL = pMethod->GetWrappedMethodDesc();

COR_ILMETHOD* pILHeader = pMethodIL->GetILHeader();
pILHeader = pMethodIL->GetILHeader();
}

if (pILHeader)
{
MethodTable * pExceptionHandlingClauseMT = CoreLibBinder::GetClass(CLASS__RUNTIME_EH_CLAUSE);
TypeHandle thEHClauseArray = ClassLoader::LoadArrayTypeThrowing(TypeHandle(pExceptionHandlingClauseMT), ELEMENT_TYPE_SZARRAY);
if (pILHeader)
{
MethodTable * pExceptionHandlingClauseMT = CoreLibBinder::GetClass(CLASS__RUNTIME_EH_CLAUSE);
TypeHandle thEHClauseArray = ClassLoader::LoadArrayTypeThrowing(TypeHandle(pExceptionHandlingClauseMT), ELEMENT_TYPE_SZARRAY);

MethodTable * pLocalVariableMT = CoreLibBinder::GetClass(CLASS__RUNTIME_LOCAL_VARIABLE_INFO);
TypeHandle thLocalVariableArray = ClassLoader::LoadArrayTypeThrowing(TypeHandle(pLocalVariableMT), ELEMENT_TYPE_SZARRAY);
MethodTable * pLocalVariableMT = CoreLibBinder::GetClass(CLASS__RUNTIME_LOCAL_VARIABLE_INFO);
TypeHandle thLocalVariableArray = ClassLoader::LoadArrayTypeThrowing(TypeHandle(pLocalVariableMT), ELEMENT_TYPE_SZARRAY);

Module* pModule = pMethod->GetModule();
COR_ILMETHOD_DECODER::DecoderStatus status;
COR_ILMETHOD_DECODER header(pILHeader, pModule->GetMDImport(), &status);
Module* pModule = pMethod->GetModule();
COR_ILMETHOD_DECODER::DecoderStatus status;
COR_ILMETHOD_DECODER header(pILHeader, pModule->GetMDImport(), &status);

if (status != COR_ILMETHOD_DECODER::SUCCESS)
if (status != COR_ILMETHOD_DECODER::SUCCESS)
{
if (status == COR_ILMETHOD_DECODER::VERIFICATION_ERROR)
{
if (status == COR_ILMETHOD_DECODER::VERIFICATION_ERROR)
{
// Throw a verification HR
COMPlusThrowHR(COR_E_VERIFICATION);
}
else
{
COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
}
// Throw a verification HR
COMPlusThrowHR(COR_E_VERIFICATION);
}
else
{
COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
}
}

gc.MethodBodyObj = (RUNTIMEMETHODBODYREF)AllocateObject(CoreLibBinder::GetClass(CLASS__RUNTIME_METHOD_BODY));
gc.MethodBodyObj = (RUNTIMEMETHODBODYREF)AllocateObject(CoreLibBinder::GetClass(CLASS__RUNTIME_METHOD_BODY));

gc.MethodBodyObj->_maxStackSize = header.GetMaxStack();
gc.MethodBodyObj->_initLocals = !!(header.GetFlags() & CorILMethod_InitLocals);
gc.MethodBodyObj->_maxStackSize = header.GetMaxStack();
gc.MethodBodyObj->_initLocals = !!(header.GetFlags() & CorILMethod_InitLocals);

if (header.IsFat())
gc.MethodBodyObj->_localVarSigToken = header.GetLocalVarSigTok();
else
gc.MethodBodyObj->_localVarSigToken = 0;
if (header.IsFat())
gc.MethodBodyObj->_localVarSigToken = header.GetLocalVarSigTok();
else
gc.MethodBodyObj->_localVarSigToken = 0;

// Allocate the array of IL and fill it in from the method header.
BYTE* pIL = const_cast<BYTE*>(header.Code);
COUNT_T cIL = header.GetCodeSize();
gc.U1Array = (U1ARRAYREF) AllocatePrimitiveArray(ELEMENT_TYPE_U1, cIL);
// Allocate the array of IL and fill it in from the method header.
BYTE* pIL = const_cast<BYTE*>(header.Code);
COUNT_T cIL = header.GetCodeSize();
gc.U1Array = (U1ARRAYREF) AllocatePrimitiveArray(ELEMENT_TYPE_U1, cIL);

SetObjectReference((OBJECTREF*)&gc.MethodBodyObj->_IL, gc.U1Array);
memcpyNoGCRefs(gc.MethodBodyObj->_IL->GetDataPtr(), pIL, cIL);
SetObjectReference((OBJECTREF*)&gc.MethodBodyObj->_IL, gc.U1Array);
memcpyNoGCRefs(gc.MethodBodyObj->_IL->GetDataPtr(), pIL, cIL);

// Allocate the array of exception clauses.
INT32 cEh = (INT32)header.EHCount();
const COR_ILMETHOD_SECT_EH* ehInfo = header.EH;
gc.TempArray = (BASEARRAYREF) AllocateSzArray(thEHClauseArray, cEh);
// Allocate the array of exception clauses.
INT32 cEh = (INT32)header.EHCount();
const COR_ILMETHOD_SECT_EH* ehInfo = header.EH;
gc.TempArray = (BASEARRAYREF) AllocateSzArray(thEHClauseArray, cEh);

SetObjectReference((OBJECTREF*)&gc.MethodBodyObj->_exceptionClauses, gc.TempArray);
SetObjectReference((OBJECTREF*)&gc.MethodBodyObj->_exceptionClauses, gc.TempArray);

for (INT32 i = 0; i < cEh; i++)
{
COR_ILMETHOD_SECT_EH_CLAUSE_FAT ehBuff;
const COR_ILMETHOD_SECT_EH_CLAUSE_FAT* ehClause =
(const COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)ehInfo->EHClause(i, &ehBuff);
for (INT32 i = 0; i < cEh; i++)
{
COR_ILMETHOD_SECT_EH_CLAUSE_FAT ehBuff;
const COR_ILMETHOD_SECT_EH_CLAUSE_FAT* ehClause =
(const COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)ehInfo->EHClause(i, &ehBuff);

gc.EHClauseObj = (RUNTIMEEXCEPTIONHANDLINGCLAUSEREF) AllocateObject(pExceptionHandlingClauseMT);
gc.EHClauseObj = (RUNTIMEEXCEPTIONHANDLINGCLAUSEREF) AllocateObject(pExceptionHandlingClauseMT);

gc.EHClauseObj->_flags = ehClause->GetFlags();
gc.EHClauseObj->_tryOffset = ehClause->GetTryOffset();
gc.EHClauseObj->_tryLength = ehClause->GetTryLength();
gc.EHClauseObj->_handlerOffset = ehClause->GetHandlerOffset();
gc.EHClauseObj->_handlerLength = ehClause->GetHandlerLength();
gc.EHClauseObj->_flags = ehClause->GetFlags();
gc.EHClauseObj->_tryOffset = ehClause->GetTryOffset();
gc.EHClauseObj->_tryLength = ehClause->GetTryLength();
gc.EHClauseObj->_handlerOffset = ehClause->GetHandlerOffset();
gc.EHClauseObj->_handlerLength = ehClause->GetHandlerLength();

if ((ehClause->GetFlags() & COR_ILEXCEPTION_CLAUSE_FILTER) == 0)
gc.EHClauseObj->_catchToken = ehClause->GetClassToken();
else
gc.EHClauseObj->_filterOffset = ehClause->GetFilterOffset();
if ((ehClause->GetFlags() & COR_ILEXCEPTION_CLAUSE_FILTER) == 0)
gc.EHClauseObj->_catchToken = ehClause->GetClassToken();
else
gc.EHClauseObj->_filterOffset = ehClause->GetFilterOffset();

gc.MethodBodyObj->_exceptionClauses->SetAt(i, (OBJECTREF) gc.EHClauseObj);
SetObjectReference((OBJECTREF*)&(gc.EHClauseObj->_methodBody), (OBJECTREF)gc.MethodBodyObj);
}
gc.MethodBodyObj->_exceptionClauses->SetAt(i, (OBJECTREF) gc.EHClauseObj);
SetObjectReference((OBJECTREF*)&(gc.EHClauseObj->_methodBody), (OBJECTREF)gc.MethodBodyObj);
}

if (header.LocalVarSig != NULL)
if (header.LocalVarSig != NULL)
{
SigTypeContext sigTypeContext(pMethod, declaringType, pMethod->LoadMethodInstantiation());
MetaSig metaSig(header.LocalVarSig,
header.cbLocalVarSig,
pModule,
&sigTypeContext,
MetaSig::sigLocalVars);
INT32 cLocals = metaSig.NumFixedArgs();
gc.TempArray = (BASEARRAYREF) AllocateSzArray(thLocalVariableArray, cLocals);
SetObjectReference((OBJECTREF*)&gc.MethodBodyObj->_localVariables, gc.TempArray);

for (INT32 i = 0; i < cLocals; i ++)
{
SigTypeContext sigTypeContext(pMethod, declaringType, pMethod->LoadMethodInstantiation());
MetaSig metaSig(header.LocalVarSig,
header.cbLocalVarSig,
pModule,
&sigTypeContext,
MetaSig::sigLocalVars);
INT32 cLocals = metaSig.NumFixedArgs();
gc.TempArray = (BASEARRAYREF) AllocateSzArray(thLocalVariableArray, cLocals);
SetObjectReference((OBJECTREF*)&gc.MethodBodyObj->_localVariables, gc.TempArray);

for (INT32 i = 0; i < cLocals; i ++)
{
gc.RuntimeLocalVariableInfoObj = (RUNTIMELOCALVARIABLEINFOREF)AllocateObject(pLocalVariableMT);
gc.RuntimeLocalVariableInfoObj = (RUNTIMELOCALVARIABLEINFOREF)AllocateObject(pLocalVariableMT);

gc.RuntimeLocalVariableInfoObj->_localIndex = i;
gc.RuntimeLocalVariableInfoObj->_localIndex = i;

metaSig.NextArg();
metaSig.NextArg();

CorElementType eType;
IfFailThrow(metaSig.GetArgProps().PeekElemType(&eType));
if (ELEMENT_TYPE_PINNED == eType)
gc.RuntimeLocalVariableInfoObj->_isPinned = TRUE;
CorElementType eType;
IfFailThrow(metaSig.GetArgProps().PeekElemType(&eType));
if (ELEMENT_TYPE_PINNED == eType)
gc.RuntimeLocalVariableInfoObj->_isPinned = TRUE;

TypeHandle tempType= metaSig.GetArgProps().GetTypeHandleThrowing(pModule, &sigTypeContext);
OBJECTREF refLocalType = tempType.GetManagedClassObject();
gc.RuntimeLocalVariableInfoObj->SetType(refLocalType);
gc.MethodBodyObj->_localVariables->SetAt(i, (OBJECTREF) gc.RuntimeLocalVariableInfoObj);
}
}
else
{
INT32 cLocals = 0;
gc.TempArray = (BASEARRAYREF) AllocateSzArray(thLocalVariableArray, cLocals);
SetObjectReference((OBJECTREF*)&gc.MethodBodyObj->_localVariables, gc.TempArray);
TypeHandle tempType= metaSig.GetArgProps().GetTypeHandleThrowing(pModule, &sigTypeContext);
OBJECTREF refLocalType = tempType.GetManagedClassObject();
gc.RuntimeLocalVariableInfoObj->SetType(refLocalType);
gc.MethodBodyObj->_localVariables->SetAt(i, (OBJECTREF) gc.RuntimeLocalVariableInfoObj);
}
}
else
{
INT32 cLocals = 0;
gc.TempArray = (BASEARRAYREF) AllocateSzArray(thLocalVariableArray, cLocals);
SetObjectReference((OBJECTREF*)&gc.MethodBodyObj->_localVariables, gc.TempArray);
}
}
HELPER_METHOD_FRAME_END();

return (RuntimeMethodBody*)OBJECTREFToObject(gc.MethodBodyObj);
result.Set(gc.MethodBodyObj);

GCPROTECT_END();
END_QCALL;
}
FCIMPLEND

FCIMPL1(FC_BOOL_RET, RuntimeMethodHandle::IsConstructor, MethodDesc *pMethod)
{
4 changes: 1 addition & 3 deletions src/coreclr/vm/runtimehandles.h
Original file line number Diff line number Diff line change
@@ -225,9 +225,6 @@ class RuntimeMethodHandle
static
FCDECL1(Object*, GetResolver, MethodDesc * pMethod);


static FCDECL2(RuntimeMethodBody*, GetMethodBody, ReflectMethodObject *pMethodUNSAFE, PTR_ReflectClassBaseObject pDeclaringType);

static FCDECL1(FC_BOOL_RET, IsConstructor, MethodDesc *pMethod);

static FCDECL1(Object*, GetLoaderAllocatorInternal, MethodDesc *pMethod);
@@ -257,6 +254,7 @@ extern "C" void QCALLTYPE RuntimeMethodHandle_GetTypicalMethodDefinition(MethodD
extern "C" void QCALLTYPE RuntimeMethodHandle_StripMethodInstantiation(MethodDesc * pMethod, QCall::ObjectHandleOnStack refMethod);
extern "C" void QCALLTYPE RuntimeMethodHandle_Destroy(MethodDesc * pMethod);
extern "C" MethodDesc* QCALLTYPE RuntimeMethodHandle_GetStubIfNeededSlow(MethodDesc* pMethod, QCall::TypeHandle declaringTypeHandle, QCall::ObjectHandleOnStack methodInstantiation);
extern "C" void QCALLTYPE RuntimeMethodHandle_GetMethodBody(MethodDesc* pMethod, EnregisteredTypeHandle pDeclaringType, QCall::ObjectHandleOnStack result);

class RuntimeFieldHandle
{

0 comments on commit fffc08e

Please sign in to comment.