From 1818734c4b4abdcd4970888af4038cd5caaad99c Mon Sep 17 00:00:00 2001 From: Sean Gillespie Date: Sun, 9 Apr 2017 13:58:29 -0700 Subject: [PATCH] [Local GC] Move knowledge of the free object method table outside of the GC (dotnet/coreclr#10755) * [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 | 1 + src/coreclr/src/gc/gc.cpp | 24 +++++++++++++----------- src/coreclr/src/gc/gc.h | 1 + src/coreclr/src/gc/gccommon.cpp | 1 + src/coreclr/src/gc/gcenv.ee.standalone.inl | 5 +++++ src/coreclr/src/gc/gcinterface.ee.h | 10 ++++++++++ src/coreclr/src/gc/sample/gcenv.ee.cpp | 5 +++++ src/coreclr/src/vm/gcenv.ee.cpp | 6 ++++++ src/coreclr/src/vm/gcenv.ee.h | 1 + 9 files changed, 43 insertions(+), 11 deletions(-) diff --git a/src/coreclr/src/gc/env/gcenv.ee.h b/src/coreclr/src/gc/env/gcenv.ee.h index 5914f33..aa00d19 100644 --- a/src/coreclr/src/gc/env/gcenv.ee.h +++ b/src/coreclr/src/gc/env/gcenv.ee.h @@ -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__ diff --git a/src/coreclr/src/gc/gc.cpp b/src/coreclr/src/gc/gc.cpp index ca03aaf..ecc13e3 100644 --- a/src/coreclr/src/gc/gc.cpp +++ b/src/coreclr/src/gc/gc.cpp @@ -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; diff --git a/src/coreclr/src/gc/gc.h b/src/coreclr/src/gc/gc.h index 8cd92fd..a661c31 100644 --- a/src/coreclr/src/gc/gc.h +++ b/src/coreclr/src/gc/gc.h @@ -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(); diff --git a/src/coreclr/src/gc/gccommon.cpp b/src/coreclr/src/gc/gccommon.cpp index 1cd3c82..f931597 100644 --- a/src/coreclr/src/gc/gccommon.cpp +++ b/src/coreclr/src/gc/gccommon.cpp @@ -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) diff --git a/src/coreclr/src/gc/gcenv.ee.standalone.inl b/src/coreclr/src/gc/gcenv.ee.standalone.inl index f26a776..f6954fc 100644 --- a/src/coreclr/src/gc/gcenv.ee.standalone.inl +++ b/src/coreclr/src/gc/gcenv.ee.standalone.inl @@ -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__ diff --git a/src/coreclr/src/gc/gcinterface.ee.h b/src/coreclr/src/gc/gcinterface.ee.h index 3723dab..7b868e7 100644 --- a/src/coreclr/src/gc/gcinterface.ee.h +++ b/src/coreclr/src/gc/gcinterface.ee.h @@ -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_ diff --git a/src/coreclr/src/gc/sample/gcenv.ee.cpp b/src/coreclr/src/gc/sample/gcenv.ee.cpp index 0f7dca1..fa6efbf 100644 --- a/src/coreclr/src/gc/sample/gcenv.ee.cpp +++ b/src/coreclr/src/gc/sample/gcenv.ee.cpp @@ -286,6 +286,11 @@ bool GCToEEInterface::EagerFinalized(Object* obj) return false; } +MethodTable* GCToEEInterface::GetFreeObjectMethodTable() +{ + return g_pFreeObjectMethodTable; +} + bool IsGCSpecialThread() { // TODO: Implement for background GC diff --git a/src/coreclr/src/vm/gcenv.ee.cpp b/src/coreclr/src/vm/gcenv.ee.cpp index f11b8f9..54c7991 100644 --- a/src/coreclr/src/vm/gcenv.ee.cpp +++ b/src/coreclr/src/vm/gcenv.ee.cpp @@ -1394,3 +1394,9 @@ bool GCToEEInterface::EagerFinalized(Object* obj) return false; } + +MethodTable* GCToEEInterface::GetFreeObjectMethodTable() +{ + assert(g_pFreeObjectMethodTable != nullptr); + return g_pFreeObjectMethodTable; +} diff --git a/src/coreclr/src/vm/gcenv.ee.h b/src/coreclr/src/vm/gcenv.ee.h index 424dea7..9f7df14 100644 --- a/src/coreclr/src/vm/gcenv.ee.h +++ b/src/coreclr/src/vm/gcenv.ee.h @@ -48,6 +48,7 @@ public: bool ShouldFinalizeObjectForUnload(AppDomain* pDomain, Object* obj); bool ForceFullGCToBeBlocking(); bool EagerFinalized(Object* obj); + MethodTable* GetFreeObjectMethodTable(); }; #endif // FEATURE_STANDALONE_GC -- 2.7.4