@@ -329,6 +329,10 @@ void Module::NotifyEtwLoadFinished(HRESULT hr)
329329// It cannot throw or fail.
330330//
331331Module::Module (Assembly *pAssembly, PEAssembly *pPEAssembly)
332+ : m_pPEAssembly{pPEAssembly}
333+ , m_dwTransientFlags{CLASSES_FREED}
334+ , m_pAssembly{pAssembly}
335+ , m_hExposedObject{}
332336{
333337 CONTRACTL
334338 {
@@ -338,15 +342,12 @@ Module::Module(Assembly *pAssembly, PEAssembly *pPEAssembly)
338342 }
339343 CONTRACTL_END
340344
341- PREFIX_ASSUME (pAssembly != NULL );
345+ PREFIX_ASSUME (m_pAssembly != NULL );
342346
343347 m_loaderAllocator = NULL ;
344- m_pAssembly = pAssembly;
345- m_pPEAssembly = pPEAssembly;
346- m_dwTransientFlags = CLASSES_FREED;
347348 m_pDynamicMetadata = (TADDR)NULL ;
348349
349- pPEAssembly ->AddRef ();
350+ m_pPEAssembly ->AddRef ();
350351}
351352
352353uint32_t Module::GetNativeMetadataAssemblyCount ()
@@ -1147,6 +1148,11 @@ void Module::SetDomainAssembly(DomainAssembly *pDomainAssembly)
11471148 m_pDomainAssembly = pDomainAssembly;
11481149}
11491150
1151+ // ---------------------------------------------------------------------------------------
1152+ //
1153+ // Returns managed representation of the module (Module or ModuleBuilder).
1154+ // Returns NULL if the managed scout was already collected (see code:LoaderAllocator#AssemblyPhases).
1155+ //
11501156OBJECTREF Module::GetExposedObject ()
11511157{
11521158 CONTRACT (OBJECTREF)
@@ -1159,7 +1165,62 @@ OBJECTREF Module::GetExposedObject()
11591165 }
11601166 CONTRACT_END;
11611167
1162- RETURN GetDomainAssembly ()->GetExposedModuleObject ();
1168+ LoaderAllocator * pLoaderAllocator = GetLoaderAllocator ();
1169+
1170+ if (m_hExposedObject == (LOADERHANDLE)NULL )
1171+ {
1172+ // Atomically create a handle
1173+ LOADERHANDLE handle = pLoaderAllocator->AllocateHandle (NULL );
1174+
1175+ InterlockedCompareExchangeT (&m_hExposedObject, handle, static_cast <LOADERHANDLE>(0 ));
1176+ }
1177+
1178+ if (pLoaderAllocator->GetHandleValue (m_hExposedObject) == NULL )
1179+ {
1180+ REFLECTMODULEBASEREF refClass = NULL ;
1181+
1182+ // Will be true only if LoaderAllocator managed object was already collected and therefore we should
1183+ // return NULL
1184+ bool fIsLoaderAllocatorCollected = false ;
1185+
1186+ GCPROTECT_BEGIN (refClass);
1187+
1188+ refClass = (REFLECTMODULEBASEREF) AllocateObject (CoreLibBinder::GetClass (CLASS__MODULE));
1189+ refClass->SetModule (this );
1190+
1191+ // Attach the reference to the assembly to keep the LoaderAllocator for this collectible type
1192+ // alive as long as a reference to the module is kept alive.
1193+ if (GetAssembly () != NULL )
1194+ {
1195+ OBJECTREF refAssembly = GetAssembly ()->GetExposedObject ();
1196+ if ((refAssembly == NULL ) && GetAssembly ()->IsCollectible ())
1197+ {
1198+ fIsLoaderAllocatorCollected = true ;
1199+ }
1200+ refClass->SetAssembly (refAssembly);
1201+ }
1202+
1203+ pLoaderAllocator->CompareExchangeValueInHandle (m_hExposedObject, (OBJECTREF)refClass, NULL );
1204+ GCPROTECT_END ();
1205+
1206+ if (fIsLoaderAllocatorCollected )
1207+ { // The LoaderAllocator managed object was already collected, we cannot re-create it
1208+ // Note: We did not publish the allocated Module/ModuleBuilder object, it will get collected
1209+ // by GC
1210+ return NULL ;
1211+ }
1212+ }
1213+
1214+ RETURN pLoaderAllocator->GetHandleValue (m_hExposedObject);
1215+ }
1216+
1217+ OBJECTREF Module::GetExposedObjectIfExists ()
1218+ {
1219+ LIMITED_METHOD_CONTRACT;
1220+
1221+ OBJECTREF objRet = NULL ;
1222+ GET_LOADERHANDLE_VALUE_FAST (GetLoaderAllocator (), m_hExposedObject, &objRet);
1223+ return objRet;
11631224}
11641225
11651226//
@@ -2411,6 +2472,9 @@ Module *Module::GetModuleIfLoaded(mdFile kFile)
24112472
24122473 ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE ();
24132474
2475+ if (kFile == mdFileNil)
2476+ return this ;
2477+
24142478 // Handle the module ref case
24152479 if (TypeFromToken (kFile ) == mdtModuleRef)
24162480 {
@@ -2423,19 +2487,14 @@ Module *Module::GetModuleIfLoaded(mdFile kFile)
24232487 RETURN GetAssembly ()->GetModule ()->GetModuleIfLoaded (mdFileNil);
24242488 }
24252489
2426- if (kFile == mdFileNil)
2427- {
2428- return this ;
2429- }
2430-
24312490 RETURN NULL ;
24322491}
24332492
24342493#ifndef DACCESS_COMPILE
24352494
2436- DomainAssembly *ModuleBase::LoadModule (mdFile kFile )
2495+ Module *ModuleBase::LoadModule (mdFile kFile )
24372496{
2438- CONTRACT (DomainAssembly *)
2497+ CONTRACT (Module *)
24392498 {
24402499 INSTANCE_CHECK;
24412500 THROWS;
0 commit comments