diff options
author | Jan Vorlicek <janvorli@microsoft.com> | 2018-08-23 02:42:43 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-08-23 02:42:43 +0200 |
commit | 8cd4b39a42c1c7cf37502357e6a4cb2888f5dfd7 (patch) | |
tree | a767facb00becfc9b6b9f0c3a8d731e566e3d1c3 /src/vm/assemblynative.cpp | |
parent | 8013a4b6786d9e6618f8ed36bd0a473aa17b72aa (diff) | |
download | coreclr-8cd4b39a42c1c7cf37502357e6a4cb2888f5dfd7.tar.gz coreclr-8cd4b39a42c1c7cf37502357e6a4cb2888f5dfd7.tar.bz2 coreclr-8cd4b39a42c1c7cf37502357e6a4cb2888f5dfd7.zip |
Enable unloading of AssemblyLoadContext (#18476)
Enable assembly unloading
* Allow PInvoke methods on collectible assemblies
* Fix test unloadability
Several hundreds of tests were using Helper class that created
GCHandle, but never freed it. That prevented unloading of those
tests. The change modifies the Helper class to keep the handle
in a finalizable object.
Several GCHandle related tests were not freeing the GCHandle they
allocated, so this change adds freeing them to enable the unloading.
* Add missing error messages to the resources
* Fix shuffle thunk cache for unloadability
* Add GetLoaderAllocator to ICLRPrivBinder
Diffstat (limited to 'src/vm/assemblynative.cpp')
-rw-r--r-- | src/vm/assemblynative.cpp | 57 |
1 files changed, 55 insertions, 2 deletions
diff --git a/src/vm/assemblynative.cpp b/src/vm/assemblynative.cpp index be1cbc39b9..e658f25822 100644 --- a/src/vm/assemblynative.cpp +++ b/src/vm/assemblynative.cpp @@ -1184,7 +1184,8 @@ void QCALLTYPE AssemblyNative::GetImageRuntimeVersion(QCall::AssemblyHandle pAss } /*static*/ -INT_PTR QCALLTYPE AssemblyNative::InitializeAssemblyLoadContext(INT_PTR ptrManagedAssemblyLoadContext, BOOL fRepresentsTPALoadContext) + +INT_PTR QCALLTYPE AssemblyNative::InitializeAssemblyLoadContext(INT_PTR ptrManagedAssemblyLoadContext, BOOL fRepresentsTPALoadContext, BOOL fIsCollectible) { QCALL_CONTRACT; @@ -1203,7 +1204,41 @@ INT_PTR QCALLTYPE AssemblyNative::InitializeAssemblyLoadContext(INT_PTR ptrManag { // Initialize a custom Assembly Load Context CLRPrivBinderAssemblyLoadContext *pBindContext = NULL; - IfFailThrow(CLRPrivBinderAssemblyLoadContext::SetupContext(pCurDomain->GetId().m_dwId, pTPABinderContext, ptrManagedAssemblyLoadContext, &pBindContext)); + + AssemblyLoaderAllocator* loaderAllocator = NULL; + OBJECTHANDLE loaderAllocatorHandle = NULL; + + if (fIsCollectible) + { + // Create a new AssemblyLoaderAllocator for an AssemblyLoadContext + loaderAllocator = new AssemblyLoaderAllocator(); + loaderAllocator->SetCollectible(); + + GCX_COOP(); + LOADERALLOCATORREF pManagedLoaderAllocator = NULL; + GCPROTECT_BEGIN(pManagedLoaderAllocator); + { + GCX_PREEMP(); + // Some of the initialization functions are not virtual. Call through the derived class + // to prevent calling the base class version. + loaderAllocator->Init(pCurDomain); + loaderAllocator->InitVirtualCallStubManager(pCurDomain); + + // Setup the managed proxy now, but do not actually transfer ownership to it. + // Once everything is setup and nothing can fail anymore, the ownership will be + // atomically transfered by call to LoaderAllocator::ActivateManagedTracking(). + loaderAllocator->SetupManagedTracking(&pManagedLoaderAllocator); + } + + // Create a strong handle to the LoaderAllocator + loaderAllocatorHandle = pCurDomain->CreateHandle(pManagedLoaderAllocator); + + GCPROTECT_END(); + + loaderAllocator->ActivateManagedTracking(); + } + + IfFailThrow(CLRPrivBinderAssemblyLoadContext::SetupContext(pCurDomain->GetId().m_dwId, pTPABinderContext, loaderAllocator, loaderAllocatorHandle, ptrManagedAssemblyLoadContext, &pBindContext)); ptrNativeAssemblyLoadContext = reinterpret_cast<INT_PTR>(pBindContext); } else @@ -1227,6 +1262,24 @@ INT_PTR QCALLTYPE AssemblyNative::InitializeAssemblyLoadContext(INT_PTR ptrManag } /*static*/ +void QCALLTYPE AssemblyNative::PrepareForAssemblyLoadContextRelease(INT_PTR ptrNativeAssemblyLoadContext, INT_PTR ptrManagedStrongAssemblyLoadContext) +{ + QCALL_CONTRACT; + + BOOL fDestroyed = FALSE; + + BEGIN_QCALL; + + + { + GCX_COOP(); + reinterpret_cast<CLRPrivBinderAssemblyLoadContext *>(ptrNativeAssemblyLoadContext)->PrepareForLoadContextRelease(ptrManagedStrongAssemblyLoadContext); + } + + END_QCALL; +} + +/*static*/ BOOL QCALLTYPE AssemblyNative::OverrideDefaultAssemblyLoadContextForCurrentDomain(INT_PTR ptrNativeAssemblyLoadContext) { QCALL_CONTRACT; |