1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 #ifndef _GC_INTERFACE_H_ 6 #define _GC_INTERFACE_H_ 7 8 struct ScanContext; 9 struct gc_alloc_context; 10 class CrawlFrame; 11 12 // Callback passed to GcScanRoots. 13 typedef void promote_func(PTR_PTR_Object, ScanContext*, uint32_t); 14 15 // Callback passed to GcEnumAllocContexts. 16 typedef void enum_alloc_context_func(gc_alloc_context*, void*); 17 18 // Callback passed to CreateBackgroundThread. 19 typedef uint32_t (__stdcall *GCBackgroundThreadFunction)(void* param); 20 21 // Struct often used as a parameter to callbacks. 22 typedef struct 23 { 24 promote_func* f; 25 ScanContext* sc; 26 CrawlFrame * cf; 27 } GCCONTEXT; 28 29 // SUSPEND_REASON is the reason why the GC wishes to suspend the EE, 30 // used as an argument to IGCToCLR::SuspendEE. 31 typedef enum 32 { 33 SUSPEND_FOR_GC = 1, 34 SUSPEND_FOR_GC_PREP = 6 35 } SUSPEND_REASON; 36 37 typedef enum 38 { 39 walk_for_gc = 1, 40 walk_for_bgc = 2, 41 walk_for_loh = 3 42 } walk_surv_type; 43 44 // Different operations that can be done by GCToEEInterface::StompWriteBarrier 45 enum class WriteBarrierOp 46 { 47 StompResize, 48 StompEphemeral, 49 Initialize, 50 SwitchToWriteWatch, 51 SwitchToNonWriteWatch 52 }; 53 54 // Arguments to GCToEEInterface::StompWriteBarrier 55 struct WriteBarrierParameters 56 { 57 // The operation that StompWriteBarrier will perform. 58 WriteBarrierOp operation; 59 60 // Whether or not the runtime is currently suspended. If it is not, 61 // the EE will need to suspend it before bashing the write barrier. 62 // Used for all operations. 63 bool is_runtime_suspended; 64 65 // Whether or not the GC has moved the ephemeral generation to no longer 66 // be at the top of the heap. When the ephemeral generation is at the top 67 // of the heap, and the write barrier observes that a pointer is greater than 68 // g_ephemeral_low, it does not need to check that the pointer is less than 69 // g_ephemeral_high because there is nothing in the GC heap above the ephemeral 70 // generation. When this is not the case, however, the GC must inform the EE 71 // so that the EE can switch to a write barrier that checks that a pointer 72 // is both greater than g_ephemeral_low and less than g_ephemeral_high. 73 // Used for WriteBarrierOp::StompResize. 74 bool requires_upper_bounds_check; 75 76 // The new card table location. May or may not be the same as the previous 77 // card table. Used for WriteBarrierOp::Initialize and WriteBarrierOp::StompResize. 78 uint32_t* card_table; 79 80 // The heap's new low boundary. May or may not be the same as the previous 81 // value. Used for WriteBarrierOp::Initialize and WriteBarrierOp::StompResize. 82 uint8_t* lowest_address; 83 84 // The heap's new high boundary. May or may not be the same as the previous 85 // value. Used for WriteBarrierOp::Initialize and WriteBarrierOp::StompResize. 86 uint8_t* highest_address; 87 88 // The new start of the ephemeral generation. 89 // Used for WriteBarrierOp::StompEphemeral. 90 uint8_t* ephemeral_low; 91 92 // The new end of the ephemeral generation. 93 // Used for WriteBarrierOp::StompEphemeral. 94 uint8_t* ephemeral_high; 95 96 // The new write watch table, if we are using our own write watch 97 // implementation. Used for WriteBarrierOp::SwitchToWriteWatch only. 98 uint8_t* write_watch_table; 99 }; 100 101 #include "gcinterface.ee.h" 102 103 // The allocation context must be known to the VM for use in the allocation 104 // fast path and known to the GC for performing the allocation. Every Thread 105 // has its own allocation context that it hands to the GC when allocating. 106 struct gc_alloc_context 107 { 108 uint8_t* alloc_ptr; 109 uint8_t* alloc_limit; 110 int64_t alloc_bytes; //Number of bytes allocated on SOH by this context 111 int64_t alloc_bytes_loh; //Number of bytes allocated on LOH by this context 112 // These two fields are deliberately not exposed past the EE-GC interface. 113 void* gc_reserved_1; 114 void* gc_reserved_2; 115 int alloc_count; 116 public: 117 initgc_alloc_context118 void init() 119 { 120 LIMITED_METHOD_CONTRACT; 121 122 alloc_ptr = 0; 123 alloc_limit = 0; 124 alloc_bytes = 0; 125 alloc_bytes_loh = 0; 126 gc_reserved_1 = 0; 127 gc_reserved_2 = 0; 128 alloc_count = 0; 129 } 130 }; 131 132 // stub type to abstract a heap segment 133 struct gc_heap_segment_stub; 134 typedef gc_heap_segment_stub *segment_handle; 135 136 struct segment_info 137 { 138 void * pvMem; // base of the allocation, not the first object (must add ibFirstObject) 139 size_t ibFirstObject; // offset to the base of the first object in the segment 140 size_t ibAllocated; // limit of allocated memory in the segment (>= firstobject) 141 size_t ibCommit; // limit of committed memory in the segment (>= alllocated) 142 size_t ibReserved; // limit of reserved memory in the segment (>= commit) 143 }; 144 145 #ifdef PROFILING_SUPPORTED 146 #define GC_PROFILING //Turn on profiling 147 #endif // PROFILING_SUPPORTED 148 149 #define LARGE_OBJECT_SIZE ((size_t)(85000)) 150 151 // The minimum size of an object is three pointers wide: one for the syncblock, 152 // one for the object header, and one for the first field in the object. 153 #define min_obj_size ((sizeof(uint8_t*) + sizeof(uintptr_t) + sizeof(size_t))) 154 155 #define max_generation 2 156 157 // The bit shift used to convert a memory address into an index into the 158 // Software Write Watch table. 159 #define SOFTWARE_WRITE_WATCH_AddressToTableByteIndexShift 0xc 160 161 class Object; 162 class IGCHeap; 163 164 // Initializes the garbage collector. Should only be called 165 // once, during EE startup. 166 IGCHeap* InitializeGarbageCollector(IGCToCLR* clrToGC); 167 168 // The runtime needs to know whether we're using workstation or server GC 169 // long before the GCHeap is created. This function sets the type of 170 // heap that will be created, before InitializeGarbageCollector is called 171 // and the heap is actually recated. 172 void InitializeHeapType(bool bServerHeap); 173 174 #ifdef WRITE_BARRIER_CHECK 175 //always defined, but should be 0 in Server GC 176 extern uint8_t* g_GCShadow; 177 extern uint8_t* g_GCShadowEnd; 178 // saves the g_lowest_address in between GCs to verify the consistency of the shadow segment 179 extern uint8_t* g_shadow_lowest_address; 180 #endif 181 182 // For low memory notification from host 183 extern int32_t g_bLowMemoryFromHost; 184 185 extern VOLATILE(int32_t) m_GCLock; 186 187 // !!!!!!!!!!!!!!!!!!!!!!! 188 // make sure you change the def in bcl\system\gc.cs 189 // if you change this! 190 enum collection_mode 191 { 192 collection_non_blocking = 0x00000001, 193 collection_blocking = 0x00000002, 194 collection_optimized = 0x00000004, 195 collection_compacting = 0x00000008 196 #ifdef STRESS_HEAP 197 , collection_gcstress = 0x80000000 198 #endif // STRESS_HEAP 199 }; 200 201 // !!!!!!!!!!!!!!!!!!!!!!! 202 // make sure you change the def in bcl\system\gc.cs 203 // if you change this! 204 enum wait_full_gc_status 205 { 206 wait_full_gc_success = 0, 207 wait_full_gc_failed = 1, 208 wait_full_gc_cancelled = 2, 209 wait_full_gc_timeout = 3, 210 wait_full_gc_na = 4 211 }; 212 213 // !!!!!!!!!!!!!!!!!!!!!!! 214 // make sure you change the def in bcl\system\gc.cs 215 // if you change this! 216 enum start_no_gc_region_status 217 { 218 start_no_gc_success = 0, 219 start_no_gc_no_memory = 1, 220 start_no_gc_too_large = 2, 221 start_no_gc_in_progress = 3 222 }; 223 224 enum end_no_gc_region_status 225 { 226 end_no_gc_success = 0, 227 end_no_gc_not_in_progress = 1, 228 end_no_gc_induced = 2, 229 end_no_gc_alloc_exceeded = 3 230 }; 231 232 typedef BOOL (* walk_fn)(Object*, void*); 233 typedef void (* gen_walk_fn)(void* context, int generation, uint8_t* range_start, uint8_t* range_end, uint8_t* range_reserved); 234 typedef void (* record_surv_fn)(uint8_t* begin, uint8_t* end, ptrdiff_t reloc, size_t context, BOOL compacting_p, BOOL bgc_p); 235 typedef void (* fq_walk_fn)(BOOL, void*); 236 typedef void (* fq_scan_fn)(Object** ppObject, ScanContext *pSC, uint32_t dwFlags); 237 typedef void (* handle_scan_fn)(Object** pRef, Object* pSec, uint32_t flags, ScanContext* context, BOOL isDependent); 238 239 // IGCHeap is the interface that the VM will use when interacting with the GC. 240 class IGCHeap { 241 public: 242 /* 243 =========================================================================== 244 Hosting APIs. These are used by GC hosting. The code that 245 calls these methods may possibly be moved behind the interface - 246 today, the VM handles the setting of segment size and max gen 0 size. 247 (See src/vm/corehost.cpp) 248 =========================================================================== 249 */ 250 251 // Returns whether or not the given size is a valid segment size. 252 virtual BOOL IsValidSegmentSize(size_t size) = 0; 253 254 // Returns whether or not the given size is a valid gen 0 max size. 255 virtual BOOL IsValidGen0MaxSize(size_t size) = 0; 256 257 // Gets a valid segment size. 258 virtual size_t GetValidSegmentSize(BOOL large_seg = FALSE) = 0; 259 260 // Sets the limit for reserved virtual memory. 261 virtual void SetReservedVMLimit(size_t vmlimit) = 0; 262 263 /* 264 =========================================================================== 265 Concurrent GC routines. These are used in various places in the VM 266 to synchronize with the GC, when the VM wants to update something that 267 the GC is potentially using, if it's doing a background GC. 268 269 Concrete examples of this are moving async pinned handles across appdomains 270 and profiling/ETW scenarios. 271 =========================================================================== 272 */ 273 274 // Blocks until any running concurrent GCs complete. 275 virtual void WaitUntilConcurrentGCComplete() = 0; 276 277 // Returns true if a concurrent GC is in progress, false otherwise. 278 virtual BOOL IsConcurrentGCInProgress() = 0; 279 280 // Temporarily enables concurrent GC, used during profiling. 281 virtual void TemporaryEnableConcurrentGC() = 0; 282 283 // Temporarily disables concurrent GC, used during profiling. 284 virtual void TemporaryDisableConcurrentGC() = 0; 285 286 // Returns whether or not Concurrent GC is enabled. 287 virtual BOOL IsConcurrentGCEnabled() = 0; 288 289 // Wait for a concurrent GC to complete if one is in progress, with the given timeout. 290 virtual HRESULT WaitUntilConcurrentGCCompleteAsync(int millisecondsTimeout) = 0; // Use in native threads. TRUE if succeed. FALSE if failed or timeout 291 292 293 /* 294 =========================================================================== 295 Finalization routines. These are used by the finalizer thread to communicate 296 with the GC. 297 =========================================================================== 298 */ 299 300 // Finalizes an app domain by finalizing objects within that app domain. 301 virtual BOOL FinalizeAppDomain(AppDomain* pDomain, BOOL fRunFinalizers) = 0; 302 303 // Finalizes all registered objects for shutdown, even if they are still reachable. 304 virtual void SetFinalizeQueueForShutdown(BOOL fHasLock) = 0; 305 306 // Gets the number of finalizable objects. 307 virtual size_t GetNumberOfFinalizable() = 0; 308 309 // Traditionally used by the finalizer thread on shutdown to determine 310 // whether or not to time out. Returns true if the GC lock has not been taken. 311 virtual BOOL ShouldRestartFinalizerWatchDog() = 0; 312 313 // Gets the next finalizable object. 314 virtual Object* GetNextFinalizable() = 0; 315 316 // Sets whether or not the GC should report all finalizable objects as 317 // ready to be finalized, instead of only collectable objects. 318 virtual void SetFinalizeRunOnShutdown(bool value) = 0; 319 320 /* 321 =========================================================================== 322 BCL routines. These are routines that are directly exposed by mscorlib 323 as a part of the `System.GC` class. These routines behave in the same 324 manner as the functions on `System.GC`. 325 =========================================================================== 326 */ 327 328 // Gets the current GC latency mode. 329 virtual int GetGcLatencyMode() = 0; 330 331 // Sets the current GC latency mode. newLatencyMode has already been 332 // verified by mscorlib to be valid. 333 virtual int SetGcLatencyMode(int newLatencyMode) = 0; 334 335 // Gets the current LOH compaction mode. 336 virtual int GetLOHCompactionMode() = 0; 337 338 // Sets the current LOH compaction mode. newLOHCompactionMode has 339 // already been verified by mscorlib to be valid. 340 virtual void SetLOHCompactionMode(int newLOHCompactionMode) = 0; 341 342 // Registers for a full GC notification, raising a notification if the gen 2 or 343 // LOH object heap thresholds are exceeded. 344 virtual BOOL RegisterForFullGCNotification(uint32_t gen2Percentage, uint32_t lohPercentage) = 0; 345 346 // Cancels a full GC notification that was requested by `RegisterForFullGCNotification`. 347 virtual BOOL CancelFullGCNotification() = 0; 348 349 // Returns the status of a registered notification for determining whether a blocking 350 // Gen 2 collection is about to be initiated, with the given timeout. 351 virtual int WaitForFullGCApproach(int millisecondsTimeout) = 0; 352 353 // Returns the status of a registered notification for determining whether a blocking 354 // Gen 2 collection has completed, with the given timeout. 355 virtual int WaitForFullGCComplete(int millisecondsTimeout) = 0; 356 357 // Returns the generation in which obj is found. Also used by the VM 358 // in some places, in particular syncblk code. 359 virtual unsigned WhichGeneration(Object* obj) = 0; 360 361 // Returns the number of GCs that have transpired in the given generation 362 // since the beginning of the life of the process. Also used by the VM 363 // for debug code and app domains. 364 virtual int CollectionCount(int generation, int get_bgc_fgc_coutn = 0) = 0; 365 366 // Begins a no-GC region, returning a code indicating whether entering the no-GC 367 // region was successful. 368 virtual int StartNoGCRegion(uint64_t totalSize, BOOL lohSizeKnown, uint64_t lohSize, BOOL disallowFullBlockingGC) = 0; 369 370 // Exits a no-GC region. 371 virtual int EndNoGCRegion() = 0; 372 373 // Gets the total number of bytes in use. 374 virtual size_t GetTotalBytesInUse() = 0; 375 376 // Forces a garbage collection of the given generation. Also used extensively 377 // throughout the VM. 378 virtual HRESULT GarbageCollect(int generation = -1, BOOL low_memory_p = FALSE, int mode = collection_blocking) = 0; 379 380 // Gets the largest GC generation. Also used extensively throughout the VM. 381 virtual unsigned GetMaxGeneration() = 0; 382 383 // Indicates that an object's finalizer should not be run upon the object's collection. 384 virtual void SetFinalizationRun(Object* obj) = 0; 385 386 // Indicates that an object's finalizer should be run upon the object's collection. 387 virtual bool RegisterForFinalization(int gen, Object* obj) = 0; 388 389 /* 390 =========================================================================== 391 Miscellaneous routines used by the VM. 392 =========================================================================== 393 */ 394 395 // Initializes the GC heap, returning whether or not the initialization 396 // was successful. 397 virtual HRESULT Initialize() = 0; 398 399 // Returns whether nor this GC was promoted by the last GC. 400 virtual BOOL IsPromoted(Object* object) = 0; 401 402 // Returns true if this pointer points into a GC heap, false otherwise. 403 virtual BOOL IsHeapPointer(void* object, BOOL small_heap_only = FALSE) = 0; 404 405 // Return the generation that has been condemned by the current GC. 406 virtual unsigned GetCondemnedGeneration() = 0; 407 408 // Returns whether or not a GC is in progress. 409 virtual BOOL IsGCInProgressHelper(BOOL bConsiderGCStart = FALSE) = 0; 410 411 // Returns the number of GCs that have occured. Mainly used for 412 // sanity checks asserting that a GC has not occured. 413 virtual unsigned GetGcCount() = 0; 414 415 // Gets whether or not the home heap of this alloc context matches the heap 416 // associated with this thread. 417 virtual bool IsThreadUsingAllocationContextHeap(gc_alloc_context* acontext, int thread_number) = 0; 418 419 // Returns whether or not this object resides in an ephemeral generation. 420 virtual BOOL IsEphemeral(Object* object) = 0; 421 422 // Blocks until a GC is complete, returning a code indicating the wait was successful. 423 virtual uint32_t WaitUntilGCComplete(BOOL bConsiderGCStart = FALSE) = 0; 424 425 // "Fixes" an allocation context by binding its allocation pointer to a 426 // location on the heap. 427 virtual void FixAllocContext(gc_alloc_context* acontext, BOOL lockp, void* arg, void* heap) = 0; 428 429 // Gets the total survived size plus the total allocated bytes on the heap. 430 virtual size_t GetCurrentObjSize() = 0; 431 432 // Sets whether or not a GC is in progress. 433 virtual void SetGCInProgress(BOOL fInProgress) = 0; 434 435 /* 436 ============================================================================ 437 Add/RemoveMemoryPressure support routines. These are on the interface 438 for now, but we should move Add/RemoveMemoryPressure from the VM to the GC. 439 When that occurs, these three routines can be removed from the interface. 440 ============================================================================ 441 */ 442 443 // Get the timestamp corresponding to the last GC that occured for the 444 // given generation. 445 virtual size_t GetLastGCStartTime(int generation) = 0; 446 447 // Gets the duration of the last GC that occured for the given generation. 448 virtual size_t GetLastGCDuration(int generation) = 0; 449 450 // Gets a timestamp for the current moment in time. 451 virtual size_t GetNow() = 0; 452 453 /* 454 =========================================================================== 455 Allocation routines. These all call into the GC's allocator and may trigger a garbage 456 collection. All allocation routines return NULL when the allocation request 457 couldn't be serviced due to being out of memory. 458 =========================================================================== 459 */ 460 461 // Allocates an object on the given allocation context with the given size and flags. 462 virtual Object* Alloc(gc_alloc_context* acontext, size_t size, uint32_t flags) = 0; 463 464 // Allocates an object on the default allocation context with the given size and flags. 465 virtual Object* Alloc(size_t size, uint32_t flags) = 0; 466 467 // Allocates an object on the large object heap with the given size and flags. 468 virtual Object* AllocLHeap(size_t size, uint32_t flags) = 0; 469 470 // Allocates an object on the default allocation context, aligned to 64 bits, 471 // with the given size and flags. 472 virtual Object* AllocAlign8 (size_t size, uint32_t flags) = 0; 473 474 // Allocates an object on the given allocation context, aligned to 64 bits, 475 // with the given size and flags. 476 virtual Object* AllocAlign8 (gc_alloc_context* acontext, size_t size, uint32_t flags) = 0; 477 478 // This is for the allocator to indicate it's done allocating a large object during a 479 // background GC as the BGC threads also need to walk LOH. 480 virtual void PublishObject(uint8_t* obj) = 0; 481 482 // Gets the event that suspended threads will use to wait for the 483 // end of a GC. 484 virtual CLREventStatic* GetWaitForGCEvent() = 0; 485 486 /* 487 =========================================================================== 488 Heap verification routines. These are used during heap verification only. 489 =========================================================================== 490 */ 491 // Returns whether or not this object is in the fixed heap. 492 virtual BOOL IsObjectInFixedHeap(Object* pObj) = 0; 493 494 // Walks an object and validates its members. 495 virtual void ValidateObjectMember(Object* obj) = 0; 496 497 // Retrieves the next object after the given object. When the EE 498 // is not suspended, the result is not accurate - if the input argument 499 // is in Gen0, the function could return zeroed out memory as the next object. 500 virtual Object* NextObj(Object* object) = 0; 501 502 // Given an interior pointer, return a pointer to the object 503 // containing that pointer. This is safe to call only when the EE is suspended. 504 virtual Object* GetContainingObject(void* pInteriorPtr) = 0; 505 506 /* 507 =========================================================================== 508 Profiling routines. Used for event tracing and profiling to broadcast 509 information regarding the heap. 510 =========================================================================== 511 */ 512 513 // Walks an object, invoking a callback on each member. 514 virtual void DiagWalkObject(Object* obj, walk_fn fn, void* context) = 0; 515 516 // Walk the heap object by object. 517 virtual void DiagWalkHeap(walk_fn fn, void* context, int gen_number, BOOL walk_large_object_heap_p) = 0; 518 519 // Walks the survivors and get the relocation information if objects have moved. 520 virtual void DiagWalkSurvivorsWithType(void* gc_context, record_surv_fn fn, size_t diag_context, walk_surv_type type) = 0; 521 522 // Walks the finalization queue. 523 virtual void DiagWalkFinalizeQueue(void* gc_context, fq_walk_fn fn) = 0; 524 525 // Scan roots on finalizer queue. This is a generic function. 526 virtual void DiagScanFinalizeQueue(fq_scan_fn fn, ScanContext* context) = 0; 527 528 // Scan handles for profiling or ETW. 529 virtual void DiagScanHandles(handle_scan_fn fn, int gen_number, ScanContext* context) = 0; 530 531 // Scan dependent handles for profiling or ETW. 532 virtual void DiagScanDependentHandles(handle_scan_fn fn, int gen_number, ScanContext* context) = 0; 533 534 // Describes all generations to the profiler, invoking a callback on each generation. 535 virtual void DiagDescrGenerations(gen_walk_fn fn, void* context) = 0; 536 537 // Traces all GC segments and fires ETW events with information on them. 538 virtual void DiagTraceGCSegments() = 0; 539 540 /* 541 =========================================================================== 542 GC Stress routines. Used only when running under GC Stress. 543 =========================================================================== 544 */ 545 546 // Returns TRUE if GC actually happens, otherwise FALSE 547 virtual BOOL StressHeap(gc_alloc_context* acontext = 0) = 0; 548 549 /* 550 =========================================================================== 551 Routines to register read only segments for frozen objects. 552 Only valid if FEATURE_BASICFREEZE is defined. 553 =========================================================================== 554 */ 555 556 // Registers a frozen segment with the GC. 557 virtual segment_handle RegisterFrozenSegment(segment_info *pseginfo) = 0; 558 559 // Unregisters a frozen segment. 560 virtual void UnregisterFrozenSegment(segment_handle seg) = 0; 561 IGCHeap()562 IGCHeap() {} ~IGCHeap()563 virtual ~IGCHeap() {} 564 565 typedef enum 566 { 567 GC_HEAP_INVALID = 0, 568 GC_HEAP_WKS = 1, 569 GC_HEAP_SVR = 2 570 } GC_HEAP_TYPE; 571 572 #ifdef FEATURE_SVR_GC 573 SVAL_DECL(uint32_t, gcHeapType); 574 #endif 575 576 SVAL_DECL(uint32_t, maxGeneration); 577 }; 578 579 #ifdef WRITE_BARRIER_CHECK 580 void updateGCShadow(Object** ptr, Object* val); 581 #endif 582 583 //constants for the flags parameter to the gc call back 584 585 #define GC_CALL_INTERIOR 0x1 586 #define GC_CALL_PINNED 0x2 587 #define GC_CALL_CHECK_APP_DOMAIN 0x4 588 589 //flags for IGCHeapAlloc(...) 590 #define GC_ALLOC_FINALIZE 0x1 591 #define GC_ALLOC_CONTAINS_REF 0x2 592 #define GC_ALLOC_ALIGN8_BIAS 0x4 593 #define GC_ALLOC_ALIGN8 0x8 594 595 struct ScanContext 596 { 597 Thread* thread_under_crawl; 598 int thread_number; 599 uintptr_t stack_limit; // Lowest point on the thread stack that the scanning logic is permitted to read 600 BOOL promotion; //TRUE: Promotion, FALSE: Relocation. 601 BOOL concurrent; //TRUE: concurrent scanning 602 #if CHECK_APP_DOMAIN_LEAKS || defined (FEATURE_APPDOMAIN_RESOURCE_MONITORING) || defined (DACCESS_COMPILE) 603 AppDomain *pCurrentDomain; 604 #endif //CHECK_APP_DOMAIN_LEAKS || FEATURE_APPDOMAIN_RESOURCE_MONITORING || DACCESS_COMPILE 605 606 #ifndef FEATURE_REDHAWK 607 #if defined(GC_PROFILING) || defined (DACCESS_COMPILE) 608 MethodDesc *pMD; 609 #endif //GC_PROFILING || DACCESS_COMPILE 610 #endif // FEATURE_REDHAWK 611 #if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) 612 EtwGCRootKind dwEtwRootKind; 613 #endif // GC_PROFILING || FEATURE_EVENT_TRACE 614 ScanContextScanContext615 ScanContext() 616 { 617 LIMITED_METHOD_CONTRACT; 618 619 thread_under_crawl = 0; 620 thread_number = -1; 621 stack_limit = 0; 622 promotion = FALSE; 623 concurrent = FALSE; 624 #ifdef GC_PROFILING 625 pMD = NULL; 626 #endif //GC_PROFILING 627 #ifdef FEATURE_EVENT_TRACE 628 dwEtwRootKind = kEtwGCRootKindOther; 629 #endif // FEATURE_EVENT_TRACE 630 } 631 }; 632 633 #endif // _GC_INTERFACE_H_ 634