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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license 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
};
// <TODO>
// @TODO (JSW): For compatibility with the existing GC code we use CNamespace
// as the name of this class. I'm planning on changing it to
// something like GCDomain....
// </TODO>
typedef void enum_alloc_context_func(alloc_context*);
class CNameSpace
{
friend struct ::_DacGlobals;
public:
// Called on gc start
static void GcStartDoWork();
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
#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)
static void GcScanHandlesForProfilerAndETW (int max_gen, ScanContext* sc);
static void GcScanDependentHandlesForProfilerAndETW (int max_gen, ProfilingScanContext* sc);
#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)
// 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 void GcEnumAllocContexts (enum_alloc_context_func* fn);
static void GcFixAllocContexts (void* arg, void *heap);
static size_t AskForMoreReservedMemory (size_t old_size, size_t need_size);
static void VerifyHandleTable(int condemned, int max_gen, ScanContext* sc);
private:
#ifdef DACCESS_COMPILE
SVAL_DECL(LONG, m_GcStructuresInvalidCnt);
#else
static VOLATILE(LONG) m_GcStructuresInvalidCnt;
#endif //DACCESS_COMPILE
};
#endif // _GCSCAN_H_
|