[Local GC] Move knowledge of the free object method table outside of the GC (dotnet...
authorSean Gillespie <sean@swgillespie.me>
Sun, 9 Apr 2017 20:58:29 +0000 (13:58 -0700)
committerGitHub <noreply@github.com>
Sun, 9 Apr 2017 20:58:29 +0000 (13:58 -0700)
* [Local GC] Move knowledge of the free object method table outside of the GC

* Revert "[Local GC] Move knowledge of the free object method table outside of the GC"

This reverts commit dotnet/coreclr@02979e5eb12dd44edb2603e16411dd7d7ffc377d.

* Address code review feedback: leave ArrayBase alone, as it should be part of the binary contract between the EE and the GC

* Correct a bad merge

Commit migrated from https://github.com/dotnet/coreclr/commit/2dfc74df1f9fe238eb2ec25c4764b8b65432b010

src/coreclr/src/gc/env/gcenv.ee.h
src/coreclr/src/gc/gc.cpp
src/coreclr/src/gc/gc.h
src/coreclr/src/gc/gccommon.cpp
src/coreclr/src/gc/gcenv.ee.standalone.inl
src/coreclr/src/gc/gcinterface.ee.h
src/coreclr/src/gc/sample/gcenv.ee.cpp
src/coreclr/src/vm/gcenv.ee.cpp
src/coreclr/src/vm/gcenv.ee.h

index 5914f33..aa00d19 100644 (file)
@@ -73,6 +73,7 @@ public:
     static bool ShouldFinalizeObjectForUnload(AppDomain* pDomain, Object* obj);
     static bool ForceFullGCToBeBlocking();
     static bool EagerFinalized(Object* obj);
+    static MethodTable* GetFreeObjectMethodTable();
 };
 
 #endif // __GCENV_EE_H__
