mirror of
https://github.com/VSadov/Satori.git
synced 2025-06-08 03:27:04 +09:00
338 lines
11 KiB
C
338 lines
11 KiB
C
// Licensed to the .NET Foundation under one or more agreements.
|
|
// The .NET Foundation licenses this file to you under the MIT license.
|
|
|
|
|
|
#ifndef GCIMPL_H_
|
|
#define GCIMPL_H_
|
|
|
|
#ifdef SERVER_GC
|
|
#define MULTIPLE_HEAPS 1
|
|
#endif // SERVER_GC
|
|
|
|
#ifdef MULTIPLE_HEAPS
|
|
|
|
#define PER_HEAP
|
|
|
|
#else //MULTIPLE_HEAPS
|
|
|
|
#define PER_HEAP static
|
|
|
|
#endif // MULTIPLE_HEAPS
|
|
|
|
#define PER_HEAP_ISOLATED static
|
|
|
|
#if defined(WRITE_BARRIER_CHECK) && !defined (MULTIPLE_HEAPS)
|
|
void initGCShadow();
|
|
void deleteGCShadow();
|
|
void checkGCWriteBarrier();
|
|
#else
|
|
inline void initGCShadow() {}
|
|
inline void deleteGCShadow() {}
|
|
inline void checkGCWriteBarrier() {}
|
|
#endif
|
|
|
|
void GCProfileWalkHeap(bool etwOnly);
|
|
|
|
class gc_heap;
|
|
class CFinalize;
|
|
|
|
extern bool g_fFinalizerRunOnShutDown;
|
|
extern bool g_built_with_svr_gc;
|
|
extern uint8_t g_build_variant;
|
|
extern VOLATILE(int32_t) g_no_gc_lock;
|
|
|
|
class GCHeap : public IGCHeapInternal
|
|
{
|
|
protected:
|
|
|
|
#ifdef MULTIPLE_HEAPS
|
|
gc_heap* pGenGCHeap;
|
|
#else
|
|
#define pGenGCHeap ((gc_heap*)0)
|
|
#endif //MULTIPLE_HEAPS
|
|
|
|
friend class CFinalize;
|
|
friend class gc_heap;
|
|
friend struct ::alloc_context;
|
|
friend void EnterAllocLock();
|
|
friend void LeaveAllocLock();
|
|
friend void ProfScanRootsHelper(Object** object, ScanContext *pSC, uint32_t dwFlags);
|
|
friend void GCProfileWalkHeap(bool etwOnly);
|
|
|
|
public:
|
|
//In order to keep gc.cpp cleaner, ugly EE specific code is relegated to methods.
|
|
static void UpdatePreGCCounters();
|
|
static void UpdatePostGCCounters();
|
|
|
|
public:
|
|
GCHeap(){};
|
|
|
|
/* BaseGCHeap Methods*/
|
|
PER_HEAP_ISOLATED HRESULT StaticShutdown ();
|
|
|
|
size_t GetTotalBytesInUse ();
|
|
// Gets the amount of bytes objects currently occupy on the GC heap.
|
|
size_t GetCurrentObjSize();
|
|
|
|
uint64_t GetTotalAllocatedBytes();
|
|
|
|
size_t GetLastGCStartTime(int generation);
|
|
size_t GetLastGCDuration(int generation);
|
|
size_t GetNow();
|
|
|
|
void DiagTraceGCSegments ();
|
|
void PublishObject(uint8_t* obj);
|
|
|
|
bool IsGCInProgressHelper (bool bConsiderGCStart = false);
|
|
|
|
uint32_t WaitUntilGCComplete (bool bConsiderGCStart = false);
|
|
|
|
void SetGCInProgress(bool fInProgress);
|
|
|
|
bool RuntimeStructuresValid();
|
|
|
|
void SetSuspensionPending(bool fSuspensionPending);
|
|
|
|
void SetYieldProcessorScalingFactor(float yieldProcessorScalingFactor);
|
|
|
|
void SetWaitForGCEvent();
|
|
void ResetWaitForGCEvent();
|
|
|
|
HRESULT Initialize ();
|
|
|
|
Object* Alloc (gc_alloc_context* acontext, size_t size, uint32_t flags);
|
|
|
|
void FixAllocContext (gc_alloc_context* acontext, void* arg, void *heap);
|
|
|
|
Object* GetContainingObject(void *pInteriorPtr, bool fCollectedGenOnly);
|
|
|
|
#ifdef MULTIPLE_HEAPS
|
|
static void AssignHeap (alloc_context* acontext);
|
|
static GCHeap* GetHeap (int);
|
|
#endif //MULTIPLE_HEAPS
|
|
|
|
int GetHomeHeapNumber ();
|
|
bool IsThreadUsingAllocationContextHeap(gc_alloc_context* acontext, int thread_number);
|
|
int GetNumberOfHeaps ();
|
|
void HideAllocContext(alloc_context*);
|
|
void RevealAllocContext(alloc_context*);
|
|
|
|
bool IsLargeObject(Object *pObj);
|
|
|
|
HRESULT GarbageCollect (int generation = -1, bool low_memory_p=false, int mode=collection_blocking);
|
|
|
|
////
|
|
// GC callback functions
|
|
// Check if an argument is promoted (ONLY CALL DURING
|
|
// THE PROMOTIONSGRANTED CALLBACK.)
|
|
bool IsPromoted (Object *object);
|
|
|
|
size_t GetPromotedBytes (int heap_index);
|
|
|
|
int CollectionCount (int generation, int get_bgc_fgc_count = 0);
|
|
|
|
// promote an object
|
|
PER_HEAP_ISOLATED void Promote (Object** object,
|
|
ScanContext* sc,
|
|
uint32_t flags=0);
|
|
|
|
// Find the relocation address for an object
|
|
PER_HEAP_ISOLATED void Relocate (Object** object,
|
|
ScanContext* sc,
|
|
uint32_t flags=0);
|
|
|
|
|
|
HRESULT Init (size_t heapSize);
|
|
|
|
//Register an object for finalization
|
|
bool RegisterForFinalization (int gen, Object* obj);
|
|
|
|
//Unregister an object for finalization
|
|
void SetFinalizationRun (Object* obj);
|
|
|
|
// returns the generation number of an object (not valid during relocation) or
|
|
// INT32_MAX if the object belongs to a non-GC heap.
|
|
unsigned WhichGeneration (Object* object);
|
|
// returns TRUE is the object is ephemeral
|
|
bool IsEphemeral (Object* object);
|
|
bool IsHeapPointer (void* object, bool small_heap_only = false);
|
|
|
|
void ValidateObjectMember (Object *obj);
|
|
|
|
PER_HEAP size_t ApproxTotalBytesInUse(BOOL small_heap_only = FALSE);
|
|
|
|
unsigned GetCondemnedGeneration();
|
|
|
|
void GetMemoryInfo(uint64_t* highMemLoadThresholdBytes,
|
|
uint64_t* totalAvailableMemoryBytes,
|
|
uint64_t* lastRecordedMemLoadBytes,
|
|
uint64_t* lastRecordedHeapSizeBytes,
|
|
uint64_t* lastRecordedFragmentationBytes,
|
|
uint64_t* totalCommittedBytes,
|
|
uint64_t* promotedBytes,
|
|
uint64_t* pinnedObjectCount,
|
|
uint64_t* finalizationPendingCount,
|
|
uint64_t* index,
|
|
uint32_t* generation,
|
|
uint32_t* pauseTimePct,
|
|
bool* isCompaction,
|
|
bool* isConcurrent,
|
|
uint64_t* genInfoRaw,
|
|
uint64_t* pauseInfoRaw,
|
|
int kind);
|
|
|
|
int64_t GetTotalPauseDuration();
|
|
|
|
void EnumerateConfigurationValues(void* context, ConfigurationValueFunc configurationValueFunc);
|
|
|
|
uint32_t GetMemoryLoad();
|
|
|
|
int GetGcLatencyMode();
|
|
int SetGcLatencyMode(int newLatencyMode);
|
|
|
|
int GetLOHCompactionMode();
|
|
void SetLOHCompactionMode(int newLOHCompactionyMode);
|
|
|
|
bool RegisterForFullGCNotification(uint32_t gen2Percentage,
|
|
uint32_t lohPercentage);
|
|
bool CancelFullGCNotification();
|
|
int WaitForFullGCApproach(int millisecondsTimeout);
|
|
int WaitForFullGCComplete(int millisecondsTimeout);
|
|
|
|
int StartNoGCRegion(uint64_t totalSize, bool lohSizeKnown, uint64_t lohSize, bool disallowFullBlockingGC);
|
|
int EndNoGCRegion();
|
|
enable_no_gc_region_callback_status EnableNoGCRegionCallback(NoGCRegionCallbackFinalizerWorkItem* callback, uint64_t callback_threshold);
|
|
FinalizerWorkItem* GetExtraWorkForFinalization();
|
|
uint64_t GetGenerationBudget(int generation);
|
|
size_t GetLOHThreshold();
|
|
|
|
unsigned GetGcCount();
|
|
|
|
Object* GetNextFinalizable() { return GetNextFinalizableObject(); };
|
|
size_t GetNumberOfFinalizable() { return GetNumberFinalizableObjects(); }
|
|
|
|
size_t GetValidSegmentSize(bool large_seg = false);
|
|
|
|
void SetReservedVMLimit (size_t vmlimit);
|
|
|
|
PER_HEAP_ISOLATED Object* GetNextFinalizableObject();
|
|
PER_HEAP_ISOLATED size_t GetNumberFinalizableObjects();
|
|
PER_HEAP_ISOLATED size_t GetFinalizablePromotedCount();
|
|
|
|
void DiagWalkObject (Object* obj, walk_fn fn, void* context);
|
|
void DiagWalkObject2 (Object* obj, walk_fn2 fn, void* context);
|
|
|
|
public: // FIX
|
|
|
|
// Lock for finalization
|
|
PER_HEAP_ISOLATED
|
|
VOLATILE(int32_t) m_GCFLock;
|
|
|
|
PER_HEAP_ISOLATED BOOL GcCollectClasses;
|
|
PER_HEAP_ISOLATED
|
|
VOLATILE(BOOL) GcInProgress; // used for syncing w/GC
|
|
PER_HEAP_ISOLATED VOLATILE(unsigned) GcCount;
|
|
PER_HEAP_ISOLATED unsigned GcCondemnedGeneration;
|
|
// calculated at the end of a GC.
|
|
PER_HEAP_ISOLATED size_t totalSurvivedSize;
|
|
|
|
// Use only for GC tracing.
|
|
PER_HEAP uint64_t GcDuration;
|
|
|
|
size_t GarbageCollectGeneration (unsigned int gen=0, gc_reason reason=reason_empty);
|
|
// Interface with gc_heap
|
|
size_t GarbageCollectTry (int generation, BOOL low_memory_p=FALSE, int mode=collection_blocking);
|
|
|
|
// frozen segment management functions
|
|
virtual segment_handle RegisterFrozenSegment(segment_info *pseginfo);
|
|
virtual void UnregisterFrozenSegment(segment_handle seg);
|
|
virtual bool IsInFrozenSegment(Object *object);
|
|
virtual void UpdateFrozenSegment(segment_handle seg, uint8_t* allocated, uint8_t* committed);
|
|
|
|
// Event control functions
|
|
void ControlEvents(GCEventKeyword keyword, GCEventLevel level);
|
|
void ControlPrivateEvents(GCEventKeyword keyword, GCEventLevel level);
|
|
|
|
void WaitUntilConcurrentGCComplete (); // Use in managd threads
|
|
#ifndef DACCESS_COMPILE
|
|
HRESULT WaitUntilConcurrentGCCompleteAsync(int millisecondsTimeout); // Use in native threads. TRUE if succeed. FALSE if failed or timeout
|
|
#endif
|
|
bool IsConcurrentGCInProgress();
|
|
|
|
// Enable/disable concurrent GC
|
|
void TemporaryEnableConcurrentGC();
|
|
void TemporaryDisableConcurrentGC();
|
|
bool IsConcurrentGCEnabled();
|
|
|
|
PER_HEAP_ISOLATED GCEvent *WaitForGCEvent; // used for syncing w/GC
|
|
|
|
PER_HEAP_ISOLATED CFinalize* m_Finalize;
|
|
|
|
PER_HEAP_ISOLATED gc_heap* Getgc_heap();
|
|
|
|
private:
|
|
static bool SafeToRestartManagedThreads()
|
|
{
|
|
// Note: this routine should return true when the last barrier
|
|
// to threads returning to cooperative mode is down after gc.
|
|
// In other words, if the sequence in GCHeap::RestartEE changes,
|
|
// the condition here may have to change as well.
|
|
return g_fSuspensionPending == 0;
|
|
}
|
|
public:
|
|
//return TRUE if GC actually happens, otherwise FALSE
|
|
bool StressHeap(gc_alloc_context * acontext);
|
|
|
|
#ifndef FEATURE_NATIVEAOT // Redhawk forces relocation a different way
|
|
#ifdef STRESS_HEAP
|
|
protected:
|
|
|
|
// only used in BACKGROUND_GC, but the symbol is not defined yet...
|
|
PER_HEAP_ISOLATED int gc_stress_fgcs_in_bgc;
|
|
|
|
#if !defined(MULTIPLE_HEAPS)
|
|
// handles to hold the string objects that will force GC movement
|
|
enum { NUM_HEAP_STRESS_OBJS = 8 };
|
|
PER_HEAP OBJECTHANDLE m_StressObjs[NUM_HEAP_STRESS_OBJS];
|
|
PER_HEAP int m_CurStressObj;
|
|
#endif // !defined(MULTIPLE_HEAPS)
|
|
#endif // STRESS_HEAP
|
|
#endif // FEATURE_NATIVEAOT
|
|
|
|
virtual void DiagDescrGenerations (gen_walk_fn fn, void *context);
|
|
|
|
virtual void DiagWalkSurvivorsWithType (void* gc_context, record_surv_fn fn, void* diag_context, walk_surv_type type, int gen_number=-1);
|
|
|
|
virtual void DiagWalkFinalizeQueue (void* gc_context, fq_walk_fn fn);
|
|
|
|
virtual void DiagScanFinalizeQueue (fq_scan_fn fn, ScanContext* context);
|
|
|
|
virtual void DiagScanHandles (handle_scan_fn fn, int gen_number, ScanContext* context);
|
|
|
|
virtual void DiagScanDependentHandles (handle_scan_fn fn, int gen_number, ScanContext* context);
|
|
|
|
virtual void DiagWalkHeap(walk_fn fn, void* context, int gen_number, bool walk_large_object_heap_p);
|
|
|
|
virtual void DiagGetGCSettings(EtwGCSettingsInfo* etw_settings);
|
|
|
|
virtual unsigned int GetGenerationWithRange(Object* object, uint8_t** ppStart, uint8_t** ppAllocated, uint8_t** ppReserved);
|
|
|
|
virtual void DiagWalkHeapWithACHandling(walk_fn fn, void* context, int gen_number, bool walk_large_object_heap_p);
|
|
public:
|
|
Object * NextObj (Object * object);
|
|
|
|
int GetLastGCPercentTimeInGC();
|
|
|
|
size_t GetLastGCGenerationSize(int gen);
|
|
|
|
virtual void Shutdown();
|
|
|
|
static void ReportGenerationBounds();
|
|
|
|
virtual int RefreshMemoryLimit();
|
|
|
|
// Inherited via IGCHeapInternal
|
|
virtual void BulkMoveWithWriteBarrier(void* dst, const void* src, size_t byteCount);
|
|
};
|
|
|
|
#endif // GCIMPL_H_
|