summaryrefslogtreecommitdiff
path: root/src/gc/gcscan.h
blob: 3515b8e1b67691a5f020f56b249b6c4011a33948 (plain)
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
// 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
{
    friend struct ::_DacGlobals;

  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

#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 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(int32_t, m_GcStructuresInvalidCnt);
#else
    static VOLATILE(int32_t) m_GcStructuresInvalidCnt;
#endif //DACCESS_COMPILE
};

// These two functions are utilized to scan the heap if requested by ETW
// or a profiler. The implementations of these two functions are in profheapwalkhelper.cpp.
#if defined(FEATURE_EVENT_TRACE) | defined(GC_PROFILING)
void ScanRootsHelper(Object* pObj, Object** ppRoot, ScanContext * pSC, DWORD dwFlags);
BOOL HeapWalkHelper(Object * pBO, void * pvContext);
#endif

#endif // _GCSCAN_H_