index ca03aaf..ecc13e3 100644 (file)
@@ -3891,10 +3891,10 @@ public:
     {
         assert (size >= free_object_base_size);
 
-        assert (g_pFreeObjectMethodTable->GetBaseSize() == free_object_base_size);
-        assert (g_pFreeObjectMethodTable->RawGetComponentSize() == 1);
+        assert (g_gc_pFreeObjectMethodTable->GetBaseSize() == free_object_base_size);
+        assert (g_gc_pFreeObjectMethodTable->RawGetComponentSize() == 1);
 
-        RawSetMethodTable( g_pFreeObjectMethodTable );
+        RawSetMethodTable( g_gc_pFreeObjectMethodTable );
 
         size_t* numComponentsPtr = (size_t*) &((uint8_t*) this)[ArrayBase::GetOffsetOfNumComponents()];
         *numComponentsPtr = size - free_object_base_size;
@@ -3919,7 +3919,7 @@ public:
 
     BOOL IsFree () const
     {
-        return (GetMethodTable() == g_pFreeObjectMethodTable);
+        return (GetMethodTable() == g_gc_pFreeObjectMethodTable);
     }
 
 #ifdef FEATURE_STRUCTALIGN
@@ -21090,7 +21090,7 @@ BOOL gc_heap::plan_loh()
         {
             while (o < heap_segment_allocated (seg) && !marked (o))
             {
-                dprintf (1235, ("%Ix(%Id) F (%d)", o, AlignQword (size (o)), ((method_table (o) == g_pFreeObjectMethodTable) ? 1 : 0)));
+                dprintf (1235, ("%Ix(%Id) F (%d)", o, AlignQword (size (o)), ((method_table (o) == g_gc_pFreeObjectMethodTable) ? 1 : 0)));
                 o = o + AlignQword (size (o));
             }
         }
@@ -24346,7 +24346,7 @@ void gc_heap::walk_survivors_for_bgc (void* profiling_context, record_surv_fn fn
 
         while (o < end)
         {
-            if (method_table(o) == g_pFreeObjectMethodTable)
+            if (method_table(o) == g_gc_pFreeObjectMethodTable)
             {
                 o += Align (size (o), align_const);
                 continue;
@@ -24357,7 +24357,7 @@ void gc_heap::walk_survivors_for_bgc (void* profiling_context, record_surv_fn fn
 
             uint8_t* plug_start = o;
 
-            while (method_table(o) != g_pFreeObjectMethodTable)
+            while (method_table(o) != g_gc_pFreeObjectMethodTable)
             {
                 o += Align (size (o), align_const);
                 if (o >= end)
@@ -31543,7 +31543,7 @@ void gc_heap::background_sweep()
                     seg = start_seg;
                     prev_seg = 0;
                     o = generation_allocation_start (gen);
-                    assert (method_table (o) == g_pFreeObjectMethodTable);
+                    assert (method_table (o) == g_gc_pFreeObjectMethodTable);
                     align_const = get_alignment_constant (FALSE);
                     o = o + Align(size (o), align_const);
                     plug_end = o;
@@ -32885,7 +32885,7 @@ void gc_heap::verify_partial ()
                             //dprintf (3, ("VOM: verifying member %Ix in obj %Ix", (size_t)*oo, o));
                             MethodTable *pMT = method_table (*oo);
 
-                            if (pMT == g_pFreeObjectMethodTable)
+                            if (pMT == g_gc_pFreeObjectMethodTable)
                             {
                                 free_ref_p = TRUE;
                                 FATAL_GC_ERROR();
@@ -33319,12 +33319,12 @@ gc_heap::verify_heap (BOOL begin_gc_p)
             }
         }
 
-        if (*((uint8_t**)curr_object) != (uint8_t *) g_pFreeObjectMethodTable)
+        if (*((uint8_t**)curr_object) != (uint8_t *) g_gc_pFreeObjectMethodTable)
         {
 #ifdef FEATURE_LOH_COMPACTION
             if ((curr_gen_num == (max_generation+1)) && (prev_object != 0))
             {
-                assert (method_table (prev_object) == g_pFreeObjectMethodTable);
+                assert (method_table (prev_object) == g_gc_pFreeObjectMethodTable);
             }
 #endif //FEATURE_LOH_COMPACTION
 
@@ -33630,6 +33630,8 @@ HRESULT GCHeap::Initialize ()
         return E_FAIL;
     }
 
+    g_gc_pFreeObjectMethodTable = GCToEEInterface::GetFreeObjectMethodTable();
+
 //Initialize the static members.
 #ifdef TRACE_GC
     GcDuration = 0;
index 8cd92fd..a661c31 100644 (file)
@@ -113,6 +113,7 @@ extern "C" uint8_t* g_gc_lowest_address;
 extern "C" uint8_t* g_gc_highest_address;
 extern "C" GCHeapType g_gc_heap_type;
 extern "C" uint32_t g_max_generation;
+extern "C" MethodTable* g_gc_pFreeObjectMethodTable;
 
 ::IGCHandleTable*  CreateGCHandleTable();
 
index 1cd3c82..f931597 100644 (file)
@@ -43,6 +43,7 @@ uint8_t* g_gc_lowest_address  = 0;
 uint8_t* g_gc_highest_address = 0;
 GCHeapType g_gc_heap_type = GC_HEAP_INVALID;
 uint32_t g_max_generation = max_generation;
+MethodTable* g_gc_pFreeObjectMethodTable = nullptr;
 
 #ifdef GC_CONFIG_DRIVEN
 void record_global_mechanism (int mech_index)
index f26a776..f6954fc 100644 (file)
@@ -231,6 +231,11 @@ ALWAYS_INLINE bool GCToEEInterface::EagerFinalized(Object* obj)
     return g_theGCToCLR->EagerFinalized(obj);
 }
 
+ALWAYS_INLINE MethodTable* GCToEEInterface::GetFreeObjectMethodTable()
+{
+    assert(g_theGCToCLR != nullptr);
+    return g_theGCToCLR->GetFreeObjectMethodTable();
+}
 #undef ALWAYS_INLINE
 
 #endif // __GCTOENV_EE_STANDALONE_INL__
index 3723dab..7b868e7 100644 (file)
@@ -156,6 +156,16 @@ public:
     // the EE can opt to elevate that collection to be a blocking GC and not a background one.
     virtual
     bool ForceFullGCToBeBlocking() = 0;
+
+    // Retrieves the method table for the free object, a special kind of object used by the GC
+    // to keep the heap traversable. Conceptually, the free object is similar to a managed array
+    // of bytes: it consists of an object header (like all objects) and a "numComponents" field,
+    // followed by some number of bytes of space that's free on the heap.
+    //
+    // The free object allows the GC to traverse the heap because it can inspect the numComponents
+    // field to see how many bytes to skip before the next object on a heap segment begins.
+    virtual
+    MethodTable* GetFreeObjectMethodTable() = 0;
 };
 
 #endif // _GCINTERFACE_EE_H_
index 0f7dca1..fa6efbf 100644 (file)
@@ -286,6 +286,11 @@ bool GCToEEInterface::EagerFinalized(Object* obj)
     return false;
 }
 
+MethodTable* GCToEEInterface::GetFreeObjectMethodTable()
+{
+    return g_pFreeObjectMethodTable;
+}
+
 bool IsGCSpecialThread()
 {
     // TODO: Implement for background GC
index f11b8f9..54c7991 100644 (file)
@@ -1394,3 +1394,9 @@ bool GCToEEInterface::EagerFinalized(Object* obj)
 
     return false;
 }
+
+MethodTable* GCToEEInterface::GetFreeObjectMethodTable()
+{
+    assert(g_pFreeObjectMethodTable != nullptr);
+    return g_pFreeObjectMethodTable;
+}
index 424dea7..9f7df14 100644 (file)
@@ -48,6 +48,7 @@ public:
     bool ShouldFinalizeObjectForUnload(AppDomain* pDomain, Object* obj);
     bool ForceFullGCToBeBlocking();
     bool EagerFinalized(Object* obj);
+    MethodTable* GetFreeObjectMethodTable();
 };
 
 #endif // FEATURE_STANDALONE_GC