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.
5 // File: contractimpl.h
7 // Keeps track of contract implementations, used primarily in stub dispatch.
14 // ============================================================================
16 #ifndef CONTRACTIMPL_H_
17 #define CONTRACTIMPL_H_
24 class StackingAllocator;
26 // ===========================================================================
33 //------------------------------------------------------------------------
34 inline DispatchSlot(PCODE slot) : m_slot(slot)
35 { LIMITED_METHOD_CONTRACT; }
37 //------------------------------------------------------------------------
38 inline DispatchSlot(const DispatchSlot &slot) : m_slot(slot.m_slot)
39 { LIMITED_METHOD_CONTRACT; }
41 //------------------------------------------------------------------------
42 inline DispatchSlot& operator=(PCODE slot)
43 { LIMITED_METHOD_CONTRACT; m_slot = slot; return *this; }
45 //------------------------------------------------------------------------
46 inline DispatchSlot& operator=(const DispatchSlot &slot)
47 { LIMITED_METHOD_CONTRACT; m_slot = slot.m_slot; return *this; }
49 //------------------------------------------------------------------------
51 { LIMITED_METHOD_CONTRACT; return (m_slot == NULL); }
53 //------------------------------------------------------------------------
55 { LIMITED_METHOD_CONTRACT; m_slot = NULL; }
57 //------------------------------------------------------------------------
58 inline PCODE GetTarget()
59 { LIMITED_METHOD_CONTRACT; return m_slot; }
61 //------------------------------------------------------------------------
62 MethodDesc *GetMethodDesc();
63 }; // struct DispatchSlot
65 // ===========================================================================
66 // This value indicates that a slot number is in reference to the
67 // current class. Thus, no TypeID can have a value of 0. This is stored
68 // inside a DispatchToken as the TypeID for such cases.
69 static const UINT32 TYPE_ID_THIS_CLASS = 0;
72 // ===========================================================================
73 // The type IDs used in the dispatch map are relative to the implementing
74 // type, and are a discriminated union between:
75 // - a special value to indicate "this" class
76 // - a special value to indicate that an interface is not implemented by the type
77 // - an index into the InterfaceMap
78 class DispatchMapTypeID
81 static const UINT32 const_nFirstInterfaceIndex = 1;
84 DispatchMapTypeID(UINT32 id) { LIMITED_METHOD_DAC_CONTRACT; m_typeIDVal = id; }
87 static DispatchMapTypeID ThisClassID() { LIMITED_METHOD_CONTRACT; return DispatchMapTypeID(TYPE_ID_THIS_CLASS); }
88 static DispatchMapTypeID InterfaceClassID(UINT32 inum)
90 LIMITED_METHOD_CONTRACT;
91 _ASSERTE(inum + const_nFirstInterfaceIndex > inum);
92 return DispatchMapTypeID(inum + const_nFirstInterfaceIndex);
94 DispatchMapTypeID() { LIMITED_METHOD_DAC_CONTRACT; m_typeIDVal = TYPE_ID_THIS_CLASS; }
97 BOOL IsThisClass() const { LIMITED_METHOD_DAC_CONTRACT; return (m_typeIDVal == TYPE_ID_THIS_CLASS); }
98 BOOL IsImplementedInterface() const { LIMITED_METHOD_CONTRACT; return (m_typeIDVal >= const_nFirstInterfaceIndex); }
99 UINT32 GetInterfaceNum() const
101 LIMITED_METHOD_CONTRACT;
102 _ASSERTE(IsImplementedInterface());
103 return (m_typeIDVal - const_nFirstInterfaceIndex);
107 BOOL operator ==(const DispatchMapTypeID &that) const { LIMITED_METHOD_CONTRACT; return m_typeIDVal == that.m_typeIDVal; }
108 BOOL operator !=(const DispatchMapTypeID &that) const { LIMITED_METHOD_CONTRACT; return m_typeIDVal != that.m_typeIDVal; }
109 BOOL operator <(const DispatchMapTypeID &that) const { LIMITED_METHOD_CONTRACT; return m_typeIDVal < that.m_typeIDVal; }
111 // To/from UINT32, for encoding/decoding etc.
112 UINT32 ToUINT32() const { LIMITED_METHOD_DAC_CONTRACT; return m_typeIDVal; }
113 static DispatchMapTypeID FromUINT32(UINT32 x) { LIMITED_METHOD_DAC_CONTRACT; return DispatchMapTypeID(x); }
114 }; // class DispatchMapTypeID
116 #ifdef FAT_DISPATCH_TOKENS
117 // ===========================================================================
118 // This is the structure that is used when typeId becomes too be to be
119 // contained in a regular DispatchToken. DispatchToken is able to encapsulate
120 // a DispatchTokenFat*, somewhat like TypeHandle may encapsulate a TypeDesc*.
121 struct DispatchTokenFat
123 friend struct DispatchToken;
124 friend class BaseDomain;
131 DispatchTokenFat(UINT32 typeID, UINT32 slotNumber)
132 : m_typeId(typeID), m_slotNum(slotNumber)
135 // Equality comparison, used in SHash set.
136 bool operator==(const DispatchTokenFat &other) const
137 { return m_typeId == other.m_typeId && m_slotNum == other.m_slotNum; }
139 // Hashing operator, using in SHash set.
140 operator size_t() const
141 { return (size_t)m_typeId ^ (size_t)m_slotNum; }
142 }; // struct DispatchTokenFat
144 typedef DPTR(DispatchTokenFat) PTR_DispatchTokenFat;
147 // ===========================================================================
148 // This represents the contract used for code lookups throughout the
149 // virtual stub dispatch mechanism. It is important to know that
150 // sizeof(DispatchToken) is UINT_PTR, which means it can be thrown around
151 // by value without a problem.
156 // IMPORTANT: This is the ONLY member of this class.
160 // NOTE: On 32-bit, we use the uppermost bit to indicate that the
161 // token is really a DispatchTokenFat*, and to recover the pointer
162 // we just shift left by 1; correspondingly, when storing a
163 // DispatchTokenFat* in a DispatchToken, we shift right by 1.
164 static const UINT_PTR MASK_TYPE_ID = 0x00007FFF;
165 static const UINT_PTR MASK_SLOT_NUMBER = 0x0000FFFF;
167 static const UINT_PTR SHIFT_TYPE_ID = 0x10;
168 static const UINT_PTR SHIFT_SLOT_NUMBER = 0x0;
170 #ifdef FAT_DISPATCH_TOKENS
171 static const UINT_PTR FAT_TOKEN_FLAG = 0x80000000;
172 #endif // FAT_DISPATCH_TOKENS
174 static const UINT_PTR INVALID_TOKEN = 0x7FFFFFFF;
176 static const UINT_PTR MASK_TYPE_ID = UI64(0x000000007FFFFFFF);
177 static const UINT_PTR MASK_SLOT_NUMBER = UI64(0x000000000000FFFF);
179 static const UINT_PTR SHIFT_TYPE_ID = 0x20;
180 static const UINT_PTR SHIFT_SLOT_NUMBER = 0x0;
182 #ifdef FAT_DISPATCH_TOKENS
183 static const UINT_PTR FAT_TOKEN_FLAG = UI64(0x8000000000000000);
184 #endif // FAT_DISPATCH_TOKENS
186 static const UINT_PTR INVALID_TOKEN = 0x7FFFFFFFFFFFFFFF;
189 #ifdef FAT_DISPATCH_TOKENS
190 //------------------------------------------------------------------------
191 static inline BOOL IsFat(UINT_PTR token)
193 return (token & FAT_TOKEN_FLAG) != 0;
196 //------------------------------------------------------------------------
197 static inline DispatchTokenFat* ToFat(UINT_PTR token)
199 return PTR_DispatchTokenFat(token << 1);
203 //------------------------------------------------------------------------
204 // Combines the two values into a single 32-bit number.
205 static UINT_PTR CreateToken(UINT32 typeID, UINT32 slotNumber)
207 LIMITED_METHOD_CONTRACT;
208 CONSISTENCY_CHECK(((UINT_PTR)typeID & MASK_TYPE_ID) == (UINT_PTR)typeID);
209 CONSISTENCY_CHECK(((UINT_PTR)slotNumber & MASK_SLOT_NUMBER) == (UINT_PTR)slotNumber);
210 return ((((UINT_PTR)typeID & MASK_TYPE_ID) << SHIFT_TYPE_ID) |
211 (((UINT_PTR)slotNumber & MASK_SLOT_NUMBER) << SHIFT_SLOT_NUMBER));
214 //------------------------------------------------------------------------
215 // Extracts the type ID from a token created by CreateToken
216 static UINT32 DecodeTypeID(UINT_PTR token)
218 LIMITED_METHOD_CONTRACT;
219 CONSISTENCY_CHECK(token != INVALID_TOKEN);
220 #ifdef FAT_DISPATCH_TOKENS
222 return ToFat(token)->m_typeId;
225 return ((token >> SHIFT_TYPE_ID) & MASK_TYPE_ID);
228 //------------------------------------------------------------------------
229 // Extracts the slot number from a token created by CreateToken
230 static UINT32 DecodeSlotNumber(UINT_PTR token)
232 LIMITED_METHOD_CONTRACT;
233 CONSISTENCY_CHECK(token != INVALID_TOKEN);
234 #ifdef FAT_DISPATCH_TOKENS
236 return ToFat(token)->m_slotNum;
239 return ((token >> SHIFT_SLOT_NUMBER) & MASK_SLOT_NUMBER);
244 #ifdef FAT_DISPATCH_TOKENS
246 static const UINT32 MAX_TYPE_ID_SMALL = 0x00007FFF;
248 static const UINT32 MAX_TYPE_ID_SMALL = 0x7FFFFFFF;
250 #endif // FAT_DISPATCH_TOKENS
252 //------------------------------------------------------------------------
255 LIMITED_METHOD_CONTRACT;
256 m_token = INVALID_TOKEN;
259 DispatchToken(UINT_PTR token)
261 CONSISTENCY_CHECK(token != INVALID_TOKEN);
265 #ifdef FAT_DISPATCH_TOKENS
266 //------------------------------------------------------------------------
267 DispatchToken(DispatchTokenFat *pFat)
269 LIMITED_METHOD_CONTRACT;
270 CONSISTENCY_CHECK((((UINT_PTR)pFat) & 0x1) == 0);
271 m_token = (UINT_PTR(pFat) >> 1) | FAT_TOKEN_FLAG;
274 //------------------------------------------------------------------------
275 static bool RequiresDispatchTokenFat(UINT32 typeID, UINT32 slotNumber)
277 LIMITED_METHOD_CONTRACT;
278 return typeID > MAX_TYPE_ID_SMALL
280 // Stress the overflow mechanism in debug builds.
281 || ((typeID != TYPE_ID_THIS_CLASS) && ((typeID % 7) < 4))
285 #endif //FAT_DISPATCH_TOKENS
287 //------------------------------------------------------------------------
288 inline bool operator==(const DispatchToken &tok) const
290 LIMITED_METHOD_CONTRACT;
291 return m_token == tok.m_token;
294 //------------------------------------------------------------------------
295 // Creates a "this" type dispatch token. This means that the type for the
296 // token is implied by the type on which one wishes to invoke. In other
297 // words, the value returned by GetTypeID is TYPE_ID_THIS_CLASS.
298 static DispatchToken CreateDispatchToken(UINT32 slotNumber)
301 return DispatchToken(CreateToken(TYPE_ID_THIS_CLASS, slotNumber));
304 //------------------------------------------------------------------------
305 // Creates a fully qualified type dispatch token. This means that the ID
306 // for the type is encoded directly in the token.
307 static DispatchToken CreateDispatchToken(UINT32 typeID, UINT32 slotNumber)
310 return DispatchToken(CreateToken(typeID, slotNumber));
313 //------------------------------------------------------------------------
314 // Returns the type ID for this dispatch contract
315 inline UINT32 GetTypeID() const
318 return DecodeTypeID(m_token);
321 //------------------------------------------------------------------------
322 // Returns the slot number for this dispatch contract
323 inline UINT32 GetSlotNumber() const
326 return DecodeSlotNumber(m_token);
329 //------------------------------------------------------------------------
330 inline bool IsThisToken() const
333 return (GetTypeID() == TYPE_ID_THIS_CLASS);
336 //------------------------------------------------------------------------
337 inline bool IsTypedToken() const
340 return (!IsThisToken());
343 //------------------------------------------------------------------------
344 static DispatchToken From_SIZE_T(SIZE_T token)
347 return DispatchToken((UINT_PTR)token);
350 //------------------------------------------------------------------------
351 SIZE_T To_SIZE_T() const
354 static_assert_no_msg(sizeof(SIZE_T) == sizeof(UINT_PTR));
355 return (SIZE_T) m_token;
358 //------------------------------------------------------------------------
359 inline BOOL IsValid() const
361 LIMITED_METHOD_CONTRACT;
362 return !(m_token == INVALID_TOKEN);
364 }; // struct DispatchToken
366 // DispatchToken.m_token should be the only field of DispatchToken.
367 static_assert_no_msg(sizeof(DispatchToken) == sizeof(UINT_PTR));
369 // ===========================================================================
378 // This is used for an invalid type ID.
379 static const UINT32 INVALID_TYPE_ID = ~0;
381 // If we can have more than 2^32-1 types, we'll need to revisit this.
382 static const UINT32 MAX_TYPE_ID = INVALID_TYPE_ID - 1;
384 //------------------------------------------------------------------------
387 : m_nextID(0), m_incSize(0), m_nextFatID(0)
388 { LIMITED_METHOD_CONTRACT; }
391 //------------------------------------------------------------------------
392 void Init(UINT32 idStartValue, UINT32 idIncrementValue)
394 LIMITED_METHOD_CONTRACT;
395 m_nextID = idStartValue;
396 m_incSize = idIncrementValue;
397 m_nextFatID = DispatchToken::MAX_TYPE_ID_SMALL + 1;
400 while (!OwnsID(m_nextFatID))
407 //------------------------------------------------------------------------
408 // Returns the next available ID
409 inline UINT32 GetNextID()
416 INJECT_FAULT(COMPlusThrowOM());
417 PRECONDITION(m_nextID != 0);
418 PRECONDITION(m_incSize != 0);
420 UINT32 id = m_nextID;
422 if (id > DispatchToken::MAX_TYPE_ID_SMALL)
424 return GetNextFatID();
427 if (!ClrSafeInt<UINT32>::addition(m_nextID, m_incSize, m_nextID) ||
428 m_nextID == INVALID_TYPE_ID)
435 //------------------------------------------------------------------------
436 // Returns the next available ID
437 inline UINT32 GetNextFatID()
444 INJECT_FAULT(COMPlusThrowOM());
445 PRECONDITION(m_nextFatID != 0);
446 PRECONDITION(m_incSize != 0);
448 UINT32 id = m_nextFatID;
449 if (!ClrSafeInt<UINT32>::addition(m_nextFatID, m_incSize, m_nextFatID) ||
450 m_nextID == INVALID_TYPE_ID)
457 //------------------------------------------------------------------------
458 inline BOOL OwnsID(UINT32 id)
460 LIMITED_METHOD_CONTRACT;
461 return ((id % m_incSize) == (m_nextID % m_incSize));
463 }; // class TypeIDProvider
465 // ===========================================================================
472 TypeIDProvider m_idProvider;
473 BOOL m_fUseFatIdsForUniqueness;
476 //------------------------------------------------------------------------
477 // Returns the next available ID
478 inline UINT32 GetNextID()
481 CONSISTENCY_CHECK(m_lock.OwnedByCurrentThread());
482 UINT32 id = m_idProvider.GetNextID();
483 CONSISTENCY_CHECK(id != TYPE_ID_THIS_CLASS);
487 //------------------------------------------------------------------------
488 // Returns the next available FAT ID
489 inline UINT32 GetNextFatID()
492 CONSISTENCY_CHECK(m_lock.OwnedByCurrentThread());
493 UINT32 id = m_idProvider.GetNextFatID();
494 CONSISTENCY_CHECK(id != TYPE_ID_THIS_CLASS);
499 // Starting values for shared and unshared domains
502 STARTING_SHARED_DOMAIN_ID = 0x2,
503 STARTING_UNSHARED_DOMAIN_ID = 0x3,
506 //------------------------------------------------------------------------
507 void Init(UINT32 idStartValue, UINT32 idIncrementValue, BOOL fUseFatTokensForUniqueness);
509 //------------------------------------------------------------------------
512 : m_lock(CrstTypeIDMap, CrstFlags(CRST_REENTRANCY))
515 static_assert_no_msg(TypeIDProvider::INVALID_TYPE_ID == static_cast<UINT32>(INVALIDENTRY));
518 //------------------------------------------------------------------------
521 { WRAPPER_NO_CONTRACT; }
523 //------------------------------------------------------------------------
524 // Returns the ID of the type if found. If not found, returns INVALID_TYPE_ID
525 UINT32 LookupTypeID(PTR_MethodTable pMT);
527 //------------------------------------------------------------------------
528 // Returns the ID of the type if found. If not found, returns NULL.
529 PTR_MethodTable LookupType(UINT32 id);
531 //------------------------------------------------------------------------
532 // Returns the ID of the type if found. If not found, assigns the ID and
533 // returns the new ID.
534 UINT32 GetTypeID(PTR_MethodTable pMT);
536 //------------------------------------------------------------------------
537 inline UINT32 GetCount()
538 { LIMITED_METHOD_CONTRACT; return m_entryCount; }
540 //------------------------------------------------------------------------
549 m_idProvider.Init(0, 0);
552 //------------------------------------------------------------------------
555 HashMap::Iterator m_it;
558 //--------------------------------------------------------------------
559 inline Iterator(TypeIDMap *map)
560 : m_it(map->m_mtMap.begin())
565 //--------------------------------------------------------------------
566 inline BOOL IsValid()
572 //--------------------------------------------------------------------
575 // We want to skip the entries that are ID->Type, and just
576 // enumerate the Type->ID entries to avoid duplicates.
581 //--------------------------------------------------------------------
582 inline MethodTable *GetType()
585 return (MethodTable *) m_it.GetKey();
588 //--------------------------------------------------------------------
589 inline UINT32 GetID()
592 return (UINT32) m_it.GetValue();
595 }; // class TypeIDMap
598 // ===========================================================================
599 struct DispatchMapEntry
602 DispatchMapTypeID m_typeID;
604 UINT16 m_targetSlotNumber;
613 //------------------------------------------------------------------------
614 // Initializes this structure.
615 void InitVirtualMapping(
616 DispatchMapTypeID typeID,
618 UINT32 targetSlotNumber)
620 LIMITED_METHOD_DAC_CONTRACT;
623 m_slotNumber = (UINT16)slotNumber;
624 m_targetSlotNumber = (UINT16)targetSlotNumber;
627 m_flags = e_IS_VALID;
630 //------------------------------------------------------------------------
631 inline DispatchMapTypeID GetTypeID()
632 { LIMITED_METHOD_CONTRACT; return m_typeID; }
634 //------------------------------------------------------------------------
635 inline UINT32 GetSlotNumber()
636 { LIMITED_METHOD_CONTRACT; return (UINT32) m_slotNumber; }
638 //------------------------------------------------------------------------
639 inline UINT32 GetTargetSlotNumber()
641 LIMITED_METHOD_DAC_CONTRACT;
642 CONSISTENCY_CHECK(IsValid());
643 return (UINT32)m_targetSlotNumber;
645 inline void SetTargetSlotNumber(UINT32 targetSlotNumber)
647 LIMITED_METHOD_CONTRACT;
648 CONSISTENCY_CHECK(IsValid());
649 m_targetSlotNumber = (UINT16)targetSlotNumber;
652 //------------------------------------------------------------------------
653 // Ctor - just blanks everything out - need to call Init*Mapping function.
654 inline DispatchMapEntry() : m_flags(0)
655 { LIMITED_METHOD_DAC_CONTRACT; }
657 inline BOOL IsValid()
658 { LIMITED_METHOD_CONTRACT; return (m_flags & e_IS_VALID); }
659 }; // struct DispatchMapEntry
661 // ===========================================================================
662 // This represents an entry in the dispatch mapping. Conceptually, there is a
663 // source to target mapping. There are additional housekeeping flags.
664 struct DispatchMapBuilderNode
666 // This represents the type and slot for this mapping
667 DispatchMapTypeID m_typeID;
670 // These represent the target, and type of mapping
671 MethodDesc * m_pMDTarget;
677 e_ENTRY_IS_METHODIMPL = 1
680 // Next entry in the list
681 DispatchMapBuilderNode *m_next;
683 //------------------------------------------------------------------------
685 DispatchMapTypeID typeID,
687 MethodDesc * pMDTarget)
690 CONSISTENCY_CHECK(CheckPointer(pMDTarget, NULL_OK));
691 // Remember type and slot
693 m_slotNumber = slotNumber;
695 m_pMDTarget = pMDTarget;
696 // Initialize the flags
698 // Default to null link
702 //------------------------------------------------------------------------
703 inline BOOL IsMethodImpl()
706 return (m_flags & e_ENTRY_IS_METHODIMPL);
709 //------------------------------------------------------------------------
710 inline void SetIsMethodImpl()
713 m_flags |= e_ENTRY_IS_METHODIMPL;
715 }; // struct DispatchMapBuilderNode
717 // ===========================================================================
718 class DispatchMapBuilder
723 //------------------------------------------------------------------------
724 DispatchMapBuilder(StackingAllocator *allocator)
725 : m_pHead(NULL), m_cEntries(0), m_pAllocator(allocator)
726 { LIMITED_METHOD_CONTRACT; CONSISTENCY_CHECK(CheckPointer(m_pAllocator)); }
728 //------------------------------------------------------------------------
729 inline StackingAllocator *GetAllocator()
730 { LIMITED_METHOD_CONTRACT; return m_pAllocator; }
732 //------------------------------------------------------------------------
733 // If TRUE, it points to a matching entry.
734 // If FALSE, it is at the insertion point.
735 BOOL Find(DispatchMapTypeID typeID, UINT32 slotNumber, Iterator &it);
737 //------------------------------------------------------------------------
738 // If TRUE, contains such an entry.
739 // If FALSE, no such entry exists.
740 BOOL Contains(DispatchMapTypeID typeID, UINT32 slotNumber);
742 //------------------------------------------------------------------------
743 // This is used when building a MT, and things such as implementation
744 // table index and chain delta can't be calculated until later on. That's
745 // why we use an MD to get the information later.
746 void InsertMDMapping(
747 DispatchMapTypeID typeID,
749 MethodDesc * pMDTarget,
752 //------------------------------------------------------------------------
753 inline UINT32 Count()
754 { LIMITED_METHOD_CONTRACT; return m_cEntries; }
756 //------------------------------------------------------------------------
759 friend class DispatchMapBuilder;
762 DispatchMapBuilderNode **m_cur;
764 //--------------------------------------------------------------------
765 inline DispatchMapBuilderNode **EntryNodePtr()
766 { LIMITED_METHOD_CONTRACT; return m_cur; }
768 //--------------------------------------------------------------------
769 inline DispatchMapBuilderNode *EntryNode()
770 { LIMITED_METHOD_CONTRACT; CONSISTENCY_CHECK(IsValid()); return *m_cur; }
773 //--------------------------------------------------------------------
774 // Creates an iterator that is pointing to the first entry of the map.
775 inline Iterator(DispatchMapBuilder *pMap)
776 : m_cur(&pMap->m_pHead)
777 { LIMITED_METHOD_CONTRACT; }
779 //--------------------------------------------------------------------
780 // Creates an iterator this is pointing to the same location as 'it'.
781 inline Iterator(Iterator &it)
783 { LIMITED_METHOD_CONTRACT; }
785 //--------------------------------------------------------------------
786 inline BOOL IsValid()
787 { LIMITED_METHOD_CONTRACT; return (*m_cur != NULL); }
789 //--------------------------------------------------------------------
796 m_cur = &((*m_cur)->m_next);
800 //--------------------------------------------------------------------
801 inline DispatchMapTypeID GetTypeID()
804 CONSISTENCY_CHECK(IsValid());
805 return EntryNode()->m_typeID;
808 //--------------------------------------------------------------------
809 inline UINT32 GetSlotNumber()
812 CONSISTENCY_CHECK(IsValid());
813 return EntryNode()->m_slotNumber;
816 //--------------------------------------------------------------------
817 inline MethodDesc *GetTargetMD()
820 CONSISTENCY_CHECK(IsValid());
821 return EntryNode()->m_pMDTarget;
824 //--------------------------------------------------------------------
825 UINT32 GetTargetSlot();
827 //--------------------------------------------------------------------
828 inline void SetTarget(MethodDesc *pMDTarget)
831 CONSISTENCY_CHECK(IsValid());
832 CONSISTENCY_CHECK(CheckPointer(pMDTarget));
833 EntryNode()->m_pMDTarget = pMDTarget;
836 //--------------------------------------------------------------------
837 inline BOOL IsMethodImpl()
840 CONSISTENCY_CHECK(IsValid());
841 return EntryNode()->IsMethodImpl();
844 //--------------------------------------------------------------------
845 inline void SetIsMethodImpl()
848 CONSISTENCY_CHECK(IsValid());
849 EntryNode()->SetIsMethodImpl();
852 inline void SkipThisTypeEntries()
854 LIMITED_METHOD_CONTRACT;
855 while (IsValid() && GetTypeID() == DispatchMapTypeID::ThisClassID())
863 DispatchMapBuilderNode * m_pHead;
865 StackingAllocator * m_pAllocator;
867 //------------------------------------------------------------------------
868 DispatchMapBuilderNode * NewEntry();
870 }; // class DispatchMapBuilder
872 typedef DPTR(class DispatchMap) PTR_DispatchMap;
873 // ===========================================================================
879 static const INT32 ENCODING_TYPE_DELTA = 1;
880 static const INT32 ENCODING_SLOT_DELTA = 1;
881 static const INT32 ENCODING_TARGET_SLOT_DELTA = 1;
884 //------------------------------------------------------------------------
885 // Need to make sure that you allocate GetObjectSize(pMap) bytes for any
886 // instance of DispatchMap, as this constructor assumes that m_rgMap is
887 // large enough to store cbMap bytes, which GetObjectSize ensures.
892 //------------------------------------------------------------------------
893 static void CreateEncodedMapping(
895 DispatchMapBuilder * pMapBuilder,
896 StackingAllocator * pAllocator,
900 //------------------------------------------------------------------------
901 static UINT32 GetObjectSize(UINT32 cbMap)
903 LIMITED_METHOD_CONTRACT;
904 return (UINT32)(sizeof(DispatchMap) + cbMap);
907 //------------------------------------------------------------------------
910 #ifdef DACCESS_COMPILE
911 void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
914 #ifdef FEATURE_PREJIT
915 //------------------------------------------------------------------------
916 void Save(DataImage *image);
918 //------------------------------------------------------------------------
919 void Fixup(DataImage *image);
920 #endif //FEATURE_PREJIT
922 //------------------------------------------------------------------------
923 class EncodedMapIterator
925 friend class DispatchMap;
927 DispatchMapEntry m_e;
929 // These fields are for decoding the implementation map
931 // Keep count of the number of types in the list
934 DispatchMapTypeID m_curTypeId;
935 BOOL m_fCurTypeHasNegativeEntries;
937 // Keep count of the number of entries for the current type
942 UINT32 m_curTargetSlot;
944 //--------------------------------------------------------------------
947 //--------------------------------------------------------------------
948 void Init(PTR_BYTE pbMap);
951 //--------------------------------------------------------------------
952 EncodedMapIterator(MethodTable *pMT);
954 //--------------------------------------------------------------------
955 // This should be used only when a dispatch map needs to be used
956 // separately from its MethodTable.
957 EncodedMapIterator(DispatchMap *pMap);
959 //--------------------------------------------------------------------
960 EncodedMapIterator(PTR_BYTE pbMap);
962 //--------------------------------------------------------------------
963 inline BOOL IsValid()
964 { LIMITED_METHOD_DAC_CONTRACT; return (m_curType < m_numTypes); }
966 //--------------------------------------------------------------------
969 //--------------------------------------------------------------------
970 inline DispatchMapEntry *Entry()
971 { LIMITED_METHOD_CONTRACT; CONSISTENCY_CHECK(IsValid()); return &m_e; }
972 }; // class EncodedMapIterator
975 //------------------------------------------------------------------------
979 // This is for generating entries from the encoded map
980 EncodedMapIterator m_mapIt;
983 //--------------------------------------------------------------------
984 Iterator(MethodTable *pMT);
986 //--------------------------------------------------------------------
989 //--------------------------------------------------------------------
992 //--------------------------------------------------------------------
993 DispatchMapEntry *Entry();
995 }; // class DispatchMap
998 struct StubDispatchStats
1000 // DispatchMap stats
1001 UINT32 m_cDispatchMap; // Number of DispatchMaps created
1002 UINT32 m_cbDispatchMap; // Total size of created maps
1003 UINT32 m_cNGENDispatchMap;
1004 UINT32 m_cbNGENDispatchMap;
1006 // Some comparative stats with the old world (simulated)
1007 UINT32 m_cVTables; // Number of vtables out there
1008 UINT32 m_cVTableSlots; // Total number of slots.
1009 UINT32 m_cVTableDuplicateSlots; // Total number of duplicated slots
1011 UINT32 m_cCacheLookups;
1012 UINT32 m_cCacheMisses;
1014 UINT32 m_cbComInteropData;
1015 }; // struct StubDispatchStats
1017 extern StubDispatchStats g_sdStats;
1020 #endif // !CONTRACTIMPL_H_