Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert some handle APIs from FCalls to fast FCall and slow QCall #107513

Merged
merged 1 commit into from
Sep 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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