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_DAC_H_
6#define _GC_INTERFACE_DAC_H_
7
8// This file defines the interface between the GC and the DAC. The interface consists of two things:
9// 1. A number of variables ("DAC vars") whose addresses are exposed to the DAC (see "struct GcDacVars")
10// 2. A number of types that are analogues to GC-internal types. These types expose a subset of the
11// GC-internal type's fields, while still maintaining the same layout.
12// This interface is strictly versioned, see gcinterface.dacvars.def for more information.
13
14#define NUM_GC_DATA_POINTS 9
15#define MAX_COMPACT_REASONS_COUNT 11
16#define MAX_EXPAND_MECHANISMS_COUNT 6
17#define MAX_GC_MECHANISM_BITS_COUNT 2
18#define MAX_GLOBAL_GC_MECHANISMS_COUNT 6
19#define NUMBERGENERATIONS 4
20#define INITIAL_HANDLE_TABLE_ARRAY_SIZE 10
21#define HANDLE_MAX_INTERNAL_TYPES 12
22
23// Analogue for the GC heap_segment class, containing information regarding a single
24// heap segment.
25class dac_heap_segment {
26public:
27 uint8_t* allocated;
28 uint8_t* committed;
29 uint8_t* reserved;
30 uint8_t* used;
31 uint8_t* mem;
32 size_t flags;
33 DPTR(dac_heap_segment) next;
34 uint8_t* background_allocated;
35 class dac_gc_heap* heap;
36};
37
38// Analogue for the GC generation class, containing information about the start segment
39// of a generation and its allocation context.
40class dac_generation {
41public:
42 gc_alloc_context allocation_context;
43 DPTR(dac_heap_segment) start_segment;
44 uint8_t* allocation_start;
45};
46
47// Analogue for the GC CFinalize class, containing information about the finalize queue.
48class dac_finalize_queue {
49public:
50 static const int ExtraSegCount = 2;
51 uint8_t** m_FillPointers[NUMBERGENERATIONS + ExtraSegCount];
52};
53
54class dac_handle_table {
55public:
56 // On the handle table side, this is an ADIndex. They should still have
57 // the same layout.
58 //
59 // We do try to keep everything that the DAC knows about as close to the
60 // start of the struct as possible to avoid having padding members. However,
61 // HandleTable has rgTypeFlags at offset 0 for performance reasons and
62 // we don't want to disrupt that.
63 uint32_t padding[HANDLE_MAX_INTERNAL_TYPES];
64 DWORD uADIndex;
65};
66
67class dac_handle_table_bucket {
68public:
69 DPTR(DPTR(dac_handle_table)) pTable;
70 uint32_t HandleTableIndex;
71};
72
73class dac_handle_table_map {
74public:
75 DPTR(DPTR(dac_handle_table_bucket)) pBuckets;
76 DPTR(dac_handle_table_map) pNext;
77 uint32_t dwMaxIndex;
78};
79
80// Possible values of the current_c_gc_state dacvar, indicating the state of
81// a background GC.
82enum c_gc_state
83{
84 c_gc_state_marking,
85 c_gc_state_planning,
86 c_gc_state_free
87};
88
89// Reasons why an OOM might occur, recorded in the oom_history
90// struct below.
91enum oom_reason
92{
93 oom_no_failure = 0,
94 oom_budget = 1,
95 oom_cant_commit = 2,
96 oom_cant_reserve = 3,
97 oom_loh = 4,
98 oom_low_mem = 5,
99 oom_unproductive_full_gc = 6
100};
101
102/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
103/* If you modify failure_get_memory and */
104/* oom_reason be sure to make the corresponding */
105/* changes in toolbox\sos\strike\strike.cpp. */
106/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
107enum failure_get_memory
108{
109 fgm_no_failure = 0,
110 fgm_reserve_segment = 1,
111 fgm_commit_segment_beg = 2,
112 fgm_commit_eph_segment = 3,
113 fgm_grow_table = 4,
114 fgm_commit_table = 5
115};
116
117// A record of the last OOM that occured in the GC, with some
118// additional information as to what triggered the OOM.
119struct oom_history
120{
121 oom_reason reason;
122 size_t alloc_size;
123 uint8_t* reserved;
124 uint8_t* allocated;
125 size_t gc_index;
126 failure_get_memory fgm;
127 size_t size;
128 size_t available_pagefile_mb;
129 BOOL loh_p;
130};
131
132// Analogue for the GC gc_heap class, containing information regarding a single
133// GC heap (of which there are multiple, with server GC).
134class dac_gc_heap {
135public:
136 uint8_t* alloc_allocated;
137 DPTR(dac_heap_segment) ephemeral_heap_segment;
138 DPTR(dac_finalize_queue) finalize_queue;
139 oom_history oom_info;
140 size_t interesting_data_per_heap[NUM_GC_DATA_POINTS];
141 size_t compact_reasons_per_heap[MAX_COMPACT_REASONS_COUNT];
142 size_t expand_mechanisms_per_heap[MAX_EXPAND_MECHANISMS_COUNT];
143 size_t interesting_mechanism_bits_per_heap[MAX_GC_MECHANISM_BITS_COUNT];
144 uint8_t* internal_root_array;
145 size_t internal_root_array_index;
146 BOOL heap_analyze_success;
147
148 // The generation table must always be last, because the size of this array
149 // (stored inline in the gc_heap class) can vary.
150 //
151 // The size of the generation class is not part of the GC-DAC interface,
152 // despite being embedded by-value into the gc_heap class. The DAC variable
153 // "generation_size" stores the size of the generation class, so the DAC can
154 // use it and pointer arithmetic to calculate correct offsets into the generation
155 // table. (See "GenerationTableIndex" function in the DAC for details)
156 //
157 // Also note that this array has length 1 because the C++ standard doesn't allow
158 // for 0-length arrays, although every major compiler is willing to tolerate it.
159 dac_generation generation_table[1];
160};
161
162
163// The DAC links against six symbols that build as part of the VM DACCESS_COMPILE
164// build. These symbols are considered to be GC-private functions, but the DAC needs
165// to use them in order to perform some handle-related functions. These six functions
166// are adorned by this macro to make clear that their implementations must be versioned
167// alongside the rest of this file.
168//
169// Practically, this macro ensures that the target symbols aren't mangled, since the
170// DAC calls them with a signature slightly different than the one used when they
171// were defined.
172#define GC_DAC_VISIBLE
173
174#ifdef DACCESS_COMPILE
175#define GC_DAC_VISIBLE_NO_MANGLE extern "C"
176#else
177#define GC_DAC_VISIBLE_NO_MANGLE
178#endif // DACCESS_COMPILE
179
180// The actual structure containing the DAC variables. When DACCESS_COMPILE is not
181// defined (i.e. the normal runtime build), this structure contains pointers to the
182// GC's global DAC variabels. When DACCESS_COMPILE is defined (i.e. the DAC build),
183// this structure contains __DPtrs for every DAC variable that will marshal values
184// from the debugee process to the debugger process when dereferenced.
185struct GcDacVars {
186 uint8_t major_version_number;
187 uint8_t minor_version_number;
188 size_t generation_size;
189#ifdef DACCESS_COMPILE
190 #define GC_DAC_VAR(type, name) DPTR(type) name;
191 #define GC_DAC_PTR_VAR(type, name) DPTR(type*) name;
192 #define GC_DAC_ARRAY_VAR(type, name) DPTR(type) name;
193#else
194 #define GC_DAC_VAR(type, name) type *name;
195#endif
196#include "gcinterface.dacvars.def"
197};
198
199#endif // _GC_INTERFACE_DAC_H_
200