Change how VM calls ObjectFromHandle.
authorAditya Mandaleeka <adityam@microsoft.com>
Sat, 1 Apr 2017 00:12:03 +0000 (17:12 -0700)
committerAditya Mandaleeka <adityam@microsoft.com>
Sat, 1 Apr 2017 02:30:25 +0000 (19:30 -0700)
12 files changed:
src/debug/daccess/dacdbiimpl.cpp
src/debug/daccess/request.cpp
src/gc/gc.cpp
src/gc/gchandletable.cpp
src/gc/gchandletableimpl.h
src/gc/gcinterface.h
src/gc/handletable.h
src/gc/objecthandle.h
src/gc/sample/GCSample.cpp
src/vm/exinfo.h
src/vm/gcheaputilities.cpp
src/vm/gcheaputilities.h

index 74ba14f2eb74441a12f14dc84cfa26c1a8284dc6..605d5c7cee75b0932c6661c1649ac9b00e38738a 100644 (file)
@@ -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())
index c30501f374f2a184ec57c2d9515a86ee77b85c31..c52b6cd3c18528c604e318627d53c07a843b9002 100644 (file)
@@ -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;
index 9435357eebe27549e678a172cadb2dab2b4503d6..fa98c6e76d4933c8f005cf3c7fdbd7d7d217f544 100644 (file)
@@ -34206,11 +34206,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);
@@ -34242,7 +34242,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.
index c096d9fbd6f707a065a12044f9a38c6f86d95c23..f468bd300f203237146135371dacd4cb2d220eb6 100644 (file)
@@ -23,12 +23,12 @@ void GCHandleTable::Shutdown()
     Ref_Shutdown();
 }
 
-void* GCHandleTable::GetHandleTableContext(HHANDLETABLE hTable)
+void* GCHandleTable::GetHandleTableContext(void* handleTable)
 {
-    return (void*)((uintptr_t)::HndGetHandleTableADIndex(hTable).m_dwIndex);
+    return (void*)((uintptr_t)::HndGetHandleTableADIndex((HHANDLETABLE)handleTable).m_dwIndex);
 }
 
-HHANDLETABLE GCHandleTable::GetHandleTableForHandle(OBJECTHANDLE handle)
+void* GCHandleTable::GetHandleTableForHandle(OBJECTHANDLE handle)
 {
-    return ::HndGetHandleTable(handle);
+    return (void*)::HndGetHandleTable(handle);
 }
index eafb0a03984b357fb916f183ef2bb032f04cfb72..11fa163df785c69b5ac5fb9b9e5e8d211a2f5824 100644 (file)
@@ -14,9 +14,9 @@ public:
 
     virtual void Shutdown();
 
-    virtual void* GetHandleTableContext(HHANDLETABLE hTable);
+    virtual void* GetHandleTableContext(void* handleTable);
 
-    virtual HHANDLETABLE GetHandleTableForHandle(OBJECTHANDLE handle);
+    virtual void* GetHandleTableForHandle(OBJECTHANDLE handle);
 };
 
 #endif  // GCHANDLETABLE_H_
index e1e73012479df1bc3f6b9a9184d6e71f5b1859e5..b5a9e0e8f9bbafa3de7f242fd1b354105f9c30eb 100644 (file)
@@ -153,14 +153,6 @@ struct segment_info
     size_t ibReserved; // limit of reserved memory in the segment (>= commit)
 };
 
-
-/*
- * handle to handle table
- */
-typedef DPTR(struct HandleTable) PTR_HandleTable;
-typedef DPTR(PTR_HandleTable) PTR_PTR_HandleTable;
-typedef PTR_HandleTable HHANDLETABLE;
-typedef PTR_PTR_HandleTable PTR_HHANDLETABLE;
 #ifdef PROFILING_SUPPORTED
 #define GC_PROFILING       //Turn on profiling
 #endif // PROFILING_SUPPORTED
@@ -400,9 +392,9 @@ public:
 
     virtual void Shutdown() = 0;
 
-    virtual void* GetHandleTableContext(HHANDLETABLE hTable) = 0;
+    virtual void* GetHandleTableContext(void* handleTable) = 0;
 
-    virtual HHANDLETABLE GetHandleTableForHandle(OBJECTHANDLE handle) = 0;
+    virtual void* GetHandleTableForHandle(OBJECTHANDLE handle) = 0;
 };
 
 // IGCHeap is the interface that the VM will use when interacting with the GC.
index 2e847659f3b6dd2f494bd8bf28ca1726cea189d7..5b0299fe028863153be31fec378edefed419bf03 100644 (file)
@@ -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;
index b86572b276cb1c740076994b1adce57dddd813b2..386c5d45120cc499960e3e90cccfc9c386e7752a 100644 (file)
@@ -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));
 }
 
 
index 5d5371c76ec3da94c8366a02dc963090d2a51a76..45915c0d04ac720e11a8630bbf18328df2141e40 100644 (file)
@@ -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");
 
index 6b34e7111609272b6205ff9460aab4e234f6d705..4a6c3e5dcca9e6273f8c5b1021e3aa51171fc75c 100644 (file)
@@ -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;
index e24f1ad7c3031959a60ae6b7e5eabf88684c6d89..730728927ac238f2bd3e567e4eba4aa6885ffe18 100644 (file)
@@ -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
@@ -35,3 +37,38 @@ bool g_sw_ww_enabled_for_gc_heap = false;
 #endif // FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP
 
 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
+}
index 1e920127fe5f8dc67feceae1b4cbe7bb98d9e112..064165bc11c1f04c49c2d03f33ea5735145b0c5b 100644 (file)
@@ -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_