diff options
author | Aditya Mandaleeka <adityamandaleeka@users.noreply.github.com> | 2017-04-01 12:25:08 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-04-01 12:25:08 -0700 |
commit | 036ff00ad33e3bdd8f0eef7513af331eb841d5b9 (patch) | |
tree | a0fad66ce5474a1090433d673ccd67316a7200bb /src | |
parent | b1928070df5ab896e9b3f635f577b9be7e848385 (diff) | |
parent | 958279de27e7f3c30ad53e35277653d1ec0f1e6e (diff) | |
download | coreclr-036ff00ad33e3bdd8f0eef7513af331eb841d5b9.tar.gz coreclr-036ff00ad33e3bdd8f0eef7513af331eb841d5b9.tar.bz2 coreclr-036ff00ad33e3bdd8f0eef7513af331eb841d5b9.zip |
Merge pull request #10584 from adityamandaleeka/handle_table_local_gc_init
Change how the VM calls ObjectFromHandle.
Diffstat (limited to 'src')
-rw-r--r-- | src/debug/daccess/dacdbiimpl.cpp | 4 | ||||
-rw-r--r-- | src/debug/daccess/request.cpp | 4 | ||||
-rw-r--r-- | src/gc/gc.cpp | 6 | ||||
-rw-r--r-- | src/gc/gchandletable.cpp | 10 | ||||
-rw-r--r-- | src/gc/gchandletableimpl.h | 4 | ||||
-rw-r--r-- | src/gc/gcinterface.h | 6 | ||||
-rw-r--r-- | src/gc/handletable.h | 5 | ||||
-rw-r--r-- | src/gc/objecthandle.h | 3 | ||||
-rw-r--r-- | src/gc/sample/GCSample.cpp | 10 | ||||
-rw-r--r-- | src/vm/exinfo.h | 2 | ||||
-rw-r--r-- | src/vm/gcheaputilities.cpp | 36 | ||||
-rw-r--r-- | src/vm/gcheaputilities.h | 17 |
12 files changed, 90 insertions, 17 deletions
diff --git a/src/debug/daccess/dacdbiimpl.cpp b/src/debug/daccess/dacdbiimpl.cpp index 74ba14f2eb..605d5c7cee 100644 --- a/src/debug/daccess/dacdbiimpl.cpp +++ b/src/debug/daccess/dacdbiimpl.cpp @@ -5718,9 +5718,9 @@ BOOL DacDbiInterfaceImpl::IsVmObjectHandleValid(VMPTR_OBJECTHANDLE vmHandle) // SEH exceptions will be caught EX_TRY { - OBJECTREF objRef = ObjectFromHandle((OBJECTHANDLE)vmHandle.GetDacPtr()); + OBJECTREF objRef = HndFetchHandle((OBJECTHANDLE)vmHandle.GetDacPtr()); - // NULL is certinally valid... + // NULL is certainly valid... if (objRef != NULL) { if (objRef->ValidateObjectWithPossibleAV()) diff --git a/src/debug/daccess/request.cpp b/src/debug/daccess/request.cpp index c30501f374..c52b6cd3c1 100644 --- a/src/debug/daccess/request.cpp +++ b/src/debug/daccess/request.cpp @@ -3890,7 +3890,7 @@ HRESULT ClrDataAccess::GetClrWatsonBucketsWorker(Thread * pThread, GenericModeBl if (ohThrowable != NULL) { // Get the object from handle and check if the throwable is preallocated or not - OBJECTREF oThrowable = ObjectFromHandle(ohThrowable); + OBJECTREF oThrowable = ::HndFetchHandle(ohThrowable); if (oThrowable != NULL) { // Does the throwable have buckets? @@ -4184,7 +4184,7 @@ HRESULT ClrDataAccess::GetCCWData(CLRDATA_ADDRESS ccw, struct DacpCCWData *ccwDa ccwData->isAggregated = pCCW->GetSimpleWrapper()->IsAggregated(); if (pCCW->GetObjectHandle() != NULL) - ccwData->managedObject = PTR_CDADDR(ObjectFromHandle(pCCW->GetObjectHandle())); + ccwData->managedObject = PTR_CDADDR(::HndFetchHandle(pCCW->GetObjectHandle())); // count the number of COM vtables ccwData->interfaceCount = 0; diff --git a/src/gc/gc.cpp b/src/gc/gc.cpp index 65c6742878..515069b7c2 100644 --- a/src/gc/gc.cpp +++ b/src/gc/gc.cpp @@ -34207,11 +34207,11 @@ bool GCHeap::StressHeap(gc_alloc_context * context) StringObject* str; // If the current string is used up - if (ObjectFromHandle(m_StressObjs[m_CurStressObj]) == 0) + if (HndFetchHandle(m_StressObjs[m_CurStressObj]) == 0) { // Populate handles with strings int i = m_CurStressObj; - while(ObjectFromHandle(m_StressObjs[i]) == 0) + while(HndFetchHandle(m_StressObjs[i]) == 0) { _ASSERTE(m_StressObjs[i] != 0); unsigned strLen = (LARGE_OBJECT_SIZE - 32) / sizeof(WCHAR); @@ -34243,7 +34243,7 @@ bool GCHeap::StressHeap(gc_alloc_context * context) } // Get the current string - str = (StringObject*) OBJECTREFToObject(ObjectFromHandle(m_StressObjs[m_CurStressObj])); + str = (StringObject*) OBJECTREFToObject(HndFetchHandle(m_StressObjs[m_CurStressObj])); if (str) { // Chop off the end of the string and form a new object out of it. diff --git a/src/gc/gchandletable.cpp b/src/gc/gchandletable.cpp index a4c3352b86..f468bd300f 100644 --- a/src/gc/gchandletable.cpp +++ b/src/gc/gchandletable.cpp @@ -22,3 +22,13 @@ void GCHandleTable::Shutdown() { Ref_Shutdown(); } + +void* GCHandleTable::GetHandleTableContext(void* handleTable) +{ + return (void*)((uintptr_t)::HndGetHandleTableADIndex((HHANDLETABLE)handleTable).m_dwIndex); +} + +void* GCHandleTable::GetHandleTableForHandle(OBJECTHANDLE handle) +{ + return (void*)::HndGetHandleTable(handle); +} diff --git a/src/gc/gchandletableimpl.h b/src/gc/gchandletableimpl.h index 233e326a64..11fa163df7 100644 --- a/src/gc/gchandletableimpl.h +++ b/src/gc/gchandletableimpl.h @@ -13,6 +13,10 @@ public: virtual bool Initialize(); virtual void Shutdown(); + + virtual void* GetHandleTableContext(void* handleTable); + + virtual void* GetHandleTableForHandle(OBJECTHANDLE handle); }; #endif // GCHANDLETABLE_H_ diff --git a/src/gc/gcinterface.h b/src/gc/gcinterface.h index 77425b1cc3..b5a9e0e8f9 100644 --- a/src/gc/gcinterface.h +++ b/src/gc/gcinterface.h @@ -149,7 +149,7 @@ struct segment_info void * pvMem; // base of the allocation, not the first object (must add ibFirstObject) size_t ibFirstObject; // offset to the base of the first object in the segment size_t ibAllocated; // limit of allocated memory in the segment (>= firstobject) - size_t ibCommit; // limit of committed memory in the segment (>= alllocated) + size_t ibCommit; // limit of committed memory in the segment (>= allocated) size_t ibReserved; // limit of reserved memory in the segment (>= commit) }; @@ -391,6 +391,10 @@ public: virtual bool Initialize() = 0; virtual void Shutdown() = 0; + + virtual void* GetHandleTableContext(void* handleTable) = 0; + + virtual void* GetHandleTableForHandle(OBJECTHANDLE handle) = 0; }; // IGCHeap is the interface that the VM will use when interacting with the GC. diff --git a/src/gc/handletable.h b/src/gc/handletable.h index 2e847659f3..5b0299fe02 100644 --- a/src/gc/handletable.h +++ b/src/gc/handletable.h @@ -177,8 +177,11 @@ BOOL HndFirstAssignHandle(OBJECTHANDLE handle, OBJECTREF objref); /* * inline handle dereferencing + * + * NOTE: Changes to this implementation should be kept in sync with ObjectFromHandle + * on the VM side. + * */ - FORCEINLINE OBJECTREF HndFetchHandle(OBJECTHANDLE handle) { WRAPPER_NO_CONTRACT; diff --git a/src/gc/objecthandle.h b/src/gc/objecthandle.h index b86572b276..386c5d4512 100644 --- a/src/gc/objecthandle.h +++ b/src/gc/objecthandle.h @@ -27,7 +27,6 @@ * non-NULL. In other words, if this handle is being initialized for the first * time. */ -#define ObjectFromHandle(handle) HndFetchHandle(handle) #define StoreObjectInHandle(handle, object) HndAssignHandle(handle, object) #define InterlockedCompareExchangeObjectInHandle(handle, object, oldObj) HndInterlockedCompareExchangeHandle(handle, object, oldObj) #define StoreFirstObjectInHandle(handle, object) HndFirstAssignHandle(handle, object) @@ -119,7 +118,7 @@ inline OBJECTHANDLE CreateDuplicateHandle(OBJECTHANDLE handle) { WRAPPER_NO_CONTRACT; // Create a new STRONG handle in the same table as an existing handle. - return HndCreateHandle(HndGetHandleTable(handle), HNDTYPE_DEFAULT, ObjectFromHandle(handle)); + return HndCreateHandle(HndGetHandleTable(handle), HNDTYPE_DEFAULT, HndFetchHandle(handle)); } diff --git a/src/gc/sample/GCSample.cpp b/src/gc/sample/GCSample.cpp index 5d5371c76e..45915c0d04 100644 --- a/src/gc/sample/GCSample.cpp +++ b/src/gc/sample/GCSample.cpp @@ -207,24 +207,24 @@ int __cdecl main(int argc, char* argv[]) for (int i = 0; i < 1000000; i++) { - Object * pBefore = ((My *)ObjectFromHandle(oh))->m_pOther1; + Object * pBefore = ((My *)HndFetchHandle(oh))->m_pOther1; // Allocate more instances of the same object Object * p = AllocateObject(pMyMethodTable); if (p == NULL) return -1; - Object * pAfter = ((My *)ObjectFromHandle(oh))->m_pOther1; + Object * pAfter = ((My *)HndFetchHandle(oh))->m_pOther1; // Uncomment this assert to see how GC triggered inside AllocateObject moved objects around // assert(pBefore == pAfter); // Store the newly allocated object into a field using WriteBarrier - WriteBarrier(&(((My *)ObjectFromHandle(oh))->m_pOther1), p); + WriteBarrier(&(((My *)HndFetchHandle(oh))->m_pOther1), p); } // Create weak handle that points to our object - OBJECTHANDLE ohWeak = CreateGlobalWeakHandle(ObjectFromHandle(oh)); + OBJECTHANDLE ohWeak = CreateGlobalWeakHandle(HndFetchHandle(oh)); if (ohWeak == NULL) return -1; @@ -235,7 +235,7 @@ int __cdecl main(int argc, char* argv[]) pGCHeap->GarbageCollect(); // Verify that the weak handle got cleared by the GC - assert(ObjectFromHandle(ohWeak) == NULL); + assert(HndFetchHandle(ohWeak) == NULL); printf("Done\n"); diff --git a/src/vm/exinfo.h b/src/vm/exinfo.h index 6b34e71116..4a6c3e5dcc 100644 --- a/src/vm/exinfo.h +++ b/src/vm/exinfo.h @@ -134,7 +134,7 @@ public: return m_pPrevNestedInfo; } - // Returns the throwble associated with the tracker + // Returns the throwable associated with the tracker inline OBJECTREF GetThrowable() { LIMITED_METHOD_CONTRACT; diff --git a/src/vm/gcheaputilities.cpp b/src/vm/gcheaputilities.cpp index aa90341159..730728927a 100644 --- a/src/vm/gcheaputilities.cpp +++ b/src/vm/gcheaputilities.cpp @@ -4,6 +4,8 @@ #include "common.h" #include "gcheaputilities.h" +#include "appdomain.hpp" + // These globals are variables used within the GC and maintained // by the EE for use in write barriers. It is the responsibility @@ -36,3 +38,37 @@ bool g_sw_ww_enabled_for_gc_heap = false; gc_alloc_context g_global_alloc_context = {}; +// Debug-only validation for handle. +void ValidateHandleAndAppDomain(OBJECTHANDLE handle) +{ +#ifdef _DEBUG_IMPL + OBJECTREF objRef = ObjectToOBJECTREF(*(Object**)handle); + VALIDATEOBJECTREF(objRef); + + IGCHandleTable *pHandleTable = GCHeapUtilities::GetGCHandleTable(); + + void* handleTable = pHandleTable->GetHandleTableForHandle(handle); + DWORD context = (DWORD)pHandleTable->GetHandleTableContext(handleTable); + + ADIndex appDomainIndex = ADIndex(context); + AppDomain *domain = SystemDomain::GetAppDomainAtIndex(appDomainIndex); + + // Access to a handle in an unloaded domain is not allowed + assert(domain != nullptr); + assert(!domain->NoAccessToHandleTable()); + +#if CHECK_APP_DOMAIN_LEAKS + if (g_pConfig->AppDomainLeaks() && objRef != NULL) + { + if (appDomainIndex.m_dwIndex) + { + objRef->TryAssignAppDomain(domain); + } + else + { + objRef->TrySetAppDomainAgile(); + } + } +#endif // CHECK_APP_DOMAIN_LEAKS +#endif // _DEBUG_IMPL +} diff --git a/src/vm/gcheaputilities.h b/src/vm/gcheaputilities.h index 1e920127fe..064165bc11 100644 --- a/src/vm/gcheaputilities.h +++ b/src/vm/gcheaputilities.h @@ -209,5 +209,22 @@ private: GCHeapUtilities() = delete; }; +// Handle-related utilities. + +void ValidateHandleAndAppDomain(OBJECTHANDLE handle); + +// Given a handle, returns an OBJECTREF for the object it refers to. +inline OBJECTREF ObjectFromHandle(OBJECTHANDLE handle) +{ + _ASSERTE(handle); + +#ifdef _DEBUG_IMPL + ValidateHandleAndAppDomain(handle); +#endif // _DEBUG_IMPL + + // Wrap the raw OBJECTREF and return it + return UNCHECKED_OBJECTREF_TO_OBJECTREF(*PTR_UNCHECKED_OBJECTREF(handle)); +} + #endif // _GCHEAPUTILITIES_H_ |