diff options
Diffstat (limited to 'src/vm/gcheaputilities.h')
-rw-r--r-- | src/vm/gcheaputilities.h | 81 |
1 files changed, 40 insertions, 41 deletions
diff --git a/src/vm/gcheaputilities.h b/src/vm/gcheaputilities.h index e76a21173c..e4812ce8c0 100644 --- a/src/vm/gcheaputilities.h +++ b/src/vm/gcheaputilities.h @@ -16,10 +16,18 @@ extern "C" { GPTR_DECL(uint8_t,g_lowest_address); GPTR_DECL(uint8_t,g_highest_address); GPTR_DECL(uint32_t,g_card_table); +GVAL_DECL(GCHeapType, g_heap_type); #ifndef DACCESS_COMPILE } #endif // !DACCESS_COMPILE +// For single-proc machines, the EE will use a single, shared alloc context +// for all allocations. In order to avoid extra indirections in assembly +// allocation helpers, the EE owns the global allocation context and the +// GC will update it when it needs to. +extern "C" gc_alloc_context g_global_alloc_context; + +extern "C" uint32_t* g_card_bundle_table; extern "C" uint8_t* g_ephemeral_low; extern "C" uint8_t* g_ephemeral_high; @@ -34,6 +42,21 @@ extern "C" bool g_sw_ww_enabled_for_gc_heap; #endif // FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP +// g_gc_dac_vars is a structure of pointers to GC globals that the +// DAC uses. It is not exposed directly to the DAC. +extern GcDacVars g_gc_dac_vars; + +// Instead of exposing g_gc_dac_vars to the DAC, a pointer to it +// is exposed here (g_gcDacGlobals). The reason for this is to avoid +// a problem in which a debugger attaches to a program while the program +// is in the middle of initializing the GC DAC vars - if the "publishing" +// of DAC vars isn't atomic, the debugger could see a partially initialized +// GcDacVars structure. +// +// Instead, the debuggee "publishes" GcDacVars by assigning a pointer to g_gc_dac_vars +// to this global, and the DAC will read this global. +typedef DPTR(GcDacVars) PTR_GcDacVars; +GPTR_DECL(GcDacVars, g_gcDacGlobals); // GCHeapUtilities provides a number of static methods // that operate on the global heap instance. It can't be @@ -59,7 +82,7 @@ public: // Returns true if a the heap is initialized and a garbage collection // is in progress, false otherwise. - inline static BOOL IsGCInProgress(BOOL bConsiderGCStart = FALSE) + inline static bool IsGCInProgress(bool bConsiderGCStart = false) { WRAPPER_NO_CONTRACT; @@ -68,7 +91,7 @@ public: // Returns true if we should be competing marking for statics. This // influences the behavior of `GCToEEInterface::GcScanRoots`. - inline static BOOL MarkShouldCompeteForStatics() + inline static bool MarkShouldCompeteForStatics() { WRAPPER_NO_CONTRACT; @@ -76,7 +99,7 @@ public: } // Waits until a GC is complete, if the heap has been initialized. - inline static void WaitForGCCompletion(BOOL bConsiderGCStart = FALSE) + inline static void WaitForGCCompletion(bool bConsiderGCStart = false) { WRAPPER_NO_CONTRACT; @@ -84,53 +107,29 @@ public: GetGCHeap()->WaitUntilGCComplete(bConsiderGCStart); } - // Returns true if we should be using allocation contexts, false otherwise. - inline static bool UseAllocationContexts() - { - WRAPPER_NO_CONTRACT; -#ifdef FEATURE_REDHAWK - // SIMPLIFY: only use allocation contexts - return true; -#else -#if defined(_TARGET_ARM_) || defined(FEATURE_PAL) - return true; -#else - return ((IsServerHeap() ? true : (g_SystemInfo.dwNumberOfProcessors >= 2))); -#endif -#endif - } - // Returns true if the held GC heap is a Server GC heap, false otherwise. inline static bool IsServerHeap() { LIMITED_METHOD_CONTRACT; + #ifdef FEATURE_SVR_GC - _ASSERTE(IGCHeap::gcHeapType != IGCHeap::GC_HEAP_INVALID); - return (IGCHeap::gcHeapType == IGCHeap::GC_HEAP_SVR); -#else // FEATURE_SVR_GC + _ASSERTE(g_heap_type != GC_HEAP_INVALID); + return g_heap_type == GC_HEAP_SVR; +#else return false; #endif // FEATURE_SVR_GC } - // Gets the maximum generation number by reading the static field - // on IGCHeap. This should only be done by the DAC code paths - all other code - // should go through IGCHeap::GetMaxGeneration. - // - // The reason for this is that, while we are in the early stages of - // decoupling the GC, the GC and the DAC still remain tightly coupled - // and, in particular, the DAC needs to know how many generations the GC - // has. However, it is not permitted to invoke virtual methods on g_pGCHeap - // while on a DAC code path. Therefore, we need to determine the max generation - // non-virtually, while still in a manner consistent with the interface - - // therefore, a static field is used. - // - // This is not without precedent - IGCHeap::gcHeapType is a static field used - // for a similar reason (the DAC needs to know what kind of heap it's looking at). - inline static unsigned GetMaxGeneration() + static bool UseThreadAllocationContexts() { - WRAPPER_NO_CONTRACT; + // When running on a single-proc system, it's more efficient to use a single global + // allocation context for SOH allocations than to use one for every thread. +#if defined(_TARGET_ARM_) || defined(FEATURE_PAL) || defined(FEATURE_REDHAWK) + return true; +#else + return IsServerHeap() || ::GetCurrentProcessCpuCount() != 1; +#endif - return IGCHeap::maxGeneration; } #ifdef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP @@ -197,10 +196,10 @@ public: } #endif // FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP - private: // This class should never be instantiated. GCHeapUtilities() = delete; }; -#endif // _GCHEAPUTILITIES_H_
\ No newline at end of file +#endif // _GCHEAPUTILITIES_H_ + |