From b4650943618bfd06296c61f8f46bddce9b851015 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Mon, 14 Jan 2019 15:49:45 -0800 Subject: [PATCH] Custom Marshalers in custom-ALC-loaded assemblies results in types loaded from crossing ALCs (#21606) * Create repro for dotnet/coreclr#19654 * Update ICustomMarshaler.csproj * Update ICustomMarshaler.csproj * Clean up repro per feedback. * Add test case for different assemblies with the same CustomMarshaler name. * Move EEMarshalingData cache from AppDomain to LoaderAllocator. This fixes the custom-marshaler conflict when using unloadable assembly contexts. * Internalize the LoaderHeap* parameter. * Add the pointer to the requesting assembly to the hashtable key. * Fix linux-musl build break. * Move Crst out of FEATURE_COMINTEROP block. * Make sure to copy over the assembly pointer to the key that's actually stored in the hash table. * Add comment for m_invokingAssembly. * Move all usages of EEMarshallingData to hang off the correct loader allocator instead of always the global one. * Change to m_InteropDataCrst since this EEMarshallingData can be used in preemptive GC mode. * Always init m_InteropDataCrst (since it's used by EEMarshallingData as well as COM). * PR Feedback. * Remove extraneous inlines. --- src/vm/appdomain.cpp | 50 --------------- src/vm/appdomain.hpp | 10 --- src/vm/ceemain.cpp | 5 -- src/vm/cominterfacemarshaler.cpp | 4 +- src/vm/custommarshalerinfo.cpp | 14 +++-- src/vm/custommarshalerinfo.h | 22 ++++--- src/vm/dispparammarshaler.cpp | 2 +- src/vm/ilmarshalers.cpp | 72 +++++++++++----------- src/vm/ilmarshalers.h | 12 ++-- src/vm/interopconverter.cpp | 4 +- src/vm/interoputil.cpp | 6 +- src/vm/loaderallocator.cpp | 53 +++++++++++++++- src/vm/loaderallocator.hpp | 19 +++++- src/vm/mlinfo.cpp | 21 +++---- src/vm/mlinfo.h | 5 +- tests/src/Interop/CMakeLists.txt | 1 + .../ConflictingNames/CMakeLists.txt | 11 ++++ .../ConflictingNames/CustomMarshaler.cs | 54 ++++++++++++++++ .../ConflictingNames/CustomMarshaler.csproj | 28 +++++++++ .../ConflictingNames/CustomMarshaler2.csproj | 29 +++++++++ .../ConflictingNames/CustomMarshalerNative.cpp | 12 ++++ .../ConflictingNames/MultipleALCs.csproj | 35 +++++++++++ .../ICustomMarshaler/ConflictingNames/RunInALC.cs | 72 ++++++++++++++++++++++ .../ConflictingNames/SameNameDifferentAssembly.cs | 28 +++++++++ .../SameNameDifferentAssembly.csproj | 35 +++++++++++ .../{ => Primitives}/ICustomMarshaler.cs | 0 .../{ => Primitives}/ICustomMarshaler.csproj | 5 +- 27 files changed, 463 insertions(+), 146 deletions(-) create mode 100644 tests/src/Interop/ICustomMarshaler/ConflictingNames/CMakeLists.txt create mode 100644 tests/src/Interop/ICustomMarshaler/ConflictingNames/CustomMarshaler.cs create mode 100644 tests/src/Interop/ICustomMarshaler/ConflictingNames/CustomMarshaler.csproj create mode 100644 tests/src/Interop/ICustomMarshaler/ConflictingNames/CustomMarshaler2.csproj create mode 100644 tests/src/Interop/ICustomMarshaler/ConflictingNames/CustomMarshalerNative.cpp create mode 100644 tests/src/Interop/ICustomMarshaler/ConflictingNames/MultipleALCs.csproj create mode 100644 tests/src/Interop/ICustomMarshaler/ConflictingNames/RunInALC.cs create mode 100644 tests/src/Interop/ICustomMarshaler/ConflictingNames/SameNameDifferentAssembly.cs create mode 100644 tests/src/Interop/ICustomMarshaler/ConflictingNames/SameNameDifferentAssembly.csproj rename tests/src/Interop/ICustomMarshaler/{ => Primitives}/ICustomMarshaler.cs (100%) rename tests/src/Interop/ICustomMarshaler/{ => Primitives}/ICustomMarshaler.csproj (92%) diff --git a/src/vm/appdomain.cpp b/src/vm/appdomain.cpp index 37d9c84..0c2ebd6 100644 --- a/src/vm/appdomain.cpp +++ b/src/vm/appdomain.cpp @@ -711,8 +711,6 @@ BaseDomain::BaseDomain() m_handleStore = NULL; #endif - m_pMarshalingData = NULL; - #ifdef FEATURE_COMINTEROP m_pMngStdInterfacesInfo = NULL; m_pWinRtBinder = NULL; @@ -785,9 +783,6 @@ void BaseDomain::Init() m_crstAssemblyList.Init(CrstAssemblyList, CrstFlags( CRST_GC_NOTRIGGER_WHEN_TAKEN | CRST_DEBUGGER_THREAD | CRST_TAKEN_DURING_SHUTDOWN)); - // Initialize the EE marshaling data to NULL. - m_pMarshalingData = NULL; - #ifdef FEATURE_COMINTEROP // Allocate the managed standard interfaces information. m_pMngStdInterfacesInfo = new MngStdInterfacesInfo(); @@ -1805,51 +1800,6 @@ OBJECTREF AppDomain::GetMissingObject() #ifndef DACCESS_COMPILE -EEMarshalingData *BaseDomain::GetMarshalingData() -{ - CONTRACT (EEMarshalingData*) - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - INJECT_FAULT(COMPlusThrowOM()); - POSTCONDITION(CheckPointer(m_pMarshalingData)); - } - CONTRACT_END; - - if (!m_pMarshalingData) - { - // Take the lock - CrstHolder holder(&m_InteropDataCrst); - - if (!m_pMarshalingData) - { - LoaderHeap* pHeap = GetLoaderAllocator()->GetLowFrequencyHeap(); - m_pMarshalingData = new (pHeap) EEMarshalingData(this, pHeap, &m_DomainCrst); - } - } - - RETURN m_pMarshalingData; -} - -void BaseDomain::DeleteMarshalingData() -{ - CONTRACTL - { - NOTHROW; - GC_TRIGGERS; - MODE_ANY; - } - CONTRACTL_END; - - // We are in shutdown - no need to take any lock - if (m_pMarshalingData) - { - delete m_pMarshalingData; - m_pMarshalingData = NULL; - } -} - #ifndef CROSSGEN_COMPILE STRINGREF *BaseDomain::IsStringInterned(STRINGREF *pString) diff --git a/src/vm/appdomain.hpp b/src/vm/appdomain.hpp index 9b5d01a..8e13b51 100644 --- a/src/vm/appdomain.hpp +++ b/src/vm/appdomain.hpp @@ -1121,14 +1121,6 @@ public: return m_pWinRtBinder; } #endif // FEATURE_COMINTEROP - - //**************************************************************************************** - // This method returns marshaling data that the EE uses that is stored on a per app domain - // basis. - EEMarshalingData *GetMarshalingData(); - - // Deletes marshaling data at shutdown (which contains cached factories that needs to be released) - void DeleteMarshalingData(); #ifdef _DEBUG BOOL OwnDomainLocalBlockLock() @@ -1329,8 +1321,6 @@ protected: // The large heap handle table critical section. CrstExplicitInit m_LargeHeapHandleTableCrst; - EEMarshalingData *m_pMarshalingData; - #ifdef FEATURE_COMINTEROP // Information regarding the managed standard interfaces. MngStdInterfacesInfo *m_pMngStdInterfacesInfo; diff --git a/src/vm/ceemain.cpp b/src/vm/ceemain.cpp index defa4ac..6186a0c 100644 --- a/src/vm/ceemain.cpp +++ b/src/vm/ceemain.cpp @@ -1189,11 +1189,6 @@ void InnerCoEEShutDownCOM() // Release all of the RCWs in all contexts in all caches. ReleaseRCWsInCaches(NULL); - // Release all marshaling data in all AppDomains - AppDomainIterator i(TRUE); - while (i.Next()) - i.GetDomain()->DeleteMarshalingData(); - #ifdef FEATURE_APPX // Cleanup cached factory pointer in SynchronizationContextNative SynchronizationContextNative::Cleanup(); diff --git a/src/vm/cominterfacemarshaler.cpp b/src/vm/cominterfacemarshaler.cpp index a206222..5ee831c 100644 --- a/src/vm/cominterfacemarshaler.cpp +++ b/src/vm/cominterfacemarshaler.cpp @@ -745,7 +745,7 @@ void COMInterfaceMarshaler::MarshalToNonRCWType(OBJECTREF *poref) LPCWSTR pwszRawUri = hsRawUri.GetRawBuffer(&cchRawUri); gc.refRawURI = StringObject::NewString(pwszRawUri, cchRawUri); - UriMarshalingInfo *pUriMarshalingInfo = GetAppDomain()->GetMarshalingData()->GetUriMarshalingInfo(); + UriMarshalingInfo *pUriMarshalingInfo = GetAppDomain()->GetLoaderAllocator()->GetMarshalingData()->GetUriMarshalingInfo(); MethodDesc* pSystemUriCtorMD = pUriMarshalingInfo->GetSystemUriCtorMD(); MethodTable *pMTSystemUri = pUriMarshalingInfo->GetSystemUriType().AsMethodTable(); @@ -787,7 +787,7 @@ void COMInterfaceMarshaler::MarshalToNonRCWType(OBJECTREF *poref) case WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs: { MethodDesc *pMD; - EventArgsMarshalingInfo *pInfo = GetAppDomain()->GetMarshalingData()->GetEventArgsMarshalingInfo(); + EventArgsMarshalingInfo *pInfo = GetAppDomain()->GetLoaderAllocator()->GetMarshalingData()->GetEventArgsMarshalingInfo(); if (index == WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs) pMD = pInfo->GetWinRTNCCEventArgsToSystemNCCEventArgsMD(); diff --git a/src/vm/custommarshalerinfo.cpp b/src/vm/custommarshalerinfo.cpp index 9848487..d2d9ef2 100644 --- a/src/vm/custommarshalerinfo.cpp +++ b/src/vm/custommarshalerinfo.cpp @@ -23,7 +23,7 @@ // Implementation of the custom marshaler info class. //========================================================================== -CustomMarshalerInfo::CustomMarshalerInfo(BaseDomain *pDomain, TypeHandle hndCustomMarshalerType, TypeHandle hndManagedType, LPCUTF8 strCookie, DWORD cCookieStrBytes) +CustomMarshalerInfo::CustomMarshalerInfo(LoaderAllocator *pLoaderAllocator, TypeHandle hndCustomMarshalerType, TypeHandle hndManagedType, LPCUTF8 strCookie, DWORD cCookieStrBytes) : m_NativeSize(0) , m_hndManagedType(hndManagedType) , m_hndCustomMarshaler(NULL) @@ -38,7 +38,7 @@ CustomMarshalerInfo::CustomMarshalerInfo(BaseDomain *pDomain, TypeHandle hndCust THROWS; GC_TRIGGERS; MODE_COOPERATIVE; - PRECONDITION(CheckPointer(pDomain)); + PRECONDITION(CheckPointer(pLoaderAllocator)); } CONTRACTL_END; @@ -112,7 +112,7 @@ CustomMarshalerInfo::CustomMarshalerInfo(BaseDomain *pDomain, TypeHandle hndCust IDS_EE_NOCUSTOMMARSHALER, GetFullyQualifiedNameForClassW(hndCustomMarshalerType.GetMethodTable())); } - m_hndCustomMarshaler = pDomain->CreateHandle(CustomMarshalerObj); + m_hndCustomMarshaler = pLoaderAllocator->GetDomain()->CreateHandle(CustomMarshalerObj); // Retrieve the size of the native data. if (m_bDataIsByValue) @@ -367,6 +367,7 @@ EEHashEntry_t * EECMHelperHashtableHelper::AllocateEntry(EECMHelperHashtableKey cbEntry += S_SIZE_T(pKey->GetMarshalerTypeNameByteCount()); cbEntry += S_SIZE_T(pKey->GetCookieStringByteCount()); cbEntry += S_SIZE_T(pKey->GetMarshalerInstantiation().GetNumArgs()) * S_SIZE_T(sizeof(LPVOID)); + cbEntry += S_SIZE_T(sizeof(LPVOID)); // For EECMHelperHashtableKey::m_invokingAssembly if (cbEntry.IsOverflow()) return NULL; @@ -387,6 +388,7 @@ EEHashEntry_t * EECMHelperHashtableHelper::AllocateEntry(EECMHelperHashtableKey memcpy((void*)pEntryKey->m_strCookie, pKey->GetCookieString(), pKey->GetCookieStringByteCount()); memcpy((void*)pEntryKey->m_Instantiation.GetRawArgs(), pKey->GetMarshalerInstantiation().GetRawArgs(), pEntryKey->m_Instantiation.GetNumArgs() * sizeof(LPVOID)); + pEntryKey->m_invokingAssembly = pKey->GetInvokingAssembly(); } else { @@ -401,6 +403,7 @@ EEHashEntry_t * EECMHelperHashtableHelper::AllocateEntry(EECMHelperHashtableKey pEntryKey->m_cCookieStrBytes = pKey->GetCookieStringByteCount(); pEntryKey->m_strCookie = pKey->GetCookieString(); pEntryKey->m_Instantiation = Instantiation(pKey->GetMarshalerInstantiation()); + pEntryKey->m_invokingAssembly = pKey->GetInvokingAssembly(); } return pEntry; @@ -458,6 +461,9 @@ BOOL EECMHelperHashtableHelper::CompareKeys(EEHashEntry_t *pEntry, EECMHelperHas return FALSE; } + if (pEntryKey->GetInvokingAssembly() != pKey->GetInvokingAssembly()) + return FALSE; + return TRUE; } @@ -628,7 +634,7 @@ CustomMarshalerInfo *SharedCustomMarshalerHelper::GetCustomMarshalerInfo() CONTRACTL_END; // Retrieve the marshalling data for the current app domain. - EEMarshalingData *pMarshalingData = GetThread()->GetDomain()->GetMarshalingData(); + EEMarshalingData *pMarshalingData = GetThread()->GetDomain()->GetLoaderAllocator()->GetMarshalingData(); // Retrieve the custom marshaling information for the current shared custom // marshaling helper. diff --git a/src/vm/custommarshalerinfo.h b/src/vm/custommarshalerinfo.h index aecedf4..95390f2 100644 --- a/src/vm/custommarshalerinfo.h +++ b/src/vm/custommarshalerinfo.h @@ -36,7 +36,7 @@ class CustomMarshalerInfo { public: // Constructor and destructor. - CustomMarshalerInfo(BaseDomain* pDomain, TypeHandle hndCustomMarshalerType, TypeHandle hndManagedType, LPCUTF8 strCookie, DWORD cCookieStrBytes); + CustomMarshalerInfo(LoaderAllocator* pLoaderAllocator, TypeHandle hndCustomMarshalerType, TypeHandle hndManagedType, LPCUTF8 strCookie, DWORD cCookieStrBytes); ~CustomMarshalerInfo(); // CustomMarshalerInfo's are always allocated on the loader heap so we need to redefine @@ -114,51 +114,59 @@ private: typedef SList CMINFOLIST; +class Assembly; class EECMHelperHashtableKey { public: - EECMHelperHashtableKey(DWORD cMarshalerTypeNameBytes, LPCSTR strMarshalerTypeName, DWORD cCookieStrBytes, LPCSTR strCookie, Instantiation instantiation) + EECMHelperHashtableKey(DWORD cMarshalerTypeNameBytes, LPCSTR strMarshalerTypeName, DWORD cCookieStrBytes, LPCSTR strCookie, Instantiation instantiation, Assembly* invokingAssembly) : m_cMarshalerTypeNameBytes(cMarshalerTypeNameBytes) , m_strMarshalerTypeName(strMarshalerTypeName) , m_cCookieStrBytes(cCookieStrBytes) , m_strCookie(strCookie) , m_Instantiation(instantiation) + , m_invokingAssembly(invokingAssembly) { LIMITED_METHOD_CONTRACT; } - inline DWORD GetMarshalerTypeNameByteCount() const + DWORD GetMarshalerTypeNameByteCount() const { LIMITED_METHOD_CONTRACT; return m_cMarshalerTypeNameBytes; } - inline LPCSTR GetMarshalerTypeName() const + LPCSTR GetMarshalerTypeName() const { LIMITED_METHOD_CONTRACT; return m_strMarshalerTypeName; } - inline LPCSTR GetCookieString() const + LPCSTR GetCookieString() const { LIMITED_METHOD_CONTRACT; return m_strCookie; } - inline ULONG GetCookieStringByteCount() const + ULONG GetCookieStringByteCount() const { LIMITED_METHOD_CONTRACT; return m_cCookieStrBytes; } - inline Instantiation GetMarshalerInstantiation() const + Instantiation GetMarshalerInstantiation() const { LIMITED_METHOD_CONTRACT; return m_Instantiation; } + Assembly* GetInvokingAssembly() const + { + LIMITED_METHOD_CONTRACT; + return m_invokingAssembly; + } DWORD m_cMarshalerTypeNameBytes; LPCSTR m_strMarshalerTypeName; DWORD m_cCookieStrBytes; LPCSTR m_strCookie; Instantiation m_Instantiation; + Assembly* m_invokingAssembly; }; diff --git a/src/vm/dispparammarshaler.cpp b/src/vm/dispparammarshaler.cpp index 04d1566..06ae5bb 100644 --- a/src/vm/dispparammarshaler.cpp +++ b/src/vm/dispparammarshaler.cpp @@ -102,7 +102,7 @@ void DispParamOleColorMarshaler::MarshalNativeToManaged(VARIANT *pSrcVar, OBJECT // Box the System.Drawing.Color value class and give back the boxed object. TypeHandle hndColorType = - GetThread()->GetDomain()->GetMarshalingData()->GetOleColorMarshalingInfo()->GetColorType(); + GetThread()->GetDomain()->GetLoaderAllocator()->GetMarshalingData()->GetOleColorMarshalingInfo()->GetColorType(); *pDestObj = hndColorType.GetMethodTable()->Box(&MngColor); } diff --git a/src/vm/ilmarshalers.cpp b/src/vm/ilmarshalers.cpp index 1912e02..ea39f94 100644 --- a/src/vm/ilmarshalers.cpp +++ b/src/vm/ilmarshalers.cpp @@ -1511,8 +1511,8 @@ LocalDesc ILOleColorMarshaler::GetManagedType() { STANDARD_VM_CONTRACT; - BaseDomain* pDomain = m_pargs->m_pMarshalInfo->GetModule()->GetDomain(); - TypeHandle hndColorType = pDomain->GetMarshalingData()->GetOleColorMarshalingInfo()->GetColorType(); + LoaderAllocator* pLoader = m_pargs->m_pMarshalInfo->GetModule()->GetLoaderAllocator(); + TypeHandle hndColorType = pLoader->GetMarshalingData()->GetOleColorMarshalingInfo()->GetColorType(); // // value class @@ -1524,8 +1524,8 @@ void ILOleColorMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit { STANDARD_VM_CONTRACT; - BaseDomain* pDomain = m_pargs->m_pMarshalInfo->GetModule()->GetDomain(); - MethodDesc* pConvertMD = pDomain->GetMarshalingData()->GetOleColorMarshalingInfo()->GetSystemColorToOleColorMD(); + LoaderAllocator* pLoader = m_pargs->m_pMarshalInfo->GetModule()->GetLoaderAllocator(); + MethodDesc* pConvertMD = pLoader->GetMarshalingData()->GetOleColorMarshalingInfo()->GetSystemColorToOleColorMD(); EmitLoadManagedValue(pslILEmit); // int System.Drawing.ColorTranslator.ToOle(System.Drawing.Color c) @@ -1537,8 +1537,8 @@ void ILOleColorMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit { STANDARD_VM_CONTRACT; - BaseDomain* pDomain = m_pargs->m_pMarshalInfo->GetModule()->GetDomain(); - MethodDesc* pConvertMD = pDomain->GetMarshalingData()->GetOleColorMarshalingInfo()->GetOleColorToSystemColorMD(); + LoaderAllocator* pLoader = m_pargs->m_pMarshalInfo->GetModule()->GetLoaderAllocator(); + MethodDesc* pConvertMD = pLoader->GetMarshalingData()->GetOleColorMarshalingInfo()->GetOleColorToSystemColorMD(); EmitLoadNativeValue(pslILEmit); // System.Drawing.Color System.Drawing.ColorTranslator.FromOle(int oleColor) @@ -4802,15 +4802,15 @@ void ILHiddenLengthArrayMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* switch (m_pargs->na.m_redirectedTypeIndex) { case WinMDAdapter::RedirectedTypeIndex_System_Uri: - ILUriMarshaler::EmitConvertCLRUriToWinRTUri(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain()); + ILUriMarshaler::EmitConvertCLRUriToWinRTUri(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetLoaderAllocator()); break; case WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs: - ILNCCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain()); + ILNCCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetLoaderAllocator()); break; case WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs: - ILPCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain()); + ILPCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetLoaderAllocator()); break; default: UNREACHABLE(); @@ -4875,15 +4875,15 @@ void ILHiddenLengthArrayMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* switch (m_pargs->na.m_redirectedTypeIndex) { case WinMDAdapter::RedirectedTypeIndex_System_Uri: - ILUriMarshaler::EmitConvertWinRTUriToCLRUri(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain()); + ILUriMarshaler::EmitConvertWinRTUriToCLRUri(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetLoaderAllocator()); break; case WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs: - ILNCCEventArgsMarshaler::EmitConvertWinRTEventArgsToCLREventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain()); + ILNCCEventArgsMarshaler::EmitConvertWinRTEventArgsToCLREventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetLoaderAllocator()); break; case WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs: - ILPCEventArgsMarshaler::EmitConvertWinRTEventArgsToCLREventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain()); + ILPCEventArgsMarshaler::EmitConvertWinRTEventArgsToCLREventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetLoaderAllocator()); break; default: UNREACHABLE(); @@ -5674,8 +5674,8 @@ LocalDesc ILUriMarshaler::GetNativeType() LocalDesc ILUriMarshaler::GetManagedType() { STANDARD_VM_CONTRACT;; - BaseDomain* pDomain = m_pargs->m_pMarshalInfo->GetModule()->GetDomain(); - TypeHandle hndUriType = pDomain->GetMarshalingData()->GetUriMarshalingInfo()->GetSystemUriType(); + LoaderAllocator* pLoader = m_pargs->m_pMarshalInfo->GetModule()->GetLoaderAllocator(); + TypeHandle hndUriType = pLoader->GetMarshalingData()->GetUriMarshalingInfo()->GetSystemUriType(); return LocalDesc(hndUriType); // System.Uri } @@ -5688,11 +5688,11 @@ bool ILUriMarshaler::NeedsClearNative() // Note that this method expects the CLR Uri on top of the evaluation stack and leaves the WinRT Uri there. //static -void ILUriMarshaler::EmitConvertCLRUriToWinRTUri(ILCodeStream* pslILEmit, BaseDomain* pDomain) +void ILUriMarshaler::EmitConvertCLRUriToWinRTUri(ILCodeStream* pslILEmit, LoaderAllocator* pLoader) { STANDARD_VM_CONTRACT; - UriMarshalingInfo* marshalingInfo = pDomain->GetMarshalingData()->GetUriMarshalingInfo(); + UriMarshalingInfo* marshalingInfo = pLoader->GetMarshalingData()->GetUriMarshalingInfo(); ILCodeLabel *pNotNullLabel = pslILEmit->NewCodeLabel(); ILCodeLabel *pDoneLabel = pslILEmit->NewCodeLabel(); @@ -5720,17 +5720,17 @@ void ILUriMarshaler::EmitConvertContentsCLRToNative(ILCodeStream* pslILEmit) STANDARD_VM_CONTRACT; EmitLoadManagedValue(pslILEmit); - EmitConvertCLRUriToWinRTUri(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain()); + EmitConvertCLRUriToWinRTUri(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetLoaderAllocator()); EmitStoreNativeValue(pslILEmit); } // Note that this method expects the WinRT Uri on top of the evaluation stack and leaves the CLR Uri there. //static -void ILUriMarshaler::EmitConvertWinRTUriToCLRUri(ILCodeStream* pslILEmit, BaseDomain* pDomain) +void ILUriMarshaler::EmitConvertWinRTUriToCLRUri(ILCodeStream* pslILEmit, LoaderAllocator* pLoader) { STANDARD_VM_CONTRACT; - MethodDesc* pSystemUriCtorMD = pDomain->GetMarshalingData()->GetUriMarshalingInfo()->GetSystemUriCtorMD(); + MethodDesc* pSystemUriCtorMD = pLoader->GetMarshalingData()->GetUriMarshalingInfo()->GetSystemUriCtorMD(); ILCodeLabel *pNotNullLabel = pslILEmit->NewCodeLabel(); ILCodeLabel *pDoneLabel = pslILEmit->NewCodeLabel(); @@ -5758,7 +5758,7 @@ void ILUriMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmit) STANDARD_VM_CONTRACT; EmitLoadNativeValue(pslILEmit); - EmitConvertWinRTUriToCLRUri(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain()); + EmitConvertWinRTUriToCLRUri(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetLoaderAllocator()); EmitStoreManagedValue(pslILEmit); } @@ -5782,8 +5782,8 @@ LocalDesc ILNCCEventArgsMarshaler::GetManagedType() { STANDARD_VM_CONTRACT;; - BaseDomain *pDomain = m_pargs->m_pMarshalInfo->GetModule()->GetDomain(); - TypeHandle hndNCCEventArgType = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetSystemNCCEventArgsType(); + LoaderAllocator *pLoader = m_pargs->m_pMarshalInfo->GetModule()->GetLoaderAllocator(); + TypeHandle hndNCCEventArgType = pLoader->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetSystemNCCEventArgsType(); return LocalDesc(hndNCCEventArgType); // System.Collections.Specialized.NotifyCollectionChangedEventArgs } @@ -5797,11 +5797,11 @@ bool ILNCCEventArgsMarshaler::NeedsClearNative() // Note that this method expects the CLR NotifyCollectionChangedEventArgs on top of the evaluation stack and // leaves the WinRT NotifyCollectionChangedEventArgs IP there. //static -void ILNCCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(ILCodeStream *pslILEmit, BaseDomain *pDomain) +void ILNCCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(ILCodeStream *pslILEmit, LoaderAllocator* pLoader) { STANDARD_VM_CONTRACT; - MethodDesc *pConvertMD = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetSystemNCCEventArgsToWinRTNCCEventArgsMD(); + MethodDesc *pConvertMD = pLoader->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetSystemNCCEventArgsToWinRTNCCEventArgsMD(); // IntPtr System.Runtime.InteropServices.WindowsRuntime.NotifyCollectionChangedEventArgsMarshaler.ConvertToNative(NotifyCollectionChangedEventArgs) pslILEmit->EmitCALL(pslILEmit->GetToken(pConvertMD), 1, 1); @@ -5812,18 +5812,18 @@ void ILNCCEventArgsMarshaler::EmitConvertContentsCLRToNative(ILCodeStream *pslIL STANDARD_VM_CONTRACT; EmitLoadManagedValue(pslILEmit); - EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain()); + EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetLoaderAllocator()); EmitStoreNativeValue(pslILEmit); } // Note that this method expects the WinRT NotifyCollectionChangedEventArgs on top of the evaluation stack and // leaves the CLR NotifyCollectionChangedEventArgs there. //static -void ILNCCEventArgsMarshaler::EmitConvertWinRTEventArgsToCLREventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain) +void ILNCCEventArgsMarshaler::EmitConvertWinRTEventArgsToCLREventArgs(ILCodeStream* pslILEmit, LoaderAllocator* pLoader) { STANDARD_VM_CONTRACT; - MethodDesc *pConvertMD = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetWinRTNCCEventArgsToSystemNCCEventArgsMD(); + MethodDesc *pConvertMD = pLoader->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetWinRTNCCEventArgsToSystemNCCEventArgsMD(); // NotifyCollectionChangedEventArgs System.Runtime.InteropServices.WindowsRuntime.NotifyCollectionChangedEventArgsMarshaler.ConvertToManaged(IntPtr) pslILEmit->EmitCALL(pslILEmit->GetToken(pConvertMD), 1, 1); @@ -5834,7 +5834,7 @@ void ILNCCEventArgsMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslIL STANDARD_VM_CONTRACT; EmitLoadNativeValue(pslILEmit); - EmitConvertWinRTEventArgsToCLREventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain()); + EmitConvertWinRTEventArgsToCLREventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetLoaderAllocator()); EmitStoreManagedValue(pslILEmit); } @@ -5858,8 +5858,8 @@ LocalDesc ILPCEventArgsMarshaler::GetManagedType() { STANDARD_VM_CONTRACT;; - BaseDomain *pDomain = m_pargs->m_pMarshalInfo->GetModule()->GetDomain(); - TypeHandle hndPCEventArgType = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetSystemPCEventArgsType(); + LoaderAllocator* pLoader = m_pargs->m_pMarshalInfo->GetModule()->GetLoaderAllocator(); + TypeHandle hndPCEventArgType = pLoader->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetSystemPCEventArgsType(); return LocalDesc(hndPCEventArgType); // System.ComponentModel.PropertyChangedEventArgs } @@ -5873,11 +5873,11 @@ bool ILPCEventArgsMarshaler::NeedsClearNative() // Note that this method expects the CLR PropertyChangedEventArgs on top of the evaluation stack and // leaves the WinRT PropertyChangedEventArgs IP there. //static -void ILPCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(ILCodeStream *pslILEmit, BaseDomain *pDomain) +void ILPCEventArgsMarshaler::EmitConvertCLREventArgsToWinRTEventArgs(ILCodeStream *pslILEmit, LoaderAllocator* pLoader) { STANDARD_VM_CONTRACT; - MethodDesc *pConvertMD = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetSystemPCEventArgsToWinRTPCEventArgsMD(); + MethodDesc *pConvertMD = pLoader->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetSystemPCEventArgsToWinRTPCEventArgsMD(); // IntPtr System.Runtime.InteropServices.WindowsRuntime.PropertyChangedEventArgsMarshaler.ConvertToNative(PropertyChangedEventArgs) pslILEmit->EmitCALL(pslILEmit->GetToken(pConvertMD), 1, 1); @@ -5888,18 +5888,18 @@ void ILPCEventArgsMarshaler::EmitConvertContentsCLRToNative(ILCodeStream *pslILE STANDARD_VM_CONTRACT; EmitLoadManagedValue(pslILEmit); - EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain()); + EmitConvertCLREventArgsToWinRTEventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetLoaderAllocator()); EmitStoreNativeValue(pslILEmit); } // Note that this method expects the WinRT PropertyChangedEventArgs on top of the evaluation stack and // leaves the CLR PropertyChangedEventArgs there. //static -void ILPCEventArgsMarshaler::EmitConvertWinRTEventArgsToCLREventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain) +void ILPCEventArgsMarshaler::EmitConvertWinRTEventArgsToCLREventArgs(ILCodeStream* pslILEmit, LoaderAllocator* pLoader) { STANDARD_VM_CONTRACT; - MethodDesc *pConvertMD = pDomain->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetWinRTPCEventArgsToSystemPCEventArgsMD(); + MethodDesc *pConvertMD = pLoader->GetMarshalingData()->GetEventArgsMarshalingInfo()->GetWinRTPCEventArgsToSystemPCEventArgsMD(); // PropertyChangedEventArgs System.Runtime.InteropServices.WindowsRuntime.PropertyChangedEventArgsMarshaler.ConvertToManaged(IntPtr) pslILEmit->EmitCALL(pslILEmit->GetToken(pConvertMD), 1, 1); @@ -5910,7 +5910,7 @@ void ILPCEventArgsMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILE STANDARD_VM_CONTRACT; EmitLoadNativeValue(pslILEmit); - EmitConvertWinRTEventArgsToCLREventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetDomain()); + EmitConvertWinRTEventArgsToCLREventArgs(pslILEmit, m_pargs->m_pMarshalInfo->GetModule()->GetLoaderAllocator()); EmitStoreManagedValue(pslILEmit); } diff --git a/src/vm/ilmarshalers.h b/src/vm/ilmarshalers.h index 0566903..1c58c0c 100644 --- a/src/vm/ilmarshalers.h +++ b/src/vm/ilmarshalers.h @@ -3234,8 +3234,8 @@ public: c_CLRSize = sizeof(OBJECTREF), }; - static void EmitConvertCLRUriToWinRTUri(ILCodeStream* pslILEmit, BaseDomain* pDomain); - static void EmitConvertWinRTUriToCLRUri(ILCodeStream* pslILEmit, BaseDomain* pDomain); + static void EmitConvertCLRUriToWinRTUri(ILCodeStream* pslILEmit, LoaderAllocator* pLoader); + static void EmitConvertWinRTUriToCLRUri(ILCodeStream* pslILEmit, LoaderAllocator* pLoader); protected: virtual LocalDesc GetNativeType(); @@ -3258,8 +3258,8 @@ public: c_CLRSize = sizeof(OBJECTREF), }; - static void EmitConvertCLREventArgsToWinRTEventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain); - static void EmitConvertWinRTEventArgsToCLREventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain); + static void EmitConvertCLREventArgsToWinRTEventArgs(ILCodeStream* pslILEmit, LoaderAllocator* pLoader); + static void EmitConvertWinRTEventArgsToCLREventArgs(ILCodeStream* pslILEmit, LoaderAllocator* pLoader); protected: virtual LocalDesc GetNativeType(); @@ -3282,8 +3282,8 @@ public: c_CLRSize = sizeof(OBJECTREF), }; - static void EmitConvertCLREventArgsToWinRTEventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain); - static void EmitConvertWinRTEventArgsToCLREventArgs(ILCodeStream* pslILEmit, BaseDomain* pDomain); + static void EmitConvertCLREventArgsToWinRTEventArgs(ILCodeStream* pslILEmit, LoaderAllocator* pLoader); + static void EmitConvertWinRTEventArgsToCLREventArgs(ILCodeStream* pslILEmit, LoaderAllocator* pLoader); protected: virtual LocalDesc GetNativeType(); diff --git a/src/vm/interopconverter.cpp b/src/vm/interopconverter.cpp index c681023..26254e1 100644 --- a/src/vm/interopconverter.cpp +++ b/src/vm/interopconverter.cpp @@ -207,7 +207,7 @@ IUnknown *GetComIPFromObjectRef(OBJECTREF *poref, ComIpType ReqIpType, ComIpType // This is a redirected type - see if we need to manually marshal it if (redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_Uri) { - UriMarshalingInfo *pUriMarshalInfo = GetAppDomain()->GetMarshalingData()->GetUriMarshalingInfo(); + UriMarshalingInfo *pUriMarshalInfo = GetAppDomain()->GetLoaderAllocator()->GetMarshalingData()->GetUriMarshalingInfo(); struct { OBJECTREF ref; @@ -241,7 +241,7 @@ IUnknown *GetComIPFromObjectRef(OBJECTREF *poref, ComIpType ReqIpType, ComIpType redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs) { MethodDesc *pMD; - EventArgsMarshalingInfo *pInfo = GetAppDomain()->GetMarshalingData()->GetEventArgsMarshalingInfo(); + EventArgsMarshalingInfo *pInfo = GetAppDomain()->GetLoaderAllocator()->GetMarshalingData()->GetEventArgsMarshalingInfo(); if (redirectedTypeIndex == WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs) pMD = pInfo->GetSystemNCCEventArgsToWinRTNCCEventArgsMD(); diff --git a/src/vm/interoputil.cpp b/src/vm/interoputil.cpp index a21e68b..b84670b 100644 --- a/src/vm/interoputil.cpp +++ b/src/vm/interoputil.cpp @@ -3261,7 +3261,7 @@ void ConvertOleColorToSystemColor(OLE_COLOR SrcOleColor, SYSTEMCOLOR *pDestSysCo // Retrieve the method desc to use for the current AD. MethodDesc *pOleColorToSystemColorMD = - GetAppDomain()->GetMarshalingData()->GetOleColorMarshalingInfo()->GetOleColorToSystemColorMD(); + GetAppDomain()->GetLoaderAllocator()->GetMarshalingData()->GetOleColorMarshalingInfo()->GetOleColorToSystemColorMD(); MethodDescCallSite oleColorToSystemColor(pOleColorToSystemColorMD); @@ -3290,7 +3290,7 @@ OLE_COLOR ConvertSystemColorToOleColor(OBJECTREF *pSrcObj) // Retrieve the method desc to use for the current AD. MethodDesc *pSystemColorToOleColorMD = - GetAppDomain()->GetMarshalingData()->GetOleColorMarshalingInfo()->GetSystemColorToOleColorMD(); + GetAppDomain()->GetLoaderAllocator()->GetMarshalingData()->GetOleColorMarshalingInfo()->GetSystemColorToOleColorMD(); MethodDescCallSite systemColorToOleColor(pSystemColorToOleColorMD); // Set up the args and call the method. @@ -6732,7 +6732,7 @@ ABI::Windows::Foundation::IUriRuntimeClass *CreateWinRTUri(LPCWSTR wszUri, INT32 { STANDARD_VM_CONTRACT; - UriMarshalingInfo* marshalingInfo = GetAppDomain()->GetMarshalingData()->GetUriMarshalingInfo(); + UriMarshalingInfo* marshalingInfo = GetAppDomain()->GetLoaderAllocator()->GetMarshalingData()->GetUriMarshalingInfo(); // Get the cached factory from the UriMarshalingInfo object of the current appdomain ABI::Windows::Foundation::IUriRuntimeClassFactory* pFactory = marshalingInfo->GetUriFactory(); diff --git a/src/vm/loaderallocator.cpp b/src/vm/loaderallocator.cpp index 7b2ef1e..21c6f27 100644 --- a/src/vm/loaderallocator.cpp +++ b/src/vm/loaderallocator.cpp @@ -73,6 +73,8 @@ LoaderAllocator::LoaderAllocator() m_pJumpStubCache = NULL; m_IsCollectible = false; + m_pMarshalingData = NULL; + #ifdef FEATURE_COMINTEROP m_pComCallWrapperCache = NULL; #endif @@ -1079,8 +1081,8 @@ void LoaderAllocator::Init(BaseDomain *pDomain, BYTE *pExecutableHeapMemory) m_pDomain = pDomain; m_crstLoaderAllocator.Init(CrstLoaderAllocator, (CrstFlags)CRST_UNSAFE_COOPGC); -#ifdef FEATURE_COMINTEROP m_InteropDataCrst.Init(CrstInteropData, CRST_REENTRANCY); +#ifdef FEATURE_COMINTEROP m_ComCallWrapperCrst.Init(CrstCOMCallWrapper); #endif @@ -1227,6 +1229,9 @@ void LoaderAllocator::Init(BaseDomain *pDomain, BYTE *pExecutableHeapMemory) m_pPrecodeHeap = new (&m_PrecodeHeapInstance) CodeFragmentHeap(this, STUB_CODE_BLOCK_PRECODE); #endif + // Initialize the EE marshaling data to NULL. + m_pMarshalingData = NULL; + // Set up the IL stub cache m_ILStubCache.Init(m_pHighFrequencyHeap); @@ -1332,6 +1337,8 @@ void LoaderAllocator::Terminate() LOG((LF_CLASSLOADER, LL_INFO100, "Begin LoaderAllocator::Terminate for loader allocator %p\n", reinterpret_cast(static_cast(this)))); + DeleteMarshalingData(); + if (m_fGCPressure) { GCX_PREEMP(); @@ -1632,6 +1639,50 @@ void LoaderAllocator::UninitVirtualCallStubManager() #endif // !CROSSGEN_COMPILE +EEMarshalingData *LoaderAllocator::GetMarshalingData() +{ + CONTRACT (EEMarshalingData*) + { + THROWS; + GC_TRIGGERS; + MODE_ANY; + INJECT_FAULT(COMPlusThrowOM()); + POSTCONDITION(CheckPointer(m_pMarshalingData)); + } + CONTRACT_END; + + if (!m_pMarshalingData) + { + // Take the lock + CrstHolder holder(&m_InteropDataCrst); + + if (!m_pMarshalingData) + { + m_pMarshalingData = new (GetLowFrequencyHeap()) EEMarshalingData(this, &m_InteropDataCrst); + } + } + + RETURN m_pMarshalingData; +} + +void LoaderAllocator::DeleteMarshalingData() +{ + CONTRACTL + { + NOTHROW; + GC_TRIGGERS; + MODE_ANY; + } + CONTRACTL_END; + + // We are in shutdown - no need to take any lock + if (m_pMarshalingData) + { + delete m_pMarshalingData; + m_pMarshalingData = NULL; + } +} + #endif // !DACCESS_COMPILE BOOL GlobalLoaderAllocator::CanUnload() diff --git a/src/vm/loaderallocator.hpp b/src/vm/loaderallocator.hpp index e2c5dc5..dc63ab9 100644 --- a/src/vm/loaderallocator.hpp +++ b/src/vm/loaderallocator.hpp @@ -135,6 +135,7 @@ class UMEntryThunkCache; #ifdef FEATURE_COMINTEROP class ComCallWrapperCache; #endif // FEATURE_COMINTEROP +class EEMarshalingData; class LoaderAllocator { @@ -262,10 +263,13 @@ private: CrstExplicitInit m_ComCallWrapperCrst; // Hash table that maps a MethodTable to COM Interop compatibility data. PtrHashMap m_interopDataHash; - // Used for synchronizing access to the m_interopDataHash - CrstExplicitInit m_InteropDataCrst; + #endif + // Used for synchronizing access to the m_interopDataHash and m_pMarshalingData + CrstExplicitInit m_InteropDataCrst; + EEMarshalingData* m_pMarshalingData; + #ifdef FEATURE_TIERED_COMPILATION CallCounter m_callCounter; #endif @@ -556,6 +560,17 @@ public: return &m_ILStubCache; } + //**************************************************************************************** + // This method returns marshaling data that the EE uses that is stored on a per LoaderAllocator + // basis. + EEMarshalingData *GetMarshalingData(); + +private: + // Deletes marshaling data at shutdown (which contains cached factories that needs to be released) + void DeleteMarshalingData(); + +public: + #ifdef FEATURE_COMINTEROP ComCallWrapperCache * GetComCallWrapperCache(); diff --git a/src/vm/mlinfo.cpp b/src/vm/mlinfo.cpp index cc9760a..32f77cd 100644 --- a/src/vm/mlinfo.cpp +++ b/src/vm/mlinfo.cpp @@ -429,7 +429,7 @@ CustomMarshalerHelper *SetupCustomMarshalerHelper(LPCUTF8 strMarshalerTypeName, EEMarshalingData *pMarshalingData = NULL; // The assembly is not shared so we use the current app domain's marshaling data. - pMarshalingData = GetThread()->GetDomain()->GetMarshalingData(); + pMarshalingData = pAssembly->GetLoaderAllocator()->GetMarshalingData(); // Retrieve the custom marshaler helper from the EE marshaling data. RETURN pMarshalingData->GetCustomMarshalerHelper(pAssembly, hndManagedType, strMarshalerTypeName, cMarshalerTypeNameBytes, strCookie, cCookieStrBytes); @@ -1072,9 +1072,10 @@ void OleColorMarshalingInfo::operator delete(void *pMem) #endif // FEATURE_COMINTEROP -EEMarshalingData::EEMarshalingData(BaseDomain *pDomain, LoaderHeap *pHeap, CrstBase *pCrst) : - m_pHeap(pHeap), - m_pDomain(pDomain) +EEMarshalingData::EEMarshalingData(LoaderAllocator* pAllocator, CrstBase *pCrst) : + m_pAllocator(pAllocator), + m_pHeap(pAllocator->GetLowFrequencyHeap()), + m_lock(pCrst) { CONTRACTL { @@ -1177,7 +1178,7 @@ CustomMarshalerHelper *EEMarshalingData::GetCustomMarshalerHelper(Assembly *pAss TypeHandle hndCustomMarshalerType; // Create the key that will be used to lookup in the hashtable. - EECMHelperHashtableKey Key(cMarshalerTypeNameBytes, strMarshalerTypeName, cCookieStrBytes, strCookie, hndManagedType.GetInstantiation()); + EECMHelperHashtableKey Key(cMarshalerTypeNameBytes, strMarshalerTypeName, cCookieStrBytes, strCookie, hndManagedType.GetInstantiation(), pAssembly); // Lookup the custom marshaler helper in the hashtable. if (m_CMHelperHashtable.GetValue(&Key, (HashDatum*)&pCMHelper)) @@ -1209,15 +1210,14 @@ CustomMarshalerHelper *EEMarshalingData::GetCustomMarshalerHelper(Assembly *pAss // Create the custom marshaler info in the specified heap. - pNewCMInfo = new (m_pHeap) CustomMarshalerInfo(m_pDomain, hndCustomMarshalerType, hndManagedType, strCookie, cCookieStrBytes); + pNewCMInfo = new (m_pHeap) CustomMarshalerInfo(m_pAllocator, hndCustomMarshalerType, hndManagedType, strCookie, cCookieStrBytes); // Create the custom marshaler helper in the specified heap. pNewCMHelper = new (m_pHeap) NonSharedCustomMarshalerHelper(pNewCMInfo); } - // Take the app domain lock before we insert the custom marshaler info into the hashtable. { - BaseDomain::LockHolder lh(m_pDomain); + CrstHolder lock(m_lock); // Verify that the custom marshaler helper has not already been added by another thread. if (m_CMHelperHashtable.GetValue(&Key, (HashDatum*)&pCMHelper)) @@ -1277,15 +1277,14 @@ CustomMarshalerInfo *EEMarshalingData::GetCustomMarshalerInfo(SharedCustomMarsha } // Create the custom marshaler info in the specified heap. - pNewCMInfo = new (m_pHeap) CustomMarshalerInfo(m_pDomain, + pNewCMInfo = new (m_pHeap) CustomMarshalerInfo(m_pAllocator, hndCustomMarshalerType, pSharedCMHelper->GetManagedType(), pSharedCMHelper->GetCookieString(), pSharedCMHelper->GetCookieStringByteCount()); { - // Take the app domain lock before we insert the custom marshaler info into the hashtable. - BaseDomain::LockHolder lh(m_pDomain); + CrstHolder lock(m_lock); // Verify that the custom marshaler info has not already been added by another thread. if (m_SharedCMHelperToCMInfoMap.GetValue(pSharedCMHelper, (HashDatum*)&pCMInfo)) diff --git a/src/vm/mlinfo.h b/src/vm/mlinfo.h index 91afec9..00a417b 100644 --- a/src/vm/mlinfo.h +++ b/src/vm/mlinfo.h @@ -371,7 +371,7 @@ private: class EEMarshalingData { public: - EEMarshalingData(BaseDomain *pDomain, LoaderHeap *pHeap, CrstBase *pCrst); + EEMarshalingData(LoaderAllocator *pAllocator, CrstBase *pCrst); ~EEMarshalingData(); // EEMarshalingData's are always allocated on the loader heap so we need to redefine @@ -400,14 +400,15 @@ private: EECMHelperHashTable m_CMHelperHashtable; EEPtrHashTable m_SharedCMHelperToCMInfoMap; #endif // CROSSGEN_COMPILE + LoaderAllocator* m_pAllocator; LoaderHeap* m_pHeap; - BaseDomain* m_pDomain; CMINFOLIST m_pCMInfoList; #ifdef FEATURE_COMINTEROP OleColorMarshalingInfo* m_pOleColorInfo; UriMarshalingInfo* m_pUriInfo; EventArgsMarshalingInfo* m_pEventArgsInfo; #endif // FEATURE_COMINTEROP + CrstBase* m_lock; }; struct ItfMarshalInfo; diff --git a/tests/src/Interop/CMakeLists.txt b/tests/src/Interop/CMakeLists.txt index e46e78a..9b67844 100644 --- a/tests/src/Interop/CMakeLists.txt +++ b/tests/src/Interop/CMakeLists.txt @@ -62,6 +62,7 @@ add_subdirectory(DllImportAttribute/ExeFile) add_subdirectory(DllImportAttribute/FileNameContainDot) add_subdirectory(DllImportAttribute/Simple) add_subdirectory(ExecInDefAppDom) +add_subdirectory(ICustomMarshaler/ConflictingNames) add_subdirectory(LayoutClass) if(WIN32) diff --git a/tests/src/Interop/ICustomMarshaler/ConflictingNames/CMakeLists.txt b/tests/src/Interop/ICustomMarshaler/ConflictingNames/CMakeLists.txt new file mode 100644 index 0000000..b1743b7 --- /dev/null +++ b/tests/src/Interop/ICustomMarshaler/ConflictingNames/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required (VERSION 2.6) +project (CustomMarshalersConflictingNames) +include_directories(${INC_PLATFORM_DIR}) +set(SOURCES CustomMarshalerNative.cpp ) + +# add the executable +add_library (CustomMarshalerNative SHARED ${SOURCES}) +target_link_libraries(CustomMarshalerNative ${LINK_LIBRARIES_ADDITIONAL}) + +# add the install targets +install (TARGETS CustomMarshalerNative DESTINATION bin) diff --git a/tests/src/Interop/ICustomMarshaler/ConflictingNames/CustomMarshaler.cs b/tests/src/Interop/ICustomMarshaler/ConflictingNames/CustomMarshaler.cs new file mode 100644 index 0000000..506f8b2 --- /dev/null +++ b/tests/src/Interop/ICustomMarshaler/ConflictingNames/CustomMarshaler.cs @@ -0,0 +1,54 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; + +class WrappedString +{ + public WrappedString(string str) + { + _str = str; + } + + internal string _str; +} + +class WrappedStringCustomMarshaler : ICustomMarshaler +{ + public void CleanUpManagedData(object ManagedObj) { } + public void CleanUpNativeData(IntPtr pNativeData) { Marshal.ZeroFreeCoTaskMemAnsi(pNativeData); } + + public int GetNativeDataSize() => IntPtr.Size; + + public IntPtr MarshalManagedToNative(object ManagedObj) => Marshal.StringToCoTaskMemAnsi(((WrappedString)ManagedObj)._str); + public object MarshalNativeToManaged(IntPtr pNativeData) => new WrappedString(Marshal.PtrToStringAnsi(pNativeData)); + + public static ICustomMarshaler GetInstance(string cookie) => new WrappedStringCustomMarshaler(); +} + +// Use an ifdef here to give us two separate public API surfaces to call while allowing us to have the same implementation code +// as well as allowing us to share the custom marshaler implementations above. +// If we wanted to add more tests here, we would want to put the public API surface in the namespace and the private +// details and marshalers in the global scope as done above. +#if CUSTOMMARSHALERS2 +namespace CustomMarshalers2 +#else +namespace CustomMarshalers +#endif +{ + public class CustomMarshalerTest + { + [DllImport("CustomMarshalerNative", CharSet = CharSet.Ansi)] + private static extern int NativeParseInt([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(WrappedStringCustomMarshaler))] WrappedString str); + + public int ParseInt(string str) + { + return NativeParseInt(new WrappedString(str)); + } + } +} + diff --git a/tests/src/Interop/ICustomMarshaler/ConflictingNames/CustomMarshaler.csproj b/tests/src/Interop/ICustomMarshaler/ConflictingNames/CustomMarshaler.csproj new file mode 100644 index 0000000..e04f27f --- /dev/null +++ b/tests/src/Interop/ICustomMarshaler/ConflictingNames/CustomMarshaler.csproj @@ -0,0 +1,28 @@ + + + + + + Debug + AnyCPU + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + library + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\ + + + + + + + False + + + + + + + + + diff --git a/tests/src/Interop/ICustomMarshaler/ConflictingNames/CustomMarshaler2.csproj b/tests/src/Interop/ICustomMarshaler/ConflictingNames/CustomMarshaler2.csproj new file mode 100644 index 0000000..38c0cba --- /dev/null +++ b/tests/src/Interop/ICustomMarshaler/ConflictingNames/CustomMarshaler2.csproj @@ -0,0 +1,29 @@ + + + + + + Debug + AnyCPU + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + library + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\ + $(DefineConstants);CUSTOMMARSHALERS2 + + + + + + + False + + + + + + + + + diff --git a/tests/src/Interop/ICustomMarshaler/ConflictingNames/CustomMarshalerNative.cpp b/tests/src/Interop/ICustomMarshaler/ConflictingNames/CustomMarshalerNative.cpp new file mode 100644 index 0000000..11aee80 --- /dev/null +++ b/tests/src/Interop/ICustomMarshaler/ConflictingNames/CustomMarshalerNative.cpp @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#include +#include + + +extern "C" int DLL_EXPORT STDMETHODCALLTYPE NativeParseInt(LPCSTR str) +{ + return atoi(str); +} diff --git a/tests/src/Interop/ICustomMarshaler/ConflictingNames/MultipleALCs.csproj b/tests/src/Interop/ICustomMarshaler/ConflictingNames/MultipleALCs.csproj new file mode 100644 index 0000000..045a2b6 --- /dev/null +++ b/tests/src/Interop/ICustomMarshaler/ConflictingNames/MultipleALCs.csproj @@ -0,0 +1,35 @@ + + + + + + Debug + AnyCPU + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\ + true + + + + + + + False + + + + + + + + + + + + + + + diff --git a/tests/src/Interop/ICustomMarshaler/ConflictingNames/RunInALC.cs b/tests/src/Interop/ICustomMarshaler/ConflictingNames/RunInALC.cs new file mode 100644 index 0000000..1d61f2d --- /dev/null +++ b/tests/src/Interop/ICustomMarshaler/ConflictingNames/RunInALC.cs @@ -0,0 +1,72 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.Loader; +using TestLibrary; + +public class RunInALC +{ + public static int Main(string[] args) + { + try + { + ConflictingCustomMarshalerNamesInCollectibleLoadContexts_Succeeds(); + ConflictingCustomMarshalerNamesInNoncollectibleLoadContexts_Succeeds(); + } + catch (System.Exception e) + { + Console.WriteLine(e.ToString()); + return 101; + } + return 100; + } + + static void ConflictingCustomMarshalerNamesInCollectibleLoadContexts_Succeeds() + { + Run(new UnloadableLoadContext()); + Run(new UnloadableLoadContext()); + } + + static void ConflictingCustomMarshalerNamesInNoncollectibleLoadContexts_Succeeds() + { + Run(new CustomLoadContext()); + Run(new CustomLoadContext()); + } + + static void Run(AssemblyLoadContext context) + { + string currentAssemblyDirectory = Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).AbsolutePath); + Assembly inContextAssembly = context.LoadFromAssemblyPath(Path.Combine(currentAssemblyDirectory, "CustomMarshaler.dll")); + Type inContextType = inContextAssembly.GetType("CustomMarshalers.CustomMarshalerTest"); + object instance = Activator.CreateInstance(inContextType); + MethodInfo parseIntMethod = inContextType.GetMethod("ParseInt", BindingFlags.Instance | BindingFlags.Public); + Assert.AreEqual(1234, (int)parseIntMethod.Invoke(instance, new object[]{"1234"})); + } +} + +class UnloadableLoadContext : AssemblyLoadContext +{ + public UnloadableLoadContext() + :base(true) + { + + } + + protected override Assembly Load(AssemblyName assemblyName) + { + return null; + } +} + +class CustomLoadContext : AssemblyLoadContext +{ + protected override Assembly Load(AssemblyName assemblyName) + { + return null; + } +} diff --git a/tests/src/Interop/ICustomMarshaler/ConflictingNames/SameNameDifferentAssembly.cs b/tests/src/Interop/ICustomMarshaler/ConflictingNames/SameNameDifferentAssembly.cs new file mode 100644 index 0000000..ce91134 --- /dev/null +++ b/tests/src/Interop/ICustomMarshaler/ConflictingNames/SameNameDifferentAssembly.cs @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.Loader; +using TestLibrary; + +public class RunInALC +{ + public static int Main(string[] args) + { + try + { + Assert.AreEqual(123, new CustomMarshalers.CustomMarshalerTest().ParseInt("123")); + Assert.AreEqual(123, new CustomMarshalers2.CustomMarshalerTest().ParseInt("123")); + return 100; + } + catch (Exception e) + { + Console.WriteLine(e); + return 101; + } + } +} diff --git a/tests/src/Interop/ICustomMarshaler/ConflictingNames/SameNameDifferentAssembly.csproj b/tests/src/Interop/ICustomMarshaler/ConflictingNames/SameNameDifferentAssembly.csproj new file mode 100644 index 0000000..6b1f7df --- /dev/null +++ b/tests/src/Interop/ICustomMarshaler/ConflictingNames/SameNameDifferentAssembly.csproj @@ -0,0 +1,35 @@ + + + + + + Debug + AnyCPU + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\ + true + + + + + + + False + + + + + + + + + + + + + + + diff --git a/tests/src/Interop/ICustomMarshaler/ICustomMarshaler.cs b/tests/src/Interop/ICustomMarshaler/Primitives/ICustomMarshaler.cs similarity index 100% rename from tests/src/Interop/ICustomMarshaler/ICustomMarshaler.cs rename to tests/src/Interop/ICustomMarshaler/Primitives/ICustomMarshaler.cs diff --git a/tests/src/Interop/ICustomMarshaler/ICustomMarshaler.csproj b/tests/src/Interop/ICustomMarshaler/Primitives/ICustomMarshaler.csproj similarity index 92% rename from tests/src/Interop/ICustomMarshaler/ICustomMarshaler.csproj rename to tests/src/Interop/ICustomMarshaler/Primitives/ICustomMarshaler.csproj index ae3ef0e..0e68e23 100644 --- a/tests/src/Interop/ICustomMarshaler/ICustomMarshaler.csproj +++ b/tests/src/Interop/ICustomMarshaler/Primitives/ICustomMarshaler.csproj @@ -21,11 +21,8 @@ - - - - + -- 2.7.4