Skip to content

Commit

Permalink
Convert some handle APIs to QCalls (dotnet#107513)
Browse files Browse the repository at this point in the history
Convert RuntimeTypeHandle.GetAssembly()
Convert RuntimeTypeHandle.GetModule()
Convert RuntimeAssembly.GetManifestModule()
  • Loading branch information
AaronRobinsonMSFT committed Sep 9, 2024
1 parent 600f6bd commit b7b91cb
Show file tree
Hide file tree
Showing 8 changed files with 134 additions and 92 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,6 @@ public override string? CodeBase
}
}

internal RuntimeAssembly GetNativeHandle() => this;

// If the assembly is copied before it is loaded, the codebase will be set to the
// actual file loaded if copiedName is true. If it is false, then the original code base
// is returned.
Expand Down Expand Up @@ -263,7 +261,7 @@ public override Type[] GetExportedTypes()
public override IEnumerable<TypeInfo> DefinedTypes
{
[RequiresUnreferencedCode("Types might be removed")]
get => GetManifestModule(GetNativeHandle()).GetDefinedTypes();
get => GetManifestModule().GetDefinedTypes();
}

[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_GetIsCollectible")]
Expand Down Expand Up @@ -324,7 +322,7 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont
public override Module ManifestModule =>
// We don't need to return the "external" ModuleBuilder because
// it is meant to be read-only
GetManifestModule(GetNativeHandle());
GetManifestModule();

public override object[] GetCustomAttributes(bool inherit)
{
Expand Down Expand Up @@ -588,7 +586,7 @@ private CultureInfo GetLocale()
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern bool FCallIsDynamic(RuntimeAssembly assembly);

public override bool IsDynamic => FCallIsDynamic(GetNativeHandle());
public override bool IsDynamic => FCallIsDynamic(this);

[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_GetSimpleName")]
private static partial void GetSimpleName(QCallAssembly assembly, StringHandleOnStack retSimpleName);
Expand Down Expand Up @@ -701,8 +699,24 @@ public override Module[] GetLoadedModules(bool getResourceModules)
return GetModulesInternal(false, getResourceModules);
}

private RuntimeModule GetManifestModule()
{
return GetManifestModule(this) ?? GetManifestModuleWorker(this);

[MethodImpl(MethodImplOptions.NoInlining)]
static RuntimeModule GetManifestModuleWorker(RuntimeAssembly assembly)
{
RuntimeModule? module = null;
GetManifestModuleSlow(ObjectHandleOnStack.Create(ref assembly), ObjectHandleOnStack.Create(ref module));
return module!;
}
}

[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern RuntimeModule GetManifestModule(RuntimeAssembly assembly);
private static extern RuntimeModule? GetManifestModule(RuntimeAssembly assembly);

[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyHandle_GetManifestModuleSlow")]
private static partial void GetManifestModuleSlow(ObjectHandleOnStack assembly, ObjectHandleOnStack module);

[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern int GetToken(RuntimeAssembly assembly);
Expand All @@ -713,7 +727,7 @@ public sealed override Type[] GetForwardedTypes()
List<Type> types = new List<Type>();
List<Exception> exceptions = new List<Exception>();

MetadataImport scope = GetManifestModule(GetNativeHandle()).MetadataImport;
MetadataImport scope = GetManifestModule().MetadataImport;
scope.Enum(MetadataTokenType.ExportedType, 0, out MetadataEnumResult enumResult);
RuntimeAssembly runtimeAssembly = this;
QCallAssembly pAssembly = new QCallAssembly(ref runtimeAssembly);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ internal static IList<CustomAttributeData> GetCustomAttributesInternal(RuntimeAs

// No pseudo attributes for RuntimeAssembly

return GetCustomAttributes((RuntimeModule)target.ManifestModule, RuntimeAssembly.GetToken(target.GetNativeHandle()));
return GetCustomAttributes((RuntimeModule)target.ManifestModule, RuntimeAssembly.GetToken(target));
}

internal static IList<CustomAttributeData> GetCustomAttributesInternal(RuntimeParameterInfo target)
Expand Down Expand Up @@ -1227,7 +1227,7 @@ internal static bool IsDefined(RuntimeAssembly assembly, RuntimeType caType)
Debug.Assert(caType is not null);

// No pseudo attributes for RuntimeAssembly
return IsCustomAttributeDefined((assembly.ManifestModule as RuntimeModule)!, RuntimeAssembly.GetToken(assembly.GetNativeHandle()), caType);
return IsCustomAttributeDefined((assembly.ManifestModule as RuntimeModule)!, RuntimeAssembly.GetToken(assembly), caType);
}

internal static bool IsDefined(RuntimeModule module, RuntimeType caType)
Expand Down Expand Up @@ -1388,7 +1388,7 @@ internal static object[] GetCustomAttributes(RuntimeAssembly assembly, RuntimeTy

// No pseudo attributes for RuntimeAssembly

int assemblyToken = RuntimeAssembly.GetToken(assembly.GetNativeHandle());
int assemblyToken = RuntimeAssembly.GetToken(assembly);
return GetCustomAttributes((assembly.ManifestModule as RuntimeModule)!, assemblyToken, 0, caType);
}

Expand Down
36 changes: 34 additions & 2 deletions src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs
Original file line number Diff line number Diff line change
Expand Up @@ -306,11 +306,43 @@ internal RuntimeType GetRuntimeType()
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern CorElementType GetCorElementType(RuntimeType type);

internal static RuntimeAssembly GetAssembly(RuntimeType type)
{
return GetAssemblyIfExists(type) ?? GetAssemblyWorker(type);

[MethodImpl(MethodImplOptions.NoInlining)]
static RuntimeAssembly GetAssemblyWorker(RuntimeType type)
{
RuntimeAssembly? assembly = null;
GetAssemblySlow(ObjectHandleOnStack.Create(ref type), ObjectHandleOnStack.Create(ref assembly));
return assembly!;
}
}

[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern RuntimeAssembly GetAssembly(RuntimeType type);
private static extern RuntimeAssembly? GetAssemblyIfExists(RuntimeType type);

[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "RuntimeTypeHandle_GetAssemblySlow")]
private static partial void GetAssemblySlow(ObjectHandleOnStack type, ObjectHandleOnStack assembly);

internal static RuntimeModule GetModule(RuntimeType type)
{
return GetModuleIfExists(type) ?? GetModuleWorker(type);

[MethodImpl(MethodImplOptions.NoInlining)]
static RuntimeModule GetModuleWorker(RuntimeType type)
{
RuntimeModule? module = null;
GetModuleSlow(ObjectHandleOnStack.Create(ref type), ObjectHandleOnStack.Create(ref module));
return module!;
}
}

[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern RuntimeModule GetModule(RuntimeType type);
private static extern RuntimeModule? GetModuleIfExists(RuntimeType type);

[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "RuntimeTypeHandle_GetModuleSlow")]
private static partial void GetModuleSlow(ObjectHandleOnStack type, ObjectHandleOnStack module);

public ModuleHandle GetModuleHandle()
{
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/vm/ecalllist.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,8 @@ FCFuncStart(gCOMTypeHandleFuncs)
FCFuncElement("GetFirstIntroducedMethod", RuntimeTypeHandle::GetFirstIntroducedMethod)
FCFuncElement("GetNextIntroducedMethod", RuntimeTypeHandle::GetNextIntroducedMethod)
FCFuncElement("GetCorElementType", RuntimeTypeHandle::GetCorElementType)
FCFuncElement("GetAssembly", RuntimeTypeHandle::GetAssembly)
FCFuncElement("GetModule", RuntimeTypeHandle::GetModule)
FCFuncElement("GetAssemblyIfExists", RuntimeTypeHandle::GetAssemblyIfExists)
FCFuncElement("GetModuleIfExists", RuntimeTypeHandle::GetModuleIfExists)
FCFuncElement("GetBaseType", RuntimeTypeHandle::GetBaseType)
FCFuncElement("GetElementType", RuntimeTypeHandle::GetElementType)
FCFuncElement("GetArrayRank", RuntimeTypeHandle::GetArrayRank)
Expand Down
9 changes: 0 additions & 9 deletions src/coreclr/vm/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -1219,13 +1219,6 @@ class ReflectModuleBaseObject : public Object
}
};

NOINLINE ReflectModuleBaseObject* GetRuntimeModuleHelper(LPVOID __me, Module *pModule, OBJECTREF keepAlive);
#define FC_RETURN_MODULE_OBJECT(pModule, refKeepAlive) FC_INNER_RETURN(ReflectModuleBaseObject*, GetRuntimeModuleHelper(__me, pModule, refKeepAlive))





class ThreadBaseObject;
class SynchronizationContextObject: public Object
{
Expand Down Expand Up @@ -1439,8 +1432,6 @@ class AssemblyBaseObject : public Object
SetObjectReference(&m_pSyncRoot, pSyncRoot);
}
};
NOINLINE AssemblyBaseObject* GetRuntimeAssemblyHelper(LPVOID __me, Assembly *pAssembly, OBJECTREF keepAlive);
#define FC_RETURN_ASSEMBLY_OBJECT(pAssembly, refKeepAlive) FC_INNER_RETURN(AssemblyBaseObject*, GetRuntimeAssemblyHelper(__me, pAssembly, refKeepAlive))

// AssemblyLoadContextBaseObject
// This class is the base class for AssemblyLoadContext
Expand Down
3 changes: 3 additions & 0 deletions src/coreclr/vm/qcallentrypoints.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ static const Entry s_QCall[] =
DllImportEntry(RuntimeTypeHandle_MakeArray)
DllImportEntry(RuntimeTypeHandle_IsCollectible)
DllImportEntry(RuntimeTypeHandle_GetConstraints)
DllImportEntry(RuntimeTypeHandle_GetAssemblySlow)
DllImportEntry(RuntimeTypeHandle_GetModuleSlow)
DllImportEntry(RuntimeTypeHandle_GetNumVirtualsAndStaticVirtuals)
DllImportEntry(RuntimeTypeHandle_VerifyInterfaceIsImplemented)
DllImportEntry(RuntimeTypeHandle_GetInterfaceMethodImplementation)
Expand Down Expand Up @@ -158,6 +160,7 @@ static const Entry s_QCall[] =
DllImportEntry(ModuleHandle_ResolveMethod)
DllImportEntry(ModuleHandle_ResolveField)
DllImportEntry(ModuleHandle_GetPEKind)
DllImportEntry(AssemblyHandle_GetManifestModuleSlow)
DllImportEntry(TypeBuilder_DefineGenericParam)
DllImportEntry(TypeBuilder_DefineType)
DllImportEntry(TypeBuilder_SetParentType)
Expand Down
127 changes: 63 additions & 64 deletions src/coreclr/vm/runtimehandles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,43 +161,6 @@ NOINLINE static ReflectClassBaseObject* GetRuntimeTypeHelper(LPVOID __me, TypeHa

#define RETURN_CLASS_OBJECT(typeHandle, keepAlive) FC_INNER_RETURN(ReflectClassBaseObject*, GetRuntimeTypeHelper(__me, typeHandle, keepAlive))

NOINLINE ReflectModuleBaseObject* GetRuntimeModuleHelper(LPVOID __me, Module *pModule, OBJECTREF keepAlive)
{
FC_INNER_PROLOG_NO_ME_SETUP();
if (pModule == NULL)
return NULL;

OBJECTREF refModule = pModule->GetExposedObjectIfExists();
if (refModule != NULL)
return (ReflectModuleBaseObject*)OBJECTREFToObject(refModule);

HELPER_METHOD_FRAME_BEGIN_RET_ATTRIB_1(Frame::FRAME_ATTR_EXACT_DEPTH|Frame::FRAME_ATTR_CAPTURE_DEPTH_2, keepAlive);
refModule = pModule->GetExposedObject();
HELPER_METHOD_FRAME_END();

FC_INNER_EPILOG();
return (ReflectModuleBaseObject*)OBJECTREFToObject(refModule);
}

NOINLINE AssemblyBaseObject* GetRuntimeAssemblyHelper(LPVOID __me, Assembly *pAssembly, OBJECTREF keepAlive)
{
FC_INNER_PROLOG_NO_ME_SETUP();
if (pAssembly == NULL)
return NULL;

OBJECTREF refAssembly = (pAssembly != NULL) ? pAssembly->GetExposedObjectIfExists() : NULL;

if(refAssembly != NULL)
return (AssemblyBaseObject*)OBJECTREFToObject(refAssembly);

HELPER_METHOD_FRAME_BEGIN_RET_ATTRIB_1(Frame::FRAME_ATTR_EXACT_DEPTH|Frame::FRAME_ATTR_CAPTURE_DEPTH_2, keepAlive);
refAssembly = pAssembly->GetExposedObject();
HELPER_METHOD_FRAME_END();

FC_INNER_EPILOG();
return (AssemblyBaseObject*)OBJECTREFToObject(refAssembly);
}

FCIMPL1(ReflectClassBaseObject*, RuntimeTypeHandle::GetRuntimeType, EnregisteredTypeHandle th)
{
FCALL_CONTRACT;
Expand Down Expand Up @@ -298,23 +261,35 @@ FCIMPL1(INT32, RuntimeTypeHandle::GetCorElementType, ReflectClassBaseObject *pTy
}
FCIMPLEND

FCIMPL1(AssemblyBaseObject*, RuntimeTypeHandle::GetAssembly, ReflectClassBaseObject *pTypeUNSAFE) {
CONTRACTL {
FCALL_CHECK;
}
CONTRACTL_END;
FCIMPL1(AssemblyBaseObject*, RuntimeTypeHandle::GetAssemblyIfExists, ReflectClassBaseObject *pTypeUNSAFE)
{
FCALL_CONTRACT;

REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);

if (refType == NULL)
FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
return NULL;

Assembly* pAssembly = refType->GetType().GetAssembly();

FC_RETURN_ASSEMBLY_OBJECT(pAssembly, refType);
OBJECTREF refAssembly = pAssembly->GetExposedObjectIfExists();
return (AssemblyBaseObject*)OBJECTREFToObject(refAssembly);
}
FCIMPLEND

extern "C" void QCALLTYPE RuntimeTypeHandle_GetAssemblySlow(QCall::ObjectHandleOnStack type, QCall::ObjectHandleOnStack assembly)
{
QCALL_CONTRACT;

BEGIN_QCALL;
GCX_COOP();

if (type.Get() == NULL)
COMPlusThrow(kArgumentNullException, W("Arg_InvalidHandle"));

Assembly* pAssembly = ((REFLECTCLASSBASEREF)type.Get())->GetType().GetAssembly();
assembly.Set(pAssembly->GetExposedObject());
END_QCALL;
}

FCIMPL1(FC_BOOL_RET, RuntimeFieldHandle::AcquiresContextFromThis, FieldDesc* pField)
{
CONTRACTL {
Expand Down Expand Up @@ -351,25 +326,35 @@ FCIMPL1(Object*, RuntimeFieldHandle::GetLoaderAllocator, FieldDesc* pField)
}
FCIMPLEND

FCIMPL1(ReflectModuleBaseObject*, RuntimeTypeHandle::GetModule, ReflectClassBaseObject *pTypeUNSAFE) {
CONTRACTL {
FCALL_CHECK;
}
CONTRACTL_END;

Module *result;
FCIMPL1(ReflectModuleBaseObject*, RuntimeTypeHandle::GetModuleIfExists, ReflectClassBaseObject *pTypeUNSAFE)
{
FCALL_CONTRACT;

REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);

if (refType == NULL)
FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));

result = refType->GetType().GetModule();
return NULL;

FC_RETURN_MODULE_OBJECT(result, refType);
Module* pModule = refType->GetType().GetModule();
OBJECTREF refModule = pModule->GetExposedObjectIfExists();
return (ReflectModuleBaseObject*)OBJECTREFToObject(refModule);
}
FCIMPLEND

extern "C" void QCALLTYPE RuntimeTypeHandle_GetModuleSlow(QCall::ObjectHandleOnStack type, QCall::ObjectHandleOnStack module)
{
QCALL_CONTRACT;

BEGIN_QCALL;
GCX_COOP();

if (type.Get() == NULL)
COMPlusThrow(kArgumentNullException, W("Arg_InvalidHandle"));

Module* pModule = ((REFLECTCLASSBASEREF)type.Get())->GetType().GetModule();
module.Set(pModule->GetExposedObject());
END_QCALL;
}

FCIMPL1(ReflectClassBaseObject *, RuntimeTypeHandle::GetBaseType, ReflectClassBaseObject *pTypeUNSAFE) {
CONTRACTL {
FCALL_CHECK;
Expand Down Expand Up @@ -2679,17 +2664,17 @@ FCIMPL2(FieldDesc*, RuntimeFieldHandle::GetStaticFieldForGenericType, FieldDesc
}
FCIMPLEND

FCIMPL1(ReflectModuleBaseObject*, AssemblyHandle::GetManifestModule, AssemblyBaseObject* pAssemblyUNSAFE) {
FCIMPL1(ReflectModuleBaseObject*, AssemblyHandle::GetManifestModule, AssemblyBaseObject* pAssemblyUNSAFE)
{
FCALL_CONTRACT;

ASSEMBLYREF refAssembly = (ASSEMBLYREF)ObjectToOBJECTREF(pAssemblyUNSAFE);

if (refAssembly == NULL)
FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));

Assembly* currentAssembly = refAssembly->GetAssembly();
return NULL;

FC_RETURN_MODULE_OBJECT(currentAssembly->GetModule(), refAssembly);
Module* pModule = refAssembly->GetAssembly()->GetModule();
OBJECTREF refModule = pModule->GetExposedObjectIfExists();
return (ReflectModuleBaseObject*)OBJECTREFToObject(refModule);
}
FCIMPLEND

Expand All @@ -2716,6 +2701,20 @@ FCIMPL1(INT32, AssemblyHandle::GetToken, AssemblyBaseObject* pAssemblyUNSAFE) {
}
FCIMPLEND

extern "C" void QCALLTYPE AssemblyHandle_GetManifestModuleSlow(QCall::ObjectHandleOnStack assembly, QCall::ObjectHandleOnStack module)
{
QCALL_CONTRACT;

BEGIN_QCALL;
GCX_COOP();

if (assembly.Get() == NULL)
COMPlusThrow(kArgumentNullException, W("Arg_InvalidHandle"));

Module* pModule = ((ASSEMBLYREF)assembly.Get())->GetAssembly()->GetModule();
module.Set(pModule->GetExposedObject());
END_QCALL;
}

extern "C" void QCALLTYPE ModuleHandle_GetPEKind(QCall::ModuleHandle pModule, DWORD* pdwPEKind, DWORD* pdwMachine)
{
Expand Down
Loading

0 comments on commit b7b91cb

Please sign in to comment.