diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs index f9c11e07891095..48ebce7eb9e4cc 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs @@ -252,15 +252,16 @@ public override IEnumerable DefinedTypes get => GetManifestModule().GetDefinedTypes(); } - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_GetIsCollectible")] - internal static partial Interop.BOOL GetIsCollectible(QCallAssembly assembly); + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern bool GetIsCollectible(IntPtr assembly); public override bool IsCollectible { get { - RuntimeAssembly runtimeAssembly = this; - return GetIsCollectible(new QCallAssembly(ref runtimeAssembly)) != Interop.BOOL.FALSE; + bool isCollectible = GetIsCollectible(GetUnderlyingNativeHandle()); + GC.KeepAlive(this); // We directly pass the native handle above - make sure this object stays alive for the call + return isCollectible; } } 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 16ff331c2fdd7c..09c817b6346322 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 @@ -319,7 +319,15 @@ internal void InvokePropertySetter(object? obj, BindingFlags invokeAttr, Binder? public override ParameterInfo ReturnParameter => FetchReturnParameter(); - public override bool IsCollectible => RuntimeMethodHandle.GetIsCollectible(new RuntimeMethodHandleInternal(m_handle)) != Interop.BOOL.FALSE; + public override bool IsCollectible + { + get + { + bool isCollectible = RuntimeMethodHandle.IsCollectible(new RuntimeMethodHandleInternal(m_handle)); + GC.KeepAlive(this); // We directly pass the native handle above - make sure this object stays alive for the call + return isCollectible; + } + } public override MethodInfo GetBaseDefinition() { diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs index 95ceb043c386cc..9fa1f1f004d9b5 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs @@ -781,6 +781,7 @@ internal unsafe struct MethodTable private const uint enum_flag_HasTypeEquivalence = 0x02000000; #endif // FEATURE_TYPEEQUIVALENCE private const uint enum_flag_HasFinalizer = 0x00100000; + private const uint enum_flag_Collectible = 0x00200000; private const uint enum_flag_Category_Mask = 0x000F0000; private const uint enum_flag_Category_ValueType = 0x00040000; private const uint enum_flag_Category_Nullable = 0x00050000; @@ -841,6 +842,8 @@ internal unsafe struct MethodTable public bool HasFinalizer => (Flags & enum_flag_HasFinalizer) != 0; + public bool IsCollectible => (Flags & enum_flag_Collectible) != 0; + internal static bool AreSameType(MethodTable* mt1, MethodTable* mt2) => mt1 == mt2; public bool HasDefaultConstructor => (Flags & (enum_flag_HasComponentSize | enum_flag_HasDefaultCtor)) == enum_flag_HasDefaultCtor; @@ -978,6 +981,8 @@ internal unsafe struct TypeDesc private uint _typeAndFlags; private nint _exposedClassObject; + private const uint enum_flag_IsCollectible = 0x00000100; + public RuntimeType? ExposedClassObject { get @@ -985,6 +990,14 @@ public RuntimeType? ExposedClassObject return *(RuntimeType*)Unsafe.AsPointer(ref _exposedClassObject); } } + + public bool IsCollectible + { + get + { + return (_typeAndFlags & enum_flag_IsCollectible) != 0; + } + } } [StructLayout(LayoutKind.Sequential)] diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs index e59be872265d3b..19b63c1574d750 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs @@ -824,9 +824,6 @@ internal RuntimeType MakePointer() return type!; } - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "RuntimeTypeHandle_IsCollectible")] - internal static partial Interop.BOOL IsCollectible(QCallTypeHandle handle); - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "RuntimeTypeHandle_GetGenericTypeDefinition")] internal static partial void GetGenericTypeDefinition(QCallTypeHandle type, ObjectHandleOnStack retType); @@ -1053,8 +1050,8 @@ public IntPtr GetFunctionPointer() return ptr; } - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "RuntimeMethodHandle_GetIsCollectible")] - internal static partial Interop.BOOL GetIsCollectible(RuntimeMethodHandleInternal handle); + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern bool IsCollectible(RuntimeMethodHandleInternal method); [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "RuntimeMethodHandle_IsCAVisibleFromDecoratedType")] internal static partial Interop.BOOL IsCAVisibleFromDecoratedType( diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs index c4de3a72051b92..cd790f29de209c 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs @@ -3227,12 +3227,15 @@ public override MemberInfo GetMemberWithSameMetadataDefinitionAs(MemberInfo memb #region Identity - public sealed override bool IsCollectible + public sealed override unsafe bool IsCollectible { get { - RuntimeType thisType = this; - return RuntimeTypeHandle.IsCollectible(new QCallTypeHandle(ref thisType)) != Interop.BOOL.FALSE; + TypeHandle th = GetNativeTypeHandle(); + + bool isCollectible = th.IsTypeDesc ? th.AsTypeDesc()->IsCollectible : th.AsMethodTable()->IsCollectible; + GC.KeepAlive(this); + return isCollectible; } } diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index e8344aa85520da..26f35709a78604 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -742,20 +742,18 @@ extern "C" void QCALLTYPE AssemblyNative_GetModules(QCall::AssemblyHandle pAssem END_QCALL; } -extern "C" BOOL QCALLTYPE AssemblyNative_GetIsCollectible(QCall::AssemblyHandle pAssembly) +FCIMPL1(FC_BOOL_RET, AssemblyNative::GetIsCollectible, Assembly* pAssembly) { - QCALL_CONTRACT; - - BOOL retVal = FALSE; - - BEGIN_QCALL; - - retVal = pAssembly->IsCollectible(); - - END_QCALL; + CONTRACTL + { + FCALL_CHECK; + PRECONDITION(CheckPointer(pAssembly)); + } + CONTRACTL_END; - return retVal; + FC_RETURN_BOOL(pAssembly->IsCollectible()); } +FCIMPLEND extern volatile uint32_t g_cAssemblies; diff --git a/src/coreclr/vm/assemblynative.hpp b/src/coreclr/vm/assemblynative.hpp index 4a5a930db6f2ab..cba6b322391d2a 100644 --- a/src/coreclr/vm/assemblynative.hpp +++ b/src/coreclr/vm/assemblynative.hpp @@ -32,6 +32,9 @@ class AssemblyNative static FCDECL1(FC_BOOL_RET, GetIsDynamic, Assembly* pAssembly); + + static + FCDECL1(FC_BOOL_RET, GetIsCollectible, Assembly* pAssembly); }; extern "C" uint32_t QCALLTYPE AssemblyNative_GetAssemblyCount(); @@ -108,8 +111,6 @@ extern "C" void QCALLTYPE AssemblyNative_GetEntryPoint(QCall::AssemblyHandle pAs extern "C" void QCALLTYPE AssemblyNative_GetImageRuntimeVersion(QCall::AssemblyHandle pAssembly, QCall::StringHandleOnStack retString); -extern "C" BOOL QCALLTYPE AssemblyNative_GetIsCollectible(QCall::AssemblyHandle pAssembly); - extern "C" INT_PTR QCALLTYPE AssemblyNative_InitializeAssemblyLoadContext(INT_PTR ptrAssemblyLoadContext, BOOL fRepresentsTPALoadContext, BOOL fIsCollectible); extern "C" void QCALLTYPE AssemblyNative_PrepareForAssemblyLoadContextRelease(INT_PTR ptrNativeAssemblyBinder, INT_PTR ptrManagedStrongAssemblyLoadContext); diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index e88372128995be..1bde00305e1bde 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -134,6 +134,7 @@ FCFuncEnd() FCFuncStart(gRuntimeMethodHandle) FCFuncElement("GetImplAttributes", RuntimeMethodHandle::GetImplAttributes) + FCFuncElement("IsCollectible", RuntimeMethodHandle::IsCollectible) FCFuncElement("GetAttributes", RuntimeMethodHandle::GetAttributes) FCFuncElement("GetMethodTable", RuntimeMethodHandle::GetMethodTable) FCFuncElement("GetSlot", RuntimeMethodHandle::GetSlot) @@ -166,6 +167,7 @@ FCFuncEnd() FCFuncStart(gRuntimeAssemblyFuncs) FCFuncElement("GetIsDynamic", AssemblyNative::GetIsDynamic) + FCFuncElement("GetIsCollectible", AssemblyNative::GetIsCollectible) FCFuncElement("GetManifestModule", AssemblyHandle::GetManifestModule) FCFuncElement("GetTokenInternal", AssemblyHandle::GetTokenInternal) FCFuncEnd() diff --git a/src/coreclr/vm/method.cpp b/src/coreclr/vm/method.cpp index 15dd4f4abc3e2d..93920ad4975114 100644 --- a/src/coreclr/vm/method.cpp +++ b/src/coreclr/vm/method.cpp @@ -3856,9 +3856,15 @@ MethodDesc *MethodDesc::GetInterfaceMD() } #endif // !DACCESS_COMPILE +bool MethodDesc::IsCollectible() +{ + LIMITED_METHOD_DAC_CONTRACT; + return GetLoaderAllocator()->IsCollectible(); +} + PTR_LoaderAllocator MethodDesc::GetLoaderAllocator() { - WRAPPER_NO_CONTRACT; + LIMITED_METHOD_DAC_CONTRACT; return GetLoaderModule()->GetLoaderAllocator(); } diff --git a/src/coreclr/vm/method.hpp b/src/coreclr/vm/method.hpp index 27720b14df2e17..07683f725f4a8d 100644 --- a/src/coreclr/vm/method.hpp +++ b/src/coreclr/vm/method.hpp @@ -595,6 +595,8 @@ class MethodDesc MethodDescBackpatchInfoTracker* GetBackpatchInfoTracker(); + bool IsCollectible(); + PTR_LoaderAllocator GetLoaderAllocator(); Module* GetLoaderModule(); diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index e2dd498b8b483a..b4f9dbb0e0ad16 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -122,7 +122,6 @@ static const Entry s_QCall[] = DllImportEntry(RuntimeTypeHandle_MakeByRef) DllImportEntry(RuntimeTypeHandle_MakeSZArray) DllImportEntry(RuntimeTypeHandle_MakeArray) - DllImportEntry(RuntimeTypeHandle_IsCollectible) DllImportEntry(RuntimeTypeHandle_GetConstraints) DllImportEntry(RuntimeTypeHandle_GetArgumentTypesFromFunctionPointer) DllImportEntry(RuntimeTypeHandle_GetAssemblySlow) @@ -159,7 +158,6 @@ static const Entry s_QCall[] = DllImportEntry(RuntimeMethodHandle_InvokeMethod) DllImportEntry(RuntimeMethodHandle_ConstructInstantiation) DllImportEntry(RuntimeMethodHandle_GetFunctionPointer) - DllImportEntry(RuntimeMethodHandle_GetIsCollectible) DllImportEntry(RuntimeMethodHandle_GetMethodInstantiation) DllImportEntry(RuntimeMethodHandle_GetTypicalMethodDefinition) DllImportEntry(RuntimeMethodHandle_StripMethodInstantiation) @@ -249,7 +247,6 @@ static const Entry s_QCall[] = DllImportEntry(AssemblyNative_GetExportedTypes) DllImportEntry(AssemblyNative_GetEntryPoint) DllImportEntry(AssemblyNative_GetImageRuntimeVersion) - DllImportEntry(AssemblyNative_GetIsCollectible) DllImportEntry(AssemblyNative_InternalTryGetRawMetadata) DllImportEntry(AssemblyNative_ApplyUpdate) DllImportEntry(AssemblyNative_IsApplyUpdateSupported) diff --git a/src/coreclr/vm/runtimehandles.cpp b/src/coreclr/vm/runtimehandles.cpp index f408fe64a92796..9b2e05cb658a99 100644 --- a/src/coreclr/vm/runtimehandles.cpp +++ b/src/coreclr/vm/runtimehandles.cpp @@ -1092,19 +1092,6 @@ extern "C" void QCALLTYPE RuntimeTypeHandle_MakeByRef(QCall::TypeHandle pTypeHan return; } -extern "C" BOOL QCALLTYPE RuntimeTypeHandle_IsCollectible(QCall::TypeHandle pTypeHandle) -{ - QCALL_CONTRACT; - - BOOL retVal = FALSE; - - BEGIN_QCALL; - retVal = pTypeHandle.AsTypeHandle().GetLoaderAllocator()->IsCollectible(); - END_QCALL; - - return retVal; -} - extern "C" void QCALLTYPE RuntimeTypeHandle_Instantiate(QCall::TypeHandle pTypeHandle, TypeHandle * pInstArray, INT32 cInstArray, QCall::ObjectHandleOnStack retType) { QCALL_CONTRACT; @@ -1292,21 +1279,6 @@ extern "C" void * QCALLTYPE RuntimeMethodHandle_GetFunctionPointer(MethodDesc * return funcPtr; } -extern "C" BOOL QCALLTYPE RuntimeMethodHandle_GetIsCollectible(MethodDesc* pMethod) -{ - QCALL_CONTRACT; - - BOOL isCollectible = FALSE; - - BEGIN_QCALL; - - isCollectible = pMethod->GetLoaderAllocator()->IsCollectible(); - - END_QCALL; - - return isCollectible; -} - FCIMPL1(LPCUTF8, RuntimeMethodHandle::GetUtf8Name, MethodDesc* pMethod) { CONTRACTL @@ -1320,6 +1292,14 @@ FCIMPL1(LPCUTF8, RuntimeMethodHandle::GetUtf8Name, MethodDesc* pMethod) } FCIMPLEND +FCIMPL1(FC_BOOL_RET, RuntimeMethodHandle::IsCollectible, MethodDesc *pMethod) +{ + FCALL_CONTRACT; + _ASSERTE(pMethod != NULL); + FC_RETURN_BOOL(pMethod->IsCollectible()); +} +FCIMPLEND + FCIMPL1(INT32, RuntimeMethodHandle::GetAttributes, MethodDesc *pMethod) { FCALL_CONTRACT; diff --git a/src/coreclr/vm/runtimehandles.h b/src/coreclr/vm/runtimehandles.h index a35021f74375d2..4af0a340d22f72 100644 --- a/src/coreclr/vm/runtimehandles.h +++ b/src/coreclr/vm/runtimehandles.h @@ -159,7 +159,6 @@ extern "C" void QCALLTYPE RuntimeTypeHandle_MakeByRef(QCall::TypeHandle pTypeHan extern "C" void QCALLTYPE RuntimeTypeHandle_MakePointer(QCall::TypeHandle pTypeHandle, QCall::ObjectHandleOnStack retType); extern "C" void QCALLTYPE RuntimeTypeHandle_MakeSZArray(QCall::TypeHandle pTypeHandle, QCall::ObjectHandleOnStack retType); extern "C" void QCALLTYPE RuntimeTypeHandle_MakeArray(QCall::TypeHandle pTypeHandle, INT32 rank, QCall::ObjectHandleOnStack retType); -extern "C" BOOL QCALLTYPE RuntimeTypeHandle_IsCollectible(QCall::TypeHandle pTypeHandle); extern "C" void QCALLTYPE RuntimeTypeHandle_PrepareMemberInfoCache(QCall::TypeHandle pMemberInfoCache); extern "C" void QCALLTYPE RuntimeTypeHandle_ConstructName(QCall::TypeHandle pTypeHandle, DWORD format, QCall::StringHandleOnStack retString); extern "C" void QCALLTYPE RuntimeTypeHandle_GetInterfaces(MethodTable* pMT, QCall::ObjectHandleOnStack result); @@ -185,6 +184,7 @@ extern "C" void QCALLTYPE RuntimeTypeHandle_RegisterCollectibleTypeDependency(QC class RuntimeMethodHandle { public: + static FCDECL1(FC_BOOL_RET, IsCollectible, MethodDesc *pMethod); static FCDECL1(INT32, GetAttributes, MethodDesc *pMethod); static FCDECL1(INT32, GetImplAttributes, ReflectMethodObject *pMethodUNSAFE); static FCDECL1(MethodTable*, GetMethodTable, MethodDesc *pMethod); diff --git a/src/coreclr/vm/typedesc.h b/src/coreclr/vm/typedesc.h index 8cff26f064e657..1edcb3f1ae0971 100644 --- a/src/coreclr/vm/typedesc.h +++ b/src/coreclr/vm/typedesc.h @@ -32,10 +32,10 @@ class TypeDesc { public: #ifndef DACCESS_COMPILE - TypeDesc(CorElementType type) { + TypeDesc(CorElementType type, bool isCollectible) { LIMITED_METHOD_CONTRACT; - _typeAndFlags = type; + _typeAndFlags = type | (isCollectible ? enum_flag_IsCollectible : 0); } #endif @@ -112,14 +112,19 @@ class TypeDesc // Is actually ParamTypeDesc (BYREF, PTR) BOOL HasTypeParam(); + bool IsCollectible() const + { + LIMITED_METHOD_CONTRACT; + return (_typeAndFlags & TypeDesc::enum_flag_IsCollectible) != 0; + } - BOOL HasTypeEquivalence() const + bool HasTypeEquivalence() const { LIMITED_METHOD_CONTRACT; return (_typeAndFlags & TypeDesc::enum_flag_HasTypeEquivalence) != 0; } - BOOL IsFullyLoaded() const + bool IsFullyLoaded() const { LIMITED_METHOD_CONTRACT; @@ -186,7 +191,7 @@ class TypeDesc // See methodtable.h for details of the flags with the same name there enum { - // unused = 0x00000100, + enum_flag_IsCollectible = 0x00000100, // unused = 0x00000200, // unused = 0x00000400, // unused = 0x00000800, @@ -228,7 +233,7 @@ class ParamTypeDesc : public TypeDesc { public: #ifndef DACCESS_COMPILE ParamTypeDesc(CorElementType type, TypeHandle arg) - : TypeDesc(type), m_Arg(arg) { + : TypeDesc(type, arg.IsCollectible()), m_Arg(arg) { LIMITED_METHOD_CONTRACT; @@ -291,7 +296,7 @@ class TypeVarTypeDesc : public TypeDesc #ifndef DACCESS_COMPILE TypeVarTypeDesc(PTR_Module pModule, mdToken typeOrMethodDef, unsigned int index, mdGenericParam token) : - TypeDesc(TypeFromToken(typeOrMethodDef) == mdtTypeDef ? ELEMENT_TYPE_VAR : ELEMENT_TYPE_MVAR) + TypeDesc(TypeFromToken(typeOrMethodDef) == mdtTypeDef ? ELEMENT_TYPE_VAR : ELEMENT_TYPE_MVAR, pModule->IsCollectible()) { CONTRACTL { @@ -416,7 +421,7 @@ class FnPtrTypeDesc : public TypeDesc public: #ifndef DACCESS_COMPILE FnPtrTypeDesc(BYTE callConv, DWORD numArgs, TypeHandle * retAndArgTypes, PTR_Module pLoaderModule) - : TypeDesc(ELEMENT_TYPE_FNPTR), m_pLoaderModule(pLoaderModule), m_NumArgs(numArgs), m_CallConv(callConv) + : TypeDesc(ELEMENT_TYPE_FNPTR, pLoaderModule->IsCollectible()), m_pLoaderModule(pLoaderModule), m_NumArgs(numArgs), m_CallConv(callConv) { LIMITED_METHOD_CONTRACT; for (DWORD i = 0; i <= numArgs; i++) diff --git a/src/coreclr/vm/typehandle.cpp b/src/coreclr/vm/typehandle.cpp index b2511bf8640aab..05b80e1fd662fa 100644 --- a/src/coreclr/vm/typehandle.cpp +++ b/src/coreclr/vm/typehandle.cpp @@ -256,10 +256,7 @@ PTR_Module TypeHandle::GetLoaderModule() const PTR_LoaderAllocator TypeHandle::GetLoaderAllocator() const { - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_NOTRIGGER; - STATIC_CONTRACT_FORBID_FAULT; - STATIC_CONTRACT_SUPPORTS_DAC; + LIMITED_METHOD_DAC_CONTRACT; if (IsTypeDesc()) { @@ -271,6 +268,20 @@ PTR_LoaderAllocator TypeHandle::GetLoaderAllocator() const } } +bool TypeHandle::IsCollectible() const +{ + LIMITED_METHOD_DAC_CONTRACT; + + if (IsTypeDesc()) + { + return AsTypeDesc()->IsCollectible(); + } + else + { + return AsMethodTable()->Collectible(); + } +} + BOOL TypeHandle::IsSharedByGenericInstantiations() const { LIMITED_METHOD_DAC_CONTRACT; diff --git a/src/coreclr/vm/typehandle.h b/src/coreclr/vm/typehandle.h index 77922010549645..c4fb31c7324be4 100644 --- a/src/coreclr/vm/typehandle.h +++ b/src/coreclr/vm/typehandle.h @@ -414,6 +414,8 @@ class TypeHandle PTR_LoaderAllocator GetLoaderAllocator() const; + bool IsCollectible() const; + // Get the class token, assuming the type handle represents a named type, // i.e. a class, a value type, a generic instantiation etc. inline mdTypeDef GetCl() const; diff --git a/src/coreclr/vm/virtualcallstub.cpp b/src/coreclr/vm/virtualcallstub.cpp index c70f5d7bafed19..96160b3cacf20a 100644 --- a/src/coreclr/vm/virtualcallstub.cpp +++ b/src/coreclr/vm/virtualcallstub.cpp @@ -1876,7 +1876,7 @@ PCODE VirtualCallStubManager::ResolveWorker(StubCallSite* pCallSite, // We care about the following cases: // Call from any site -> collectible target - if (objectType->GetLoaderAllocator()->IsCollectible()) + if (objectType->Collectible()) { // The callee's manager pCalleeMgr = objectType->GetLoaderAllocator()->GetVirtualCallStubManager();