Add a fourth parameter to the DEFINE_DACVAR macro that is the actual fully qualified...
[platform/upstream/coreclr.git] / src / gc / gc.h
1 //
2 // Copyright (c) Microsoft. All rights reserved.
3 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
4 //
5
6
7 /*++
8
9 Module Name:
10
11     gc.h
12
13 --*/
14
15 #ifndef __GC_H
16 #define __GC_H
17
18 #ifndef BINDER
19
20 #ifdef PROFILING_SUPPORTED
21 #define GC_PROFILING       //Turn on profiling
22 #endif // PROFILING_SUPPORTED
23
24 #endif
25
26 /*
27  * Promotion Function Prototypes
28  */
29 typedef void enum_func (Object*);
30
31 // callback functions for heap walkers
32 typedef void object_callback_func(void * pvContext, void * pvDataLoc);
33
34 // stub type to abstract a heap segment
35 struct gc_heap_segment_stub;
36 typedef gc_heap_segment_stub *segment_handle;
37
38 struct segment_info
39 {
40     LPVOID pvMem; // base of the allocation, not the first object (must add ibFirstObject)
41     size_t ibFirstObject;   // offset to the base of the first object in the segment
42     size_t ibAllocated; // limit of allocated memory in the segment (>= firstobject)
43     size_t ibCommit; // limit of committed memory in the segment (>= alllocated)
44     size_t ibReserved; // limit of reserved memory in the segment (>= commit)
45 };
46
47 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
48 /* If you modify failure_get_memory and         */
49 /* oom_reason be sure to make the corresponding */
50 /* changes in toolbox\sos\strike\strike.cpp.    */
51 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
52 enum failure_get_memory
53 {
54     fgm_no_failure = 0,
55     fgm_reserve_segment = 1,
56     fgm_commit_segment_beg = 2,
57     fgm_commit_eph_segment = 3,
58     fgm_grow_table = 4,
59     fgm_commit_table = 5
60 };
61
62 struct fgm_history
63 {
64     failure_get_memory fgm;
65     size_t size;
66     size_t available_pagefile_mb;
67     BOOL loh_p;
68
69     void set_fgm (failure_get_memory f, size_t s, BOOL l)
70     {
71         fgm = f;
72         size = s;
73         loh_p = l;
74     }
75 };
76
77 enum oom_reason
78 {
79     oom_no_failure = 0,
80     oom_budget = 1,
81     oom_cant_commit = 2,
82     oom_cant_reserve = 3,
83     oom_loh = 4,
84     oom_low_mem = 5,
85     oom_unproductive_full_gc = 6
86 };
87
88 struct oom_history
89 {
90     oom_reason reason;
91     size_t alloc_size;
92     BYTE* reserved;
93     BYTE* allocated;
94     size_t gc_index;
95     failure_get_memory fgm;
96     size_t size;
97     size_t available_pagefile_mb;
98     BOOL loh_p;
99 };
100
101 /* forward declerations */
102 class CObjectHeader;
103 class Object;
104
105 class GCHeap;
106
107 /* misc defines */
108 #define LARGE_OBJECT_SIZE ((size_t)(85000))
109
110 GPTR_DECL(GCHeap, g_pGCHeap);
111
112 #ifndef DACCESS_COMPILE
113 extern "C" {
114 #endif
115 GPTR_DECL(BYTE,g_lowest_address);
116 GPTR_DECL(BYTE,g_highest_address);
117 GPTR_DECL(DWORD,g_card_table);
118 #ifndef DACCESS_COMPILE
119 }
120 #endif
121
122 #ifdef DACCESS_COMPILE
123 class DacHeapWalker;
124 #endif
125
126 #ifdef _DEBUG
127 #define  _LOGALLOC
128 #endif
129
130 #ifdef WRITE_BARRIER_CHECK
131 //always defined, but should be 0 in Server GC
132 extern BYTE* g_GCShadow;
133 extern BYTE* g_GCShadowEnd;
134 // saves the g_lowest_address in between GCs to verify the consistency of the shadow segment
135 extern BYTE* g_shadow_lowest_address;
136 #endif
137
138 #define MP_LOCKS
139
140 extern "C" BYTE* g_ephemeral_low;
141 extern "C" BYTE* g_ephemeral_high;
142
143 namespace WKS {
144     ::GCHeap* CreateGCHeap();
145     class GCHeap;
146     class gc_heap;
147     }
148
149 #if defined(FEATURE_SVR_GC)
150 namespace SVR {
151     ::GCHeap* CreateGCHeap();
152     class GCHeap;
153     class gc_heap;
154 }
155 #endif // defined(FEATURE_SVR_GC)
156
157 /*
158  * Ephemeral Garbage Collected Heap Interface
159  */
160
161
162 struct alloc_context 
163 {
164     friend class WKS::gc_heap;
165 #if defined(FEATURE_SVR_GC)
166     friend class SVR::gc_heap;
167     friend class SVR::GCHeap;
168 #endif // defined(FEATURE_SVR_GC)
169     friend struct ClassDumpInfo;
170
171     BYTE*          alloc_ptr;
172     BYTE*          alloc_limit;
173     __int64        alloc_bytes; //Number of bytes allocated on SOH by this context
174     __int64        alloc_bytes_loh; //Number of bytes allocated on LOH by this context
175 #if defined(FEATURE_SVR_GC)
176     SVR::GCHeap*   alloc_heap;
177     SVR::GCHeap*   home_heap;
178 #endif // defined(FEATURE_SVR_GC)
179     int            alloc_count;
180 public:
181
182     void init()
183     {
184         LIMITED_METHOD_CONTRACT;
185
186         alloc_ptr = 0;
187         alloc_limit = 0;
188         alloc_bytes = 0;
189         alloc_bytes_loh = 0;
190 #if defined(FEATURE_SVR_GC)
191         alloc_heap = 0;
192         home_heap = 0;
193 #endif // defined(FEATURE_SVR_GC)
194         alloc_count = 0;
195     }
196 };
197
198 struct ScanContext
199 {
200     Thread* thread_under_crawl;
201     int thread_number;
202     BOOL promotion; //TRUE: Promotion, FALSE: Relocation.
203     BOOL concurrent; //TRUE: concurrent scanning 
204 #if CHECK_APP_DOMAIN_LEAKS || defined (FEATURE_APPDOMAIN_RESOURCE_MONITORING) || defined (DACCESS_COMPILE)
205     AppDomain *pCurrentDomain;
206 #endif //CHECK_APP_DOMAIN_LEAKS || FEATURE_APPDOMAIN_RESOURCE_MONITORING || DACCESS_COMPILE
207
208 #if defined(GC_PROFILING) || defined (DACCESS_COMPILE)
209     MethodDesc *pMD;
210 #endif //GC_PROFILING || DACCESS_COMPILE
211 #if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)
212     EtwGCRootKind dwEtwRootKind;
213 #endif // GC_PROFILING || FEATURE_EVENT_TRACE
214     
215     ScanContext()
216     {
217         LIMITED_METHOD_CONTRACT;
218
219         thread_under_crawl = 0;
220         thread_number = -1;
221         promotion = FALSE;
222         concurrent = FALSE;
223 #ifdef GC_PROFILING
224         pMD = NULL;
225 #endif //GC_PROFILING
226 #ifdef FEATURE_EVENT_TRACE
227         dwEtwRootKind = kEtwGCRootKindOther;
228 #endif // FEATURE_EVENT_TRACE
229     }
230 };
231
232 typedef BOOL (* walk_fn)(Object*, void*);
233 typedef void (* gen_walk_fn)(void *context, int generation, BYTE *range_start, BYTE * range_end, BYTE *range_reserved);
234
235 #if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)
236 struct ProfilingScanContext : ScanContext
237 {
238     BOOL fProfilerPinned;
239     LPVOID pvEtwContext;
240     void *pHeapId;
241     
242     ProfilingScanContext(BOOL fProfilerPinnedParam) : ScanContext()
243     {
244         LIMITED_METHOD_CONTRACT;
245
246         pHeapId = NULL;
247         fProfilerPinned = fProfilerPinnedParam;
248         pvEtwContext = NULL;
249 #ifdef FEATURE_CONSERVATIVE_GC
250         // To not confuse CNameSpace::GcScanRoots
251         promotion = g_pConfig->GetGCConservative();
252 #endif
253     }
254 };
255 #endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)
256
257 #ifdef STRESS_HEAP
258 #define IN_STRESS_HEAP(x) x
259 #define STRESS_HEAP_ARG(x) ,x
260 #else // STRESS_HEAP
261 #define IN_STRESS_HEAP(x)
262 #define STRESS_HEAP_ARG(x)
263 #endif // STRESS_HEAP
264
265
266 //dynamic data interface
267 struct gc_counters
268 {
269     size_t current_size;
270     size_t promoted_size;
271     size_t collection_count;
272 };
273
274 // !!!!!!!!!!!!!!!!!!!!!!!
275 // make sure you change the def in bcl\system\gc.cs 
276 // if you change this!
277 enum collection_mode
278 {
279     collection_non_blocking = 0x00000001,
280     collection_blocking = 0x00000002,
281     collection_optimized = 0x00000004,
282     collection_compacting = 0x00000008
283 #ifdef STRESS_HEAP
284     , collection_gcstress = 0x80000000
285 #endif // STRESS_HEAP
286 };
287
288 // !!!!!!!!!!!!!!!!!!!!!!!
289 // make sure you change the def in bcl\system\gc.cs 
290 // if you change this!
291 enum wait_full_gc_status
292 {
293     wait_full_gc_success = 0,
294     wait_full_gc_failed = 1,
295     wait_full_gc_cancelled = 2,
296     wait_full_gc_timeout = 3,
297     wait_full_gc_na = 4
298 };
299
300 // !!!!!!!!!!!!!!!!!!!!!!!
301 // make sure you change the def in bcl\system\gc.cs 
302 // if you change this!
303 enum start_no_gc_region_status
304 {
305     start_no_gc_success = 0,
306     start_no_gc_no_memory = 1,
307     start_no_gc_too_large = 2,
308     start_no_gc_in_progress = 3
309 };
310
311 enum end_no_gc_region_status
312 {
313     end_no_gc_success = 0,
314     end_no_gc_not_in_progress = 1,
315     end_no_gc_induced = 2,
316     end_no_gc_alloc_exceeded = 3
317 };
318
319 enum bgc_state
320 {
321     bgc_not_in_process = 0,
322     bgc_initialized,
323     bgc_reset_ww,
324     bgc_mark_handles,
325     bgc_mark_stack,
326     bgc_revisit_soh,
327     bgc_revisit_loh,
328     bgc_overflow_soh,
329     bgc_overflow_loh,
330     bgc_final_marking,
331     bgc_sweep_soh,
332     bgc_sweep_loh,
333     bgc_plan_phase
334 };
335
336 enum changed_seg_state
337 {
338     seg_deleted,
339     seg_added
340 };
341
342 void record_changed_seg (BYTE* start, BYTE* end, 
343                          size_t current_gc_index, 
344                          bgc_state current_bgc_state,
345                          changed_seg_state changed_state);
346
347 //constants for the flags parameter to the gc call back
348
349 #define GC_CALL_INTERIOR            0x1
350 #define GC_CALL_PINNED              0x2
351 #define GC_CALL_CHECK_APP_DOMAIN    0x4
352
353 //flags for GCHeap::Alloc(...)
354 #define GC_ALLOC_FINALIZE 0x1
355 #define GC_ALLOC_CONTAINS_REF 0x2
356 #define GC_ALLOC_ALIGN8_BIAS 0x4
357
358 class GCHeap {
359     friend struct ::_DacGlobals;
360 #ifdef DACCESS_COMPILE
361     friend class ClrDataAccess;
362 #endif
363     
364 public:
365     static GCHeap *GetGCHeap()
366     {
367 #ifdef CLR_STANDALONE_BINDER
368         return NULL;
369 #else
370         LIMITED_METHOD_CONTRACT;
371
372         _ASSERTE(g_pGCHeap != NULL);
373         return g_pGCHeap;
374 #endif
375     }
376     
377 #ifndef CLR_STANDALONE_BINDER   
378     static BOOL IsGCHeapInitialized()
379     {
380         LIMITED_METHOD_CONTRACT;
381
382         return (g_pGCHeap != NULL);
383     }
384     static BOOL IsGCInProgress(BOOL bConsiderGCStart = FALSE)
385     {
386         WRAPPER_NO_CONTRACT;
387
388         return (IsGCHeapInitialized() ? GetGCHeap()->IsGCInProgressHelper(bConsiderGCStart) : false);
389     }   
390
391     static void WaitForGCCompletion(BOOL bConsiderGCStart = FALSE)
392     {
393         WRAPPER_NO_CONTRACT;
394
395         if (IsGCHeapInitialized())
396             GetGCHeap()->WaitUntilGCComplete(bConsiderGCStart);
397     }   
398
399     // The runtime needs to know whether we're using workstation or server GC 
400     // long before the GCHeap is created.  So IsServerHeap cannot be a virtual 
401     // method on GCHeap.  Instead we make it a static method and initialize 
402     // gcHeapType before any of the calls to IsServerHeap.  Note that this also 
403     // has the advantage of getting the answer without an indirection
404     // (virtual call), which is important for perf critical codepaths.
405
406     #ifndef DACCESS_COMPILE
407     static void InitializeHeapType(bool bServerHeap)
408     {
409         LIMITED_METHOD_CONTRACT;
410 #ifdef FEATURE_SVR_GC
411         gcHeapType = bServerHeap ? GC_HEAP_SVR : GC_HEAP_WKS;
412 #ifdef WRITE_BARRIER_CHECK
413         if (gcHeapType == GC_HEAP_SVR)
414         {
415             g_GCShadow = 0;
416             g_GCShadowEnd = 0;
417         }
418 #endif
419 #else // FEATURE_SVR_GC
420         CONSISTENCY_CHECK(bServerHeap == false);
421 #endif // FEATURE_SVR_GC
422     }
423     #endif
424     
425     static BOOL IsValidSegmentSize(size_t cbSize)
426     {
427         //Must be aligned on a Mb and greater than 4Mb
428         return (((cbSize & (1024*1024-1)) ==0) && (cbSize >> 22));
429     }
430
431     static BOOL IsValidGen0MaxSize(size_t cbSize)
432     {
433         return (cbSize >= 64*1024);
434     }
435
436     inline static bool IsServerHeap()
437     {
438         LIMITED_METHOD_CONTRACT;
439 #ifdef FEATURE_SVR_GC
440         _ASSERTE(gcHeapType != GC_HEAP_INVALID);
441         return (gcHeapType == GC_HEAP_SVR);
442 #else // FEATURE_SVR_GC
443         return false;
444 #endif // FEATURE_SVR_GC
445     }
446
447     inline static bool UseAllocationContexts()
448     {
449         WRAPPER_NO_CONTRACT;
450 #ifdef FEATURE_REDHAWK
451         // SIMPLIFY:  only use allocation contexts
452         return true;
453 #else
454 #ifdef _TARGET_ARM_
455         return TRUE;
456 #endif
457         return ((IsServerHeap() ? true : (g_SystemInfo.dwNumberOfProcessors >= 2)));
458 #endif 
459     }
460
461    inline static bool MarkShouldCompeteForStatics()
462     {
463         WRAPPER_NO_CONTRACT;
464
465         return IsServerHeap() && g_SystemInfo.dwNumberOfProcessors >= 2;
466     }
467     
468 #ifndef DACCESS_COMPILE
469     static GCHeap * CreateGCHeap()
470     {
471         WRAPPER_NO_CONTRACT;
472
473         GCHeap * pGCHeap;
474
475 #if defined(FEATURE_SVR_GC)
476         pGCHeap = (IsServerHeap() ? SVR::CreateGCHeap() : WKS::CreateGCHeap());
477 #else
478         pGCHeap = WKS::CreateGCHeap();
479 #endif // defined(FEATURE_SVR_GC)
480
481         g_pGCHeap = pGCHeap;
482         return pGCHeap;
483     }
484 #endif // DACCESS_COMPILE
485
486 #endif // !CLR_STANDALONE_BINDER
487
488 private:
489     typedef enum
490     {
491         GC_HEAP_INVALID = 0,
492         GC_HEAP_WKS     = 1,
493         GC_HEAP_SVR     = 2
494     } GC_HEAP_TYPE;
495     
496 #ifdef FEATURE_SVR_GC
497     SVAL_DECL(DWORD,gcHeapType);
498 #endif // FEATURE_SVR_GC
499
500 public:
501         // TODO Synchronization, should be moved out
502     virtual BOOL    IsGCInProgressHelper (BOOL bConsiderGCStart = FALSE) = 0;
503     virtual DWORD    WaitUntilGCComplete (BOOL bConsiderGCStart = FALSE) = 0;
504     virtual void SetGCInProgress(BOOL fInProgress) = 0;
505     virtual CLREventStatic * GetWaitForGCEvent() = 0;
506
507     virtual void    SetFinalizationRun (Object* obj) = 0;
508     virtual Object* GetNextFinalizable() = 0;
509     virtual size_t GetNumberOfFinalizable() = 0;
510
511     virtual void SetFinalizeQueueForShutdown(BOOL fHasLock) = 0;
512     virtual BOOL FinalizeAppDomain(AppDomain *pDomain, BOOL fRunFinalizers) = 0;
513     virtual BOOL ShouldRestartFinalizerWatchDog() = 0;
514
515     //wait for concurrent GC to finish
516     virtual void WaitUntilConcurrentGCComplete () = 0;                                  // Use in managed threads
517 #ifndef DACCESS_COMPILE    
518     virtual HRESULT WaitUntilConcurrentGCCompleteAsync(int millisecondsTimeout) = 0;    // Use in native threads. TRUE if succeed. FALSE if failed or timeout
519 #endif    
520     virtual BOOL IsConcurrentGCInProgress() = 0;
521
522     // Enable/disable concurrent GC    
523     virtual void TemporaryEnableConcurrentGC() = 0;
524     virtual void TemporaryDisableConcurrentGC() = 0;
525     virtual BOOL IsConcurrentGCEnabled() = 0;
526
527     virtual void FixAllocContext (alloc_context* acontext, BOOL lockp, void* arg, void *heap) = 0;
528     virtual Object* Alloc (alloc_context* acontext, size_t size, DWORD flags) = 0;
529
530     // This is safe to call only when EE is suspended.
531     virtual Object* GetContainingObject(void *pInteriorPtr) = 0;
532
533         // TODO Should be folded into constructor
534     virtual HRESULT Initialize () = 0;
535
536     virtual HRESULT GarbageCollect (int generation = -1, BOOL low_memory_p=FALSE, int mode = collection_blocking) = 0;
537     virtual Object*  Alloc (size_t size, DWORD flags) = 0;
538 #ifdef FEATURE_64BIT_ALIGNMENT
539     virtual Object*  AllocAlign8 (size_t size, DWORD flags) = 0;
540     virtual Object*  AllocAlign8 (alloc_context* acontext, size_t size, DWORD flags) = 0;
541 private:
542     virtual Object*  AllocAlign8Common (void* hp, alloc_context* acontext, size_t size, DWORD flags) = 0;
543 public:
544 #endif // FEATURE_64BIT_ALIGNMENT
545     virtual Object*  AllocLHeap (size_t size, DWORD flags) = 0;
546     virtual void     SetReservedVMLimit (size_t vmlimit) = 0;
547     virtual void SetCardsAfterBulkCopy( Object**, size_t ) = 0;
548 #if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)
549     virtual void WalkObject (Object* obj, walk_fn fn, void* context) = 0;
550 #endif //defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)
551
552     virtual bool IsThreadUsingAllocationContextHeap(alloc_context* acontext, int thread_number) = 0;
553     virtual int GetNumberOfHeaps () = 0; 
554     virtual int GetHomeHeapNumber () = 0;
555     
556     virtual int CollectionCount (int generation, int get_bgc_fgc_count = 0) = 0;
557
558         // Finalizer queue stuff (should stay)
559     virtual bool    RegisterForFinalization (int gen, Object* obj) = 0;
560
561         // General queries to the GC
562     virtual BOOL    IsPromoted (Object *object) = 0;
563     virtual unsigned WhichGeneration (Object* object) = 0;
564     virtual BOOL    IsEphemeral (Object* object) = 0;
565     virtual BOOL    IsHeapPointer (void* object, BOOL small_heap_only = FALSE) = 0;
566
567     virtual unsigned GetCondemnedGeneration() = 0;
568     virtual int GetGcLatencyMode() = 0;
569     virtual int SetGcLatencyMode(int newLatencyMode) = 0;
570
571     virtual int GetLOHCompactionMode() = 0;
572     virtual void SetLOHCompactionMode(int newLOHCompactionyMode) = 0;
573
574     virtual BOOL RegisterForFullGCNotification(DWORD gen2Percentage, 
575                                                DWORD lohPercentage) = 0;
576     virtual BOOL CancelFullGCNotification() = 0;
577     virtual int WaitForFullGCApproach(int millisecondsTimeout) = 0;
578     virtual int WaitForFullGCComplete(int millisecondsTimeout) = 0;
579
580     virtual int StartNoGCRegion(ULONGLONG totalSize, BOOL lohSizeKnown, ULONGLONG lohSize, BOOL disallowFullBlockingGC) = 0;
581     virtual int EndNoGCRegion() = 0;
582
583     virtual BOOL IsObjectInFixedHeap(Object *pObj) = 0;
584     virtual size_t  GetTotalBytesInUse () = 0;
585     virtual size_t  GetCurrentObjSize() = 0;
586     virtual size_t  GetLastGCStartTime(int generation) = 0;
587     virtual size_t  GetLastGCDuration(int generation) = 0;
588     virtual size_t  GetNow() = 0;
589     virtual unsigned GetGcCount() = 0;
590     virtual void TraceGCSegments() = 0;
591
592     virtual void PublishObject(BYTE* obj) = 0;
593
594     // static if since restricting for all heaps is fine
595     virtual size_t GetValidSegmentSize(BOOL large_seg = FALSE) = 0;
596
597
598     static BOOL IsLargeObject(MethodTable *mt) { 
599         WRAPPER_NO_CONTRACT;
600
601         return mt->GetBaseSize() >= LARGE_OBJECT_SIZE; 
602     }
603     
604     static unsigned GetMaxGeneration() {
605         LIMITED_METHOD_DAC_CONTRACT;  
606         return max_generation;
607     }
608
609     virtual size_t GetPromotedBytes(int heap_index) = 0;
610
611 private:
612     enum {
613         max_generation  = 2,
614     };
615     
616 public:
617
618 #ifdef FEATURE_BASICFREEZE
619     // frozen segment management functions
620     virtual segment_handle RegisterFrozenSegment(segment_info *pseginfo) = 0;
621 #endif //FEATURE_BASICFREEZE
622
623         // debug support 
624 #ifndef FEATURE_REDHAWK // Redhawk forces relocation a different way
625 #ifdef STRESS_HEAP
626     //return TRUE if GC actually happens, otherwise FALSE
627     virtual BOOL    StressHeap(alloc_context * acontext = 0) = 0;
628 #endif
629 #endif // FEATURE_REDHAWK
630 #ifdef VERIFY_HEAP
631     virtual void    ValidateObjectMember (Object *obj) = 0;
632 #endif
633
634 #if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)
635     virtual void DescrGenerationsToProfiler (gen_walk_fn fn, void *context) = 0;
636 #endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)
637
638 protected: 
639 #ifdef VERIFY_HEAP
640 public:
641     // Return NULL if can't find next object. When EE is not suspended,
642     // the result is not accurate: if the input arg is in gen0, the function could 
643     // return zeroed out memory as next object
644     virtual Object * NextObj (Object * object) = 0;
645 #ifdef FEATURE_BASICFREEZE
646     // Return TRUE if object lives in frozen segment
647     virtual BOOL IsInFrozenSegment (Object * object) = 0;
648 #endif //FEATURE_BASICFREEZE
649 #endif //VERIFY_HEAP    
650 };
651
652 extern VOLATILE(LONG) m_GCLock;
653
654 // Go through and touch (read) each page straddled by a memory block.
655 void TouchPages(LPVOID pStart, UINT cb);
656
657 // For low memory notification from host
658 extern LONG g_bLowMemoryFromHost;
659
660 #ifdef WRITE_BARRIER_CHECK
661 void updateGCShadow(Object** ptr, Object* val);
662 #endif
663
664 // the method table for the WeakReference class
665 extern MethodTable  *pWeakReferenceMT;
666 // The canonical method table for WeakReference<T>
667 extern MethodTable  *pWeakReferenceOfTCanonMT;
668 extern void FinalizeWeakReference(Object * obj);
669
670 #endif // __GC_H