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: methodtable.inl
12 // ============================================================================
14 #ifndef _METHODTABLE_INL_
15 #define _METHODTABLE_INL_
17 #include "methodtable.h"
18 #include "genericdict.h"
19 #include "threadstatics.h"
21 //==========================================================================================
22 inline PTR_EEClass MethodTable::GetClass_NoLogging()
24 LIMITED_METHOD_DAC_CONTRACT;
26 TADDR addr = ReadPointer(this, &MethodTable::m_pCanonMT);
29 LowBits lowBits = union_getLowBits(addr);
30 if (lowBits == UNION_EECLASS)
32 return PTR_EEClass(addr);
34 else if (lowBits == UNION_METHODTABLE)
36 // pointer to canonical MethodTable.
37 TADDR canonicalMethodTable = union_getPointer(addr);
38 return PTR_EEClass(ReadPointer((MethodTable *) PTR_MethodTable(canonicalMethodTable), &MethodTable::m_pCanonMT));
41 else if (lowBits == UNION_INDIRECTION)
43 // pointer to indirection cell that points to canonical MethodTable
44 TADDR canonicalMethodTable = *PTR_TADDR(union_getPointer(addr));
45 return PTR_EEClass(ReadPointer((MethodTable *) PTR_MethodTable(canonicalMethodTable), &MethodTable::m_pCanonMT));
48 #ifdef DACCESS_COMPILE
49 // Minidumps don't guarantee that every member of every class will be able to work here.
51 _ASSERTE(!"Malformed m_pEEClass in MethodTable");
60 return PTR_EEClass(addr);
66 // pointer to indirection cell that points to canonical MethodTable
67 TADDR canonicalMethodTable = *PTR_TADDR(addr - 3);
68 return PTR_EEClass(ReadPointer((MethodTable *) PTR_MethodTable(canonicalMethodTable), &MethodTable::m_pCanonMT));
72 // pointer to canonical MethodTable.
73 return PTR_EEClass(ReadPointer((MethodTable *) PTR_MethodTable(addr - 2), &MethodTable::m_pCanonMT));
77 //==========================================================================================
78 inline PTR_EEClass MethodTable::GetClass()
80 LIMITED_METHOD_DAC_CONTRACT;
82 _ASSERTE_IMPL(!IsAsyncPinType());
83 _ASSERTE_IMPL(GetClass_NoLogging() != NULL);
85 g_IBCLogger.LogEEClassAndMethodTableAccess(this);
86 return GetClass_NoLogging();
89 //==========================================================================================
90 inline Assembly * MethodTable::GetAssembly()
93 return GetModule()->GetAssembly();
96 //==========================================================================================
97 // DO NOT ADD ANY ASSERTS OR ANY OTHER CODE TO THIS METHOD.
98 // DO NOT USE THIS METHOD.
99 // Yes folks, for better or worse the debugger pokes supposed object addresses
100 // to try to see if objects are valid, possibly firing an AccessViolation or
101 // worse. Thus it is "correct" behaviour for this to AV, and incorrect
102 // behaviour for it to assert if called on an invalid pointer.
103 inline PTR_EEClass MethodTable::GetClassWithPossibleAV()
105 CANNOT_HAVE_CONTRACT;
107 return GetClass_NoLogging();
110 //==========================================================================================
111 inline BOOL MethodTable::IsClassPointerValid()
116 TADDR addr = ReadPointer(this, &MethodTable::m_pCanonMT);
118 LowBits lowBits = union_getLowBits(addr);
119 if (lowBits == UNION_EECLASS)
121 return !m_pEEClass.IsNull();
123 else if (lowBits == UNION_METHODTABLE)
125 // pointer to canonical MethodTable.
126 TADDR canonicalMethodTable = union_getPointer(addr);
127 return !PTR_MethodTable(canonicalMethodTable)->m_pEEClass.IsNull();
129 #ifdef FEATURE_PREJIT
130 else if (lowBits == UNION_INDIRECTION)
132 // pointer to indirection cell that points to canonical MethodTable
133 TADDR canonicalMethodTable = *PTR_TADDR(union_getPointer(addr));
134 if (CORCOMPILE_IS_POINTER_TAGGED(canonicalMethodTable))
136 return !PTR_MethodTable(canonicalMethodTable)->m_pEEClass.IsNull();
139 _ASSERTE(!"Malformed m_pEEClass in MethodTable");
143 //==========================================================================================
144 // Does this immediate item live in an NGEN module?
145 inline BOOL MethodTable::IsZapped()
147 LIMITED_METHOD_DAC_CONTRACT;
149 #ifdef FEATURE_PREJIT
150 return GetFlag(enum_flag_IsZapped);
156 //==========================================================================================
157 // For types that are part of an ngen-ed assembly this gets the
158 // Module* that contains this methodtable.
159 inline PTR_Module MethodTable::GetZapModule()
161 LIMITED_METHOD_DAC_CONTRACT;
163 PTR_Module zapModule = NULL;
166 zapModule = ReadPointer(this, &MethodTable::m_pLoaderModule);
172 //==========================================================================================
173 inline PTR_Module MethodTable::GetLoaderModule()
175 LIMITED_METHOD_DAC_CONTRACT;
176 return ReadPointer(this, &MethodTable::m_pLoaderModule);
179 inline PTR_LoaderAllocator MethodTable::GetLoaderAllocator()
181 LIMITED_METHOD_DAC_CONTRACT;
182 return GetLoaderModule()->GetLoaderAllocator();
187 #ifndef DACCESS_COMPILE
188 //==========================================================================================
189 inline void MethodTable::SetLoaderModule(Module* pModule)
192 m_pLoaderModule.SetValue(pModule);
195 inline void MethodTable::SetLoaderAllocator(LoaderAllocator* pAllocator)
197 LIMITED_METHOD_CONTRACT;
198 _ASSERTE(pAllocator == GetLoaderAllocator());
200 if (pAllocator->Id()->IsCollectible())
202 SetFlag(enum_flag_Collectible);
208 //==========================================================================================
209 inline WORD MethodTable::GetNumNonVirtualSlots()
211 LIMITED_METHOD_DAC_CONTRACT;
212 return HasNonVirtualSlots() ? GetClass()->GetNumNonVirtualSlots() : 0;
215 //==========================================================================================
216 inline WORD MethodTable::GetNumInstanceFields()
219 return (GetClass()->GetNumInstanceFields());
222 //==========================================================================================
223 inline WORD MethodTable::GetNumStaticFields()
225 LIMITED_METHOD_DAC_CONTRACT;
226 return (GetClass()->GetNumStaticFields());
229 //==========================================================================================
230 inline WORD MethodTable::GetNumThreadStaticFields()
232 LIMITED_METHOD_DAC_CONTRACT;
233 return (GetClass()->GetNumThreadStaticFields());
236 //==========================================================================================
237 inline DWORD MethodTable::GetNumInstanceFieldBytes()
239 LIMITED_METHOD_DAC_CONTRACT;
240 return(GetBaseSize() - GetClass()->GetBaseSizePadding());
243 //==========================================================================================
244 inline WORD MethodTable::GetNumIntroducedInstanceFields()
246 LIMITED_METHOD_DAC_CONTRACT;
248 WORD wNumFields = GetNumInstanceFields();
250 MethodTable * pParentMT = GetParentMethodTable();
251 if (pParentMT != NULL)
253 WORD wNumParentFields = pParentMT->GetNumInstanceFields();
255 // If this assert fires, then our bookkeeping is bad. Perhaps we incremented the count
256 // of fields on the base class w/o incrementing the count in the derived class. (EnC scenarios).
257 _ASSERTE(wNumFields >= wNumParentFields);
259 wNumFields -= wNumParentFields;
265 //==========================================================================================
266 inline DWORD MethodTable::GetAlignedNumInstanceFieldBytes()
269 return((GetNumInstanceFieldBytes() + 3) & (~3));
272 //==========================================================================================
273 inline PTR_FieldDesc MethodTable::GetApproxFieldDescListRaw()
276 // Careful about using this method. If it's possible that fields may have been added via EnC, then
277 // must use the FieldDescIterator as any fields added via EnC won't be in the raw list
279 return GetClass()->GetFieldDescList();
282 #ifdef FEATURE_COMINTEROP
283 //==========================================================================================
284 inline DWORD MethodTable::IsComClassInterface()
287 return GetClass()->IsComClassInterface();
290 //==========================================================================================
291 inline DWORD MethodTable::IsComImport()
294 return GetClass()->IsComImport();
297 //==========================================================================================
298 // Sparse VTables. These require a SparseVTableMap in the EEClass in
299 // order to record how the CLR's vtable slots map across to COM
302 inline int MethodTable::IsSparseForCOMInterop()
305 return GetClass()->IsSparseForCOMInterop();
308 //==========================================================================================
309 inline int MethodTable::IsComEventItfType()
312 _ASSERTE(GetClass());
313 return GetClass()->IsComEventItfType();
316 #endif // FEATURE_COMINTEROP
318 //==========================================================================================
319 inline DWORD MethodTable::GetAttrClass()
322 return GetClass()->GetAttrClass();
325 //==========================================================================================
326 inline BOOL MethodTable::IsSerializable()
329 return GetClass()->IsSerializable();
332 //==========================================================================================
333 inline BOOL MethodTable::SupportsGenericInterop(TypeHandle::InteropKind interopKind,
334 MethodTable::Mode mode /*= modeAll*/)
336 LIMITED_METHOD_CONTRACT;
338 #ifdef FEATURE_COMINTEROP
339 return ((IsInterface() || IsDelegate()) && // interface or delegate
340 HasInstantiation() && // generic
341 !IsSharedByGenericInstantiations() && // unshared
342 !ContainsGenericVariables() && // closed over concrete types
343 // defined in .winmd or one of the redirected mscorlib interfaces
344 ((((mode & modeProjected) != 0) && IsProjectedFromWinRT()) ||
345 (((mode & modeRedirected) != 0) && (IsWinRTRedirectedInterface(interopKind) || IsWinRTRedirectedDelegate()))));
346 #else // FEATURE_COMINTEROP
348 #endif // FEATURE_COMINTEROP
352 //==========================================================================================
353 inline BOOL MethodTable::IsNotTightlyPacked()
356 return GetClass()->IsNotTightlyPacked();
359 //==========================================================================================
360 inline BOOL MethodTable::HasFieldsWhichMustBeInited()
363 return GetClass()->HasFieldsWhichMustBeInited();
366 //==========================================================================================
367 inline BOOL MethodTable::SupportsAutoNGen()
369 LIMITED_METHOD_CONTRACT;
373 //==========================================================================================
374 inline BOOL MethodTable::RunCCTorAsIfNGenImageExists()
376 LIMITED_METHOD_CONTRACT;
377 #ifdef FEATURE_CORESYSTEM
378 return TRUE; // On our coresystem builds we will always be using triton in the customer scenario.
384 //==========================================================================================
385 inline BOOL MethodTable::IsAbstract()
388 return GetClass()->IsAbstract();
391 //==========================================================================================
393 #ifdef FEATURE_COMINTEROP
394 //==========================================================================================
395 inline void MethodTable::SetHasGuidInfo()
397 LIMITED_METHOD_CONTRACT;
398 _ASSERTE(IsInterface() || (HasCCWTemplate() && IsDelegate()));
400 // for delegates, having CCW template implies having GUID info
402 SetFlag(enum_flag_IfInterfaceThenHasGuidInfo);
405 //==========================================================================================
406 inline BOOL MethodTable::HasGuidInfo()
408 LIMITED_METHOD_DAC_CONTRACT;
411 return GetFlag(enum_flag_IfInterfaceThenHasGuidInfo);
413 // HasCCWTemplate() is intentionally checked first here to avoid hitting
414 // g_pMulticastDelegateClass == NULL inside IsDelegate() during startup
415 return HasCCWTemplate() && IsDelegate();
418 //==========================================================================================
419 // True IFF the type has a GUID explicitly assigned to it (including WinRT generic interfaces
420 // where the GUID is computed).
421 inline BOOL MethodTable::HasExplicitGuid()
431 GetGuid(&guid, FALSE);
432 return (guid != GUID_NULL);
435 //==========================================================================================
436 inline void MethodTable::SetHasCCWTemplate()
438 LIMITED_METHOD_CONTRACT;
439 SetFlag(enum_flag_HasCCWTemplate);
442 //==========================================================================================
443 inline BOOL MethodTable::HasCCWTemplate()
445 LIMITED_METHOD_DAC_CONTRACT;
446 return GetFlag(enum_flag_HasCCWTemplate);
449 //==========================================================================================
450 inline void MethodTable::SetHasRCWPerTypeData()
452 LIMITED_METHOD_CONTRACT;
453 SetFlag(enum_flag_HasRCWPerTypeData);
456 //==========================================================================================
457 inline BOOL MethodTable::HasRCWPerTypeData()
459 LIMITED_METHOD_DAC_CONTRACT;
460 return GetFlag(enum_flag_HasRCWPerTypeData);
463 //==========================================================================================
464 // Get the GUID used for WinRT interop
465 // * if the type is not a WinRT type or a redirected interfae return FALSE
466 inline BOOL MethodTable::GetGuidForWinRT(GUID *pGuid)
476 if ((IsProjectedFromWinRT() && !HasInstantiation()) ||
477 (SupportsGenericInterop(TypeHandle::Interop_NativeToManaged) && IsLegalNonArrayWinRTType()))
479 bRes = SUCCEEDED(GetGuidNoThrow(pGuid, TRUE, FALSE));
486 #endif // FEATURE_COMINTEROP
488 //==========================================================================================
489 // The following two methods produce correct results only if this type is
490 // marked Serializable (verified by assert in checked builds) and the field
491 // in question was introduced in this type (the index is the FieldDesc
493 inline BOOL MethodTable::IsFieldNotSerialized(DWORD dwFieldIndex)
495 LIMITED_METHOD_CONTRACT;
496 _ASSERTE(IsSerializable());
500 //==========================================================================================
501 inline BOOL MethodTable::IsFieldOptionallySerialized(DWORD dwFieldIndex)
503 LIMITED_METHOD_CONTRACT;
504 _ASSERTE(IsSerializable());
508 //==========================================================================================
509 // Is pParentMT System.Enum? (Cannot be called before System.Enum is loaded.)
510 inline BOOL MethodTable::IsEnum()
512 LIMITED_METHOD_DAC_CONTRACT;
514 // We should not be calling this before our parent method table pointer
516 _ASSERTE_IMPL(IsParentMethodTablePointerValid());
518 PTR_MethodTable pParentMT = GetParentMethodTable();
520 // Make sure that we are not using this method during startup
521 _ASSERTE(g_pEnumClass != NULL);
523 return (pParentMT == g_pEnumClass);
526 //==========================================================================================
527 // Is pParentMT either System.ValueType or System.Enum?
528 inline BOOL MethodTable::IsValueType()
530 LIMITED_METHOD_DAC_CONTRACT;
532 g_IBCLogger.LogMethodTableAccess(this);
534 return GetFlag(enum_flag_Category_ValueType_Mask) == enum_flag_Category_ValueType;
537 //==========================================================================================
538 inline CorElementType MethodTable::GetArrayElementType()
542 _ASSERTE (IsArray());
543 return dac_cast<PTR_ArrayClass>(GetClass())->GetArrayElementType();
546 //==========================================================================================
547 inline DWORD MethodTable::GetRank()
549 LIMITED_METHOD_DAC_CONTRACT;
551 _ASSERTE (IsArray());
552 if (GetFlag(enum_flag_Category_IfArrayThenSzArray))
553 return 1; // ELEMENT_TYPE_SZARRAY
555 return dac_cast<PTR_ArrayClass>(GetClass())->GetRank();
558 //==========================================================================================
559 inline BOOL MethodTable::IsTruePrimitive()
561 LIMITED_METHOD_DAC_CONTRACT;
562 return GetFlag(enum_flag_Category_Mask) == enum_flag_Category_TruePrimitive;
565 //==========================================================================================
566 inline void MethodTable::SetIsTruePrimitive()
568 LIMITED_METHOD_DAC_CONTRACT;
569 SetFlag(enum_flag_Category_TruePrimitive);
572 //==========================================================================================
573 inline BOOL MethodTable::IsBlittable()
576 #ifndef DACCESS_COMPILE
577 _ASSERTE(GetClass());
578 return GetClass()->IsBlittable();
579 #else // DACCESS_COMPILE
582 #endif // DACCESS_COMPILE
585 //==========================================================================================
586 inline BOOL MethodTable::HasClassConstructor()
589 return GetFlag(enum_flag_HasCctor);
592 //==========================================================================================
593 inline void MethodTable::SetHasClassConstructor()
596 return SetFlag(enum_flag_HasCctor);
599 //==========================================================================================
600 inline WORD MethodTable::GetClassConstructorSlot()
603 _ASSERTE(HasClassConstructor());
605 // The class constructor slot is the first non-vtable slot
606 return GetNumVirtuals();
609 //==========================================================================================
610 inline BOOL MethodTable::HasDefaultConstructor()
613 return GetFlag(enum_flag_HasDefaultCtor);
616 //==========================================================================================
617 inline void MethodTable::SetHasDefaultConstructor()
620 return SetFlag(enum_flag_HasDefaultCtor);
623 //==========================================================================================
624 inline WORD MethodTable::GetDefaultConstructorSlot()
627 _ASSERTE(HasDefaultConstructor());
629 // The default ctor slot is right after cctor slot if there is one
630 return GetNumVirtuals() + (HasClassConstructor() ? 1 : 0);
633 //==========================================================================================
634 inline BOOL MethodTable::HasLayout()
637 _ASSERTE(GetClass());
638 return GetClass()->HasLayout();
641 //==========================================================================================
642 inline MethodDesc* MethodTable::GetMethodDescForSlot(DWORD slot)
653 PCODE pCode = GetRestoredSlot(slot);
655 // This is an optimization that we can take advantage of if we're trying to get the MethodDesc
656 // for an interface virtual, since their slots usually point to stub.
657 if (IsInterface() && slot < GetNumVirtuals())
659 return MethodDesc::GetMethodDescFromStubAddr(pCode);
662 return MethodTable::GetMethodDescForSlotAddress(pCode);
665 #ifndef DACCESS_COMPILE
667 //==========================================================================================
668 inline INT32 MethodTable::MethodIterator::GetNumMethods() const
670 LIMITED_METHOD_CONTRACT;
671 // assert that number of methods hasn't changed during the iteration
672 CONSISTENCY_CHECK( m_pMethodData->GetNumMethods() == static_cast< UINT32 >( m_iMethods ) );
676 //==========================================================================================
677 // Returns TRUE if it's valid to request data from the current position
678 inline BOOL MethodTable::MethodIterator::IsValid() const
680 LIMITED_METHOD_CONTRACT;
681 return m_iCur >= 0 && m_iCur < GetNumMethods();
684 //==========================================================================================
685 inline BOOL MethodTable::MethodIterator::MoveTo(UINT32 idx)
687 LIMITED_METHOD_CONTRACT;
692 //==========================================================================================
693 inline BOOL MethodTable::MethodIterator::Prev()
701 //==========================================================================================
702 inline BOOL MethodTable::MethodIterator::Next()
710 //==========================================================================================
711 inline void MethodTable::MethodIterator::MoveToBegin()
717 //==========================================================================================
718 inline void MethodTable::MethodIterator::MoveToEnd()
721 m_iCur = GetNumMethods() - 1;
724 //==========================================================================================
725 inline UINT32 MethodTable::MethodIterator::GetSlotNumber() const {
726 LIMITED_METHOD_CONTRACT;
727 CONSISTENCY_CHECK(IsValid());
728 return (UINT32)m_iCur;
731 //==========================================================================================
732 inline UINT32 MethodTable::MethodIterator::GetImplSlotNumber() const {
734 CONSISTENCY_CHECK(IsValid());
735 return (UINT32)m_pMethodData->GetImplSlotNumber(m_iCur);
738 //==========================================================================================
739 inline BOOL MethodTable::MethodIterator::IsVirtual() const {
740 LIMITED_METHOD_CONTRACT;
741 CONSISTENCY_CHECK(IsValid());
742 return m_iCur < (INT32)(GetNumVirtuals());
745 //==========================================================================================
746 inline UINT32 MethodTable::MethodIterator::GetNumVirtuals() const {
747 LIMITED_METHOD_CONTRACT;
748 return m_pMethodData->GetNumVirtuals();;
751 //==========================================================================================
752 inline DispatchSlot MethodTable::MethodIterator::GetTarget() const {
753 LIMITED_METHOD_CONTRACT;
754 CONSISTENCY_CHECK(IsValid());
755 return m_pMethodData->GetImplSlot(m_iCur);
758 //==========================================================================================
759 inline MethodDesc *MethodTable::MethodIterator::GetMethodDesc() const {
760 LIMITED_METHOD_CONTRACT;
761 CONSISTENCY_CHECK(IsValid());
762 MethodDesc *pMD = m_pMethodData->GetImplMethodDesc(m_iCur);
763 CONSISTENCY_CHECK(CheckPointer(pMD));
767 //==========================================================================================
768 inline MethodDesc *MethodTable::MethodIterator::GetDeclMethodDesc() const {
769 LIMITED_METHOD_CONTRACT;
770 CONSISTENCY_CHECK(IsValid());
771 MethodDesc *pMD = m_pMethodData->GetDeclMethodDesc(m_iCur);
772 CONSISTENCY_CHECK(CheckPointer(pMD));
773 CONSISTENCY_CHECK(pMD->GetSlot() == GetSlotNumber());
777 #endif // DACCESS_COMPILE
779 //==========================================================================================
780 // Non-canonical types share the method bodies with the canonical type. So the canonical
781 // type can be said to own the method bodies. Hence, by default, IntroducedMethodIterator
782 // only lets you iterate methods of the canonical type. You have to pass in
783 // restrictToCanonicalTypes=FALSE to iterate methods through a non-canonical type.
785 inline MethodTable::IntroducedMethodIterator::IntroducedMethodIterator(
787 BOOL restrictToCanonicalTypes /* = TRUE */ )
790 CONSISTENCY_CHECK(pMT->IsCanonicalMethodTable() || !restrictToCanonicalTypes);
792 SetChunk(pMT->GetClass()->GetChunks());
795 //==========================================================================================
796 FORCEINLINE BOOL MethodTable::IntroducedMethodIterator::Next()
799 CONSISTENCY_CHECK(IsValid());
801 // Check whether the next MethodDesc is still within the bounds of the current chunk
802 TADDR pNext = dac_cast<TADDR>(m_pMethodDesc) + m_pMethodDesc->SizeOf();
804 if (pNext < m_pChunkEnd)
806 // Just skip to the next method in the same chunk
807 m_pMethodDesc = PTR_MethodDesc(pNext);
811 _ASSERTE(pNext == m_pChunkEnd);
813 // We have walked all the methods in the current chunk. Move on
814 // to the next chunk.
815 SetChunk(m_pChunk->GetNextChunk());
821 //==========================================================================================
822 inline BOOL MethodTable::IntroducedMethodIterator::IsValid() const
824 LIMITED_METHOD_CONTRACT;
825 return m_pMethodDesc != NULL;
828 //==========================================================================================
829 inline MethodDesc * MethodTable::IntroducedMethodIterator::GetMethodDesc() const
832 CONSISTENCY_CHECK(IsValid());
833 return m_pMethodDesc;
836 //==========================================================================================
837 inline DWORD MethodTable::GetIndexOfVtableIndirection(DWORD slotNum)
839 LIMITED_METHOD_DAC_CONTRACT;
840 _ASSERTE((1 << VTABLE_SLOTS_PER_CHUNK_LOG2) == VTABLE_SLOTS_PER_CHUNK);
842 return slotNum >> VTABLE_SLOTS_PER_CHUNK_LOG2;
845 //==========================================================================================
846 inline DWORD MethodTable::GetStartSlotForVtableIndirection(UINT32 indirectionIndex, DWORD wNumVirtuals)
848 LIMITED_METHOD_DAC_CONTRACT;
849 _ASSERTE(indirectionIndex < GetNumVtableIndirections(wNumVirtuals));
851 return indirectionIndex * VTABLE_SLOTS_PER_CHUNK;
854 //==========================================================================================
855 inline DWORD MethodTable::GetEndSlotForVtableIndirection(UINT32 indirectionIndex, DWORD wNumVirtuals)
857 LIMITED_METHOD_DAC_CONTRACT;
858 _ASSERTE(indirectionIndex < GetNumVtableIndirections(wNumVirtuals));
860 DWORD end = (indirectionIndex + 1) * VTABLE_SLOTS_PER_CHUNK;
862 if (end > wNumVirtuals)
870 //==========================================================================================
871 inline UINT32 MethodTable::GetIndexAfterVtableIndirection(UINT32 slotNum)
873 LIMITED_METHOD_DAC_CONTRACT;
874 _ASSERTE((1 << VTABLE_SLOTS_PER_CHUNK_LOG2) == VTABLE_SLOTS_PER_CHUNK);
876 return (slotNum & (VTABLE_SLOTS_PER_CHUNK - 1));
879 //==========================================================================================
880 inline DWORD MethodTable::GetNumVtableIndirections(DWORD wNumVirtuals)
882 LIMITED_METHOD_DAC_CONTRACT;
883 _ASSERTE((1 << VTABLE_SLOTS_PER_CHUNK_LOG2) == VTABLE_SLOTS_PER_CHUNK);
885 return (wNumVirtuals + (VTABLE_SLOTS_PER_CHUNK - 1)) >> VTABLE_SLOTS_PER_CHUNK_LOG2;
888 //==========================================================================================
889 inline DPTR(MethodTable::VTableIndir_t) MethodTable::GetVtableIndirections()
891 LIMITED_METHOD_DAC_CONTRACT;
892 return dac_cast<DPTR(VTableIndir_t)>(dac_cast<TADDR>(this) + sizeof(MethodTable));
895 //==========================================================================================
896 inline DWORD MethodTable::GetNumVtableIndirections()
900 return GetNumVtableIndirections(GetNumVirtuals_NoLogging());
903 //==========================================================================================
904 inline MethodTable::VtableIndirectionSlotIterator::VtableIndirectionSlotIterator(MethodTable *pMT)
905 : m_pSlot(pMT->GetVtableIndirections()),
907 m_count(pMT->GetNumVtableIndirections()),
913 //==========================================================================================
914 inline MethodTable::VtableIndirectionSlotIterator::VtableIndirectionSlotIterator(MethodTable *pMT, DWORD index)
915 : m_pSlot(pMT->GetVtableIndirections() + index),
917 m_count(pMT->GetNumVtableIndirections()),
921 PRECONDITION(index != (DWORD) -1 && index < m_count);
924 //==========================================================================================
925 inline BOOL MethodTable::VtableIndirectionSlotIterator::Next()
927 LIMITED_METHOD_DAC_CONTRACT;
928 PRECONDITION(!Finished());
929 if (m_i != (DWORD) -1)
931 return (++m_i < m_count);
934 //==========================================================================================
935 inline BOOL MethodTable::VtableIndirectionSlotIterator::Finished()
937 LIMITED_METHOD_DAC_CONTRACT;
938 return (m_i == m_count);
941 //==========================================================================================
942 inline DWORD MethodTable::VtableIndirectionSlotIterator::GetIndex()
944 LIMITED_METHOD_DAC_CONTRACT;
948 //==========================================================================================
949 inline DWORD MethodTable::VtableIndirectionSlotIterator::GetOffsetFromMethodTable()
952 PRECONDITION(m_i != (DWORD) -1 && m_i < m_count);
954 return GetVtableOffset() + sizeof(VTableIndir_t) * m_i;
957 //==========================================================================================
958 inline DPTR(MethodTable::VTableIndir2_t) MethodTable::VtableIndirectionSlotIterator::GetIndirectionSlot()
960 LIMITED_METHOD_DAC_CONTRACT;
961 PRECONDITION(m_i != (DWORD) -1 && m_i < m_count);
963 return m_pSlot->GetValueMaybeNull(dac_cast<TADDR>(m_pSlot));
966 //==========================================================================================
967 #ifndef DACCESS_COMPILE
968 inline void MethodTable::VtableIndirectionSlotIterator::SetIndirectionSlot(DPTR(MethodTable::VTableIndir2_t) pChunk)
970 LIMITED_METHOD_CONTRACT;
971 m_pSlot->SetValueMaybeNull(pChunk);
975 //==========================================================================================
976 inline DWORD MethodTable::VtableIndirectionSlotIterator::GetStartSlot()
979 PRECONDITION(m_i != (DWORD) -1 && m_i < m_count);
981 return GetStartSlotForVtableIndirection(m_i, m_pMT->GetNumVirtuals());
984 //==========================================================================================
985 inline DWORD MethodTable::VtableIndirectionSlotIterator::GetEndSlot()
988 PRECONDITION(m_i != (DWORD) -1 && m_i < m_count);
990 return GetEndSlotForVtableIndirection(m_i, m_pMT->GetNumVirtuals());
993 //==========================================================================================
994 inline DWORD MethodTable::VtableIndirectionSlotIterator::GetNumSlots()
998 return GetEndSlot() - GetStartSlot();
1001 //==========================================================================================
1002 inline DWORD MethodTable::VtableIndirectionSlotIterator::GetSize()
1004 WRAPPER_NO_CONTRACT;
1006 return GetNumSlots() * sizeof(PCODE);
1009 //==========================================================================================
1010 // Create a new iterator over the vtable indirection slots
1011 // The iterator starts just before the first item
1012 inline MethodTable::VtableIndirectionSlotIterator MethodTable::IterateVtableIndirectionSlots()
1014 WRAPPER_NO_CONTRACT;
1015 return VtableIndirectionSlotIterator(this);
1018 //==========================================================================================
1019 // Create a new iterator over the vtable indirection slots, starting at the index specified
1020 inline MethodTable::VtableIndirectionSlotIterator MethodTable::IterateVtableIndirectionSlotsFrom(DWORD index)
1022 WRAPPER_NO_CONTRACT;
1023 return VtableIndirectionSlotIterator(this, index);
1026 #ifndef DACCESS_COMPILE
1027 #ifdef FEATURE_COMINTEROP
1029 //==========================================================================================
1030 inline ComCallWrapperTemplate *MethodTable::GetComCallWrapperTemplate()
1032 LIMITED_METHOD_CONTRACT;
1033 if (HasCCWTemplate())
1035 return *GetCCWTemplatePtr();
1037 return GetClass()->GetComCallWrapperTemplate();
1040 //==========================================================================================
1041 inline BOOL MethodTable::SetComCallWrapperTemplate(ComCallWrapperTemplate *pTemplate)
1051 if (HasCCWTemplate())
1053 TypeHandle th(this);
1054 g_IBCLogger.LogTypeMethodTableWriteableAccess(&th);
1055 return (InterlockedCompareExchangeT(EnsureWritablePages(GetCCWTemplatePtr()), pTemplate, NULL) == NULL);
1057 g_IBCLogger.LogEEClassCOWTableAccess(this);
1058 return GetClass_NoLogging()->SetComCallWrapperTemplate(pTemplate);
1061 #ifdef FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
1062 //==========================================================================================
1063 inline ClassFactoryBase *MethodTable::GetComClassFactory()
1065 LIMITED_METHOD_CONTRACT;
1066 return GetClass()->GetComClassFactory();
1069 //==========================================================================================
1070 inline BOOL MethodTable::SetComClassFactory(ClassFactoryBase *pFactory)
1080 g_IBCLogger.LogEEClassCOWTableAccess(this);
1081 return GetClass_NoLogging()->SetComClassFactory(pFactory);
1083 #endif // FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
1084 #endif // FEATURE_COMINTEROP
1085 #endif // DACCESS_COMPILE
1087 #ifdef FEATURE_COMINTEROP
1088 //==========================================================================================
1089 inline BOOL MethodTable::IsProjectedFromWinRT()
1091 LIMITED_METHOD_DAC_CONTRACT;
1092 _ASSERTE(GetClass());
1093 return GetClass()->IsProjectedFromWinRT();
1096 //==========================================================================================
1097 inline BOOL MethodTable::IsExportedToWinRT()
1099 LIMITED_METHOD_DAC_CONTRACT;
1100 _ASSERTE(GetClass());
1101 return GetClass()->IsExportedToWinRT();
1104 //==========================================================================================
1105 inline BOOL MethodTable::IsWinRTDelegate()
1107 LIMITED_METHOD_DAC_CONTRACT;
1108 return (IsProjectedFromWinRT() && IsDelegate()) || IsWinRTRedirectedDelegate();
1111 #else // FEATURE_COMINTEROP
1113 //==========================================================================================
1114 inline BOOL MethodTable::IsProjectedFromWinRT()
1116 LIMITED_METHOD_DAC_CONTRACT;
1120 //==========================================================================================
1121 inline BOOL MethodTable::IsExportedToWinRT()
1123 LIMITED_METHOD_DAC_CONTRACT;
1127 //==========================================================================================
1128 inline BOOL MethodTable::IsWinRTDelegate()
1130 LIMITED_METHOD_DAC_CONTRACT;
1134 #endif // FEATURE_COMINTEROP
1136 //==========================================================================================
1137 inline UINT32 MethodTable::GetNativeSize()
1139 LIMITED_METHOD_CONTRACT;
1140 _ASSERTE(GetClass());
1141 return GetClass()->GetNativeSize();
1144 //==========================================================================================
1145 inline PTR_MethodTable MethodTable::GetCanonicalMethodTable()
1147 LIMITED_METHOD_DAC_CONTRACT;
1149 TADDR addr = ReadPointer(this, &MethodTable::m_pCanonMT);
1152 LowBits lowBits = union_getLowBits(addr);
1153 if (lowBits == UNION_EECLASS)
1155 return dac_cast<PTR_MethodTable>(this);
1157 else if (lowBits == UNION_METHODTABLE)
1159 // pointer to canonical MethodTable.
1160 return PTR_MethodTable(union_getPointer(addr));
1162 #ifdef FEATURE_PREJIT
1163 else if (lowBits == UNION_INDIRECTION)
1165 return PTR_MethodTable(*PTR_TADDR(union_getPointer(addr)));
1168 _ASSERTE(!"Malformed m_pCanonMT in MethodTable");
1172 if ((addr & 2) == 0)
1173 return dac_cast<PTR_MethodTable>(this);
1175 #ifdef FEATURE_PREJIT
1176 if ((addr & 1) != 0)
1177 return PTR_MethodTable(*PTR_TADDR(addr - 3));
1180 return PTR_MethodTable(addr - 2);
1184 //==========================================================================================
1185 inline TADDR MethodTable::GetCanonicalMethodTableFixup()
1187 LIMITED_METHOD_DAC_CONTRACT;
1189 #ifdef FEATURE_PREJIT
1190 TADDR addr = ReadPointer(this, &MethodTable::m_pCanonMT);
1191 LowBits lowBits = union_getLowBits(addr);
1192 if (lowBits == UNION_INDIRECTION)
1194 // pointer to canonical MethodTable.
1195 return *PTR_TADDR(union_getPointer(addr));
1204 //==========================================================================================
1205 #ifndef DACCESS_COMPILE
1206 FORCEINLINE BOOL MethodTable::IsEquivalentTo(MethodTable *pOtherMT COMMA_INDEBUG(TypeHandlePairList *pVisited /*= NULL*/))
1208 WRAPPER_NO_CONTRACT;
1210 if (this == pOtherMT)
1213 #ifdef FEATURE_TYPEEQUIVALENCE
1214 // bail early for normal types
1215 if (!HasTypeEquivalence() || !pOtherMT->HasTypeEquivalence())
1218 if (IsEquivalentTo_Worker(pOtherMT COMMA_INDEBUG(pVisited)))
1220 #endif // FEATURE_TYPEEQUIVALENCE
1226 //==========================================================================================
1227 inline IMDInternalImport* MethodTable::GetMDImport()
1229 LIMITED_METHOD_CONTRACT;
1230 return GetModule()->GetMDImport();
1233 //==========================================================================================
1234 inline BOOL MethodTable::IsSealed()
1236 LIMITED_METHOD_CONTRACT;
1237 return GetClass()->IsSealed();
1240 //==========================================================================================
1241 inline BOOL MethodTable::IsManagedSequential()
1243 LIMITED_METHOD_CONTRACT;
1244 return GetClass()->IsManagedSequential();
1247 //==========================================================================================
1248 inline BOOL MethodTable::HasExplicitSize()
1250 LIMITED_METHOD_CONTRACT;
1251 return GetClass()->HasExplicitSize();
1254 //==========================================================================================
1255 inline DWORD MethodTable::GetPerInstInfoSize()
1257 LIMITED_METHOD_DAC_CONTRACT;
1258 return GetNumDicts() * sizeof(PerInstInfoElem_t);
1261 //==========================================================================================
1262 inline EEClassLayoutInfo *MethodTable::GetLayoutInfo()
1264 LIMITED_METHOD_CONTRACT;
1265 PRECONDITION(HasLayout());
1266 return GetClass()->GetLayoutInfo();
1269 //==========================================================================================
1270 // These come after the pointers to the generic dictionaries (if any)
1271 inline DWORD MethodTable::GetInterfaceMapSize()
1273 LIMITED_METHOD_DAC_CONTRACT;
1275 DWORD cbIMap = GetNumInterfaces() * sizeof(InterfaceInfo_t);
1276 #ifdef FEATURE_COMINTEROP
1277 cbIMap += (HasDynamicInterfaceMap() ? sizeof(DWORD_PTR) : 0);
1282 //==========================================================================================
1283 // These are the generic dictionaries themselves and are come after
1284 // the interface map. In principle they need not be inline in the method table.
1285 inline DWORD MethodTable::GetInstAndDictSize()
1287 LIMITED_METHOD_DAC_CONTRACT;
1289 if (!HasInstantiation())
1292 return DictionaryLayout::GetFirstDictionaryBucketSize(GetNumGenericArgs(), GetClass()->GetDictionaryLayout());
1295 //==========================================================================================
1296 inline BOOL MethodTable::IsSharedByGenericInstantiations()
1298 LIMITED_METHOD_DAC_CONTRACT;
1300 g_IBCLogger.LogMethodTableAccess(this);
1302 return TestFlagWithMask(enum_flag_GenericsMask, enum_flag_GenericsMask_SharedInst);
1305 //==========================================================================================
1306 inline BOOL MethodTable::IsCanonicalMethodTable()
1308 LIMITED_METHOD_DAC_CONTRACT;
1310 return (union_getLowBits(ReadPointer(this, &MethodTable::m_pCanonMT)) == UNION_EECLASS);
1313 //==========================================================================================
1314 FORCEINLINE BOOL MethodTable::HasInstantiation()
1316 LIMITED_METHOD_DAC_CONTRACT;
1318 // Generics flags cannot be expressed in terms of GetFlag()
1319 return !TestFlagWithMask(enum_flag_GenericsMask, enum_flag_GenericsMask_NonGeneric);
1322 //==========================================================================================
1323 inline void MethodTable::SetHasInstantiation(BOOL fTypicalInstantiation, BOOL fSharedByGenericInstantiations)
1325 LIMITED_METHOD_CONTRACT;
1326 _ASSERTE(!IsStringOrArray());
1327 SetFlag(fTypicalInstantiation ? enum_flag_GenericsMask_TypicalInst :
1328 (fSharedByGenericInstantiations ? enum_flag_GenericsMask_SharedInst : enum_flag_GenericsMask_GenericInst));
1330 //==========================================================================================
1331 inline BOOL MethodTable::IsGenericTypeDefinition()
1333 LIMITED_METHOD_DAC_CONTRACT;
1335 // Generics flags cannot be expressed in terms of GetFlag()
1336 return TestFlagWithMask(enum_flag_GenericsMask, enum_flag_GenericsMask_TypicalInst);
1339 //==========================================================================================
1340 inline PTR_InterfaceInfo MethodTable::GetInterfaceMap()
1342 LIMITED_METHOD_DAC_CONTRACT;
1344 return ReadPointer(this, &MethodTable::m_pInterfaceMap);
1347 //==========================================================================================
1348 FORCEINLINE TADDR MethodTable::GetMultipurposeSlotPtr(WFLAGS2_ENUM flag, const BYTE * offsets)
1350 LIMITED_METHOD_DAC_CONTRACT;
1352 _ASSERTE(GetFlag(flag));
1354 DWORD offset = offsets[GetFlag((WFLAGS2_ENUM)(flag - 1))];
1356 if (offset >= sizeof(MethodTable)) {
1357 offset += GetNumVtableIndirections() * sizeof(VTableIndir_t);
1360 return dac_cast<TADDR>(this) + offset;
1363 //==========================================================================================
1364 // This method is dependent on the declared order of optional members
1365 // If you add or remove an optional member or reorder them please change this method
1366 FORCEINLINE DWORD MethodTable::GetOffsetOfOptionalMember(OptionalMemberId id)
1368 LIMITED_METHOD_CONTRACT;
1370 DWORD offset = c_OptionalMembersStartOffsets[GetFlag(enum_flag_MultipurposeSlotsMask)];
1372 offset += GetNumVtableIndirections() * sizeof(VTableIndir_t);
1374 #undef METHODTABLE_OPTIONAL_MEMBER
1375 #define METHODTABLE_OPTIONAL_MEMBER(NAME, TYPE, GETTER) \
1376 if (id == OptionalMember_##NAME) { \
1379 C_ASSERT(sizeof(TYPE) % sizeof(UINT_PTR) == 0); /* To insure proper alignment */ \
1380 if (Has##NAME()) { \
1381 offset += sizeof(TYPE); \
1384 METHODTABLE_OPTIONAL_MEMBERS()
1386 _ASSERTE(!"Wrong optional member" || id == OptionalMember_Count);
1390 //==========================================================================================
1391 // this is not the pretties function however I got bitten pretty hard by the computation
1392 // of the allocation size of a MethodTable done "by hand" in few places.
1393 // Essentially the idea is that this is going to centralize computation of size for optional
1394 // members so the next morons that need to add an optional member will look at this function
1395 // and hopefully be less exposed to code doing size computation behind their back
1396 inline DWORD MethodTable::GetOptionalMembersAllocationSize(DWORD dwMultipurposeSlotsMask,
1397 BOOL needsRemotableMethodInfo,
1398 BOOL needsGenericsStaticsInfo,
1400 BOOL needsCCWTemplate,
1401 BOOL needsRCWPerTypeData,
1402 BOOL needsRemotingVtsInfo,
1403 BOOL needsContextStatic,
1404 BOOL needsTokenOverflow)
1406 LIMITED_METHOD_CONTRACT;
1408 DWORD size = c_OptionalMembersStartOffsets[dwMultipurposeSlotsMask] - sizeof(MethodTable);
1410 if (needsRemotableMethodInfo)
1411 size += sizeof(UINT_PTR);
1412 if (needsGenericsStaticsInfo)
1413 size += sizeof(GenericsStaticsInfo);
1415 size += sizeof(UINT_PTR);
1416 if (needsCCWTemplate)
1417 size += sizeof(UINT_PTR);
1418 if (needsRCWPerTypeData)
1419 size += sizeof(UINT_PTR);
1420 if (needsRemotingVtsInfo)
1421 size += sizeof(UINT_PTR);
1422 if (needsContextStatic)
1423 size += sizeof(UINT_PTR);
1424 if (dwMultipurposeSlotsMask & enum_flag_HasInterfaceMap)
1425 size += sizeof(UINT_PTR);
1426 if (needsTokenOverflow)
1427 size += sizeof(UINT_PTR);
1432 inline DWORD MethodTable::GetOptionalMembersSize()
1434 WRAPPER_NO_CONTRACT;
1436 return GetEndOffsetOfOptionalMembers() - GetStartOffsetOfOptionalMembers();
1439 #ifndef DACCESS_COMPILE
1441 //==========================================================================================
1442 inline PTR_BYTE MethodTable::GetNonGCStaticsBasePointer()
1444 WRAPPER_NO_CONTRACT;
1445 return GetDomainLocalModule()->GetNonGCStaticsBasePointer(this);
1448 //==========================================================================================
1449 inline PTR_BYTE MethodTable::GetGCStaticsBasePointer()
1451 WRAPPER_NO_CONTRACT;
1452 return GetDomainLocalModule()->GetGCStaticsBasePointer(this);
1455 //==========================================================================================
1456 inline PTR_BYTE MethodTable::GetNonGCThreadStaticsBasePointer()
1466 // Get the current thread
1467 PTR_Thread pThread = dac_cast<PTR_Thread>(GetThread());
1469 // Get the current module's ModuleIndex
1470 ModuleIndex index = GetModuleForStatics()->GetModuleIndex();
1472 PTR_ThreadLocalBlock pTLB = ThreadStatics::GetCurrentTLBIfExists(pThread, NULL);
1476 PTR_ThreadLocalModule pTLM = pTLB->GetTLMIfExists(index);
1480 return pTLM->GetNonGCStaticsBasePointer(this);
1483 //==========================================================================================
1484 inline PTR_BYTE MethodTable::GetGCThreadStaticsBasePointer()
1494 // Get the current thread
1495 PTR_Thread pThread = dac_cast<PTR_Thread>(GetThread());
1497 // Get the current module's ModuleIndex
1498 ModuleIndex index = GetModuleForStatics()->GetModuleIndex();
1500 PTR_ThreadLocalBlock pTLB = ThreadStatics::GetCurrentTLBIfExists(pThread, NULL);
1504 PTR_ThreadLocalModule pTLM = pTLB->GetTLMIfExists(index);
1508 return pTLM->GetGCStaticsBasePointer(this);
1511 #endif //!DACCESS_COMPILE
1513 //==========================================================================================
1514 inline PTR_BYTE MethodTable::GetNonGCThreadStaticsBasePointer(PTR_Thread pThread, PTR_AppDomain pDomain)
1516 LIMITED_METHOD_DAC_CONTRACT;
1518 // Get the current module's ModuleIndex
1519 ModuleIndex index = GetModuleForStatics()->GetModuleIndex();
1521 PTR_ThreadLocalBlock pTLB = ThreadStatics::GetCurrentTLBIfExists(pThread, pDomain);
1525 PTR_ThreadLocalModule pTLM = pTLB->GetTLMIfExists(index);
1529 return pTLM->GetNonGCStaticsBasePointer(this);
1532 //==========================================================================================
1533 inline PTR_BYTE MethodTable::GetGCThreadStaticsBasePointer(PTR_Thread pThread, PTR_AppDomain pDomain)
1535 LIMITED_METHOD_DAC_CONTRACT;
1537 // Get the current module's ModuleIndex
1538 ModuleIndex index = GetModuleForStatics()->GetModuleIndex();
1540 PTR_ThreadLocalBlock pTLB = ThreadStatics::GetCurrentTLBIfExists(pThread, pDomain);
1544 PTR_ThreadLocalModule pTLM = pTLB->GetTLMIfExists(index);
1548 return pTLM->GetGCStaticsBasePointer(this);
1551 //==========================================================================================
1552 inline PTR_DomainLocalModule MethodTable::GetDomainLocalModule(AppDomain * pAppDomain)
1554 WRAPPER_NO_CONTRACT;
1555 return GetModuleForStatics()->GetDomainLocalModule(pAppDomain);
1558 #ifndef DACCESS_COMPILE
1559 //==========================================================================================
1560 inline PTR_DomainLocalModule MethodTable::GetDomainLocalModule()
1562 WRAPPER_NO_CONTRACT;
1563 return GetModuleForStatics()->GetDomainLocalModule();
1565 #endif //!DACCESS_COMPILE
1567 //==========================================================================================
1568 inline OBJECTREF MethodTable::AllocateNoChecks()
1578 // we know an instance of this class already exists in the same appdomain
1579 // therefore, some checks become redundant.
1580 // this currently only happens for Delegate.Combine
1581 CONSISTENCY_CHECK(IsRestored_NoLogging());
1583 CONSISTENCY_CHECK(CheckInstanceActivated());
1585 return AllocateObject(this);
1589 //==========================================================================================
1590 inline DWORD MethodTable::GetClassIndex()
1592 WRAPPER_NO_CONTRACT;
1593 return GetClassIndexFromToken(GetCl());
1596 #ifndef DACCESS_COMPILE
1597 //==========================================================================================
1598 // unbox src into dest, making sure src is of the correct type.
1600 inline BOOL MethodTable::UnBoxInto(void *dest, OBJECTREF src)
1611 if (Nullable::IsNullableType(TypeHandle(this)))
1612 return Nullable::UnBoxNoGC(dest, src, this);
1615 if (src == NULL || src->GetMethodTable() != this)
1618 CopyValueClass(dest, src->UnBox(), this, src->GetAppDomain());
1623 //==========================================================================================
1624 // unbox src into argument, making sure src is of the correct type.
1626 inline BOOL MethodTable::UnBoxIntoArg(ArgDestination *argDest, OBJECTREF src)
1637 if (Nullable::IsNullableType(TypeHandle(this)))
1638 return Nullable::UnBoxIntoArgNoGC(argDest, src, this);
1641 if (src == NULL || src->GetMethodTable() != this)
1644 CopyValueClassArg(argDest, src->UnBox(), this, src->GetAppDomain(), 0);
1649 //==========================================================================================
1650 // unbox src into dest, No checks are done
1652 inline void MethodTable::UnBoxIntoUnchecked(void *dest, OBJECTREF src)
1663 if (Nullable::IsNullableType(TypeHandle(this))) {
1665 ret = Nullable::UnBoxNoGC(dest, src, this);
1670 _ASSERTE(src->GetMethodTable()->GetNumInstanceFieldBytes() == GetNumInstanceFieldBytes());
1672 CopyValueClass(dest, src->UnBox(), this, src->GetAppDomain());
1676 //==========================================================================================
1677 __forceinline TypeHandle::CastResult MethodTable::CanCastToClassOrInterfaceNoGC(MethodTable *pTargetMT)
1686 PRECONDITION(CheckPointer(pTargetMT));
1687 PRECONDITION(!pTargetMT->IsArray());
1691 if (pTargetMT->IsInterface())
1692 return CanCastToInterfaceNoGC(pTargetMT);
1694 return CanCastToClassNoGC(pTargetMT);
1697 //==========================================================================================
1698 inline BOOL MethodTable::CanCastToClassOrInterface(MethodTable *pTargetMT, TypeHandlePairList *pVisited)
1706 PRECONDITION(CheckPointer(pTargetMT));
1707 PRECONDITION(!pTargetMT->IsArray());
1708 PRECONDITION(IsRestored_NoLogging());
1712 if (pTargetMT->IsInterface())
1713 return CanCastToInterface(pTargetMT, pVisited);
1715 return CanCastToClass(pTargetMT, pVisited);
1718 //==========================================================================================
1719 FORCEINLINE PTR_Module MethodTable::GetGenericsStaticsModuleAndID(DWORD * pID)
1731 _ASSERTE(HasGenericsStaticsInfo());
1733 #ifdef FEATURE_PREJIT
1734 // This is performance sensitive codepath inlined into JIT helpers. Test the flag directly without
1735 // checking IsStringOrArray() first. IsStringOrArray() will always be false here.
1736 _ASSERTE(!IsStringOrArray());
1737 if (m_dwFlags & enum_flag_StaticsMask_IfGenericsThenCrossModule)
1739 CrossModuleGenericsStaticsInfo *pInfo = ReadPointer(this, &MethodTable::m_pWriteableData)->GetCrossModuleGenericsStaticsInfo();
1740 _ASSERTE(FitsIn<DWORD>(pInfo->m_DynamicTypeID) || pInfo->m_DynamicTypeID == (SIZE_T)-1);
1741 *pID = static_cast<DWORD>(pInfo->m_DynamicTypeID);
1742 return pInfo->m_pModuleForStatics;
1744 #endif // FEATURE_PREJIT
1746 _ASSERTE(FitsIn<DWORD>(GetGenericsStaticsInfo()->m_DynamicTypeID) || GetGenericsStaticsInfo()->m_DynamicTypeID == (SIZE_T)-1);
1747 *pID = static_cast<DWORD>(GetGenericsStaticsInfo()->m_DynamicTypeID);
1748 return GetLoaderModule();
1751 //==========================================================================================
1752 inline OBJECTHANDLE MethodTable::GetLoaderAllocatorObjectHandle()
1754 LIMITED_METHOD_CONTRACT;
1755 return GetLoaderAllocator()->GetLoaderAllocatorObjectHandle();
1758 //==========================================================================================
1759 FORCEINLINE OBJECTREF MethodTable::GetManagedClassObjectIfExists()
1761 LIMITED_METHOD_CONTRACT;
1763 // Logging will be done by the slow path
1764 LOADERHANDLE handle = GetWriteableData_NoLogging()->GetExposedClassObjectHandle();
1768 // GET_LOADERHANDLE_VALUE_FAST macro is inlined here to let us give hint to the compiler
1769 // when the return value is not null.
1770 if (!LoaderAllocator::GetHandleValueFast(handle, &retVal) &&
1771 !GetLoaderAllocator()->GetHandleValueFastPhase2(handle, &retVal))
1776 COMPILER_ASSUME(retVal != NULL);
1780 //==========================================================================================
1781 inline void MethodTable::SetIsArray(CorElementType arrayType, CorElementType elementType)
1783 STANDARD_VM_CONTRACT;
1785 DWORD category = enum_flag_Category_Array;
1786 if (arrayType == ELEMENT_TYPE_SZARRAY)
1787 category |= enum_flag_Category_IfArrayThenSzArray;
1789 _ASSERTE((m_dwFlags & enum_flag_Category_Mask) == 0);
1790 m_dwFlags |= category;
1792 _ASSERTE(GetInternalCorElementType() == arrayType);
1795 //==========================================================================================
1796 FORCEINLINE BOOL MethodTable::ImplementsInterfaceInline(MethodTable *pInterface)
1803 PRECONDITION(pInterface->IsInterface()); // class we are looking up should be an interface
1808 // Inline InterfaceMapIterator here for performance reasons
1811 DWORD numInterfaces = GetNumInterfaces();
1812 if (numInterfaces == 0)
1815 InterfaceInfo_t *pInfo = GetInterfaceMap();
1819 if (pInfo->GetMethodTable() == pInterface)
1821 // Extensible RCW's need to be handled specially because they can have interfaces
1822 // in their map that are added at runtime. These interfaces will have a start offset
1823 // of -1 to indicate this. We cannot take for granted that every instance of this
1824 // COM object has this interface so FindInterface on these interfaces is made to fail.
1826 // However, we are only considering the statically available slots here
1827 // (m_wNumInterface doesn't contain the dynamic slots), so we can safely
1828 // ignore this detail.
1833 while (--numInterfaces);
1838 #endif // !_METHODTABLE_INL_