Skip to content

Commit

Permalink
Convert RuntimeMethodHandle.GetMethodBody() to QCall.
Browse files Browse the repository at this point in the history
  • Loading branch information
AaronRobinsonMSFT committed Dec 11, 2024
1 parent f9ff74a commit fffc08e
Show file tree
Hide file tree
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
Expand Up @@ -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);
Expand Down
1 change: 0 additions & 1 deletion src/coreclr/vm/ecalllist.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/vm/qcallentrypoints.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
224 changes: 107 additions & 117 deletions src/coreclr/vm/runtimehandles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
4 changes: 1 addition & 3 deletions src/coreclr/vm/runtimehandles.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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
{
Expand Down

0 comments on commit fffc08e

Please sign in to comment.