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 | |
6 | // |
7 | // File: DacDbiInterface.inl |
8 | // |
9 | // Inline functions for DacDbiStructures.h |
10 | // |
11 | //***************************************************************************** |
12 | |
13 | #ifndef DACDBISTRUCTURES_INL_ |
14 | #define DACDBISTRUCTURES_INL_ |
15 | |
16 | //----------------------------------------------------------------------------------- |
17 | // DacDbiArrayList member function implementations |
18 | //----------------------------------------------------------------------------------- |
19 | |
20 | // constructor--sets list to empty state |
21 | // Arguments: none |
22 | // Notes: this allocates no memory, so the list will not be ready to use |
23 | template<class T> |
24 | inline |
25 | DacDbiArrayList<T>::DacDbiArrayList(): |
26 | m_pList(NULL), |
27 | m_nEntries(0) |
28 | { |
29 | } |
30 | |
31 | // conversion constructor--takes a list of type T and a count and converts to a |
32 | // DacDbiArrayList |
33 | // Arguments: |
34 | // input: list - a consecutive list (array) of elements of type T |
35 | // count - the number of elements in list |
36 | // Notes: - Allocates memory and copies the elements of list into "this" |
37 | // - It is assumed that the list does NOT already have memory allocated; if it does, |
38 | // calling Init will cause a leak. |
39 | // - the element copy relies on the assignment operator for T |
40 | // - may throw OOM |
41 | template<class T> |
42 | inline |
43 | DacDbiArrayList<T>::DacDbiArrayList(const T * pList, int count): |
44 | m_pList(NULL), |
45 | m_nEntries(0) |
46 | { |
47 | Init(pList, count); |
48 | } |
49 | |
50 | // destructor: deallocates memory and sets list back to empty state |
51 | // Arguments: none |
52 | template<class T> |
53 | inline |
54 | DacDbiArrayList<T>::~DacDbiArrayList() |
55 | { |
56 | Dealloc(); |
57 | } |
58 | |
59 | // explicitly deallocate the list and set it back to the empty state |
60 | // Arguments: none |
61 | // Notes: - Dealloc can be called multiple times without danger, since it |
62 | // checks first that memory has been allocated |
63 | template<class T> |
64 | inline |
65 | void DacDbiArrayList<T>::Dealloc() |
66 | { |
67 | CONTRACT_VOID |
68 | { |
69 | NOTHROW; |
70 | } |
71 | CONTRACT_END; |
72 | |
73 | if (m_pList != NULL) |
74 | { |
75 | delete [] m_pList; |
76 | m_pList = NULL; |
77 | } |
78 | m_nEntries = 0; |
79 | RETURN; |
80 | } |
81 | |
82 | // Alloc and Init are very similar. Both preallocate the array; but Alloc leaves the |
83 | // contents unintialized while Init provides initial values. The array contents are always |
84 | // mutable. |
85 | |
86 | // allocate space for the list--in some instances, we'll know the count first, and then |
87 | // we'll compute the elements one at a time. This (along with the array access operator |
88 | // overload) allows us to handle that situation |
89 | // Arguments: |
90 | // input: nElements - number of elements of type T for which we need space |
91 | // Notes: |
92 | // - Alloc can be called multiple times and will free previous arrays. |
93 | // - May throw OOM |
94 | // - The array is not expandable, so you must allocate for all the elements at once. |
95 | // - requesting an allocation of 0 or fewer bytes will not cause an error, but no memory is |
96 | // allocated |
97 | template<class T> |
98 | inline |
99 | void DacDbiArrayList<T>::Alloc(int nElements) |
100 | { |
101 | Dealloc(); |
102 | if (nElements > 0) |
103 | { |
104 | m_pList = new(forDbi) T[(size_t)nElements]; |
105 | m_nEntries = nElements; |
106 | } |
107 | } |
108 | |
109 | // allocate and initialize a DacDbiArrayList from a list of type T and a count |
110 | // Arguments: |
111 | // input: list - consecutive list (array) of elements of type T to be copied into |
112 | // "this" |
113 | // count - number of elements in list |
114 | // Notes: |
115 | // - May throw OOM |
116 | // - Can be called multiple times with different lists, since this will deallocate |
117 | // previous arrays. |
118 | template<class T> |
119 | inline |
120 | void DacDbiArrayList<T>::Init(const T * pList, int count) |
121 | { |
122 | _ASSERTE((m_pList == NULL) && (m_nEntries == 0)); |
123 | if (count > 0) |
124 | { |
125 | Alloc(count); |
126 | m_nEntries = count; |
127 | for (int index = 0; index < count; ++index) |
128 | { |
129 | m_pList[index] = pList[index]; |
130 | } |
131 | } |
132 | } |
133 | |
134 | // read-only list element access |
135 | template<class T> |
136 | inline |
137 | const T & DacDbiArrayList<T>::operator [](int i) const |
138 | { |
139 | _ASSERTE(m_pList != NULL); |
140 | _ASSERTE((i >= 0) && (i < m_nEntries)); |
141 | return m_pList[i]; |
142 | } |
143 | |
144 | // writeable list element access |
145 | template<class T> |
146 | inline |
147 | T & DacDbiArrayList<T>::operator [](int i) |
148 | { |
149 | _ASSERTE(m_pList != NULL); |
150 | _ASSERTE((i >= 0) && (i < m_nEntries)); |
151 | return m_pList[i]; |
152 | } |
153 | |
154 | // get the number of elements in the list |
155 | template<class T> |
156 | inline |
157 | int DacDbiArrayList<T>::Count() const |
158 | { |
159 | return m_nEntries; |
160 | } |
161 | |
162 | //----------------------------------------------------------------------------- |
163 | // Target Buffer functions |
164 | //----------------------------------------------------------------------------- |
165 | |
166 | // Default ctor |
167 | inline |
168 | TargetBuffer::TargetBuffer() |
169 | { |
170 | this->pAddress = NULL; |
171 | this->cbSize = 0; |
172 | } |
173 | |
174 | // Convenience Ctor to initialize around an (Address, size). |
175 | inline |
176 | TargetBuffer::TargetBuffer(CORDB_ADDRESS pBuffer, ULONG cbSizeInput) |
177 | { |
178 | this->pAddress = pBuffer; |
179 | this->cbSize = cbSizeInput; |
180 | } |
181 | |
182 | // Convenience Ctor to initialize around an (Address, size). |
183 | inline |
184 | TargetBuffer::TargetBuffer(void * pBuffer, ULONG cbSizeInput) |
185 | { |
186 | this->pAddress = PTR_TO_CORDB_ADDRESS(pBuffer); |
187 | this->cbSize = cbSizeInput; |
188 | } |
189 | |
190 | // Return a sub-buffer that's starts at byteOffset within this buffer and runs to the end. |
191 | // |
192 | // Arguments: |
193 | // byteOffset - offset in bytes within this buffer that the new buffer starts at. |
194 | // |
195 | // Returns: |
196 | // A new buffer that's a subset of the existing buffer. |
197 | inline |
198 | TargetBuffer TargetBuffer::SubBuffer(ULONG byteOffset) const |
199 | { |
200 | _ASSERTE(byteOffset <= cbSize); |
201 | return TargetBuffer(pAddress + byteOffset, cbSize - byteOffset); |
202 | } |
203 | |
204 | // Return a sub-buffer that starts at byteOffset within this buffer and is byteLength long. |
205 | // |
206 | // Arguments: |
207 | // byteOffset - offset in bytes within this buffer that the new buffer starts at. |
208 | // byteLength - length in bytes of the new buffer. |
209 | // |
210 | // Returns: |
211 | // A new buffer that's a subset of the existing buffer. |
212 | inline |
213 | TargetBuffer TargetBuffer::SubBuffer(ULONG byteOffset, ULONG byteLength) const |
214 | { |
215 | _ASSERTE(byteOffset + byteLength <= cbSize); |
216 | return TargetBuffer(pAddress + byteOffset, byteLength); |
217 | } |
218 | |
219 | // Sets address to NULL and size to 0 |
220 | inline |
221 | void TargetBuffer::Clear() |
222 | { |
223 | pAddress = NULL; |
224 | cbSize = 0; |
225 | } |
226 | |
227 | // Initialize fields |
228 | inline |
229 | void TargetBuffer::Init(CORDB_ADDRESS address, ULONG size) |
230 | { |
231 | pAddress = address; |
232 | cbSize = size; |
233 | } |
234 | |
235 | |
236 | // Returns true iff the buffer is empty. |
237 | inline |
238 | bool TargetBuffer::IsEmpty() const |
239 | { |
240 | return (this->cbSize == 0); |
241 | } |
242 | |
243 | //----------------------------------------------------------------------------- |
244 | // NativeVarData member function implementations |
245 | //----------------------------------------------------------------------------- |
246 | |
247 | // Initialize a new instance of NativeVarData |
248 | inline NativeVarData::NativeVarData() : |
249 | m_allArgsCount(0), |
250 | m_fInitialized(false) |
251 | { |
252 | } |
253 | |
254 | // destructor |
255 | inline NativeVarData::~NativeVarData() |
256 | { |
257 | m_fInitialized = false; |
258 | } |
259 | |
260 | // initialize the list of native var information structures, including the starting address of the list, the number of |
261 | // entries and the number of fixed args. |
262 | inline void NativeVarData::InitVarDataList(ICorDebugInfo::NativeVarInfo * pListStart, |
263 | int fixedArgCount, |
264 | int entryCount) |
265 | { |
266 | m_offsetInfo.Init(pListStart, entryCount); |
267 | m_fixedArgsCount = fixedArgCount; |
268 | m_fInitialized = true; |
269 | } |
270 | |
271 | //----------------------------------------------------------------------------- |
272 | // SequencePoints member function implementations |
273 | //----------------------------------------------------------------------------- |
274 | |
275 | // initializing constructor |
276 | inline SequencePoints::SequencePoints() : |
277 | m_mapCount(0), |
278 | m_lastILOffset(0), |
279 | m_fInitialized(false) |
280 | { |
281 | } |
282 | |
283 | // destructor |
284 | inline SequencePoints::~SequencePoints() |
285 | { |
286 | m_fInitialized = false; |
287 | } |
288 | |
289 | // Initialize the m_pMap data member to the address of an allocated chunk |
290 | // of memory (or to NULL if the count is zero). Set m_count as the |
291 | // number of entries in the map. |
292 | inline void SequencePoints::InitSequencePoints(ULONG32 count) |
293 | { |
294 | m_map.Alloc(count), |
295 | m_fInitialized = true; |
296 | } |
297 | |
298 | // |
299 | // Map the given native offset to IL offset and return the mapping type. |
300 | // |
301 | // Arguments: |
302 | // dwNativeOffset - the native offset to be mapped |
303 | // pMapType - out parameter; return the mapping type |
304 | // |
305 | // Return Value: |
306 | // Return the IL offset corresponding to the given native offset. |
307 | // For a prolog, return 0. |
308 | // For an epilog, return the IL offset of the last sequence point before the epilog. |
309 | // If we can't map to an IL offset, then return 0, with a mapping type of MAPPING_NO_INFO. |
310 | // |
311 | // Assumptions: |
312 | // The sequence points are sorted. |
313 | // |
314 | |
315 | inline |
316 | DWORD SequencePoints::MapNativeOffsetToIL(DWORD dwNativeOffset, |
317 | CorDebugMappingResult *pMapType) |
318 | { |
319 | //_ASSERTE(IsInitialized()); |
320 | if (!IsInitialized()) |
321 | { |
322 | (*pMapType) = MAPPING_NO_INFO; |
323 | return 0; |
324 | } |
325 | |
326 | _ASSERTE(pMapType != NULL); |
327 | |
328 | int i; |
329 | |
330 | for (i = 0; i < (int)m_mapCount; ++i) |
331 | { |
332 | // Check to determine if dwNativeOffset is within this sequence point. Checking the lower bound is trivial-- |
333 | // we just make sure that dwNativeOffset >= m_map[i].nativeStartOffset. |
334 | // Checking to be sure it's before the end of the range is a little trickier. We can have |
335 | // m_map[i].nativeEndOffset = 0 for two reasons: |
336 | // 1. We use an end offset of 0 to signify that this end offset is also the end of the method. |
337 | // 2. We could also have an end offset of 0 if the IL prologue doesn't translate to any native |
338 | // instructions. Thus, the first native instruction (which will not be in the prologue) is at an offset |
339 | // of 0. The end offset is always set to the start offset of the next sequence point, so this means |
340 | // that both the start and end offsets of the (non-existent) native instruction range for the |
341 | // prologue is also 0. |
342 | // If the end offset is 0, we want to check if we're in the prologue before concluding that the |
343 | // value of dwNativeOffset is out of range. |
344 | if ((dwNativeOffset >= m_map[i].nativeStartOffset) && |
345 | (((m_map[i].nativeEndOffset == 0) && (m_map[i].ilOffset != (ULONG)ICorDebugInfo::PROLOG)) || |
346 | (dwNativeOffset < m_map[i].nativeEndOffset))) |
347 | { |
348 | ULONG uILOffset = m_map[i].ilOffset; |
349 | |
350 | if (m_map[i].ilOffset == (ULONG)ICorDebugInfo::PROLOG) |
351 | { |
352 | uILOffset = 0; |
353 | (*pMapType) = MAPPING_PROLOG; |
354 | } |
355 | else if (m_map[i].ilOffset == (ULONG)ICorDebugInfo::NO_MAPPING) |
356 | { |
357 | uILOffset = 0; |
358 | (*pMapType) = MAPPING_UNMAPPED_ADDRESS; |
359 | } |
360 | else if (m_map[i].ilOffset == (ULONG)ICorDebugInfo::EPILOG) |
361 | { |
362 | uILOffset = m_lastILOffset; |
363 | (*pMapType) = MAPPING_EPILOG; |
364 | } |
365 | else if (dwNativeOffset == m_map[i].nativeStartOffset) |
366 | { |
367 | (*pMapType) = MAPPING_EXACT; |
368 | } |
369 | else |
370 | { |
371 | (*pMapType) = MAPPING_APPROXIMATE; |
372 | } |
373 | return uILOffset; |
374 | } |
375 | } |
376 | |
377 | (*pMapType) = MAPPING_NO_INFO; |
378 | return 0; |
379 | } |
380 | |
381 | // |
382 | // Copy data from the VM map data to our own map structure and sort. The |
383 | // information comes to us in a data structure that differs slightly from the |
384 | // one we use out of process, so we have to copy it to the right-side struct. |
385 | // Arguments |
386 | // input |
387 | // mapCopy sequence points |
388 | // output |
389 | // pSeqPoints.m_map is initialized with the correct right side representation of sequence points |
390 | |
391 | inline |
392 | void SequencePoints::CopyAndSortSequencePoints(const ICorDebugInfo::OffsetMapping mapCopy[]) |
393 | { |
394 | // copy information to pSeqPoint and set end offsets |
395 | int i; |
396 | |
397 | ULONG32 lastILOffset = 0; |
398 | |
399 | const DWORD call_inst = (DWORD)ICorDebugInfo::CALL_INSTRUCTION; |
400 | for (i = 0; i < m_map.Count(); i++) |
401 | { |
402 | m_map[i].ilOffset = mapCopy[i].ilOffset; |
403 | m_map[i].nativeStartOffset = mapCopy[i].nativeOffset; |
404 | |
405 | if (i < m_map.Count() - 1) |
406 | { |
407 | // We need to not use CALL_INSTRUCTION's IL start offset. |
408 | int j = i + 1; |
409 | while ((mapCopy[j].source & call_inst) == call_inst && j < m_map.Count()-1) |
410 | j++; |
411 | |
412 | m_map[i].nativeEndOffset = mapCopy[j].nativeOffset; |
413 | } |
414 | |
415 | m_map[i].source = mapCopy[i].source; |
416 | |
417 | // need to cast the offsets to signed values first because we do actually use |
418 | // special negative offsets such as ICorDebugInfo::PROLOG |
419 | if ((m_map[i].source & call_inst) != call_inst) |
420 | lastILOffset = max((int)lastILOffset, (int)m_map[i].ilOffset); |
421 | } |
422 | |
423 | if (m_map.Count() >= 1) |
424 | { |
425 | m_map[i - 1].nativeEndOffset = 0; |
426 | m_map[i - 1].source = |
427 | (ICorDebugInfo::SourceTypes)(m_map[i - 1].source | ICorDebugInfo::NATIVE_END_OFFSET_UNKNOWN); |
428 | } |
429 | |
430 | // sort the map |
431 | MapSortILMap mapSorter(&m_map[0], m_map.Count()); |
432 | mapSorter.Sort(); |
433 | |
434 | |
435 | m_mapCount = m_map.Count(); |
436 | while (m_mapCount > 0 && (m_map[m_mapCount-1].source & (call_inst)) == call_inst) |
437 | m_mapCount--; |
438 | |
439 | SetLastILOffset(lastILOffset); |
440 | } // CopyAndSortSequencePoints |
441 | |
442 | //----------------------------------------------------------------------------- |
443 | // member function implementations for MapSortILMap class to sort sequence points |
444 | // by IL offset |
445 | //----------------------------------------------------------------------------- |
446 | |
447 | // secondary key comparison--if two IL offsets are the same, |
448 | // we determine order based on native offset |
449 | |
450 | inline |
451 | int SequencePoints::MapSortILMap::CompareInternal(DebuggerILToNativeMap *first, |
452 | DebuggerILToNativeMap *second) |
453 | { |
454 | LIMITED_METHOD_CONTRACT; |
455 | |
456 | if (first->nativeStartOffset == second->nativeStartOffset) |
457 | return 0; |
458 | else if (first->nativeStartOffset < second->nativeStartOffset) |
459 | return -1; |
460 | else |
461 | return 1; |
462 | } |
463 | |
464 | //Comparison operator |
465 | inline |
466 | int SequencePoints::MapSortILMap::Compare(DebuggerILToNativeMap * first, |
467 | DebuggerILToNativeMap * second) |
468 | { |
469 | LIMITED_METHOD_CONTRACT; |
470 | const DWORD call_inst = (DWORD)ICorDebugInfo::CALL_INSTRUCTION; |
471 | |
472 | //PROLOGs go first |
473 | if (first->ilOffset == (ULONG) ICorDebugInfo::PROLOG && |
474 | second->ilOffset == (ULONG) ICorDebugInfo::PROLOG) |
475 | { |
476 | return CompareInternal(first, second); |
477 | } |
478 | else if (first->ilOffset == (ULONG) ICorDebugInfo::PROLOG) |
479 | { |
480 | return -1; |
481 | } |
482 | else if (second->ilOffset == (ULONG) ICorDebugInfo::PROLOG) |
483 | { |
484 | return 1; |
485 | } |
486 | // call_instruction goes at the very very end of the table. |
487 | else if ((first->source & call_inst) == call_inst |
488 | && (second->source & call_inst) == call_inst) |
489 | { |
490 | return CompareInternal(first, second); |
491 | } else if ((first->source & call_inst) == call_inst) |
492 | { |
493 | return 1; |
494 | } else if ((second->source & call_inst) == call_inst) |
495 | { |
496 | return -1; |
497 | } |
498 | //NO_MAPPING go last |
499 | else if (first->ilOffset == (ULONG) ICorDebugInfo::NO_MAPPING && |
500 | second->ilOffset == (ULONG) ICorDebugInfo::NO_MAPPING) |
501 | { |
502 | return CompareInternal(first, second); |
503 | } |
504 | else if (first->ilOffset == (ULONG) ICorDebugInfo::NO_MAPPING) |
505 | { |
506 | return 1; |
507 | } |
508 | else if (second->ilOffset == (ULONG) ICorDebugInfo::NO_MAPPING) |
509 | { |
510 | return -1; |
511 | } |
512 | //EPILOGs go next-to-last |
513 | else if (first->ilOffset == (ULONG) ICorDebugInfo::EPILOG && |
514 | second->ilOffset == (ULONG) ICorDebugInfo::EPILOG) |
515 | { |
516 | return CompareInternal(first, second); |
517 | } |
518 | else if (first->ilOffset == (ULONG) ICorDebugInfo::EPILOG) |
519 | { |
520 | return 1; |
521 | } |
522 | else if (second->ilOffset == (ULONG) ICorDebugInfo::EPILOG) |
523 | { |
524 | return -1; |
525 | } |
526 | //normal offsets compared otherwise |
527 | else if (first->ilOffset < second->ilOffset) |
528 | { |
529 | return -1; |
530 | } |
531 | else if (first->ilOffset == second->ilOffset) |
532 | { |
533 | return CompareInternal(first, second); |
534 | } |
535 | else |
536 | { |
537 | return 1; |
538 | } |
539 | } |
540 | |
541 | //----------------------------------------------------------------------------- |
542 | // NativeCodeFunctionData member function implementations |
543 | // (for getting native code regions) |
544 | //----------------------------------------------------------------------------- |
545 | |
546 | inline |
547 | CodeBlobRegion & operator++(CodeBlobRegion & rs) |
548 | { |
549 | return rs = CodeBlobRegion(rs + 1); |
550 | } |
551 | |
552 | // Convert the data in an instance of DebuggerIPCE_JITFUncData to an instance of NativeCodeFunctionData. |
553 | // We need to have this latter type to look up or create a new CordbNativeCode object, but the stack walker is |
554 | // using the former type to gather information. |
555 | // Arguments: |
556 | // Input: |
557 | // source - an initialized instance of DebuggerIPCE_JITFuncData containing the information to |
558 | // be copied into this instance of NativeCodeFunctionData |
559 | // @dbgtodo dlaw: Once CordbThread::RefreshStack is fully DAC-ized, we can change the data structure that it uses |
560 | // to have a member of type NativeCodeFunctionData which we can pass without copying. At that point, |
561 | // this method can disappear. |
562 | inline |
563 | NativeCodeFunctionData::NativeCodeFunctionData(DebuggerIPCE_JITFuncData * source) |
564 | { |
565 | // copy the code region information |
566 | m_rgCodeRegions[kHot].Init(CORDB_ADDRESS(source->nativeStartAddressPtr), (ULONG)source->nativeHotSize); |
567 | m_rgCodeRegions[kCold].Init(CORDB_ADDRESS(source->nativeStartAddressColdPtr), (ULONG)source->nativeColdSize); |
568 | |
569 | // copy the other function information |
570 | isInstantiatedGeneric = source->isInstantiatedGeneric; |
571 | vmNativeCodeMethodDescToken = source->vmNativeCodeMethodDescToken; |
572 | encVersion = source->enCVersion; |
573 | } |
574 | |
575 | |
576 | // set all fields to default values (NULL, FALSE, or zero as appropriate) |
577 | inline |
578 | NativeCodeFunctionData::NativeCodeFunctionData() |
579 | { |
580 | Clear(); |
581 | } |
582 | |
583 | inline |
584 | void NativeCodeFunctionData::Clear() |
585 | { |
586 | isInstantiatedGeneric = FALSE; |
587 | encVersion = CorDB_DEFAULT_ENC_FUNCTION_VERSION; |
588 | for (CodeBlobRegion region = kHot; region < MAX_REGIONS; ++region) |
589 | { |
590 | m_rgCodeRegions[region].Clear(); |
591 | } |
592 | } |
593 | |
594 | //----------------------------------------------------------------------------------- |
595 | // ClassInfo member functions |
596 | //----------------------------------------------------------------------------------- |
597 | |
598 | inline |
599 | ClassInfo::ClassInfo(): |
600 | m_objectSize(0) |
601 | {} |
602 | |
603 | // clear all fields |
604 | inline |
605 | void ClassInfo::Clear() |
606 | { |
607 | m_objectSize = 0; |
608 | m_fieldList.Dealloc(); |
609 | } |
610 | |
611 | inline |
612 | ClassInfo::~ClassInfo() |
613 | { |
614 | m_fieldList.Dealloc(); |
615 | } |
616 | |
617 | //----------------------------------------------------------------------------------- |
618 | // FieldData member functions |
619 | //----------------------------------------------------------------------------------- |
620 | #ifndef RIGHT_SIDE_COMPILE |
621 | |
622 | // initialize various fields of an instance of FieldData from information retrieved from a FieldDesc |
623 | inline |
624 | void FieldData::Initialize(BOOL fIsStatic, BOOL fIsPrimitive, mdFieldDef mdToken) |
625 | { |
626 | ClearFields(); |
627 | m_fFldIsStatic = (fIsStatic == TRUE); |
628 | m_fFldIsPrimitive = (fIsPrimitive == TRUE); |
629 | // This is what tells the right side the field is unavailable due to EnC. |
630 | m_fldMetadataToken = mdToken; |
631 | } |
632 | #endif |
633 | |
634 | // clear various fields for a new instance of FieldData |
635 | inline |
636 | void FieldData::ClearFields() |
637 | { |
638 | m_fldSignatureCache = NULL; |
639 | m_fldSignatureCacheSize = 0; |
640 | m_fldInstanceOffset = 0; |
641 | m_pFldStaticAddress = NULL; |
642 | } |
643 | |
644 | typedef ULONG_PTR SIZE_T; |
645 | |
646 | inline |
647 | BOOL FieldData::OkToGetOrSetInstanceOffset() |
648 | { |
649 | return (!m_fFldIsStatic && !m_fFldIsRVA && !m_fFldIsTLS && |
650 | m_fFldStorageAvailable && (m_pFldStaticAddress == NULL)); |
651 | } |
652 | |
653 | // If this is an instance field, store its offset |
654 | inline |
655 | void FieldData::SetInstanceOffset(SIZE_T offset) |
656 | { |
657 | _ASSERTE(!m_fFldIsStatic); |
658 | _ASSERTE(!m_fFldIsRVA); |
659 | _ASSERTE(!m_fFldIsTLS); |
660 | _ASSERTE(m_fFldStorageAvailable); |
661 | _ASSERTE(m_pFldStaticAddress == NULL); |
662 | m_fldInstanceOffset = offset; |
663 | } |
664 | |
665 | inline |
666 | BOOL FieldData::OkToGetOrSetStaticAddress() |
667 | { |
668 | return (m_fFldIsStatic && !m_fFldIsTLS && |
669 | m_fFldStorageAvailable && (m_fldInstanceOffset == 0)); |
670 | } |
671 | |
672 | // If this is a "normal" static, store its absolute address |
673 | inline |
674 | void FieldData::SetStaticAddress(TADDR addr) |
675 | { |
676 | _ASSERTE(m_fFldIsStatic); |
677 | _ASSERTE(!m_fFldIsTLS); |
678 | _ASSERTE(m_fFldStorageAvailable); |
679 | _ASSERTE(m_fldInstanceOffset == 0); |
680 | m_pFldStaticAddress = TADDR(addr); |
681 | } |
682 | |
683 | // Get the offset of a field |
684 | inline |
685 | SIZE_T FieldData::GetInstanceOffset() |
686 | { |
687 | _ASSERTE(!m_fFldIsStatic); |
688 | _ASSERTE(!m_fFldIsRVA); |
689 | _ASSERTE(!m_fFldIsTLS); |
690 | _ASSERTE(m_fFldStorageAvailable); |
691 | _ASSERTE(m_pFldStaticAddress == NULL); |
692 | return m_fldInstanceOffset; |
693 | } |
694 | |
695 | // Get the static address for a field |
696 | inline |
697 | TADDR FieldData::GetStaticAddress() |
698 | { |
699 | _ASSERTE(m_fFldIsStatic); |
700 | _ASSERTE(!m_fFldIsTLS); |
701 | _ASSERTE(m_fFldStorageAvailable || (m_pFldStaticAddress == NULL)); |
702 | _ASSERTE(m_fldInstanceOffset == 0); |
703 | return m_pFldStaticAddress; |
704 | } |
705 | |
706 | //----------------------------------------------------------------------------------- |
707 | // EnCHangingFieldInfo member functions |
708 | //----------------------------------------------------------------------------------- |
709 | |
710 | inline |
711 | void EnCHangingFieldInfo::Init(VMPTR_Object pObject, |
712 | SIZE_T offset, |
713 | mdFieldDef fieldToken, |
714 | CorElementType elementType, |
715 | mdTypeDef metadataToken, |
716 | VMPTR_DomainFile vmDomainFile) |
717 | { |
718 | m_vmObject = pObject; |
719 | m_offsetToVars = offset; |
720 | m_fldToken = fieldToken; |
721 | m_objectTypeData.elementType = elementType; |
722 | m_objectTypeData.metadataToken = metadataToken; |
723 | m_objectTypeData.vmDomainFile = vmDomainFile; |
724 | } |
725 | |
726 | |
727 | |
728 | #endif // DACDBISTRUCTURES_INL_ |
729 | |