1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
/*
* GCSCAN.H
*
* GC Root Scanning
*
*
*/
#ifndef _GCSCAN_H_
#define _GCSCAN_H_
#include "gc.h"
// Scanning dependent handles for promotion can become a complex operation due to cascaded dependencies and
// other issues (see the comments for GcDhInitialScan and friends in gcscan.cpp for further details). As a
// result we need to maintain a context between all the DH scanning methods called during a single mark phase.
// The structure below describes this context. We allocate one of these per GC heap at Ref_Initialize time and
// select between them based on the ScanContext passed to us by the GC during the mark phase.
struct DhContext
{
bool m_fUnpromotedPrimaries; // Did last scan find at least one non-null unpromoted primary?
bool m_fPromoted; // Did last scan promote at least one secondary?
promote_func *m_pfnPromoteFunction; // GC promote callback to be used for all secondary promotions
int m_iCondemned; // The condemned generation
int m_iMaxGen; // The maximum generation
ScanContext *m_pScanContext; // The GC's scan context for this phase
};
class GCScan
{
public:
static void GcScanSizedRefs(promote_func* fn, int condemned, int max_gen, ScanContext* sc);
// Regular stack Roots
static void GcScanRoots (promote_func* fn, int condemned, int max_gen, ScanContext* sc);
//
static void GcScanHandles (promote_func* fn, int condemned, int max_gen, ScanContext* sc);
static void GcRuntimeStructuresValid (BOOL bValid);
static bool GetGcRuntimeStructuresValid ();
#ifdef DACCESS_COMPILE
static void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
#endif // DACCESS_COMPILE
static void GcScanHandlesForProfilerAndETW (int max_gen, ScanContext* sc, handle_scan_fn fn);
static void GcScanDependentHandlesForProfilerAndETW (int max_gen, ScanContext* sc, handle_scan_fn fn);
// scan for dead weak pointers
static void GcWeakPtrScan (promote_func* fn, int condemned, int max_gen, ScanContext*sc );
static void GcWeakPtrScanBySingleThread (int condemned, int max_gen, ScanContext*sc );
// scan for dead weak pointers
static void GcShortWeakPtrScan (promote_func* fn, int condemned, int max_gen,
ScanContext* sc);
//
// Dependent handle promotion scan support
//
// Perform initial (incomplete) scan which will deterimine if there's any further work required.
static void GcDhInitialScan(promote_func* fn, int condemned, int max_gen, ScanContext* sc);
// Called between scans to ask if any handles with an unpromoted secondary existed at the end of the last
// scan.
static bool GcDhUnpromotedHandlesExist(ScanContext* sc);
// Rescan the handles for additonal primaries that have been promoted since the last scan. Return true if
// any objects were promoted as a result.
static bool GcDhReScan(ScanContext* sc);
// post-promotions callback
static void GcPromotionsGranted (int condemned, int max_gen,
ScanContext* sc);
// post-promotions callback some roots were demoted
static void GcDemote (int condemned, int max_gen, ScanContext* sc);
static size_t AskForMoreReservedMemory (size_t old_size, size_t need_size);
static void VerifyHandleTable(int condemned, int max_gen, ScanContext* sc);
static VOLATILE(int32_t) m_GcStructuresInvalidCnt;
};
#endif // _GCSCAN_H_
|