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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
|
// 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.
/*
* Generational GC handle manager. Entrypoint Header.
*
* Implements generic support for external handles into a GC heap.
*
*
*/
#ifndef _HANDLETABLE_H
#define _HANDLETABLE_H
#include "gcinterface.h"
/****************************************************************************
*
* FLAGS, CONSTANTS AND DATA TYPES
*
****************************************************************************/
#ifdef _DEBUG
#define DEBUG_DestroyedHandleValue ((_UNCHECKED_OBJECTREF)0x7)
#endif
/*
* handle flags used by HndCreateHandleTable
*/
#define HNDF_NORMAL (0x00)
#define HNDF_EXTRAINFO (0x01)
/*
* handle to handle table
*/
typedef DPTR(struct HandleTable) PTR_HandleTable;
typedef DPTR(PTR_HandleTable) PTR_PTR_HandleTable;
typedef PTR_HandleTable HHANDLETABLE;
typedef PTR_PTR_HandleTable PTR_HHANDLETABLE;
/*--------------------------------------------------------------------------*/
/****************************************************************************
*
* PUBLIC ROUTINES AND MACROS
*
****************************************************************************/
#ifndef DACCESS_COMPILE
/*
* handle manager init and shutdown routines
*/
HHANDLETABLE HndCreateHandleTable(const uint32_t *pTypeFlags, uint32_t uTypeCount, ADIndex uADIndex);
void HndDestroyHandleTable(HHANDLETABLE hTable);
#endif // !DACCESS_COMPILE
/*
* retrieve index stored in table at creation
*/
void HndSetHandleTableIndex(HHANDLETABLE hTable, uint32_t uTableIndex);
uint32_t HndGetHandleTableIndex(HHANDLETABLE hTable);
ADIndex HndGetHandleTableADIndex(HHANDLETABLE hTable);
GC_DAC_VISIBLE
ADIndex HndGetHandleADIndex(OBJECTHANDLE handle);
#ifndef DACCESS_COMPILE
/*
* individual handle allocation and deallocation
*/
OBJECTHANDLE HndCreateHandle(HHANDLETABLE hTable, uint32_t uType, OBJECTREF object, uintptr_t lExtraInfo = 0);
void HndDestroyHandle(HHANDLETABLE hTable, uint32_t uType, OBJECTHANDLE handle);
void HndDestroyHandleOfUnknownType(HHANDLETABLE hTable, OBJECTHANDLE handle);
/*
* owner data associated with handles
*/
void HndSetHandleExtraInfo(OBJECTHANDLE handle, uint32_t uType, uintptr_t lExtraInfo);
uintptr_t HndCompareExchangeHandleExtraInfo(OBJECTHANDLE handle, uint32_t uType, uintptr_t lOldExtraInfo, uintptr_t lNewExtraInfo);
#endif // !DACCESS_COMPILE
GC_DAC_VISIBLE
uintptr_t HndGetHandleExtraInfo(OBJECTHANDLE handle);
/*
* get parent table of handle
*/
HHANDLETABLE HndGetHandleTable(OBJECTHANDLE handle);
/*
* write barrier
*/
void HndWriteBarrier(OBJECTHANDLE handle, OBJECTREF value);
/*
* logging an ETW event (for inlined methods)
*/
void HndLogSetEvent(OBJECTHANDLE handle, _UNCHECKED_OBJECTREF value);
/*
* NON-GC handle enumeration
*/
GC_DAC_VISIBLE_NO_MANGLE
void HndEnumHandles(HHANDLETABLE hTable, const uint32_t *puType, uint32_t uTypeCount,
HANDLESCANPROC pfnEnum, uintptr_t lParam1, uintptr_t lParam2, bool fAsync);
/*
* GC-time handle scanning
*/
#define HNDGCF_NORMAL (0x00000000) // normal scan
#define HNDGCF_AGE (0x00000001) // age handles while scanning
#define HNDGCF_ASYNC (0x00000002) // drop the table lock while scanning
#define HNDGCF_EXTRAINFO (0x00000004) // iterate per-handle data while scanning
GC_DAC_VISIBLE_NO_MANGLE
void HndScanHandlesForGC(HHANDLETABLE hTable,
HANDLESCANPROC scanProc,
uintptr_t param1,
uintptr_t param2,
const uint32_t *types,
uint32_t typeCount,
uint32_t condemned,
uint32_t maxgen,
uint32_t flags);
void HndResetAgeMap(HHANDLETABLE hTable, const uint32_t *types, uint32_t typeCount, uint32_t condemned, uint32_t maxgen, uint32_t flags);
void HndVerifyTable(HHANDLETABLE hTable, const uint32_t *types, uint32_t typeCount, uint32_t condemned, uint32_t maxgen, uint32_t flags);
void HndNotifyGcCycleComplete(HHANDLETABLE hTable, uint32_t condemned, uint32_t maxgen);
/*
* Handle counting
*/
uint32_t HndCountHandles(HHANDLETABLE hTable);
uint32_t HndCountAllHandles(BOOL fUseLocks);
/*--------------------------------------------------------------------------*/
#ifdef _DEBUG_IMPL
void ValidateAssignObjrefForHandle(OBJECTREF, ADIndex appDomainIndex);
void ValidateFetchObjrefForHandle(OBJECTREF, ADIndex appDomainIndex);
void ValidateAppDomainForHandle(OBJECTHANDLE handle);
#endif
/*
* handle assignment
*/
void HndAssignHandle(OBJECTHANDLE handle, OBJECTREF objref);
/*
* interlocked-exchange assignment
*/
void* HndInterlockedCompareExchangeHandle(OBJECTHANDLE handle, OBJECTREF objref, OBJECTREF oldObjref);
/*
* Note that HndFirstAssignHandle is similar to HndAssignHandle, except that it only
* succeeds if transitioning from NULL to non-NULL. In other words, if this handle
* is being initialized for the first time.
*/
BOOL HndFirstAssignHandle(OBJECTHANDLE handle, OBJECTREF objref);
/*
* inline handle dereferencing
*
* NOTE: Changes to this implementation should be kept in sync with ObjectFromHandle
* on the VM side.
*
*/
GC_DAC_VISIBLE
FORCEINLINE
OBJECTREF HndFetchHandle(OBJECTHANDLE handle)
{
WRAPPER_NO_CONTRACT;
// sanity
_ASSERTE(handle);
#ifdef _DEBUG_IMPL
_ASSERTE("Attempt to access destroyed handle." && *(_UNCHECKED_OBJECTREF *)handle != DEBUG_DestroyedHandleValue);
// Make sure the objref for handle is valid
ValidateFetchObjrefForHandle(ObjectToOBJECTREF(*(Object **)handle),
HndGetHandleTableADIndex(HndGetHandleTable(handle)));
#endif // _DEBUG_IMPL
// wrap the raw objectref and return it
return UNCHECKED_OBJECTREF_TO_OBJECTREF(*PTR_UNCHECKED_OBJECTREF(handle));
}
/*
* inline null testing (needed in certain cases where we're in the wrong GC mod)
*/
FORCEINLINE BOOL HndIsNull(OBJECTHANDLE handle)
{
LIMITED_METHOD_CONTRACT;
// sanity
_ASSERTE(handle);
return NULL == *(Object **)handle;
}
/*
*
* Checks handle value for null or special value used for free handles in cache.
*
*/
FORCEINLINE BOOL HndIsNullOrDestroyedHandle(_UNCHECKED_OBJECTREF value)
{
LIMITED_METHOD_CONTRACT;
#ifdef DEBUG_DestroyedHandleValue
if (value == DEBUG_DestroyedHandleValue)
return TRUE;
#endif
return (value == NULL);
}
/*--------------------------------------------------------------------------*/
#include "handletable.inl"
#endif //_HANDLETABLE_H
|