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 /*****************************************************************************\
6 * FixupPointer.h - Fixup pointer holder types *
8 \*****************************************************************************/
10 #ifndef _FIXUPPOINTER_H
11 #define _FIXUPPOINTER_H
17 //----------------------------------------------------------------------------
18 // RelativePointer is pointer encoded as relative offset. It is used to reduce size of
19 // relocation section in NGen images. Conversion from/to RelativePointer needs
20 // address of the pointer ("this") converted to TADDR passed in from outside.
21 // Converting "this" to TADDR is not possible in the DAC transparently because
22 // DAC is based on exact pointers, not ranges.
23 // There are several flavors of conversions from/to RelativePointer:
24 // - GetValue/SetValue: The most common version. Assumes that the pointer is not NULL.
25 // - GetValueMaybeNull/SetValueMaybeNull: Pointer can be NULL.
26 // - GetValueAtPtr: Static version of GetValue. It is
27 // meant to simplify access to arrays of RelativePointers.
28 // - GetValueMaybeNullAtPtr
29 template<typename PTR_TYPE>
34 static constexpr bool isRelative = true;
35 typedef PTR_TYPE type;
37 #ifndef DACCESS_COMPILE
40 m_delta = (TADDR)NULL;
44 #else // DACCESS_COMPILE
45 RelativePointer() =delete;
46 #endif // DACCESS_COMPILE
48 // Implicit copy/move is not allowed
49 // Bitwise copy is implemented by BitwiseCopyTo method
50 RelativePointer<PTR_TYPE>(const RelativePointer<PTR_TYPE> &) =delete;
51 RelativePointer<PTR_TYPE>(RelativePointer<PTR_TYPE> &&) =delete;
52 RelativePointer<PTR_TYPE>& operator = (const RelativePointer<PTR_TYPE> &) =delete;
53 RelativePointer<PTR_TYPE>& operator = (RelativePointer<PTR_TYPE> &&) =delete;
55 // Returns whether the encoded pointer is NULL.
58 LIMITED_METHOD_DAC_CONTRACT;
59 // Pointer pointing to itself is treated as NULL
60 return m_delta == (TADDR)NULL;
63 // Returns value of the encoded pointer. Assumes that the pointer is not NULL.
64 PTR_TYPE GetValue(TADDR base) const
66 LIMITED_METHOD_DAC_CONTRACT;
67 PRECONDITION(!IsNull());
68 return dac_cast<PTR_TYPE>(base + m_delta);
71 #ifndef DACCESS_COMPILE
72 // Returns value of the encoded pointer. Assumes that the pointer is not NULL.
73 // Does not need explicit base and thus can be used in non-DAC builds only.
74 FORCEINLINE PTR_TYPE GetValue() const
76 LIMITED_METHOD_CONTRACT;
77 return GetValue((TADDR)this);
81 // Static version of GetValue. It is meant to simplify access to arrays of pointers.
82 FORCEINLINE static PTR_TYPE GetValueAtPtr(TADDR base)
84 LIMITED_METHOD_DAC_CONTRACT;
85 return dac_cast<DPTR(RelativePointer<PTR_TYPE>)>(base)->GetValue(base);
88 // Returns value of the encoded pointer. The pointer can be NULL.
89 PTR_TYPE GetValueMaybeNull(TADDR base) const
91 LIMITED_METHOD_DAC_CONTRACT;
93 // Cache local copy of delta to avoid races when the value is changing under us.
94 TADDR delta = m_delta;
99 return dac_cast<PTR_TYPE>(base + delta);
102 #ifndef DACCESS_COMPILE
103 // Returns value of the encoded pointer. The pointer can be NULL.
104 // Does not need explicit base and thus can be used in non-DAC builds only.
105 FORCEINLINE PTR_TYPE GetValueMaybeNull() const
107 LIMITED_METHOD_CONTRACT;
108 return GetValueMaybeNull((TADDR)this);
112 // Static version of GetValueMaybeNull. It is meant to simplify access to arrays of pointers.
113 FORCEINLINE static PTR_TYPE GetValueMaybeNullAtPtr(TADDR base)
115 LIMITED_METHOD_DAC_CONTRACT;
116 return dac_cast<DPTR(RelativePointer<PTR_TYPE>)>(base)->GetValueMaybeNull(base);
119 #ifndef DACCESS_COMPILE
120 // Set encoded value of the pointer. Assumes that the value is not NULL.
121 FORCEINLINE void SetValue(PTR_TYPE addr)
123 LIMITED_METHOD_CONTRACT;
124 PRECONDITION(addr != NULL);
125 m_delta = (TADDR)addr - (TADDR)this;
128 // Set encoded value of the pointer. The value can be NULL.
129 void SetValueMaybeNull(TADDR base, PTR_TYPE addr)
131 LIMITED_METHOD_CONTRACT;
135 m_delta = (TADDR)addr - (TADDR)base;
138 // Set encoded value of the pointer. The value can be NULL.
139 FORCEINLINE void SetValueMaybeNull(PTR_TYPE addr)
141 LIMITED_METHOD_CONTRACT;
142 SetValueMaybeNull((TADDR)this, addr);
145 FORCEINLINE void SetValueVolatile(PTR_TYPE addr)
147 LIMITED_METHOD_CONTRACT;
152 #ifndef DACCESS_COMPILE
153 void BitwiseCopyTo(RelativePointer<PTR_TYPE> &dest) const
155 dest.m_delta = m_delta;
157 #endif // DACCESS_COMPILE
160 #ifndef DACCESS_COMPILE
161 Volatile<TADDR> m_delta;
167 //----------------------------------------------------------------------------
168 // FixupPointer is pointer with optional indirection. It is used to reduce number
169 // of private pages in NGen images - cross-module pointers that written to at runtime
170 // are packed together and accessed via indirection.
172 // The direct flavor (lowest bit of m_addr is cleared) is user for intra-module pointers
173 // in NGen images, and in datastructuters allocated at runtime.
175 // The indirect mode (lowest bit of m_addr is set) is used for cross-module pointers
179 // Friendly name for lowest bit that marks the indirection
180 #define FIXUP_POINTER_INDIRECTION 1
182 template<typename PTR_TYPE>
187 static constexpr bool isRelative = false;
188 typedef PTR_TYPE type;
190 // Returns whether the encoded pointer is NULL.
193 LIMITED_METHOD_DAC_CONTRACT;
197 // Returns whether the indirection cell contain fixup that has not been converted to real pointer yet.
198 FORCEINLINE BOOL IsTagged() const
200 LIMITED_METHOD_DAC_CONTRACT;
202 if ((addr & FIXUP_POINTER_INDIRECTION) != 0)
203 return (*PTR_TADDR(addr - FIXUP_POINTER_INDIRECTION) & 1) != 0;
207 // Returns value of the encoded pointer.
208 FORCEINLINE PTR_TYPE GetValue() const
210 LIMITED_METHOD_DAC_CONTRACT;
212 if ((addr & FIXUP_POINTER_INDIRECTION) != 0)
213 addr = *PTR_TADDR(addr - FIXUP_POINTER_INDIRECTION);
214 return dac_cast<PTR_TYPE>(addr);
217 // Returns value of the encoded pointer.
218 FORCEINLINE PTR_TYPE GetValueMaybeNull() const
220 LIMITED_METHOD_DAC_CONTRACT;
224 #ifndef DACCESS_COMPILE
225 // Returns the pointer to the indirection cell.
226 PTR_TYPE * GetValuePtr() const
228 LIMITED_METHOD_CONTRACT;
230 if ((addr & FIXUP_POINTER_INDIRECTION) != 0)
231 return (PTR_TYPE *)(addr - FIXUP_POINTER_INDIRECTION);
232 return (PTR_TYPE *)&m_addr;
234 #endif // !DACCESS_COMPILE
236 // Static version of GetValue. It is meant to simplify access to arrays of pointers.
237 FORCEINLINE static PTR_TYPE GetValueAtPtr(TADDR base)
239 LIMITED_METHOD_DAC_CONTRACT;
240 return dac_cast<DPTR(FixupPointer<PTR_TYPE>)>(base)->GetValue();
243 // Static version of GetValueMaybeNull. It is meant to simplify access to arrays of pointers.
244 FORCEINLINE static PTR_TYPE GetValueMaybeNullAtPtr(TADDR base)
246 LIMITED_METHOD_DAC_CONTRACT;
247 return dac_cast<DPTR(FixupPointer<PTR_TYPE>)>(base)->GetValueMaybeNull();
250 // Returns value of the encoded pointer.
251 // Allows the value to be tagged.
252 FORCEINLINE TADDR GetValueMaybeTagged() const
254 LIMITED_METHOD_DAC_CONTRACT;
256 if ((addr & FIXUP_POINTER_INDIRECTION) != 0)
257 addr = *PTR_TADDR(addr - FIXUP_POINTER_INDIRECTION);
261 #ifndef DACCESS_COMPILE
262 void SetValue(PTR_TYPE addr)
264 LIMITED_METHOD_CONTRACT;
265 m_addr = dac_cast<TADDR>(addr);
268 void SetValueMaybeNull(PTR_TYPE addr)
270 LIMITED_METHOD_CONTRACT;
273 #endif // !DACCESS_COMPILE
279 //----------------------------------------------------------------------------
280 // RelativeFixupPointer is combination of RelativePointer and FixupPointer
281 template<typename PTR_TYPE>
282 class RelativeFixupPointer
286 static constexpr bool isRelative = true;
287 typedef PTR_TYPE type;
289 #ifndef DACCESS_COMPILE
290 RelativeFixupPointer()
292 SetValueMaybeNull(NULL);
294 #else // DACCESS_COMPILE
295 RelativeFixupPointer() =delete;
296 #endif // DACCESS_COMPILE
298 // Implicit copy/move is not allowed
299 RelativeFixupPointer<PTR_TYPE>(const RelativeFixupPointer<PTR_TYPE> &) =delete;
300 RelativeFixupPointer<PTR_TYPE>(RelativeFixupPointer<PTR_TYPE> &&) =delete;
301 RelativeFixupPointer<PTR_TYPE>& operator = (const RelativeFixupPointer<PTR_TYPE> &) =delete;
302 RelativeFixupPointer<PTR_TYPE>& operator = (RelativeFixupPointer<PTR_TYPE> &&) =delete;
304 // Returns whether the encoded pointer is NULL.
307 LIMITED_METHOD_DAC_CONTRACT;
308 // Pointer pointing to itself is treated as NULL
309 return m_delta == (TADDR)NULL;
312 // Returns whether the indirection cell contain fixup that has not been converted to real pointer yet.
313 FORCEINLINE BOOL IsTagged(TADDR base) const
315 LIMITED_METHOD_DAC_CONTRACT;
316 TADDR addr = base + m_delta;
317 if ((addr & FIXUP_POINTER_INDIRECTION) != 0)
318 return (*PTR_TADDR(addr - FIXUP_POINTER_INDIRECTION) & 1) != 0;
322 // Returns whether the indirection cell contain fixup that has not been converted to real pointer yet.
323 // Ignores isIndirect and offset values.
324 FORCEINLINE BOOL IsTaggedIndirect(TADDR base, bool isIndirect, intptr_t offset) const
326 LIMITED_METHOD_DAC_CONTRACT;
327 return IsTagged(base);
330 #ifndef DACCESS_COMPILE
331 // Returns whether the indirection cell contain fixup that has not been converted to real pointer yet.
332 // Does not need explicit base and thus can be used in non-DAC builds only.
333 FORCEINLINE BOOL IsTagged() const
335 LIMITED_METHOD_CONTRACT;
336 return IsTagged((TADDR)this);
338 #endif // !DACCESS_COMPILE
340 // Returns value of the encoded pointer. Assumes that the pointer is not NULL.
341 FORCEINLINE PTR_TYPE GetValue(TADDR base) const
343 LIMITED_METHOD_DAC_CONTRACT;
344 PRECONDITION(!IsNull());
345 PRECONDITION(!IsTagged(base));
346 TADDR addr = base + m_delta;
347 if ((addr & FIXUP_POINTER_INDIRECTION) != 0)
348 addr = *PTR_TADDR(addr - FIXUP_POINTER_INDIRECTION);
349 return dac_cast<PTR_TYPE>(addr);
352 #ifndef DACCESS_COMPILE
353 // Returns value of the encoded pointer. Assumes that the pointer is not NULL.
354 // Does not need explicit base and thus can be used in non-DAC builds only.
355 FORCEINLINE PTR_TYPE GetValue() const
357 LIMITED_METHOD_CONTRACT;
358 return GetValue((TADDR)this);
362 // Static version of GetValue. It is meant to simplify access to arrays of pointers.
363 FORCEINLINE static PTR_TYPE GetValueAtPtr(TADDR base)
365 LIMITED_METHOD_DAC_CONTRACT;
366 return dac_cast<DPTR(RelativeFixupPointer<PTR_TYPE>)>(base)->GetValue(base);
369 // Static version of GetValue. It is meant to simplify access to arrays of pointers.
370 // Ignores isIndirect and offset values.
371 FORCEINLINE static PTR_TYPE GetValueAtPtrIndirect(TADDR base, bool isIndirect, intptr_t offset)
373 LIMITED_METHOD_DAC_CONTRACT;
374 return GetValueAtPtr(base);
377 // Returns value of the encoded pointer. The pointer can be NULL.
378 PTR_TYPE GetValueMaybeNull(TADDR base) const
380 LIMITED_METHOD_DAC_CONTRACT;
381 PRECONDITION(!IsTagged(base));
383 // Cache local copy of delta to avoid races when the value is changing under us.
384 TADDR delta = m_delta;
389 TADDR addr = base + delta;
390 if ((addr & FIXUP_POINTER_INDIRECTION) != 0)
391 addr = *PTR_TADDR(addr - FIXUP_POINTER_INDIRECTION);
392 return dac_cast<PTR_TYPE>(addr);
395 #ifndef DACCESS_COMPILE
396 // Returns value of the encoded pointer. The pointer can be NULL.
397 // Does not need explicit base and thus can be used in non-DAC builds only.
398 FORCEINLINE PTR_TYPE GetValueMaybeNull() const
400 LIMITED_METHOD_CONTRACT;
401 return GetValueMaybeNull((TADDR)this);
405 // Static version of GetValueMaybeNull. It is meant to simplify access to arrays of pointers.
406 FORCEINLINE static PTR_TYPE GetValueMaybeNullAtPtr(TADDR base)
408 LIMITED_METHOD_DAC_CONTRACT;
409 return dac_cast<DPTR(RelativeFixupPointer<PTR_TYPE>)>(base)->GetValueMaybeNull(base);
412 // Static version of GetValueMaybeNull. It is meant to simplify access to arrays of pointers.
413 // Ignores isIndirect and offset values.
414 FORCEINLINE static PTR_TYPE GetValueMaybeNullAtPtrIndirect(TADDR base, bool isIndirect, intptr_t offset)
416 LIMITED_METHOD_DAC_CONTRACT;
417 return GetValueMaybeNullAtPtr(base);
420 #ifndef DACCESS_COMPILE
421 // Set encoded value of the pointer. Assumes that the value is not NULL.
422 FORCEINLINE void SetValue(PTR_TYPE addr)
424 LIMITED_METHOD_CONTRACT;
425 PRECONDITION(addr != NULL);
426 m_delta = dac_cast<TADDR>(addr) - (TADDR)this;
429 // Set encoded value of the pointer. The value can be NULL.
430 void SetValueMaybeNull(TADDR base, PTR_TYPE addr)
432 LIMITED_METHOD_CONTRACT;
436 m_delta = dac_cast<TADDR>(addr) - (TADDR)base;
439 // Set encoded value of the pointer. The value can be NULL.
440 FORCEINLINE void SetValueMaybeNull(PTR_TYPE addr)
442 LIMITED_METHOD_CONTRACT;
443 SetValueMaybeNull((TADDR)this, addr);
447 #ifndef DACCESS_COMPILE
448 // Returns the pointer to the indirection cell.
449 PTR_TYPE * GetValuePtr() const
451 LIMITED_METHOD_CONTRACT;
452 TADDR addr = ((TADDR)this) + m_delta;
453 _ASSERTE((addr & FIXUP_POINTER_INDIRECTION) != 0);
454 return (PTR_TYPE *)(addr - FIXUP_POINTER_INDIRECTION);
457 // Returns the pointer to the indirection cell.
458 // Ignores isIndirect and offset values.
459 PTR_TYPE * GetValuePtrIndirect(bool isIndirect, intptr_t offset) const
461 LIMITED_METHOD_CONTRACT;
462 return GetValuePtr();
464 #endif // !DACCESS_COMPILE
466 // Returns value of the encoded pointer. Assumes that the pointer is not NULL.
467 // Allows the value to be tagged.
468 FORCEINLINE TADDR GetValueMaybeTagged(TADDR base) const
470 LIMITED_METHOD_DAC_CONTRACT;
471 PRECONDITION(!IsNull());
472 TADDR addr = base + m_delta;
473 if ((addr & FIXUP_POINTER_INDIRECTION) != 0)
474 addr = *PTR_TADDR(addr - FIXUP_POINTER_INDIRECTION);
478 // Returns whether pointer is indirect. Assumes that the value is not NULL.
479 bool IsIndirectPtr(TADDR base) const
481 LIMITED_METHOD_DAC_CONTRACT;
482 PRECONDITION(!IsNull());
484 TADDR addr = base + m_delta;
486 return (addr & FIXUP_POINTER_INDIRECTION) != 0;
489 #ifndef DACCESS_COMPILE
490 // Returns whether pointer is indirect. Assumes that the value is not NULL.
491 // Does not need explicit base and thus can be used in non-DAC builds only.
492 bool IsIndirectPtr() const
494 LIMITED_METHOD_CONTRACT;
495 return IsIndirectPtr((TADDR)this);
498 // Returns whether pointer is indirect. Assumes that the value is not NULL.
499 // Ignores isIndirect and offset values.
500 bool IsIndirectPtrIndirect(bool isIndirect, intptr_t offset) const
502 LIMITED_METHOD_DAC_CONTRACT;
503 return IsIndirectPtr();
507 // Returns whether pointer is indirect. The value can be NULL.
508 bool IsIndirectPtrMaybeNull(TADDR base) const
510 LIMITED_METHOD_DAC_CONTRACT;
515 return IsIndirectPtr(base);
518 #ifndef DACCESS_COMPILE
519 // Returns whether pointer is indirect. The value can be NULL.
520 // Does not need explicit base and thus can be used in non-DAC builds only.
521 bool IsIndirectPtrMaybeNull() const
523 LIMITED_METHOD_CONTRACT;
524 return IsIndirectPtrMaybeNull((TADDR)this);
527 // Returns whether pointer is indirect. The value can be NULL.
528 // Ignores isIndirect and offset values.
529 bool IsIndirectPtrMaybeNullIndirect(bool isIndirect, intptr_t offset) const
531 LIMITED_METHOD_DAC_CONTRACT;
532 return IsIndirectPtrMaybeNull();
537 #ifndef DACCESS_COMPILE
538 Volatile<TADDR> m_delta;
544 // Fixup used for RelativePointer
545 #define IMAGE_REL_BASED_RelativePointer IMAGE_REL_BASED_RELPTR
547 #endif // FEATURE_PREJIT
549 //----------------------------------------------------------------------------
550 // PlainPointer is simple pointer wrapper to support compilation without indirections
551 // This is useful for building size-constrained runtime without NGen support.
552 template<typename PTR_TYPE>
557 static constexpr bool isRelative = false;
558 typedef PTR_TYPE type;
560 // Returns whether the encoded pointer is NULL.
563 LIMITED_METHOD_DAC_CONTRACT;
564 return m_ptr == NULL;
567 // Returns whether the indirection cell contain fixup that has not been converted to real pointer yet.
568 BOOL IsTagged(TADDR base) const
570 LIMITED_METHOD_DAC_CONTRACT;
574 // Returns whether the indirection cell contain fixup that has not been converted to real pointer yet.
575 BOOL IsTagged() const
577 LIMITED_METHOD_DAC_CONTRACT;
579 if ((addr & FIXUP_POINTER_INDIRECTION) != 0)
580 return (*PTR_TADDR(addr - FIXUP_POINTER_INDIRECTION) & 1) != 0;
584 // Returns value of the encoded pointer.
585 PTR_TYPE GetValue() const
587 LIMITED_METHOD_DAC_CONTRACT;
588 return dac_cast<PTR_TYPE>(m_ptr);
591 #ifndef DACCESS_COMPILE
592 // Returns the pointer to the indirection cell.
593 PTR_TYPE * GetValuePtr() const
595 LIMITED_METHOD_CONTRACT;
597 if ((addr & FIXUP_POINTER_INDIRECTION) != 0)
598 return (PTR_TYPE *)(addr - FIXUP_POINTER_INDIRECTION);
599 return (PTR_TYPE *)&m_ptr;
601 #endif // !DACCESS_COMPILE
603 // Returns value of the encoded pointer. Assumes that the pointer is not NULL.
604 PTR_TYPE GetValue(TADDR base) const
606 LIMITED_METHOD_DAC_CONTRACT;
607 return dac_cast<PTR_TYPE>(m_ptr);
610 // Static version of GetValue. It is meant to simplify access to arrays of pointers.
611 FORCEINLINE static PTR_TYPE GetValueAtPtr(TADDR base)
613 LIMITED_METHOD_DAC_CONTRACT;
614 return dac_cast<DPTR(PlainPointer<PTR_TYPE>)>(base)->GetValue(base);
617 // Returns value of the encoded pointer. The pointer can be NULL.
618 PTR_TYPE GetValueMaybeNull() const
620 LIMITED_METHOD_DAC_CONTRACT;
621 return dac_cast<PTR_TYPE>(m_ptr);
624 // Returns value of the encoded pointer. The pointer can be NULL.
625 PTR_TYPE GetValueMaybeNull(TADDR base) const
627 LIMITED_METHOD_DAC_CONTRACT;
628 return dac_cast<PTR_TYPE>(m_ptr);
631 // Static version of GetValueMaybeNull. It is meant to simplify access to arrays of pointers.
632 FORCEINLINE static PTR_TYPE GetValueMaybeNullAtPtr(TADDR base)
634 LIMITED_METHOD_DAC_CONTRACT;
635 return dac_cast<DPTR(PlainPointer<PTR_TYPE>)>(base)->GetValueMaybeNull(base);
638 // Returns whether pointer is indirect. Assumes that the value is not NULL.
639 bool IsIndirectPtr(TADDR base) const
641 LIMITED_METHOD_DAC_CONTRACT;
643 return (m_ptr & FIXUP_POINTER_INDIRECTION) != 0;
646 #ifndef DACCESS_COMPILE
647 // Returns whether pointer is indirect. Assumes that the value is not NULL.
648 // Does not need explicit base and thus can be used in non-DAC builds only.
649 bool IsIndirectPtr() const
651 LIMITED_METHOD_CONTRACT;
652 return IsIndirectPtr((TADDR)this);
656 // Returns whether pointer is indirect. The value can be NULL.
657 bool IsIndirectPtrMaybeNull(TADDR base) const
659 LIMITED_METHOD_DAC_CONTRACT;
661 return IsIndirectPtr(base);
664 #ifndef DACCESS_COMPILE
665 // Returns whether pointer is indirect. The value can be NULL.
666 // Does not need explicit base and thus can be used in non-DAC builds only.
667 bool IsIndirectPtrMaybeNull() const
669 LIMITED_METHOD_CONTRACT;
670 return IsIndirectPtrMaybeNull((TADDR)this);
674 #ifndef DACCESS_COMPILE
675 void SetValue(PTR_TYPE addr)
677 LIMITED_METHOD_CONTRACT;
678 m_ptr = dac_cast<TADDR>(addr);
681 // Set encoded value of the pointer. Assumes that the value is not NULL.
682 void SetValue(TADDR base, PTR_TYPE addr)
684 LIMITED_METHOD_CONTRACT;
685 m_ptr = dac_cast<TADDR>(addr);
688 // Static version of SetValue. It is meant to simplify access to arrays of pointers.
689 FORCEINLINE static void SetValueAtPtr(TADDR base, PTR_TYPE addr)
691 LIMITED_METHOD_CONTRACT;
692 dac_cast<DPTR(PlainPointer<PTR_TYPE>)>(base)->SetValue(base, addr);
695 // Set encoded value of the pointer. The value can be NULL.
696 void SetValueMaybeNull(TADDR base, PTR_TYPE addr)
698 LIMITED_METHOD_CONTRACT;
699 m_ptr = dac_cast<TADDR>(addr);
702 // Set encoded value of the pointer. The value can be NULL.
703 // Does not need explicit base and thus can be used in non-DAC builds only.
704 FORCEINLINE void SetValueMaybeNull(PTR_TYPE addr)
706 LIMITED_METHOD_CONTRACT;
707 return SetValueMaybeNull((TADDR)this, addr);
710 // Static version of SetValueMaybeNull. It is meant to simplify access to arrays of pointers.
711 FORCEINLINE static void SetValueMaybeNullAtPtr(TADDR base, PTR_TYPE addr)
713 LIMITED_METHOD_CONTRACT;
714 dac_cast<DPTR(PlainPointer<PTR_TYPE>)>(base)->SetValueMaybeNull(base, addr);
717 FORCEINLINE void SetValueVolatile(PTR_TYPE addr)
719 LIMITED_METHOD_CONTRACT;
720 VolatileStore((PTR_TYPE *)(&m_ptr), addr);
728 #ifndef FEATURE_PREJIT
730 #define FixupPointer PlainPointer
731 #define RelativePointer PlainPointer
732 #define RelativeFixupPointer PlainPointer
734 #endif // !FEATURE_PREJIT
736 //----------------------------------------------------------------------------
737 // RelativePointer32 is pointer encoded as relative 32-bit offset. It is used
738 // to reduce both the size of the pointer itself as well as size of relocation
739 // section for pointers that live exlusively in NGen images.
740 template<typename PTR_TYPE>
741 class RelativePointer32
745 static constexpr bool isRelative = true;
746 typedef PTR_TYPE type;
748 // Returns whether the encoded pointer is NULL.
751 LIMITED_METHOD_DAC_CONTRACT;
752 // Pointer pointing to itself is treated as NULL
756 // Returns value of the encoded pointer. Assumes that the pointer is not NULL.
757 PTR_TYPE GetValue(TADDR base) const
759 LIMITED_METHOD_DAC_CONTRACT;
760 PRECONDITION(!IsNull());
761 return dac_cast<PTR_TYPE>(base + m_delta);
764 #ifndef DACCESS_COMPILE
765 // Returns value of the encoded pointer. Assumes that the pointer is not NULL.
766 // Does not need explicit base and thus can be used in non-DAC builds only.
767 FORCEINLINE PTR_TYPE GetValue() const
769 LIMITED_METHOD_CONTRACT;
770 return GetValue((TADDR)this);
774 // Static version of GetValue. It is meant to simplify access to arrays of pointers.
775 FORCEINLINE static PTR_TYPE GetValueAtPtr(TADDR base)
777 LIMITED_METHOD_DAC_CONTRACT;
778 return dac_cast<DPTR(RelativePointer<PTR_TYPE>)>(base)->GetValue(base);
781 // Returns value of the encoded pointer. The pointer can be NULL.
782 PTR_TYPE GetValueMaybeNull(TADDR base) const
784 LIMITED_METHOD_DAC_CONTRACT;
786 // Cache local copy of delta to avoid races when the value is changing under us.
787 TADDR delta = m_delta;
792 return dac_cast<PTR_TYPE>(base + delta);
795 #ifndef DACCESS_COMPILE
796 // Returns value of the encoded pointer. The pointer can be NULL.
797 // Does not need explicit base and thus can be used in non-DAC builds only.
798 FORCEINLINE PTR_TYPE GetValueMaybeNull() const
800 LIMITED_METHOD_CONTRACT;
801 return GetValueMaybeNull((TADDR)this);
805 // Static version of GetValueMaybeNull. It is meant to simplify access to arrays of pointers.
806 FORCEINLINE static PTR_TYPE GetValueMaybeNullAtPtr(TADDR base)
808 LIMITED_METHOD_DAC_CONTRACT;
809 return dac_cast<DPTR(RelativePointer<PTR_TYPE>)>(base)->GetValueMaybeNull(base);
816 //----------------------------------------------------------------------------
817 // IndirectPointer is pointer with optional indirection, similar to FixupPointer and RelativeFixupPointer.
819 // In comparison to FixupPointer, IndirectPointer's indirection is handled from outside by isIndirect flag.
820 // In comparison to RelativeFixupPointer, IndirectPointer's offset is a constant,
821 // while RelativeFixupPointer's offset is an address.
823 // IndirectPointer can contain NULL only if it is not indirect.
825 template<typename PTR_TYPE>
826 class IndirectPointer
830 static constexpr bool isRelative = false;
831 typedef PTR_TYPE type;
833 // Returns whether the encoded pointer is NULL.
836 LIMITED_METHOD_DAC_CONTRACT;
837 return m_addr == (TADDR)NULL;
840 // Returns whether the indirection cell contain fixup that has not been converted to real pointer yet.
841 // Uses isIndirect to identify, whether pointer is indirect or not. If it is, uses offset.
842 FORCEINLINE BOOL IsTaggedIndirect(TADDR base, bool isIndirect, intptr_t offset) const
844 LIMITED_METHOD_DAC_CONTRACT;
849 return (*PTR_TADDR(addr + offset) & 1) != 0;
854 // Returns value of the encoded pointer.
855 // Uses isIndirect to identify, whether pointer is indirect or not. If it is, uses offset.
856 FORCEINLINE PTR_TYPE GetValueIndirect(bool isIndirect, intptr_t offset) const
858 LIMITED_METHOD_DAC_CONTRACT;
863 addr = *PTR_TADDR(addr + offset);
865 return dac_cast<PTR_TYPE>(addr);
868 #ifndef DACCESS_COMPILE
869 // Returns the pointer to the indirection cell.
870 // Uses isIndirect to identify, whether pointer is indirect or not. If it is, uses offset.
871 PTR_TYPE * GetValuePtrIndirect(bool isIndirect, intptr_t offset) const
873 LIMITED_METHOD_CONTRACT;
878 return (PTR_TYPE *)(addr + offset);
880 return (PTR_TYPE *)&m_addr;
882 #endif // !DACCESS_COMPILE
884 // Static version of GetValue. It is meant to simplify access to arrays of pointers.
885 // Uses isIndirect to identify, whether pointer is indirect or not. If it is, uses offset.
886 FORCEINLINE static PTR_TYPE GetValueAtPtrIndirect(TADDR base, bool isIndirect, intptr_t offset)
888 LIMITED_METHOD_DAC_CONTRACT;
889 return dac_cast<DPTR(IndirectPointer<PTR_TYPE>)>(base)->GetValueIndirect(isIndirect, offset);
892 // Static version of GetValueMaybeNull. It is meant to simplify access to arrays of pointers.
893 // Uses isIndirect to identify, whether pointer is indirect or not. If it is, uses offset.
894 FORCEINLINE static PTR_TYPE GetValueMaybeNullAtPtrIndirect(TADDR base, bool isIndirect, intptr_t offset)
896 LIMITED_METHOD_DAC_CONTRACT;
897 return GetValueAtPtrIndirect(base, isIndirect, offset);
900 #ifndef DACCESS_COMPILE
901 // Returns whether pointer is indirect. Assumes that the value is not NULL.
902 // Uses isIndirect to identify, whether pointer is indirect or not. If it is, uses offset.
903 bool IsIndirectPtrIndirect(bool isIndirect, intptr_t offset) const
905 LIMITED_METHOD_CONTRACT;
911 // Returns whether pointer is indirect. The value can be NULL.
912 // Uses isIndirect to identify, whether pointer is indirect or not. If it is, uses offset.
913 bool IsIndirectPtrMaybeNullIndirect(bool isIndirect, intptr_t offset) const
915 LIMITED_METHOD_CONTRACT;
916 return IsIndirectPtrIndirect(isIndirect, offset);
918 #endif // !DACCESS_COMPILE
920 #ifndef DACCESS_COMPILE
921 // Set encoded value of the pointer. Assumes that the value is not NULL.
922 void SetValue(PTR_TYPE addr)
924 LIMITED_METHOD_CONTRACT;
925 m_addr = dac_cast<TADDR>(addr);
928 // Set encoded value of the pointer. The value can be NULL.
929 void SetValueMaybeNull(PTR_TYPE addr)
931 LIMITED_METHOD_CONTRACT;
934 #endif // !DACCESS_COMPILE
940 template<bool isMaybeNull, typename T, typename PT>
942 ReadPointer(const T *base, const PT T::* pPointerFieldMember)
944 LIMITED_METHOD_DAC_CONTRACT;
946 uintptr_t offset = (uintptr_t) &(base->*pPointerFieldMember) - (uintptr_t) base;
950 return PT::GetValueMaybeNullAtPtr(dac_cast<TADDR>(base) + offset);
954 return PT::GetValueAtPtr(dac_cast<TADDR>(base) + offset);
958 template<bool isMaybeNull, typename T, typename PT>
960 ReadPointer(const T *base, const PT T::* pPointerFieldMember, bool isIndirect)
962 LIMITED_METHOD_DAC_CONTRACT;
964 uintptr_t offset = (uintptr_t) &(base->*pPointerFieldMember) - (uintptr_t) base;
968 return PT::GetValueMaybeNullAtPtrIndirect(dac_cast<TADDR>(base) + offset, isIndirect, offset);
972 return PT::GetValueAtPtrIndirect(dac_cast<TADDR>(base) + offset, isIndirect, offset);
976 template<typename T, typename PT>
978 ReadPointerMaybeNull(const T *base, const PT T::* pPointerFieldMember)
980 LIMITED_METHOD_DAC_CONTRACT;
982 return ReadPointer<true>(base, pPointerFieldMember);
985 template<typename T, typename PT>
987 ReadPointerMaybeNull(const T *base, const PT T::* pPointerFieldMember, bool isIndirect)
989 LIMITED_METHOD_DAC_CONTRACT;
991 return ReadPointer<true>(base, pPointerFieldMember, isIndirect);
994 template<typename T, typename PT>
996 ReadPointer(const T *base, const PT T::* pPointerFieldMember)
998 LIMITED_METHOD_DAC_CONTRACT;
1000 return ReadPointer<false>(base, pPointerFieldMember);
1003 template<typename T, typename PT>
1005 ReadPointer(const T *base, const PT T::* pPointerFieldMember, bool isIndirect)
1007 LIMITED_METHOD_DAC_CONTRACT;
1009 return ReadPointer<false>(base, pPointerFieldMember, isIndirect);
1012 template<bool isMaybeNull, typename T, typename C, typename PT>
1014 ReadPointer(const T *base, const C T::* pFirstPointerFieldMember, const PT C::* pSecondPointerFieldMember)
1016 LIMITED_METHOD_DAC_CONTRACT;
1018 const PT *ptr = &(base->*pFirstPointerFieldMember.*pSecondPointerFieldMember);
1019 uintptr_t offset = (uintptr_t) ptr - (uintptr_t) base;
1023 return PT::GetValueMaybeNullAtPtr(dac_cast<TADDR>(base) + offset);
1027 return PT::GetValueAtPtr(dac_cast<TADDR>(base) + offset);
1031 template<typename T, typename C, typename PT>
1033 ReadPointerMaybeNull(const T *base, const C T::* pFirstPointerFieldMember, const PT C::* pSecondPointerFieldMember)
1035 LIMITED_METHOD_DAC_CONTRACT;
1037 return ReadPointer<true>(base, pFirstPointerFieldMember, pSecondPointerFieldMember);
1040 template<typename T, typename C, typename PT>
1042 ReadPointer(const T *base, const C T::* pFirstPointerFieldMember, const PT C::* pSecondPointerFieldMember)
1044 LIMITED_METHOD_DAC_CONTRACT;
1046 return ReadPointer<false>(base, pFirstPointerFieldMember, pSecondPointerFieldMember);
1049 #endif //_FIXUPPOINTER_H