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
159 static TADDR GetRelativeMaybeNull(TADDR base, TADDR addr)
161 LIMITED_METHOD_DAC_CONTRACT;
172 static TADDR GetRelative(TADDR base, TADDR addr)
174 LIMITED_METHOD_DAC_CONTRACT;
175 PRECONDITION(addr != NULL);
180 #ifndef DACCESS_COMPILE
181 Volatile<TADDR> m_delta;
187 //----------------------------------------------------------------------------
188 // FixupPointer is pointer with optional indirection. It is used to reduce number
189 // of private pages in NGen images - cross-module pointers that written to at runtime
190 // are packed together and accessed via indirection.
192 // The direct flavor (lowest bit of m_addr is cleared) is user for intra-module pointers
193 // in NGen images, and in datastructuters allocated at runtime.
195 // The indirect mode (lowest bit of m_addr is set) is used for cross-module pointers
199 // Friendly name for lowest bit that marks the indirection
200 #define FIXUP_POINTER_INDIRECTION 1
202 template<typename PTR_TYPE>
207 static constexpr bool isRelative = false;
208 typedef PTR_TYPE type;
210 // Returns whether the encoded pointer is NULL.
213 LIMITED_METHOD_DAC_CONTRACT;
217 // Returns whether the indirection cell contain fixup that has not been converted to real pointer yet.
218 FORCEINLINE BOOL IsTagged() const
220 LIMITED_METHOD_DAC_CONTRACT;
222 if ((addr & FIXUP_POINTER_INDIRECTION) != 0)
223 return (*PTR_TADDR(addr - FIXUP_POINTER_INDIRECTION) & 1) != 0;
227 // Returns value of the encoded pointer.
228 FORCEINLINE PTR_TYPE GetValue() const
230 LIMITED_METHOD_DAC_CONTRACT;
232 if ((addr & FIXUP_POINTER_INDIRECTION) != 0)
233 addr = *PTR_TADDR(addr - FIXUP_POINTER_INDIRECTION);
234 return dac_cast<PTR_TYPE>(addr);
237 // Returns value of the encoded pointer.
238 FORCEINLINE PTR_TYPE GetValueMaybeNull() const
240 LIMITED_METHOD_DAC_CONTRACT;
244 #ifndef DACCESS_COMPILE
245 // Returns the pointer to the indirection cell.
246 PTR_TYPE * GetValuePtr() const
248 LIMITED_METHOD_CONTRACT;
250 if ((addr & FIXUP_POINTER_INDIRECTION) != 0)
251 return (PTR_TYPE *)(addr - FIXUP_POINTER_INDIRECTION);
252 return (PTR_TYPE *)&m_addr;
254 #endif // !DACCESS_COMPILE
256 // Static version of GetValue. It is meant to simplify access to arrays of pointers.
257 FORCEINLINE static PTR_TYPE GetValueAtPtr(TADDR base)
259 LIMITED_METHOD_DAC_CONTRACT;
260 return dac_cast<DPTR(FixupPointer<PTR_TYPE>)>(base)->GetValue();
263 // Static version of GetValueMaybeNull. It is meant to simplify access to arrays of pointers.
264 FORCEINLINE static PTR_TYPE GetValueMaybeNullAtPtr(TADDR base)
266 LIMITED_METHOD_DAC_CONTRACT;
267 return dac_cast<DPTR(FixupPointer<PTR_TYPE>)>(base)->GetValueMaybeNull();
270 // Returns value of the encoded pointer.
271 // Allows the value to be tagged.
272 FORCEINLINE TADDR GetValueMaybeTagged() const
274 LIMITED_METHOD_DAC_CONTRACT;
276 if ((addr & FIXUP_POINTER_INDIRECTION) != 0)
277 addr = *PTR_TADDR(addr - FIXUP_POINTER_INDIRECTION);
281 #ifndef DACCESS_COMPILE
282 void SetValue(PTR_TYPE addr)
284 LIMITED_METHOD_CONTRACT;
285 m_addr = dac_cast<TADDR>(addr);
288 void SetValueMaybeNull(PTR_TYPE addr)
290 LIMITED_METHOD_CONTRACT;
293 #endif // !DACCESS_COMPILE
299 //----------------------------------------------------------------------------
300 // RelativeFixupPointer is combination of RelativePointer and FixupPointer
301 template<typename PTR_TYPE>
302 class RelativeFixupPointer
306 static constexpr bool isRelative = true;
307 typedef PTR_TYPE type;
309 #ifndef DACCESS_COMPILE
310 RelativeFixupPointer()
312 SetValueMaybeNull(NULL);
314 #else // DACCESS_COMPILE
315 RelativeFixupPointer() =delete;
316 #endif // DACCESS_COMPILE
318 // Implicit copy/move is not allowed
319 RelativeFixupPointer<PTR_TYPE>(const RelativeFixupPointer<PTR_TYPE> &) =delete;
320 RelativeFixupPointer<PTR_TYPE>(RelativeFixupPointer<PTR_TYPE> &&) =delete;
321 RelativeFixupPointer<PTR_TYPE>& operator = (const RelativeFixupPointer<PTR_TYPE> &) =delete;
322 RelativeFixupPointer<PTR_TYPE>& operator = (RelativeFixupPointer<PTR_TYPE> &&) =delete;
324 // Returns whether the encoded pointer is NULL.
327 LIMITED_METHOD_DAC_CONTRACT;
328 // Pointer pointing to itself is treated as NULL
329 return m_delta == (TADDR)NULL;
332 // Returns whether the indirection cell contain fixup that has not been converted to real pointer yet.
333 FORCEINLINE BOOL IsTagged(TADDR base) const
335 LIMITED_METHOD_DAC_CONTRACT;
336 TADDR addr = base + m_delta;
337 if ((addr & FIXUP_POINTER_INDIRECTION) != 0)
338 return (*PTR_TADDR(addr - FIXUP_POINTER_INDIRECTION) & 1) != 0;
342 // Returns whether the indirection cell contain fixup that has not been converted to real pointer yet.
343 // Ignores isIndirect and offset values.
344 FORCEINLINE BOOL IsTaggedIndirect(TADDR base, bool isIndirect, intptr_t offset) const
346 LIMITED_METHOD_DAC_CONTRACT;
347 return IsTagged(base);
350 #ifndef DACCESS_COMPILE
351 // Returns whether the indirection cell contain fixup that has not been converted to real pointer yet.
352 // Does not need explicit base and thus can be used in non-DAC builds only.
353 FORCEINLINE BOOL IsTagged() const
355 LIMITED_METHOD_CONTRACT;
356 return IsTagged((TADDR)this);
358 #endif // !DACCESS_COMPILE
360 // Returns value of the encoded pointer. Assumes that the pointer is not NULL.
361 FORCEINLINE PTR_TYPE GetValue(TADDR base) const
363 LIMITED_METHOD_DAC_CONTRACT;
364 PRECONDITION(!IsNull());
365 PRECONDITION(!IsTagged(base));
366 TADDR addr = base + m_delta;
367 if ((addr & FIXUP_POINTER_INDIRECTION) != 0)
368 addr = *PTR_TADDR(addr - FIXUP_POINTER_INDIRECTION);
369 return dac_cast<PTR_TYPE>(addr);
372 #ifndef DACCESS_COMPILE
373 // Returns value of the encoded pointer. Assumes that the pointer is not NULL.
374 // Does not need explicit base and thus can be used in non-DAC builds only.
375 FORCEINLINE PTR_TYPE GetValue() const
377 LIMITED_METHOD_CONTRACT;
378 return GetValue((TADDR)this);
382 // Static version of GetValue. It is meant to simplify access to arrays of pointers.
383 FORCEINLINE static PTR_TYPE GetValueAtPtr(TADDR base)
385 LIMITED_METHOD_DAC_CONTRACT;
386 return dac_cast<DPTR(RelativeFixupPointer<PTR_TYPE>)>(base)->GetValue(base);
389 // Static version of GetValue. It is meant to simplify access to arrays of pointers.
390 // Ignores isIndirect and offset values.
391 FORCEINLINE static PTR_TYPE GetValueAtPtrIndirect(TADDR base, bool isIndirect, intptr_t offset)
393 LIMITED_METHOD_DAC_CONTRACT;
394 return GetValueAtPtr(base);
397 // Returns value of the encoded pointer. The pointer can be NULL.
398 PTR_TYPE GetValueMaybeNull(TADDR base) const
400 LIMITED_METHOD_DAC_CONTRACT;
401 PRECONDITION(!IsTagged(base));
403 // Cache local copy of delta to avoid races when the value is changing under us.
404 TADDR delta = m_delta;
409 TADDR addr = base + delta;
410 if ((addr & FIXUP_POINTER_INDIRECTION) != 0)
411 addr = *PTR_TADDR(addr - FIXUP_POINTER_INDIRECTION);
412 return dac_cast<PTR_TYPE>(addr);
415 #ifndef DACCESS_COMPILE
416 // Returns value of the encoded pointer. The pointer can be NULL.
417 // Does not need explicit base and thus can be used in non-DAC builds only.
418 FORCEINLINE PTR_TYPE GetValueMaybeNull() const
420 LIMITED_METHOD_CONTRACT;
421 return GetValueMaybeNull((TADDR)this);
425 // Static version of GetValueMaybeNull. It is meant to simplify access to arrays of pointers.
426 FORCEINLINE static PTR_TYPE GetValueMaybeNullAtPtr(TADDR base)
428 LIMITED_METHOD_DAC_CONTRACT;
429 return dac_cast<DPTR(RelativeFixupPointer<PTR_TYPE>)>(base)->GetValueMaybeNull(base);
432 // Static version of GetValueMaybeNull. It is meant to simplify access to arrays of pointers.
433 // Ignores isIndirect and offset values.
434 FORCEINLINE static PTR_TYPE GetValueMaybeNullAtPtrIndirect(TADDR base, bool isIndirect, intptr_t offset)
436 LIMITED_METHOD_DAC_CONTRACT;
437 return GetValueMaybeNullAtPtr(base);
440 #ifndef DACCESS_COMPILE
441 // Set encoded value of the pointer. Assumes that the value is not NULL.
442 FORCEINLINE void SetValue(PTR_TYPE addr)
444 LIMITED_METHOD_CONTRACT;
445 PRECONDITION(addr != NULL);
446 m_delta = dac_cast<TADDR>(addr) - (TADDR)this;
449 // Set encoded value of the pointer. The value can be NULL.
450 void SetValueMaybeNull(TADDR base, PTR_TYPE addr)
452 LIMITED_METHOD_CONTRACT;
456 m_delta = dac_cast<TADDR>(addr) - (TADDR)base;
459 // Set encoded value of the pointer. The value can be NULL.
460 FORCEINLINE void SetValueMaybeNull(PTR_TYPE addr)
462 LIMITED_METHOD_CONTRACT;
463 SetValueMaybeNull((TADDR)this, addr);
467 #ifndef DACCESS_COMPILE
468 // Returns the pointer to the indirection cell.
469 PTR_TYPE * GetValuePtr() const
471 LIMITED_METHOD_CONTRACT;
472 TADDR addr = ((TADDR)this) + m_delta;
473 _ASSERTE((addr & FIXUP_POINTER_INDIRECTION) != 0);
474 return (PTR_TYPE *)(addr - FIXUP_POINTER_INDIRECTION);
477 // Returns the pointer to the indirection cell.
478 // Ignores isIndirect and offset values.
479 PTR_TYPE * GetValuePtrIndirect(bool isIndirect, intptr_t offset) const
481 LIMITED_METHOD_CONTRACT;
482 return GetValuePtr();
484 #endif // !DACCESS_COMPILE
486 // Returns value of the encoded pointer. Assumes that the pointer is not NULL.
487 // Allows the value to be tagged.
488 FORCEINLINE TADDR GetValueMaybeTagged(TADDR base) const
490 LIMITED_METHOD_DAC_CONTRACT;
491 PRECONDITION(!IsNull());
492 TADDR addr = base + m_delta;
493 if ((addr & FIXUP_POINTER_INDIRECTION) != 0)
494 addr = *PTR_TADDR(addr - FIXUP_POINTER_INDIRECTION);
498 // Returns whether pointer is indirect. Assumes that the value is not NULL.
499 bool IsIndirectPtr(TADDR base) const
501 LIMITED_METHOD_DAC_CONTRACT;
502 PRECONDITION(!IsNull());
504 TADDR addr = base + m_delta;
506 return (addr & FIXUP_POINTER_INDIRECTION) != 0;
509 #ifndef DACCESS_COMPILE
510 // Returns whether pointer is indirect. Assumes that the value is not NULL.
511 // Does not need explicit base and thus can be used in non-DAC builds only.
512 bool IsIndirectPtr() const
514 LIMITED_METHOD_CONTRACT;
515 return IsIndirectPtr((TADDR)this);
518 // Returns whether pointer is indirect. Assumes that the value is not NULL.
519 // Ignores isIndirect and offset values.
520 bool IsIndirectPtrIndirect(bool isIndirect, intptr_t offset) const
522 LIMITED_METHOD_DAC_CONTRACT;
523 return IsIndirectPtr();
527 // Returns whether pointer is indirect. The value can be NULL.
528 bool IsIndirectPtrMaybeNull(TADDR base) const
530 LIMITED_METHOD_DAC_CONTRACT;
535 return IsIndirectPtr(base);
538 #ifndef DACCESS_COMPILE
539 // Returns whether pointer is indirect. The value can be NULL.
540 // Does not need explicit base and thus can be used in non-DAC builds only.
541 bool IsIndirectPtrMaybeNull() const
543 LIMITED_METHOD_CONTRACT;
544 return IsIndirectPtrMaybeNull((TADDR)this);
547 // Returns whether pointer is indirect. The value can be NULL.
548 // Ignores isIndirect and offset values.
549 bool IsIndirectPtrMaybeNullIndirect(bool isIndirect, intptr_t offset) const
551 LIMITED_METHOD_DAC_CONTRACT;
552 return IsIndirectPtrMaybeNull();
557 #ifndef DACCESS_COMPILE
558 Volatile<TADDR> m_delta;
564 // Fixup used for RelativePointer
565 #define IMAGE_REL_BASED_RelativePointer IMAGE_REL_BASED_RELPTR
567 #endif // FEATURE_PREJIT
569 //----------------------------------------------------------------------------
570 // PlainPointer is simple pointer wrapper to support compilation without indirections
571 // This is useful for building size-constrained runtime without NGen support.
572 template<typename PTR_TYPE>
577 static constexpr bool isRelative = false;
578 typedef PTR_TYPE type;
580 // Returns whether the encoded pointer is NULL.
583 LIMITED_METHOD_DAC_CONTRACT;
584 return m_ptr == NULL;
587 // Returns whether the indirection cell contain fixup that has not been converted to real pointer yet.
588 BOOL IsTagged(TADDR base) const
590 LIMITED_METHOD_DAC_CONTRACT;
594 // Returns whether the indirection cell contain fixup that has not been converted to real pointer yet.
595 BOOL IsTagged() const
597 LIMITED_METHOD_DAC_CONTRACT;
599 if ((addr & FIXUP_POINTER_INDIRECTION) != 0)
600 return (*PTR_TADDR(addr - FIXUP_POINTER_INDIRECTION) & 1) != 0;
604 // Returns value of the encoded pointer.
605 PTR_TYPE GetValue() const
607 LIMITED_METHOD_DAC_CONTRACT;
608 return dac_cast<PTR_TYPE>(m_ptr);
611 #ifndef DACCESS_COMPILE
612 // Returns the pointer to the indirection cell.
613 PTR_TYPE * GetValuePtr() const
615 LIMITED_METHOD_CONTRACT;
617 if ((addr & FIXUP_POINTER_INDIRECTION) != 0)
618 return (PTR_TYPE *)(addr - FIXUP_POINTER_INDIRECTION);
619 return (PTR_TYPE *)&m_ptr;
621 #endif // !DACCESS_COMPILE
623 // Returns value of the encoded pointer. Assumes that the pointer is not NULL.
624 PTR_TYPE GetValue(TADDR base) const
626 LIMITED_METHOD_DAC_CONTRACT;
627 return dac_cast<PTR_TYPE>(m_ptr);
630 // Static version of GetValue. It is meant to simplify access to arrays of pointers.
631 FORCEINLINE static PTR_TYPE GetValueAtPtr(TADDR base)
633 LIMITED_METHOD_DAC_CONTRACT;
634 return dac_cast<DPTR(PlainPointer<PTR_TYPE>)>(base)->GetValue(base);
637 // Returns value of the encoded pointer. The pointer can be NULL.
638 PTR_TYPE GetValueMaybeNull() const
640 LIMITED_METHOD_DAC_CONTRACT;
641 return dac_cast<PTR_TYPE>(m_ptr);
644 // Returns value of the encoded pointer. The pointer can be NULL.
645 PTR_TYPE GetValueMaybeNull(TADDR base) const
647 LIMITED_METHOD_DAC_CONTRACT;
648 return dac_cast<PTR_TYPE>(m_ptr);
651 // Static version of GetValueMaybeNull. It is meant to simplify access to arrays of pointers.
652 FORCEINLINE static PTR_TYPE GetValueMaybeNullAtPtr(TADDR base)
654 LIMITED_METHOD_DAC_CONTRACT;
655 return dac_cast<DPTR(PlainPointer<PTR_TYPE>)>(base)->GetValueMaybeNull(base);
658 // Returns whether pointer is indirect. Assumes that the value is not NULL.
659 bool IsIndirectPtr(TADDR base) const
661 LIMITED_METHOD_DAC_CONTRACT;
663 return (m_ptr & FIXUP_POINTER_INDIRECTION) != 0;
666 #ifndef DACCESS_COMPILE
667 // Returns whether pointer is indirect. Assumes that the value is not NULL.
668 // Does not need explicit base and thus can be used in non-DAC builds only.
669 bool IsIndirectPtr() const
671 LIMITED_METHOD_CONTRACT;
672 return IsIndirectPtr((TADDR)this);
676 // Returns whether pointer is indirect. The value can be NULL.
677 bool IsIndirectPtrMaybeNull(TADDR base) const
679 LIMITED_METHOD_DAC_CONTRACT;
681 return IsIndirectPtr(base);
684 #ifndef DACCESS_COMPILE
685 // Returns whether pointer is indirect. The value can be NULL.
686 // Does not need explicit base and thus can be used in non-DAC builds only.
687 bool IsIndirectPtrMaybeNull() const
689 LIMITED_METHOD_CONTRACT;
690 return IsIndirectPtrMaybeNull((TADDR)this);
694 #ifndef DACCESS_COMPILE
695 void SetValue(PTR_TYPE addr)
697 LIMITED_METHOD_CONTRACT;
698 m_ptr = dac_cast<TADDR>(addr);
701 // Set encoded value of the pointer. Assumes that the value is not NULL.
702 void SetValue(TADDR base, PTR_TYPE addr)
704 LIMITED_METHOD_CONTRACT;
705 m_ptr = dac_cast<TADDR>(addr);
708 // Static version of SetValue. It is meant to simplify access to arrays of pointers.
709 FORCEINLINE static void SetValueAtPtr(TADDR base, PTR_TYPE addr)
711 LIMITED_METHOD_CONTRACT;
712 dac_cast<DPTR(PlainPointer<PTR_TYPE>)>(base)->SetValue(base, addr);
715 // Set encoded value of the pointer. The value can be NULL.
716 void SetValueMaybeNull(TADDR base, PTR_TYPE addr)
718 LIMITED_METHOD_CONTRACT;
719 m_ptr = dac_cast<TADDR>(addr);
722 // Set encoded value of the pointer. The value can be NULL.
723 // Does not need explicit base and thus can be used in non-DAC builds only.
724 FORCEINLINE void SetValueMaybeNull(PTR_TYPE addr)
726 LIMITED_METHOD_CONTRACT;
727 return SetValueMaybeNull((TADDR)this, addr);
730 // Static version of SetValueMaybeNull. It is meant to simplify access to arrays of pointers.
731 FORCEINLINE static void SetValueMaybeNullAtPtr(TADDR base, PTR_TYPE addr)
733 LIMITED_METHOD_CONTRACT;
734 dac_cast<DPTR(PlainPointer<PTR_TYPE>)>(base)->SetValueMaybeNull(base, addr);
737 FORCEINLINE void SetValueVolatile(PTR_TYPE addr)
739 LIMITED_METHOD_CONTRACT;
740 VolatileStore((PTR_TYPE *)(&m_ptr), addr);
744 static TADDR GetRelativeMaybeNull(TADDR base, TADDR addr)
746 LIMITED_METHOD_DAC_CONTRACT;
750 static TADDR GetRelative(TADDR base, TADDR addr)
752 LIMITED_METHOD_DAC_CONTRACT;
753 PRECONDITION(addr != NULL);
761 #ifndef FEATURE_PREJIT
763 #define FixupPointer PlainPointer
764 #define RelativePointer PlainPointer
765 #define RelativeFixupPointer PlainPointer
767 #endif // !FEATURE_PREJIT
769 //----------------------------------------------------------------------------
770 // RelativePointer32 is pointer encoded as relative 32-bit offset. It is used
771 // to reduce both the size of the pointer itself as well as size of relocation
772 // section for pointers that live exlusively in NGen images.
773 template<typename PTR_TYPE>
774 class RelativePointer32
778 static constexpr bool isRelative = true;
779 typedef PTR_TYPE type;
781 // Returns whether the encoded pointer is NULL.
784 LIMITED_METHOD_DAC_CONTRACT;
785 // Pointer pointing to itself is treated as NULL
789 // Returns value of the encoded pointer. Assumes that the pointer is not NULL.
790 PTR_TYPE GetValue(TADDR base) const
792 LIMITED_METHOD_DAC_CONTRACT;
793 PRECONDITION(!IsNull());
794 return dac_cast<PTR_TYPE>(base + m_delta);
797 #ifndef DACCESS_COMPILE
798 // Returns value of the encoded pointer. Assumes that the pointer is not NULL.
799 // Does not need explicit base and thus can be used in non-DAC builds only.
800 FORCEINLINE PTR_TYPE GetValue() const
802 LIMITED_METHOD_CONTRACT;
803 return GetValue((TADDR)this);
807 // Static version of GetValue. It is meant to simplify access to arrays of pointers.
808 FORCEINLINE static PTR_TYPE GetValueAtPtr(TADDR base)
810 LIMITED_METHOD_DAC_CONTRACT;
811 return dac_cast<DPTR(RelativePointer<PTR_TYPE>)>(base)->GetValue(base);
814 // Returns value of the encoded pointer. The pointer can be NULL.
815 PTR_TYPE GetValueMaybeNull(TADDR base) const
817 LIMITED_METHOD_DAC_CONTRACT;
819 // Cache local copy of delta to avoid races when the value is changing under us.
820 TADDR delta = m_delta;
825 return dac_cast<PTR_TYPE>(base + delta);
828 #ifndef DACCESS_COMPILE
829 // Returns value of the encoded pointer. The pointer can be NULL.
830 // Does not need explicit base and thus can be used in non-DAC builds only.
831 FORCEINLINE PTR_TYPE GetValueMaybeNull() const
833 LIMITED_METHOD_CONTRACT;
834 return GetValueMaybeNull((TADDR)this);
838 // Static version of GetValueMaybeNull. It is meant to simplify access to arrays of pointers.
839 FORCEINLINE static PTR_TYPE GetValueMaybeNullAtPtr(TADDR base)
841 LIMITED_METHOD_DAC_CONTRACT;
842 return dac_cast<DPTR(RelativePointer<PTR_TYPE>)>(base)->GetValueMaybeNull(base);
849 //----------------------------------------------------------------------------
850 // IndirectPointer is pointer with optional indirection, similar to FixupPointer and RelativeFixupPointer.
852 // In comparison to FixupPointer, IndirectPointer's indirection is handled from outside by isIndirect flag.
853 // In comparison to RelativeFixupPointer, IndirectPointer's offset is a constant,
854 // while RelativeFixupPointer's offset is an address.
856 // IndirectPointer can contain NULL only if it is not indirect.
858 template<typename PTR_TYPE>
859 class IndirectPointer
863 static constexpr bool isRelative = false;
864 typedef PTR_TYPE type;
866 // Returns whether the encoded pointer is NULL.
869 LIMITED_METHOD_DAC_CONTRACT;
870 return m_addr == (TADDR)NULL;
873 // Returns whether the indirection cell contain fixup that has not been converted to real pointer yet.
874 // Uses isIndirect to identify, whether pointer is indirect or not. If it is, uses offset.
875 FORCEINLINE BOOL IsTaggedIndirect(TADDR base, bool isIndirect, intptr_t offset) const
877 LIMITED_METHOD_DAC_CONTRACT;
882 return (*PTR_TADDR(addr + offset) & 1) != 0;
887 // Returns value of the encoded pointer.
888 // Uses isIndirect to identify, whether pointer is indirect or not. If it is, uses offset.
889 FORCEINLINE PTR_TYPE GetValueIndirect(bool isIndirect, intptr_t offset) const
891 LIMITED_METHOD_DAC_CONTRACT;
896 addr = *PTR_TADDR(addr + offset);
898 return dac_cast<PTR_TYPE>(addr);
901 #ifndef DACCESS_COMPILE
902 // Returns the pointer to the indirection cell.
903 // Uses isIndirect to identify, whether pointer is indirect or not. If it is, uses offset.
904 PTR_TYPE * GetValuePtrIndirect(bool isIndirect, intptr_t offset) const
906 LIMITED_METHOD_CONTRACT;
911 return (PTR_TYPE *)(addr + offset);
913 return (PTR_TYPE *)&m_addr;
915 #endif // !DACCESS_COMPILE
917 // Static version of GetValue. It is meant to simplify access to arrays of pointers.
918 // Uses isIndirect to identify, whether pointer is indirect or not. If it is, uses offset.
919 FORCEINLINE static PTR_TYPE GetValueAtPtrIndirect(TADDR base, bool isIndirect, intptr_t offset)
921 LIMITED_METHOD_DAC_CONTRACT;
922 return dac_cast<DPTR(IndirectPointer<PTR_TYPE>)>(base)->GetValueIndirect(isIndirect, offset);
925 // Static version of GetValueMaybeNull. It is meant to simplify access to arrays of pointers.
926 // Uses isIndirect to identify, whether pointer is indirect or not. If it is, uses offset.
927 FORCEINLINE static PTR_TYPE GetValueMaybeNullAtPtrIndirect(TADDR base, bool isIndirect, intptr_t offset)
929 LIMITED_METHOD_DAC_CONTRACT;
930 return GetValueAtPtrIndirect(base, isIndirect, offset);
933 #ifndef DACCESS_COMPILE
934 // Returns whether pointer is indirect. Assumes that the value is not NULL.
935 // Uses isIndirect to identify, whether pointer is indirect or not. If it is, uses offset.
936 bool IsIndirectPtrIndirect(bool isIndirect, intptr_t offset) const
938 LIMITED_METHOD_CONTRACT;
944 // Returns whether pointer is indirect. The value can be NULL.
945 // Uses isIndirect to identify, whether pointer is indirect or not. If it is, uses offset.
946 bool IsIndirectPtrMaybeNullIndirect(bool isIndirect, intptr_t offset) const
948 LIMITED_METHOD_CONTRACT;
949 return IsIndirectPtrIndirect(isIndirect, offset);
951 #endif // !DACCESS_COMPILE
953 #ifndef DACCESS_COMPILE
954 // Set encoded value of the pointer. Assumes that the value is not NULL.
955 void SetValue(PTR_TYPE addr)
957 LIMITED_METHOD_CONTRACT;
958 m_addr = dac_cast<TADDR>(addr);
961 // Set encoded value of the pointer. The value can be NULL.
962 void SetValueMaybeNull(PTR_TYPE addr)
964 LIMITED_METHOD_CONTRACT;
967 #endif // !DACCESS_COMPILE
973 template<bool isMaybeNull, typename T, typename PT>
975 ReadPointer(const T *base, const PT T::* pPointerFieldMember)
977 LIMITED_METHOD_DAC_CONTRACT;
979 uintptr_t offset = (uintptr_t) &(base->*pPointerFieldMember) - (uintptr_t) base;
983 return PT::GetValueMaybeNullAtPtr(dac_cast<TADDR>(base) + offset);
987 return PT::GetValueAtPtr(dac_cast<TADDR>(base) + offset);
991 template<bool isMaybeNull, typename T, typename PT>
993 ReadPointer(const T *base, const PT T::* pPointerFieldMember, bool isIndirect)
995 LIMITED_METHOD_DAC_CONTRACT;
997 uintptr_t offset = (uintptr_t) &(base->*pPointerFieldMember) - (uintptr_t) base;
1001 return PT::GetValueMaybeNullAtPtrIndirect(dac_cast<TADDR>(base) + offset, isIndirect, offset);
1005 return PT::GetValueAtPtrIndirect(dac_cast<TADDR>(base) + offset, isIndirect, offset);
1009 template<typename T, typename PT>
1011 ReadPointerMaybeNull(const T *base, const PT T::* pPointerFieldMember)
1013 LIMITED_METHOD_DAC_CONTRACT;
1015 return ReadPointer<true>(base, pPointerFieldMember);
1018 template<typename T, typename PT>
1020 ReadPointerMaybeNull(const T *base, const PT T::* pPointerFieldMember, bool isIndirect)
1022 LIMITED_METHOD_DAC_CONTRACT;
1024 return ReadPointer<true>(base, pPointerFieldMember, isIndirect);
1027 template<typename T, typename PT>
1029 ReadPointer(const T *base, const PT T::* pPointerFieldMember)
1031 LIMITED_METHOD_DAC_CONTRACT;
1033 return ReadPointer<false>(base, pPointerFieldMember);
1036 template<typename T, typename PT>
1038 ReadPointer(const T *base, const PT T::* pPointerFieldMember, bool isIndirect)
1040 LIMITED_METHOD_DAC_CONTRACT;
1042 return ReadPointer<false>(base, pPointerFieldMember, isIndirect);
1045 template<bool isMaybeNull, typename T, typename C, typename PT>
1047 ReadPointer(const T *base, const C T::* pFirstPointerFieldMember, const PT C::* pSecondPointerFieldMember)
1049 LIMITED_METHOD_DAC_CONTRACT;
1051 const PT *ptr = &(base->*pFirstPointerFieldMember.*pSecondPointerFieldMember);
1052 uintptr_t offset = (uintptr_t) ptr - (uintptr_t) base;
1056 return PT::GetValueMaybeNullAtPtr(dac_cast<TADDR>(base) + offset);
1060 return PT::GetValueAtPtr(dac_cast<TADDR>(base) + offset);
1064 template<typename T, typename C, typename PT>
1066 ReadPointerMaybeNull(const T *base, const C T::* pFirstPointerFieldMember, const PT C::* pSecondPointerFieldMember)
1068 LIMITED_METHOD_DAC_CONTRACT;
1070 return ReadPointer<true>(base, pFirstPointerFieldMember, pSecondPointerFieldMember);
1073 template<typename T, typename C, typename PT>
1075 ReadPointer(const T *base, const C T::* pFirstPointerFieldMember, const PT C::* pSecondPointerFieldMember)
1077 LIMITED_METHOD_DAC_CONTRACT;
1079 return ReadPointer<false>(base, pFirstPointerFieldMember, pSecondPointerFieldMember);
1082 #endif //_FIXUPPOINTER_H