From 3e6334b8797731bc24a2b9c69a7b7073a92b66a9 Mon Sep 17 00:00:00 2001 From: Aditya Mandaleeka Date: Tue, 11 Apr 2017 18:28:03 -0700 Subject: [PATCH] Hide knowledge of handle table buckets and home heaps from VM side. --- src/gc/gchandletable.cpp | 30 +++++++++++++++++++--- src/gc/gchandletableimpl.h | 8 ++++++ src/gc/gcinterface.h | 8 ++++++ src/vm/appdomain.cpp | 55 ++++++++++++++++------------------------- src/vm/appdomain.hpp | 42 +++++++++++++++++-------------- src/vm/exstate.cpp | 6 +++-- src/vm/exstate.h | 2 +- src/vm/gchandletableutilities.h | 33 ++++++++++++++----------- 8 files changed, 112 insertions(+), 72 deletions(-) diff --git a/src/gc/gchandletable.cpp b/src/gc/gchandletable.cpp index 7ac006d..28852df 100644 --- a/src/gc/gchandletable.cpp +++ b/src/gc/gchandletable.cpp @@ -38,9 +38,31 @@ void* GCHandleTable::GetHandleContext(OBJECTHANDLE handle) return (void*)((uintptr_t)::HndGetHandleTableADIndex(::HndGetHandleTable(handle)).m_dwIndex); } +void GCHandleTable::DestroyHandleTable(void* table) +{ + Ref_DestroyHandleTableBucket((HandleTableBucket*) table); +} + +void GCHandleTable::UprootHandleTable(void* table) +{ + Ref_RemoveHandleTableBucket((HandleTableBucket*) table); +} + +bool GCHandleTable::ContainsHandle(void* table, OBJECTHANDLE handle) +{ + return ((HandleTableBucket*)table)->Contains(handle); +} + OBJECTHANDLE GCHandleTable::CreateHandleOfType(void* table, Object* object, int type) { - return ::HndCreateHandle((HHANDLETABLE)table, type, ObjectToOBJECTREF(object)); + HHANDLETABLE handletable = ((HandleTableBucket*)table)->pTable[GetCurrentThreadHomeHeapNumber()]; + return ::HndCreateHandle(handletable, type, ObjectToOBJECTREF(object)); +} + +OBJECTHANDLE GCHandleTable::CreateHandleOfType(void* table, Object* object, int type, int heapToAffinitizeTo) +{ + HHANDLETABLE handletable = ((HandleTableBucket*)table)->pTable[heapToAffinitizeTo]; + return ::HndCreateHandle(handletable, type, ObjectToOBJECTREF(object)); } OBJECTHANDLE GCHandleTable::CreateGlobalHandleOfType(Object* object, int type) @@ -50,12 +72,14 @@ OBJECTHANDLE GCHandleTable::CreateGlobalHandleOfType(Object* object, int type) OBJECTHANDLE GCHandleTable::CreateHandleWithExtraInfo(void* table, Object* object, int type, void* pExtraInfo) { - return ::HndCreateHandle((HHANDLETABLE)table, type, ObjectToOBJECTREF(object), reinterpret_cast(pExtraInfo)); + HHANDLETABLE handletable = ((HandleTableBucket*)table)->pTable[GetCurrentThreadHomeHeapNumber()]; + return ::HndCreateHandle(handletable, type, ObjectToOBJECTREF(object), reinterpret_cast(pExtraInfo)); } OBJECTHANDLE GCHandleTable::CreateDependentHandle(void* table, Object* primary, Object* secondary) { - OBJECTHANDLE handle = ::HndCreateHandle((HHANDLETABLE)table, HNDTYPE_DEPENDENT, ObjectToOBJECTREF(primary)); + HHANDLETABLE handletable = ((HandleTableBucket*)table)->pTable[GetCurrentThreadHomeHeapNumber()]; + OBJECTHANDLE handle = ::HndCreateHandle(handletable, HNDTYPE_DEPENDENT, ObjectToOBJECTREF(primary)); ::SetDependentHandleSecondary(handle, ObjectToOBJECTREF(secondary)); return handle; diff --git a/src/gc/gchandletableimpl.h b/src/gc/gchandletableimpl.h index 1cac0d2..a45f983 100644 --- a/src/gc/gchandletableimpl.h +++ b/src/gc/gchandletableimpl.h @@ -20,8 +20,16 @@ public: virtual void* GetHandleContext(OBJECTHANDLE handle); + virtual void DestroyHandleTable(void* table); + + virtual void UprootHandleTable(void* table); + + virtual bool ContainsHandle(void* table, OBJECTHANDLE handle); + virtual OBJECTHANDLE CreateHandleOfType(void* table, Object* object, int type); + virtual OBJECTHANDLE CreateHandleOfType(void* table, Object* object, int type, int heapToAffinitizeTo); + virtual OBJECTHANDLE CreateHandleWithExtraInfo(void* table, Object* object, int type, void* pExtraInfo); virtual OBJECTHANDLE CreateDependentHandle(void* table, Object* primary, Object* secondary); diff --git a/src/gc/gcinterface.h b/src/gc/gcinterface.h index 5be332b..b2bfbb7 100644 --- a/src/gc/gcinterface.h +++ b/src/gc/gcinterface.h @@ -415,8 +415,16 @@ public: virtual void* GetNewHandleTable(void* context) = 0; + virtual void DestroyHandleTable(void* table) = 0; + + virtual void UprootHandleTable(void* table) = 0; + + virtual bool ContainsHandle(void* table, OBJECTHANDLE handle) = 0; + virtual OBJECTHANDLE CreateHandleOfType(void* table, Object* object, int type) = 0; + virtual OBJECTHANDLE CreateHandleOfType(void* table, Object* object, int type, int heapToAffinitizeTo) = 0; + virtual OBJECTHANDLE CreateHandleWithExtraInfo(void* table, Object* object, int type, void* pExtraInfo) = 0; virtual OBJECTHANDLE CreateDependentHandle(void* table, Object* primary, Object* secondary) = 0; diff --git a/src/vm/appdomain.cpp b/src/vm/appdomain.cpp index d9f4295..34c1822 100644 --- a/src/vm/appdomain.cpp +++ b/src/vm/appdomain.cpp @@ -740,10 +740,10 @@ BaseDomain::BaseDomain() m_pLargeHeapHandleTable = NULL; #ifndef CROSSGEN_COMPILE - // Note that m_hHandleTableBucket is overridden by app domains - m_hHandleTableBucket = g_HandleTableMap.pBuckets[0]; + // Note that m_gcHandleTable is overridden by app domains + m_gcHandleTable = GCHandleTableUtilities::GetGCHandleTable()->GetGlobalHandleTable(); #else - m_hHandleTableBucket = NULL; + m_gcHandleTable = NULL; #endif m_pMarshalingData = NULL; @@ -4042,7 +4042,7 @@ AppDomain::AppDomain() m_pUMEntryThunkCache = NULL; m_pAsyncPool = NULL; - m_hHandleTableBucket = NULL; + m_gcHandleTable = NULL; m_ExposedObject = NULL; m_pComIPForExposedObject = NULL; @@ -4273,18 +4273,13 @@ void AppDomain::Init() // default domain cannot be unloaded. if (GetId().m_dwId == DefaultADID) { - m_hHandleTableBucket = g_HandleTableMap.pBuckets[0]; + m_gcHandleTable = GCHandleTableUtilities::GetGCHandleTable()->GetGlobalHandleTable(); } else { - m_hHandleTableBucket = Ref_CreateHandleTableBucket(m_dwIndex); + m_gcHandleTable = GCHandleTableUtilities::GetGCHandleTable()->GetNewHandleTable((void*)(uintptr_t)m_dwIndex.m_dwIndex); } -#ifdef _DEBUG - if (((HandleTable *)(m_hHandleTableBucket->pTable[0]))->uADIndex != m_dwIndex) - _ASSERTE (!"AD index mismatch"); -#endif // _DEBUG - #endif // CROSSGEN_COMPILE #ifdef FEATURE_TYPEEQUIVALENCE @@ -4583,16 +4578,10 @@ void AppDomain::Terminate() BaseDomain::Terminate(); -#ifdef _DEBUG - if (m_hHandleTableBucket && - m_hHandleTableBucket->pTable && - ((HandleTable *)(m_hHandleTableBucket->pTable[0]))->uADIndex != m_dwIndex) - _ASSERTE (!"AD index mismatch"); -#endif // _DEBUG - - if (m_hHandleTableBucket) { - Ref_DestroyHandleTableBucket(m_hHandleTableBucket); - m_hHandleTableBucket = NULL; + if (m_gcHandleTable) + { + GCHandleTableUtilities::GetGCHandleTable()->DestroyHandleTable(m_gcHandleTable); + m_gcHandleTable = NULL; } #ifdef FEATURE_APPDOMAIN_RESOURCE_MONITORING @@ -9209,14 +9198,7 @@ void AppDomain::ClearGCHandles() HandleAsyncPinHandles(); // Remove our handle table as a source of GC roots - HandleTableBucket *pBucket = m_hHandleTableBucket; - -#ifdef _DEBUG - if (((HandleTable *)(pBucket->pTable[0]))->uADIndex != m_dwIndex) - _ASSERTE (!"AD index mismatch"); -#endif // _DEBUG - - Ref_RemoveHandleTableBucket(pBucket); + GCHandleTableUtilities::GetGCHandleTable()->UprootHandleTable(m_gcHandleTable); } // When an AD is unloaded, we will release all objects in this AD. @@ -9232,13 +9214,17 @@ void AppDomain::HandleAsyncPinHandles() } CONTRACTL_END; - HandleTableBucket *pBucket = m_hHandleTableBucket; + // TODO: Temporarily casting stuff here until Ref_RelocateAsyncPinHandles is moved to the interface. + HandleTableBucket *pBucket = (HandleTableBucket*)m_gcHandleTable; + // IO completion port picks IO job using FIFO. Here is how we know which AsyncPinHandle can be freed. // 1. We mark all non-pending AsyncPinHandle with READYTOCLEAN. // 2. We queue a dump Overlapped to the IO completion as a marker. // 3. When the Overlapped is picked up by completion port, we wait until all previous IO jobs are processed. // 4. Then we can delete all AsyncPinHandle marked with READYTOCLEAN. - HandleTableBucket *pBucketInDefault = SystemDomain::System()->DefaultDomain()->m_hHandleTableBucket; + HandleTableBucket *pBucketInDefault = (HandleTableBucket*)SystemDomain::System()->DefaultDomain()->m_gcHandleTable; + + // TODO: When this function is moved to the interface it will take void*s Ref_RelocateAsyncPinHandles(pBucket, pBucketInDefault); OverlappedDataObject::RequestCleanup(); @@ -9261,14 +9247,15 @@ void AppDomain::ClearGCRoots() // this point, so only need to synchronize the preemptive mode threads. ExecutionManager::Unload(GetLoaderAllocator()); + IGCHandleTable* pHandleTable = GCHandleTableUtilities::GetGCHandleTable(); + while ((pThread = ThreadStore::GetAllThreadList(pThread, 0, 0)) != NULL) { // Delete the thread local static store pThread->DeleteThreadStaticData(this); - // @TODO: A pre-allocated AppDomainUnloaded exception might be better. - if (m_hHandleTableBucket->Contains(pThread->m_LastThrownObjectHandle)) + if (pHandleTable->ContainsHandle(m_gcHandleTable, pThread->m_LastThrownObjectHandle)) { // Never delete a handle to a preallocated exception object. if (!CLRException::IsPreallocatedExceptionHandle(pThread->m_LastThrownObjectHandle)) @@ -9280,7 +9267,7 @@ void AppDomain::ClearGCRoots() } // Clear out the exceptions objects held by a thread. - pThread->GetExceptionState()->ClearThrowablesForUnload(m_hHandleTableBucket); + pThread->GetExceptionState()->ClearThrowablesForUnload(m_gcHandleTable); } //delete them while we still have the runtime suspended diff --git a/src/vm/appdomain.hpp b/src/vm/appdomain.hpp index 3573d2a..d74bd7e 100644 --- a/src/vm/appdomain.hpp +++ b/src/vm/appdomain.hpp @@ -1240,63 +1240,70 @@ public: //**************************************************************************************** // Handles -#if !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE) // needs GetCurrentThreadHomeHeapNumber +#if !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE) OBJECTHANDLE CreateTypedHandle(OBJECTREF object, int type) { WRAPPER_NO_CONTRACT; IGCHandleTable *pHandleTable = GCHandleTableUtilities::GetGCHandleTable(); - return pHandleTable->CreateHandleOfType(m_hHandleTableBucket->pTable[GetCurrentThreadHomeHeapNumber()], OBJECTREFToObject(object), type); + return pHandleTable->CreateHandleOfType(m_gcHandleTable, OBJECTREFToObject(object), type); } OBJECTHANDLE CreateHandle(OBJECTREF object) { WRAPPER_NO_CONTRACT; CONDITIONAL_CONTRACT_VIOLATION(ModeViolation, object == NULL) - return ::CreateHandle(m_hHandleTableBucket->pTable[GetCurrentThreadHomeHeapNumber()], object); + return ::CreateHandle(m_gcHandleTable, object); } OBJECTHANDLE CreateWeakHandle(OBJECTREF object) { WRAPPER_NO_CONTRACT; - return ::CreateWeakHandle(m_hHandleTableBucket->pTable[GetCurrentThreadHomeHeapNumber()], object); + return ::CreateWeakHandle(m_gcHandleTable, object); } OBJECTHANDLE CreateShortWeakHandle(OBJECTREF object) { WRAPPER_NO_CONTRACT; - return ::CreateShortWeakHandle(m_hHandleTableBucket->pTable[GetCurrentThreadHomeHeapNumber()], object); + return ::CreateShortWeakHandle(m_gcHandleTable, object); } OBJECTHANDLE CreateLongWeakHandle(OBJECTREF object) { WRAPPER_NO_CONTRACT; CONDITIONAL_CONTRACT_VIOLATION(ModeViolation, object == NULL) - return ::CreateLongWeakHandle(m_hHandleTableBucket->pTable[GetCurrentThreadHomeHeapNumber()], object); + return ::CreateLongWeakHandle(m_gcHandleTable, object); } OBJECTHANDLE CreateStrongHandle(OBJECTREF object) { WRAPPER_NO_CONTRACT; - return ::CreateStrongHandle(m_hHandleTableBucket->pTable[GetCurrentThreadHomeHeapNumber()], object); + return ::CreateStrongHandle(m_gcHandleTable, object); } OBJECTHANDLE CreatePinningHandle(OBJECTREF object) { WRAPPER_NO_CONTRACT; -#if CHECK_APP_DOMAIN_LEAKS +#if CHECK_APP_DOMAIN_LEAKS if(IsAppDomain()) object->TryAssignAppDomain((AppDomain*)this,TRUE); #endif - return ::CreatePinningHandle(m_hHandleTableBucket->pTable[GetCurrentThreadHomeHeapNumber()], object); + return ::CreatePinningHandle(m_gcHandleTable, object); } OBJECTHANDLE CreateSizedRefHandle(OBJECTREF object) { WRAPPER_NO_CONTRACT; - OBJECTHANDLE h = ::CreateSizedRefHandle( - m_hHandleTableBucket->pTable[GCHeapUtilities::IsServerHeap() ? (m_dwSizedRefHandles % m_iNumberOfProcessors) : GetCurrentThreadHomeHeapNumber()], - object); + OBJECTHANDLE h; + if (GCHeapUtilities::IsServerHeap()) + { + h = ::CreateSizedRefHandle(m_gcHandleTable, object, m_dwSizedRefHandles % m_iNumberOfProcessors); + } + else + { + h = ::CreateSizedRefHandle(m_gcHandleTable, object); + } + InterlockedIncrement((LONG*)&m_dwSizedRefHandles); return h; } @@ -1305,7 +1312,7 @@ public: OBJECTHANDLE CreateRefcountedHandle(OBJECTREF object) { WRAPPER_NO_CONTRACT; - return ::CreateRefcountedHandle(m_hHandleTableBucket->pTable[GetCurrentThreadHomeHeapNumber()], object); + return ::CreateRefcountedHandle(m_gcHandleTable, object); } OBJECTHANDLE CreateWinRTWeakHandle(OBJECTREF object, IWeakReference* pWinRTWeakReference) @@ -1318,14 +1325,14 @@ public: } CONTRACTL_END; - return ::CreateWinRTWeakHandle(m_hHandleTableBucket->pTable[GetCurrentThreadHomeHeapNumber()], object, pWinRTWeakReference); + return ::CreateWinRTWeakHandle(m_gcHandleTable, object, pWinRTWeakReference); } #endif // FEATURE_COMINTEROP OBJECTHANDLE CreateVariableHandle(OBJECTREF object, UINT type) { WRAPPER_NO_CONTRACT; - return ::CreateVariableHandle(m_hHandleTableBucket->pTable[GetCurrentThreadHomeHeapNumber()], object, type); + return ::CreateVariableHandle(m_gcHandleTable, object, type); } OBJECTHANDLE CreateDependentHandle(OBJECTREF primary, OBJECTREF secondary) @@ -1339,7 +1346,7 @@ public: CONTRACTL_END; IGCHandleTable *pHandleTable = GCHandleTableUtilities::GetGCHandleTable(); - return pHandleTable->CreateDependentHandle((void*)m_hHandleTableBucket->pTable[GetCurrentThreadHomeHeapNumber()], OBJECTREFToObject(primary), OBJECTREFToObject(secondary)); + return pHandleTable->CreateDependentHandle(m_gcHandleTable, OBJECTREFToObject(primary), OBJECTREFToObject(secondary)); } #endif // DACCESS_COMPILE && !CROSSGEN_COMPILE @@ -1395,8 +1402,7 @@ protected: CLRPrivBinderCoreCLR *m_pTPABinderContext; // Reference to the binding context that holds TPA list details - - HandleTableBucket *m_hHandleTableBucket; + void* m_gcHandleTable; // The large heap handle table. LargeHeapHandleTable *m_pLargeHeapHandleTable; diff --git a/src/vm/exstate.cpp b/src/vm/exstate.cpp index 29c7a06..6cca98f 100644 --- a/src/vm/exstate.cpp +++ b/src/vm/exstate.cpp @@ -102,7 +102,7 @@ void ThreadExceptionState::FreeAllStackTraces() } } -void ThreadExceptionState::ClearThrowablesForUnload(HandleTableBucket* pHndTblBucket) +void ThreadExceptionState::ClearThrowablesForUnload(void* handleTable) { WRAPPER_NO_CONTRACT; @@ -112,11 +112,13 @@ void ThreadExceptionState::ClearThrowablesForUnload(HandleTableBucket* pHndTblBu ExInfo* pNode = &m_currentExInfo; #endif // WIN64EXCEPTIONS + IGCHandleTable *pHandleTable = GCHandleTableUtilities::GetGCHandleTable(); + for ( ; pNode != NULL; pNode = pNode->m_pPrevNestedInfo) { - if (pHndTblBucket->Contains(pNode->m_hThrowable)) + if (pHandleTable->ContainsHandle(handleTable, pNode->m_hThrowable)) { pNode->DestroyExceptionHandle(); } diff --git a/src/vm/exstate.h b/src/vm/exstate.h index 34f6427..79a8f57 100644 --- a/src/vm/exstate.h +++ b/src/vm/exstate.h @@ -56,7 +56,7 @@ class ThreadExceptionState public: void FreeAllStackTraces(); - void ClearThrowablesForUnload(HandleTableBucket* pHndTblBucket); + void ClearThrowablesForUnload(void* handleTable); #ifdef _DEBUG typedef enum diff --git a/src/vm/gchandletableutilities.h b/src/vm/gchandletableutilities.h index 003136f..6e32add 100644 --- a/src/vm/gchandletableutilities.h +++ b/src/vm/gchandletableutilities.h @@ -64,49 +64,54 @@ inline BOOL ObjectHandleIsNull(OBJECTHANDLE handle) // Handle creation convenience functions -inline OBJECTHANDLE CreateHandle(HHANDLETABLE table, OBJECTREF object) +inline OBJECTHANDLE CreateHandle(void* table, OBJECTREF object) { return GCHandleTableUtilities::GetGCHandleTable()->CreateHandleOfType(table, OBJECTREFToObject(object), HNDTYPE_DEFAULT); } -inline OBJECTHANDLE CreateWeakHandle(HHANDLETABLE table, OBJECTREF object) +inline OBJECTHANDLE CreateWeakHandle(void* table, OBJECTREF object) { return GCHandleTableUtilities::GetGCHandleTable()->CreateHandleOfType(table, OBJECTREFToObject(object), HNDTYPE_WEAK_DEFAULT); } -inline OBJECTHANDLE CreateShortWeakHandle(HHANDLETABLE table, OBJECTREF object) +inline OBJECTHANDLE CreateShortWeakHandle(void* table, OBJECTREF object) { return GCHandleTableUtilities::GetGCHandleTable()->CreateHandleOfType(table, OBJECTREFToObject(object), HNDTYPE_WEAK_SHORT); } -inline OBJECTHANDLE CreateLongWeakHandle(HHANDLETABLE table, OBJECTREF object) +inline OBJECTHANDLE CreateLongWeakHandle(void* table, OBJECTREF object) { return GCHandleTableUtilities::GetGCHandleTable()->CreateHandleOfType(table, OBJECTREFToObject(object), HNDTYPE_WEAK_LONG); } -inline OBJECTHANDLE CreateStrongHandle(HHANDLETABLE table, OBJECTREF object) +inline OBJECTHANDLE CreateStrongHandle(void* table, OBJECTREF object) { return GCHandleTableUtilities::GetGCHandleTable()->CreateHandleOfType(table, OBJECTREFToObject(object), HNDTYPE_STRONG); } -inline OBJECTHANDLE CreatePinningHandle(HHANDLETABLE table, OBJECTREF object) +inline OBJECTHANDLE CreatePinningHandle(void* table, OBJECTREF object) { return GCHandleTableUtilities::GetGCHandleTable()->CreateHandleOfType(table, OBJECTREFToObject(object), HNDTYPE_PINNED); } -inline OBJECTHANDLE CreateSizedRefHandle(HHANDLETABLE table, OBJECTREF object) +inline OBJECTHANDLE CreateAsyncPinningHandle(void* table, OBJECTREF object) { - return GCHandleTableUtilities::GetGCHandleTable()->CreateHandleOfType(table, OBJECTREFToObject(object), HNDTYPE_SIZEDREF); + return GCHandleTableUtilities::GetGCHandleTable()->CreateHandleOfType(table, OBJECTREFToObject(object), HNDTYPE_ASYNCPINNED); } -inline OBJECTHANDLE CreateAsyncPinningHandle(HHANDLETABLE table, OBJECTREF object) +inline OBJECTHANDLE CreateRefcountedHandle(void* table, OBJECTREF object) { - return GCHandleTableUtilities::GetGCHandleTable()->CreateHandleOfType(table, OBJECTREFToObject(object), HNDTYPE_ASYNCPINNED); + return GCHandleTableUtilities::GetGCHandleTable()->CreateHandleOfType(table, OBJECTREFToObject(object), HNDTYPE_REFCOUNTED); } -inline OBJECTHANDLE CreateRefcountedHandle(HHANDLETABLE table, OBJECTREF object) +inline OBJECTHANDLE CreateSizedRefHandle(void* table, OBJECTREF object) { - return GCHandleTableUtilities::GetGCHandleTable()->CreateHandleOfType(table, OBJECTREFToObject(object), HNDTYPE_REFCOUNTED); + return GCHandleTableUtilities::GetGCHandleTable()->CreateHandleOfType(table, OBJECTREFToObject(object), HNDTYPE_SIZEDREF); +} + +inline OBJECTHANDLE CreateSizedRefHandle(void* table, OBJECTREF object, int heapToAffinitizeTo) +{ + return GCHandleTableUtilities::GetGCHandleTable()->CreateHandleOfType(table, OBJECTREFToObject(object), HNDTYPE_SIZEDREF, heapToAffinitizeTo); } // Global handle creation convenience functions @@ -152,7 +157,7 @@ inline OBJECTHANDLE CreateGlobalRefcountedHandle(OBJECTREF object) // Special handle creation convenience functions #ifdef FEATURE_COMINTEROP -inline OBJECTHANDLE CreateWinRTWeakHandle(HHANDLETABLE table, OBJECTREF object, IWeakReference* pWinRTWeakReference) +inline OBJECTHANDLE CreateWinRTWeakHandle(void* table, OBJECTREF object, IWeakReference* pWinRTWeakReference) { return GCHandleTableUtilities::GetGCHandleTable()->CreateHandleWithExtraInfo(table, OBJECTREFToObject(object), @@ -162,7 +167,7 @@ inline OBJECTHANDLE CreateWinRTWeakHandle(HHANDLETABLE table, OBJECTREF object, #endif // FEATURE_COMINTEROP // Creates a variable-strength handle -inline OBJECTHANDLE CreateVariableHandle(HHANDLETABLE table, OBJECTREF object, uint32_t type) +inline OBJECTHANDLE CreateVariableHandle(void* table, OBJECTREF object, uint32_t type) { return GCHandleTableUtilities::GetGCHandleTable()->CreateHandleWithExtraInfo(table, OBJECTREFToObject(object), -- 2.7.4