summaryrefslogtreecommitdiff
path: root/src/gc/gc.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/gc/gc.h')
-rw-r--r--src/gc/gc.h571
1 files changed, 104 insertions, 467 deletions
diff --git a/src/gc/gc.h b/src/gc/gc.h
index 14c6baee83..b7f1e956b6 100644
--- a/src/gc/gc.h
+++ b/src/gc/gc.h
@@ -14,9 +14,24 @@ Module Name:
#ifndef __GC_H
#define __GC_H
-#ifdef PROFILING_SUPPORTED
-#define GC_PROFILING //Turn on profiling
-#endif // PROFILING_SUPPORTED
+#ifdef Sleep
+// This is a funny workaround for the fact that "common.h" defines Sleep to be
+// Dont_Use_Sleep, with the hope of causing linker errors whenever someone tries to use sleep.
+//
+// However, GCToOSInterface defines a function called Sleep, which (due to this define) becomes
+// "Dont_Use_Sleep", which the GC in turn happily uses. The symbol that GCToOSInterface actually
+// exported was called "GCToOSInterface::Dont_Use_Sleep". While we progress in making the GC standalone,
+// we'll need to break the dependency on common.h (the VM header) and this problem will become moot.
+#undef Sleep
+#endif // Sleep
+
+#include "gcinterface.h"
+#include "env/gcenv.os.h"
+#include "env/gcenv.ee.h"
+
+#ifdef FEATURE_STANDALONE_GC
+#include "gcenv.ee.standalone.inl"
+#endif // FEATURE_STANDALONE_GC
/*
* Promotion Function Prototypes
@@ -26,19 +41,6 @@ typedef void enum_func (Object*);
// callback functions for heap walkers
typedef void object_callback_func(void * pvContext, void * pvDataLoc);
-// stub type to abstract a heap segment
-struct gc_heap_segment_stub;
-typedef gc_heap_segment_stub *segment_handle;
-
-struct segment_info
-{
- void * pvMem; // base of the allocation, not the first object (must add ibFirstObject)
- size_t ibFirstObject; // offset to the base of the first object in the segment
- size_t ibAllocated; // limit of allocated memory in the segment (>= firstobject)
- size_t ibCommit; // limit of committed memory in the segment (>= alllocated)
- size_t ibReserved; // limit of reserved memory in the segment (>= commit)
-};
-
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
/* If you modify failure_get_memory and */
/* oom_reason be sure to make the corresponding */
@@ -80,6 +82,24 @@ enum oom_reason
oom_unproductive_full_gc = 6
};
+// TODO : it would be easier to make this an ORed value
+enum gc_reason
+{
+ reason_alloc_soh = 0,
+ reason_induced = 1,
+ reason_lowmemory = 2,
+ reason_empty = 3,
+ reason_alloc_loh = 4,
+ reason_oos_soh = 5,
+ reason_oos_loh = 6,
+ reason_induced_noforce = 7, // it's an induced GC and doesn't have to be blocking.
+ reason_gcstress = 8, // this turns into reason_induced & gc_mechanisms.stress_induced = true
+ reason_lowmemory_blocking = 9,
+ reason_induced_compacting = 10,
+ reason_lowmemory_host = 11,
+ reason_max
+};
+
struct oom_history
{
oom_reason reason;
@@ -97,28 +117,16 @@ struct oom_history
class CObjectHeader;
class Object;
-class GCHeap;
+class IGCHeapInternal;
/* misc defines */
#define LARGE_OBJECT_SIZE ((size_t)(85000))
-GPTR_DECL(GCHeap, g_pGCHeap);
-
#ifdef GC_CONFIG_DRIVEN
#define MAX_GLOBAL_GC_MECHANISMS_COUNT 6
GARY_DECL(size_t, gc_global_mechanisms, MAX_GLOBAL_GC_MECHANISMS_COUNT);
#endif //GC_CONFIG_DRIVEN
-#ifndef DACCESS_COMPILE
-extern "C" {
-#endif
-GPTR_DECL(uint8_t,g_lowest_address);
-GPTR_DECL(uint8_t,g_highest_address);
-GPTR_DECL(uint32_t,g_card_table);
-#ifndef DACCESS_COMPILE
-}
-#endif
-
#ifdef DACCESS_COMPILE
class DacHeapWalker;
#endif
@@ -127,137 +135,28 @@ class DacHeapWalker;
#define _LOGALLOC
#endif
-#ifdef WRITE_BARRIER_CHECK
-//always defined, but should be 0 in Server GC
-extern uint8_t* g_GCShadow;
-extern uint8_t* g_GCShadowEnd;
-// saves the g_lowest_address in between GCs to verify the consistency of the shadow segment
-extern uint8_t* g_shadow_lowest_address;
-#endif
-
#define MP_LOCKS
-extern "C" uint8_t* g_ephemeral_low;
-extern "C" uint8_t* g_ephemeral_high;
+extern "C" uint32_t* g_gc_card_table;
+extern "C" uint8_t* g_gc_lowest_address;
+extern "C" uint8_t* g_gc_highest_address;
+extern "C" uint8_t* g_gc_ephemeral_low;
+extern "C" uint8_t* g_gc_ephemeral_high;
namespace WKS {
- ::GCHeap* CreateGCHeap();
+ ::IGCHeapInternal* CreateGCHeap();
class GCHeap;
class gc_heap;
}
#if defined(FEATURE_SVR_GC)
namespace SVR {
- ::GCHeap* CreateGCHeap();
+ ::IGCHeapInternal* CreateGCHeap();
class GCHeap;
class gc_heap;
}
#endif // defined(FEATURE_SVR_GC)
-/*
- * Ephemeral Garbage Collected Heap Interface
- */
-
-
-struct alloc_context
-{
- friend class WKS::gc_heap;
-#if defined(FEATURE_SVR_GC)
- friend class SVR::gc_heap;
- friend class SVR::GCHeap;
-#endif // defined(FEATURE_SVR_GC)
- friend struct ClassDumpInfo;
-
- uint8_t* alloc_ptr;
- uint8_t* alloc_limit;
- int64_t alloc_bytes; //Number of bytes allocated on SOH by this context
- int64_t alloc_bytes_loh; //Number of bytes allocated on LOH by this context
-#if defined(FEATURE_SVR_GC)
- SVR::GCHeap* alloc_heap;
- SVR::GCHeap* home_heap;
-#endif // defined(FEATURE_SVR_GC)
- int alloc_count;
-public:
-
- void init()
- {
- LIMITED_METHOD_CONTRACT;
-
- alloc_ptr = 0;
- alloc_limit = 0;
- alloc_bytes = 0;
- alloc_bytes_loh = 0;
-#if defined(FEATURE_SVR_GC)
- alloc_heap = 0;
- home_heap = 0;
-#endif // defined(FEATURE_SVR_GC)
- alloc_count = 0;
- }
-};
-
-struct ScanContext
-{
- Thread* thread_under_crawl;
- int thread_number;
- uintptr_t stack_limit; // Lowest point on the thread stack that the scanning logic is permitted to read
- BOOL promotion; //TRUE: Promotion, FALSE: Relocation.
- BOOL concurrent; //TRUE: concurrent scanning
-#if CHECK_APP_DOMAIN_LEAKS || defined (FEATURE_APPDOMAIN_RESOURCE_MONITORING) || defined (DACCESS_COMPILE)
- AppDomain *pCurrentDomain;
-#endif //CHECK_APP_DOMAIN_LEAKS || FEATURE_APPDOMAIN_RESOURCE_MONITORING || DACCESS_COMPILE
-
-#ifndef FEATURE_REDHAWK
-#if defined(GC_PROFILING) || defined (DACCESS_COMPILE)
- MethodDesc *pMD;
-#endif //GC_PROFILING || DACCESS_COMPILE
-#endif // FEATURE_REDHAWK
-#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)
- EtwGCRootKind dwEtwRootKind;
-#endif // GC_PROFILING || FEATURE_EVENT_TRACE
-
- ScanContext()
- {
- LIMITED_METHOD_CONTRACT;
-
- thread_under_crawl = 0;
- thread_number = -1;
- stack_limit = 0;
- promotion = FALSE;
- concurrent = FALSE;
-#ifdef GC_PROFILING
- pMD = NULL;
-#endif //GC_PROFILING
-#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)
- dwEtwRootKind = kEtwGCRootKindOther;
-#endif // GC_PROFILING || FEATURE_EVENT_TRACE
- }
-};
-
-typedef BOOL (* walk_fn)(Object*, void*);
-typedef void (* gen_walk_fn)(void *context, int generation, uint8_t *range_start, uint8_t * range_end, uint8_t *range_reserved);
-
-#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)
-struct ProfilingScanContext : ScanContext
-{
- BOOL fProfilerPinned;
- void * pvEtwContext;
- void *pHeapId;
-
- ProfilingScanContext(BOOL fProfilerPinnedParam) : ScanContext()
- {
- LIMITED_METHOD_CONTRACT;
-
- pHeapId = NULL;
- fProfilerPinned = fProfilerPinnedParam;
- pvEtwContext = NULL;
-#ifdef FEATURE_CONSERVATIVE_GC
- // To not confuse GCScan::GcScanRoots
- promotion = g_pConfig->GetGCConservative();
-#endif
- }
-};
-#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)
-
#ifdef STRESS_HEAP
#define IN_STRESS_HEAP(x) x
#define STRESS_HEAP_ARG(x) ,x
@@ -266,7 +165,6 @@ struct ProfilingScanContext : ScanContext
#define STRESS_HEAP_ARG(x)
#endif // STRESS_HEAP
-
//dynamic data interface
struct gc_counters
{
@@ -275,51 +173,6 @@ struct gc_counters
size_t collection_count;
};
-// !!!!!!!!!!!!!!!!!!!!!!!
-// make sure you change the def in bcl\system\gc.cs
-// if you change this!
-enum collection_mode
-{
- collection_non_blocking = 0x00000001,
- collection_blocking = 0x00000002,
- collection_optimized = 0x00000004,
- collection_compacting = 0x00000008
-#ifdef STRESS_HEAP
- , collection_gcstress = 0x80000000
-#endif // STRESS_HEAP
-};
-
-// !!!!!!!!!!!!!!!!!!!!!!!
-// make sure you change the def in bcl\system\gc.cs
-// if you change this!
-enum wait_full_gc_status
-{
- wait_full_gc_success = 0,
- wait_full_gc_failed = 1,
- wait_full_gc_cancelled = 2,
- wait_full_gc_timeout = 3,
- wait_full_gc_na = 4
-};
-
-// !!!!!!!!!!!!!!!!!!!!!!!
-// make sure you change the def in bcl\system\gc.cs
-// if you change this!
-enum start_no_gc_region_status
-{
- start_no_gc_success = 0,
- start_no_gc_no_memory = 1,
- start_no_gc_too_large = 2,
- start_no_gc_in_progress = 3
-};
-
-enum end_no_gc_region_status
-{
- end_no_gc_success = 0,
- end_no_gc_not_in_progress = 1,
- end_no_gc_induced = 2,
- end_no_gc_alloc_exceeded = 3
-};
-
enum bgc_state
{
bgc_not_in_process = 0,
@@ -352,321 +205,82 @@ void record_changed_seg (uint8_t* start, uint8_t* end,
void record_global_mechanism (int mech_index);
#endif //GC_CONFIG_DRIVEN
-//constants for the flags parameter to the gc call back
-
-#define GC_CALL_INTERIOR 0x1
-#define GC_CALL_PINNED 0x2
-#define GC_CALL_CHECK_APP_DOMAIN 0x4
-
-//flags for GCHeap::Alloc(...)
-#define GC_ALLOC_FINALIZE 0x1
-#define GC_ALLOC_CONTAINS_REF 0x2
-#define GC_ALLOC_ALIGN8_BIAS 0x4
-#define GC_ALLOC_ALIGN8 0x8
-
-class GCHeap {
- friend struct ::_DacGlobals;
-#ifdef DACCESS_COMPILE
- friend class ClrDataAccess;
-#endif
-
-public:
-
- virtual ~GCHeap() {}
-
- static GCHeap *GetGCHeap()
+struct alloc_context : gc_alloc_context
+{
+#ifdef FEATURE_SVR_GC
+ inline SVR::GCHeap* get_alloc_heap()
{
- LIMITED_METHOD_CONTRACT;
-
- _ASSERTE(g_pGCHeap != NULL);
- return g_pGCHeap;
+ return static_cast<SVR::GCHeap*>(gc_reserved_1);
}
-#ifndef DACCESS_COMPILE
- static BOOL IsGCInProgress(BOOL bConsiderGCStart = FALSE)
+ inline void set_alloc_heap(SVR::GCHeap* heap)
{
- WRAPPER_NO_CONTRACT;
-
- return (IsGCHeapInitialized() ? GetGCHeap()->IsGCInProgressHelper(bConsiderGCStart) : false);
- }
-#endif
-
- static BOOL IsGCHeapInitialized()
- {
- LIMITED_METHOD_CONTRACT;
-
- return (g_pGCHeap != NULL);
+ gc_reserved_1 = heap;
}
- static void WaitForGCCompletion(BOOL bConsiderGCStart = FALSE)
+ inline SVR::GCHeap* get_home_heap()
{
- WRAPPER_NO_CONTRACT;
-
- if (IsGCHeapInitialized())
- GetGCHeap()->WaitUntilGCComplete(bConsiderGCStart);
- }
-
- // The runtime needs to know whether we're using workstation or server GC
- // long before the GCHeap is created. So IsServerHeap cannot be a virtual
- // method on GCHeap. Instead we make it a static method and initialize
- // gcHeapType before any of the calls to IsServerHeap. Note that this also
- // has the advantage of getting the answer without an indirection
- // (virtual call), which is important for perf critical codepaths.
-
- #ifndef DACCESS_COMPILE
- static void InitializeHeapType(bool bServerHeap)
- {
- LIMITED_METHOD_CONTRACT;
-#ifdef FEATURE_SVR_GC
- gcHeapType = bServerHeap ? GC_HEAP_SVR : GC_HEAP_WKS;
-#ifdef WRITE_BARRIER_CHECK
- if (gcHeapType == GC_HEAP_SVR)
- {
- g_GCShadow = 0;
- g_GCShadowEnd = 0;
- }
-#endif
-#else // FEATURE_SVR_GC
- UNREFERENCED_PARAMETER(bServerHeap);
- CONSISTENCY_CHECK(bServerHeap == false);
-#endif // FEATURE_SVR_GC
- }
- #endif
-
- static BOOL IsValidSegmentSize(size_t cbSize)
- {
- //Must be aligned on a Mb and greater than 4Mb
- return (((cbSize & (1024*1024-1)) ==0) && (cbSize >> 22));
+ return static_cast<SVR::GCHeap*>(gc_reserved_2);
}
- static BOOL IsValidGen0MaxSize(size_t cbSize)
+ inline void set_home_heap(SVR::GCHeap* heap)
{
- return (cbSize >= 64*1024);
+ gc_reserved_2 = heap;
}
-
- inline static bool IsServerHeap()
- {
- LIMITED_METHOD_CONTRACT;
-#ifdef FEATURE_SVR_GC
- _ASSERTE(gcHeapType != GC_HEAP_INVALID);
- return (gcHeapType == GC_HEAP_SVR);
-#else // FEATURE_SVR_GC
- return false;
#endif // FEATURE_SVR_GC
- }
+};
- 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)));
+class IGCHeapInternal : public IGCHeap {
+ friend struct ::_DacGlobals;
+#ifdef DACCESS_COMPILE
+ friend class ClrDataAccess;
#endif
-#endif
- }
-
- inline static bool MarkShouldCompeteForStatics()
- {
- WRAPPER_NO_CONTRACT;
-
- return IsServerHeap() && g_SystemInfo.dwNumberOfProcessors >= 2;
- }
-#ifndef DACCESS_COMPILE
- static GCHeap * CreateGCHeap()
- {
- WRAPPER_NO_CONTRACT;
-
- GCHeap * pGCHeap;
-
-#if defined(FEATURE_SVR_GC)
- pGCHeap = (IsServerHeap() ? SVR::CreateGCHeap() : WKS::CreateGCHeap());
-#else
- pGCHeap = WKS::CreateGCHeap();
-#endif // defined(FEATURE_SVR_GC)
-
- g_pGCHeap = pGCHeap;
- return pGCHeap;
- }
-#endif // DACCESS_COMPILE
+public:
-private:
- typedef enum
- {
- GC_HEAP_INVALID = 0,
- GC_HEAP_WKS = 1,
- GC_HEAP_SVR = 2
- } GC_HEAP_TYPE;
-
-#ifdef FEATURE_SVR_GC
- SVAL_DECL(uint32_t,gcHeapType);
-#endif // FEATURE_SVR_GC
+ virtual ~IGCHeapInternal() {}
-public:
- // TODO Synchronization, should be moved out
- virtual BOOL IsGCInProgressHelper (BOOL bConsiderGCStart = FALSE) = 0;
- virtual uint32_t WaitUntilGCComplete (BOOL bConsiderGCStart = FALSE) = 0;
- virtual void SetGCInProgress(BOOL fInProgress) = 0;
- virtual CLREventStatic * GetWaitForGCEvent() = 0;
-
- virtual void SetFinalizationRun (Object* obj) = 0;
- virtual Object* GetNextFinalizable() = 0;
- virtual size_t GetNumberOfFinalizable() = 0;
-
- virtual void SetFinalizeQueueForShutdown(BOOL fHasLock) = 0;
- virtual BOOL FinalizeAppDomain(AppDomain *pDomain, BOOL fRunFinalizers) = 0;
- virtual BOOL ShouldRestartFinalizerWatchDog() = 0;
-
- //wait for concurrent GC to finish
- virtual void WaitUntilConcurrentGCComplete () = 0; // Use in managed threads
-#ifndef DACCESS_COMPILE
- virtual HRESULT WaitUntilConcurrentGCCompleteAsync(int millisecondsTimeout) = 0; // Use in native threads. TRUE if succeed. FALSE if failed or timeout
-#endif
- virtual BOOL IsConcurrentGCInProgress() = 0;
-
- // Enable/disable concurrent GC
- virtual void TemporaryEnableConcurrentGC() = 0;
- virtual void TemporaryDisableConcurrentGC() = 0;
- virtual BOOL IsConcurrentGCEnabled() = 0;
-
- virtual void FixAllocContext (alloc_context* acontext, BOOL lockp, void* arg, void *heap) = 0;
- virtual Object* Alloc (alloc_context* acontext, size_t size, uint32_t flags) = 0;
-
- // This is safe to call only when EE is suspended.
- virtual Object* GetContainingObject(void *pInteriorPtr) = 0;
-
- // TODO Should be folded into constructor
- virtual HRESULT Initialize () = 0;
-
- virtual HRESULT GarbageCollect (int generation = -1, BOOL low_memory_p=FALSE, int mode = collection_blocking) = 0;
- virtual Object* Alloc (size_t size, uint32_t flags) = 0;
-#ifdef FEATURE_64BIT_ALIGNMENT
- virtual Object* AllocAlign8 (size_t size, uint32_t flags) = 0;
- virtual Object* AllocAlign8 (alloc_context* acontext, size_t size, uint32_t flags) = 0;
private:
- virtual Object* AllocAlign8Common (void* hp, alloc_context* acontext, size_t size, uint32_t flags) = 0;
+ virtual Object* AllocAlign8Common (void* hp, alloc_context* acontext, size_t size, uint32_t flags) = 0;
public:
-#endif // FEATURE_64BIT_ALIGNMENT
- virtual Object* AllocLHeap (size_t size, uint32_t flags) = 0;
- virtual void SetReservedVMLimit (size_t vmlimit) = 0;
- virtual void SetCardsAfterBulkCopy( Object**, size_t ) = 0;
-#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)
- virtual void WalkObject (Object* obj, walk_fn fn, void* context) = 0;
-#endif //defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)
-
- virtual bool IsThreadUsingAllocationContextHeap(alloc_context* acontext, int thread_number) = 0;
virtual int GetNumberOfHeaps () = 0;
virtual int GetHomeHeapNumber () = 0;
-
- virtual int CollectionCount (int generation, int get_bgc_fgc_count = 0) = 0;
-
- // Finalizer queue stuff (should stay)
- virtual bool RegisterForFinalization (int gen, Object* obj) = 0;
-
- // General queries to the GC
- virtual BOOL IsPromoted (Object *object) = 0;
- virtual unsigned WhichGeneration (Object* object) = 0;
- virtual BOOL IsEphemeral (Object* object) = 0;
- virtual BOOL IsHeapPointer (void* object, BOOL small_heap_only = FALSE) = 0;
-
- virtual unsigned GetCondemnedGeneration() = 0;
- virtual int GetGcLatencyMode() = 0;
- virtual int SetGcLatencyMode(int newLatencyMode) = 0;
-
- virtual int GetLOHCompactionMode() = 0;
- virtual void SetLOHCompactionMode(int newLOHCompactionyMode) = 0;
-
- virtual BOOL RegisterForFullGCNotification(uint32_t gen2Percentage,
- uint32_t lohPercentage) = 0;
- virtual BOOL CancelFullGCNotification() = 0;
- virtual int WaitForFullGCApproach(int millisecondsTimeout) = 0;
- virtual int WaitForFullGCComplete(int millisecondsTimeout) = 0;
-
- virtual int StartNoGCRegion(uint64_t totalSize, BOOL lohSizeKnown, uint64_t lohSize, BOOL disallowFullBlockingGC) = 0;
- virtual int EndNoGCRegion() = 0;
+ virtual size_t GetPromotedBytes(int heap_index) = 0;
- virtual BOOL IsObjectInFixedHeap(Object *pObj) = 0;
- virtual size_t GetTotalBytesInUse () = 0;
- virtual size_t GetCurrentObjSize() = 0;
- virtual size_t GetLastGCStartTime(int generation) = 0;
- virtual size_t GetLastGCDuration(int generation) = 0;
- virtual size_t GetNow() = 0;
- virtual unsigned GetGcCount() = 0;
- virtual void TraceGCSegments() = 0;
+ unsigned GetMaxGeneration()
+ {
+ return IGCHeap::maxGeneration;
+ }
- virtual void PublishObject(uint8_t* obj) = 0;
+ BOOL IsValidSegmentSize(size_t cbSize)
+ {
+ //Must be aligned on a Mb and greater than 4Mb
+ return (((cbSize & (1024*1024-1)) ==0) && (cbSize >> 22));
+ }
- // static if since restricting for all heaps is fine
- virtual size_t GetValidSegmentSize(BOOL large_seg = FALSE) = 0;
+ BOOL IsValidGen0MaxSize(size_t cbSize)
+ {
+ return (cbSize >= 64*1024);
+ }
- static BOOL IsLargeObject(MethodTable *mt) {
+ BOOL IsLargeObject(MethodTable *mt)
+ {
WRAPPER_NO_CONTRACT;
return mt->GetBaseSize() >= LARGE_OBJECT_SIZE;
}
- static unsigned GetMaxGeneration() {
- LIMITED_METHOD_DAC_CONTRACT;
- return max_generation;
- }
-
- virtual size_t GetPromotedBytes(int heap_index) = 0;
-
-private:
- enum {
- max_generation = 2,
- };
-
-public:
-
-#ifdef FEATURE_BASICFREEZE
- // frozen segment management functions
- virtual segment_handle RegisterFrozenSegment(segment_info *pseginfo) = 0;
- virtual void UnregisterFrozenSegment(segment_handle seg) = 0;
-#endif //FEATURE_BASICFREEZE
-
- // debug support
-#ifndef FEATURE_REDHAWK // Redhawk forces relocation a different way
-#ifdef STRESS_HEAP
- //return TRUE if GC actually happens, otherwise FALSE
- virtual BOOL StressHeap(alloc_context * acontext = 0) = 0;
-#endif
-#endif // FEATURE_REDHAWK
-#ifdef VERIFY_HEAP
- virtual void ValidateObjectMember (Object *obj) = 0;
-#endif
-
-#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)
- virtual void DescrGenerationsToProfiler (gen_walk_fn fn, void *context) = 0;
-#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)
-
protected:
-#ifdef VERIFY_HEAP
public:
- // Return NULL if can't find next object. When EE is not suspended,
- // the result is not accurate: if the input arg is in gen0, the function could
- // return zeroed out memory as next object
- virtual Object * NextObj (Object * object) = 0;
-#ifdef FEATURE_BASICFREEZE
+#if defined(FEATURE_BASICFREEZE) && defined(VERIFY_HEAP)
// Return TRUE if object lives in frozen segment
virtual BOOL IsInFrozenSegment (Object * object) = 0;
-#endif //FEATURE_BASICFREEZE
-#endif //VERIFY_HEAP
+#endif // defined(FEATURE_BASICFREEZE) && defined(VERIFY_HEAP)
};
-extern VOLATILE(int32_t) m_GCLock;
-
// Go through and touch (read) each page straddled by a memory block.
void TouchPages(void * pStart, size_t cb);
-// For low memory notification from host
-extern int32_t g_bLowMemoryFromHost;
-
#ifdef WRITE_BARRIER_CHECK
void updateGCShadow(Object** ptr, Object* val);
#endif
@@ -677,4 +291,27 @@ extern MethodTable *pWeakReferenceMT;
extern MethodTable *pWeakReferenceOfTCanonMT;
extern void FinalizeWeakReference(Object * obj);
+// The single GC heap instance, shared with the VM.
+extern IGCHeapInternal* g_theGCHeap;
+
+#ifndef DACCESS_COMPILE
+inline BOOL IsGCInProgress(bool bConsiderGCStart = FALSE)
+{
+ WRAPPER_NO_CONTRACT;
+
+ return g_theGCHeap != nullptr ? g_theGCHeap->IsGCInProgressHelper(bConsiderGCStart) : false;
+}
+#endif // DACCESS_COMPILE
+
+inline 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
+ return false;
+#endif // FEATURE_SVR_GC
+}
+
#endif // __GC_H