summaryrefslogtreecommitdiff
path: root/src/vm/gcheaputilities.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm/gcheaputilities.h')
-rw-r--r--src/vm/gcheaputilities.h81
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_
+