Remove Marshaling MDA (#22579)
[platform/upstream/coreclr.git] / src / vm / methodtablebuilder.cpp
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 //
5 // File: METHODTABLEBUILDER.CPP
6 //
7
8
9 //
10
11 //
12 // ============================================================================
13
14 #include "common.h"
15
16 #include "methodtablebuilder.h"
17
18 #include "sigbuilder.h"
19 #include "dllimport.h"
20 #include "fieldmarshaler.h"
21 #include "encee.h"
22 #include "mdaassistants.h"
23 #include "ecmakey.h"
24 #include "customattribute.h"
25 #include "typestring.h"
26
27 //*******************************************************************************
28 // Helper functions to sort GCdescs by offset (decending order)
29 int __cdecl compareCGCDescSeries(const void *arg1, const void *arg2)
30 {
31     STATIC_CONTRACT_NOTHROW;
32     STATIC_CONTRACT_GC_NOTRIGGER;
33     STATIC_CONTRACT_FORBID_FAULT;
34
35     CGCDescSeries* gcInfo1 = (CGCDescSeries*) arg1;
36     CGCDescSeries* gcInfo2 = (CGCDescSeries*) arg2;
37
38     return (int)(gcInfo2->GetSeriesOffset() - gcInfo1->GetSeriesOffset());
39 }
40
41 //*******************************************************************************
42
43 const char* FormatSig(MethodDesc* pMD, LoaderHeap *pHeap, AllocMemTracker *pamTracker);
44
45 #ifdef _DEBUG 
46 unsigned g_dupMethods = 0;
47 #endif // _DEBUG
48
49 //==========================================================================
50 // This function is very specific about how it constructs a EEClass.  It first
51 // determines the necessary size of the vtable and the number of statics that
52 // this class requires.  The necessary memory is then allocated for a EEClass
53 // and its vtable and statics.  The class members are then initialized and
54 // the memory is then returned to the caller
55 //
56 // LPEEClass CreateClass()
57 //
58 // Parameters :
59 //      [in] scope - scope of the current class not the one requested to be opened
60 //      [in] cl - class token of the class to be created.
61 //      [out] ppEEClass - pointer to pointer to hold the address of the EEClass
62 //                        allocated in this function.
63 // Return : returns an HRESULT indicating the success of this function.
64 //
65 // This parameter has been removed but might need to be reinstated if the
66 // global for the metadata loader is removed.
67 //      [in] pIMLoad - MetaDataLoader class/object for the current scope.
68
69
70 //==========================================================================
71 /*static*/ EEClass *
72 MethodTableBuilder::CreateClass( Module *pModule,
73                                 mdTypeDef cl,
74                                 BOOL fHasLayout,
75                                 BOOL fDelegate,
76                                 BOOL fIsEnum,
77                                 const MethodTableBuilder::bmtGenericsInfo *bmtGenericsInfo,
78                                 LoaderAllocator * pAllocator,
79                                 AllocMemTracker *pamTracker)
80 {
81     CONTRACTL
82     {
83         STANDARD_VM_CHECK;
84         PRECONDITION(!(fHasLayout && fDelegate));
85         PRECONDITION(!(fHasLayout && fIsEnum));
86         PRECONDITION(CheckPointer(bmtGenericsInfo));
87     }
88     CONTRACTL_END;
89
90     EEClass *pEEClass = NULL;
91     IMDInternalImport *pInternalImport;
92
93     //<TODO>============================================================================
94     // vtabsize and static size need to be converted from pointer sizes to #'s
95     // of bytes this will be very important for 64 bit NT!
96     // We will need to call on IMetaDataLoad to get these sizes and fill out the
97     // tables
98
99     // From the classref call on metadata to resolve the classref and check scope
100     // to make sure that this class is in the same scope otherwise we need to open
101     // a new scope and possibly file.
102
103     // if the scopes are different call the code to load a new file and get the new scope
104
105     // scopes are the same so we can use the existing scope to get the class info
106
107     // This method needs to be fleshed out.more it currently just returns enough
108     // space for the defined EEClass and the vtable and statics are not set.
109     //=============================================================================</TODO>
110
111     if (fHasLayout)
112     {
113         pEEClass = new (pAllocator->GetLowFrequencyHeap(), pamTracker) LayoutEEClass();
114     }
115     else if (fDelegate)
116     {
117         pEEClass = new (pAllocator->GetLowFrequencyHeap(), pamTracker) DelegateEEClass();
118     }
119     else
120     {
121         pEEClass = new (pAllocator->GetLowFrequencyHeap(), pamTracker) EEClass(sizeof(EEClass));
122     }
123
124     DWORD dwAttrClass = 0;
125     mdToken tkExtends = mdTokenNil;
126
127     // Set up variance info
128     if (bmtGenericsInfo->pVarianceInfo)
129     {
130         // Variance info is an optional field on EEClass, so ensure the optional field descriptor has been
131         // allocated.
132         EnsureOptionalFieldsAreAllocated(pEEClass, pamTracker, pAllocator->GetLowFrequencyHeap());
133         pEEClass->SetVarianceInfo((BYTE*) pamTracker->Track(
134             pAllocator->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(bmtGenericsInfo->GetNumGenericArgs()))));
135
136         memcpy(pEEClass->GetVarianceInfo(), bmtGenericsInfo->pVarianceInfo, bmtGenericsInfo->GetNumGenericArgs());
137     }
138
139     pInternalImport = pModule->GetMDImport();
140
141     if (pInternalImport == NULL)
142         COMPlusThrowHR(COR_E_TYPELOAD);
143     
144     IfFailThrow(pInternalImport->GetTypeDefProps(
145         cl, 
146         &dwAttrClass, 
147         &tkExtends));
148     
149     pEEClass->m_dwAttrClass = dwAttrClass;
150
151     // MDVal check: can't be both tdSequentialLayout and tdExplicitLayout
152     if((dwAttrClass & tdLayoutMask) == tdLayoutMask)
153         COMPlusThrowHR(COR_E_TYPELOAD);
154
155     if (IsTdInterface(dwAttrClass))
156     {
157         // MDVal check: must have nil tkExtends and must be tdAbstract
158         if((tkExtends & 0x00FFFFFF)||(!IsTdAbstract(dwAttrClass)))
159             COMPlusThrowHR(COR_E_TYPELOAD);
160     }
161
162     if (fHasLayout)
163         pEEClass->SetHasLayout();
164     
165 #ifdef FEATURE_COMINTEROP
166     if (IsTdWindowsRuntime(dwAttrClass))
167     {
168         Assembly *pAssembly = pModule->GetAssembly();
169
170         // On the desktop CLR, we do not allow non-FX assemblies to use/define WindowsRuntimeImport attribute.
171         //
172         // On CoreCLR, however, we do allow non-FX assemblies to have this attribute. This enables scenarios where we can
173         // activate 3rd-party WinRT components outside AppContainer - 1st party WinRT components are already allowed
174         // to be activated outside AppContainer (on both Desktop and CoreCLR).
175
176         pEEClass->SetProjectedFromWinRT();
177     }
178
179     if (pEEClass->IsProjectedFromWinRT())
180     {
181         if (IsTdInterface(dwAttrClass))
182         {
183             //
184             // Check for GuidAttribute
185             //
186             BOOL bHasGuid = FALSE;
187         
188             GUID guid;
189             HRESULT hr = pModule->GetMDImport()->GetItemGuid(cl, &guid);
190             IfFailThrow(hr);
191             
192             if (IsEqualGUID(guid, GUID_NULL))
193             {
194                 // A WinRT interface should have a GUID
195                 pModule->GetAssembly()->ThrowTypeLoadException(pModule->GetMDImport(), cl, IDS_EE_WINRT_INTERFACE_WITHOUT_GUID);            
196             }
197         }
198     }
199
200     WinMDAdapter::RedirectedTypeIndex redirectedTypeIndex;
201     redirectedTypeIndex = WinRTTypeNameConverter::GetRedirectedTypeIndexByName(pModule, cl);
202     if (redirectedTypeIndex != WinMDAdapter::RedirectedTypeIndex_Invalid)
203     {
204         EnsureOptionalFieldsAreAllocated(pEEClass, pamTracker, pAllocator->GetLowFrequencyHeap());
205         pEEClass->SetWinRTRedirectedTypeIndex(redirectedTypeIndex);
206     }
207 #endif // FEAUTRE_COMINTEROP
208
209 #ifdef _DEBUG 
210     pModule->GetClassLoader()->m_dwDebugClasses++;
211 #endif
212
213     return pEEClass;
214 }
215
216 //*******************************************************************************
217 //
218 // Create a hash of all methods in this class.  The hash is from method name to MethodDesc.
219 //
220 MethodTableBuilder::MethodNameHash *
221 MethodTableBuilder::CreateMethodChainHash(
222     MethodTable *pMT)
223 {
224     STANDARD_VM_CONTRACT;
225
226     MethodNameHash *pHash = new (GetStackingAllocator()) MethodNameHash();
227     pHash->Init(pMT->GetNumVirtuals(), GetStackingAllocator());
228
229     unsigned numVirtuals = GetParentMethodTable()->GetNumVirtuals();
230     for (unsigned i = 0; i < numVirtuals; ++i)
231     {
232         bmtMethodSlot &slot = (*bmtParent->pSlotTable)[i];
233         bmtRTMethod * pMethod = slot.Decl().AsRTMethod();
234         const MethodSignature &sig = pMethod->GetMethodSignature();
235         pHash->Insert(sig.GetName(), pMethod);
236     }
237
238     // Success
239     return pHash;
240 }
241
242 //*******************************************************************************
243 //
244 // Find a method in this class hierarchy - used ONLY by the loader during layout.  Do not use at runtime.
245 //
246 // *ppMemberSignature must be NULL on entry - it and *pcMemberSignature may or may not be filled out
247 //
248 // ppMethodDesc will be filled out with NULL if no matching method in the hierarchy is found.
249 //
250 // Returns FALSE if there was an error of some kind.
251 //
252 // pMethodConstraintsMatch receives the result of comparing the method constraints.
253 MethodTableBuilder::bmtRTMethod *
254 MethodTableBuilder::LoaderFindMethodInParentClass(
255     const MethodSignature & methodSig,
256     BOOL *                  pMethodConstraintsMatch)
257 {
258     CONTRACTL
259     {
260         STANDARD_VM_CHECK;
261         PRECONDITION(CheckPointer(this));
262         PRECONDITION(CheckPointer(bmtParent));
263         PRECONDITION(CheckPointer(methodSig.GetModule()));
264         PRECONDITION(CheckPointer(methodSig.GetSignature()));
265         PRECONDITION(HasParent());
266         PRECONDITION(methodSig.GetSignatureLength() != 0);
267     }
268     CONTRACTL_END;
269
270 //#if 0
271     MethodNameHash::HashEntry * pEntry;
272
273     // Have we created a hash of all the methods in the class chain?
274     if (bmtParent->pParentMethodHash == NULL)
275     {
276         // There may be such a method, so we will now create a hash table to reduce the pain for
277         // further lookups
278
279         // <TODO> Are we really sure that this is worth doing? </TODO>
280         bmtParent->pParentMethodHash = CreateMethodChainHash(GetParentMethodTable());
281     }
282
283     // We have a hash table, so use it
284     pEntry = bmtParent->pParentMethodHash->Lookup(methodSig.GetName());
285
286     // Traverse the chain of all methods with this name
287     while (pEntry != NULL)
288     {
289         bmtRTMethod * pEntryMethod = pEntry->m_data;
290         const MethodSignature & entrySig = pEntryMethod->GetMethodSignature();
291
292         // Note instantiation info
293         {
294             if (methodSig.Equivalent(entrySig))
295             {
296                 if (pMethodConstraintsMatch != NULL)
297                 {
298                     // Check the constraints are consistent,
299                     // and return the result to the caller.
300                     // We do this here to avoid recalculating pSubst.
301                     *pMethodConstraintsMatch = MetaSig::CompareMethodConstraints(
302                         &methodSig.GetSubstitution(), methodSig.GetModule(), methodSig.GetToken(),
303                         &entrySig.GetSubstitution(),  entrySig.GetModule(),  entrySig.GetToken());
304                 }
305
306                 return pEntryMethod;
307             }
308         }
309
310         // Advance to next item in the hash chain which has the same name
311         pEntry = bmtParent->pParentMethodHash->FindNext(pEntry);
312     }
313 //#endif
314
315 //@TODO: Move to this code, as the use of a HashTable is broken; overriding semantics
316 //@TODO: require matching against the most-derived slot of a given name and signature,
317 //@TODO: (which deals specifically with newslot methods with identical name and sig), but
318 //@TODO: HashTables are by definition unordered and so we've only been getting by with the
319 //@TODO: implementation being compatible with the order in which methods were added to
320 //@TODO: the HashTable in CreateMethodChainHash.
321 #if 0 
322     bmtParentInfo::Iterator it(bmtParent->IterateSlots());
323     it.MoveTo(static_cast<size_t>(GetParentMethodTable()->GetNumVirtuals()));
324     while (it.Prev())
325     {
326         bmtMethodHandle decl(it->Decl());
327         const MethodSignature &declSig(decl.GetMethodSignature());
328         if (declSig == methodSig)
329         {
330             if (pMethodConstraintsMatch != NULL)
331             {
332                 // Check the constraints are consistent,
333                 // and return the result to the caller.
334                 // We do this here to avoid recalculating pSubst.
335                 *pMethodConstraintsMatch = MetaSig::CompareMethodConstraints(
336                     &methodSig.GetSubstitution(), methodSig.GetModule(), methodSig.GetToken(),
337                     &declSig.GetSubstitution(),  declSig.GetModule(),  declSig.GetToken());
338             }
339
340             return decl.AsRTMethod();
341         }
342     }
343 #endif // 0
344
345     return NULL;
346 }
347
348 //*******************************************************************************
349 //
350 // Given an interface map to fill out, expand pNewInterface (and its sub-interfaces) into it, increasing
351 // pdwInterfaceListSize as appropriate, and avoiding duplicates.
352 //
353 void
354 MethodTableBuilder::ExpandApproxInterface(
355     bmtInterfaceInfo *          bmtInterface,  // out parameter, various parts cumulatively written to.
356     const Substitution *        pNewInterfaceSubstChain, 
357     MethodTable *               pNewInterface, 
358     InterfaceDeclarationScope   declScope 
359     COMMA_INDEBUG(MethodTable * dbg_pClassMT))
360 {
361     STANDARD_VM_CONTRACT;
362     
363     //#ExpandingInterfaces
364     // We expand the tree of inherited interfaces into a set by adding the
365     // current node BEFORE expanding the parents of the current node.
366     // ****** This must be consistent with code:ExpandExactInterface *******
367     // ****** This must be consistent with code:ClassCompat::MethodTableBuilder::BuildInteropVTable_ExpandInterface *******
368
369     // The interface list contains the fully expanded set of interfaces from the parent then
370     // we start adding all the interfaces we declare. We need to know which interfaces
371     // we declare but do not need duplicates of the ones we declare. This means we can
372     // duplicate our parent entries.
373
374     // Is it already present in the list?
375     for (DWORD i = 0; i < bmtInterface->dwInterfaceMapSize; i++)
376     {
377         bmtInterfaceEntry * pItfEntry = &bmtInterface->pInterfaceMap[i];
378         bmtRTType * pItfType = pItfEntry->GetInterfaceType();
379
380         // Type Equivalence is not respected for this comparision as you can have multiple type equivalent interfaces on a class
381         TokenPairList newVisited = TokenPairList::AdjustForTypeEquivalenceForbiddenScope(NULL);
382         if (MetaSig::CompareTypeDefsUnderSubstitutions(pItfType->GetMethodTable(),
383                                                        pNewInterface,
384                                                        &pItfType->GetSubstitution(),
385                                                        pNewInterfaceSubstChain,
386                                                        &newVisited))
387         {
388             if (declScope.fIsInterfaceDeclaredOnType)
389             {
390                 pItfEntry->IsDeclaredOnType() = true;
391             }
392 #ifdef _DEBUG
393             //#InjectInterfaceDuplicates_ApproxInterfaces
394             // We can inject duplicate interfaces in check builds.
395             // Has to be in sync with code:#InjectInterfaceDuplicates_Main
396             if (((dbg_pClassMT == NULL) && bmtInterface->dbg_fShouldInjectInterfaceDuplicates) || 
397                 ((dbg_pClassMT != NULL) && dbg_pClassMT->Debug_HasInjectedInterfaceDuplicates()))
398             {   
399                 // The injected duplicate interface should have the same status 'ImplementedByParent' as 
400                 // the original interface (can be false if the interface is implemented indirectly twice)
401                 declScope.fIsInterfaceDeclaredOnParent = pItfEntry->IsImplementedByParent();
402                 // Just pretend we didn't find this match, but mark all duplicates as 'DeclaredOnType' if 
403                 // needed
404                 continue;
405             }
406 #endif //_DEBUG
407             return; // found it, don't add it again
408         }
409     }
410
411     bmtRTType * pNewItfType =
412         new (GetStackingAllocator()) bmtRTType(*pNewInterfaceSubstChain, pNewInterface);
413
414     if (bmtInterface->dwInterfaceMapSize >= bmtInterface->dwInterfaceMapAllocated)
415     {
416         //
417         // Grow the array of interfaces
418         //
419         S_UINT32 dwNewAllocated = S_UINT32(2) * S_UINT32(bmtInterface->dwInterfaceMapAllocated) + S_UINT32(5);
420
421         if (dwNewAllocated.IsOverflow())
422         {
423             BuildMethodTableThrowException(COR_E_OVERFLOW);
424         }
425
426         S_SIZE_T safeSize = S_SIZE_T(sizeof(bmtInterfaceEntry)) *
427                             S_SIZE_T(dwNewAllocated.Value());
428
429         if (safeSize.IsOverflow())
430         {
431             BuildMethodTableThrowException(COR_E_OVERFLOW);
432         }
433
434         bmtInterfaceEntry * pNewMap = (bmtInterfaceEntry *)new (GetStackingAllocator()) BYTE[safeSize.Value()];
435         memcpy(pNewMap, bmtInterface->pInterfaceMap, sizeof(bmtInterfaceEntry) * bmtInterface->dwInterfaceMapAllocated);
436
437         bmtInterface->pInterfaceMap = pNewMap;
438         bmtInterface->dwInterfaceMapAllocated = dwNewAllocated.Value();
439     }
440
441     // The interface map memory was just allocated as an array of bytes, so we use
442     // in place new to init the new map entry. No need to do anything with the result,
443     // so just chuck it.
444     CONSISTENCY_CHECK(bmtInterface->dwInterfaceMapSize < bmtInterface->dwInterfaceMapAllocated);
445     new ((void *)&bmtInterface->pInterfaceMap[bmtInterface->dwInterfaceMapSize])
446         bmtInterfaceEntry(pNewItfType, declScope);
447
448     bmtInterface->dwInterfaceMapSize++;
449
450     // Make sure to pass in the substitution from the new itf type created above as
451     // these methods assume that substitutions are allocated in the stacking heap,
452     // not the stack.
453     InterfaceDeclarationScope declaredItfScope(declScope.fIsInterfaceDeclaredOnParent, false);
454     ExpandApproxDeclaredInterfaces(
455         bmtInterface,
456         bmtTypeHandle(pNewItfType),
457         declaredItfScope 
458         COMMA_INDEBUG(dbg_pClassMT));
459 } // MethodTableBuilder::ExpandApproxInterface
460
461 //*******************************************************************************
462 // Arguments:
463 //   dbg_pClassMT - Class on which the interfaces are declared (either explicitly or implicitly).
464 //                  It will never be an interface. It may be NULL (if it is the type being built).
465 void 
466 MethodTableBuilder::ExpandApproxDeclaredInterfaces(
467     bmtInterfaceInfo *          bmtInterface,  // out parameter, various parts cumulatively written to.
468     bmtTypeHandle               thType, 
469     InterfaceDeclarationScope   declScope 
470     COMMA_INDEBUG(MethodTable * dbg_pClassMT))
471 {
472     STANDARD_VM_CONTRACT;
473
474     _ASSERTE((dbg_pClassMT == NULL) || !dbg_pClassMT->IsInterface());
475
476     HRESULT hr;
477     // Iterate the list of interfaces declared by thType and add them to the map.
478     InterfaceImplEnum ie(thType.GetModule(), thType.GetTypeDefToken(), &thType.GetSubstitution());
479     while ((hr = ie.Next()) == S_OK)
480     {
481         MethodTable *pGenericIntf = ClassLoader::LoadApproxTypeThrowing(
482             thType.GetModule(), ie.CurrentToken(), NULL, NULL).GetMethodTable();
483         CONSISTENCY_CHECK(pGenericIntf->IsInterface());
484
485         ExpandApproxInterface(bmtInterface,
486                               ie.CurrentSubst(),
487                               pGenericIntf,
488                               declScope 
489                               COMMA_INDEBUG(dbg_pClassMT));
490     }
491     if (FAILED(hr))
492     {
493         BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
494     }
495 } // MethodTableBuilder::ExpandApproxDeclaredInterfaces
496
497 //*******************************************************************************
498 void
499 MethodTableBuilder::ExpandApproxInheritedInterfaces(
500     bmtInterfaceInfo *      bmtInterface,
501     bmtRTType *             pParentType)
502 {
503     STANDARD_VM_CONTRACT;
504
505     // Expand interfaces in superclasses first.  Interfaces inherited from parents
506     // must have identical indexes as in the parent.
507     bmtRTType * pParentOfParent = pParentType->GetParentType();
508     
509     //#InterfaceMap_SupersetOfParent
510     // We have to load parent's interface map the same way the parent did it (as open type).
511     // Further code depends on this:
512     //    code:#InterfaceMap_UseParentInterfaceImplementations
513     // We check that it is truth:
514     //    code:#ApproxInterfaceMap_SupersetOfParent
515     //    code:#ExactInterfaceMap_SupersetOfParent
516     // 
517     //#InterfaceMap_CanonicalSupersetOfParent
518     // Note that canonical instantiation of parent can have different interface instantiations in the 
519     // interface map than derived type:
520     //    class MyClass<T> : MyBase<string, T>, I<T>
521     //    class MyBase<U, V> : I<U>
522     // Type MyClass<_Canon> has MyBase<_Canon,_Canon> as parent. The interface maps are:
523     //    MyBase<_Canon,_Canon> ... I<_Canon>
524     //    MyClass<_Canon> ... I<string> (#1)
525     //                        I<_Canon> (#2)
526     // The I's instantiation I<string> (#1) in MyClass and I<_Canon> from MyBase are not the same 
527     // instantiations.
528     
529     // Backup parent substitution
530     Substitution parentSubstitution = pParentType->GetSubstitution();
531     // Make parent an open type
532     pParentType->SetSubstitution(Substitution());
533     
534     if (pParentOfParent != NULL)
535     {
536         ExpandApproxInheritedInterfaces(bmtInterface, pParentOfParent);
537     }
538
539     InterfaceDeclarationScope declScope(true, false);
540     ExpandApproxDeclaredInterfaces(
541         bmtInterface, 
542         bmtTypeHandle(pParentType), 
543         declScope 
544         COMMA_INDEBUG(pParentType->GetMethodTable()));
545     
546     // Make sure we loaded the same number of interfaces as the parent type itself
547     CONSISTENCY_CHECK(pParentType->GetMethodTable()->GetNumInterfaces() == bmtInterface->dwInterfaceMapSize);
548     
549     // Restore parent's substitution
550     pParentType->SetSubstitution(parentSubstitution);
551 } // MethodTableBuilder::ExpandApproxInheritedInterfaces
552
553 //*******************************************************************************
554 // Fill out a fully expanded interface map, such that if we are declared to
555 // implement I3, and I3 extends I1,I2, then I1,I2 are added to our list if
556 // they are not already present.
557 void
558 MethodTableBuilder::LoadApproxInterfaceMap()
559 {
560     STANDARD_VM_CONTRACT;
561
562     bmtInterface->dwInterfaceMapSize = 0;
563
564 #ifdef _DEBUG
565     //#InjectInterfaceDuplicates_Main
566     // We will inject duplicate interfaces in check builds if env. var. 
567     // COMPLUS_INTERNAL_TypeLoader_InjectInterfaceDuplicates is set to TRUE for all types (incl. non-generic 
568     // types).
569     // This should allow us better test coverage of duplicates in interface map.
570     // 
571     // The duplicates are legal for some types:
572     //     A<T> : I<T>
573     //     B<U,V> : A<U>, I<V>
574     //     C : B<int,int>
575     //   where the interface maps are:
576     //     A<T>             ... 1 item:  I<T>
577     //     A<int>           ... 1 item:  I<int>
578     //     B<U,V>           ... 2 items: I<U>, I<V>
579     //     B<int,int>       ... 2 items: I<int>, I<int>
580     //     B<_Canon,_Canon> ... 2 items: I<_Canon>, I<_Canon>
581     //     B<string,string> ... 2 items: I<string>, I<string>
582     //     C                ... 2 items: I<int>, I<int>
583     //     Note: C had only 1 item (I<int>) in CLR 2.0 RTM/SP1/SP2 and early in CLR 4.0.
584     // 
585     // We will create duplicate from every re-implemented interface (incl. non-generic):
586     //   code:#InjectInterfaceDuplicates_ApproxInterfaces
587     //   code:#InjectInterfaceDuplicates_LoadExactInterfaceMap
588     //   code:#InjectInterfaceDuplicates_ExactInterfaces
589     // 
590     // Note that we don't have to do anything for COM, because COM has its own interface map 
591     // (code:InteropMethodTableData)which is independent on type's interface map and is created only from 
592     // non-generic interfaces (see code:ClassCompat::MethodTableBuilder::BuildInteropVTable_InterfaceList)
593     
594     // We need to keep track which interface duplicates were injected. Right now its either all interfaces 
595     // (declared on the type being built, not inheritted) or none. In the future we could inject duplicates 
596     // just for some of them.
597     bmtInterface->dbg_fShouldInjectInterfaceDuplicates = 
598         (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_TypeLoader_InjectInterfaceDuplicates) != 0);
599     if (bmtGenerics->Debug_GetTypicalMethodTable() != NULL)
600     {   // It's safer to require that all instantiations have the same injected interface duplicates.
601         // In future we could inject different duplicates for various non-shared instantiations.
602         
603         // Use the same injection status as typical instantiation
604         bmtInterface->dbg_fShouldInjectInterfaceDuplicates = 
605             bmtGenerics->Debug_GetTypicalMethodTable()->Debug_HasInjectedInterfaceDuplicates();
606         
607         if (GetModule() == g_pObjectClass->GetModule())
608         {   // mscorlib has some weird hardcoded information about interfaces (e.g. 
609             // code:CEEPreloader::ApplyTypeDependencyForSZArrayHelper), so we don't inject duplicates into 
610             // mscorlib types
611             bmtInterface->dbg_fShouldInjectInterfaceDuplicates = FALSE;
612         }
613     }
614 #endif //_DEBUG
615
616     // First inherit all the parent's interfaces.  This is important, because our interface map must
617     // list the interfaces in identical order to our parent.
618     //
619     // <NICE> we should document the reasons why.  One reason is that DispatchMapTypeIDs can be indexes
620     // into the list </NICE>
621     if (HasParent())
622     {
623         ExpandApproxInheritedInterfaces(bmtInterface, GetParentType());
624 #ifdef _DEBUG
625         //#ApproxInterfaceMap_SupersetOfParent
626         // Check that parent's interface map is the same as what we just computed
627         // See code:#InterfaceMap_SupersetOfParent
628         {
629             MethodTable * pParentMT = GetParentMethodTable();
630             _ASSERTE(pParentMT->GetNumInterfaces() == bmtInterface->dwInterfaceMapSize);
631             
632             MethodTable::InterfaceMapIterator parentInterfacesIterator = pParentMT->IterateInterfaceMap();
633             UINT32 nInterfaceIndex = 0;
634             while (parentInterfacesIterator.Next())
635             {
636                 // Compare TypeDefs of the parent's interface and this interface (full MT comparison is in 
637                 // code:#ExactInterfaceMap_SupersetOfParent)
638                 OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOAD_APPROXPARENTS);
639                 _ASSERTE(parentInterfacesIterator.GetInterfaceInfo()->GetApproxMethodTable(pParentMT->GetLoaderModule())->HasSameTypeDefAs(
640                     bmtInterface->pInterfaceMap[nInterfaceIndex].GetInterfaceType()->GetMethodTable()));
641                 nInterfaceIndex++;
642             }
643             _ASSERTE(nInterfaceIndex == bmtInterface->dwInterfaceMapSize);
644         }
645 #endif //_DEBUG
646     }
647
648     // Now add in any freshly declared interfaces, possibly augmenting the flags
649     InterfaceDeclarationScope declScope(false, true);
650     ExpandApproxDeclaredInterfaces(
651         bmtInterface, 
652         bmtInternal->pType, 
653         declScope 
654         COMMA_INDEBUG(NULL));
655 } // MethodTableBuilder::LoadApproxInterfaceMap
656
657 //*******************************************************************************
658 // Fills array of TypeIDs with all duplicate occurences of pDeclIntfMT in the interface map.
659 // 
660 // Arguments:
661 //    rg/c DispatchMapTypeIDs - Array of TypeIDs and its count of elements.
662 //    pcIfaceDuplicates - Number of duplicate occurences of the interface in the interface map (ideally <= 
663 //         count of elements TypeIDs.
664 // 
665 // Note: If the passed rgDispatchMapTypeIDs array is smaller than the number of duplicates, fills it 
666 // with the duplicates that fit and returns number of all existing duplicates (not just those fileld in the 
667 // array) in pcIfaceDuplicates.
668 // 
669 void 
670 MethodTableBuilder::ComputeDispatchMapTypeIDs(
671     MethodTable *        pDeclInftMT, 
672     const Substitution * pDeclIntfSubst, 
673     DispatchMapTypeID *  rgDispatchMapTypeIDs, 
674     UINT32               cDispatchMapTypeIDs, 
675     UINT32 *             pcIfaceDuplicates)
676 {
677     STANDARD_VM_CONTRACT;
678     
679     _ASSERTE(pDeclInftMT->IsInterface());
680     
681     // Count of interface duplicates (also used as index into TypeIDs array)
682     *pcIfaceDuplicates = 0;
683     for (DWORD idx = 0; idx < bmtInterface->dwInterfaceMapSize; idx++)
684     {
685         bmtInterfaceEntry * pItfEntry = &bmtInterface->pInterfaceMap[idx];
686         bmtRTType * pItfType = pItfEntry->GetInterfaceType();
687         // Type Equivalence is forbidden in interface type ids.
688         TokenPairList newVisited = TokenPairList::AdjustForTypeEquivalenceForbiddenScope(NULL);
689         if (MetaSig::CompareTypeDefsUnderSubstitutions(pItfType->GetMethodTable(),
690                                                        pDeclInftMT,
691                                                        &pItfType->GetSubstitution(),
692                                                        pDeclIntfSubst,
693                                                        &newVisited))
694         {   // We found another occurence of this interface
695             // Can we fit it into the TypeID array?
696             if (*pcIfaceDuplicates < cDispatchMapTypeIDs)
697             {
698                 rgDispatchMapTypeIDs[*pcIfaceDuplicates] = DispatchMapTypeID::InterfaceClassID(idx);
699             }
700             // Increase number of duplicate interfaces
701             (*pcIfaceDuplicates)++;
702         }
703     }
704 } // MethodTableBuilder::ComputeDispatchMapTypeIDs
705
706 //*******************************************************************************
707 /*static*/
708 VOID DECLSPEC_NORETURN
709 MethodTableBuilder::BuildMethodTableThrowException(
710     HRESULT hr,
711     const bmtErrorInfo & bmtError)
712 {
713     CONTRACTL
714     {
715         THROWS;
716         GC_TRIGGERS;
717         INJECT_FAULT(COMPlusThrowOM(););
718     }
719     CONTRACTL_END
720
721     LPCUTF8 pszClassName, pszNameSpace;
722     if (FAILED(bmtError.pModule->GetMDImport()->GetNameOfTypeDef(bmtError.cl, &pszClassName, &pszNameSpace)))
723     {
724         pszClassName = pszNameSpace = "Invalid TypeDef record";
725     }
726     
727     if (IsNilToken(bmtError.dMethodDefInError) && (bmtError.szMethodNameForError == NULL))
728     {
729         if (hr == E_OUTOFMEMORY)
730         {
731             COMPlusThrowOM();
732         }
733         else
734             bmtError.pModule->GetAssembly()->ThrowTypeLoadException(
735                 pszNameSpace, pszClassName, bmtError.resIDWhy);
736     }
737     else
738     {
739         LPCUTF8 szMethodName;
740         if (bmtError.szMethodNameForError == NULL)
741         {
742             if (FAILED((bmtError.pModule->GetMDImport())->GetNameOfMethodDef(bmtError.dMethodDefInError, &szMethodName)))
743             {
744                 szMethodName = "Invalid MethodDef record";
745             }
746         }
747         else
748         {
749             szMethodName = bmtError.szMethodNameForError;
750         }
751
752         bmtError.pModule->GetAssembly()->ThrowTypeLoadException(
753             pszNameSpace, pszClassName, szMethodName, bmtError.resIDWhy);
754     }
755 } // MethodTableBuilder::BuildMethodTableThrowException
756
757 //*******************************************************************************
758 void MethodTableBuilder::SetBMTData(
759     LoaderAllocator *bmtAllocator,
760     bmtErrorInfo *bmtError,
761     bmtProperties *bmtProp,
762     bmtVtable *bmtVT,
763     bmtParentInfo *bmtParent,
764     bmtInterfaceInfo *bmtInterface,
765     bmtMetaDataInfo *bmtMetaData,
766     bmtMethodInfo *bmtMethod,
767     bmtMethAndFieldDescs *bmtMFDescs,
768     bmtFieldPlacement *bmtFP,
769     bmtInternalInfo *bmtInternal,
770     bmtGCSeriesInfo *bmtGCSeries,
771     bmtMethodImplInfo *bmtMethodImpl,
772     const bmtGenericsInfo *bmtGenerics,
773     bmtEnumFieldInfo *bmtEnumFields)
774 {
775     LIMITED_METHOD_CONTRACT;
776     this->bmtAllocator = bmtAllocator;
777     this->bmtError = bmtError;
778     this->bmtProp = bmtProp;
779     this->bmtVT = bmtVT;
780     this->bmtParent = bmtParent;
781     this->bmtInterface = bmtInterface;
782     this->bmtMetaData = bmtMetaData;
783     this->bmtMethod = bmtMethod;
784     this->bmtMFDescs = bmtMFDescs;
785     this->bmtFP = bmtFP;
786     this->bmtInternal = bmtInternal;
787     this->bmtGCSeries = bmtGCSeries;
788     this->bmtMethodImpl = bmtMethodImpl;
789     this->bmtGenerics = bmtGenerics;
790     this->bmtEnumFields = bmtEnumFields;
791 }
792
793 //*******************************************************************************
794 // Used by MethodTableBuilder
795
796 MethodTableBuilder::bmtRTType *
797 MethodTableBuilder::CreateTypeChain(
798     MethodTable *        pMT,
799     const Substitution & subst)
800 {
801     CONTRACTL
802     {
803         STANDARD_VM_CHECK;
804         INSTANCE_CHECK;
805         PRECONDITION(CheckPointer(GetStackingAllocator()));
806         PRECONDITION(CheckPointer(pMT));
807     } CONTRACTL_END;
808
809     pMT = pMT->GetCanonicalMethodTable();
810
811     bmtRTType * pType = new (GetStackingAllocator())
812         bmtRTType(subst, pMT);
813
814     MethodTable * pMTParent = pMT->GetParentMethodTable();
815     if (pMTParent != NULL)
816     {
817         pType->SetParentType(
818             CreateTypeChain(
819                 pMTParent,
820                 pMT->GetSubstitutionForParent(&pType->GetSubstitution())));
821     }
822
823     return pType;
824 }
825
826 //*******************************************************************************
827 /* static */
828 MethodTableBuilder::bmtRTType *
829 MethodTableBuilder::bmtRTType::FindType(
830     bmtRTType *          pType,
831     MethodTable *        pTargetMT)
832 {
833     CONTRACTL {
834         STANDARD_VM_CHECK;
835         PRECONDITION(CheckPointer(pType));
836         PRECONDITION(CheckPointer(pTargetMT));
837     } CONTRACTL_END;
838
839     pTargetMT = pTargetMT->GetCanonicalMethodTable();
840     while (pType != NULL &&
841            pType->GetMethodTable()->GetCanonicalMethodTable() != pTargetMT)
842     {
843         pType = pType->GetParentType();
844     }
845
846     return pType;
847 }
848
849 //*******************************************************************************
850 mdTypeDef
851 MethodTableBuilder::bmtRTType::GetEnclosingTypeToken() const
852 {
853     STANDARD_VM_CONTRACT;
854
855     mdTypeDef tok = mdTypeDefNil;
856
857     if (IsNested())
858     {   // This is guaranteed to succeed because the EEClass would not have been
859         // set as nested unless a valid token was stored in metadata.
860         if (FAILED(GetModule()->GetMDImport()->GetNestedClassProps(
861             GetTypeDefToken(), &tok)))
862         {
863             return mdTypeDefNil;
864         }
865     }
866     
867     return tok;
868 }
869
870 //*******************************************************************************
871 /*static*/ bool
872 MethodTableBuilder::MethodSignature::NamesEqual(
873     const MethodSignature & sig1,
874     const MethodSignature & sig2)
875 {
876     STANDARD_VM_CONTRACT;
877
878     if (sig1.GetNameHash() != sig2.GetNameHash())
879     {
880         return false;
881     }
882
883     if (strcmp(sig1.GetName(), sig2.GetName()) != 0)
884     {
885         return false;
886     }
887
888     return true;
889 }
890
891 //*******************************************************************************
892 /*static*/ bool
893 MethodTableBuilder::MethodSignature::SignaturesEquivalent(
894     const MethodSignature & sig1, 
895     const MethodSignature & sig2)
896 {
897     STANDARD_VM_CONTRACT;
898
899     return !!MetaSig::CompareMethodSigs(
900         sig1.GetSignature(), static_cast<DWORD>(sig1.GetSignatureLength()), sig1.GetModule(), &sig1.GetSubstitution(), 
901         sig2.GetSignature(), static_cast<DWORD>(sig2.GetSignatureLength()), sig2.GetModule(), &sig2.GetSubstitution());
902 }
903
904 //*******************************************************************************
905 /*static*/ bool
906 MethodTableBuilder::MethodSignature::SignaturesExactlyEqual(
907     const MethodSignature & sig1, 
908     const MethodSignature & sig2)
909 {
910     STANDARD_VM_CONTRACT;
911
912     TokenPairList newVisited = TokenPairList::AdjustForTypeEquivalenceForbiddenScope(NULL);
913     return !!MetaSig::CompareMethodSigs(
914         sig1.GetSignature(), static_cast<DWORD>(sig1.GetSignatureLength()), sig1.GetModule(), &sig1.GetSubstitution(), 
915         sig2.GetSignature(), static_cast<DWORD>(sig2.GetSignatureLength()), sig2.GetModule(), &sig2.GetSubstitution(),
916         &newVisited);
917 }
918
919 //*******************************************************************************
920 bool
921 MethodTableBuilder::MethodSignature::Equivalent(
922     const MethodSignature &rhs) const
923 {
924     STANDARD_VM_CONTRACT;
925
926     return NamesEqual(*this, rhs) && SignaturesEquivalent(*this, rhs);
927 }
928
929 //*******************************************************************************
930 bool
931 MethodTableBuilder::MethodSignature::ExactlyEqual(
932     const MethodSignature &rhs) const
933 {
934     STANDARD_VM_CONTRACT;
935
936     return NamesEqual(*this, rhs) && SignaturesExactlyEqual(*this, rhs);
937 }
938
939 //*******************************************************************************
940 void
941 MethodTableBuilder::MethodSignature::GetMethodAttributes() const
942 {
943     STANDARD_VM_CONTRACT;
944
945     IMDInternalImport * pIMD = GetModule()->GetMDImport();
946     if (TypeFromToken(GetToken()) == mdtMethodDef)
947     {
948         DWORD cSig;
949         if (FAILED(pIMD->GetNameAndSigOfMethodDef(GetToken(), &m_pSig, &cSig, &m_szName)))
950         {   // We have empty name or signature on error, do nothing
951         }
952         m_cSig = static_cast<size_t>(cSig);
953     }
954     else
955     {
956         CONSISTENCY_CHECK(TypeFromToken(m_tok) == mdtMemberRef);
957         DWORD cSig;
958         if (FAILED(pIMD->GetNameAndSigOfMemberRef(GetToken(), &m_pSig, &cSig, &m_szName)))
959         {   // We have empty name or signature on error, do nothing
960         }
961         m_cSig = static_cast<size_t>(cSig);
962     }
963 }
964
965 //*******************************************************************************
966 UINT32
967 MethodTableBuilder::MethodSignature::GetNameHash() const
968 {
969     STANDARD_VM_CONTRACT;
970
971     CheckGetMethodAttributes();
972
973     if (m_nameHash == INVALID_NAME_HASH)
974     {
975         ULONG nameHash = HashStringA(GetName());
976         if (nameHash == INVALID_NAME_HASH)
977         {
978             nameHash /= 2;
979         }
980         m_nameHash = nameHash;
981     }
982
983     return m_nameHash;
984 }
985
986 //*******************************************************************************
987 MethodTableBuilder::bmtMDType::bmtMDType(
988     bmtRTType *             pParentType,
989     Module *                pModule,
990     mdTypeDef               tok,
991     const SigTypeContext &  sigContext)
992     : m_pParentType(pParentType),
993       m_pModule(pModule),
994       m_tok(tok),
995       m_enclTok(mdTypeDefNil),
996       m_sigContext(sigContext),
997       m_subst(),
998       m_dwAttrs(0),
999       m_pMT(NULL)
1000 {
1001     STANDARD_VM_CONTRACT;
1002
1003     IfFailThrow(m_pModule->GetMDImport()->GetTypeDefProps(m_tok, &m_dwAttrs, NULL));
1004
1005     HRESULT hr = m_pModule->GetMDImport()->GetNestedClassProps(m_tok, &m_enclTok);
1006     if (FAILED(hr))
1007     {
1008         if (hr != CLDB_E_RECORD_NOTFOUND)
1009         {
1010             ThrowHR(hr);
1011         }
1012         // Just in case GetNestedClassProps sets the out param to some other value
1013         m_enclTok = mdTypeDefNil;
1014     }
1015 }
1016
1017 //*******************************************************************************
1018 MethodTableBuilder::bmtRTMethod::bmtRTMethod(
1019     bmtRTType *     pOwningType,
1020     MethodDesc *    pMD)
1021     : m_pOwningType(pOwningType),
1022       m_pMD(pMD),
1023       m_methodSig(pMD->GetModule(),
1024                   pMD->GetMemberDef(),
1025                   &pOwningType->GetSubstitution())
1026 {
1027     CONTRACTL
1028     {
1029         THROWS;
1030         GC_TRIGGERS;
1031         MODE_ANY;
1032     }
1033     CONTRACTL_END;
1034 }
1035
1036 //*******************************************************************************
1037 MethodTableBuilder::bmtMDMethod::bmtMDMethod(
1038     bmtMDType * pOwningType,
1039     mdMethodDef tok,
1040     DWORD dwDeclAttrs,
1041     DWORD dwImplAttrs,
1042     DWORD dwRVA,
1043     METHOD_TYPE type,
1044     METHOD_IMPL_TYPE implType)
1045     : m_pOwningType(pOwningType),
1046       m_dwDeclAttrs(dwDeclAttrs),
1047       m_dwImplAttrs(dwImplAttrs),
1048       m_dwRVA(dwRVA),
1049       m_type(type),
1050       m_implType(implType),
1051       m_methodSig(pOwningType->GetModule(),
1052                   tok,
1053                   &pOwningType->GetSubstitution()),
1054       m_pMD(NULL),
1055       m_pUnboxedMD(NULL),
1056       m_slotIndex(INVALID_SLOT_INDEX),
1057       m_unboxedSlotIndex(INVALID_SLOT_INDEX)
1058     {
1059         CONTRACTL
1060         {
1061             THROWS;
1062             GC_TRIGGERS;
1063             MODE_ANY;
1064         }
1065         CONTRACTL_END;
1066     }
1067 //*******************************************************************************
1068 void
1069 MethodTableBuilder::ImportParentMethods()
1070 {
1071     STANDARD_VM_CONTRACT;
1072
1073     if (!HasParent())
1074     {   // If there's no parent, there's no methods to import
1075         return;
1076     }
1077
1078     SLOT_INDEX numMethods = static_cast<SLOT_INDEX>
1079         (GetParentMethodTable()->GetNumMethods());
1080
1081     bmtParent->pSlotTable = new (GetStackingAllocator())
1082         bmtMethodSlotTable(numMethods, GetStackingAllocator());
1083
1084     MethodTable::MethodIterator it(GetParentMethodTable());
1085     for (;it.IsValid(); it.Next())
1086     {
1087         MethodDesc *  pDeclDesc = NULL;
1088         MethodTable * pDeclMT   = NULL;
1089         MethodDesc *  pImplDesc = NULL;
1090         MethodTable * pImplMT   = NULL;
1091
1092         if (it.IsVirtual())
1093         {
1094             pDeclDesc = it.GetDeclMethodDesc();
1095             pDeclMT = pDeclDesc->GetMethodTable();
1096             pImplDesc = it.GetMethodDesc();
1097             pImplMT = pImplDesc->GetMethodTable();
1098         }
1099         else
1100         {
1101             pDeclDesc = pImplDesc = it.GetMethodDesc();
1102             pDeclMT = pImplMT = it.GetMethodDesc()->GetMethodTable();
1103         }
1104
1105         CONSISTENCY_CHECK(CheckPointer(pDeclDesc));
1106         CONSISTENCY_CHECK(CheckPointer(pImplDesc));
1107
1108         // Create and assign to each slot
1109         bmtMethodSlot newSlot;
1110         newSlot.Decl() = new (GetStackingAllocator())
1111             bmtRTMethod(bmtRTType::FindType(GetParentType(), pDeclMT), pDeclDesc);
1112         if (pDeclDesc == pImplDesc)
1113         {
1114             newSlot.Impl() = newSlot.Decl();
1115         }
1116         else
1117         {
1118             newSlot.Impl() = new (GetStackingAllocator())
1119                 bmtRTMethod(bmtRTType::FindType(GetParentType(), pImplMT), pImplDesc);
1120         }
1121
1122         if (!bmtParent->pSlotTable->AddMethodSlot(newSlot))
1123             BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
1124     }
1125 }
1126
1127 //*******************************************************************************
1128 void
1129 MethodTableBuilder::CopyParentVtable()
1130 {
1131     STANDARD_VM_CONTRACT;
1132
1133     if (!HasParent())
1134     {
1135         return;
1136     }
1137
1138     for (bmtParentInfo::Iterator it = bmtParent->IterateSlots();
1139          !it.AtEnd() && it.CurrentIndex() < GetParentMethodTable()->GetNumVirtuals();
1140          ++it)
1141      {
1142         if (!bmtVT->pSlotTable->AddMethodSlot(*it))
1143             BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
1144         ++bmtVT->cVirtualSlots;
1145         ++bmtVT->cTotalSlots;
1146      }
1147 }
1148
1149 //*******************************************************************************
1150 // Determine if this is the special SIMD type System.Numerics.Vector<T>, whose
1151 // size is determined dynamically based on the hardware and the presence of JIT
1152 // support.
1153 // If so:
1154 //   - Update the NumInstanceFieldBytes on the bmtFieldPlacement.
1155 //   - Update the m_cbNativeSize and m_cbManagedSize if HasLayout() is true.
1156 // Return a BOOL result to indicate whether the size has been updated.
1157 //
1158 // Will throw IDS_EE_SIMD_NGEN_DISALLOWED if the type is System.Numerics.Vector`1
1159 // and this is an ngen compilation process.
1160 //
1161 BOOL MethodTableBuilder::CheckIfSIMDAndUpdateSize()
1162 {
1163     STANDARD_VM_CONTRACT;
1164
1165 #if defined(_TARGET_X86_) || defined(_TARGET_AMD64_)
1166     if (!(GetAssembly()->IsSIMDVectorAssembly() || bmtProp->fIsIntrinsicType))
1167         return false;
1168
1169     if (bmtFP->NumInstanceFieldBytes != 16)
1170         return false;
1171
1172     LPCUTF8 className;
1173     LPCUTF8 nameSpace;
1174     if (FAILED(GetMDImport()->GetNameOfTypeDef(bmtInternal->pType->GetTypeDefToken(), &className, &nameSpace)))
1175         return false;
1176
1177     if (strcmp(className, "Vector`1") != 0 || strcmp(nameSpace, "System.Numerics") != 0)
1178         return false;
1179
1180     if (IsCompilationProcess())
1181     {
1182         COMPlusThrow(kTypeLoadException, IDS_EE_SIMD_NGEN_DISALLOWED);
1183     }
1184
1185 #ifndef CROSSGEN_COMPILE
1186     if (!TargetHasAVXSupport())
1187         return false;
1188
1189     EEJitManager *jitMgr = ExecutionManager::GetEEJitManager();
1190     if (jitMgr->LoadJIT())
1191     {
1192         CORJIT_FLAGS cpuCompileFlags = jitMgr->GetCPUCompileFlags();
1193         if (cpuCompileFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_FEATURE_SIMD))
1194         {
1195             unsigned intrinsicSIMDVectorLength = jitMgr->m_jit->getMaxIntrinsicSIMDVectorLength(cpuCompileFlags);
1196             if (intrinsicSIMDVectorLength != 0)
1197             {
1198                 bmtFP->NumInstanceFieldBytes     = intrinsicSIMDVectorLength;
1199                 if (HasLayout())
1200                 {
1201                     GetLayoutInfo()->m_cbNativeSize = intrinsicSIMDVectorLength;
1202                     GetLayoutInfo()->m_cbManagedSize = intrinsicSIMDVectorLength;
1203                 }
1204                 return true;
1205             }
1206         }
1207     }
1208 #endif // !CROSSGEN_COMPILE
1209 #endif // defined(_TARGET_X86_) || defined(_TARGET_AMD64_)
1210     return false;
1211 }
1212
1213 //*******************************************************************************
1214 void
1215 MethodTableBuilder::bmtInterfaceEntry::CreateSlotTable(
1216     StackingAllocator * pStackingAllocator)
1217 {
1218     STANDARD_VM_CONTRACT;
1219
1220     CONSISTENCY_CHECK(m_pImplTable == NULL);
1221
1222     SLOT_INDEX cSlots = (SLOT_INDEX)GetInterfaceType()->GetMethodTable()->GetNumVirtuals();
1223     bmtInterfaceSlotImpl * pST = new (pStackingAllocator) bmtInterfaceSlotImpl[cSlots];
1224
1225     MethodTable::MethodIterator it(GetInterfaceType()->GetMethodTable());
1226     for (; it.IsValid(); it.Next())
1227     {
1228         if (!it.IsVirtual())
1229         {
1230             break;
1231         }
1232
1233         bmtRTMethod * pCurMethod = new (pStackingAllocator)
1234             bmtRTMethod(GetInterfaceType(), it.GetDeclMethodDesc());
1235
1236         CONSISTENCY_CHECK(m_cImplTable == it.GetSlotNumber());
1237         pST[m_cImplTable++] = bmtInterfaceSlotImpl(pCurMethod, INVALID_SLOT_INDEX);
1238     }
1239
1240     m_pImplTable = pST;
1241 }
1242
1243 #ifdef _PREFAST_ 
1244 #pragma warning(push)
1245 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
1246 #endif // _PREFAST_
1247 //---------------------------------------------------------------------------------------
1248 // 
1249 // Builds the method table, allocates MethodDesc, handles overloaded members, attempts to compress
1250 // interface storage.  All dependent classes must already be resolved!
1251 // 
1252 MethodTable *
1253 MethodTableBuilder::BuildMethodTableThrowing(
1254     LoaderAllocator *          pAllocator, 
1255     Module *                   pLoaderModule, 
1256     Module *                   pModule, 
1257     mdToken                    cl, 
1258     BuildingInterfaceInfo_t *  pBuildingInterfaceList, 
1259     const LayoutRawFieldInfo * pLayoutRawFieldInfos, 
1260     MethodTable *              pParentMethodTable, 
1261     const bmtGenericsInfo *    bmtGenericsInfo, 
1262     SigPointer                 parentInst, 
1263     WORD                       cBuildingInterfaceList)
1264 {
1265     CONTRACTL
1266     {
1267         STANDARD_VM_CHECK;
1268         PRECONDITION(CheckPointer(GetHalfBakedClass()));
1269         PRECONDITION(CheckPointer(bmtGenericsInfo));
1270     }
1271     CONTRACTL_END;
1272
1273     pModule->EnsureLibraryLoaded();
1274
1275     // The following structs, defined as private members of MethodTableBuilder, contain the necessary local
1276     // parameters needed for BuildMethodTable Look at the struct definitions for a detailed list of all
1277     // parameters available to BuildMethodTableThrowing.
1278
1279     SetBMTData(
1280         pAllocator,
1281         new (GetStackingAllocator()) bmtErrorInfo(),
1282         new (GetStackingAllocator()) bmtProperties(),
1283         new (GetStackingAllocator()) bmtVtable(),
1284         new (GetStackingAllocator()) bmtParentInfo(),
1285         new (GetStackingAllocator()) bmtInterfaceInfo(),
1286         new (GetStackingAllocator()) bmtMetaDataInfo(),
1287         new (GetStackingAllocator()) bmtMethodInfo(),
1288         new (GetStackingAllocator()) bmtMethAndFieldDescs(),
1289         new (GetStackingAllocator()) bmtFieldPlacement(),
1290         new (GetStackingAllocator()) bmtInternalInfo(),
1291         new (GetStackingAllocator()) bmtGCSeriesInfo(),
1292         new (GetStackingAllocator()) bmtMethodImplInfo(),
1293         bmtGenericsInfo,
1294         new (GetStackingAllocator()) bmtEnumFieldInfo(pModule->GetMDImport()));
1295
1296     //Initialize structs
1297
1298     bmtError->resIDWhy = IDS_CLASSLOAD_GENERAL;          // Set the reason and the offending method def. If the method information
1299     bmtError->pThrowable = NULL;
1300     bmtError->pModule  = pModule;
1301     bmtError->cl       = cl;
1302
1303     bmtInternal->pInternalImport = pModule->GetMDImport();
1304     bmtInternal->pModule = pModule;
1305
1306     bmtInternal->pParentMT = pParentMethodTable;
1307
1308     // Create the chain of bmtRTType for the parent types. This allows all imported
1309     // parent methods to be associated with their declaring types, and as such it is
1310     // easy to access the appropriate Substitution when comparing signatures.
1311     bmtRTType * pParent = NULL;
1312     if (pParentMethodTable != NULL)
1313     {
1314         Substitution * pParentSubst =
1315             new (GetStackingAllocator()) Substitution(pModule, parentInst, NULL);
1316         pParent = CreateTypeChain(pParentMethodTable, *pParentSubst);
1317     }
1318
1319     // Now create the bmtMDType for the type being built.
1320     bmtInternal->pType = new (GetStackingAllocator())
1321         bmtMDType(pParent, pModule, cl, bmtGenericsInfo->typeContext);
1322
1323     // If not NULL, it means there are some by-value fields, and this contains an entry for each inst
1324
1325 #ifdef _DEBUG 
1326     // Set debug class name string for easier debugging.
1327     LPCUTF8 className;
1328     LPCUTF8 nameSpace;
1329     if (FAILED(GetMDImport()->GetNameOfTypeDef(bmtInternal->pType->GetTypeDefToken(), &className, &nameSpace)))
1330     {
1331         className = nameSpace = "Invalid TypeDef record";
1332     }
1333     
1334     {
1335         S_SIZE_T safeLen = S_SIZE_T(sizeof(char))*(S_SIZE_T(strlen(className)) + S_SIZE_T(strlen(nameSpace)) + S_SIZE_T(2));
1336         if(safeLen.IsOverflow()) COMPlusThrowHR(COR_E_OVERFLOW);
1337
1338         size_t len = safeLen.Value();
1339         char *name = (char*) AllocateFromHighFrequencyHeap(safeLen);
1340         strcpy_s(name, len, nameSpace);
1341         if (strlen(nameSpace) > 0) {
1342             name[strlen(nameSpace)] = '.';
1343             name[strlen(nameSpace) + 1] = '\0';
1344         }
1345         strcat_s(name, len, className);
1346
1347         GetHalfBakedClass()->SetDebugClassName(name);
1348     }
1349
1350     if (g_pConfig->ShouldBreakOnClassBuild(className))
1351     {
1352         CONSISTENCY_CHECK_MSGF(false, ("BreakOnClassBuild: typename '%s' ", className));
1353         GetHalfBakedClass()->m_fDebuggingClass = TRUE;
1354     }
1355
1356     LPCUTF8 pszDebugName,pszDebugNamespace;
1357     if (FAILED(pModule->GetMDImport()->GetNameOfTypeDef(bmtInternal->pType->GetTypeDefToken(), &pszDebugName, &pszDebugNamespace)))
1358     {
1359         pszDebugName = pszDebugNamespace = "Invalid TypeDef record";
1360     }
1361
1362     StackSString debugName(SString::Utf8, pszDebugName);
1363
1364     // If there is an instantiation, update the debug name to include instantiation type names.
1365     if (bmtGenerics->HasInstantiation())
1366     {
1367         StackSString debugName(SString::Utf8, GetDebugClassName());
1368         TypeString::AppendInst(debugName, bmtGenerics->GetInstantiation(), TypeString::FormatBasic);
1369         StackScratchBuffer buff;
1370         const char* pDebugNameUTF8 = debugName.GetUTF8(buff);
1371         S_SIZE_T safeLen = S_SIZE_T(strlen(pDebugNameUTF8)) + S_SIZE_T(1);
1372         if(safeLen.IsOverflow())
1373             COMPlusThrowHR(COR_E_OVERFLOW);
1374
1375         size_t len = safeLen.Value();
1376         char *name = (char*) AllocateFromLowFrequencyHeap(safeLen);
1377         strcpy_s(name, len, pDebugNameUTF8);
1378         GetHalfBakedClass()->SetDebugClassName(name);
1379         pszDebugName = (LPCUTF8)name;
1380     }
1381
1382     LOG((LF_CLASSLOADER, LL_INFO1000, "Loading class \"%s%s%S\" from module \"%ws\" in domain 0x%p %s\n",
1383         *pszDebugNamespace ? pszDebugNamespace : "",
1384         *pszDebugNamespace ? NAMESPACE_SEPARATOR_STR : "",
1385         debugName.GetUnicode(),
1386         pModule->GetDebugName(),
1387         pModule->GetDomain(),
1388         (pModule->IsSystem()) ? "System Domain" : ""
1389     ));
1390 #endif // _DEBUG
1391
1392     // If this is mscorlib, then don't perform some sanity checks on the layout
1393     bmtProp->fNoSanityChecks = ((g_pObjectClass == NULL) || pModule == g_pObjectClass->GetModule()) ||
1394 #ifdef FEATURE_READYTORUN
1395         // No sanity checks for ready-to-run compiled images if possible
1396         (pModule->IsReadyToRun() && pModule->GetReadyToRunInfo()->SkipTypeValidation()) ||
1397 #endif
1398         // No sanity checks for real generic instantiations
1399         !bmtGenerics->IsTypicalTypeDefinition();
1400
1401     // Interfaces have a parent class of Object, but we don't really want to inherit all of
1402     // Object's virtual methods, so pretend we don't have a parent class - at the bottom of this
1403     // function we reset the parent class
1404     if (IsInterface())
1405     {
1406         bmtInternal->pType->SetParentType(NULL);
1407         bmtInternal->pParentMT = NULL;
1408     }
1409
1410     unsigned totalDeclaredFieldSize=0;
1411
1412     // Check to see if the class is a valuetype; but we don't want to mark System.Enum
1413     // as a ValueType. To accomplish this, the check takes advantage of the fact
1414     // that System.ValueType and System.Enum are loaded one immediately after the
1415     // other in that order, and so if the parent MethodTable is System.ValueType and
1416     // the System.Enum MethodTable is unset, then we must be building System.Enum and
1417     // so we don't mark it as a ValueType.
1418     if(HasParent() &&
1419        ((g_pEnumClass != NULL && GetParentMethodTable() == g_pValueTypeClass) ||
1420         GetParentMethodTable() == g_pEnumClass))
1421     {
1422         bmtProp->fIsValueClass = true;
1423
1424         HRESULT hr = GetMDImport()->GetCustomAttributeByName(bmtInternal->pType->GetTypeDefToken(),
1425                                                                 g_CompilerServicesUnsafeValueTypeAttribute,
1426                                                                 NULL, NULL);
1427         IfFailThrow(hr);
1428         if (hr == S_OK)
1429         {
1430             SetUnsafeValueClass();
1431         }
1432
1433         hr = GetMDImport()->GetCustomAttributeByName(bmtInternal->pType->GetTypeDefToken(),
1434             g_CompilerServicesIsByRefLikeAttribute,
1435             NULL, NULL);
1436         IfFailThrow(hr);
1437         if (hr == S_OK)
1438         {
1439             bmtFP->fIsByRefLikeType = true;
1440         }
1441     }
1442
1443     // Check to see if the class is an enumeration. No fancy checks like the one immediately
1444     // above for value types are necessary here.
1445     if(HasParent() && GetParentMethodTable() == g_pEnumClass)
1446     {
1447         bmtProp->fIsEnum = true;
1448
1449         // Ensure we don't have generic enums, or at least enums that have a
1450         // different number of type parameters from their enclosing class.
1451         // The goal is to ensure that the enum's values can't depend on the
1452         // type parameters in any way.  And we don't see any need for an
1453         // enum to have additional type parameters.
1454         if (bmtGenerics->GetNumGenericArgs() != 0)
1455         {
1456             // Nested enums can have generic type parameters from their enclosing class.
1457             // CLS rules require type parameters to be propogated to nested types.
1458             // Note that class G<T> { enum E { } } will produce "G`1+E<T>".
1459             // We want to disallow class G<T> { enum E<T, U> { } }
1460             // Perhaps the IL equivalent of class G<T> { enum E { } } should be legal.
1461             if (!IsNested())
1462             {
1463                 BuildMethodTableThrowException(IDS_CLASSLOAD_ENUM_EXTRA_GENERIC_TYPE_PARAM);
1464             }
1465
1466             mdTypeDef tdEnclosing = mdTypeDefNil;
1467             HRESULT hr = GetMDImport()->GetNestedClassProps(GetCl(), &tdEnclosing);
1468             if (FAILED(hr))
1469                 ThrowHR(hr, BFA_UNABLE_TO_GET_NESTED_PROPS);
1470
1471             HENUMInternalHolder   hEnumGenericPars(GetMDImport());
1472             if (FAILED(hEnumGenericPars.EnumInitNoThrow(mdtGenericParam, tdEnclosing)))
1473             {
1474                 GetAssembly()->ThrowTypeLoadException(GetMDImport(), tdEnclosing, IDS_CLASSLOAD_BADFORMAT);
1475             }
1476
1477             if (hEnumGenericPars.EnumGetCount() != bmtGenerics->GetNumGenericArgs())
1478             {
1479                 BuildMethodTableThrowException(IDS_CLASSLOAD_ENUM_EXTRA_GENERIC_TYPE_PARAM);
1480             }
1481         }
1482     }
1483
1484     // If this type is marked by [Intrinsic] attribute, it may be specially treated by the runtime/compiler
1485     // SIMD types have [Intrinsic] attribute, for example
1486     //
1487     // We check this here fairly early to ensure other downstream checks on these types can be slightly more efficient.
1488     if (GetModule()->IsSystem() || GetAssembly()->IsSIMDVectorAssembly())
1489     {
1490         HRESULT hr = GetMDImport()->GetCustomAttributeByName(bmtInternal->pType->GetTypeDefToken(),
1491             g_CompilerServicesIntrinsicAttribute,
1492             NULL,
1493             NULL);
1494
1495         if (hr == S_OK)
1496         {
1497             bmtProp->fIsIntrinsicType = true;
1498         }
1499     }
1500
1501 #if defined(_TARGET_X86_) || defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_)
1502     if (bmtProp->fIsIntrinsicType && !bmtGenerics->HasInstantiation())
1503     {
1504         LPCUTF8 className;
1505         LPCUTF8 nameSpace;
1506         HRESULT hr = GetMDImport()->GetNameOfTypeDef(bmtInternal->pType->GetTypeDefToken(), &className, &nameSpace);
1507
1508 #if defined(_TARGET_ARM64_)
1509         // All the funtions in System.Runtime.Intrinsics.Arm.Arm64 are hardware intrinsics.
1510         if (hr == S_OK && strcmp(nameSpace, "System.Runtime.Intrinsics.Arm.Arm64") == 0)
1511 #else
1512         // All the funtions in System.Runtime.Intrinsics.X86 are hardware intrinsics.
1513         if (bmtInternal->pType->IsNested())
1514         {
1515             IfFailThrow(GetMDImport()->GetNameOfTypeDef(bmtInternal->pType->GetEnclosingTypeToken(), NULL, &nameSpace));
1516         }
1517         
1518         if (hr == S_OK && (strcmp(nameSpace, "System.Runtime.Intrinsics.X86") == 0))
1519 #endif
1520         {
1521             if (IsCompilationProcess())
1522             {
1523                 // Disable AOT compiling for managed implementation of hardware intrinsics in mscorlib.
1524                 // We specially treat them here to ensure correct ISA features are set during compilation
1525                 COMPlusThrow(kTypeLoadException, IDS_EE_HWINTRINSIC_NGEN_DISALLOWED);
1526             }
1527             bmtProp->fIsHardwareIntrinsic = true;
1528         }
1529     }
1530 #endif
1531
1532     // Com Import classes are special. These types must derive from System.Object,
1533     // and we then substitute the parent with System._ComObject.
1534     if (IsComImport() && !IsEnum() && !IsInterface() && !IsValueClass() && !IsDelegate())
1535     {
1536 #ifdef FEATURE_COMINTEROP        
1537         // ComImport classes must either extend from Object or be a WinRT class
1538         // that extends from another WinRT class (and so form a chain of WinRT classes
1539         // that ultimately extend from object).
1540         MethodTable* pMTParent = GetParentMethodTable();
1541         if ((pMTParent == NULL) || !(
1542                 // is the parent valid?
1543                 (pMTParent == g_pObjectClass) ||
1544                 (GetHalfBakedClass()->IsProjectedFromWinRT() && pMTParent->IsProjectedFromWinRT())
1545                 ))
1546         {
1547             BuildMethodTableThrowException(IDS_CLASSLOAD_CANTEXTEND);
1548         }
1549
1550         if (HasLayout())
1551         {
1552             // ComImport classes cannot have layout information.
1553             BuildMethodTableThrowException(IDS_CLASSLOAD_COMIMPCANNOTHAVELAYOUT);
1554         }
1555
1556         if (pMTParent == g_pObjectClass)
1557         {                
1558             // ComImport classes ultimately extend from our __ComObject or RuntimeClass class
1559             MethodTable *pCOMMT = NULL;
1560             if (GetHalfBakedClass()->IsProjectedFromWinRT())
1561                 pCOMMT = g_pBaseRuntimeClass;
1562             else
1563                 pCOMMT = g_pBaseCOMObject;
1564             
1565             _ASSERTE(pCOMMT);
1566
1567             // We could have had COM interop classes derive from System._ComObject,
1568             // but instead we have them derive from System.Object, have them set the
1569             // ComImport bit in the type attributes, and then we swap out the parent
1570             // type under the covers.
1571             bmtInternal->pType->SetParentType(CreateTypeChain(pCOMMT, Substitution()));
1572             bmtInternal->pParentMT = pCOMMT;
1573         }
1574 #endif
1575         // if the current class is imported
1576         bmtProp->fIsComObjectType = true;
1577     }
1578
1579 #ifdef FEATURE_COMINTEROP
1580     if (GetHalfBakedClass()->IsProjectedFromWinRT() && IsValueClass() && !IsEnum())
1581     {
1582         // WinRT structures must have sequential layout
1583         if (!GetHalfBakedClass()->HasSequentialLayout())
1584         {
1585             BuildMethodTableThrowException(IDS_EE_STRUCTLAYOUT_WINRT);
1586         }
1587     }
1588
1589     // Check for special COM interop types.
1590     CheckForSpecialTypes();
1591
1592     CheckForTypeEquivalence(cBuildingInterfaceList, pBuildingInterfaceList);
1593
1594     if (HasParent())
1595     {   // Types that inherit from com object types are themselves com object types.
1596         if (GetParentMethodTable()->IsComObjectType())
1597         {
1598             // if the parent class is of ComObjectType
1599             // so is the child
1600             bmtProp->fIsComObjectType = true;
1601         }
1602
1603 #ifdef FEATURE_TYPEEQUIVALENCE
1604         // If your parent is type equivalent then so are you
1605         if (GetParentMethodTable()->HasTypeEquivalence())
1606         {
1607             bmtProp->fHasTypeEquivalence = true;
1608         }
1609 #endif
1610     }
1611
1612 #endif // FEATURE_COMINTEROP
1613
1614     if (!HasParent() && !IsInterface())
1615     {
1616         if(g_pObjectClass != NULL)
1617         {
1618             if(!IsGlobalClass())
1619             {
1620                 // Non object derived types that are not the global class are prohibited by spec
1621                 BuildMethodTableThrowException(IDS_CLASSLOAD_PARENTNULL);
1622             }
1623         }
1624     }
1625
1626     // NOTE: This appears to be the earliest point during class loading that other classes MUST be loaded
1627     // resolve unresolved interfaces, determine an upper bound on the size of the interface map,
1628     // and determine the size of the largest interface (in # slots)
1629     ResolveInterfaces(cBuildingInterfaceList, pBuildingInterfaceList);
1630
1631     // Enumerate this class's methodImpls
1632     EnumerateMethodImpls();
1633
1634     // Enumerate this class's methods and fields
1635     EnumerateClassMethods();
1636     ValidateMethods();
1637
1638     EnumerateClassFields();
1639
1640     // Import the slots of the parent for use in placing this type's methods.
1641     ImportParentMethods();
1642
1643     // This will allocate the working versions of the VTable and NonVTable in bmtVT
1644     AllocateWorkingSlotTables();
1645
1646     // Allocate a MethodDesc* for each method (needed later when doing interfaces), and a FieldDesc* for each field
1647     AllocateFieldDescs();
1648
1649     // Copy the parent's vtable into the current type's vtable
1650     CopyParentVtable();
1651
1652     bmtVT->pDispatchMapBuilder = new (GetStackingAllocator()) DispatchMapBuilder(GetStackingAllocator());
1653
1654     // Determine vtable placement for each member in this class
1655     PlaceVirtualMethods();
1656     PlaceNonVirtualMethods();
1657
1658     // Allocate MethodDescs (expects methods placed methods)
1659     AllocAndInitMethodDescs();
1660
1661     if (IsInterface())
1662     {
1663         //
1664         // We need to process/place method impls for default interface method overrides.
1665         // We won't build dispatch map for interfaces, though.
1666         //
1667         ProcessMethodImpls();
1668         PlaceMethodImpls();
1669     }
1670     else
1671     {
1672         //
1673         // If we are a class, then there may be some unplaced vtable methods (which are by definition
1674         // interface methods, otherwise they'd already have been placed).  Place as many unplaced methods
1675         // as possible, in the order preferred by interfaces.  However, do not allow any duplicates - once
1676         // a method has been placed, it cannot be placed again - if we are unable to neatly place an interface,
1677         // create duplicate slots for it starting at dwCurrentDuplicateVtableSlot.  Fill out the interface
1678         // map for all interfaces as they are placed.
1679         //
1680         // If we are an interface, then all methods are already placed.  Fill out the interface map for
1681         // interfaces as they are placed.
1682         //
1683         ComputeInterfaceMapEquivalenceSet();
1684
1685         PlaceInterfaceMethods();
1686
1687         ProcessMethodImpls();
1688         ProcessInexactMethodImpls();
1689         PlaceMethodImpls();
1690
1691         if (!bmtProp->fNoSanityChecks)
1692         {
1693             // Now that interface method implementation have been fully resolved,
1694             // we need to make sure that type constraints are also met.
1695             ValidateInterfaceMethodConstraints();
1696         }
1697     }
1698
1699     // Verify that we have not overflowed the number of slots.
1700     if (!FitsInU2((UINT64)bmtVT->pSlotTable->GetSlotCount()))
1701     {
1702         BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
1703     }
1704
1705     // ensure we didn't overflow the temporary vtable
1706     _ASSERTE(bmtVT->pSlotTable->GetSlotCount() <= bmtVT->dwMaxVtableSize);
1707
1708     // Allocate and initialize the dictionary for the type. This will be filled out later
1709     // with the final values.
1710     AllocAndInitDictionary();
1711
1712     ////////////////////////////////////////////////////////////////////////////////////////////////
1713     // Fields
1714     //
1715
1716     // We decide here if we need a dynamic entry for our statics. We need it here because
1717     // the offsets of our fields will depend on this. For the dynamic case (which requires
1718     // an extra indirection (indirect depending of methodtable) we'll allocate the slot
1719     // in setupmethodtable
1720     if (((pAllocator->IsCollectible() ||  pModule->IsReflection() || bmtGenerics->HasInstantiation() || !pModule->IsStaticStoragePrepared(cl)) &&
1721         (bmtVT->GetClassCtorSlotIndex() != INVALID_SLOT_INDEX || bmtEnumFields->dwNumStaticFields !=0))
1722 #ifdef EnC_SUPPORTED 
1723         // Classes in modules that have been edited (would do on class level if there were a
1724         // way to tell if the class had been edited) also have dynamic statics as the number
1725         // of statics might have changed, so can't use the static module-wide storage
1726         || (pModule->IsEditAndContinueEnabled() &&
1727                 ((EditAndContinueModule*)pModule)->GetApplyChangesCount() > CorDB_DEFAULT_ENC_FUNCTION_VERSION)
1728 #endif // EnC_SUPPORTED
1729         )
1730     {
1731         // We will need a dynamic id
1732         bmtProp->fDynamicStatics = true;
1733
1734         if (bmtGenerics->HasInstantiation())
1735         {
1736             bmtProp->fGenericsStatics = true;
1737         }
1738     }
1739
1740     // If not NULL, it means there are some by-value fields, and this contains an entry for each instance or static field,
1741     // which is NULL if not a by value field, and points to the EEClass of the field if a by value field.  Instance fields
1742     // come first, statics come second.
1743     MethodTable ** pByValueClassCache = NULL;
1744
1745     // Go thru all fields and initialize their FieldDescs.
1746     InitializeFieldDescs(GetApproxFieldDescListRaw(), pLayoutRawFieldInfos, bmtInternal, bmtGenerics,
1747         bmtMetaData, bmtEnumFields, bmtError,
1748         &pByValueClassCache, bmtMFDescs, bmtFP,
1749         &totalDeclaredFieldSize);
1750
1751     // Place regular static fields
1752     PlaceRegularStaticFields();
1753
1754     // Place thread static fields
1755     PlaceThreadStaticFields();
1756
1757     LOG((LF_CODESHARING,
1758             LL_INFO10000,
1759             "Placing %d statics (%d handles) for class %s.\n",
1760             GetNumStaticFields(), GetNumHandleRegularStatics() + GetNumHandleThreadStatics(),
1761             pszDebugName));
1762
1763     if (IsBlittable() || IsManagedSequential())
1764     {
1765         bmtFP->NumGCPointerSeries = 0;
1766         bmtFP->NumInstanceGCPointerFields = 0;
1767
1768         _ASSERTE(HasLayout());
1769
1770         bmtFP->NumInstanceFieldBytes = IsBlittable() ? GetLayoutInfo()->m_cbNativeSize
1771                                                      : GetLayoutInfo()->m_cbManagedSize;
1772
1773         // For simple Blittable types we still need to check if they have any overlapping 
1774         // fields and call the method SetHasOverLayedFields() when they are detected.
1775         //
1776         if (HasExplicitFieldOffsetLayout())
1777         {
1778             _ASSERTE(!bmtGenerics->fContainsGenericVariables);   // A simple Blittable type can't ever be an open generic type.
1779             HandleExplicitLayout(pByValueClassCache);
1780         }
1781     }
1782     else
1783     {
1784         _ASSERTE(!IsBlittable());
1785         // HandleExplicitLayout fails for the GenericTypeDefinition when
1786         // it will succeed for some particular instantiations.
1787         // Thus we only do explicit layout for real instantiations, e.g. C<int>, not
1788         // the open types such as the GenericTypeDefinition C<!0> or any
1789         // of the "fake" types involving generic type variables which are
1790         // used for reflection and verification, e.g. C<List<!0>>.
1791         // 
1792         if (!bmtGenerics->fContainsGenericVariables && HasExplicitFieldOffsetLayout())
1793         {
1794             HandleExplicitLayout(pByValueClassCache);
1795         }
1796         else
1797         {
1798             // Place instance fields
1799             PlaceInstanceFields(pByValueClassCache);
1800         }
1801     }
1802
1803     if (CheckIfSIMDAndUpdateSize())
1804     {
1805         totalDeclaredFieldSize = bmtFP->NumInstanceFieldBytes;
1806     }
1807
1808     // We enforce that all value classes have non-zero size
1809     if (IsValueClass() && bmtFP->NumInstanceFieldBytes == 0)
1810     {
1811         BuildMethodTableThrowException(IDS_CLASSLOAD_ZEROSIZE);
1812     }
1813     
1814     if (bmtFP->fHasSelfReferencingStaticValueTypeField_WithRVA)
1815     {   // Verify self-referencing statics with RVA (now when the ValueType size is known)
1816         VerifySelfReferencingStaticValueTypeFields_WithRVA(pByValueClassCache);
1817     }
1818     
1819
1820     // Now setup the method table
1821
1822 #ifdef FEATURE_PREJIT
1823     Module *pComputedPZM = pLoaderModule;
1824
1825     if (bmtGenerics->GetNumGenericArgs() > 0)
1826     {
1827         pComputedPZM = Module::ComputePreferredZapModule(pModule, bmtGenerics->GetInstantiation());
1828     }
1829
1830     SetupMethodTable2(pLoaderModule, pComputedPZM);
1831 #else // FEATURE_PREJIT
1832     SetupMethodTable2(pLoaderModule);
1833 #endif // FEATURE_PREJIT
1834
1835     MethodTable * pMT = GetHalfBakedMethodTable();
1836
1837 #ifdef FEATURE_64BIT_ALIGNMENT
1838     if (GetHalfBakedClass()->IsAlign8Candidate())
1839         pMT->SetRequiresAlign8();
1840 #endif
1841
1842     if (bmtGenerics->pVarianceInfo != NULL)
1843     {
1844         pMT->SetHasVariance();
1845     }
1846
1847     if (bmtFP->NumRegularStaticGCBoxedFields != 0)
1848     {
1849         pMT->SetHasBoxedRegularStatics();
1850     }
1851
1852     if (bmtFP->fIsByRefLikeType)
1853     {
1854         pMT->SetIsByRefLike();
1855     }
1856
1857     if (IsValueClass())
1858     {
1859         if (bmtFP->NumInstanceFieldBytes != totalDeclaredFieldSize || HasOverLayedField())
1860             GetHalfBakedClass()->SetIsNotTightlyPacked();
1861
1862 #ifdef FEATURE_HFA
1863         GetHalfBakedClass()->CheckForHFA(pByValueClassCache);
1864 #endif
1865 #ifdef UNIX_AMD64_ABI
1866 #ifdef FEATURE_HFA
1867 #error Can't have FEATURE_HFA and UNIX_AMD64_ABI defined at the same time.
1868 #endif // FEATURE_HFA
1869         SystemVAmd64CheckForPassStructInRegister();
1870 #endif // UNIX_AMD64_ABI
1871     }
1872
1873 #ifdef UNIX_AMD64_ABI
1874 #ifdef FEATURE_HFA
1875 #error Can't have FEATURE_HFA and UNIX_AMD64_ABI defined at the same time.
1876 #endif // FEATURE_HFA
1877     if (HasLayout())
1878     {
1879         SystemVAmd64CheckForPassNativeStructInRegister();
1880     }
1881 #endif // UNIX_AMD64_ABI
1882 #ifdef FEATURE_HFA
1883     if (HasLayout())
1884     {
1885         GetHalfBakedClass()->CheckForNativeHFA();
1886     }
1887 #endif
1888
1889 #ifdef _DEBUG 
1890     pMT->SetDebugClassName(GetDebugClassName());
1891 #endif
1892
1893 #ifdef FEATURE_COMINTEROP 
1894     if (IsInterface())
1895     {
1896         GetCoClassAttribInfo();
1897     }
1898 #endif // FEATURE_COMINTEROP
1899
1900     if (HasExplicitFieldOffsetLayout())
1901         // Perform relevant GC calculations for tdexplicit
1902         HandleGCForExplicitLayout();
1903     else
1904         // Perform relevant GC calculations for value classes
1905         HandleGCForValueClasses(pByValueClassCache);
1906
1907         // GC reqires the series to be sorted.
1908         // TODO: fix it so that we emit them in the correct order in the first place.
1909     if (pMT->ContainsPointers())
1910     {
1911         CGCDesc* gcDesc = CGCDesc::GetCGCDescFromMT(pMT);
1912         qsort(gcDesc->GetLowestSeries(), (int)gcDesc->GetNumSeries(), sizeof(CGCDescSeries), compareCGCDescSeries);
1913     }
1914
1915     SetFinalizationSemantics();
1916
1917     // Allocate dynamic slot if necessary
1918     if (bmtProp->fDynamicStatics)
1919     {
1920         if (bmtProp->fGenericsStatics)
1921         {
1922             FieldDesc* pStaticFieldDescs = NULL;
1923
1924             if (bmtEnumFields->dwNumStaticFields != 0)
1925             {
1926                 pStaticFieldDescs = pMT->GetApproxFieldDescListRaw() + bmtEnumFields->dwNumInstanceFields;
1927             }
1928
1929             pMT->SetupGenericsStaticsInfo(pStaticFieldDescs);
1930         }
1931         else
1932         {
1933             // Get an id for the dynamic class. We store it in the class because
1934             // no class that is persisted in ngen should have it (ie, if the class is ngened
1935             // The id is stored in an optional field so we need to ensure an optional field descriptor has
1936             // been allocated for this EEClass instance.
1937             EnsureOptionalFieldsAreAllocated(GetHalfBakedClass(), m_pAllocMemTracker, pAllocator->GetLowFrequencyHeap());
1938             SetModuleDynamicID(GetModule()->AllocateDynamicEntry(pMT));
1939         }
1940     }
1941
1942     //
1943     // if there are context or thread static set the info in the method table optional members
1944     //
1945
1946     // Check for the RemotingProxy Attribute
1947     // structs with GC pointers MUST be pointer sized aligned because the GC assumes it
1948     if (IsValueClass() && pMT->ContainsPointers() && (bmtFP->NumInstanceFieldBytes % TARGET_POINTER_SIZE != 0))
1949     {
1950         BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
1951     }
1952
1953     if (IsInterface())
1954     {
1955         // Reset parent class
1956         pMT->SetParentMethodTable (g_pObjectClass);
1957     }
1958
1959 #ifdef _DEBUG 
1960     // Reset the debug method names for BoxedEntryPointStubs
1961     // so they reflect the very best debug information for the methods
1962     {
1963         DeclaredMethodIterator methIt(*this);
1964         while (methIt.Next())
1965         {
1966             if (methIt->GetUnboxedMethodDesc() != NULL)
1967             {
1968                 {
1969                     MethodDesc *pMD = methIt->GetUnboxedMethodDesc();
1970                     StackSString name(SString::Utf8);
1971                     TypeString::AppendMethodDebug(name, pMD);
1972                     StackScratchBuffer buff;
1973                     const char* pDebugNameUTF8 = name.GetUTF8(buff);
1974                     S_SIZE_T safeLen = S_SIZE_T(strlen(pDebugNameUTF8)) + S_SIZE_T(1);
1975                     if(safeLen.IsOverflow()) COMPlusThrowHR(COR_E_OVERFLOW);
1976                     size_t len = safeLen.Value();
1977                     pMD->m_pszDebugMethodName = (char*) AllocateFromLowFrequencyHeap(safeLen);
1978                     _ASSERTE(pMD->m_pszDebugMethodName);
1979                     strcpy_s((char *) pMD->m_pszDebugMethodName, len, pDebugNameUTF8);
1980                 }
1981
1982                 {
1983                     MethodDesc *pMD = methIt->GetMethodDesc();
1984
1985                     StackSString name(SString::Utf8);
1986                     TypeString::AppendMethodDebug(name, pMD);
1987                     StackScratchBuffer buff;
1988                     const char* pDebugNameUTF8 = name.GetUTF8(buff);
1989                     S_SIZE_T safeLen = S_SIZE_T(strlen(pDebugNameUTF8))+S_SIZE_T(1);
1990                     if(safeLen.IsOverflow()) COMPlusThrowHR(COR_E_OVERFLOW);
1991                     size_t len = safeLen.Value();
1992                     pMD->m_pszDebugMethodName = (char*) AllocateFromLowFrequencyHeap(safeLen);
1993                     _ASSERTE(pMD->m_pszDebugMethodName);
1994                     strcpy_s((char *) pMD->m_pszDebugMethodName, len, pDebugNameUTF8);
1995                 }
1996             }
1997         }
1998     }
1999 #endif // _DEBUG
2000
2001
2002     //If this is a value type, then propagate the UnsafeValueTypeAttribute from
2003     //its instance members to this type.
2004     if (IsValueClass() && !IsUnsafeValueClass())
2005     {
2006         ApproxFieldDescIterator fields(GetHalfBakedMethodTable(),
2007                                        ApproxFieldDescIterator::INSTANCE_FIELDS );
2008         FieldDesc * current;
2009         while (NULL != (current = fields.Next()))
2010         {
2011             CONSISTENCY_CHECK(!current->IsStatic());
2012             if (current->GetFieldType() == ELEMENT_TYPE_VALUETYPE)
2013             {
2014                 TypeHandle th = current->LookupApproxFieldTypeHandle();
2015                 CONSISTENCY_CHECK(!th.IsNull());
2016                 if (th.AsMethodTable()->GetClass()->IsUnsafeValueClass())
2017                 {
2018                     SetUnsafeValueClass();
2019                     break;
2020                 }
2021             }
2022         }
2023     }
2024
2025 #ifdef FEATURE_ICASTABLE
2026     if (!IsValueClass() && g_pICastableInterface != NULL && pMT->CanCastToInterface(g_pICastableInterface))
2027     {
2028         pMT->SetICastable();
2029     }
2030 #endif // FEATURE_ICASTABLE       
2031
2032     // Grow the typedef ridmap in advance as we can't afford to
2033     // fail once we set the resolve bit
2034     pModule->EnsureTypeDefCanBeStored(bmtInternal->pType->GetTypeDefToken());
2035
2036     // Grow the tables in advance so that RID map filling cannot fail
2037     // once we're past the commit point.
2038     EnsureRIDMapsCanBeFilled();
2039
2040     {
2041         // NOTE. NOTE!! the EEclass can now be accessed by other threads.
2042         // Do NOT place any initialization after this point.
2043         // You may NOT fail the call after this point.
2044         FAULT_FORBID();
2045         CANNOTTHROWCOMPLUSEXCEPTION();
2046
2047         /*
2048         GetMemTracker()->SuppressRelease();
2049         */
2050     }
2051     
2052 #ifdef _DEBUG 
2053     if (g_pConfig->ShouldDumpOnClassLoad(pszDebugName))
2054     {
2055         LOG((LF_ALWAYS, LL_ALWAYS, "Method table summary for '%s':\n", pszDebugName));
2056         LOG((LF_ALWAYS, LL_ALWAYS, "Number of static fields: %d\n", bmtEnumFields->dwNumStaticFields));
2057         LOG((LF_ALWAYS, LL_ALWAYS, "Number of instance fields: %d\n", bmtEnumFields->dwNumInstanceFields));
2058         LOG((LF_ALWAYS, LL_ALWAYS, "Number of static obj ref fields: %d\n", bmtEnumFields->dwNumStaticObjRefFields));
2059         LOG((LF_ALWAYS, LL_ALWAYS, "Number of static boxed fields: %d\n", bmtEnumFields->dwNumStaticBoxedFields));
2060         LOG((LF_ALWAYS, LL_ALWAYS, "Number of declared fields: %d\n", NumDeclaredFields()));
2061         LOG((LF_ALWAYS, LL_ALWAYS, "Number of declared methods: %d\n", NumDeclaredMethods()));
2062         LOG((LF_ALWAYS, LL_ALWAYS, "Number of declared non-abstract methods: %d\n", bmtMethod->dwNumDeclaredNonAbstractMethods));
2063         pMT->Debug_DumpInterfaceMap("Approximate");
2064         pMT->DebugDumpVtable(pszDebugName, FALSE);
2065         pMT->DebugDumpFieldLayout(pszDebugName, FALSE);
2066         pMT->DebugDumpGCDesc(pszDebugName, FALSE);
2067         pMT->Debug_DumpDispatchMap();
2068     }
2069 #endif //_DEBUG
2070     
2071     STRESS_LOG3(LF_CLASSLOADER,  LL_INFO1000, "MethodTableBuilder: finished method table for module %p token %x = %pT \n",
2072         pModule,
2073         GetCl(),
2074         GetHalfBakedMethodTable());
2075
2076 #ifdef FEATURE_PREJIT
2077     _ASSERTE(pComputedPZM == Module::GetPreferredZapModuleForMethodTable(pMT));
2078 #endif // FEATURE_PREJIT
2079
2080     return GetHalfBakedMethodTable();
2081 } // MethodTableBuilder::BuildMethodTableThrowing
2082 #ifdef _PREFAST_ 
2083 #pragma warning(pop)
2084 #endif
2085
2086
2087 //---------------------------------------------------------------------------------------
2088 // 
2089 // Resolve unresolved interfaces, determine an upper bound on the size of the interface map.
2090 // 
2091 VOID 
2092 MethodTableBuilder::ResolveInterfaces(
2093     WORD                      cBuildingInterfaceList, 
2094     BuildingInterfaceInfo_t * pBuildingInterfaceList)
2095 {
2096     CONTRACTL
2097     {
2098         STANDARD_VM_CHECK;
2099         PRECONDITION(CheckPointer(this));
2100         PRECONDITION(CheckPointer(bmtAllocator));
2101         PRECONDITION(CheckPointer(bmtInterface));
2102         PRECONDITION(CheckPointer(bmtVT));
2103         PRECONDITION(CheckPointer(bmtParent));
2104     }
2105     CONTRACTL_END;
2106
2107     // resolve unresolved interfaces and determine the size of the largest interface (in # slots)
2108
2109
2110     LoadApproxInterfaceMap();
2111
2112     // Inherit parental slot counts
2113     //@TODO: This doesn't belong here.
2114     if (HasParent())
2115     {
2116         MethodTable * pParentClass = GetParentMethodTable();
2117         PREFIX_ASSUME(pParentClass != NULL);
2118
2119         bmtParent->NumParentPointerSeries  = pParentClass->ContainsPointers() ?
2120             (DWORD)CGCDesc::GetCGCDescFromMT(pParentClass)->GetNumSeries() : 0;
2121
2122         if (pParentClass->HasFieldsWhichMustBeInited())
2123         {
2124             SetHasFieldsWhichMustBeInited();
2125         }
2126 #ifdef FEATURE_READYTORUN
2127         if (!(IsValueClass() || (pParentClass == g_pObjectClass)))
2128         {
2129             CheckLayoutDependsOnOtherModules(pParentClass);
2130         }
2131 #endif
2132     }
2133     else
2134     {
2135         bmtParent->NumParentPointerSeries  = 0;
2136     }
2137 } // MethodTableBuilder::ResolveInterfaces
2138
2139 //*******************************************************************************
2140 /* static */
2141 int __cdecl MethodTableBuilder::bmtMetaDataInfo::MethodImplTokenPair::Compare(
2142         const void *elem1,
2143         const void *elem2)
2144 {
2145     STATIC_CONTRACT_LEAF;
2146     MethodImplTokenPair *e1 = (MethodImplTokenPair *)elem1;
2147     MethodImplTokenPair *e2 = (MethodImplTokenPair *)elem2;
2148     if (e1->methodBody < e2->methodBody) return -1;
2149     else if (e1->methodBody > e2->methodBody) return 1;
2150     else if (e1->methodDecl < e2->methodDecl) return -1;
2151     else if (e1->methodDecl > e2->methodDecl) return 1;
2152     else return 0;
2153 }
2154
2155 //*******************************************************************************
2156 /* static */
2157 BOOL MethodTableBuilder::bmtMetaDataInfo::MethodImplTokenPair::Equal(
2158         const MethodImplTokenPair *elem1,
2159         const MethodImplTokenPair *elem2)
2160 {
2161     STATIC_CONTRACT_LEAF;
2162     return ((elem1->methodBody == elem2->methodBody) &&
2163             (elem1->methodDecl == elem2->methodDecl));
2164 }
2165
2166 //*******************************************************************************
2167 VOID
2168 MethodTableBuilder::EnumerateMethodImpls()
2169 {
2170     STANDARD_VM_CONTRACT;
2171
2172     HRESULT hr = S_OK;
2173     IMDInternalImport * pMDInternalImport = GetMDImport();
2174     DWORD rid, maxRidMD, maxRidMR;
2175     HENUMInternalMethodImplHolder hEnumMethodImpl(pMDInternalImport);
2176     hr = hEnumMethodImpl.EnumMethodImplInitNoThrow(GetCl());
2177     
2178     if (FAILED(hr))
2179     {
2180         BuildMethodTableThrowException(hr, *bmtError);
2181     }
2182     
2183     // This gets the count out of the metadata interface.
2184     bmtMethod->dwNumberMethodImpls = hEnumMethodImpl.EnumMethodImplGetCount();
2185     bmtMethod->dwNumberInexactMethodImplCandidates = 0;
2186
2187     // This is the first pass. In this we will simply enumerate the token pairs and fill in
2188     // the data structures. In addition, we'll sort the list and eliminate duplicates.
2189     if (bmtMethod->dwNumberMethodImpls > 0)
2190     {
2191         //
2192         // Allocate the structures to keep track of the token pairs
2193         //
2194         bmtMetaData->rgMethodImplTokens = new (GetStackingAllocator())
2195             bmtMetaDataInfo::MethodImplTokenPair[bmtMethod->dwNumberMethodImpls];
2196
2197         // Iterate through each MethodImpl declared on this class
2198         for (DWORD i = 0; i < bmtMethod->dwNumberMethodImpls; i++)
2199         {
2200             hr = hEnumMethodImpl.EnumMethodImplNext(
2201                 &bmtMetaData->rgMethodImplTokens[i].methodBody,
2202                 &bmtMetaData->rgMethodImplTokens[i].methodDecl);
2203             bmtMetaData->rgMethodImplTokens[i].fConsiderDuringInexactMethodImplProcessing = false;
2204             bmtMetaData->rgMethodImplTokens[i].fThrowIfUnmatchedDuringInexactMethodImplProcessing = false;
2205             bmtMetaData->rgMethodImplTokens[i].interfaceEquivalenceSet = 0;
2206
2207             if (FAILED(hr))
2208             {
2209                 BuildMethodTableThrowException(hr, *bmtError);
2210             }
2211             // Grab the next set of body/decl tokens
2212             if (hr == S_FALSE)
2213             {
2214                 // In the odd case that the enumerator fails before we've reached the total reported
2215                 // entries, let's reset the count and just break out. (Should we throw?)
2216                 bmtMethod->dwNumberMethodImpls = i;
2217                 break;
2218             }
2219         }
2220
2221         // No need to do any sorting or duplicate elimination if there's not two or more methodImpls
2222         if (bmtMethod->dwNumberMethodImpls > 1)
2223         {
2224             // Now sort
2225             qsort(bmtMetaData->rgMethodImplTokens,
2226                   bmtMethod->dwNumberMethodImpls,
2227                   sizeof(bmtMetaDataInfo::MethodImplTokenPair),
2228                   &bmtMetaDataInfo::MethodImplTokenPair::Compare);
2229
2230             // Now eliminate duplicates
2231             for (DWORD i = 0; i < bmtMethod->dwNumberMethodImpls - 1; i++)
2232             {
2233                 CONSISTENCY_CHECK((i + 1) < bmtMethod->dwNumberMethodImpls);
2234
2235                 bmtMetaDataInfo::MethodImplTokenPair *e1 = &bmtMetaData->rgMethodImplTokens[i];
2236                 bmtMetaDataInfo::MethodImplTokenPair *e2 = &bmtMetaData->rgMethodImplTokens[i + 1];
2237
2238                 // If the pair are equal, eliminate the first one, and reduce the total count by one.
2239                 if (bmtMetaDataInfo::MethodImplTokenPair::Equal(e1, e2))
2240                 {
2241                     DWORD dwCopyNum = bmtMethod->dwNumberMethodImpls - (i + 1);
2242                     memcpy(e1, e2, dwCopyNum * sizeof(bmtMetaDataInfo::MethodImplTokenPair));
2243                     bmtMethod->dwNumberMethodImpls--;
2244                     CONSISTENCY_CHECK(bmtMethod->dwNumberMethodImpls > 0);
2245                 }
2246             }
2247         }
2248     }
2249
2250     if (bmtMethod->dwNumberMethodImpls != 0)
2251     {
2252         //
2253         // Allocate the structures to keep track of the impl matches
2254         //
2255         bmtMetaData->pMethodDeclSubsts = new (GetStackingAllocator())
2256             Substitution[bmtMethod->dwNumberMethodImpls];
2257
2258         // These are used for verification
2259         maxRidMD = pMDInternalImport->GetCountWithTokenKind(mdtMethodDef);
2260         maxRidMR = pMDInternalImport->GetCountWithTokenKind(mdtMemberRef);
2261
2262         // Iterate through each MethodImpl declared on this class
2263         for (DWORD i = 0; i < bmtMethod->dwNumberMethodImpls; i++)
2264         {
2265             PCCOR_SIGNATURE pSigDecl = NULL;
2266             PCCOR_SIGNATURE pSigBody = NULL;
2267             ULONG           cbSigDecl;
2268             ULONG           cbSigBody;
2269             mdToken tkParent;
2270
2271             mdToken theBody, theDecl;
2272             Substitution theDeclSubst(GetModule(), SigPointer(), NULL); // this can get updated later below.
2273
2274             theBody = bmtMetaData->rgMethodImplTokens[i].methodBody;
2275             theDecl = bmtMetaData->rgMethodImplTokens[i].methodDecl;
2276
2277             // IMPLEMENTATION LIMITATION: currently, we require that the body of a methodImpl
2278             // belong to the current type. This is because we need to allocate a different
2279             // type of MethodDesc for bodies that are part of methodImpls.
2280             if (TypeFromToken(theBody) != mdtMethodDef)
2281             {
2282                 hr = FindMethodDeclarationForMethodImpl(
2283                     theBody, 
2284                     &theBody, 
2285                     TRUE);
2286                 if (FAILED(hr))
2287                 {
2288                     BuildMethodTableThrowException(hr, IDS_CLASSLOAD_MI_ILLEGAL_BODY, mdMethodDefNil);
2289                 }
2290
2291                 // Make sure to update the stored token with the resolved token.
2292                 bmtMetaData->rgMethodImplTokens[i].methodBody = theBody;
2293             }
2294
2295             if (TypeFromToken(theBody) != mdtMethodDef)
2296             {
2297                 BuildMethodTableThrowException(BFA_METHODDECL_NOT_A_METHODDEF);
2298             }
2299             CONSISTENCY_CHECK(theBody == bmtMetaData->rgMethodImplTokens[i].methodBody);
2300
2301             //
2302             // Now that the tokens of Decl and Body are obtained, do the MD validation
2303             //
2304
2305             rid = RidFromToken(theDecl);
2306
2307             // Perform initial rudimentary validation of the token. Full token verification
2308             // will be done in TestMethodImpl when placing the methodImpls.
2309             if (TypeFromToken(theDecl) == mdtMethodDef)
2310             {
2311                 // Decl must be valid token
2312                 if ((rid == 0) || (rid > maxRidMD))
2313                 {
2314                     BuildMethodTableThrowException(IDS_CLASSLOAD_MI_ILLEGAL_TOKEN_DECL);
2315                 }
2316                 // Get signature and length
2317                 if (FAILED(pMDInternalImport->GetSigOfMethodDef(theDecl, &cbSigDecl, &pSigDecl)))
2318                 {
2319                     BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
2320                 }
2321             }
2322
2323             // The token is not a MethodDef (likely a MemberRef)
2324             else
2325             {
2326                 // Decl must be valid token
2327                 if ((TypeFromToken(theDecl) != mdtMemberRef) || (rid == 0) || (rid > maxRidMR))
2328                 {
2329                     bmtError->resIDWhy = IDS_CLASSLOAD_MI_ILLEGAL_TOKEN_DECL;
2330                     BuildMethodTableThrowException(IDS_CLASSLOAD_MI_ILLEGAL_TOKEN_DECL);
2331                 }
2332
2333                 // Get signature and length
2334                 LPCSTR szDeclName;
2335                 if (FAILED(pMDInternalImport->GetNameAndSigOfMemberRef(theDecl, &pSigDecl, &cbSigDecl, &szDeclName)))
2336                 {
2337                     BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
2338                 }
2339
2340                 // Get parent
2341                 hr = pMDInternalImport->GetParentToken(theDecl,&tkParent);
2342                 if (FAILED(hr))
2343                     BuildMethodTableThrowException(hr, *bmtError);
2344
2345                 theDeclSubst = Substitution(tkParent, GetModule(), NULL);
2346             }
2347
2348             // Perform initial rudimentary validation of the token. Full token verification
2349             // will be done in TestMethodImpl when placing the methodImpls.
2350             {
2351                 // Body must be valid token
2352                 rid = RidFromToken(theBody);
2353                 if ((rid == 0)||(rid > maxRidMD))
2354                 {
2355                     BuildMethodTableThrowException(IDS_CLASSLOAD_MI_ILLEGAL_TOKEN_BODY);
2356                 }
2357                 // Body's parent must be this class
2358                 hr = pMDInternalImport->GetParentToken(theBody,&tkParent);
2359                 if (FAILED(hr))
2360                     BuildMethodTableThrowException(hr, *bmtError);
2361                 if(tkParent != GetCl())
2362                 {
2363                     BuildMethodTableThrowException(IDS_CLASSLOAD_MI_ILLEGAL_BODY);
2364                 }
2365             }
2366             // Decl's and Body's signatures must match
2367             if(pSigDecl && cbSigDecl)
2368             {
2369                 if (FAILED(pMDInternalImport->GetSigOfMethodDef(theBody, &cbSigBody, &pSigBody)) || 
2370                     (pSigBody == NULL) || 
2371                     (cbSigBody == 0))
2372                 {
2373                     BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MISSING_SIG_BODY);
2374                 }
2375                 // Can't use memcmp because there may be two AssemblyRefs
2376                 // in this scope, pointing to the same assembly, etc.).
2377                 if (!MetaSig::CompareMethodSigs(
2378                         pSigDecl,
2379                         cbSigDecl,
2380                         GetModule(),
2381                         &theDeclSubst,
2382                         pSigBody,
2383                         cbSigBody,
2384                         GetModule(),
2385                         NULL))
2386                 {
2387                     BuildMethodTableThrowException(IDS_CLASSLOAD_MI_BODY_DECL_MISMATCH);
2388                 }
2389             }
2390             else
2391             {
2392                 BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MISSING_SIG_DECL);
2393             }
2394
2395             bmtMetaData->pMethodDeclSubsts[i] = theDeclSubst;
2396         }
2397     }
2398 } // MethodTableBuilder::EnumerateMethodImpls
2399
2400 //*******************************************************************************
2401 //
2402 // Find a method declaration that must reside in the scope passed in. This method cannot be called if
2403 // the reference travels to another scope.
2404 //
2405 // Protect against finding a declaration that lives within
2406 // us (the type being created)
2407 //
2408 HRESULT MethodTableBuilder::FindMethodDeclarationForMethodImpl(
2409             mdToken  pToken,       // Token that is being located (MemberRef or MemberDef)
2410             mdToken* pDeclaration, // [OUT] Method definition for Member
2411             BOOL fSameClass)       // Does the declaration need to be in this class
2412 {
2413     STANDARD_VM_CONTRACT;
2414
2415     HRESULT hr = S_OK;
2416
2417     IMDInternalImport *pMDInternalImport = GetMDImport();
2418
2419     PCCOR_SIGNATURE pSig;  // Signature of Member
2420     DWORD           cSig;
2421     LPCUTF8         szMember = NULL;
2422
2423     // The token should be a member ref or def. If it is a ref then we need to travel
2424     // back to us hopefully.
2425     if(TypeFromToken(pToken) == mdtMemberRef)
2426     {
2427         // Get the parent
2428         mdToken typeref;
2429         if (FAILED(pMDInternalImport->GetParentOfMemberRef(pToken, &typeref)))
2430         {
2431             BAD_FORMAT_NOTHROW_ASSERT(!"Invalid MemberRef record");
2432             IfFailRet(COR_E_TYPELOAD);
2433         }
2434         GOTPARENT:
2435         if (TypeFromToken(typeref) == mdtMethodDef)
2436         {   // If parent is a method def then this is a varags method
2437             mdTypeDef typeDef;
2438             hr = pMDInternalImport->GetParentToken(typeref, &typeDef);
2439
2440             if (TypeFromToken(typeDef) != mdtTypeDef)
2441             {   // A mdtMethodDef must be parented by a mdtTypeDef
2442                 BAD_FORMAT_NOTHROW_ASSERT(!"MethodDef without TypeDef as Parent");
2443                 IfFailRet(COR_E_TYPELOAD);
2444             }
2445
2446             BAD_FORMAT_NOTHROW_ASSERT(typeDef == GetCl());
2447
2448             // This is the real method we are overriding
2449             *pDeclaration = typeref;
2450         }
2451         else if (TypeFromToken(typeref) == mdtTypeSpec)
2452         {   // Added so that method impls can refer to instantiated interfaces or classes
2453             if (FAILED(pMDInternalImport->GetSigFromToken(typeref, &cSig, &pSig)))
2454             {
2455                 BAD_FORMAT_NOTHROW_ASSERT(!"Invalid TypeSpec record");
2456                 IfFailRet(COR_E_TYPELOAD);
2457             }
2458             CorElementType elemType = (CorElementType) *pSig++;
2459
2460             if (elemType == ELEMENT_TYPE_GENERICINST)
2461             {   // If this is a generic inst, we expect that the next elem is ELEMENT_TYPE_CLASS,
2462                 // which is handled in the case below.
2463                 elemType = (CorElementType) *pSig++;
2464                 BAD_FORMAT_NOTHROW_ASSERT(elemType == ELEMENT_TYPE_CLASS);
2465             }
2466
2467             if (elemType == ELEMENT_TYPE_CLASS)
2468             {   // This covers E_T_GENERICINST and E_T_CLASS typespec formats. We don't expect
2469                 // any other kinds to come through here.
2470                 CorSigUncompressToken(pSig, &typeref);
2471             }
2472             else
2473             {   // This is an unrecognized signature format.
2474                 BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT,
2475                                                IDS_CLASSLOAD_MI_BAD_SIG,
2476                                                mdMethodDefNil);
2477             }
2478             goto GOTPARENT;
2479         }
2480         else
2481         {   // Verify that the ref points back to us
2482             mdToken tkDef = mdTokenNil;
2483
2484             if (TypeFromToken(typeref) == mdtTypeRef)
2485             {   // We only get here when we know the token does not reference a type in a different scope.
2486                 LPCUTF8 pszNameSpace;
2487                 LPCUTF8 pszClassName;
2488
2489                 if (FAILED(pMDInternalImport->GetNameOfTypeRef(typeref, &pszNameSpace, &pszClassName)))
2490                 {
2491                     IfFailRet(COR_E_TYPELOAD);
2492                 }
2493                 mdToken tkRes;
2494                 if (FAILED(pMDInternalImport->GetResolutionScopeOfTypeRef(typeref, &tkRes)))
2495                 {
2496                     IfFailRet(COR_E_TYPELOAD);
2497                 }
2498                 hr = pMDInternalImport->FindTypeDef(pszNameSpace,
2499                                                     pszClassName,
2500                                                     (TypeFromToken(tkRes) == mdtTypeRef) ? tkRes : mdTokenNil,
2501                                                     &tkDef);
2502                 if (FAILED(hr))
2503                 {
2504                     IfFailRet(COR_E_TYPELOAD);
2505                 }
2506             }
2507             else if (TypeFromToken(typeref) == mdtTypeDef)
2508             {   // We get a typedef when the parent of the token is a typespec to the type.
2509                 tkDef = typeref;
2510             }
2511             else
2512             {
2513                 CONSISTENCY_CHECK_MSGF(FALSE, ("Invalid methodimpl signature in class %s.", GetDebugClassName()));
2514                 BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT,
2515                                                IDS_CLASSLOAD_MI_BAD_SIG,
2516                                                mdMethodDefNil);
2517             }
2518
2519             if (fSameClass && tkDef != GetCl())
2520             {   // If we required that the typedef be the same type as the current class,
2521                 // and it doesn't match, we need to return a failure result.
2522                 IfFailRet(COR_E_TYPELOAD);
2523             }
2524
2525             IfFailRet(pMDInternalImport->GetNameAndSigOfMemberRef(pToken, &pSig, &cSig, &szMember));
2526             
2527             if (isCallConv(
2528                 MetaSig::GetCallingConvention(GetModule(), Signature(pSig, cSig)),
2529                 IMAGE_CEE_CS_CALLCONV_FIELD))
2530             {
2531                 return VLDTR_E_MR_BADCALLINGCONV;
2532             }
2533             
2534             hr = pMDInternalImport->FindMethodDef(
2535                 tkDef, szMember, pSig, cSig, pDeclaration);
2536
2537             IfFailRet(hr);
2538         }
2539     }
2540     else if (TypeFromToken(pToken) == mdtMethodDef)
2541     {
2542         mdTypeDef typeDef;
2543
2544         // Verify that we are the parent
2545         hr = pMDInternalImport->GetParentToken(pToken, &typeDef);
2546         IfFailRet(hr);
2547
2548         if(typeDef != GetCl())
2549         {
2550             IfFailRet(COR_E_TYPELOAD);
2551         }
2552
2553         *pDeclaration = pToken;
2554     }
2555     else
2556     {
2557         IfFailRet(COR_E_TYPELOAD);
2558     }
2559     return hr;
2560 }
2561
2562 #ifdef _PREFAST_ 
2563 #pragma warning(push)
2564 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
2565 #endif // _PREFAST_
2566 //---------------------------------------------------------------------------------------
2567 //
2568 // Used by BuildMethodTable
2569 // 
2570 // Enumerate this class's members
2571 // 
2572 VOID
2573 MethodTableBuilder::EnumerateClassMethods()
2574 {
2575     CONTRACTL
2576     {
2577         STANDARD_VM_CHECK;
2578         PRECONDITION(CheckPointer(bmtInternal));
2579         PRECONDITION(CheckPointer(bmtEnumFields));
2580         PRECONDITION(CheckPointer(bmtMFDescs));
2581         PRECONDITION(CheckPointer(bmtProp));
2582         PRECONDITION(CheckPointer(bmtMetaData));
2583         PRECONDITION(CheckPointer(bmtVT));
2584         PRECONDITION(CheckPointer(bmtError));
2585     }
2586     CONTRACTL_END;
2587
2588     HRESULT hr = S_OK;
2589     DWORD i;
2590     IMDInternalImport *pMDInternalImport = GetMDImport();
2591     mdToken tok;
2592     DWORD dwMemberAttrs;
2593     BOOL fIsClassEnum = IsEnum();
2594     BOOL fIsClassInterface = IsInterface();
2595     BOOL fIsClassValueType = IsValueClass();
2596     BOOL fIsClassComImport = IsComImport();
2597     BOOL fIsClassNotAbstract = (IsTdAbstract(GetAttrClass()) == 0);
2598     PCCOR_SIGNATURE pMemberSignature;
2599     ULONG           cMemberSignature;
2600
2601     //
2602     // Run through the method list and calculate the following:
2603     // # methods.
2604     // # "other" methods (i.e. static or private)
2605     // # non-other methods
2606     //
2607
2608     HENUMInternalHolder hEnumMethod(pMDInternalImport);
2609     hr = hEnumMethod.EnumInitNoThrow(mdtMethodDef, GetCl());
2610     if (FAILED(hr))
2611     {
2612         BuildMethodTableThrowException(hr, *bmtError);
2613     }
2614
2615     // Allocate an array to contain the method tokens as well as information about the methods.
2616     DWORD cMethAndGaps = hEnumMethod.EnumGetCount();
2617
2618     if ((DWORD)MAX_SLOT_INDEX <= cMethAndGaps)
2619         BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
2620
2621     bmtMethod->m_cMaxDeclaredMethods = (SLOT_INDEX)cMethAndGaps;
2622     bmtMethod->m_cDeclaredMethods = 0;
2623     bmtMethod->m_rgDeclaredMethods = new (GetStackingAllocator())
2624         bmtMDMethod *[bmtMethod->m_cMaxDeclaredMethods];
2625
2626     enum { SeenCtor = 1, SeenInvoke = 2, SeenBeginInvoke = 4, SeenEndInvoke = 8};
2627     unsigned delegateMethodsSeen = 0;
2628
2629     for (i = 0; i < cMethAndGaps; i++)
2630     {
2631         ULONG dwMethodRVA;
2632         DWORD dwImplFlags;
2633         METHOD_TYPE type;
2634         METHOD_IMPL_TYPE implType;
2635         LPSTR strMethodName;
2636
2637 #ifdef FEATURE_TYPEEQUIVALENCE
2638         // TypeEquivalent structs must not have methods
2639         if (bmtProp->fIsTypeEquivalent && fIsClassValueType)
2640         {
2641             BuildMethodTableThrowException(IDS_CLASSLOAD_EQUIVALENTSTRUCTMETHODS);
2642         }
2643 #endif
2644
2645         //
2646         // Go to the next method and retrieve its attributes.
2647         //
2648
2649         hEnumMethod.EnumNext(&tok);
2650         DWORD   rid = RidFromToken(tok);
2651         if ((rid == 0)||(rid > pMDInternalImport->GetCountWithTokenKind(mdtMethodDef)))
2652         {
2653             BuildMethodTableThrowException(BFA_METHOD_TOKEN_OUT_OF_RANGE);
2654         }
2655
2656         if (FAILED(pMDInternalImport->GetMethodDefProps(tok, &dwMemberAttrs)))
2657         {
2658             BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
2659         }
2660         if (IsMdRTSpecialName(dwMemberAttrs) || IsMdVirtual(dwMemberAttrs) || IsDelegate())
2661         {
2662             if (FAILED(pMDInternalImport->GetNameOfMethodDef(tok, (LPCSTR *)&strMethodName)))
2663             {
2664                 BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
2665             }
2666             if(IsStrLongerThan(strMethodName,MAX_CLASS_NAME))
2667             {
2668                 BuildMethodTableThrowException(BFA_METHOD_NAME_TOO_LONG);
2669             }
2670         }
2671         else
2672         {
2673             strMethodName = NULL;
2674         }
2675
2676         DWORD numGenericMethodArgs = 0;
2677
2678         {
2679             HENUMInternalHolder hEnumTyPars(pMDInternalImport);
2680             hr = hEnumTyPars.EnumInitNoThrow(mdtGenericParam, tok);
2681             if (FAILED(hr))
2682             {
2683                 BuildMethodTableThrowException(hr, *bmtError);
2684             }
2685
2686             numGenericMethodArgs = hEnumTyPars.EnumGetCount();
2687
2688             // We do not want to support context-bound objects with generic methods.
2689
2690             if (numGenericMethodArgs != 0)
2691             {
2692                 HENUMInternalHolder hEnumGenericPars(pMDInternalImport);
2693
2694                 hEnumGenericPars.EnumInit(mdtGenericParam, tok);
2695
2696                 for (unsigned methIdx = 0; methIdx < numGenericMethodArgs; methIdx++)
2697                 {
2698                     mdGenericParam tkTyPar;
2699                     pMDInternalImport->EnumNext(&hEnumGenericPars, &tkTyPar);
2700                     DWORD flags;
2701                     if (FAILED(pMDInternalImport->GetGenericParamProps(tkTyPar, NULL, &flags, NULL, NULL, NULL)))
2702                     {
2703                         BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
2704                     }
2705                     
2706                     if (0 != (flags & ~(gpVarianceMask | gpSpecialConstraintMask)))
2707                     {
2708                         BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
2709                     }
2710                     switch (flags & gpVarianceMask)
2711                     {
2712                         case gpNonVariant:
2713                             break;
2714
2715                         case gpCovariant: // intentional fallthru
2716                         case gpContravariant:
2717                             BuildMethodTableThrowException(VLDTR_E_GP_ILLEGAL_VARIANT_MVAR);
2718                             break;
2719
2720                         default:
2721                             BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
2722                     }
2723
2724                 }
2725             }
2726         }
2727
2728         //
2729         // We need to check if there are any gaps in the vtable. These are
2730         // represented by methods with the mdSpecial flag and a name of the form
2731         // _VTblGap_nnn (to represent nnn empty slots) or _VTblGap (to represent a
2732         // single empty slot).
2733         //
2734
2735         if (IsMdRTSpecialName(dwMemberAttrs))
2736         {
2737             PREFIX_ASSUME(strMethodName != NULL); // if we've gotten here we've called GetNameOfMethodDef
2738
2739             // The slot is special, but it might not be a vtable spacer. To
2740             // determine that we must look at the name.
2741             if (strncmp(strMethodName, "_VtblGap", 8) == 0)
2742             {
2743                                 //
2744                 // This slot doesn't really exist, don't add it to the method
2745                 // table. Instead it represents one or more empty slots, encoded
2746                 // in the method name. Locate the beginning of the count in the
2747                 // name. There are these points to consider:
2748                 //   There may be no count present at all (in which case the
2749                 //   count is taken as one).
2750                 //   There may be an additional count just after Gap but before
2751                 //   the '_'. We ignore this.
2752                                 //
2753
2754                 LPCSTR pos = strMethodName + 8;
2755
2756                 // Skip optional number.
2757                 while (IS_DIGIT(*pos))
2758                     pos++;
2759
2760                 WORD n = 0;
2761
2762                 // Check for presence of count.
2763                 if (*pos == '\0')
2764                     n = 1;
2765                 else
2766                 {
2767                     if (*pos != '_')
2768                     {
2769                         BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT,
2770                                                        IDS_CLASSLOAD_BADSPECIALMETHOD,
2771                                                        tok);
2772                     }
2773
2774                     // Skip '_'.
2775                     pos++;
2776
2777                     // Read count.
2778                     bool fReadAtLeastOneDigit = false;
2779                     while (IS_DIGIT(*pos))
2780                     {
2781                         _ASSERTE(n < 6552);
2782                         n *= 10;
2783                         n += DIGIT_TO_INT(*pos);
2784                         pos++;
2785                         fReadAtLeastOneDigit = true;
2786                     }
2787
2788                     // Check for end of name.
2789                     if (*pos != '\0' || !fReadAtLeastOneDigit)
2790                     {
2791                         BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT,
2792                                                        IDS_CLASSLOAD_BADSPECIALMETHOD,
2793                                                        tok);
2794                     }
2795                 }
2796
2797 #ifdef FEATURE_COMINTEROP 
2798                 // Record vtable gap in mapping list. The map is an optional field, so ensure we've allocated
2799                 // these fields first.
2800                 EnsureOptionalFieldsAreAllocated(GetHalfBakedClass(), m_pAllocMemTracker, GetLoaderAllocator()->GetLowFrequencyHeap());
2801                 if (GetHalfBakedClass()->GetSparseCOMInteropVTableMap() == NULL)
2802                     GetHalfBakedClass()->SetSparseCOMInteropVTableMap(new SparseVTableMap());
2803
2804                 GetHalfBakedClass()->GetSparseCOMInteropVTableMap()->RecordGap((WORD)NumDeclaredMethods(), n);
2805
2806                 bmtProp->fSparse = true;
2807 #endif // FEATURE_COMINTEROP
2808                 continue;
2809             }
2810
2811         }
2812
2813
2814         //
2815         // This is a real method so add it to the enumeration of methods. We now need to retrieve
2816         // information on the method and store it for later use.
2817         //
2818         if (FAILED(pMDInternalImport->GetMethodImplProps(tok, &dwMethodRVA, &dwImplFlags)))
2819         {
2820             BuildMethodTableThrowException(
2821                 COR_E_BADIMAGEFORMAT, 
2822                 IDS_CLASSLOAD_BADSPECIALMETHOD, 
2823                 tok);
2824         }
2825         //
2826         // But first - minimal flags validity checks
2827         //
2828         // No methods in Enums!
2829         if (fIsClassEnum)
2830         {
2831             BuildMethodTableThrowException(BFA_METHOD_IN_A_ENUM);
2832         }
2833         // RVA : 0
2834         if (dwMethodRVA != 0)
2835         {
2836             if(fIsClassComImport)
2837             {
2838                 BuildMethodTableThrowException(BFA_METHOD_WITH_NONZERO_RVA);
2839             }
2840             if(IsMdAbstract(dwMemberAttrs))
2841             {
2842                 BuildMethodTableThrowException(BFA_ABSTRACT_METHOD_WITH_RVA);
2843             }
2844             if(IsMiRuntime(dwImplFlags))
2845             {
2846                 BuildMethodTableThrowException(BFA_RUNTIME_METHOD_WITH_RVA);
2847             }
2848             if(IsMiInternalCall(dwImplFlags))
2849             {
2850                 BuildMethodTableThrowException(BFA_INTERNAL_METHOD_WITH_RVA);
2851             }
2852         }
2853
2854         // Abstract / not abstract
2855         if(IsMdAbstract(dwMemberAttrs))
2856         {
2857             if(fIsClassNotAbstract)
2858             {
2859                 BuildMethodTableThrowException(BFA_AB_METHOD_IN_AB_CLASS);
2860             }
2861             if(!IsMdVirtual(dwMemberAttrs))
2862             {
2863                 BuildMethodTableThrowException(BFA_NONVIRT_AB_METHOD);
2864             }
2865         }
2866         else if(fIsClassInterface)
2867         {
2868             if (IsMdRTSpecialName(dwMemberAttrs))
2869             {
2870                 CONSISTENCY_CHECK(CheckPointer(strMethodName));
2871                 if (strcmp(strMethodName, COR_CCTOR_METHOD_NAME))
2872                 {
2873                     BuildMethodTableThrowException(BFA_NONAB_NONCCTOR_METHOD_ON_INT);
2874                 }
2875             }
2876         }
2877
2878         // Virtual / not virtual
2879         if(IsMdVirtual(dwMemberAttrs))
2880         {
2881             if(IsMdPinvokeImpl(dwMemberAttrs))
2882             {
2883                 BuildMethodTableThrowException(BFA_VIRTUAL_PINVOKE_METHOD);
2884             }
2885             if(IsMdStatic(dwMemberAttrs))
2886             {
2887                 BuildMethodTableThrowException(BFA_VIRTUAL_STATIC_METHOD);
2888             }
2889             if(strMethodName && (0==strcmp(strMethodName, COR_CTOR_METHOD_NAME)))
2890             {
2891                 BuildMethodTableThrowException(BFA_VIRTUAL_INSTANCE_CTOR);
2892             }
2893         }
2894
2895 #ifndef FEATURE_DEFAULT_INTERFACES
2896         // Some interface checks.
2897         if (fIsClassInterface)
2898         {
2899             if (IsMdVirtual(dwMemberAttrs))
2900             {
2901                 if (!IsMdAbstract(dwMemberAttrs))
2902                 {
2903                     BuildMethodTableThrowException(BFA_VIRTUAL_NONAB_INT_METHOD);
2904                 }
2905             }
2906             else
2907             {
2908                 // Instance field/method
2909                 if (!IsMdStatic(dwMemberAttrs))
2910                 {
2911                     BuildMethodTableThrowException(BFA_NONVIRT_INST_INT_METHOD);
2912                 }
2913             }
2914         }
2915 #endif
2916
2917         // No synchronized methods in ValueTypes
2918         if(fIsClassValueType && IsMiSynchronized(dwImplFlags))
2919         {
2920             BuildMethodTableThrowException(BFA_SYNC_METHOD_IN_VT);
2921         }
2922
2923         // Global methods:
2924         if(IsGlobalClass())
2925         {
2926             if(!IsMdStatic(dwMemberAttrs))
2927             {
2928                 BuildMethodTableThrowException(BFA_NONSTATIC_GLOBAL_METHOD);
2929             }
2930             if (strMethodName)  //<TODO>@todo: investigate mc++ generating null name</TODO>
2931             {
2932                 if(0==strcmp(strMethodName, COR_CTOR_METHOD_NAME))
2933                 {
2934                     BuildMethodTableThrowException(BFA_GLOBAL_INST_CTOR);
2935                 }
2936             }
2937         }
2938         //@GENERICS:
2939         // Generic methods or methods in generic classes
2940         // may not be part of a COM Import class (except for WinRT), PInvoke, internal call outside mscorlib.
2941         if ((bmtGenerics->GetNumGenericArgs() != 0 || numGenericMethodArgs != 0) &&
2942             (
2943 #ifdef FEATURE_COMINTEROP 
2944              fIsClassComImport ||
2945              bmtProp->fComEventItfType ||
2946 #endif // FEATURE_COMINTEROP
2947              IsMdPinvokeImpl(dwMemberAttrs) ||
2948              (IsMiInternalCall(dwImplFlags) && !GetModule()->IsSystem())))
2949         {
2950 #ifdef FEATURE_COMINTEROP
2951             if (!GetHalfBakedClass()->IsProjectedFromWinRT())
2952 #endif // FEATURE_COMINTEROP
2953             {
2954                 BuildMethodTableThrowException(BFA_BAD_PLACE_FOR_GENERIC_METHOD);
2955             }
2956         }
2957
2958         // Generic methods may not be marked "runtime".  However note that
2959         // methods in generic delegate classes are, hence we don't apply this to
2960         // methods in generic classes in general.
2961         if (numGenericMethodArgs != 0 && IsMiRuntime(dwImplFlags))
2962         {
2963             BuildMethodTableThrowException(BFA_GENERIC_METHOD_RUNTIME_IMPL);
2964         }
2965
2966
2967         // Signature validation
2968         if (FAILED(pMDInternalImport->GetSigOfMethodDef(tok, &cMemberSignature, &pMemberSignature)))
2969         {
2970             BuildMethodTableThrowException(hr, BFA_BAD_SIGNATURE, mdMethodDefNil);
2971         }
2972         hr = validateTokenSig(tok,pMemberSignature,cMemberSignature,dwMemberAttrs,pMDInternalImport);
2973         if (FAILED(hr))
2974         {
2975             BuildMethodTableThrowException(hr, BFA_BAD_SIGNATURE, mdMethodDefNil);
2976         }
2977
2978         // Check the appearance of covariant and contravariant in the method signature
2979         // Note that variance is only supported for interfaces
2980         if (bmtGenerics->pVarianceInfo != NULL)
2981         {
2982             SigPointer sp(pMemberSignature, cMemberSignature);
2983             ULONG callConv;
2984             IfFailThrow(sp.GetCallingConvInfo(&callConv));
2985
2986             if (callConv & IMAGE_CEE_CS_CALLCONV_GENERIC)
2987                 IfFailThrow(sp.GetData(NULL));
2988
2989             DWORD numArgs;
2990             IfFailThrow(sp.GetData(&numArgs));
2991
2992             // Return type behaves covariantly
2993             if (!EEClass::CheckVarianceInSig(
2994                     bmtGenerics->GetNumGenericArgs(), 
2995                     bmtGenerics->pVarianceInfo, 
2996                     GetModule(), 
2997                     sp, 
2998                     gpCovariant))
2999             {
3000                 BuildMethodTableThrowException(IDS_CLASSLOAD_VARIANCE_IN_METHOD_RESULT, tok);
3001             }
3002             IfFailThrow(sp.SkipExactlyOne());
3003             for (DWORD j = 0; j < numArgs; j++)
3004             {
3005                 // Argument types behave contravariantly
3006                 if (!EEClass::CheckVarianceInSig(bmtGenerics->GetNumGenericArgs(),
3007                                                  bmtGenerics->pVarianceInfo,
3008                                                  GetModule(),
3009                                                  sp,
3010                                                  gpContravariant))
3011                 {
3012                     BuildMethodTableThrowException(IDS_CLASSLOAD_VARIANCE_IN_METHOD_ARG, tok);
3013                 }
3014                 IfFailThrow(sp.SkipExactlyOne());
3015             }
3016         }
3017
3018         //
3019         // Determine the method's type
3020         //
3021
3022         if (IsReallyMdPinvokeImpl(dwMemberAttrs) || IsMiInternalCall(dwImplFlags))
3023         {
3024             hr = NDirect::HasNAT_LAttribute(pMDInternalImport, tok, dwMemberAttrs);
3025
3026             // There was a problem querying for the attribute
3027             if (FAILED(hr))
3028             {
3029                 BuildMethodTableThrowException(hr, IDS_CLASSLOAD_BADPINVOKE, tok);
3030             }
3031
3032             // The attribute is not present
3033             if (hr == S_FALSE)
3034             {
3035 #ifdef FEATURE_COMINTEROP
3036                 if (fIsClassComImport
3037                     || GetHalfBakedClass()->IsProjectedFromWinRT()
3038                     || bmtProp->fComEventItfType
3039                     )
3040                 {
3041                     // ComImport classes have methods which are just used
3042                     // for implementing all interfaces the class supports
3043                     type = METHOD_TYPE_COMINTEROP;
3044
3045                     // constructor is special
3046                     if (IsMdRTSpecialName(dwMemberAttrs))
3047                     {
3048                         // Note: Method name (.ctor) will be checked in code:ValidateMethods
3049                         
3050                         // WinRT ctors are interop calls via stubs
3051                         if (!GetHalfBakedClass()->IsProjectedFromWinRT())
3052                         {
3053                             // Ctor on a non-WinRT class
3054                             type = METHOD_TYPE_FCALL;
3055                         }
3056                     }
3057                 }
3058                 else 
3059 #endif //FEATURE_COMINTEROP
3060                 if (dwMethodRVA == 0)
3061                 {
3062                     type = METHOD_TYPE_FCALL;
3063                 }
3064                 else
3065                 {
3066                     type = METHOD_TYPE_NDIRECT;
3067                 }
3068             }
3069             // The NAT_L attribute is present, marking this method as NDirect
3070             else
3071             {
3072                 CONSISTENCY_CHECK(hr == S_OK);
3073                 type = METHOD_TYPE_NDIRECT;
3074             }
3075         }
3076         else if (IsMiRuntime(dwImplFlags))
3077         {
3078                 // currently the only runtime implemented functions are delegate instance methods
3079             if (!IsDelegate() || IsMdStatic(dwMemberAttrs) || IsMdAbstract(dwMemberAttrs))
3080             {
3081                 BuildMethodTableThrowException(BFA_BAD_RUNTIME_IMPL);
3082             }
3083
3084             unsigned newDelegateMethodSeen = 0;
3085
3086             if (IsMdRTSpecialName(dwMemberAttrs))   // .ctor
3087             {
3088                 if (strcmp(strMethodName, COR_CTOR_METHOD_NAME) != 0 || IsMdVirtual(dwMemberAttrs))
3089                 {
3090                     BuildMethodTableThrowException(BFA_BAD_FLAGS_ON_DELEGATE);
3091                 }
3092                 newDelegateMethodSeen = SeenCtor;
3093                 type = METHOD_TYPE_FCALL;
3094             }
3095             else
3096             {
3097                 if (strcmp(strMethodName, "Invoke") == 0)
3098                     newDelegateMethodSeen = SeenInvoke;
3099                 else if (strcmp(strMethodName, "BeginInvoke") == 0)
3100                     newDelegateMethodSeen = SeenBeginInvoke;
3101                 else if (strcmp(strMethodName, "EndInvoke") == 0)
3102                     newDelegateMethodSeen = SeenEndInvoke;
3103                 else
3104                 {
3105                     BuildMethodTableThrowException(BFA_UNKNOWN_DELEGATE_METHOD);
3106                 }
3107                 type = METHOD_TYPE_EEIMPL;
3108             }
3109
3110             // If we get here we have either set newDelegateMethodSeen or we have thrown a BMT exception
3111             _ASSERTE(newDelegateMethodSeen != 0);
3112
3113             if ((delegateMethodsSeen & newDelegateMethodSeen) != 0)
3114             {
3115                 BuildMethodTableThrowException(BFA_DUPLICATE_DELEGATE_METHOD);
3116             }
3117
3118             delegateMethodsSeen |= newDelegateMethodSeen;
3119         }
3120         else if (numGenericMethodArgs != 0)
3121         {
3122             //We use an instantiated method desc to represent a generic method
3123             type = METHOD_TYPE_INSTANTIATED;
3124         }
3125         else if (fIsClassInterface)
3126         {
3127 #ifdef FEATURE_COMINTEROP 
3128             if (IsMdStatic(dwMemberAttrs))
3129             {
3130                 // Static methods in interfaces need nothing special.
3131                 type = METHOD_TYPE_NORMAL;
3132             }
3133             else if (bmtGenerics->GetNumGenericArgs() != 0 &&
3134                 (bmtGenerics->fSharedByGenericInstantiations || (!bmtProp->fIsRedirectedInterface && !GetHalfBakedClass()->IsProjectedFromWinRT())))
3135             {
3136                 // Methods in instantiated interfaces need nothing special - they are not visible from COM etc.
3137                 // mcComInterop is only useful for unshared instantiated WinRT interfaces. If the interface is
3138                 // shared by multiple instantiations, the MD would be useless for interop anyway.
3139                 type = METHOD_TYPE_NORMAL;
3140             }
3141             else if (bmtProp->fIsMngStandardItf)
3142             {
3143                 // If the interface is a standard managed interface then allocate space for an FCall method desc.
3144                 type = METHOD_TYPE_FCALL;
3145             }
3146             else if (IsMdAbstract(dwMemberAttrs))
3147             {
3148                 // If COM interop is supported then all other interface MDs may be
3149                 // accessed via COM interop. mcComInterop MDs have an additional
3150                 // pointer-sized field pointing to COM interop data which are
3151                 // allocated lazily when/if the MD actually gets used for interop.
3152                 type = METHOD_TYPE_COMINTEROP;
3153             }
3154             else
3155 #endif // !FEATURE_COMINTEROP
3156             {
3157                 // This codepath is used by remoting
3158                 type = METHOD_TYPE_NORMAL;
3159             }
3160         }
3161         else
3162         {
3163             type = METHOD_TYPE_NORMAL;
3164         }
3165
3166         // Generic methods should always be METHOD_TYPE_INSTANTIATED
3167         if ((numGenericMethodArgs != 0) && (type != METHOD_TYPE_INSTANTIATED))
3168         {
3169             BuildMethodTableThrowException(BFA_GENERIC_METHODS_INST);
3170         }
3171
3172         // count how many overrides this method does All methods bodies are defined
3173         // on this type so we can just compare the tok with the body token found
3174         // from the overrides.
3175         implType = METHOD_IMPL_NOT;
3176         for (DWORD impls = 0; impls < bmtMethod->dwNumberMethodImpls; impls++)
3177         {
3178             if (bmtMetaData->rgMethodImplTokens[impls].methodBody == tok)
3179             {
3180                 implType = METHOD_IMPL;
3181                 break;
3182             }
3183         }
3184
3185         // For delegates we don't allow any non-runtime implemented bodies
3186         // for any of the four special methods
3187         if (IsDelegate() && !IsMiRuntime(dwImplFlags))
3188         {
3189             if ((strcmp(strMethodName, COR_CTOR_METHOD_NAME) == 0) ||
3190                 (strcmp(strMethodName, "Invoke")             == 0) ||
3191                 (strcmp(strMethodName, "BeginInvoke")        == 0) ||
3192                 (strcmp(strMethodName, "EndInvoke")          == 0)   )
3193             {
3194                 BuildMethodTableThrowException(BFA_ILLEGAL_DELEGATE_METHOD);
3195             }
3196         }
3197
3198         //
3199         // Create a new bmtMDMethod representing this method and add it to the
3200         // declared method list.
3201         //
3202
3203         bmtMDMethod * pNewMethod = new (GetStackingAllocator()) bmtMDMethod(
3204             bmtInternal->pType,
3205             tok,
3206             dwMemberAttrs,
3207             dwImplFlags,
3208             dwMethodRVA,
3209             type,
3210             implType);
3211
3212         bmtMethod->AddDeclaredMethod(pNewMethod);
3213
3214         //
3215         // Update the count of the various types of methods.
3216         //
3217
3218         bmtVT->dwMaxVtableSize++;
3219
3220         // Increment the number of non-abstract declared methods
3221         if (!IsMdAbstract(dwMemberAttrs))
3222         {
3223             bmtMethod->dwNumDeclaredNonAbstractMethods++;
3224         }
3225     }
3226
3227     // Check to see that we have all of the required delegate methods (ECMA 13.6 Delegates)
3228     if (IsDelegate())
3229     {
3230         // Do we have all four special delegate methods
3231         // or just the two special delegate methods
3232         if ((delegateMethodsSeen != (SeenCtor | SeenInvoke | SeenBeginInvoke | SeenEndInvoke)) &&
3233             (delegateMethodsSeen != (SeenCtor | SeenInvoke)) )
3234         {
3235             BuildMethodTableThrowException(BFA_MISSING_DELEGATE_METHOD);
3236         }
3237     }
3238
3239     if (i != cMethAndGaps)
3240     {
3241         BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_METHOD_COUNT, mdTokenNil);
3242     }
3243
3244 #ifdef FEATURE_COMINTEROP 
3245     //
3246     // If the interface is sparse, we need to finalize the mapping list by
3247     // telling it how many real methods we found.
3248     //
3249
3250     if (bmtProp->fSparse)
3251     {
3252         GetHalfBakedClass()->GetSparseCOMInteropVTableMap()->FinalizeMapping(NumDeclaredMethods());
3253     }
3254 #endif // FEATURE_COMINTEROP
3255 } // MethodTableBuilder::EnumerateClassMethods
3256 #ifdef _PREFAST_ 
3257 #pragma warning(pop)
3258 #endif
3259
3260 //*******************************************************************************
3261 //
3262 // Run through the field list and calculate the following:
3263 // # static fields
3264 // # static fields that contain object refs.
3265 // # instance fields
3266 //
3267 VOID
3268 MethodTableBuilder::EnumerateClassFields()
3269 {
3270     STANDARD_VM_CONTRACT;
3271
3272     HRESULT hr = S_OK;
3273     DWORD i;
3274     IMDInternalImport *pMDInternalImport = GetMDImport();
3275     mdToken tok;
3276     DWORD dwMemberAttrs;
3277
3278     bmtEnumFields->dwNumStaticFields        = 0;
3279     bmtEnumFields->dwNumStaticObjRefFields  = 0;
3280     bmtEnumFields->dwNumStaticBoxedFields   = 0;
3281
3282     bmtEnumFields->dwNumThreadStaticFields  = 0;
3283     bmtEnumFields->dwNumThreadStaticObjRefFields  = 0;
3284     bmtEnumFields->dwNumThreadStaticBoxedFields   = 0;
3285
3286     bmtEnumFields->dwNumInstanceFields      = 0;
3287
3288     HENUMInternalHolder hEnumField(pMDInternalImport);
3289     hr = hEnumField.EnumInitNoThrow(mdtFieldDef, GetCl());
3290     if (FAILED(hr))
3291     {
3292         BuildMethodTableThrowException(hr, *bmtError);
3293     }
3294
3295     bmtMetaData->cFields = hEnumField.EnumGetCount();
3296
3297     // Retrieve the fields and store them in a temp array.
3298     bmtMetaData->pFields = new (GetStackingAllocator()) mdToken[bmtMetaData->cFields];
3299     bmtMetaData->pFieldAttrs = new (GetStackingAllocator()) DWORD[bmtMetaData->cFields];
3300
3301     DWORD   dwFieldLiteralInitOnly = fdLiteral | fdInitOnly;
3302     DWORD   dwMaxFieldDefRid = pMDInternalImport->GetCountWithTokenKind(mdtFieldDef);
3303
3304     for (i = 0; hEnumField.EnumNext(&tok); i++)
3305     {
3306         //
3307         // Retrieve the attributes of the field.
3308         //
3309         DWORD rid = RidFromToken(tok);
3310         if ((rid == 0)||(rid > dwMaxFieldDefRid))
3311         {
3312             BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, BFA_BAD_FIELD_TOKEN, mdTokenNil);
3313         }
3314         
3315         if (FAILED(pMDInternalImport->GetFieldDefProps(tok, &dwMemberAttrs)))
3316         {
3317             BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, BFA_BAD_FIELD_TOKEN, tok);
3318         }
3319         
3320         //
3321         // Store the field and its attributes in the bmtMetaData structure for later use.
3322         //
3323
3324         bmtMetaData->pFields[i] = tok;
3325         bmtMetaData->pFieldAttrs[i] = dwMemberAttrs;
3326
3327         if((dwMemberAttrs & fdFieldAccessMask)==fdFieldAccessMask)
3328         {
3329             BuildMethodTableThrowException(BFA_INVALID_FIELD_ACC_FLAGS);
3330         }
3331         if((dwMemberAttrs & dwFieldLiteralInitOnly)==dwFieldLiteralInitOnly)
3332         {
3333             BuildMethodTableThrowException(BFA_FIELD_LITERAL_AND_INIT);
3334         }
3335
3336         // can only have static global fields
3337         if(IsGlobalClass())
3338         {
3339             if(!IsFdStatic(dwMemberAttrs))
3340             {
3341                 BuildMethodTableThrowException(BFA_NONSTATIC_GLOBAL_FIELD);
3342             }
3343         }
3344
3345         //
3346         // Update the count of the various types of fields.
3347         //
3348
3349         if (IsFdStatic(dwMemberAttrs))
3350         {
3351             if (!IsFdLiteral(dwMemberAttrs))
3352             {
3353 #ifdef FEATURE_TYPEEQUIVALENCE
3354                 if (bmtProp->fIsTypeEquivalent)
3355                 {
3356                     BuildMethodTableThrowException(IDS_CLASSLOAD_EQUIVALENTSTRUCTFIELDS);
3357                 }
3358 #endif
3359
3360                 bmtEnumFields->dwNumStaticFields++;
3361
3362                 // If this static field is thread static, then we need
3363                 // to increment bmtEnumFields->dwNumThreadStaticFields
3364                 hr = pMDInternalImport->GetCustomAttributeByName(tok,
3365                                                                  g_ThreadStaticAttributeClassName,
3366                                                                  NULL, NULL);
3367                 IfFailThrow(hr);
3368                 if (hr == S_OK)
3369                 {
3370                     // It's a thread static, so increment the count
3371                     bmtEnumFields->dwNumThreadStaticFields++;
3372                 }
3373             }
3374         }
3375         else
3376         {
3377 #ifdef FEATURE_TYPEEQUIVALENCE
3378             if (!IsFdPublic(dwMemberAttrs) && bmtProp->fIsTypeEquivalent)
3379             {
3380                 BuildMethodTableThrowException(IDS_CLASSLOAD_EQUIVALENTSTRUCTFIELDS);
3381             }
3382 #endif
3383
3384             if (!IsFdLiteral(dwMemberAttrs))
3385             {
3386                 bmtEnumFields->dwNumInstanceFields++;
3387             }
3388             if(IsInterface())
3389             {
3390                 BuildMethodTableThrowException(BFA_INSTANCE_FIELD_IN_INT);
3391             }
3392         }
3393     }
3394
3395     if (i != bmtMetaData->cFields)
3396     {
3397         BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD_COUNT, mdTokenNil);
3398     }
3399
3400     if(IsEnum() && (bmtEnumFields->dwNumInstanceFields==0))
3401     {
3402         BuildMethodTableThrowException(BFA_INSTANCE_FIELD_IN_ENUM);
3403     }
3404
3405     bmtEnumFields->dwNumDeclaredFields = bmtEnumFields->dwNumStaticFields + bmtEnumFields->dwNumInstanceFields;
3406 }
3407
3408 //*******************************************************************************
3409 //
3410 // Used by BuildMethodTable
3411 //
3412 // Determines the maximum size of the vtable and allocates the temporary storage arrays
3413 // Also copies the parent's vtable into the working vtable.
3414 //
3415 VOID    MethodTableBuilder::AllocateWorkingSlotTables()
3416 {
3417     CONTRACTL
3418     {
3419         STANDARD_VM_CHECK;
3420         PRECONDITION(CheckPointer(this));
3421         PRECONDITION(CheckPointer(bmtAllocator));
3422         PRECONDITION(CheckPointer(bmtMFDescs));
3423         PRECONDITION(CheckPointer(bmtMetaData));
3424         PRECONDITION(CheckPointer(bmtVT));
3425         PRECONDITION(CheckPointer(bmtEnumFields));
3426         PRECONDITION(CheckPointer(bmtInterface));
3427         PRECONDITION(CheckPointer(bmtFP));
3428         PRECONDITION(CheckPointer(bmtParent));
3429
3430     }
3431     CONTRACTL_END;
3432
3433     // Allocate a FieldDesc* for each field
3434     bmtMFDescs->ppFieldDescList = new (GetStackingAllocator()) FieldDesc*[bmtMetaData->cFields];
3435     ZeroMemory(bmtMFDescs->ppFieldDescList, bmtMetaData->cFields * sizeof(FieldDesc *));
3436
3437     // Create a temporary function table (we don't know how large the vtable will be until the very end,
3438     // since we don't yet know how many declared methods are overrides vs. newslots).
3439
3440     if (IsValueClass())
3441     {   // ValueClass virtuals are converted into non-virtual methods and the virtual slots
3442         // become unboxing stubs that forward to these new non-virtual methods. This has the
3443         // side effect of doubling the number of slots introduced by newslot virtuals.
3444         bmtVT->dwMaxVtableSize += NumDeclaredMethods();
3445     }
3446
3447     _ASSERTE(!HasParent() || (bmtInterface->dwInterfaceMapSize - GetParentMethodTable()->GetNumInterfaces()) >= 0);
3448
3449     if (HasParent())
3450     {   // Add parent vtable size. <TODO> This should actually be the parent's virtual method count. </TODO>
3451         bmtVT->dwMaxVtableSize += bmtParent->pSlotTable->GetSlotCount();
3452     }
3453
3454     S_SLOT_INDEX cMaxSlots = AsClrSafeInt(bmtVT->dwMaxVtableSize) + AsClrSafeInt(NumDeclaredMethods());
3455
3456     if (cMaxSlots.IsOverflow() || MAX_SLOT_INDEX < cMaxSlots.Value())
3457         cMaxSlots = S_SLOT_INDEX(MAX_SLOT_INDEX);
3458
3459     // Allocate the temporary vtable
3460     bmtVT->pSlotTable = new (GetStackingAllocator())
3461         bmtMethodSlotTable(cMaxSlots.Value(), GetStackingAllocator());
3462
3463     if (HasParent())
3464     {
3465 #if 0 
3466         // @<TODO>todo: Figure out the right way to override Equals for value
3467         // types only.
3468         //
3469         // This is broken because
3470         // (a) g_pObjectClass->FindMethod("Equals", &gsig_IM_Obj_RetBool); will return
3471         //      the EqualsValue method
3472         // (b) When mscorlib has been preloaded (and thus the munge already done
3473         //      ahead of time), we cannot easily find both methods
3474         //      to compute EqualsAddr & EqualsSlot
3475         //
3476         // For now, the Equals method has a runtime check to see if it's
3477         // comparing value types.
3478         //</TODO>
3479
3480         // If it is a value type, over ride a few of the base class methods.
3481         if (IsValueClass())
3482         {
3483             static WORD EqualsSlot;
3484
3485             // If we haven't been through here yet, get some stuff from the Object class definition.
3486             if (EqualsSlot == NULL)
3487             {
3488                 // Get the slot of the Equals method.
3489                 MethodDesc *pEqualsMD = g_pObjectClass->FindMethod("Equals", &gsig_IM_Obj_RetBool);
3490                 THROW_BAD_FORMAT_MAYBE(pEqualsMD != NULL, 0, this);
3491                 EqualsSlot = pEqualsMD->GetSlot();
3492
3493                 // Get the address of the EqualsValue method.
3494                 MethodDesc *pEqualsValueMD = g_pObjectClass->FindMethod("EqualsValue", &gsig_IM_Obj_RetBool);
3495                 THROW_BAD_FORMAT_MAYBE(pEqualsValueMD != NULL, 0, this);
3496
3497                 // Patch the EqualsValue method desc in a dangerous way to
3498                 // look like the Equals method desc.
3499                 pEqualsValueMD->SetSlot(EqualsSlot);
3500                 pEqualsValueMD->SetMemberDef(pEqualsMD->GetMemberDef());
3501             }
3502
3503             // Override the valuetype "Equals" with "EqualsValue".
3504             bmtVT->SetMethodDescForSlot(EqualsSlot, EqualsSlot);
3505         }
3506 #endif // 0
3507     }
3508
3509     S_UINT32 cEntries = S_UINT32(2) * S_UINT32(NumDeclaredMethods());
3510     if (cEntries.IsOverflow())
3511     {
3512         ThrowHR(COR_E_OVERFLOW);
3513     }
3514 }
3515
3516 //*******************************************************************************
3517 //
3518 // Used by BuildMethodTable
3519 //
3520 // Allocate a MethodDesc* for each method (needed later when doing interfaces), and a FieldDesc* for each field
3521 //
3522 VOID MethodTableBuilder::AllocateFieldDescs()
3523 {
3524     CONTRACTL
3525     {
3526         STANDARD_VM_CHECK;
3527         PRECONDITION(CheckPointer(this));
3528         PRECONDITION(CheckPointer(bmtAllocator));
3529         PRECONDITION(CheckPointer(bmtMFDescs));
3530         PRECONDITION(CheckPointer(bmtMetaData));
3531         PRECONDITION(CheckPointer(bmtVT));
3532         PRECONDITION(CheckPointer(bmtEnumFields));
3533         PRECONDITION(CheckPointer(bmtFP));
3534         PRECONDITION(CheckPointer(bmtParent));
3535
3536     }
3537     CONTRACTL_END;
3538
3539     // We'll be counting the # fields of each size as we go along
3540     for (DWORD i = 0; i <= MAX_LOG2_PRIMITIVE_FIELD_SIZE; i++)
3541     {
3542         bmtFP->NumRegularStaticFieldsOfSize[i]    = 0;
3543         bmtFP->NumThreadStaticFieldsOfSize[i]    = 0;
3544         bmtFP->NumInstanceFieldsOfSize[i]  = 0;
3545     }
3546
3547     //
3548     // Allocate blocks of MethodDescs and FieldDescs for all declared methods and fields
3549     //
3550     // In order to avoid allocating a field pointing back to the method
3551     // table in every single method desc, we allocate memory in the
3552     // following manner:
3553     //   o  Field descs get a single contiguous block.
3554     //   o  Method descs of different sizes (normal vs NDirect) are
3555     //      allocated in different MethodDescChunks.
3556     //   o  Each method desc chunk starts with a header, and has
3557     //      at most MAX_ method descs (if there are more
3558     //      method descs of a given size, multiple chunks are allocated).
3559     // This way method descs can use an 8-bit offset field to locate the
3560     // pointer to their method table.
3561     //
3562
3563     /////////////////////////////////////////////////////////////////
3564     // Allocate fields
3565     if (NumDeclaredFields() > 0)
3566     {
3567         GetHalfBakedClass()->SetFieldDescList((FieldDesc *)
3568             AllocateFromHighFrequencyHeap(S_SIZE_T(NumDeclaredFields()) * S_SIZE_T(sizeof(FieldDesc))));
3569         INDEBUG(GetClassLoader()->m_dwDebugFieldDescs += NumDeclaredFields();)
3570         INDEBUG(GetClassLoader()->m_dwFieldDescData += (NumDeclaredFields() * sizeof(FieldDesc));)
3571     }
3572 }
3573
3574 #ifdef FEATURE_DOUBLE_ALIGNMENT_HINT
3575 //*******************************************************************************
3576 //
3577 // Heuristic to determine if we should have instances of this class 8 byte aligned
3578 //
3579 BOOL MethodTableBuilder::ShouldAlign8(DWORD dwR8Fields, DWORD dwTotalFields)
3580 {
3581     LIMITED_METHOD_CONTRACT;
3582
3583     return dwR8Fields*2>dwTotalFields && dwR8Fields>=2;
3584 }
3585 #endif
3586
3587 //*******************************************************************************
3588 BOOL MethodTableBuilder::IsSelfReferencingStaticValueTypeField(mdToken     dwByValueClassToken,
3589                                                                bmtInternalInfo* bmtInternal,
3590                                                                const bmtGenericsInfo *bmtGenerics,
3591                                                                PCCOR_SIGNATURE pMemberSignature,
3592                                                                DWORD       cMemberSignature)
3593 {
3594     STANDARD_VM_CONTRACT;
3595
3596     if (dwByValueClassToken != this->GetCl())
3597     {
3598         return FALSE;
3599     }
3600
3601     if (!bmtGenerics->HasInstantiation())
3602     {
3603         return TRUE;
3604     }
3605
3606     // The value class is generic.  Check that the signature of the field
3607     // is _exactly_ equivalent to VC<!0, !1, !2, ...>.  Do this by consing up a fake
3608     // signature.
3609     DWORD nGenericArgs = bmtGenerics->GetNumGenericArgs();
3610     CONSISTENCY_CHECK(nGenericArgs != 0);
3611
3612     SigBuilder sigBuilder;
3613
3614     sigBuilder.AppendElementType(ELEMENT_TYPE_GENERICINST);
3615     sigBuilder.AppendElementType(ELEMENT_TYPE_VALUETYPE);
3616     sigBuilder.AppendToken(dwByValueClassToken);
3617     sigBuilder.AppendData(nGenericArgs);
3618     for (unsigned int typearg = 0; typearg < nGenericArgs; typearg++)
3619     {
3620         sigBuilder.AppendElementType(ELEMENT_TYPE_VAR);
3621         sigBuilder.AppendData(typearg);
3622     }
3623
3624     DWORD cFakeSig;
3625     PCCOR_SIGNATURE pFakeSig = (PCCOR_SIGNATURE)sigBuilder.GetSignature(&cFakeSig);
3626
3627     PCCOR_SIGNATURE pFieldSig = pMemberSignature + 1; // skip the CALLCONV_FIELD
3628
3629     return MetaSig::CompareElementType(pFakeSig,             pFieldSig,
3630                                        pFakeSig + cFakeSig,  pMemberSignature + cMemberSignature,
3631                                        GetModule(), GetModule(),
3632                                        NULL,                 NULL);
3633
3634 }
3635
3636 //*******************************************************************************
3637 //
3638 // Used pByValueClass cache to mark self-references
3639 //
3640 static BOOL IsSelfRef(MethodTable * pMT)
3641 {
3642     return pMT == (MethodTable *)-1;
3643 }
3644
3645 //*******************************************************************************
3646 //
3647 // Used by BuildMethodTable
3648 //
3649 // Go thru all fields and initialize their FieldDescs.
3650 //
3651 #ifdef _PREFAST_ 
3652 #pragma warning(push)
3653 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
3654 #endif // _PREFAST_
3655
3656 VOID    MethodTableBuilder::InitializeFieldDescs(FieldDesc *pFieldDescList,
3657                                                  const LayoutRawFieldInfo* pLayoutRawFieldInfos,
3658                                                  bmtInternalInfo* bmtInternal,
3659                                                  const bmtGenericsInfo* bmtGenerics,
3660                                                  bmtMetaDataInfo* bmtMetaData,
3661                                                  bmtEnumFieldInfo* bmtEnumFields,
3662                                                  bmtErrorInfo* bmtError,
3663                                                  MethodTable *** pByValueClassCache,
3664                                                  bmtMethAndFieldDescs* bmtMFDescs,
3665                                                  bmtFieldPlacement* bmtFP,
3666                                                  unsigned* totalDeclaredSize)
3667 {
3668     CONTRACTL
3669     {
3670         STANDARD_VM_CHECK;
3671         PRECONDITION(CheckPointer(this));
3672         PRECONDITION(CheckPointer(bmtInternal));
3673         PRECONDITION(CheckPointer(bmtGenerics));
3674         PRECONDITION(CheckPointer(bmtMetaData));
3675         PRECONDITION(CheckPointer(bmtEnumFields));
3676         PRECONDITION(CheckPointer(bmtError));
3677         PRECONDITION(CheckPointer(pByValueClassCache));
3678         PRECONDITION(CheckPointer(bmtMFDescs));
3679         PRECONDITION(CheckPointer(bmtFP));
3680         PRECONDITION(CheckPointer(totalDeclaredSize));
3681     }
3682     CONTRACTL_END;
3683
3684     DWORD i;
3685     IMDInternalImport * pInternalImport = GetMDImport(); // to avoid multiple dereferencings
3686
3687     FieldMarshaler * pNextFieldMarshaler = NULL;
3688     if (HasLayout())
3689     {
3690         pNextFieldMarshaler = (FieldMarshaler*)(GetLayoutInfo()->GetFieldMarshalers());
3691     }
3692
3693
3694 //========================================================================
3695 // BEGIN:
3696 //    Go thru all fields and initialize their FieldDescs.
3697 //========================================================================
3698
3699     DWORD   dwCurrentDeclaredField = 0;
3700     DWORD   dwCurrentStaticField   = 0;
3701     DWORD   dwCurrentThreadStaticField = 0;
3702
3703
3704     DWORD   dwR8Fields              = 0;        // Number of R8's the class has
3705
3706 #ifdef FEATURE_64BIT_ALIGNMENT
3707     // Track whether any field in this type requires 8-byte alignment
3708     BOOL    fFieldRequiresAlign8 = HasParent() ? GetParentMethodTable()->RequiresAlign8() : FALSE;
3709 #endif
3710
3711     for (i = 0; i < bmtMetaData->cFields; i++)
3712     {
3713         PCCOR_SIGNATURE pMemberSignature;
3714         DWORD       cMemberSignature;
3715         DWORD       dwMemberAttrs;
3716
3717         dwMemberAttrs = bmtMetaData->pFieldAttrs[i];
3718
3719         BOOL fIsStatic = IsFdStatic(dwMemberAttrs);
3720
3721         // We don't store static final primitive fields in the class layout
3722         if (IsFdLiteral(dwMemberAttrs))
3723             continue;
3724
3725         if (!IsFdPublic(dwMemberAttrs))
3726             SetHasNonPublicFields();
3727
3728         if (IsFdNotSerialized(dwMemberAttrs))
3729             SetCannotBeBlittedByObjectCloner();
3730
3731         IfFailThrow(pInternalImport->GetSigOfFieldDef(bmtMetaData->pFields[i], &cMemberSignature, &pMemberSignature));
3732         // Signature validation
3733         IfFailThrow(validateTokenSig(bmtMetaData->pFields[i],pMemberSignature,cMemberSignature,dwMemberAttrs,pInternalImport));
3734
3735         FieldDesc * pFD;
3736         DWORD       dwLog2FieldSize = 0;
3737         BOOL        bCurrentFieldIsGCPointer = FALSE;
3738         mdToken     dwByValueClassToken = 0;
3739         MethodTable * pByValueClass = NULL;
3740         BOOL        fIsByValue = FALSE;
3741         BOOL        fIsThreadStatic = FALSE;
3742         BOOL        fHasRVA = FALSE;
3743
3744         MetaSig fsig(pMemberSignature,
3745                      cMemberSignature,
3746                      GetModule(),
3747                      &bmtGenerics->typeContext,
3748                      MetaSig::sigField);
3749         CorElementType ElementType = fsig.NextArg();
3750
3751
3752         // Get type
3753         if (!isCallConv(fsig.GetCallingConvention(), IMAGE_CEE_CS_CALLCONV_FIELD))
3754         {
3755             IfFailThrow(COR_E_TYPELOAD);
3756         }
3757
3758         // Determine if a static field is special i.e. RVA based, local to
3759         // a thread or a context
3760         if (fIsStatic)
3761         {
3762             if (IsFdHasFieldRVA(dwMemberAttrs))
3763             {
3764                 fHasRVA = TRUE;
3765             }
3766
3767             HRESULT hr;
3768  
3769             hr = pInternalImport->GetCustomAttributeByName(bmtMetaData->pFields[i],
3770                                                            g_ThreadStaticAttributeClassName,
3771                                                            NULL, NULL);
3772             IfFailThrow(hr);
3773             if (hr == S_OK)
3774             {
3775                 fIsThreadStatic = TRUE;
3776             }
3777
3778
3779             if (ElementType == ELEMENT_TYPE_VALUETYPE)
3780             {
3781                 hr = pInternalImport->GetCustomAttributeByName(bmtMetaData->pFields[i],
3782                                                                g_CompilerServicesFixedAddressValueTypeAttribute,
3783                                                                NULL, NULL);
3784                 IfFailThrow(hr);
3785                 if (hr == S_OK)
3786                 {
3787                     bmtFP->fHasFixedAddressValueTypes = true;
3788                 }
3789             }
3790
3791
3792             // Do some sanity checks that we are not mixing context and thread
3793             // relative statics.
3794             if (fHasRVA && fIsThreadStatic)
3795             {
3796                 IfFailThrow(COR_E_TYPELOAD);
3797             }
3798
3799             if (bmtFP->fHasFixedAddressValueTypes && GetAssembly()->IsCollectible())
3800             {
3801                 BuildMethodTableThrowException(IDS_CLASSLOAD_COLLECTIBLEFIXEDVTATTR);
3802             }
3803         }
3804
3805
3806     GOT_ELEMENT_TYPE:
3807         // Type to store in FieldDesc - we don't want to have extra case statements for
3808         // ELEMENT_TYPE_STRING, SDARRAY etc., so we convert all object types to CLASS.
3809         // Also, BOOLEAN, CHAR are converted to U1, I2.
3810         CorElementType FieldDescElementType = ElementType;
3811
3812         switch (ElementType)
3813         {
3814         case ELEMENT_TYPE_I1:
3815         case ELEMENT_TYPE_U1:
3816             {
3817                 dwLog2FieldSize = 0;
3818                 break;
3819             }
3820
3821         case ELEMENT_TYPE_I2:
3822         case ELEMENT_TYPE_U2:
3823             {
3824                 dwLog2FieldSize = 1;
3825                 break;
3826             }
3827
3828         case ELEMENT_TYPE_I4:
3829         case ELEMENT_TYPE_U4:
3830         IN_TARGET_32BIT(case ELEMENT_TYPE_I:)
3831         IN_TARGET_32BIT(case ELEMENT_TYPE_U:)
3832         case ELEMENT_TYPE_R4:
3833             {
3834                 dwLog2FieldSize = 2;
3835                 break;
3836             }
3837
3838         case ELEMENT_TYPE_BOOLEAN:
3839             {
3840                 //                FieldDescElementType = ELEMENT_TYPE_U1;
3841                 dwLog2FieldSize = 0;
3842                 break;
3843             }
3844
3845         case ELEMENT_TYPE_CHAR:
3846             {
3847                 //                FieldDescElementType = ELEMENT_TYPE_U2;
3848                 dwLog2FieldSize = 1;
3849                 break;
3850             }
3851
3852         case ELEMENT_TYPE_R8:
3853             {
3854                 dwR8Fields++;
3855
3856                 // Deliberate fall through...
3857             }
3858        
3859         case ELEMENT_TYPE_I8:
3860         case ELEMENT_TYPE_U8:
3861         IN_TARGET_64BIT(case ELEMENT_TYPE_I:)
3862         IN_TARGET_64BIT(case ELEMENT_TYPE_U:)
3863             {
3864 #ifdef FEATURE_64BIT_ALIGNMENT
3865                 // Record that this field requires alignment for Int64/UInt64.
3866                 if(!fIsStatic)
3867                     fFieldRequiresAlign8 = true;
3868 #endif                
3869                 dwLog2FieldSize = 3;
3870                 break;
3871             }
3872
3873         case ELEMENT_TYPE_FNPTR:
3874         case ELEMENT_TYPE_PTR:   // ptrs are unmanaged scalars, for layout
3875             {
3876                 dwLog2FieldSize = LOG2_PTRSIZE;
3877                 break;
3878             }
3879
3880         // Class type variable (method type variables aren't allowed in fields)
3881         // These only occur in open types used for verification/reflection.
3882         case ELEMENT_TYPE_VAR:
3883         case ELEMENT_TYPE_MVAR:
3884            // deliberate drop through - do fake field layout
3885         case ELEMENT_TYPE_STRING:
3886         case ELEMENT_TYPE_SZARRAY:      // single dim, zero
3887         case ELEMENT_TYPE_ARRAY:        // all other arrays
3888         case ELEMENT_TYPE_CLASS: // objectrefs
3889         case ELEMENT_TYPE_OBJECT:
3890             {
3891                 dwLog2FieldSize = LOG2_PTRSIZE;
3892                 bCurrentFieldIsGCPointer = TRUE;
3893                 FieldDescElementType = ELEMENT_TYPE_CLASS;
3894
3895                 if (!fIsStatic)
3896                 {
3897                     SetHasFieldsWhichMustBeInited();
3898                     if (ElementType != ELEMENT_TYPE_STRING)
3899                         SetCannotBeBlittedByObjectCloner();
3900                 }
3901                 else
3902                 {   // EnumerateFieldDescs already counted the total number of static vs. instance
3903                     // fields, now we're further subdividing the static field count by GC and non-GC.
3904                     bmtEnumFields->dwNumStaticObjRefFields++;
3905                     if (fIsThreadStatic)
3906                         bmtEnumFields->dwNumThreadStaticObjRefFields++;
3907                 }
3908                 break;
3909             }
3910
3911         case ELEMENT_TYPE_VALUETYPE: // a byvalue class field
3912             {
3913                 Module * pTokenModule;
3914                 dwByValueClassToken = fsig.GetArgProps().PeekValueTypeTokenClosed(GetModule(), &bmtGenerics->typeContext, &pTokenModule);
3915                 fIsByValue = TRUE;
3916
3917                 // By-value class
3918                 BAD_FORMAT_NOTHROW_ASSERT(dwByValueClassToken != 0);
3919                 
3920                 if (this->IsValueClass() && (pTokenModule == GetModule()))
3921                 {
3922                     if (TypeFromToken(dwByValueClassToken) == mdtTypeRef)
3923                     {
3924                         // It's a typeref - check if it's a class that has a static field of itself
3925                         LPCUTF8 pszNameSpace;
3926                         LPCUTF8 pszClassName;
3927                         if (FAILED(pInternalImport->GetNameOfTypeRef(dwByValueClassToken, &pszNameSpace, &pszClassName)))
3928                         {
3929                             BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
3930                         }
3931                         
3932                         if (IsStrLongerThan((char *)pszClassName, MAX_CLASS_NAME)
3933                             || IsStrLongerThan((char *)pszNameSpace, MAX_CLASS_NAME)
3934                             || (strlen(pszClassName) + strlen(pszNameSpace) + 1 >= MAX_CLASS_NAME))
3935                         {
3936                             BuildMethodTableThrowException(BFA_TYPEREG_NAME_TOO_LONG, mdMethodDefNil);
3937                         }
3938
3939                         mdToken tkRes;
3940                         if (FAILED(pInternalImport->GetResolutionScopeOfTypeRef(dwByValueClassToken, &tkRes)))
3941                         {
3942                             BuildMethodTableThrowException(BFA_BAD_TYPEREF_TOKEN, dwByValueClassToken);
3943                         }
3944                         
3945                         if (TypeFromToken(tkRes) == mdtTypeRef)
3946                         {
3947                             if (!pInternalImport->IsValidToken(tkRes))
3948                             {
3949                                 BuildMethodTableThrowException(BFA_BAD_TYPEREF_TOKEN, mdMethodDefNil);
3950                             }
3951                         }
3952                         else
3953                         {
3954                             tkRes = mdTokenNil;
3955                         }
3956                         
3957                         if (FAILED(pInternalImport->FindTypeDef(pszNameSpace,
3958                                                                 pszClassName,
3959                                                                 tkRes,
3960                                                                 &dwByValueClassToken)))
3961                         {
3962                             dwByValueClassToken = mdTokenNil;
3963                         }
3964                     } // If field is static typeref
3965
3966                     BOOL selfref = IsSelfReferencingStaticValueTypeField(dwByValueClassToken,
3967                                                                     bmtInternal,
3968                                                                     bmtGenerics,
3969                                                                     pMemberSignature,
3970                                                                     cMemberSignature);
3971
3972                     if (selfref)
3973                     {   // immediately self-referential fields must be static.
3974                         if (!fIsStatic)
3975                         {
3976                             BuildMethodTableThrowException(IDS_CLASSLOAD_VALUEINSTANCEFIELD, mdMethodDefNil);
3977                         }
3978
3979                         if (!IsValueClass())
3980                         {
3981                             BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_MUST_BE_BYVAL, mdTokenNil);
3982                         }
3983
3984                         pByValueClass = (MethodTable *)-1;
3985                     }
3986                 } // If 'this' is a value class
3987
3988                 // It's not self-referential so try to load it
3989                 if (pByValueClass == NULL)
3990                 {
3991                     // Loading a non-self-ref valuetype field.
3992                     OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOAD_APPROXPARENTS);
3993                     // We load the approximate type of the field to avoid recursion problems.
3994                     // MethodTable::DoFullyLoad() will later load it fully
3995                     pByValueClass = fsig.GetArgProps().GetTypeHandleThrowing(GetModule(),
3996                                                                             &bmtGenerics->typeContext,
3997                                                                              ClassLoader::LoadTypes,
3998                                                                              CLASS_LOAD_APPROXPARENTS,
3999                                                                              TRUE
4000                                                                              ).GetMethodTable();
4001                 }
4002                 
4003                 // #FieldDescTypeMorph  IF it is an enum, strip it down to its underlying type
4004                 if (IsSelfRef(pByValueClass) ? IsEnum() : pByValueClass->IsEnum())
4005                 {
4006                     if (IsSelfRef(pByValueClass))
4007                     {   // It is self-referencing enum (ValueType) static field - it is forbidden in the ECMA spec, but supported by CLR since v1
4008                         // Note: literal static fields are skipped early in this loop
4009                         if (bmtMFDescs->ppFieldDescList[0] == NULL)
4010                         {   // The field is defined before (the only) instance field
4011                             // AppCompat with 3.5 SP1 and 4.0 RTM behavior
4012                             BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil);
4013                         }
4014                         // We will treat the field type as if it was its underlying type (we know its size and will check correctly RVA with the size 
4015                         // later in this method)
4016                         // Therefore we do not have to run code:VerifySelfReferencingStaticValueTypeFields_WithRVA or code:#SelfReferencingStaticValueTypeField_Checks
4017                     }
4018                     BAD_FORMAT_NOTHROW_ASSERT((IsSelfRef(pByValueClass) ? 
4019                             bmtEnumFields->dwNumInstanceFields : pByValueClass->GetNumInstanceFields())
4020                                 == 1); // enums must have exactly one field
4021                     FieldDesc * enumField = IsSelfRef(pByValueClass) ?
4022                             bmtMFDescs->ppFieldDescList[0] : pByValueClass->GetApproxFieldDescListRaw();
4023                     BAD_FORMAT_NOTHROW_ASSERT(!enumField->IsStatic());   // no real static fields on enums
4024                     ElementType = enumField->GetFieldType();
4025                     BAD_FORMAT_NOTHROW_ASSERT(ElementType != ELEMENT_TYPE_VALUETYPE);
4026                     fIsByValue = FALSE; // we're going to treat it as the underlying type now
4027                     goto GOT_ELEMENT_TYPE;
4028                 }
4029                 
4030                 // Check ByRefLike fields
4031                 if (!IsSelfRef(pByValueClass) && pByValueClass->IsByRefLike())
4032                 {
4033                     if (fIsStatic)
4034                     {
4035                         // Byref-like types cannot be used for static fields
4036                         BuildMethodTableThrowException(IDS_CLASSLOAD_BYREFLIKE_STATICFIELD);
4037                     }
4038                     if (!bmtFP->fIsByRefLikeType)
4039                     {
4040                         // Non-byref-like types cannot contain byref-like instance fields
4041                         BuildMethodTableThrowException(IDS_CLASSLOAD_BYREFLIKE_INSTANCEFIELD);
4042                     }
4043                 }
4044
4045                 if (!IsSelfRef(pByValueClass) && pByValueClass->GetClass()->HasNonPublicFields())
4046                 {   // If a class has a field of type ValueType with non-public fields in it,
4047                     // the class must "inherit" this characteristic
4048                     SetHasNonPublicFields();
4049                 }
4050
4051                 if (!fHasRVA)
4052                 {
4053                     if (!fIsStatic)
4054                     {
4055                         // Inherit instance attributes
4056                         EEClass * pFieldClass = pByValueClass->GetClass();
4057
4058 #ifdef FEATURE_64BIT_ALIGNMENT
4059                         // If a value type requires 8-byte alignment this requirement must be inherited by any
4060                         // class/struct that embeds it as a field.
4061                         if (pFieldClass->IsAlign8Candidate())
4062                             fFieldRequiresAlign8 = true;
4063 #endif
4064                         if (pFieldClass->HasNonPublicFields())
4065                             SetHasNonPublicFields();
4066                         if (pFieldClass->HasFieldsWhichMustBeInited())
4067                             SetHasFieldsWhichMustBeInited();
4068
4069 #ifdef FEATURE_READYTORUN
4070                         if (!(pByValueClass->IsTruePrimitive() || pByValueClass->IsEnum()))
4071                         {
4072                             CheckLayoutDependsOnOtherModules(pByValueClass);
4073                         }
4074 #endif
4075                     }
4076                     else
4077                     {   // Increment the number of static fields that contain object references.
4078                         bmtEnumFields->dwNumStaticBoxedFields++;
4079                         if (fIsThreadStatic)
4080                             bmtEnumFields->dwNumThreadStaticBoxedFields++;
4081                     }
4082                 }
4083                 
4084                 if (*pByValueClassCache == NULL)
4085                 {
4086                     DWORD dwNumFields = bmtEnumFields->dwNumInstanceFields + bmtEnumFields->dwNumStaticFields;
4087                     
4088                     *pByValueClassCache = new (GetStackingAllocator()) MethodTable * [dwNumFields];
4089                     memset (*pByValueClassCache, 0, dwNumFields * sizeof(MethodTable **));
4090                 }
4091                 
4092                 // Thread static fields come after instance fields and regular static fields in this list
4093                 if (fIsThreadStatic)
4094                 {
4095                     (*pByValueClassCache)[bmtEnumFields->dwNumInstanceFields + bmtEnumFields->dwNumStaticFields - bmtEnumFields->dwNumThreadStaticFields + dwCurrentThreadStaticField] = pByValueClass;
4096                     // make sure to record the correct size for static field
4097                     // layout
4098                     dwLog2FieldSize = LOG2_PTRSIZE; // handle
4099                 }
4100                 // Regular static fields come after instance fields in this list
4101                 else if (fIsStatic)
4102                 {
4103                     (*pByValueClassCache)[bmtEnumFields->dwNumInstanceFields + dwCurrentStaticField] = pByValueClass;
4104                     // make sure to record the correct size for static field
4105                     // layout
4106                     dwLog2FieldSize = LOG2_PTRSIZE; // handle
4107                 }
4108                 else
4109                 {
4110                     (*pByValueClassCache)[dwCurrentDeclaredField] = pByValueClass;
4111                     dwLog2FieldSize = 0; // unused
4112                 }
4113                 
4114                 break;
4115             }
4116         default:
4117             {
4118                 BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil);
4119             }
4120         }
4121
4122         if (!fIsStatic)
4123         {
4124             pFD = &pFieldDescList[dwCurrentDeclaredField];
4125             *totalDeclaredSize += (1 << dwLog2FieldSize);
4126         }
4127         else /* (dwMemberAttrs & mdStatic) */
4128         {
4129             if (fIsThreadStatic)
4130             {
4131                 pFD = &pFieldDescList[bmtEnumFields->dwNumInstanceFields + bmtEnumFields->dwNumStaticFields - bmtEnumFields->dwNumThreadStaticFields + dwCurrentThreadStaticField];
4132             }
4133             else
4134             {
4135                 pFD = &pFieldDescList[bmtEnumFields->dwNumInstanceFields + dwCurrentStaticField];
4136             }
4137         }
4138
4139         bmtMFDescs->ppFieldDescList[i] = pFD;
4140
4141         const LayoutRawFieldInfo *pLayoutFieldInfo = NULL;
4142
4143         if (HasLayout())
4144         {
4145             const LayoutRawFieldInfo *pwalk = pLayoutRawFieldInfos;
4146             while (pwalk->m_MD != mdFieldDefNil)
4147             {
4148                 if (pwalk->m_MD == bmtMetaData->pFields[i])
4149                 {
4150                     pLayoutFieldInfo = pwalk;
4151
4152                     const FieldMarshaler *pSrcFieldMarshaler = (const FieldMarshaler *) &pwalk->m_FieldMarshaler;
4153
4154                     pSrcFieldMarshaler->CopyTo(pNextFieldMarshaler, MAXFIELDMARSHALERSIZE);
4155
4156                     pNextFieldMarshaler->SetFieldDesc(pFD);
4157                     pNextFieldMarshaler->SetExternalOffset(pwalk->m_offset);
4158
4159                     ((BYTE*&)pNextFieldMarshaler) += MAXFIELDMARSHALERSIZE;
4160                     break;
4161                 }
4162                 pwalk++;
4163             }
4164         }
4165
4166         LPCSTR pszFieldName = NULL;
4167 #ifdef _DEBUG 
4168         if (FAILED(pInternalImport->GetNameOfFieldDef(bmtMetaData->pFields[i], &pszFieldName)))
4169         {
4170             pszFieldName = "Invalid FieldDef record";
4171         }
4172 #endif
4173         // #InitCall Initialize contents of the field descriptor called from 
4174         pFD->Init(
4175                   bmtMetaData->pFields[i],
4176                   FieldDescElementType,
4177                   dwMemberAttrs,
4178                   fIsStatic,
4179                   fHasRVA,
4180                   fIsThreadStatic,
4181                   pszFieldName
4182                   );
4183
4184         // We're using FieldDesc::m_pMTOfEnclosingClass to temporarily store the field's size.
4185         // 
4186         if (fIsByValue)
4187         {
4188             if (!fIsStatic &&
4189                 (IsBlittable() || HasExplicitFieldOffsetLayout()))
4190             {
4191                 (DWORD_PTR &)pFD->m_pMTOfEnclosingClass =
4192                     (*pByValueClassCache)[dwCurrentDeclaredField]->GetNumInstanceFieldBytes();
4193
4194                 if (pLayoutFieldInfo)
4195                     IfFailThrow(pFD->SetOffset(pLayoutFieldInfo->m_offset));
4196                 else
4197                     pFD->SetOffset(FIELD_OFFSET_VALUE_CLASS);
4198             }
4199             else if (!fIsStatic && IsManagedSequential())
4200             {
4201                 (DWORD_PTR &)pFD->m_pMTOfEnclosingClass =
4202                     (*pByValueClassCache)[dwCurrentDeclaredField]->GetNumInstanceFieldBytes();
4203
4204                 IfFailThrow(pFD->SetOffset(pLayoutFieldInfo->m_managedOffset));
4205             }
4206             else
4207             {
4208                 // static value class fields hold a handle, which is ptr sized
4209                 // (instance field layout ignores this value)
4210                 (DWORD_PTR&)(pFD->m_pMTOfEnclosingClass) = LOG2_PTRSIZE;
4211                 pFD->SetOffset(FIELD_OFFSET_VALUE_CLASS);
4212             }
4213         }
4214         else
4215         {
4216             (DWORD_PTR &)(pFD->m_pMTOfEnclosingClass) = (size_t)dwLog2FieldSize;
4217
4218             // -1 (FIELD_OFFSET_UNPLACED) means that this is a non-GC field that has not yet been placed
4219             // -2 (FIELD_OFFSET_UNPLACED_GC_PTR) means that this is a GC pointer field that has not yet been placed
4220
4221             // If there is any kind of explicit layout information for this field, use it. If not, then
4222             // mark it as either GC or non-GC and as unplaced; it will get placed later on in an optimized way.
4223
4224             if ((IsBlittable() || HasExplicitFieldOffsetLayout()) && !fIsStatic)
4225                 IfFailThrow(pFD->SetOffset(pLayoutFieldInfo->m_offset));
4226             else if (IsManagedSequential() && !fIsStatic)
4227                 IfFailThrow(pFD->SetOffset(pLayoutFieldInfo->m_managedOffset));
4228             else if (bCurrentFieldIsGCPointer)
4229                 pFD->SetOffset(FIELD_OFFSET_UNPLACED_GC_PTR);
4230             else
4231                 pFD->SetOffset(FIELD_OFFSET_UNPLACED);
4232         }
4233
4234         if (!fIsStatic)
4235         {
4236             if (!fIsByValue)
4237             {
4238                 if (++bmtFP->NumInstanceFieldsOfSize[dwLog2FieldSize] == 1)
4239                     bmtFP->FirstInstanceFieldOfSize[dwLog2FieldSize] = dwCurrentDeclaredField;
4240             }
4241
4242             dwCurrentDeclaredField++;
4243
4244             if (bCurrentFieldIsGCPointer)
4245             {
4246                 bmtFP->NumInstanceGCPointerFields++;
4247             }
4248         }
4249         else /* static fields */
4250         {
4251             // Static fields are stored in the vtable after the vtable and interface slots.  We don't
4252             // know how large the vtable will be, so we will have to fixup the slot number by
4253             // <vtable + interface size> later.
4254
4255             if (fIsThreadStatic)
4256             {
4257                 dwCurrentThreadStaticField++;
4258             }
4259             else
4260             {
4261                 dwCurrentStaticField++;
4262             }
4263
4264             if (fHasRVA)
4265             {
4266                 if (FieldDescElementType == ELEMENT_TYPE_CLASS)
4267                 {   // RVA fields are not allowed to have GC pointers.
4268                     BAD_FORMAT_NOTHROW_ASSERT(!"ObjectRef in an RVA field");
4269                     BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil);
4270                 }
4271                 if (FieldDescElementType == ELEMENT_TYPE_VALUETYPE)
4272                 {
4273                     if (IsSelfRef(pByValueClass))
4274                     {   // We will verify self-referencing statics after the loop through all fields - see code:#SelfReferencingStaticValueTypeField_Checks
4275                         bmtFP->fHasSelfReferencingStaticValueTypeField_WithRVA = TRUE;
4276                     }
4277                     else
4278                     {
4279                         if (pByValueClass->GetClass()->HasFieldsWhichMustBeInited())
4280                         {   // RVA fields are not allowed to have GC pointers.
4281                             BAD_FORMAT_NOTHROW_ASSERT(!"ObjectRef in an RVA field");
4282                             BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil);
4283                         }
4284                     }
4285                 }
4286                 
4287                 // Set the field offset
4288                 DWORD rva;
4289                 IfFailThrow(pInternalImport->GetFieldRVA(pFD->GetMemberDef(), &rva));
4290                 
4291                 // Ensure that the IL image is loaded. Note that this assembly may
4292                 // have an ngen image, but this type may have failed to load during ngen.
4293                 GetModule()->GetFile()->LoadLibrary(FALSE);
4294                 
4295                 DWORD fldSize;
4296                 if (FieldDescElementType == ELEMENT_TYPE_VALUETYPE)
4297                 {
4298                     if (IsSelfRef(pByValueClass))
4299                     {
4300                         _ASSERTE(bmtFP->fHasSelfReferencingStaticValueTypeField_WithRVA);
4301                         
4302                         // We do not known the size yet
4303                         _ASSERTE(bmtFP->NumInstanceFieldBytes == 0);
4304                         // We will check just the RVA with size 0 now, the full size verification will happen in code:VerifySelfReferencingStaticValueTypeFields_WithRVA
4305                         fldSize = 0;
4306                     }
4307                     else
4308                     {
4309                         fldSize = pByValueClass->GetNumInstanceFieldBytes();
4310                     }
4311                 }
4312                 else
4313                 {
4314                     fldSize = GetSizeForCorElementType(FieldDescElementType);
4315                 }
4316                 
4317                 pFD->SetOffsetRVA(rva);
4318             }
4319             else if (fIsThreadStatic)
4320             {
4321                 bmtFP->NumThreadStaticFieldsOfSize[dwLog2FieldSize]++;
4322
4323                 if (bCurrentFieldIsGCPointer)
4324                     bmtFP->NumThreadStaticGCPointerFields++;
4325
4326                 if (fIsByValue)
4327                     bmtFP->NumThreadStaticGCBoxedFields++;
4328             }
4329             else
4330             {
4331                 bmtFP->NumRegularStaticFieldsOfSize[dwLog2FieldSize]++;
4332
4333                 if (bCurrentFieldIsGCPointer)
4334                     bmtFP->NumRegularStaticGCPointerFields++;
4335
4336                 if (fIsByValue)
4337                     bmtFP->NumRegularStaticGCBoxedFields++;
4338             }
4339         }
4340     }
4341     // We processed all fields
4342     
4343     //#SelfReferencingStaticValueTypeField_Checks
4344     if (bmtFP->fHasSelfReferencingStaticValueTypeField_WithRVA)
4345     {   // The type has self-referencing static ValueType field with RVA, do more checks now that depend on all fields being processed
4346         
4347         // For enums we already checked its underlying type, we should not get here
4348         _ASSERTE(!IsEnum());
4349         
4350         if (HasFieldsWhichMustBeInited())
4351         {   // RVA fields are not allowed to have GC pointers.
4352             BAD_FORMAT_NOTHROW_ASSERT(!"ObjectRef in an RVA self-referencing static field");
4353             BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil);
4354         }
4355     }
4356     
4357     DWORD dwNumInstanceFields = dwCurrentDeclaredField + (HasParent() ? GetParentMethodTable()->GetNumInstanceFields() : 0);
4358     DWORD dwNumStaticFields = bmtEnumFields->dwNumStaticFields;
4359     DWORD dwNumThreadStaticFields = bmtEnumFields->dwNumThreadStaticFields;
4360
4361     if (!FitsIn<WORD>(dwNumInstanceFields) ||
4362         !FitsIn<WORD>(dwNumStaticFields))
4363     {   // An implementation limitation means that it's an error if there are greater that MAX_WORD fields.
4364         BuildMethodTableThrowException(IDS_EE_TOOMANYFIELDS);
4365     }
4366
4367     GetHalfBakedClass()->SetNumInstanceFields((WORD)dwNumInstanceFields);
4368     GetHalfBakedClass()->SetNumStaticFields((WORD)dwNumStaticFields);
4369     GetHalfBakedClass()->SetNumThreadStaticFields((WORD)dwNumThreadStaticFields);
4370
4371     if (bmtFP->fHasFixedAddressValueTypes)
4372     {
4373         // To make things simpler, if the class has any field with this requirement, we'll set
4374         // all the statics to have this property. This allows us to only need to persist one bit
4375         // for the ngen case.
4376         GetHalfBakedClass()->SetHasFixedAddressVTStatics();
4377     }
4378
4379 #ifdef FEATURE_64BIT_ALIGNMENT
4380     // For types with layout we drop any 64-bit alignment requirement if the packing size was less than 8
4381     // bytes (this mimics what the native compiler does and ensures we match up calling conventions during
4382     // interop).
4383     if (HasLayout() && GetLayoutInfo()->GetPackingSize() < 8)
4384     {
4385         fFieldRequiresAlign8 = false;
4386     }
4387
4388     if (fFieldRequiresAlign8)
4389     {
4390         SetAlign8Candidate();
4391     }
4392 #endif // FEATURE_64BIT_ALIGNMENT
4393
4394 #ifdef FEATURE_DOUBLE_ALIGNMENT_HINT
4395     if (ShouldAlign8(dwR8Fields, dwNumInstanceFields))
4396     {
4397         SetAlign8Candidate();
4398     }
4399 #endif // FEATURE_DOUBLE_ALIGNMENT_HINT
4400
4401
4402     //========================================================================
4403     // END:
4404     //    Go thru all fields and initialize their FieldDescs.
4405     //========================================================================
4406
4407     return;
4408 } // MethodTableBuilder::InitializeFieldDescs
4409
4410 #ifdef _PREFAST_ 
4411 #pragma warning(pop)
4412 #endif
4413
4414 //*******************************************************************************
4415 // Verify self-referencing static ValueType fields with RVA (when the size of the ValueType is known).
4416 void 
4417 MethodTableBuilder::VerifySelfReferencingStaticValueTypeFields_WithRVA(
4418     MethodTable ** pByValueClassCache)
4419 {
4420     STANDARD_VM_CONTRACT;
4421     
4422     _ASSERTE(bmtFP->fHasSelfReferencingStaticValueTypeField_WithRVA);
4423     // Enum's static self-referencing fields have been verified as the underlying type of the enum, we should not get here for them
4424     _ASSERTE(!IsEnum());
4425     // The size of the ValueType should be known at this point (the caller throws if it is 0)
4426     _ASSERTE(bmtFP->NumInstanceFieldBytes != 0);
4427     
4428     FieldDesc * pFieldDescList = GetApproxFieldDescListRaw();
4429     DWORD nFirstThreadStaticFieldIndex = bmtEnumFields->dwNumInstanceFields + bmtEnumFields->dwNumStaticFields - bmtEnumFields->dwNumThreadStaticFields;
4430     for (DWORD i = bmtEnumFields->dwNumInstanceFields; i < nFirstThreadStaticFieldIndex; i++)
4431     {
4432         FieldDesc * pFD = &pFieldDescList[i];
4433         _ASSERTE(pFD->IsStatic());
4434         
4435         if (pFD->IsRVA() && pFD->IsByValue())
4436         {
4437             _ASSERTE(pByValueClassCache[i] != NULL);
4438             
4439             if (IsSelfRef(pByValueClassCache[i]))
4440             {
4441                 DWORD rva;
4442                 IfFailThrow(GetMDImport()->GetFieldRVA(pFD->GetMemberDef(), &rva));
4443             }
4444         }
4445     }
4446 } // MethodTableBuilder::VerifySelfReferencingStaticValueTypeFields_WithRVA
4447
4448 //*******************************************************************************
4449 // Returns true if hEnclosingTypeCandidate encloses, at any arbitrary depth,
4450 // hNestedTypeCandidate; returns false otherwise.
4451
4452 bool MethodTableBuilder::IsEnclosingNestedTypePair(
4453     bmtTypeHandle hEnclosingTypeCandidate,
4454     bmtTypeHandle hNestedTypeCandidate)
4455 {
4456     STANDARD_VM_CONTRACT;
4457
4458     CONSISTENCY_CHECK(!hEnclosingTypeCandidate.IsNull());
4459     CONSISTENCY_CHECK(!hNestedTypeCandidate.IsNull());
4460     CONSISTENCY_CHECK(!bmtTypeHandle::Equal(hEnclosingTypeCandidate, hNestedTypeCandidate));
4461
4462     Module * pModule = hEnclosingTypeCandidate.GetModule();
4463
4464     if (pModule != hNestedTypeCandidate.GetModule())
4465     {   // If the modules aren't the same, then there's no way
4466         // hBase could be an enclosing type of hChild. We make
4467         // this check early so that the code can deal with only
4468         // one Module and IMDInternalImport instance and can avoid
4469         // extra checks.
4470         return false;
4471     }
4472
4473     IMDInternalImport * pMDImport = pModule->GetMDImport();
4474
4475     mdTypeDef tkEncl = hEnclosingTypeCandidate.GetTypeDefToken();
4476     mdTypeDef tkNest = hNestedTypeCandidate.GetTypeDefToken();
4477
4478     while (tkEncl != tkNest)
4479     {   // Do this using the metadata APIs because MethodTableBuilder does
4480         // not construct type representations for enclosing type chains.
4481         if (FAILED(pMDImport->GetNestedClassProps(tkNest, &tkNest)))
4482         {   // tokNest is not a nested type.
4483             return false;
4484         }
4485     }
4486
4487     // tkNest's enclosing type is tkEncl, so we've shown that
4488     // hEnclosingTypeCandidate encloses hNestedTypeCandidate
4489     return true;
4490 }
4491
4492 //*******************************************************************************
4493 // Given an arbitrary nesting+subclassing pattern like this:
4494 //
4495 // class C1 {
4496 //     private virtual void Foo() { ... }
4497 //     class C2 : C1 {
4498 //       ...
4499 //         class CN : CN-1 {
4500 //             private override void Foo() { ... }
4501 //         }
4502 //       ...
4503 //     }
4504 // }
4505 //
4506 // this method will return true, where hChild == N and hBase == C1
4507 //
4508 // Note that there is no requirement that a type derive from its immediately
4509 // enclosing type, but can skip a level, such as this example:
4510 //
4511 // class A
4512 // {
4513 //     private virtual void Foo() { }
4514 //     public class B
4515 //     {
4516 //         public class C : A
4517 //         {
4518 //             private override void Foo() { }
4519 //         }
4520 //     }
4521 // }
4522 //
4523 // NOTE: IMPORTANT: This code assumes that hBase is indeed a base type of hChild,
4524 //                  and behaviour is undefined if this is not the case.
4525
4526 bool MethodTableBuilder::IsBaseTypeAlsoEnclosingType(
4527     bmtTypeHandle hBase,
4528     bmtTypeHandle hChild)
4529 {
4530     STANDARD_VM_CONTRACT;
4531
4532     CONSISTENCY_CHECK(!hBase.IsNull());
4533     CONSISTENCY_CHECK(!hChild.IsNull());
4534     CONSISTENCY_CHECK(!bmtTypeHandle::Equal(hBase, hChild));
4535
4536     // The idea of this algorithm is that if we climb the inheritance chain
4537     // starting at hChild then we'll eventually hit hBase. If we check that
4538     // for every (hParent, hChild) pair in the chain that hParent encloses
4539     // hChild, then we've shown that hBase encloses hChild.
4540
4541     while (!bmtTypeHandle::Equal(hBase, hChild))
4542     {
4543         CONSISTENCY_CHECK(!hChild.GetParentType().IsNull());
4544         bmtTypeHandle hParent(hChild.GetParentType());
4545
4546         if (!IsEnclosingNestedTypePair(hParent, hChild))
4547         {   // First, the parent type must enclose the child type.
4548             // If this is not the case we fail immediately.
4549             return false;
4550         }
4551
4552         // Move up one in the inheritance chain, and try again.
4553         hChild = hParent;
4554     }
4555
4556     // If the loop worked itself from the original hChild all the way
4557     // up to hBase, then we know that for every (hParent, hChild)
4558     // pair in the chain that hParent enclosed hChild, and so we know
4559     // that hBase encloses the original hChild
4560     return true;
4561 }
4562
4563 //*******************************************************************************
4564 BOOL MethodTableBuilder::TestOverrideForAccessibility(
4565     bmtMethodHandle hParentMethod,
4566     bmtTypeHandle   hChildType)
4567 {
4568     STANDARD_VM_CONTRACT;
4569
4570     bmtTypeHandle hParentType(hParentMethod.GetOwningType());
4571
4572     Module * pParentModule = hParentType.GetModule();
4573     Module * pChildModule = hChildType.GetModule();
4574
4575     Assembly * pParentAssembly = pParentModule->GetAssembly();
4576     Assembly * pChildAssembly = pChildModule->GetAssembly();
4577
4578     BOOL isSameAssembly = (pChildAssembly == pParentAssembly);
4579
4580     DWORD dwParentAttrs = hParentMethod.GetDeclAttrs();
4581
4582     // AKA "strict bit". This means that overridability is tightly bound to accessibility.
4583     if (IsMdCheckAccessOnOverride(dwParentAttrs))
4584     {
4585         // Same Assembly
4586         if (isSameAssembly || pParentAssembly->GrantsFriendAccessTo(pChildAssembly, hParentMethod.GetMethodDesc())
4587             || pChildAssembly->IgnoresAccessChecksTo(pParentAssembly))
4588         {
4589             // Can always override any method that has accessibility greater than mdPrivate
4590             if ((dwParentAttrs & mdMemberAccessMask) > mdPrivate)
4591             {   // Fall through
4592             }
4593             // Generally, types cannot override inherited mdPrivate methods, except:
4594             // Types can access enclosing type's private members, so it can
4595             // override them if the nested type extends its enclosing type.
4596             else if ((dwParentAttrs & mdMemberAccessMask) == mdPrivate &&
4597                      IsBaseTypeAlsoEnclosingType(hParentType, hChildType))
4598             {   // Fall through
4599             }
4600             else
4601             {
4602                 return FALSE;
4603             }
4604         }
4605         // Cross-Assembly
4606         else
4607         {
4608             // If the method marks itself as check visibility the the method must be
4609             // public, FamORAssem, or family
4610             if((dwParentAttrs & mdMemberAccessMask) <= mdAssem)
4611             {
4612                 return FALSE;
4613             }
4614         }
4615     }
4616     return TRUE;
4617 }
4618
4619 //*******************************************************************************
4620 VOID MethodTableBuilder::TestOverRide(bmtMethodHandle hParentMethod,
4621                                       bmtMethodHandle hChildMethod)
4622 {
4623     CONTRACTL {
4624         STANDARD_VM_CHECK;
4625         PRECONDITION(IsMdVirtual(hParentMethod.GetDeclAttrs()));
4626         PRECONDITION(IsMdVirtual(hChildMethod.GetDeclAttrs()));
4627     } CONTRACTL_END;
4628
4629     DWORD dwAttrs = hChildMethod.GetDeclAttrs();
4630     DWORD dwParentAttrs = hParentMethod.GetDeclAttrs();
4631
4632     Module *pModule = hChildMethod.GetOwningType().GetModule();
4633     Module *pParentModule = hParentMethod.GetOwningType().GetModule();
4634
4635     Assembly *pAssembly = pModule->GetAssembly();
4636     Assembly *pParentAssembly = pParentModule->GetAssembly();
4637
4638     BOOL isSameModule = (pModule == pParentModule);
4639     BOOL isSameAssembly = (pAssembly == pParentAssembly);
4640
4641     if (!TestOverrideForAccessibility(hParentMethod, hChildMethod.GetOwningType()))
4642     {
4643         BuildMethodTableThrowException(IDS_CLASSLOAD_MI_ACCESS_FAILURE, hChildMethod.GetMethodSignature().GetToken());
4644     }
4645
4646     //
4647     // Refer to Partition II, 9.3.3 for more information on what is permitted.
4648     //
4649
4650     enum WIDENING_STATUS
4651     {
4652         e_NO,       // NO
4653         e_YES,      // YES
4654         e_SA,       // YES, but only when same assembly
4655         e_NSA,      // YES, but only when NOT same assembly
4656         e_SM,       // YES, but only when same module
4657     };
4658
4659     static_assert_no_msg(mdPrivateScope == 0x00);
4660     static_assert_no_msg(mdPrivate      == 0x01);
4661     static_assert_no_msg(mdFamANDAssem  == 0x02);
4662     static_assert_no_msg(mdAssem        == 0x03);
4663     static_assert_no_msg(mdFamily       == 0x04);
4664     static_assert_no_msg(mdFamORAssem   == 0x05);
4665     static_assert_no_msg(mdPublic       == 0x06);
4666
4667     static const DWORD dwCount = mdPublic - mdPrivateScope + 1;
4668     static const WIDENING_STATUS rgWideningTable[dwCount][dwCount] =
4669
4670     //               |        Base type
4671     // Subtype       |        mdPrivateScope  mdPrivate   mdFamANDAssem   mdAssem     mdFamily    mdFamORAssem    mdPublic
4672     // --------------+-------------------------------------------------------------------------------------------------------
4673     /*mdPrivateScope | */ { { e_SM,           e_NO,       e_NO,           e_NO,       e_NO,       e_NO,           e_NO    },
4674     /*mdPrivate      | */   { e_SM,           e_YES,      e_NO,           e_NO,       e_NO,       e_NO,           e_NO    },
4675     /*mdFamANDAssem  | */   { e_SM,           e_YES,      e_SA,           e_NO,       e_NO,       e_NO,           e_NO    },
4676     /*mdAssem        | */   { e_SM,           e_YES,      e_SA,           e_SA,       e_NO,       e_NO,           e_NO    },
4677     /*mdFamily       | */   { e_SM,           e_YES,      e_YES,          e_NO,       e_YES,      e_NSA,          e_NO    },
4678     /*mdFamORAssem   | */   { e_SM,           e_YES,      e_YES,          e_SA,       e_YES,      e_YES,          e_NO    },
4679     /*mdPublic       | */   { e_SM,           e_YES,      e_YES,          e_YES,      e_YES,      e_YES,          e_YES   } };
4680
4681     DWORD idxParent = (dwParentAttrs & mdMemberAccessMask) - mdPrivateScope;
4682     DWORD idxMember = (dwAttrs & mdMemberAccessMask) - mdPrivateScope;
4683     CONSISTENCY_CHECK(idxParent < dwCount);
4684     CONSISTENCY_CHECK(idxMember < dwCount);
4685
4686     WIDENING_STATUS entry = rgWideningTable[idxMember][idxParent];
4687
4688     if (entry == e_NO ||
4689         (entry == e_SA && !isSameAssembly && !pParentAssembly->GrantsFriendAccessTo(pAssembly, hParentMethod.GetMethodDesc())
4690          && !pAssembly->IgnoresAccessChecksTo(pParentAssembly)) ||
4691         (entry == e_NSA && isSameAssembly) ||
4692         (entry == e_SM && !isSameModule)
4693        )
4694     {
4695         BuildMethodTableThrowException(IDS_CLASSLOAD_REDUCEACCESS, hChildMethod.GetMethodSignature().GetToken());
4696     }
4697
4698     return;
4699 }
4700
4701 //*******************************************************************************
4702 VOID MethodTableBuilder::TestMethodImpl(
4703     bmtMethodHandle hDeclMethod,
4704     bmtMethodHandle hImplMethod)
4705 {
4706     CONTRACTL
4707     {
4708         STANDARD_VM_CHECK;
4709         PRECONDITION(!hDeclMethod.IsNull());
4710         PRECONDITION(!hImplMethod.IsNull());
4711     }
4712     CONTRACTL_END
4713
4714     Module * pDeclModule = hDeclMethod.GetOwningType().GetModule();
4715     Module * pImplModule = hImplMethod.GetOwningType().GetModule();
4716
4717     mdTypeDef tokDecl = hDeclMethod.GetMethodSignature().GetToken();
4718     mdTypeDef tokImpl = hImplMethod.GetMethodSignature().GetToken();
4719
4720     BOOL isSameModule = pDeclModule->Equals(pImplModule);
4721
4722     IMDInternalImport *pIMDDecl = pDeclModule->GetMDImport();
4723     IMDInternalImport *pIMDImpl = pImplModule->GetMDImport();
4724
4725     DWORD dwDeclAttrs;
4726     if (FAILED(pIMDDecl->GetMethodDefProps(tokDecl, &dwDeclAttrs)))
4727     {
4728         BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
4729     }
4730     DWORD dwImplAttrs;
4731     if (FAILED(pIMDImpl->GetMethodDefProps(tokImpl, &dwImplAttrs)))
4732     {
4733         BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
4734     }
4735     
4736     HRESULT hr = COR_E_TYPELOAD;
4737
4738     if (!IsMdVirtual(dwDeclAttrs))
4739     {
4740         BuildMethodTableThrowException(IDS_CLASSLOAD_MI_NONVIRTUAL_DECL);
4741     }
4742     if (!IsMdVirtual(dwImplAttrs))
4743     {
4744         BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MUSTBEVIRTUAL);
4745     }
4746     // Virtual methods cannot be static
4747     if (IsMdStatic(dwDeclAttrs))
4748     {
4749         BuildMethodTableThrowException(IDS_CLASSLOAD_STATICVIRTUAL);
4750     }
4751     if (IsMdStatic(dwImplAttrs))
4752     {
4753         BuildMethodTableThrowException(IDS_CLASSLOAD_STATICVIRTUAL);
4754     }
4755     if (IsMdFinal(dwDeclAttrs))
4756     {
4757         BuildMethodTableThrowException(IDS_CLASSLOAD_MI_FINAL_DECL);
4758     }
4759
4760     // Interface method body that has methodimpl should always be final
4761     if (IsInterface() && !IsMdFinal(dwImplAttrs))
4762     {
4763         BuildMethodTableThrowException(IDS_CLASSLOAD_MI_FINAL_IMPL);
4764     }
4765
4766     // Since MethodImpl's do not affect the visibility of the Decl method, there's
4767     // no need to check.
4768
4769     // If Decl's parent is other than this class, Decl must not be private
4770     mdTypeDef tkImplParent = mdTypeDefNil;
4771     mdTypeDef tkDeclParent = mdTypeDefNil;
4772
4773     if (FAILED(hr = pIMDDecl->GetParentToken(tokDecl, &tkDeclParent)))
4774     {
4775         BuildMethodTableThrowException(hr, *bmtError);
4776     }
4777     if (FAILED(hr = pIMDImpl->GetParentToken(tokImpl, &tkImplParent)))
4778     {
4779         BuildMethodTableThrowException(hr, *bmtError);
4780     }
4781
4782     // Make sure that we test for accessibility restrictions only if the decl is
4783     // not within our own type, as we are allowed to methodImpl a private with the
4784     // strict bit set if it is in our own type.
4785     if (!isSameModule || tkDeclParent != tkImplParent)
4786     {
4787         if (!TestOverrideForAccessibility(hDeclMethod, hImplMethod.GetOwningType()))
4788         {
4789             BuildMethodTableThrowException(IDS_CLASSLOAD_MI_ACCESS_FAILURE, tokImpl);
4790         }
4791
4792         // Decl's parent must not be tdSealed
4793         mdToken tkGrandParentDummyVar;
4794         DWORD dwDeclTypeAttrs;
4795         if (FAILED(hr = pIMDDecl->GetTypeDefProps(tkDeclParent, &dwDeclTypeAttrs, &tkGrandParentDummyVar)))
4796         {
4797             BuildMethodTableThrowException(hr, *bmtError);
4798         }
4799         if (IsTdSealed(dwDeclTypeAttrs))
4800         {
4801             BuildMethodTableThrowException(IDS_CLASSLOAD_MI_SEALED_DECL);
4802         }
4803     }
4804     
4805     return;
4806 }
4807
4808
4809 //*******************************************************************************
4810 //
4811 // Used by BuildMethodTable
4812 //
4813 VOID
4814 MethodTableBuilder::ValidateMethods()
4815 {
4816     CONTRACTL
4817     {
4818         STANDARD_VM_CHECK;
4819
4820         PRECONDITION(CheckPointer(this));
4821         PRECONDITION(CheckPointer(bmtInternal));
4822         PRECONDITION(CheckPointer(bmtMetaData));
4823         PRECONDITION(CheckPointer(bmtError));
4824         PRECONDITION(CheckPointer(bmtProp));
4825         PRECONDITION(CheckPointer(bmtInterface));
4826         PRECONDITION(CheckPointer(bmtParent));
4827         PRECONDITION(CheckPointer(bmtMFDescs));
4828         PRECONDITION(CheckPointer(bmtEnumFields));
4829         PRECONDITION(CheckPointer(bmtMethodImpl));
4830         PRECONDITION(CheckPointer(bmtVT));
4831     }
4832     CONTRACTL_END;
4833
4834     // Used to keep track of located default and type constructors.
4835     CONSISTENCY_CHECK(bmtVT->pCCtor == NULL);
4836     CONSISTENCY_CHECK(bmtVT->pDefaultCtor == NULL);
4837
4838     // Fetch the hard-coded signatures for the type constructor and the
4839     // default constructor and create MethodSignature objects for both at
4840     // the method level so this does not happen for every specialname
4841     // method.
4842
4843     Signature sig;
4844     
4845     sig = MscorlibBinder::GetSignature(&gsig_SM_RetVoid);
4846
4847     MethodSignature cctorSig(MscorlibBinder::GetModule(),
4848                              COR_CCTOR_METHOD_NAME,
4849                              sig.GetRawSig(), sig.GetRawSigLen());
4850
4851     sig = MscorlibBinder::GetSignature(&gsig_IM_RetVoid);
4852
4853     MethodSignature defaultCtorSig(MscorlibBinder::GetModule(),
4854                                    COR_CTOR_METHOD_NAME,
4855                                    sig.GetRawSig(), sig.GetRawSigLen());
4856
4857     Module * pModule = GetModule();
4858     DeclaredMethodIterator it(*this);
4859     while (it.Next())
4860     {
4861         // The RVA is only valid/testable if it has not been overwritten
4862         // for something like edit-and-continue
4863         // Complete validation of non-zero RVAs is done later inside MethodDesc::GetILHeader.
4864         if ((it.RVA() == 0) && (pModule->GetDynamicIL(it.Token(), FALSE) == NULL))
4865         {
4866             // for IL code that is implemented here must have a valid code RVA
4867             // this came up due to a linker bug where the ImplFlags/DescrOffset were
4868             // being set to null and we weren't coping with it
4869             if((IsMiIL(it.ImplFlags()) || IsMiOPTIL(it.ImplFlags())) &&
4870                    !IsMdAbstract(it.Attrs()) &&
4871                    !IsReallyMdPinvokeImpl(it.Attrs()) &&
4872                 !IsMiInternalCall(it.ImplFlags()))
4873             {
4874                 BuildMethodTableThrowException(IDS_CLASSLOAD_MISSINGMETHODRVA, it.Token());
4875             }
4876         }
4877
4878         if (IsMdRTSpecialName(it.Attrs()))
4879         {
4880             if (IsMdVirtual(it.Attrs()))
4881             {   // Virtual specialname methods are illegal
4882                 BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
4883             }
4884
4885             // Constructors (.ctor) and class initialisers (.cctor) are special
4886             const MethodSignature &curSig(it->GetMethodSignature());
4887
4888             if (IsMdStatic(it.Attrs()))
4889             {   // The only rtSpecialName static method allowed is the .cctor
4890                 if (!curSig.ExactlyEqual(cctorSig))
4891                 {   // Bad method
4892                     BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
4893                 }
4894
4895                 // Remember it for later
4896                 bmtVT->pCCtor = *it;
4897             }
4898             else
4899             {
4900                 if(!MethodSignature::NamesEqual(curSig, defaultCtorSig))
4901                 {   // The only rtSpecialName instance methods allowed are .ctors
4902                     BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
4903                 }
4904
4905                 // .ctor must return void
4906                 MetaSig methodMetaSig(curSig.GetSignature(),
4907                                         static_cast<DWORD>(curSig.GetSignatureLength()),
4908                                         curSig.GetModule(),
4909                                         NULL);
4910
4911                 if (methodMetaSig.GetReturnType() != ELEMENT_TYPE_VOID)
4912                 {   // All constructors must have a void return type
4913                     BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
4914                 }
4915
4916                 // See if this is a default constructor.  If so, remember it for later.
4917                 if (curSig.ExactlyEqual(defaultCtorSig))
4918                 {
4919                     bmtVT->pDefaultCtor = *it;
4920                 }
4921             }
4922         }
4923
4924         // Make sure that fcalls have a 0 rva.  This is assumed by the prejit fixup logic
4925         if (it.MethodType() == METHOD_TYPE_FCALL && it.RVA() != 0)
4926         {
4927             BuildMethodTableThrowException(BFA_ECALLS_MUST_HAVE_ZERO_RVA, it.Token());
4928         }
4929
4930         // check for proper use of the Managed and native flags
4931         if (IsMiManaged(it.ImplFlags()))
4932         {
4933             if (IsMiIL(it.ImplFlags()) || IsMiRuntime(it.ImplFlags())) // IsMiOPTIL(it.ImplFlags()) no longer supported
4934             {
4935                 // No need to set code address, pre stub used automatically.
4936             }
4937             else
4938             {
4939                 if (IsMiNative(it.ImplFlags()))
4940                 {
4941                     // For now simply disallow managed native code if you turn this on you have to at least
4942                     // insure that we have SkipVerificationPermission or equivalent
4943                     BuildMethodTableThrowException(BFA_MANAGED_NATIVE_NYI, it.Token());
4944                 }
4945                 else
4946                 {
4947                     BuildMethodTableThrowException(BFA_BAD_IMPL_FLAGS, it.Token());
4948                 }
4949             }
4950         }
4951         else
4952         {
4953             if (IsMiNative(it.ImplFlags()) && IsGlobalClass())
4954             {
4955                 // global function unmanaged entrypoint via IJW thunk was handled
4956                 // above.
4957             }
4958             else
4959             {
4960                 BuildMethodTableThrowException(IDS_CLASSLOAD_BAD_UNMANAGED_RVA, it.Token());
4961             }
4962             if (it.MethodType() != METHOD_TYPE_NDIRECT)
4963             {
4964                 BuildMethodTableThrowException(BFA_BAD_UNMANAGED_ENTRY_POINT);
4965             }
4966         }
4967
4968         // Vararg methods are not allowed inside generic classes
4969         // and nor can they be generic methods.
4970         if (bmtGenerics->GetNumGenericArgs() > 0 || (it.MethodType() == METHOD_TYPE_INSTANTIATED) )
4971         {
4972             DWORD cMemberSignature;
4973             PCCOR_SIGNATURE pMemberSignature = it.GetSig(&cMemberSignature);
4974             // We've been trying to avoid asking for the signature - now we need it
4975             if (pMemberSignature == NULL)
4976             {
4977                 pMemberSignature = it.GetSig(&cMemberSignature);
4978             }
4979
4980             if (MetaSig::IsVarArg(pModule, Signature(pMemberSignature, cMemberSignature)))
4981             {
4982                 BuildMethodTableThrowException(BFA_GENCODE_NOT_BE_VARARG);
4983             }
4984         }
4985
4986         if (IsMdVirtual(it.Attrs()) && IsMdPublic(it.Attrs()) && it.Name() == NULL)
4987         {
4988             BuildMethodTableThrowException(IDS_CLASSLOAD_NOMETHOD_NAME);
4989         }
4990
4991         if (it.IsMethodImpl())
4992         {
4993             if (!IsMdVirtual(it.Attrs()))
4994             {   // Non-virtual methods cannot participate in a methodImpl pair.
4995                 BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MUSTBEVIRTUAL, it.Token());
4996             }
4997         }
4998
4999         // Virtual static methods are not allowed.
5000         if (IsMdStatic(it.Attrs()) && IsMdVirtual(it.Attrs()))
5001         {
5002             BuildMethodTableThrowException(IDS_CLASSLOAD_STATICVIRTUAL, it.Token());
5003         }
5004     }
5005 }
5006
5007 //*******************************************************************************
5008 // Essentially, this is a helper method that combines calls to InitMethodDesc and 
5009 // SetSecurityFlagsOnMethod. It then assigns the newly initialized MethodDesc to 
5010 // the bmtMDMethod.
5011 VOID
5012 MethodTableBuilder::InitNewMethodDesc(
5013     bmtMDMethod * pMethod,
5014     MethodDesc * pNewMD)
5015 {
5016     STANDARD_VM_CONTRACT;
5017
5018     //
5019     // First, set all flags that control layout of optional slots
5020     //
5021     pNewMD->SetClassification(GetMethodClassification(pMethod->GetMethodType()));
5022
5023     if (pMethod->GetMethodImplType() == METHOD_IMPL)
5024         pNewMD->SetHasMethodImplSlot();
5025
5026     if (pMethod->GetSlotIndex() >= bmtVT->cVtableSlots)
5027         pNewMD->SetHasNonVtableSlot();
5028
5029     if (NeedsNativeCodeSlot(pMethod))
5030         pNewMD->SetHasNativeCodeSlot();
5031
5032     // Now we know the classification we can allocate the correct type of
5033     // method desc and perform any classification specific initialization.
5034
5035     LPCSTR pName = pMethod->GetMethodSignature().GetName();
5036     if (pName == NULL)
5037     {
5038         if (FAILED(GetMDImport()->GetNameOfMethodDef(pMethod->GetMethodSignature().GetToken(), &pName)))
5039         {
5040             BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
5041         }
5042     }
5043     
5044 #ifdef _DEBUG 
5045     LPCUTF8 pszDebugMethodName;
5046     if (FAILED(GetMDImport()->GetNameOfMethodDef(pMethod->GetMethodSignature().GetToken(), &pszDebugMethodName)))
5047     {
5048         pszDebugMethodName = "Invalid MethodDef record";
5049     }
5050     S_SIZE_T safeLen = S_SIZE_T(strlen(pszDebugMethodName)) + S_SIZE_T(1);
5051     if(safeLen.IsOverflow())
5052         COMPlusThrowHR(COR_E_OVERFLOW);
5053
5054     size_t len = safeLen.Value();
5055     LPCUTF8 pszDebugMethodNameCopy = (char*) AllocateFromLowFrequencyHeap(safeLen);
5056     strcpy_s((char *) pszDebugMethodNameCopy, len, pszDebugMethodName);
5057 #endif // _DEBUG
5058
5059     // Do the init specific to each classification of MethodDesc & assign some common fields
5060     InitMethodDesc(pNewMD,
5061                    GetMethodClassification(pMethod->GetMethodType()),
5062                    pMethod->GetMethodSignature().GetToken(),
5063                    pMethod->GetImplAttrs(),
5064                    pMethod->GetDeclAttrs(),
5065                    FALSE,
5066                    pMethod->GetRVA(),
5067                    GetMDImport(),
5068                    pName
5069                    COMMA_INDEBUG(pszDebugMethodNameCopy)
5070                    COMMA_INDEBUG(GetDebugClassName())
5071                    COMMA_INDEBUG("") // FIX this happens on global methods, give better info
5072                   );
5073
5074     pMethod->SetMethodDesc(pNewMD);
5075
5076     bmtRTMethod * pParentMethod = NULL;
5077
5078     if (HasParent())
5079     {
5080         SLOT_INDEX idx = pMethod->GetSlotIndex();
5081         CONSISTENCY_CHECK(idx != INVALID_SLOT_INDEX);
5082
5083         if (idx < GetParentMethodTable()->GetNumVirtuals())
5084         {
5085             pParentMethod = (*bmtParent->pSlotTable)[idx].Decl().AsRTMethod();
5086         }
5087     }
5088
5089     // Turn off inlining for any calls
5090     // that are marked in the metadata as not being inlineable.
5091     if(IsMiNoInlining(pMethod->GetImplAttrs()))
5092     {
5093         pNewMD->SetNotInline(true);
5094     }
5095
5096     // Check for methods marked as [Intrinsic]
5097     if (GetModule()->IsSystem() || GetAssembly()->IsSIMDVectorAssembly())
5098     {
5099         HRESULT hr = GetMDImport()->GetCustomAttributeByName(pMethod->GetMethodSignature().GetToken(),
5100             g_CompilerServicesIntrinsicAttribute,
5101             NULL,
5102             NULL);
5103
5104         if (hr == S_OK || bmtProp->fIsHardwareIntrinsic)
5105         {
5106             pNewMD->SetIsJitIntrinsic();
5107         }
5108
5109     }
5110
5111     pNewMD->SetSlot(pMethod->GetSlotIndex());
5112 }
5113
5114 //*******************************************************************************
5115 // Determine vtable placement for each non-virtual in the class, while also
5116 // looking for default and type constructors.
5117 VOID
5118 MethodTableBuilder::PlaceNonVirtualMethods()
5119 {
5120     CONTRACTL
5121     {
5122         STANDARD_VM_CHECK;
5123
5124         PRECONDITION(CheckPointer(this));
5125         PRECONDITION(CheckPointer(bmtInternal));
5126         PRECONDITION(CheckPointer(bmtMetaData));
5127         PRECONDITION(CheckPointer(bmtError));
5128         PRECONDITION(CheckPointer(bmtProp));
5129         PRECONDITION(CheckPointer(bmtInterface));
5130         PRECONDITION(CheckPointer(bmtParent));
5131         PRECONDITION(CheckPointer(bmtMFDescs));
5132         PRECONDITION(CheckPointer(bmtEnumFields));
5133         PRECONDITION(CheckPointer(bmtMethodImpl));
5134         PRECONDITION(CheckPointer(bmtVT));
5135     }
5136     CONTRACTL_END;
5137
5138     INDEBUG(bmtVT->SealVirtualSlotSection();)
5139
5140     //
5141     // For each non-virtual method, place the method in the next available non-virtual method slot.
5142     //
5143
5144     // Place the cctor and default ctor first. code::MethodTableGetCCtorSlot and code:MethodTable::GetDefaultCtorSlot 
5145     // depends on this.
5146     if (bmtVT->pCCtor != NULL)
5147     {
5148         if (!bmtVT->AddNonVirtualMethod(bmtVT->pCCtor))
5149             BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
5150     }
5151
5152     if (bmtVT->pDefaultCtor != NULL)
5153     {
5154         if (!bmtVT->AddNonVirtualMethod(bmtVT->pDefaultCtor))
5155             BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
5156     }
5157
5158     // We use slot during remoting and to map methods between generic instantiations
5159     // (see MethodTable::GetParallelMethodDesc). The current implementation
5160     // of this mechanism requires real slots.
5161     BOOL fCanHaveNonVtableSlots = (bmtGenerics->GetNumGenericArgs() == 0) && !IsInterface();
5162
5163     // Flag to avoid second pass when possible
5164     BOOL fHasNonVtableSlots = FALSE;
5165
5166     //
5167     // Place all methods that require real vtable slot first. This is necessary so
5168     // that they get consequitive slot numbers right after virtual slots.
5169     //
5170
5171     DeclaredMethodIterator it(*this);
5172     while (it.Next())
5173     {
5174         // Skip methods that are placed already
5175         if (it->GetSlotIndex() != INVALID_SLOT_INDEX)
5176             continue;
5177
5178 #ifdef _DEBUG 
5179         if(GetHalfBakedClass()->m_fDebuggingClass && g_pConfig->ShouldBreakOnMethod(it.Name()))
5180             CONSISTENCY_CHECK_MSGF(false, ("BreakOnMethodName: '%s' ", it.Name()));
5181 #endif // _DEBUG
5182
5183         if (!fCanHaveNonVtableSlots ||
5184             it->GetMethodType() == METHOD_TYPE_INSTANTIATED)
5185         {
5186             // We use slot during remoting and to map methods between generic instantiations
5187             // (see MethodTable::GetParallelMethodDesc). The current implementation
5188             // of this mechanism requires real slots.
5189         }
5190         else
5191         {
5192             // This method does not need real vtable slot
5193             fHasNonVtableSlots = TRUE;
5194             continue;
5195         }
5196
5197         // This will update slot index in bmtMDMethod
5198         if (!bmtVT->AddNonVirtualMethod(*it))
5199             BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
5200     }
5201
5202     // Remeber last real vtable slot
5203     bmtVT->cVtableSlots = bmtVT->cTotalSlots;
5204
5205     // Are there any Non-vtable slots to place?
5206     if (!fHasNonVtableSlots)
5207         return;
5208
5209     //
5210     // Now, place the remaining methods. They will get non-vtable slot.
5211     //
5212
5213     DeclaredMethodIterator it2(*this);
5214     while (it2.Next())
5215     {
5216         // Skip methods that are placed already
5217         if (it2->GetSlotIndex() != INVALID_SLOT_INDEX)
5218             continue;
5219
5220         if (!bmtVT->AddNonVirtualMethod(*it2))
5221             BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
5222     }
5223
5224 }
5225
5226 //*******************************************************************************
5227 // Determine vtable placement for each virtual member in this class.
5228 VOID
5229 MethodTableBuilder::PlaceVirtualMethods()
5230 {
5231     CONTRACTL
5232     {
5233         STANDARD_VM_CHECK;
5234
5235         PRECONDITION(CheckPointer(this));
5236         PRECONDITION(CheckPointer(bmtInternal));
5237         PRECONDITION(CheckPointer(bmtMetaData));
5238         PRECONDITION(CheckPointer(bmtError));
5239         PRECONDITION(CheckPointer(bmtProp));
5240         PRECONDITION(CheckPointer(bmtInterface));
5241         PRECONDITION(CheckPointer(bmtParent));
5242         PRECONDITION(CheckPointer(bmtMFDescs));
5243         PRECONDITION(CheckPointer(bmtEnumFields));
5244         PRECONDITION(CheckPointer(bmtMethodImpl));
5245         PRECONDITION(CheckPointer(bmtVT));
5246     }
5247     CONTRACTL_END;
5248
5249 #ifdef _DEBUG 
5250     LPCUTF8 pszDebugName, pszDebugNamespace;
5251     if (FAILED(GetMDImport()->GetNameOfTypeDef(GetCl(), &pszDebugName, &pszDebugNamespace)))
5252     {
5253         pszDebugName = pszDebugNamespace = "Invalid TypeDef record";
5254     }
5255 #endif // _DEBUG
5256
5257     //
5258     // For each virtual method
5259     //  - If the method is not declared as newslot, search all virtual methods in the parent
5260     //    type for an override candidate.
5261     //      - If such a candidate is found, test to see if the override is valid. If
5262     //        the override is not valid, throw TypeLoadException
5263     //  - If a candidate is found above, place the method in the inherited slot as both
5264     //    the Decl and the Impl.
5265     //  - Else, place the method in the next available empty vtable slot.
5266     //
5267
5268     DeclaredMethodIterator it(*this);
5269     while (it.Next())
5270     {
5271         if (!IsMdVirtual(it.Attrs()))
5272         {   // Only processing declared virtual methods
5273             continue;
5274         }
5275
5276 #ifdef _DEBUG 
5277         if(GetHalfBakedClass()->m_fDebuggingClass && g_pConfig->ShouldBreakOnMethod(it.Name()))
5278             CONSISTENCY_CHECK_MSGF(false, ("BreakOnMethodName: '%s' ", it.Name()));
5279 #endif // _DEBUG
5280
5281         // If this member is a method which overrides a parent method, it will be set to non-NULL
5282         bmtRTMethod * pParentMethod = NULL;
5283
5284         // Hash that a method with this name exists in this class
5285         // Note that ctors and static ctors are not added to the table
5286         BOOL fMethodConstraintsMatch = FALSE;
5287
5288         // If the member is marked with a new slot we do not need to find it in the parent
5289         if (HasParent() && !IsMdNewSlot(it.Attrs()))
5290         {
5291             // Attempt to find the method with this name and signature in the parent class.
5292             // This method may or may not create pParentMethodHash (if it does not already exist).
5293             // It also may or may not fill in pMemberSignature/cMemberSignature.
5294             // An error is only returned when we can not create the hash.
5295             // NOTE: This operation touches metadata
5296             pParentMethod = LoaderFindMethodInParentClass(
5297                 it->GetMethodSignature(), bmtProp->fNoSanityChecks ? NULL : &fMethodConstraintsMatch);
5298
5299             if (pParentMethod != NULL)
5300             {   // Found an override candidate
5301                 DWORD dwParentAttrs = pParentMethod->GetDeclAttrs();
5302
5303                 if (!IsMdVirtual(dwParentAttrs))
5304                 {   // Can't override a non-virtual methods
5305                     BuildMethodTableThrowException(BFA_NONVIRT_NO_SEARCH, it.Token());
5306                 }
5307
5308                 if(IsMdFinal(dwParentAttrs))
5309                 {   // Can't override a final methods
5310                     BuildMethodTableThrowException(IDS_CLASSLOAD_MI_FINAL_DECL, it.Token());
5311                 }
5312
5313                 if(!bmtProp->fNoSanityChecks)
5314                 {
5315                     TestOverRide(bmtMethodHandle(pParentMethod),
5316                                  bmtMethodHandle(*it));
5317
5318                     if (!fMethodConstraintsMatch)
5319                     {
5320                         BuildMethodTableThrowException(
5321                                 IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_IMPLICIT_OVERRIDE,
5322                                 it.Token());
5323                     }
5324                 }
5325             }
5326         }
5327
5328         // vtable method
5329         if (IsInterface())
5330         {
5331             CONSISTENCY_CHECK(pParentMethod == NULL);
5332             // Also sets new slot number on bmtRTMethod and MethodDesc
5333             if (!bmtVT->AddVirtualMethod(*it))
5334                 BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
5335         }
5336         else if (pParentMethod != NULL)
5337         {
5338             bmtVT->SetVirtualMethodOverride(pParentMethod->GetSlotIndex(), *it);
5339         }
5340         else
5341         {
5342             if (!bmtVT->AddVirtualMethod(*it))
5343                 BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
5344         }
5345     }
5346 }
5347
5348 // Given an interface map entry, and a name+signature, compute the method on the interface
5349 // that the name+signature corresponds to. Used by ProcessMethodImpls and ProcessInexactMethodImpls
5350 // Always returns the first match that it finds. Affects the ambiguities in code:#ProcessInexactMethodImpls_Ambiguities
5351 MethodTableBuilder::bmtMethodHandle 
5352 MethodTableBuilder::FindDeclMethodOnInterfaceEntry(bmtInterfaceEntry *pItfEntry, MethodSignature &declSig)
5353 {
5354     STANDARD_VM_CONTRACT;
5355
5356     bmtMethodHandle declMethod;
5357
5358     bmtInterfaceEntry::InterfaceSlotIterator slotIt =
5359         pItfEntry->IterateInterfaceSlots(GetStackingAllocator());
5360     // Check for exact match
5361     for (; !slotIt.AtEnd(); slotIt.Next())
5362     {
5363         bmtRTMethod * pCurDeclMethod = slotIt->Decl().AsRTMethod();
5364
5365         if (declSig.ExactlyEqual(pCurDeclMethod->GetMethodSignature()))
5366         {
5367             declMethod = slotIt->Decl();
5368             break;
5369         }
5370     }
5371     slotIt.ResetToStart();
5372
5373     // Check for equivalent match if exact match wasn't found
5374     if (declMethod.IsNull())
5375     {
5376         for (; !slotIt.AtEnd(); slotIt.Next())
5377         {
5378             bmtRTMethod * pCurDeclMethod = slotIt->Decl().AsRTMethod();
5379
5380             // Type Equivalence is forbidden in MethodImpl MemberRefs
5381             if (declSig.Equivalent(pCurDeclMethod->GetMethodSignature()))
5382             {
5383                 declMethod = slotIt->Decl();
5384                 break;
5385             }
5386         }
5387     }
5388
5389     return declMethod;
5390 }
5391
5392 //*******************************************************************************
5393 //
5394 // Used by BuildMethodTable
5395 // Process the list of inexact method impls generated during ProcessMethodImpls.
5396 // This list is used to cause a methodImpl to an interface to override
5397 // methods on several equivalent interfaces in the interface map. This logic is necessary
5398 // so that in the presence of an embedded interface the behavior appears to mimic
5399 // the behavior if the interface was not embedded.
5400 //
5401 // In particular, the logic here is to handle cases such as
5402 //
5403 //  Assembly A
5404 // [TypeIdentifier("x","y")]
5405 // interface I'
5406 // {  void Method(); }
5407 // interface IOther : I' {}
5408 //
5409 //  Assembly B
5410 // [TypeIdentifier("x","y")]
5411 // interface I
5412 // {  void Method(); }
5413 // class Test : I, IOther
5414 // {
5415 //     void I.Method()
5416 //     {}
5417 // }
5418 // 
5419 // In this case, there is one method, and one methodimpl, but there are 2 interfaces on the class that both
5420 // require an implementation of their method. The correct semantic for type equivalence, is that any
5421 // methodimpl directly targeting a method on an interface must be respected, and if it also applies to a type
5422 // equivalent interface method, then if that method was not methodimpl'd directly, then the methodimpl should apply
5423 // there as well. The ProcessInexactMethodImpls function does this secondary MethodImpl mapping.
5424 //
5425 //#ProcessInexactMethodImpls_Ambiguities
5426 // In the presence of ambiguities, such as there are 3 equivalent interfaces implemented on a class and 2 methodimpls,
5427 // we will apply the 2 method impls exactly to appropriate interface methods, and arbitrarily pick one to apply to the
5428 // other interface. This is clearly ambiguous, but tricky to detect in the type loader efficiently, and should hopefully
5429 // not cause too many problems.
5430 //
5431 VOID
5432 MethodTableBuilder::ProcessInexactMethodImpls()
5433 {
5434     STANDARD_VM_CONTRACT;
5435
5436     if (bmtMethod->dwNumberInexactMethodImplCandidates == 0)
5437         return;
5438
5439     DeclaredMethodIterator it(*this);
5440     while (it.Next())
5441     {
5442         // Non-virtual methods cannot be classified as methodImpl - we should have thrown an
5443         // error before reaching this point.
5444         CONSISTENCY_CHECK(!(!IsMdVirtual(it.Attrs()) && it.IsMethodImpl()));
5445
5446         if (!IsMdVirtual(it.Attrs()))
5447         {   // Only virtual methods can participate in methodImpls
5448             continue;
5449         }
5450
5451         if(!it.IsMethodImpl())
5452         {
5453             // Skip methods which are not the bodies of MethodImpl specifications
5454             continue;
5455         }
5456
5457         // If this method serves as the BODY of a MethodImpl specification, then
5458         // we should iterate all the MethodImpl's for this class and see just how many
5459         // of them this method participates in as the BODY.
5460         for(DWORD m = 0; m < bmtMethod->dwNumberMethodImpls; m++)
5461         {
5462             // Inexact matching logic only works on MethodImpls that have been opted into inexactness by ProcessMethodImpls.
5463             if (!bmtMetaData->rgMethodImplTokens[m].fConsiderDuringInexactMethodImplProcessing)
5464             {
5465                 continue;
5466             }
5467
5468             // If the methodimpl we are working with does not match this method, continue to next methodimpl
5469             if(it.Token() != bmtMetaData->rgMethodImplTokens[m].methodBody)
5470             {
5471                 continue;
5472             }
5473
5474             bool fMatchFound = false;
5475
5476             LPCUTF8 szName = NULL;
5477             PCCOR_SIGNATURE pSig = NULL;
5478             ULONG cbSig;
5479
5480             mdToken mdDecl = bmtMetaData->rgMethodImplTokens[m].methodDecl;
5481             
5482             if (TypeFromToken(mdDecl) == mdtMethodDef)
5483             {   // Different methods are aused to access MethodDef and MemberRef
5484                 // names and signatures.
5485                 if (FAILED(GetMDImport()->GetNameOfMethodDef(mdDecl, &szName)) || 
5486                     FAILED(GetMDImport()->GetSigOfMethodDef(mdDecl, &cbSig, &pSig)))
5487                 {
5488                     BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
5489                 }
5490             }
5491             else
5492             {
5493                 if (FAILED(GetMDImport()->GetNameAndSigOfMemberRef(mdDecl, &pSig, &cbSig, &szName)))
5494                 {
5495                     BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
5496                 }
5497             }
5498
5499             Substitution *pDeclSubst = &bmtMetaData->pMethodDeclSubsts[m];
5500             MethodSignature declSig(GetModule(), szName, pSig, cbSig, pDeclSubst);
5501             bmtInterfaceEntry * pItfEntry = NULL;
5502
5503             for (DWORD i = 0; i < bmtInterface->dwInterfaceMapSize; i++)
5504             {
5505                 if (bmtInterface->pInterfaceMap[i].GetInterfaceEquivalenceSet() != bmtMetaData->rgMethodImplTokens[m].interfaceEquivalenceSet)
5506                     continue;
5507
5508                 bmtMethodHandle declMethod;
5509                 pItfEntry = &bmtInterface->pInterfaceMap[i];
5510
5511                 // Search for declmethod on this interface
5512                 declMethod = FindDeclMethodOnInterfaceEntry(pItfEntry, declSig);
5513
5514                 // If we didn't find a match, continue on to next interface in the equivalence set
5515                 if (declMethod.IsNull())
5516                     continue;
5517
5518                 if (!IsMdVirtual(declMethod.GetDeclAttrs()))
5519                 {   // Make sure the decl is virtual
5520                     BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MUSTBEVIRTUAL, it.Token());
5521                 }
5522
5523                 fMatchFound = true;
5524
5525                 bool fPreexistingImplFound = false;
5526
5527                 // Check to ensure there isn't already a matching declMethod in the method impl list
5528                 for (DWORD iMethodImpl = 0; iMethodImpl < bmtMethodImpl->pIndex; iMethodImpl++)
5529                 {
5530                     if (bmtMethodImpl->GetDeclarationMethod(iMethodImpl) == declMethod)
5531                     {
5532                         fPreexistingImplFound = true;
5533                         break;
5534                     }
5535                 }
5536
5537                 // Search for other matches
5538                 if (fPreexistingImplFound)
5539                     continue;
5540
5541                 // Otherwise, record the method impl discovery if the match is 
5542                 bmtMethodImpl->AddMethodImpl(*it, declMethod, bmtMetaData->rgMethodImplTokens[m].methodDecl, GetStackingAllocator());
5543             }
5544
5545             if (!fMatchFound && bmtMetaData->rgMethodImplTokens[m].fThrowIfUnmatchedDuringInexactMethodImplProcessing)
5546             {
5547                 BuildMethodTableThrowException(IDS_CLASSLOAD_MI_DECLARATIONNOTFOUND, it.Token());
5548             }
5549         }
5550     }
5551 }
5552
5553 //*******************************************************************************
5554 //
5555 // Used by BuildMethodTable
5556 //
5557 VOID
5558 MethodTableBuilder::ProcessMethodImpls()
5559 {
5560     STANDARD_VM_CONTRACT;
5561
5562     if (bmtMethod->dwNumberMethodImpls == 0)
5563         return;
5564
5565     HRESULT hr = S_OK;
5566
5567     DeclaredMethodIterator it(*this);
5568     while (it.Next())
5569     {
5570         // Non-virtual methods cannot be classified as methodImpl - we should have thrown an
5571         // error before reaching this point.
5572         CONSISTENCY_CHECK(!(!IsMdVirtual(it.Attrs()) && it.IsMethodImpl()));
5573
5574         if (!IsMdVirtual(it.Attrs()))
5575         {   // Only virtual methods can participate in methodImpls
5576             continue;
5577         }
5578
5579         // If this method serves as the BODY of a MethodImpl specification, then
5580         // we should iterate all the MethodImpl's for this class and see just how many
5581         // of them this method participates in as the BODY.
5582         if(it.IsMethodImpl())
5583         {
5584             for(DWORD m = 0; m < bmtMethod->dwNumberMethodImpls; m++)
5585             {
5586                 if(it.Token() == bmtMetaData->rgMethodImplTokens[m].methodBody)
5587                 {
5588                     mdToken mdDecl = bmtMetaData->rgMethodImplTokens[m].methodDecl;
5589                     bmtMethodHandle declMethod;
5590
5591                     // Get the parent token for the decl method token
5592                     mdToken tkParent = mdTypeDefNil;
5593                     if (TypeFromToken(mdDecl) == mdtMethodDef || TypeFromToken(mdDecl) == mdtMemberRef)
5594                     {
5595                         if (FAILED(hr = GetMDImport()->GetParentToken(mdDecl,&tkParent)))
5596                         {
5597                             BuildMethodTableThrowException(hr, *bmtError);
5598                         }
5599                     }
5600
5601                     if (GetCl() == tkParent)
5602                     {   // The DECL has been declared within the class that we're currently building.
5603                         hr = S_OK;
5604
5605                         if(bmtError->pThrowable != NULL)
5606                         {
5607                             *(bmtError->pThrowable) = NULL;
5608                         }
5609
5610                         if(TypeFromToken(mdDecl) != mdtMethodDef)
5611                         {
5612                             if (FAILED(hr = FindMethodDeclarationForMethodImpl(
5613                                                 mdDecl, &mdDecl, TRUE)))
5614                             {
5615                                 BuildMethodTableThrowException(hr, *bmtError);
5616                             }
5617                         }
5618
5619                         CONSISTENCY_CHECK(TypeFromToken(mdDecl) == mdtMethodDef);
5620                         declMethod = bmtMethod->FindDeclaredMethodByToken(mdDecl);
5621                     }
5622                     else
5623                     {   // We can't call GetDescFromMemberDefOrRef here because this
5624                         // method depends on a fully-loaded type, including parent types,
5625                         // which is not always guaranteed. In particular, it requires that
5626                         // the instantiation dictionary be filled. The solution is the following:
5627                         //   1. Load the approximate type that the method belongs to.
5628                         //   2. Get or create the correct substitution for the type involved
5629                         //   3. Iterate the introduced methods on that type looking for a matching
5630                         //      method.
5631
5632                         LPCUTF8 szName = NULL;
5633                         PCCOR_SIGNATURE pSig = NULL;
5634                         ULONG cbSig;
5635                         if (TypeFromToken(mdDecl) == mdtMethodDef)
5636                         {   // Different methods are aused to access MethodDef and MemberRef
5637                             // names and signatures.
5638                             if (FAILED(GetMDImport()->GetNameOfMethodDef(mdDecl, &szName)) || 
5639                                 FAILED(GetMDImport()->GetSigOfMethodDef(mdDecl, &cbSig, &pSig)))
5640                             {
5641                                 BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
5642                             }
5643                         }
5644                         else
5645                         {
5646                             if (FAILED(GetMDImport()->GetNameAndSigOfMemberRef(mdDecl, &pSig, &cbSig, &szName)))
5647                             {
5648                                 BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
5649                             }
5650                         }
5651                         
5652                         Substitution *pDeclSubst = &bmtMetaData->pMethodDeclSubsts[m];
5653                         MethodTable * pDeclMT = NULL;
5654                         MethodSignature declSig(GetModule(), szName, pSig, cbSig, pDeclSubst);
5655
5656                         {   // 1. Load the approximate type.
5657                             // Block for the LoadsTypeViolation.
5658                             CONTRACT_VIOLATION(LoadsTypeViolation);
5659                             pDeclMT = ClassLoader::LoadTypeDefOrRefOrSpecThrowing(
5660                                 GetModule(),
5661                                 tkParent,
5662                                 &bmtGenerics->typeContext,
5663                                 ClassLoader::ThrowIfNotFound,
5664                                 ClassLoader::PermitUninstDefOrRef,
5665                                 ClassLoader::LoadTypes,
5666                                 CLASS_LOAD_APPROXPARENTS,
5667                                 TRUE).GetMethodTable()->GetCanonicalMethodTable();
5668                         }
5669
5670                         {   // 2. Get or create the correct substitution
5671                             bmtRTType * pDeclType = NULL;
5672
5673                             if (pDeclMT->IsInterface())
5674                             {   // If the declaration method is a part of an interface, search through
5675                                 // the interface map to find the matching interface so we can provide
5676                                 // the correct substitution chain.
5677                                 pDeclType = NULL;
5678
5679                                 bmtInterfaceEntry * pItfEntry = NULL;
5680                                 for (DWORD i = 0; i < bmtInterface->dwInterfaceMapSize; i++)
5681                                 {
5682                                     bmtRTType * pCurItf = bmtInterface->pInterfaceMap[i].GetInterfaceType();
5683                                     // Type Equivalence is not respected for this comparision as you can have multiple type equivalent interfaces on a class
5684                                     TokenPairList newVisited = TokenPairList::AdjustForTypeEquivalenceForbiddenScope(NULL);
5685                                     if (MetaSig::CompareTypeDefsUnderSubstitutions(
5686                                         pCurItf->GetMethodTable(),      pDeclMT,
5687                                         &pCurItf->GetSubstitution(),    pDeclSubst,
5688                                         &newVisited))
5689                                     {
5690                                         pItfEntry = &bmtInterface->pInterfaceMap[i];
5691                                         pDeclType = pCurItf;
5692                                         break;
5693                                     }
5694                                 }
5695
5696                                 if (IsInterface())
5697                                 {
5698                                     if (pDeclType == NULL)
5699                                     {
5700                                         // Interface is not implemented by this type.
5701                                         BuildMethodTableThrowException(IDS_CLASSLOAD_MI_NOTIMPLEMENTED, it.Token());
5702                                     }
5703                                 }
5704                                 else
5705                                 {
5706                                     if (pDeclType == NULL)
5707                                     {
5708                                         DWORD equivalenceSet = 0;
5709
5710                                         for (DWORD i = 0; i < bmtInterface->dwInterfaceMapSize; i++)
5711                                         {
5712                                             bmtRTType * pCurItf = bmtInterface->pInterfaceMap[i].GetInterfaceType();
5713                                             // Type Equivalence is respected for this comparision as we just need to find an 
5714                                             // equivalent interface, the particular interface is unimportant
5715                                             if (MetaSig::CompareTypeDefsUnderSubstitutions(
5716                                                 pCurItf->GetMethodTable(), pDeclMT,
5717                                                 &pCurItf->GetSubstitution(), pDeclSubst,
5718                                                 NULL))
5719                                             {
5720                                                 equivalenceSet = bmtInterface->pInterfaceMap[i].GetInterfaceEquivalenceSet();
5721                                                 pItfEntry = &bmtInterface->pInterfaceMap[i];
5722                                                 break;
5723                                             }
5724                                         }
5725
5726                                         if (equivalenceSet == 0)
5727                                         {
5728                                             // Interface is not implemented by this type.
5729                                             BuildMethodTableThrowException(IDS_CLASSLOAD_MI_NOTIMPLEMENTED, it.Token());
5730                                         }
5731
5732                                         // Interface is not implemented by this type exactly. We need to consider this MethodImpl on non exact interface matches,
5733                                         // as the only match may be one of the non-exact matches
5734                                         bmtMetaData->rgMethodImplTokens[m].fConsiderDuringInexactMethodImplProcessing = true;
5735                                         bmtMetaData->rgMethodImplTokens[m].fThrowIfUnmatchedDuringInexactMethodImplProcessing = true;
5736                                         bmtMetaData->rgMethodImplTokens[m].interfaceEquivalenceSet = equivalenceSet;
5737                                         bmtMethod->dwNumberInexactMethodImplCandidates++;
5738                                         continue; // Move on to other MethodImpls
5739                                     }
5740                                     else
5741                                     {
5742                                         // This method impl may need to match other methods during inexact processing
5743                                         if (pItfEntry->InEquivalenceSetWithMultipleEntries())
5744                                         {
5745                                             bmtMetaData->rgMethodImplTokens[m].fConsiderDuringInexactMethodImplProcessing = true;
5746                                             bmtMetaData->rgMethodImplTokens[m].fThrowIfUnmatchedDuringInexactMethodImplProcessing = false;
5747                                             bmtMetaData->rgMethodImplTokens[m].interfaceEquivalenceSet = pItfEntry->GetInterfaceEquivalenceSet();
5748                                             bmtMethod->dwNumberInexactMethodImplCandidates++;
5749                                         }
5750                                     }
5751                                 }
5752
5753                                 // 3. Find the matching method.
5754                                 declMethod = FindDeclMethodOnInterfaceEntry(pItfEntry, declSig);
5755                             }
5756                             else
5757                             {   // Assume the MethodTable is a parent of the current type,
5758                                 // and create the substitution chain to match it.
5759
5760                                 pDeclType = NULL;
5761
5762                                 for (bmtRTType *pCur = GetParentType();
5763                                      pCur != NULL;
5764                                      pCur = pCur->GetParentType())
5765                                 {
5766                                     if (pCur->GetMethodTable() == pDeclMT)
5767                                     {
5768                                         pDeclType = pCur;
5769                                         break;
5770                                     }
5771                                 }
5772
5773                                 if (pDeclType == NULL)
5774                                 {   // Method's type is not a parent.
5775                                     BuildMethodTableThrowException(IDS_CLASSLOAD_MI_DECLARATIONNOTFOUND, it.Token());
5776                                 }
5777
5778                                 // 3. Find the matching method.
5779                                 bmtRTType *pCurDeclType = pDeclType;
5780                                 do
5781                                 {
5782                                     // two pass algorithm. search for exact matches followed
5783                                     // by equivalent matches.
5784                                     for (int iPass = 0; (iPass < 2) && (declMethod.IsNull()); iPass++)
5785                                     {
5786                                         MethodTable *pCurDeclMT = pCurDeclType->GetMethodTable();
5787     
5788                                         MethodTable::IntroducedMethodIterator methIt(pCurDeclMT);
5789                                         for(; methIt.IsValid(); methIt.Next())
5790                                         {
5791                                             MethodDesc * pCurMD = methIt.GetMethodDesc();
5792     
5793                                             if (pCurDeclMT != pDeclMT)
5794                                             {
5795                                                 // If the method isn't on the declaring type, then it must be virtual.
5796                                                 if (!pCurMD->IsVirtual())
5797                                                     continue;
5798                                             }
5799                                             if (strcmp(szName, pCurMD->GetName()) == 0)
5800                                             {
5801                                                 PCCOR_SIGNATURE pCurMDSig;
5802                                                 DWORD cbCurMDSig;
5803                                                 pCurMD->GetSig(&pCurMDSig, &cbCurMDSig);
5804
5805                                                 // First pass searches for declaration methods should not use type equivalence
5806                                                 TokenPairList newVisited = TokenPairList::AdjustForTypeEquivalenceForbiddenScope(NULL);
5807
5808                                                 if (MetaSig::CompareMethodSigs(
5809                                                     declSig.GetSignature(),
5810                                                     static_cast<DWORD>(declSig.GetSignatureLength()),
5811                                                     declSig.GetModule(),
5812                                                     &declSig.GetSubstitution(),
5813                                                     pCurMDSig,
5814                                                     cbCurMDSig,
5815                                                     pCurMD->GetModule(),
5816                                                     &pCurDeclType->GetSubstitution(),
5817                                                     iPass == 0 ? &newVisited : NULL))
5818                                                 {
5819                                                     declMethod = (*bmtParent->pSlotTable)[pCurMD->GetSlot()].Decl();
5820                                                     break;
5821                                                 }
5822                                             }
5823                                         }
5824                                     }
5825
5826                                     pCurDeclType = pCurDeclType->GetParentType();
5827                                 } while ((pCurDeclType != NULL) && (declMethod.IsNull()));
5828                             }
5829
5830                             if (declMethod.IsNull())
5831                             {   // Would prefer to let this fall out to the BuildMethodTableThrowException
5832                                 // below, but due to v2.0 and earlier behaviour throwing a MissingMethodException,
5833                                 // primarily because this code used to be a simple call to
5834                                 // MemberLoader::GetDescFromMemberDefOrRef (see above for reason why),
5835                                 // we must continue to do the same.
5836                                 MemberLoader::ThrowMissingMethodException(
5837                                     pDeclMT,
5838                                     declSig.GetName(),
5839                                     declSig.GetModule(),
5840                                     declSig.GetSignature(),
5841                                     static_cast<DWORD>(declSig.GetSignatureLength()),
5842                                     &bmtGenerics->typeContext);
5843                             }
5844                         }
5845                     }
5846
5847                     if (declMethod.IsNull())
5848                     {   // Method not found, throw.
5849                         BuildMethodTableThrowException(IDS_CLASSLOAD_MI_DECLARATIONNOTFOUND, it.Token());
5850                     }
5851                     
5852                     if (!IsMdVirtual(declMethod.GetDeclAttrs()))
5853                     {   // Make sure the decl is virtual
5854                         BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MUSTBEVIRTUAL, it.Token());
5855                     }
5856
5857                     bmtMethodImpl->AddMethodImpl(*it, declMethod, mdDecl, GetStackingAllocator());
5858                 }
5859             }
5860         }
5861     } /* end ... for each member */
5862 }
5863
5864 //*******************************************************************************
5865 // InitMethodDesc takes a pointer to space that's already allocated for the
5866 // particular type of MethodDesc, and initializes based on the other info.
5867 // This factors logic between PlaceMembers (the regular code path) & AddMethod
5868 // (Edit & Continue (EnC) code path) so we don't have to maintain separate copies.
5869 VOID 
5870 MethodTableBuilder::InitMethodDesc(
5871     MethodDesc *        pNewMD, // This is should actually be of the correct sub-type, based on Classification
5872     DWORD               Classification,
5873     mdToken             tok,
5874     DWORD               dwImplFlags,
5875     DWORD               dwMemberAttrs,
5876     BOOL                fEnC,
5877     DWORD               RVA,        // Only needed for NDirect case
5878     IMDInternalImport * pIMDII,     // Needed for NDirect, EEImpl(Delegate) cases
5879     LPCSTR              pMethodName // Only needed for mcEEImpl (Delegate) case
5880     COMMA_INDEBUG(LPCUTF8 pszDebugMethodName)
5881     COMMA_INDEBUG(LPCUTF8 pszDebugClassName)
5882     COMMA_INDEBUG(LPCUTF8 pszDebugMethodSignature)
5883     )
5884 {
5885     CONTRACTL
5886     {
5887         THROWS;
5888         if (fEnC) { GC_NOTRIGGER; } else { GC_TRIGGERS; }
5889         MODE_ANY;
5890     }
5891     CONTRACTL_END;
5892
5893     LOG((LF_CORDB, LL_EVERYTHING, "EEC::IMD: pNewMD:0x%x for tok:0x%x (%s::%s)\n",
5894         pNewMD, tok, pszDebugClassName, pszDebugMethodName));
5895
5896     // Now we know the classification we can perform any classification specific initialization.
5897
5898     // The method desc is zero inited by the caller.
5899
5900     switch (Classification)
5901     {
5902     case mcNDirect:
5903         {
5904             // NDirect specific initialization.
5905             NDirectMethodDesc *pNewNMD = (NDirectMethodDesc*)pNewMD;
5906
5907             // Allocate writeable data
5908             pNewNMD->ndirect.m_pWriteableData.SetValue((NDirectWriteableData*)
5909                 AllocateFromHighFrequencyHeap(S_SIZE_T(sizeof(NDirectWriteableData))));
5910
5911 #ifdef HAS_NDIRECT_IMPORT_PRECODE 
5912             pNewNMD->ndirect.m_pImportThunkGlue.SetValue(Precode::Allocate(PRECODE_NDIRECT_IMPORT, pNewMD,
5913                 GetLoaderAllocator(), GetMemTracker())->AsNDirectImportPrecode());
5914 #else // !HAS_NDIRECT_IMPORT_PRECODE
5915             pNewNMD->GetNDirectImportThunkGlue()->Init(pNewNMD);
5916 #endif // !HAS_NDIRECT_IMPORT_PRECODE
5917
5918 #if defined(_TARGET_X86_)
5919             pNewNMD->ndirect.m_cbStackArgumentSize = 0xFFFF;
5920 #endif // defined(_TARGET_X86_)
5921
5922             // If the RVA of a native method is set, this is an early-bound IJW call
5923             if (RVA != 0 && IsMiUnmanaged(dwImplFlags) && IsMiNative(dwImplFlags))
5924             {
5925                 // Note that we cannot initialize the stub directly now in the general case,
5926                 // as LoadLibrary may not have been performed yet.
5927                 pNewNMD->SetIsEarlyBound();
5928             }
5929
5930             pNewNMD->GetWriteableData()->m_pNDirectTarget = pNewNMD->GetNDirectImportThunkGlue()->GetEntrypoint();
5931         }
5932         break;
5933
5934     case mcFCall:
5935         break;
5936
5937     case mcEEImpl:
5938         // For the Invoke method we will set a standard invoke method.
5939         BAD_FORMAT_NOTHROW_ASSERT(IsDelegate());
5940
5941         // For the asserts, either the pointer is NULL (since the class hasn't
5942         // been constructed yet), or we're in EnC mode, meaning that the class
5943         // does exist, but we may be re-assigning the field to point to an
5944         // updated MethodDesc
5945
5946         // It is not allowed for EnC to replace one of the runtime builtin methods
5947
5948         if (strcmp(pMethodName, "Invoke") == 0)
5949         {
5950             BAD_FORMAT_NOTHROW_ASSERT(((DelegateEEClass*)GetHalfBakedClass())->m_pInvokeMethod.IsNull());
5951             ((DelegateEEClass*)GetHalfBakedClass())->m_pInvokeMethod.SetValue(pNewMD);
5952         }
5953         else if (strcmp(pMethodName, "BeginInvoke") == 0)
5954         {
5955             BAD_FORMAT_NOTHROW_ASSERT(((DelegateEEClass*)GetHalfBakedClass())->m_pBeginInvokeMethod.IsNull());
5956             ((DelegateEEClass*)GetHalfBakedClass())->m_pBeginInvokeMethod.SetValue(pNewMD);
5957         }
5958         else if (strcmp(pMethodName, "EndInvoke") == 0)
5959         {
5960             BAD_FORMAT_NOTHROW_ASSERT(((DelegateEEClass*)GetHalfBakedClass())->m_pEndInvokeMethod.IsNull());
5961             ((DelegateEEClass*)GetHalfBakedClass())->m_pEndInvokeMethod.SetValue(pNewMD);
5962         }
5963         else
5964         {
5965             BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
5966         }
5967
5968         // StoredSig specific intialization
5969         {
5970             StoredSigMethodDesc *pNewSMD = (StoredSigMethodDesc*) pNewMD;;
5971             DWORD cSig;
5972             PCCOR_SIGNATURE pSig;
5973             if (FAILED(pIMDII->GetSigOfMethodDef(tok, &cSig, &pSig)))
5974             {
5975                 BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
5976             }
5977             pNewSMD->SetStoredMethodSig(pSig, cSig);
5978         }
5979         break;
5980
5981 #ifdef FEATURE_COMINTEROP
5982     case mcComInterop:
5983 #endif // FEATURE_COMINTEROP
5984     case mcIL:
5985         break;
5986
5987     case mcInstantiated:
5988 #ifdef EnC_SUPPORTED 
5989         if (fEnC)
5990         {
5991             // We reuse the instantiated methoddescs to get the slot
5992             InstantiatedMethodDesc* pNewIMD = (InstantiatedMethodDesc*) pNewMD;
5993             pNewIMD->SetupEnCAddedMethod();
5994         }
5995         else
5996 #endif // EnC_SUPPORTED
5997         {
5998             // Initialize the typical instantiation.
5999             InstantiatedMethodDesc* pNewIMD = (InstantiatedMethodDesc*) pNewMD;
6000             //data has the same lifetime as method table, use our allocator
6001             pNewIMD->SetupGenericMethodDefinition(pIMDII, GetLoaderAllocator(), GetMemTracker(), GetModule(),
6002                                                   tok);
6003         }
6004         break;
6005
6006     default:
6007         BAD_FORMAT_NOTHROW_ASSERT(!"Failed to set a method desc classification");
6008     }
6009
6010     // Check the method desc's classification.
6011     _ASSERTE(pNewMD->GetClassification() == Classification);
6012
6013     pNewMD->SetMemberDef(tok);
6014
6015     if (IsMdStatic(dwMemberAttrs))
6016         pNewMD->SetStatic();
6017
6018     // Set suppress unmanaged code access permission attribute
6019
6020     if (pNewMD->IsNDirect())
6021         pNewMD->ComputeSuppressUnmanagedCodeAccessAttr(pIMDII);
6022
6023 #ifdef _DEBUG 
6024     // Mark as many methods as synchronized as possible.
6025     //
6026     // Note that this can easily cause programs to deadlock, and that
6027     // should not be treated as a bug in the program.
6028
6029     static ConfigDWORD stressSynchronized;
6030     DWORD stressSynchronizedVal = stressSynchronized.val(CLRConfig::INTERNAL_stressSynchronized);
6031
6032     bool isStressSynchronized =  stressSynchronizedVal &&
6033         pNewMD->IsIL() && // Synchronized is not supported on Ecalls, NDirect method, etc
6034         // IsValueClass() and IsEnum() do not work for System.ValueType and System.Enum themselves
6035         ((g_pValueTypeClass != NULL && g_pEnumClass != NULL &&
6036           !IsValueClass()) || // Can not synchronize on byref "this"
6037           IsMdStatic(dwMemberAttrs)) && // IsStatic() blows up in _DEBUG as pNewMD is not fully inited
6038         g_pObjectClass != NULL; // Ignore Object:* since "this" could be a boxed object
6039
6040     // stressSynchronized=1 turns off the stress in the system domain to reduce
6041     // the chances of spurious deadlocks. Deadlocks in user code can still occur.
6042     // stressSynchronized=2 will probably cause more deadlocks, and is not recommended
6043     if (stressSynchronizedVal == 1 && GetAssembly()->IsSystem())
6044         isStressSynchronized = false;
6045
6046     if (IsMiSynchronized(dwImplFlags) || isStressSynchronized)
6047 #else // !_DEBUG
6048     if (IsMiSynchronized(dwImplFlags))
6049 #endif // !_DEBUG
6050         pNewMD->SetSynchronized();
6051
6052 #ifdef _DEBUG 
6053     pNewMD->m_pszDebugMethodName = (LPUTF8)pszDebugMethodName;
6054     pNewMD->m_pszDebugClassName  = (LPUTF8)pszDebugClassName;
6055     pNewMD->m_pDebugMethodTable.SetValue(GetHalfBakedMethodTable());
6056
6057     if (pszDebugMethodSignature == NULL)
6058         pNewMD->m_pszDebugMethodSignature = FormatSig(pNewMD,pNewMD->GetLoaderAllocator()->GetLowFrequencyHeap(),GetMemTracker());
6059     else
6060         pNewMD->m_pszDebugMethodSignature = pszDebugMethodSignature;
6061 #endif // _DEBUG
6062 } // MethodTableBuilder::InitMethodDesc
6063
6064 //*******************************************************************************
6065 //
6066 // Used by BuildMethodTable
6067 //
6068 VOID 
6069 MethodTableBuilder::AddMethodImplDispatchMapping(
6070     DispatchMapTypeID typeID,
6071     SLOT_INDEX        slotNumber,
6072     bmtMDMethod *     pImplMethod)
6073 {
6074     STANDARD_VM_CONTRACT;
6075
6076     MethodDesc * pMDImpl = pImplMethod->GetMethodDesc();
6077
6078     // Look for an existing entry in the map.
6079     DispatchMapBuilder::Iterator it(bmtVT->pDispatchMapBuilder);
6080     if (bmtVT->pDispatchMapBuilder->Find(typeID, slotNumber, it))
6081     {
6082         // Throw if this entry has already previously been MethodImpl'd.
6083         if (it.IsMethodImpl())
6084         {
6085             // NOTE: This is where we check for duplicate overrides. This is the easiest place to check
6086             //       because duplicate overrides could in fact have separate MemberRefs to the same
6087             //       member and so just comparing tokens at the very start would not be enough.
6088             if (it.GetTargetMD() != pMDImpl)
6089             {
6090                 BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MULTIPLEOVERRIDES, pMDImpl->GetMemberDef());
6091             }
6092         }
6093         // This is the first MethodImpl. That's ok.
6094         else
6095         {
6096             it.SetTarget(pMDImpl);
6097             it.SetIsMethodImpl();
6098         }
6099     }
6100     // A mapping for this interface method does not exist, so insert it.
6101     else
6102     {
6103         bmtVT->pDispatchMapBuilder->InsertMDMapping(
6104             typeID, 
6105             slotNumber, 
6106             pMDImpl, 
6107             TRUE);
6108     }
6109
6110     // Save the entry into the vtable as well, if it isn't an interface methodImpl
6111     if (typeID == DispatchMapTypeID::ThisClassID())
6112     {
6113         bmtVT->SetVirtualMethodImpl(slotNumber, pImplMethod);
6114     }
6115 } // MethodTableBuilder::AddMethodImplDispatchMapping
6116
6117 //*******************************************************************************
6118 VOID
6119 MethodTableBuilder::MethodImplCompareSignatures(
6120     bmtMethodHandle     hDecl,
6121     bmtMethodHandle     hImpl,
6122     DWORD               dwConstraintErrorCode)
6123 {
6124     CONTRACTL {
6125         STANDARD_VM_CHECK;
6126         PRECONDITION(!hDecl.IsNull());
6127         PRECONDITION(!hImpl.IsNull());
6128         PRECONDITION(TypeFromToken(hDecl.GetMethodSignature().GetToken()) == mdtMethodDef);
6129         PRECONDITION(TypeFromToken(hImpl.GetMethodSignature().GetToken()) == mdtMethodDef);
6130     } CONTRACTL_END;
6131
6132     const MethodSignature &declSig(hDecl.GetMethodSignature());
6133     const MethodSignature &implSig(hImpl.GetMethodSignature());
6134
6135     if (!MethodSignature::SignaturesEquivalent(declSig, implSig))
6136     {
6137         LOG((LF_CLASSLOADER, LL_INFO1000, "BADSIG placing MethodImpl: %x\n", declSig.GetToken()));
6138         BuildMethodTableThrowException(COR_E_TYPELOAD, IDS_CLASSLOAD_MI_BADSIGNATURE, declSig.GetToken());
6139     }
6140
6141     //now compare the method constraints
6142     if (!MetaSig::CompareMethodConstraints(&implSig.GetSubstitution(), implSig.GetModule(), implSig.GetToken(),
6143                                            &declSig.GetSubstitution(), declSig.GetModule(), declSig.GetToken()))
6144     {
6145         BuildMethodTableThrowException(dwConstraintErrorCode, implSig.GetToken());
6146     }
6147 }
6148
6149 //*******************************************************************************
6150 // We should have collected all the method impls. Cycle through them creating the method impl
6151 // structure that holds the information about which slots are overridden.
6152 VOID
6153 MethodTableBuilder::PlaceMethodImpls()
6154 {
6155     STANDARD_VM_CONTRACT;
6156
6157     if(bmtMethodImpl->pIndex == 0)
6158     {
6159         return;
6160     }
6161
6162     // Allocate some temporary storage. The number of overrides for a single method impl
6163     // cannot be greater then the number of vtable slots for classes. But for interfaces
6164     // it might contain overrides for other interface methods.
6165     DWORD dwMaxSlotSize = IsInterface() ? bmtMethod->dwNumberMethodImpls : bmtVT->cVirtualSlots;
6166
6167     DWORD * slots = new (&GetThread()->m_MarshalAlloc) DWORD[dwMaxSlotSize];
6168     mdToken * tokens = new (&GetThread()->m_MarshalAlloc) mdToken[dwMaxSlotSize];
6169     RelativePointer<MethodDesc *> * replaced = new (&GetThread()->m_MarshalAlloc) RelativePointer<MethodDesc*>[dwMaxSlotSize];
6170
6171     DWORD iEntry = 0;
6172     bmtMDMethod * pCurImplMethod = bmtMethodImpl->GetImplementationMethod(iEntry);
6173
6174     DWORD slotIndex = 0;
6175
6176     // The impls are sorted according to the method descs for the body of the method impl.
6177     // Loop through the impls until the next body is found. When a single body
6178     // has been done move the slots implemented and method descs replaced into the storage
6179     // found on the body method desc.
6180     while (true)
6181     {   // collect information until we reach the next body
6182
6183         tokens[slotIndex] = bmtMethodImpl->GetDeclarationToken(iEntry);
6184
6185         // Get the declaration part of the method impl. It will either be a token
6186         // (declaration is on this type) or a method desc.
6187         bmtMethodHandle hDeclMethod = bmtMethodImpl->GetDeclarationMethod(iEntry);
6188         if(hDeclMethod.IsMDMethod())
6189         {   
6190             // The declaration is on the type being built
6191             bmtMDMethod * pCurDeclMethod = hDeclMethod.AsMDMethod();
6192
6193             mdToken mdef = pCurDeclMethod->GetMethodSignature().GetToken();
6194             if (bmtMethodImpl->IsBody(mdef))
6195             {   // A method declared on this class cannot be both a decl and an impl
6196                 BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MULTIPLEOVERRIDES, mdef);
6197             }
6198
6199             if (IsInterface())
6200             {
6201                 // Throws
6202                 PlaceInterfaceDeclarationOnInterface(
6203                     hDeclMethod,
6204                     pCurImplMethod,
6205                     slots,              // Adds override to the slot and replaced arrays.
6206                     replaced,
6207                     &slotIndex,
6208                     dwMaxSlotSize);     // Increments count                
6209             }
6210             else
6211             {
6212                 // Throws
6213                 PlaceLocalDeclarationOnClass(
6214                     pCurDeclMethod,
6215                     pCurImplMethod,
6216                     slots,              // Adds override to the slot and replaced arrays.
6217                     replaced,
6218                     &slotIndex,
6219                     dwMaxSlotSize);     // Increments count
6220             }
6221         }
6222         else
6223         {
6224             bmtRTMethod * pCurDeclMethod = hDeclMethod.AsRTMethod();
6225
6226             if (IsInterface())
6227             {
6228                 // Throws
6229                 PlaceInterfaceDeclarationOnInterface(
6230                     hDeclMethod,
6231                     pCurImplMethod,
6232                     slots,              // Adds override to the slot and replaced arrays.
6233                     replaced,
6234                     &slotIndex,
6235                     dwMaxSlotSize);     // Increments count     
6236             }
6237             else
6238             {
6239                 // Do not use pDecl->IsInterface here as that asks the method table and the MT may not yet be set up.
6240                 if (pCurDeclMethod->GetOwningType()->IsInterface())
6241                 {
6242                     // Throws
6243                     PlaceInterfaceDeclarationOnClass(
6244                         pCurDeclMethod,
6245                         pCurImplMethod);
6246                 }
6247                 else
6248                 {
6249                     // Throws
6250                     PlaceParentDeclarationOnClass(
6251                         pCurDeclMethod,
6252                         pCurImplMethod,
6253                         slots,
6254                         replaced,
6255                         &slotIndex,
6256                         dwMaxSlotSize);        // Increments count
6257                 }
6258             }
6259         }
6260
6261         iEntry++;
6262
6263         if(iEntry == bmtMethodImpl->pIndex)
6264         {
6265             // We hit the end of the list so dump the current data and leave
6266             WriteMethodImplData(pCurImplMethod, slotIndex, slots, tokens, replaced);
6267             break;
6268         }
6269         else
6270         {
6271             bmtMDMethod * pNextImplMethod = bmtMethodImpl->GetImplementationMethod(iEntry);
6272
6273             if (pNextImplMethod != pCurImplMethod)
6274             {
6275                 // If we're moving on to a new body, dump the current data and reset the counter
6276                 WriteMethodImplData(pCurImplMethod, slotIndex, slots, tokens, replaced);
6277                 slotIndex = 0;
6278             }
6279
6280             pCurImplMethod = pNextImplMethod;
6281         }
6282     }  // while(next != NULL)
6283 } // MethodTableBuilder::PlaceMethodImpls
6284
6285 //*******************************************************************************
6286 VOID
6287 MethodTableBuilder::WriteMethodImplData(
6288     bmtMDMethod * pImplMethod, 
6289     DWORD         cSlots, 
6290     DWORD *       rgSlots, 
6291     mdToken *     rgTokens,
6292     RelativePointer<MethodDesc *> * rgDeclMD)
6293 {
6294     STANDARD_VM_CONTRACT;
6295     
6296     // Use the number of overrides to
6297     // push information on to the method desc. We store the slots that
6298     // are overridden and the method desc that is replaced. That way
6299     // when derived classes need to determine if the method is to be
6300     // overridden then it can check the name against the replaced
6301     // method desc not the bodies name.
6302     if (cSlots == 0)
6303     {
6304         //@TODO:NEWVTWORK: Determine methodImpl status so that we don't need this workaround.
6305         //@TODO:NEWVTWORK: This occurs when only interface decls are involved, since
6306         //@TODO:NEWVTWORK: these are stored in the dispatch map and not on the methoddesc.
6307     }
6308     else
6309     {
6310         MethodImpl * pImpl = pImplMethod->GetMethodDesc()->GetMethodImpl();
6311
6312         // Set the size of the info the MethodImpl needs to keep track of.
6313         pImpl->SetSize(GetLoaderAllocator()->GetHighFrequencyHeap(), GetMemTracker(), cSlots);
6314
6315         if (!IsInterface())
6316         {
6317             // If we are currently builting an interface, the slots here has no meaning and we can skip it
6318             // Sort the two arrays in slot index order
6319             // This is required in MethodImpl::FindSlotIndex and MethodImpl::Iterator as we'll be using 
6320             // binary search later
6321             for (DWORD i = 0; i < cSlots; i++)
6322             {
6323                 int min = i;
6324                 for (DWORD j = i + 1; j < cSlots; j++)
6325                 {
6326                     if (rgSlots[j] < rgSlots[min])
6327                     {
6328                         min = j;
6329                     }
6330                 }
6331
6332                 if (min != i)
6333                 {
6334                     MethodDesc * mTmp = rgDeclMD[i].GetValue();
6335                     rgDeclMD[i].SetValue(rgDeclMD[min].GetValue());
6336                     rgDeclMD[min].SetValue(mTmp);
6337
6338                     DWORD sTmp = rgSlots[i];
6339                     rgSlots[i] = rgSlots[min];
6340                     rgSlots[min] = sTmp;
6341
6342                     mdToken tTmp = rgTokens[i];
6343                     rgTokens[i] = rgTokens[min];
6344                     rgTokens[min] = tTmp;
6345                 }
6346             }
6347         }
6348
6349         // Go and set the method impl
6350         pImpl->SetData(rgSlots, rgTokens, rgDeclMD);
6351
6352         GetHalfBakedClass()->SetContainsMethodImpls();
6353     }
6354 } // MethodTableBuilder::WriteMethodImplData
6355
6356 //*******************************************************************************
6357 VOID
6358 MethodTableBuilder::PlaceLocalDeclarationOnClass(
6359     bmtMDMethod * pDecl, 
6360     bmtMDMethod * pImpl, 
6361     DWORD *       slots, 
6362     RelativePointer<MethodDesc *> * replaced,
6363     DWORD *       pSlotIndex,
6364     DWORD         dwMaxSlotSize)
6365 {
6366     CONTRACTL
6367     {
6368         STANDARD_VM_CHECK;
6369         PRECONDITION(CheckPointer(bmtVT->pDispatchMapBuilder));
6370         PRECONDITION(CheckPointer(pDecl));
6371         PRECONDITION(CheckPointer(pImpl));
6372     }
6373     CONTRACTL_END
6374
6375     if (!bmtProp->fNoSanityChecks)
6376     {
6377         ///////////////////////////////
6378         // Verify the signatures match
6379
6380         MethodImplCompareSignatures(
6381             pDecl,
6382             pImpl,
6383             IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_LOCAL_METHOD_IMPL);
6384
6385         ///////////////////////////////
6386         // Validate the method impl.
6387
6388         TestMethodImpl(
6389             bmtMethodHandle(pDecl),
6390             bmtMethodHandle(pImpl));
6391     }
6392
6393     // Don't allow overrides for any of the four special runtime implemented delegate methods
6394     if (IsDelegate())
6395     {
6396         LPCUTF8 strMethodName = pDecl->GetMethodSignature().GetName();
6397         if ((strcmp(strMethodName, COR_CTOR_METHOD_NAME) == 0) || 
6398             (strcmp(strMethodName, "Invoke")             == 0) || 
6399             (strcmp(strMethodName, "BeginInvoke")        == 0) || 
6400             (strcmp(strMethodName, "EndInvoke")          == 0))
6401         {
6402             BuildMethodTableThrowException(
6403                 IDS_CLASSLOAD_MI_CANNOT_OVERRIDE, 
6404                 pDecl->GetMethodSignature().GetToken());
6405         }
6406     }
6407
6408     ///////////////////
6409     // Add the mapping
6410
6411     // Call helper to add it. Will throw if decl is already MethodImpl'd
6412     CONSISTENCY_CHECK(pDecl->GetSlotIndex() == static_cast<SLOT_INDEX>(pDecl->GetMethodDesc()->GetSlot()));
6413     AddMethodImplDispatchMapping(
6414         DispatchMapTypeID::ThisClassID(), 
6415         pDecl->GetSlotIndex(), 
6416         pImpl);
6417
6418     // We implement this slot, record it
6419     ASSERT(*pSlotIndex < dwMaxSlotSize);
6420     slots[*pSlotIndex] = pDecl->GetSlotIndex();
6421     replaced[*pSlotIndex].SetValue(pDecl->GetMethodDesc());
6422
6423     // increment the counter
6424     (*pSlotIndex)++;
6425 } // MethodTableBuilder::PlaceLocalDeclarationOnClass
6426
6427 //*******************************************************************************
6428 VOID MethodTableBuilder::PlaceInterfaceDeclarationOnClass(
6429     bmtRTMethod *     pDecl,
6430     bmtMDMethod *     pImpl)
6431 {
6432     CONTRACTL {
6433         STANDARD_VM_CHECK;
6434         PRECONDITION(CheckPointer(pDecl));
6435         PRECONDITION(CheckPointer(pImpl));
6436         PRECONDITION(pDecl->GetMethodDesc()->IsInterface());
6437         PRECONDITION(CheckPointer(bmtVT->pDispatchMapBuilder));
6438     } CONTRACTL_END;
6439
6440     MethodDesc *  pDeclMD = pDecl->GetMethodDesc();
6441     MethodTable * pDeclMT = pDeclMD->GetMethodTable();
6442
6443     // Note that the fact that pDecl is non-NULL means that we found the
6444     // declaration token to be owned by a declared interface for this type.
6445
6446     if (!bmtProp->fNoSanityChecks)
6447     {
6448         ///////////////////////////////
6449         // Verify the signatures match
6450
6451         MethodImplCompareSignatures(
6452             pDecl,
6453             pImpl,
6454             IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_INTERFACE_METHOD_IMPL);
6455
6456         ///////////////////////////////
6457         // Validate the method impl.
6458
6459         TestMethodImpl(
6460             bmtMethodHandle(pDecl),
6461             bmtMethodHandle(pImpl));
6462     }
6463
6464     ///////////////////
6465     // Add the mapping
6466
6467     // Note that we need only one DispatchMapTypeID for this interface (though there might be more if there 
6468     // are duplicates). The first one is easy to get, but we could (in theory) use the last one or a random 
6469     // one.
6470     // Q: Why don't we have to place this method for all duplicate interfaces? Because VSD knows about 
6471     // duplicates and finds the right (latest) implementation for us - see 
6472     // code:MethodTable::MethodDataInterfaceImpl::PopulateNextLevel#ProcessAllDuplicates.
6473     UINT32 cInterfaceDuplicates;
6474     DispatchMapTypeID firstDispatchMapTypeID;
6475     ComputeDispatchMapTypeIDs(
6476         pDeclMT, 
6477         &pDecl->GetMethodSignature().GetSubstitution(), 
6478         &firstDispatchMapTypeID, 
6479         1, 
6480         &cInterfaceDuplicates);
6481     CONSISTENCY_CHECK(cInterfaceDuplicates >= 1);
6482     CONSISTENCY_CHECK(firstDispatchMapTypeID.IsImplementedInterface());
6483
6484     // Call helper to add it. Will throw if decl is already MethodImpl'd
6485     CONSISTENCY_CHECK(pDecl->GetSlotIndex() == static_cast<SLOT_INDEX>(pDecl->GetMethodDesc()->GetSlot()));
6486     AddMethodImplDispatchMapping(
6487         firstDispatchMapTypeID, 
6488         pDecl->GetSlotIndex(), 
6489         pImpl);
6490
6491 #ifdef FEATURE_PREJIT
6492     if (IsCompilationProcess())
6493     {
6494         //
6495         // Mark this interface as overridable. It is used to skip generation of
6496         // CCWs stubs during NGen (see code:MethodNeedsReverseComStub)
6497         //
6498         if (!IsMdFinal(pImpl->GetDeclAttrs()))
6499         {
6500             pDeclMT->GetWriteableDataForWrite()->SetIsOverridingInterface();
6501         }
6502     }
6503 #endif
6504
6505 #ifdef _DEBUG
6506     if (bmtInterface->dbg_fShouldInjectInterfaceDuplicates)
6507     {   // We injected interface duplicates
6508         
6509         // We have to MethodImpl all interface duplicates as all duplicates are 'declared on type' (see 
6510         // code:#InjectInterfaceDuplicates_ApproxInterfaces)
6511         DispatchMapTypeID * rgDispatchMapTypeIDs = (DispatchMapTypeID *)_alloca(sizeof(DispatchMapTypeID) * cInterfaceDuplicates);
6512         ComputeDispatchMapTypeIDs(
6513             pDeclMT, 
6514             &pDecl->GetMethodSignature().GetSubstitution(), 
6515             rgDispatchMapTypeIDs, 
6516             cInterfaceDuplicates, 
6517             &cInterfaceDuplicates);
6518         for (UINT32 nInterfaceDuplicate = 1; nInterfaceDuplicate < cInterfaceDuplicates; nInterfaceDuplicate++)
6519         {
6520             // Add MethodImpl record for each injected interface duplicate
6521             AddMethodImplDispatchMapping(
6522                 rgDispatchMapTypeIDs[nInterfaceDuplicate], 
6523                 pDecl->GetSlotIndex(), 
6524                 pImpl);
6525         }
6526     }
6527 #endif //_DEBUG
6528 } // MethodTableBuilder::PlaceInterfaceDeclarationOnClass
6529
6530 //*******************************************************************************
6531 VOID MethodTableBuilder::PlaceInterfaceDeclarationOnInterface(
6532     bmtMethodHandle hDecl, 
6533     bmtMDMethod   *pImpl, 
6534     DWORD *       slots, 
6535     RelativePointer<MethodDesc *> * replaced,
6536     DWORD *       pSlotIndex,
6537     DWORD         dwMaxSlotSize)
6538 {
6539     CONTRACTL {
6540         STANDARD_VM_CHECK;
6541         PRECONDITION(CheckPointer(pImpl));
6542         PRECONDITION(IsInterface());
6543         PRECONDITION(hDecl.GetMethodDesc()->IsInterface());
6544     } CONTRACTL_END;
6545
6546     MethodDesc *  pDeclMD = hDecl.GetMethodDesc();
6547
6548     if (!bmtProp->fNoSanityChecks)
6549     {
6550         ///////////////////////////////
6551         // Verify the signatures match
6552
6553         MethodImplCompareSignatures(
6554             hDecl,
6555             bmtMethodHandle(pImpl),
6556             IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_INTERFACE_METHOD_IMPL);
6557
6558         ///////////////////////////////
6559         // Validate the method impl.
6560
6561         TestMethodImpl(hDecl, bmtMethodHandle(pImpl));
6562     }
6563
6564     // We implement this slot, record it
6565     ASSERT(*pSlotIndex < dwMaxSlotSize);
6566     slots[*pSlotIndex] = hDecl.GetSlotIndex();
6567     replaced[*pSlotIndex].SetValue(pDeclMD);
6568
6569     // increment the counter
6570     (*pSlotIndex)++;
6571 } // MethodTableBuilder::PlaceInterfaceDeclarationOnInterface
6572
6573 //*******************************************************************************
6574 VOID
6575 MethodTableBuilder::PlaceParentDeclarationOnClass(
6576     bmtRTMethod * pDecl, 
6577     bmtMDMethod * pImpl, 
6578     DWORD *       slots, 
6579     RelativePointer<MethodDesc *> * replaced,
6580     DWORD *       pSlotIndex,
6581     DWORD         dwMaxSlotSize)
6582 {
6583     CONTRACTL {
6584         STANDARD_VM_CHECK;
6585         PRECONDITION(CheckPointer(pDecl));
6586         PRECONDITION(CheckPointer(pImpl));
6587         PRECONDITION(CheckPointer(bmtVT->pDispatchMapBuilder));
6588         PRECONDITION(CheckPointer(GetParentMethodTable()));
6589     } CONTRACTL_END;
6590
6591     MethodDesc * pDeclMD = pDecl->GetMethodDesc();
6592
6593     // Note that the fact that pDecl is non-NULL means that we found the
6594     // declaration token to be owned by a parent type.
6595
6596     if (!bmtProp->fNoSanityChecks)
6597     {
6598         /////////////////////////////////////////
6599         // Verify that the signatures match
6600
6601         MethodImplCompareSignatures(
6602             pDecl,
6603             pImpl,
6604             IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_PARENT_METHOD_IMPL);
6605
6606         ////////////////////////////////
6607         // Verify rules of method impls
6608
6609         TestMethodImpl(
6610             bmtMethodHandle(pDecl),
6611             bmtMethodHandle(pImpl));
6612     }
6613
6614     ///////////////////
6615     // Add the mapping
6616
6617     // Call helper to add it. Will throw if DECL is already MethodImpl'd
6618     AddMethodImplDispatchMapping(
6619         DispatchMapTypeID::ThisClassID(), 
6620         pDeclMD->GetSlot(), 
6621         pImpl);
6622
6623     // We implement this slot, record it
6624     ASSERT(*pSlotIndex < dwMaxSlotSize);
6625     slots[*pSlotIndex] = pDeclMD->GetSlot();
6626     replaced[*pSlotIndex].SetValue(pDeclMD);
6627
6628     // increment the counter
6629     (*pSlotIndex)++;
6630 } // MethodTableBuilder::PlaceParentDeclarationOnClass
6631
6632 //*******************************************************************************
6633 // This will validate that all interface methods that were matched during
6634 // layout also validate against type constraints.
6635
6636 VOID MethodTableBuilder::ValidateInterfaceMethodConstraints()
6637 {
6638     STANDARD_VM_CONTRACT;
6639
6640     DispatchMapBuilder::Iterator it(bmtVT->pDispatchMapBuilder);
6641     for (; it.IsValid(); it.Next())
6642     {
6643         if (it.GetTypeID() != DispatchMapTypeID::ThisClassID())
6644         {
6645             bmtRTType * pItf = bmtInterface->pInterfaceMap[it.GetTypeID().GetInterfaceNum()].GetInterfaceType();
6646
6647             // Grab the method token
6648             MethodTable * pMTItf = pItf->GetMethodTable();
6649             CONSISTENCY_CHECK(CheckPointer(pMTItf->GetMethodDescForSlot(it.GetSlotNumber())));
6650             mdMethodDef mdTok = pItf->GetMethodTable()->GetMethodDescForSlot(it.GetSlotNumber())->GetMemberDef();
6651
6652             // Default to the current module. The code immediately below determines if this
6653             // assumption is incorrect.
6654             Module *          pTargetModule          = GetModule();
6655
6656             // Get the module of the target method. Get it through the chunk to
6657             // avoid triggering the assert that MethodTable is non-NULL. It may
6658             // be null since it may belong to the type we're building right now.
6659             MethodDesc *      pTargetMD              = it.GetTargetMD();
6660
6661             // If pTargetMT is null, this indicates that the target MethodDesc belongs
6662             // to the current type. Otherwise, the MethodDesc MUST be owned by a parent
6663             // of the type we're building.
6664             BOOL              fTargetIsOwnedByParent = !pTargetMD->GetMethodTablePtr()->IsNull();        
6665             
6666             // If the method is owned by a parent, we need to use the parent's module,
6667             // and we must construct the substitution chain all the way up to the parent.
6668             const Substitution *pSubstTgt = NULL;
6669             if (fTargetIsOwnedByParent)
6670             {
6671                 CONSISTENCY_CHECK(CheckPointer(GetParentType()));
6672                 bmtRTType *pTargetType = bmtRTType::FindType(GetParentType(), pTargetMD->GetMethodTable());
6673                 pSubstTgt = &pTargetType->GetSubstitution();
6674                 pTargetModule = pTargetType->GetModule();
6675             }
6676
6677             // Now compare the method constraints.
6678             if (!MetaSig::CompareMethodConstraints(pSubstTgt,
6679                                                    pTargetModule,
6680                                                    pTargetMD->GetMemberDef(),
6681                                                    &pItf->GetSubstitution(),
6682                                                    pMTItf->GetModule(),
6683                                                    mdTok))
6684             {
6685                 LOG((LF_CLASSLOADER, LL_INFO1000,
6686                      "BADCONSTRAINTS on interface method implementation: %x\n", pTargetMD));
6687                 // This exception will be due to an implicit implementation, since explicit errors
6688                 // will be detected in MethodImplCompareSignatures (for now, anyway).
6689                 CONSISTENCY_CHECK(!it.IsMethodImpl());
6690                 DWORD idsError = it.IsMethodImpl() ?
6691                                  IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_INTERFACE_METHOD_IMPL :
6692                                  IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_IMPLICIT_IMPLEMENTATION;
6693                 if (fTargetIsOwnedByParent)
6694                 {
6695                     DefineFullyQualifiedNameForClass();
6696                     LPCUTF8 szClassName = GetFullyQualifiedNameForClassNestedAware(pTargetMD->GetMethodTable());
6697                     LPCUTF8 szMethodName = pTargetMD->GetName();
6698
6699                     CQuickBytes qb;
6700                     // allocate enough room for "<class>.<method>\0"
6701                     size_t cchFullName = strlen(szClassName) + 1 + strlen(szMethodName) + 1;
6702                     LPUTF8 szFullName = (LPUTF8) qb.AllocThrows(cchFullName);
6703                     strcpy_s(szFullName, cchFullName, szClassName);
6704                     strcat_s(szFullName, cchFullName, ".");
6705                     strcat_s(szFullName, cchFullName, szMethodName);
6706
6707                     BuildMethodTableThrowException(idsError, szFullName);
6708                 }
6709                 else
6710                 {
6711                     BuildMethodTableThrowException(idsError, pTargetMD->GetMemberDef());
6712                 }
6713             }
6714         }
6715     }
6716 } // MethodTableBuilder::ValidateInterfaceMethodConstraints
6717
6718 //*******************************************************************************
6719 // Used to allocate and initialize MethodDescs (both the boxed and unboxed entrypoints)
6720 VOID MethodTableBuilder::AllocAndInitMethodDescs()
6721 {
6722     STANDARD_VM_CONTRACT;
6723
6724     //
6725     // Go over all MethodDescs and create smallest number of MethodDescChunks possible.
6726     //
6727     // Iterate over all methods and start a new chunk only if:
6728     //  - Token range (upper 24 bits of the method token) has changed.
6729     //  - The maximum size of the chunk has been reached.
6730     //
6731
6732     int currentTokenRange = -1; // current token range
6733     SIZE_T sizeOfMethodDescs = 0; // current running size of methodDesc chunk
6734     int startIndex = 0; // start of the current chunk (index into bmtMethod array)
6735
6736     DeclaredMethodIterator it(*this);
6737     while (it.Next())
6738     {
6739         int tokenRange = GetTokenRange(it.Token());
6740
6741         // This code assumes that iterator returns tokens in ascending order. If this assumption does not hold, 
6742         // the code will still work with small performance penalty (method desc chunk layout will be less efficient).
6743         _ASSERTE(tokenRange >= currentTokenRange);
6744
6745         SIZE_T size = MethodDesc::GetBaseSize(GetMethodClassification(it->GetMethodType()));
6746
6747         // Add size of optional slots
6748
6749         if (it->GetMethodImplType() == METHOD_IMPL)
6750             size += sizeof(MethodImpl);
6751
6752         if (it->GetSlotIndex() >= bmtVT->cVtableSlots)
6753             size += sizeof(MethodDesc::NonVtableSlot); // slot
6754
6755         if (NeedsNativeCodeSlot(*it))
6756             size += sizeof(MethodDesc::NativeCodeSlot);
6757
6758         // See comment in AllocAndInitMethodDescChunk
6759         if (NeedsTightlyBoundUnboxingStub(*it))
6760         {
6761             size *= 2;
6762
6763             if (bmtGenerics->GetNumGenericArgs() == 0) {
6764                 size += sizeof(MethodDesc::NonVtableSlot);
6765             }
6766             else {
6767                 bmtVT->cVtableSlots++;
6768             }
6769         }
6770
6771 #ifndef CROSSGEN_COMPILE
6772         if (tokenRange != currentTokenRange ||
6773             sizeOfMethodDescs + size > MethodDescChunk::MaxSizeOfMethodDescs)
6774 #endif // CROSSGEN_COMPILE
6775         {
6776             if (sizeOfMethodDescs != 0)
6777             {
6778                 AllocAndInitMethodDescChunk(startIndex, it.CurrentIndex() - startIndex, sizeOfMethodDescs);
6779                 startIndex = it.CurrentIndex();
6780             }
6781
6782             currentTokenRange = tokenRange;
6783             sizeOfMethodDescs = 0;
6784         }
6785
6786         sizeOfMethodDescs += size;
6787     }
6788
6789     if (sizeOfMethodDescs != 0)
6790     {
6791         AllocAndInitMethodDescChunk(startIndex, NumDeclaredMethods() - startIndex, sizeOfMethodDescs);
6792     }
6793 }
6794
6795 //*******************************************************************************
6796 // Allocates and initializes one method desc chunk.
6797 //
6798 // Arguments:
6799 //    startIndex - index of first method in bmtMethod array.
6800 //    count - number of methods in this chunk (contiguous region from startIndex)
6801 //    sizeOfMethodDescs - total expected size of MethodDescs in this chunk
6802 //
6803 // Used by AllocAndInitMethodDescs.
6804 //
6805 VOID MethodTableBuilder::AllocAndInitMethodDescChunk(COUNT_T startIndex, COUNT_T count, SIZE_T sizeOfMethodDescs)
6806 {
6807     CONTRACTL {
6808         STANDARD_VM_CHECK;
6809         PRECONDITION(sizeOfMethodDescs <= MethodDescChunk::MaxSizeOfMethodDescs);
6810     } CONTRACTL_END;
6811
6812     void * pMem = GetMemTracker()->Track(
6813         GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(TADDR) + sizeof(MethodDescChunk) + sizeOfMethodDescs)));
6814
6815     // Skip pointer to temporary entrypoints
6816     MethodDescChunk * pChunk = (MethodDescChunk *)((BYTE*)pMem + sizeof(TADDR));
6817
6818     COUNT_T methodDescCount = 0;
6819
6820     SIZE_T offset = sizeof(MethodDescChunk);
6821
6822 #ifdef _PREFAST_ 
6823 #pragma warning(push)
6824 #pragma warning(disable:22019) // Suppress PREFast warning about integer underflow
6825 #endif // _PREFAST_
6826     for (COUNT_T i = 0; i < count; i++)
6827 #ifdef _PREFAST_ 
6828 #pragma warning(pop)
6829 #endif // _PREFAST_
6830
6831     {
6832         bmtMDMethod * pMDMethod = (*bmtMethod)[static_cast<SLOT_INDEX>(startIndex + i)];
6833
6834         MethodDesc * pMD = (MethodDesc *)((BYTE *)pChunk + offset); 
6835
6836         pMD->SetChunkIndex(pChunk);
6837
6838         InitNewMethodDesc(pMDMethod, pMD);
6839
6840 #ifdef _PREFAST_ 
6841 #pragma warning(push)
6842 #pragma warning(disable:22018) // Suppress PREFast warning about integer underflow
6843 #endif // _PREFAST_
6844         offset += pMD->SizeOf();
6845 #ifdef _PREFAST_ 
6846 #pragma warning(pop)
6847 #endif // _PREFAST_
6848
6849         methodDescCount++;
6850
6851         // If we're a value class, we want to create duplicate slots
6852         // and MethodDescs for all methods in the vtable
6853         // section (i.e. not non-virtual instance methods or statics).
6854         // In the name of uniformity it would be much nicer
6855         // if we created _all_ value class BoxedEntryPointStubs at this point.
6856         // However, non-virtual instance methods only require unboxing
6857         // stubs in the rare case that we create a delegate to such a
6858         // method, and thus it would be inefficient to create them on
6859         // loading: after all typical structs will have many non-virtual
6860         // instance methods.
6861         //
6862         // Unboxing stubs for non-virtual instance methods are created
6863         // in code:MethodDesc::FindOrCreateAssociatedMethodDesc.
6864
6865         if (NeedsTightlyBoundUnboxingStub(pMDMethod))
6866         {
6867             MethodDesc * pUnboxedMD = (MethodDesc *)((BYTE *)pChunk + offset); 
6868
6869             //////////////////////////////////
6870             // Initialize the new MethodDesc
6871
6872             // <NICE> memcpy operations on data structures like MethodDescs are extremely fragile
6873             // and should not be used.  We should go to the effort of having proper constructors
6874             // in the MethodDesc class. </NICE>
6875
6876             memcpy(pUnboxedMD, pMD, pMD->SizeOf());
6877
6878             // Reset the chunk index
6879             pUnboxedMD->SetChunkIndex(pChunk);
6880
6881             if (bmtGenerics->GetNumGenericArgs() == 0) {
6882                 pUnboxedMD->SetHasNonVtableSlot();
6883             }
6884
6885             //////////////////////////////////////////////////////////
6886             // Modify the original MethodDesc to be an unboxing stub
6887
6888             pMD->SetIsUnboxingStub();
6889
6890             ////////////////////////////////////////////////////////////////////
6891             // Add the new MethodDesc to the non-virtual portion of the vtable
6892
6893             if (!bmtVT->AddUnboxedMethod(pMDMethod))
6894                 BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
6895
6896             pUnboxedMD->SetSlot(pMDMethod->GetUnboxedSlotIndex());
6897             pMDMethod->SetUnboxedMethodDesc(pUnboxedMD);
6898
6899             offset += pUnboxedMD->SizeOf();
6900             methodDescCount++;
6901         }
6902     }
6903     _ASSERTE(offset == sizeof(MethodDescChunk) + sizeOfMethodDescs);
6904
6905     pChunk->SetSizeAndCount((ULONG)sizeOfMethodDescs, methodDescCount);
6906
6907     GetHalfBakedClass()->AddChunk(pChunk);
6908 }
6909
6910 //*******************************************************************************
6911 BOOL
6912 MethodTableBuilder::NeedsTightlyBoundUnboxingStub(bmtMDMethod * pMDMethod)
6913 {
6914     STANDARD_VM_CONTRACT;
6915
6916     return IsValueClass() &&
6917            !IsMdStatic(pMDMethod->GetDeclAttrs()) &&
6918            IsMdVirtual(pMDMethod->GetDeclAttrs()) &&
6919            (pMDMethod->GetMethodType() != METHOD_TYPE_INSTANTIATED) &&
6920            !IsMdRTSpecialName(pMDMethod->GetDeclAttrs());
6921 }
6922
6923 //*******************************************************************************
6924 BOOL
6925 MethodTableBuilder::NeedsNativeCodeSlot(bmtMDMethod * pMDMethod)
6926 {
6927     LIMITED_METHOD_CONTRACT;
6928
6929
6930 #ifdef FEATURE_TIERED_COMPILATION
6931     // Keep in-sync with MethodDesc::DetermineAndSetIsEligibleForTieredCompilation()
6932     if (g_pConfig->TieredCompilation() &&
6933         (pMDMethod->GetMethodType() == METHOD_TYPE_NORMAL || pMDMethod->GetMethodType() == METHOD_TYPE_INSTANTIATED))
6934     {
6935         return TRUE;
6936     }
6937 #endif
6938
6939 #if defined(FEATURE_JIT_PITCHING)
6940     if ((CLRConfig::GetConfigValue(CLRConfig::INTERNAL_JitPitchEnabled) != 0) &&
6941         (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_JitPitchMemThreshold) != 0))
6942         return TRUE;
6943 #endif
6944
6945     return GetModule()->IsEditAndContinueEnabled();
6946 }
6947
6948 //*******************************************************************************
6949 VOID
6950 MethodTableBuilder::AllocAndInitDictionary()
6951 {
6952     STANDARD_VM_CONTRACT;
6953
6954     // Allocate dictionary layout used by all compatible instantiations
6955
6956     if (bmtGenerics->fSharedByGenericInstantiations && !bmtGenerics->fContainsGenericVariables)
6957     {
6958         // We use the number of methods as a heuristic for the number of slots in the dictionary
6959         // attached to shared class method tables.
6960         // If there are no declared methods then we have no slots, and we will never do any token lookups
6961         //
6962         // Heuristics
6963         //  - Classes with a small number of methods (2-3) tend to be more likely to use new slots,
6964         //    i.e. further methods tend to reuse slots from previous methods.
6965         //      = treat all classes with only 2-3 methods as if they have an extra method.
6966         //  - Classes with more generic parameters tend to use more slots.
6967         //      = multiply by 1.5 for 2 params or more
6968
6969         DWORD numMethodsAdjusted =
6970             (bmtMethod->dwNumDeclaredNonAbstractMethods == 0)
6971             ? 0
6972             : (bmtMethod->dwNumDeclaredNonAbstractMethods < 3)
6973             ? 3
6974             : bmtMethod->dwNumDeclaredNonAbstractMethods;
6975
6976         _ASSERTE(bmtGenerics->GetNumGenericArgs() != 0);
6977         DWORD nTypeFactorBy2 = (bmtGenerics->GetNumGenericArgs() == 1)
6978                                ? 2
6979                                : 3;
6980
6981         DWORD estNumTypeSlots = (numMethodsAdjusted * nTypeFactorBy2 + 2) / 3;
6982         // estNumTypeSlots should fit in a WORD as long as we maintain the current
6983         // limit on the number of methods in a type (approx 2^16).
6984         _ASSERTE(FitsIn<WORD>(estNumTypeSlots));
6985         WORD numTypeSlots = static_cast<WORD>(estNumTypeSlots);
6986
6987         if (numTypeSlots > 0)
6988         {
6989             // Dictionary layout is an optional field on EEClass, so ensure the optional field descriptor has
6990             // been allocated.
6991             EnsureOptionalFieldsAreAllocated(GetHalfBakedClass(), m_pAllocMemTracker, GetLoaderAllocator()->GetLowFrequencyHeap());
6992             GetHalfBakedClass()->SetDictionaryLayout(DictionaryLayout::Allocate(numTypeSlots, bmtAllocator, m_pAllocMemTracker));
6993         }
6994     }
6995
6996 }
6997
6998 //*******************************************************************************
6999 //
7000 // Used by BuildMethodTable
7001 //
7002 // Compute the set of interfaces which are equivalent. Duplicates in the interface map
7003 // will be placed into different equivalence sets unless they participate in type equivalence.
7004 // This is a bit odd, but it turns out we only need to know about equivalence classes if
7005 // there is type equivalence involved in the interface, and not detecting, or detecting equivalence
7006 // in other cases does not result in differing behavior.
7007 // 
7008 // By restricting the reasons for having equivalence matches, we reduce the algorithm from one which
7009 // is O(n*n) best case to an algorithm which will typically execute something more like O(m*n) best case time 
7010 // where m is the number of generic interface (although still n*n in worst case). The assumption is that equivalent
7011 // and generic interfaces are relatively rare.
7012 VOID
7013 MethodTableBuilder::ComputeInterfaceMapEquivalenceSet()
7014 {
7015     STANDARD_VM_CONTRACT;
7016
7017     UINT32 nextEquivalenceSet = 1;
7018
7019     for (DWORD dwCurInterface = 0;
7020          dwCurInterface < bmtInterface->dwInterfaceMapSize;
7021          dwCurInterface++)
7022     {
7023         // Keep track of the current interface we are trying to calculate the equivalence set of
7024         bmtInterfaceEntry *     pCurItfEntry = &bmtInterface->pInterfaceMap[dwCurInterface];
7025         bmtRTType *             pCurItf      = pCurItfEntry->GetInterfaceType();
7026         MethodTable *           pCurItfMT    = pCurItf->GetMethodTable();
7027         const Substitution *    pCurItfSubst = &pCurItf->GetSubstitution();
7028
7029         UINT32 currentEquivalenceSet = 0;
7030
7031         // Only interfaces with type equivalence, or that are generic need to be compared for equivalence
7032         if (pCurItfMT->HasTypeEquivalence() || pCurItfMT->HasInstantiation())
7033         {
7034             for (DWORD dwCurInterfaceCompare = 0;
7035                  dwCurInterfaceCompare < dwCurInterface;
7036                  dwCurInterfaceCompare++)
7037             {
7038                 // Keep track of the current interface we are trying to calculate the equivalence set of
7039                 bmtInterfaceEntry *     pCompareItfEntry = &bmtInterface->pInterfaceMap[dwCurInterfaceCompare];
7040                 bmtRTType *             pCompareItf      = pCompareItfEntry->GetInterfaceType();
7041                 MethodTable *           pCompareItfMT    = pCompareItf->GetMethodTable();
7042                 const Substitution *    pCompareItfSubst = &pCompareItf->GetSubstitution();
7043
7044                 // Only interfaces with type equivalence, or that are generic need to be compared for equivalence
7045                 if (pCompareItfMT->HasTypeEquivalence() || pCompareItfMT->HasInstantiation())
7046                 {
7047                     if (MetaSig::CompareTypeDefsUnderSubstitutions(pCurItfMT,
7048                                                                    pCompareItfMT,
7049                                                                    pCurItfSubst,
7050                                                                    pCompareItfSubst,
7051                                                                    NULL))
7052                     {
7053                         currentEquivalenceSet = pCompareItfEntry->GetInterfaceEquivalenceSet();
7054                         // Use the equivalence set of the interface map entry we just found
7055                         pCurItfEntry->SetInterfaceEquivalenceSet(currentEquivalenceSet, true);
7056                         // Update the interface map entry we just found to indicate that it is part of an equivalence
7057                         // set with multiple entries.
7058                         pCompareItfEntry->SetInterfaceEquivalenceSet(currentEquivalenceSet, true);
7059                         break;
7060                     }
7061                 }
7062             }
7063         }
7064
7065         // If we did not find an equivalent interface above, use the next available equivalence set indicator
7066         if (currentEquivalenceSet == 0)
7067         {
7068             pCurItfEntry->SetInterfaceEquivalenceSet(nextEquivalenceSet, false);
7069             nextEquivalenceSet++;
7070         }
7071     }
7072 }
7073
7074 //*******************************************************************************
7075 //
7076 // Used by PlaceInterfaceMethods
7077 //
7078 // Given an interface in our interface map, and a particular method on that interface, place
7079 // a method from the parent types implementation of an equivalent interface into that method 
7080 // slot. Used by PlaceInterfaceMethods to make equivalent interface implementations have the 
7081 // same behavior as if the parent interface was implemented on this type instead of an equivalent interface.
7082 //
7083 // This logic is used in situations such as below. I and I' are equivalent interfaces
7084 //
7085 //#
7086 // class Base : I
7087 // {void I.Method() { } }
7088 // interface IOther : I' {}
7089 // class Derived : IOther
7090 // { virtual void Method() {}}
7091 //
7092 // We should Map I'.Method to Base.Method, not Derived.Method
7093 // 
7094 // Another example
7095 // class Base : I
7096 // { virtual void Method() }
7097 // interface IOther : I' {}
7098 // class Derived : IOther
7099 // { virtual void Method() {}}
7100 //
7101 // We should map I'.Method to Base.Method, not Derived.Method
7102 //
7103 // class Base : I
7104 // {void I.Method() { } }
7105 // class Derived : I'
7106 // {}
7107 //
7108 // We should Map I'.Method to Base.Method, and not throw TypeLoadException
7109 //
7110 #ifdef FEATURE_COMINTEROP
7111 VOID 
7112 MethodTableBuilder::PlaceMethodFromParentEquivalentInterfaceIntoInterfaceSlot(
7113     bmtInterfaceEntry::InterfaceSlotIterator & itfSlotIt, 
7114     bmtInterfaceEntry *                        pCurItfEntry, 
7115     DispatchMapTypeID **                       prgInterfaceDispatchMapTypeIDs, 
7116     DWORD                                      dwCurInterface)
7117 {
7118     STANDARD_VM_CONTRACT;
7119
7120     bmtRTMethod * pCurItfMethod = itfSlotIt->Decl().AsRTMethod();
7121
7122     if (itfSlotIt->Impl() != INVALID_SLOT_INDEX)
7123     {
7124         return;
7125     }
7126
7127     // For every equivalent interface entry that was actually implemented by parent, then look at equivalent method slot on that entry
7128     // and if it matches and has a slot implementation, then record and continue
7129     for (DWORD dwEquivalentInterface = 0;
7130          (dwEquivalentInterface < bmtInterface->dwInterfaceMapSize) && (itfSlotIt->Impl() == INVALID_SLOT_INDEX);
7131          dwEquivalentInterface++)
7132     {
7133         bmtInterfaceEntry *  pEquivItfEntry = &bmtInterface->pInterfaceMap[dwEquivalentInterface];
7134         bmtRTType *          pEquivItf      = pEquivItfEntry->GetInterfaceType();
7135         MethodTable *        pEquivItfMT    = pEquivItf->GetMethodTable();
7136         const Substitution * pEquivItfSubst = &pEquivItf->GetSubstitution();
7137         if (pEquivItfEntry->GetInterfaceEquivalenceSet() != pCurItfEntry->GetInterfaceEquivalenceSet())
7138         {
7139             // Not equivalent
7140             continue;
7141         }
7142         if (!pEquivItfEntry->IsImplementedByParent())
7143         {
7144             // Not implemented by parent
7145             continue;
7146         }
7147         
7148         WORD slot = static_cast<WORD>(itfSlotIt.CurrentIndex());
7149         BOOL fFound = FALSE;
7150
7151         // Determine which slot on the equivalent interface would map to the slot we are attempting to fill
7152         // in with an implementation.
7153         WORD otherMTSlot = GetEquivalentMethodSlot(pCurItfEntry->GetInterfaceType()->GetMethodTable(), 
7154                                                    pEquivItfEntry->GetInterfaceType()->GetMethodTable(), 
7155                                                    slot, 
7156                                                    &fFound);
7157
7158         if (fFound)
7159         {
7160             UINT32 cInterfaceDuplicates;
7161             if (*prgInterfaceDispatchMapTypeIDs == NULL)
7162             {
7163                 *prgInterfaceDispatchMapTypeIDs = 
7164                     new (GetStackingAllocator()) DispatchMapTypeID[bmtInterface->dwInterfaceMapSize];
7165             }
7166
7167             // Compute all TypeIDs for this interface (all duplicates in the interface map)
7168             ComputeDispatchMapTypeIDs(
7169                 pEquivItfMT, 
7170                 pEquivItfSubst, 
7171                 *prgInterfaceDispatchMapTypeIDs, 
7172                 bmtInterface->dwInterfaceMapSize, 
7173                 &cInterfaceDuplicates);
7174             // There cannot be more duplicates than number of interfaces
7175             _ASSERTE(cInterfaceDuplicates <= bmtInterface->dwInterfaceMapSize);
7176             _ASSERTE(cInterfaceDuplicates > 0);
7177             
7178             // NOTE: This override does not cache the resulting MethodData object
7179             MethodTable::MethodDataWrapper hParentData;
7180             hParentData = MethodTable::GetMethodData(
7181                     *prgInterfaceDispatchMapTypeIDs, 
7182                     cInterfaceDuplicates, 
7183                     pEquivItfMT, 
7184                     GetParentMethodTable());
7185
7186             SLOT_INDEX slotIndex = static_cast<SLOT_INDEX>
7187                 (hParentData->GetImplSlotNumber(static_cast<UINT32>(otherMTSlot)));
7188
7189             // Interface is implemented on parent abstract type and this particular slot was not implemented
7190             if (slotIndex == INVALID_SLOT_INDEX)
7191             {
7192                 continue;
7193             }
7194
7195             bmtMethodSlot & parentSlotImplementation = (*bmtParent->pSlotTable)[slotIndex];
7196             bmtMethodHandle & parentImplementation = parentSlotImplementation.Impl();
7197
7198             // Check to verify that the equivalent slot on the equivalent interface actually matches the method
7199             // on the current interface. If not, then the slot is not a match, and we should search other interfaces
7200             // for an implementation of the method.
7201             if (!MethodSignature::SignaturesEquivalent(pCurItfMethod->GetMethodSignature(), parentImplementation.GetMethodSignature()))
7202             {
7203                 continue;
7204             }
7205
7206             itfSlotIt->Impl() = slotIndex;
7207
7208             MethodDesc * pMD = hParentData->GetImplMethodDesc(static_cast<UINT32>(otherMTSlot));
7209
7210             DispatchMapTypeID dispatchMapTypeID =
7211                 DispatchMapTypeID::InterfaceClassID(dwCurInterface);
7212             bmtVT->pDispatchMapBuilder->InsertMDMapping(
7213                 dispatchMapTypeID, 
7214                 static_cast<UINT32>(itfSlotIt.CurrentIndex()), 
7215                 pMD, 
7216                 FALSE);
7217         }
7218     }
7219 } // MethodTableBuilder::PlaceMethodFromParentEquivalentInterfaceIntoInterfaceSlot
7220 #endif // FEATURE_COMINTEROP
7221
7222 //*******************************************************************************
7223 //
7224 // Used by BuildMethodTable
7225 //
7226 //
7227 // If we are a class, then there may be some unplaced vtable methods (which are by definition
7228 // interface methods, otherwise they'd already have been placed).  Place as many unplaced methods
7229 // as possible, in the order preferred by interfaces.  However, do not allow any duplicates - once
7230 // a method has been placed, it cannot be placed again - if we are unable to neatly place an interface,
7231 // create duplicate slots for it starting at dwCurrentDuplicateVtableSlot.  Fill out the interface
7232 // map for all interfaces as they are placed.
7233 //
7234 // If we are an interface, then all methods are already placed.  Fill out the interface map for
7235 // interfaces as they are placed.
7236 //
7237 // BEHAVIOUR (based on Partition II: 11.2, not including MethodImpls)
7238 //   C is current class, P is a parent class, I is the interface being implemented
7239 //
7240 //   FOREACH interface I implemented by this class C
7241 //     FOREACH method I::M
7242 //       IF I is EXPLICITLY implemented by C
7243 //         IF some method C::M matches I::M
7244 //           USE C::M as implementation for I::M
7245 //         ELIF we inherit a method P::M that matches I::M
7246 //           USE P::M as implementation for I::M
7247 //         ENDIF
7248 //       ELSE
7249 //         IF I::M lacks implementation
7250 //           IF some method C::M matches I::M
7251 //             USE C::M as implementation for I::M
7252 //           ELIF we inherit a method P::M that matches I::M
7253 //             USE P::M as implementation for I::M
7254 //           ELIF I::M was implemented by the parent type with method Parent::M
7255 //             USE Parent::M for the implementation of I::M // VSD does this by default if we really 
7256 //                                                           // implemented I on the parent type, but 
7257 //                                                           // equivalent interfaces need to make this 
7258 //                                                           // explicit
7259 //           ENDIF
7260 //         ENDIF
7261 //       ENDIF
7262 //     ENDFOR
7263 //   ENDFOR
7264 //
7265
7266 VOID
7267 MethodTableBuilder::PlaceInterfaceMethods()
7268 {
7269     STANDARD_VM_CONTRACT;
7270
7271     BOOL fParentInterface;
7272     DispatchMapTypeID * rgInterfaceDispatchMapTypeIDs = NULL;
7273
7274     for (DWORD dwCurInterface = 0;
7275          dwCurInterface < bmtInterface->dwInterfaceMapSize;
7276          dwCurInterface++)
7277     {
7278         // Default to being implemented by the current class
7279         fParentInterface = FALSE;
7280
7281         // Keep track of the current interface we are trying to place
7282         bmtInterfaceEntry *     pCurItfEntry = &bmtInterface->pInterfaceMap[dwCurInterface];
7283         bmtRTType *             pCurItf      = pCurItfEntry->GetInterfaceType();
7284         MethodTable *           pCurItfMT    = pCurItf->GetMethodTable();
7285         const Substitution *    pCurItfSubst = &pCurItf->GetSubstitution();
7286
7287         //
7288         // There are three reasons why an interface could be in the implementation list
7289         // 1. Inherited from parent
7290         // 2. Explicitly declared in the implements list
7291         // 3. Implicitly declared through the implements list of an explicitly declared interface
7292         //
7293         // The reason these cases need to be distinguished is that an inherited interface that is
7294         // also explicitly redeclared in the implements list must be fully reimplemented using the
7295         // virtual methods of this type (thereby using matching methods in this type that may have
7296         // a different slot than an inherited method, but hidden it by name & sig); however all
7297         // implicitly redeclared interfaces should not be fully reimplemented if they were also
7298         // inherited from the parent.
7299         //
7300         // Example:
7301         //   interface I1 : I2
7302         //   class A : I1
7303         //   class B : A, I1
7304         //
7305         // In this example I1 must be fully reimplemented on B, but B can inherit the implementation
7306         // of I2.
7307         //
7308
7309         if (pCurItfEntry->IsImplementedByParent())
7310         {
7311             if (!pCurItfEntry->IsDeclaredOnType())
7312             {
7313                 fParentInterface = TRUE;
7314             }
7315         }
7316
7317         bool fEquivalentInterfaceImplementedByParent = pCurItfEntry->IsImplementedByParent();
7318         bool fEquivalentInterfaceDeclaredOnType = pCurItfEntry->IsDeclaredOnType();
7319
7320         if (pCurItfEntry->InEquivalenceSetWithMultipleEntries())
7321         {
7322             for (DWORD dwEquivalentInterface = 0;
7323                  dwEquivalentInterface < bmtInterface->dwInterfaceMapSize;
7324                  dwEquivalentInterface++)
7325             {
7326                 bmtInterfaceEntry *     pEquivItfEntry = &bmtInterface->pInterfaceMap[dwEquivalentInterface];
7327                 if (pEquivItfEntry->GetInterfaceEquivalenceSet() != pCurItfEntry->GetInterfaceEquivalenceSet())
7328                 {
7329                     // Not equivalent
7330                     continue;
7331                 }
7332                 if (pEquivItfEntry->IsImplementedByParent())
7333                 {
7334                     fEquivalentInterfaceImplementedByParent = true;
7335                 }
7336                 if (pEquivItfEntry->IsDeclaredOnType())
7337                 {
7338                     fEquivalentInterfaceDeclaredOnType = true;
7339                 }
7340
7341                 if (fEquivalentInterfaceDeclaredOnType && fEquivalentInterfaceImplementedByParent)
7342                     break;
7343             }
7344         }
7345
7346         bool fParentInterfaceEquivalent = fEquivalentInterfaceImplementedByParent && !fEquivalentInterfaceDeclaredOnType;
7347
7348         CONSISTENCY_CHECK(!fParentInterfaceEquivalent || HasParent());
7349
7350         if (fParentInterfaceEquivalent)
7351         {
7352             // In the case the fParentInterface is TRUE, virtual overrides are enough and the interface
7353             // does not have to be explicitly (re)implemented. The only exception is if the parent is
7354             // abstract, in which case an inherited interface may not be fully implemented yet.
7355             // This is an optimization that allows us to skip the more expensive slot filling in below.
7356             // Note that the check here is for fParentInterface and not for fParentInterfaceEquivalent.
7357             // This is necessary as if the interface is not actually implemented on the parent type we will
7358             // need to fill in the slot table below.
7359             if (fParentInterface && !GetParentMethodTable()->IsAbstract())
7360             {
7361                 continue;
7362             }
7363
7364             {
7365                 // We will reach here in two cases.
7366                 // 1 .The parent is abstract and the interface has been declared on the parent,
7367                 // and possibly partially implemented, so we need to populate the
7368                 // bmtInterfaceSlotImpl table for this interface with the implementation slot
7369                 // information.
7370                 // 2 .The the interface has not been declared on the parent,
7371                 // but an equivalent interface has been. So we need to populate the
7372                 // bmtInterfaceSlotImpl table for this interface with the implementation slot
7373                 // information from one of the parent equivalent interfaces. We may or may not
7374                 // find implementations for all of the methods on the interface on the parent type.
7375                 // The parent type may or may not be abstract.
7376
7377                 MethodTable::MethodDataWrapper hParentData;
7378                 CONSISTENCY_CHECK(CheckPointer(GetParentMethodTable()));
7379                 
7380                 if (rgInterfaceDispatchMapTypeIDs == NULL)
7381                 {
7382                     rgInterfaceDispatchMapTypeIDs = 
7383                         new (GetStackingAllocator()) DispatchMapTypeID[bmtInterface->dwInterfaceMapSize];
7384                 }
7385                 
7386                 if (pCurItfEntry->IsImplementedByParent())
7387                 {
7388                     UINT32 cInterfaceDuplicates;
7389                     // Compute all TypeIDs for this interface (all duplicates in the interface map)
7390                     ComputeDispatchMapTypeIDs(
7391                         pCurItfMT, 
7392                         pCurItfSubst, 
7393                         rgInterfaceDispatchMapTypeIDs, 
7394                         bmtInterface->dwInterfaceMapSize, 
7395                         &cInterfaceDuplicates);
7396                     // There cannot be more duplicates than number of interfaces
7397                     _ASSERTE(cInterfaceDuplicates <= bmtInterface->dwInterfaceMapSize);
7398                     _ASSERTE(cInterfaceDuplicates > 0);
7399                     
7400                     //#InterfaceMap_UseParentInterfaceImplementations
7401                     // We rely on the fact that interface map of parent type is subset of this type (incl. 
7402                     // duplicates), see code:#InterfaceMap_SupersetOfParent
7403                     // NOTE: This override does not cache the resulting MethodData object
7404                     hParentData = MethodTable::GetMethodData(
7405                             rgInterfaceDispatchMapTypeIDs, 
7406                             cInterfaceDuplicates, 
7407                             pCurItfMT, 
7408                             GetParentMethodTable());
7409
7410                     bmtInterfaceEntry::InterfaceSlotIterator itfSlotIt =
7411                         pCurItfEntry->IterateInterfaceSlots(GetStackingAllocator());
7412                     for (; !itfSlotIt.AtEnd(); itfSlotIt.Next())
7413                     {
7414                         itfSlotIt->Impl() = static_cast<SLOT_INDEX>
7415                             (hParentData->GetImplSlotNumber(static_cast<UINT32>(itfSlotIt.CurrentIndex())));
7416                     }
7417                 }
7418 #ifdef FEATURE_COMINTEROP
7419                 else
7420                 {
7421                     // Iterate through the methods on the interface, and if they have a slot which was filled in
7422                     // on an equivalent interface inherited from the parent fill in the appropriate slot.
7423                     // This code path is only used when there is an implicit implementation of an interface
7424                     // that was not implemented on a parent type, but there was an equivalent interface implemented
7425                     // on a parent type.
7426                     bmtInterfaceEntry::InterfaceSlotIterator itfSlotIt =
7427                         pCurItfEntry->IterateInterfaceSlots(GetStackingAllocator());
7428                     for (; !itfSlotIt.AtEnd(); itfSlotIt.Next())
7429                     {
7430                         PlaceMethodFromParentEquivalentInterfaceIntoInterfaceSlot(itfSlotIt, pCurItfEntry, &rgInterfaceDispatchMapTypeIDs, dwCurInterface);
7431                     }
7432                 }
7433 #endif // FEATURE_COMINTEROP
7434             }
7435         }
7436
7437 #ifdef FEATURE_COMINTEROP
7438         // WinRT types always use methodimpls to line up methods with interface implementations, so we do not want to allow implicit
7439         // interface implementations to kick in.   This can especially cause problems with redirected interfaces, where the underlying
7440         // runtimeclass doesn't actually implement the interfaces we claim it does.   For example, a WinRT class which implements both
7441         // IVector<int> and ICalculator will be projected as implementing IList<int> and ICalculator.  In this case, we do not want the
7442         // ICalculator Add(int) method to get lined up with the ICollection<int> Add method, since that will cause us to dispatch to the
7443         // wrong underlying COM interface.
7444         //
7445         // There are a special WinRT types in mscorlib (notably DisposableRuntimeClass) which do implement interfaces in the normal way
7446         // so we skip this check for them.  (Note that we can't use a methodimpl directly in mscorlib, since ComImport classes are
7447         // forbidden from having implementation code by the C# compiler).
7448         if (GetHalfBakedClass()->IsProjectedFromWinRT() && !GetModule()->IsSystem())
7449         {
7450             continue;
7451         }
7452 #endif // FEATURE_COMINTEROP
7453
7454         // For each method declared in this interface
7455         bmtInterfaceEntry::InterfaceSlotIterator itfSlotIt =
7456             pCurItfEntry->IterateInterfaceSlots(GetStackingAllocator());
7457         for (; !itfSlotIt.AtEnd(); ++itfSlotIt)
7458         {
7459             if (fParentInterfaceEquivalent)
7460             {
7461                 if (itfSlotIt->Impl() != INVALID_SLOT_INDEX)
7462                 {   // If this interface is not explicitly declared on this class, and the interface slot has already been
7463                     // given an implementation, then the only way to provide a new implementation is through an override
7464                     // or through a MethodImpl. This is necessary in addition to the continue statement before this for
7465                     // loop because an abstract interface can still have a partial implementation and it is necessary to
7466                     // skip those interface slots that have already been satisfied.
7467                     continue;
7468                 }
7469             }
7470
7471             BOOL                    fFoundMatchInBuildingClass = FALSE;
7472             bmtInterfaceSlotImpl &  curItfSlot = *itfSlotIt;
7473             bmtRTMethod *           pCurItfMethod = curItfSlot.Decl().AsRTMethod();
7474             const MethodSignature & curItfMethodSig = pCurItfMethod->GetMethodSignature();
7475
7476             //
7477             // First, try to find the method explicitly declared in our class
7478             //
7479
7480             DeclaredMethodIterator methIt(*this);
7481             while (methIt.Next())
7482             {
7483                 // Note that non-publics can legally be exposed via an interface, but only
7484                 // through methodImpls.
7485                 if (IsMdVirtual(methIt.Attrs()) && IsMdPublic(methIt.Attrs()))
7486                 {
7487 #ifdef _DEBUG 
7488                     if(GetHalfBakedClass()->m_fDebuggingClass && g_pConfig->ShouldBreakOnMethod(methIt.Name()))
7489                         CONSISTENCY_CHECK_MSGF(false, ("BreakOnMethodName: '%s' ", methIt.Name()));
7490 #endif // _DEBUG
7491
7492                     if (pCurItfMethod->GetMethodSignature().Equivalent(methIt->GetMethodSignature()))
7493                     {
7494                         fFoundMatchInBuildingClass = TRUE;
7495                         curItfSlot.Impl() = methIt->GetSlotIndex();
7496
7497                         DispatchMapTypeID dispatchMapTypeID =
7498                             DispatchMapTypeID::InterfaceClassID(dwCurInterface);
7499                         bmtVT->pDispatchMapBuilder->InsertMDMapping(
7500                             dispatchMapTypeID, 
7501                             static_cast<UINT32>(itfSlotIt.CurrentIndex()), 
7502                             methIt->GetMethodDesc(),
7503                             FALSE);
7504
7505                         break;
7506                     }
7507                 }
7508             } // end ... try to find method
7509
7510             //
7511             // The ECMA CLR spec states that a type will inherit interface implementations
7512             // and that explicit re-declaration of an inherited interface will try to match
7513             // only newslot methods with methods in the re-declared interface (note that
7514             // this also takes care of matching against unsatisfied interface methods in
7515             // the abstract parent type scenario).
7516             //
7517             // So, if the interface was not declared on a parent and we haven't found a
7518             // newslot method declared on this type as a match, search all remaining
7519             // public virtual methods (including overrides declared on this type) for a
7520             // match.
7521             //
7522             // Please see bug VSW577403 and VSW593884 for details of this breaking change.
7523             //
7524             if (!fFoundMatchInBuildingClass &&
7525                 !fEquivalentInterfaceImplementedByParent)
7526             {
7527                 if (HasParent())
7528                 {
7529                     // Iterate backward through the parent's method table. This is important to 
7530                     // find the most derived method.
7531                     bmtParentInfo::Iterator parentMethodIt = bmtParent->IterateSlots();
7532                     parentMethodIt.ResetToEnd();
7533                     while (parentMethodIt.Prev())
7534                     {
7535                         bmtRTMethod * pCurParentMethod = parentMethodIt->Decl().AsRTMethod();
7536                         DWORD dwAttrs = pCurParentMethod->GetDeclAttrs();
7537                         if (!IsMdVirtual(dwAttrs) || !IsMdPublic(dwAttrs))
7538                         {   // Only match mdPublic mdVirtual methods for interface implementation
7539                             continue;
7540                         }
7541
7542                         if (curItfMethodSig.Equivalent(pCurParentMethod->GetMethodSignature()))
7543                         {
7544                             fFoundMatchInBuildingClass = TRUE;
7545                             curItfSlot.Impl() = pCurParentMethod->GetSlotIndex();
7546
7547                             DispatchMapTypeID dispatchMapTypeID =
7548                                 DispatchMapTypeID::InterfaceClassID(dwCurInterface);
7549                             bmtVT->pDispatchMapBuilder->InsertMDMapping(
7550                                 dispatchMapTypeID, 
7551                                 static_cast<UINT32>(itfSlotIt.CurrentIndex()), 
7552                                 pCurParentMethod->GetMethodDesc(), 
7553                                 FALSE);
7554
7555                             break;
7556                         }
7557                     } // end ... try to find parent method
7558                 }
7559             }
7560
7561             // For type equivalent interfaces that had an equivalent interface implemented by their parent
7562             // and where the previous logic to fill in the method based on the virtual mappings on the type have
7563             // failed, we should attempt to get the mappings from the equivalent interfaces declared on parent types
7564             // of the type we are currently building.
7565 #ifdef FEATURE_COMINTEROP
7566             if (!fFoundMatchInBuildingClass && fEquivalentInterfaceImplementedByParent && !pCurItfEntry->IsImplementedByParent())
7567             {
7568                 PlaceMethodFromParentEquivalentInterfaceIntoInterfaceSlot(itfSlotIt, pCurItfEntry, &rgInterfaceDispatchMapTypeIDs, dwCurInterface);
7569             }
7570 #endif
7571         }
7572     }
7573 } // MethodTableBuilder::PlaceInterfaceMethods
7574
7575
7576 //*******************************************************************************
7577 //
7578 // Used by BuildMethodTable
7579 //
7580 // Place static fields
7581 //
7582 VOID MethodTableBuilder::PlaceRegularStaticFields()
7583 {
7584     STANDARD_VM_CONTRACT;
7585
7586     DWORD i;
7587
7588     LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Placing statics for %s\n", this->GetDebugClassName()));
7589
7590     //
7591     // Place gc refs and value types first, as they need to have handles created for them.
7592     // (Placing them together allows us to easily create the handles when Restoring the class,
7593     // and when initializing new DLS for the class.)
7594     //
7595
7596     DWORD   dwCumulativeStaticFieldPos = 0 ;
7597     DWORD   dwCumulativeStaticGCFieldPos = 0;
7598     DWORD   dwCumulativeStaticBoxFieldPos = 0;
7599
7600     // We don't need to do any calculations for the gc refs or valuetypes, as they're
7601     // guaranteed to be aligned in ModuleStaticsInfo
7602     bmtFP->NumRegularStaticFieldsOfSize[LOG2_PTRSIZE] -=
7603         bmtFP->NumRegularStaticGCBoxedFields + bmtFP->NumRegularStaticGCPointerFields;
7604
7605     // Place fields, largest first, padding so that each group is aligned to its natural size
7606     for (i = MAX_LOG2_PRIMITIVE_FIELD_SIZE; (signed int) i >= 0; i--)
7607     {
7608         // Fields of this size start at the next available location
7609         bmtFP->RegularStaticFieldStart[i] = dwCumulativeStaticFieldPos;
7610         dwCumulativeStaticFieldPos += (bmtFP->NumRegularStaticFieldsOfSize[i] << i);
7611
7612         // Reset counters for the loop after this one
7613         bmtFP->NumRegularStaticFieldsOfSize[i]    = 0;
7614     }
7615
7616
7617     if (dwCumulativeStaticFieldPos > FIELD_OFFSET_LAST_REAL_OFFSET)
7618         BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
7619
7620     DWORD dwNumHandleStatics = bmtFP->NumRegularStaticGCBoxedFields + bmtFP->NumRegularStaticGCPointerFields;
7621     if (!FitsIn<WORD>(dwNumHandleStatics))
7622     {   // Overflow.
7623         BuildMethodTableThrowException(IDS_EE_TOOMANYFIELDS);
7624     }
7625     SetNumHandleRegularStatics(static_cast<WORD>(dwNumHandleStatics));
7626
7627     if (!FitsIn<WORD>(bmtFP->NumRegularStaticGCBoxedFields))
7628     {   // Overflow.
7629         BuildMethodTableThrowException(IDS_EE_TOOMANYFIELDS);
7630     }
7631     SetNumBoxedRegularStatics(static_cast<WORD>(bmtFP->NumRegularStaticGCBoxedFields));
7632
7633     // Tell the module to give us the offsets we'll be using and commit space for us
7634     // if necessary
7635     DWORD dwNonGCOffset, dwGCOffset;
7636     GetModule()->GetOffsetsForRegularStaticData(bmtInternal->pType->GetTypeDefToken(),
7637                                                 bmtProp->fDynamicStatics,
7638                                                 GetNumHandleRegularStatics(), dwCumulativeStaticFieldPos,
7639                                                 &dwGCOffset, &dwNonGCOffset);
7640
7641     // Allocate boxed statics first ("x << LOG2_PTRSIZE" is equivalent to "x * sizeof(void *)")
7642     dwCumulativeStaticGCFieldPos = bmtFP->NumRegularStaticGCBoxedFields<<LOG2_PTRSIZE;
7643
7644     FieldDesc *pFieldDescList = GetApproxFieldDescListRaw();
7645     // Place static fields
7646     for (i = 0; i < bmtEnumFields->dwNumStaticFields - bmtEnumFields->dwNumThreadStaticFields; i++)
7647     {
7648         FieldDesc * pCurField   = &pFieldDescList[bmtEnumFields->dwNumInstanceFields+i];
7649         DWORD dwLog2FieldSize   = (DWORD)(DWORD_PTR&)pCurField->m_pMTOfEnclosingClass; // log2(field size)
7650         DWORD dwOffset          = (DWORD) pCurField->m_dwOffset; // offset or type of field
7651
7652         switch (dwOffset)
7653         {
7654         case FIELD_OFFSET_UNPLACED_GC_PTR:
7655             // Place GC reference static field
7656             pCurField->SetOffset(dwCumulativeStaticGCFieldPos + dwGCOffset);
7657             dwCumulativeStaticGCFieldPos += 1<<LOG2_PTRSIZE;
7658             LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Field placed at GC offset 0x%x\n", pCurField->GetOffset_NoLogging()));
7659
7660             break;
7661
7662         case FIELD_OFFSET_VALUE_CLASS:
7663             // Place boxed GC reference static field
7664             pCurField->SetOffset(dwCumulativeStaticBoxFieldPos + dwGCOffset);
7665             dwCumulativeStaticBoxFieldPos += 1<<LOG2_PTRSIZE;
7666             LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Field placed at GC offset 0x%x\n", pCurField->GetOffset_NoLogging()));
7667
7668             break;
7669
7670         case FIELD_OFFSET_UNPLACED:
7671             // Place non-GC static field
7672             pCurField->SetOffset(bmtFP->RegularStaticFieldStart[dwLog2FieldSize] +
7673                                  (bmtFP->NumRegularStaticFieldsOfSize[dwLog2FieldSize] << dwLog2FieldSize) +
7674                                  dwNonGCOffset);
7675             bmtFP->NumRegularStaticFieldsOfSize[dwLog2FieldSize]++;
7676             LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Field placed at non GC offset 0x%x\n", pCurField->GetOffset_NoLogging()));
7677             break;
7678
7679         default:
7680             // RVA field
7681             break;
7682         }
7683
7684         LOG((LF_CLASSLOADER, LL_INFO1000000, "Offset of %s: %i\n", pCurField->m_debugName, pCurField->GetOffset_NoLogging()));
7685     }
7686
7687     if (bmtProp->fDynamicStatics)
7688     {
7689         _ASSERTE(dwNonGCOffset == 0 ||  // no statics at all
7690                  dwNonGCOffset == OFFSETOF__DomainLocalModule__NormalDynamicEntry__m_pDataBlob); // We need space to point to the GC statics
7691         bmtProp->dwNonGCRegularStaticFieldBytes = dwCumulativeStaticFieldPos;
7692     }
7693     else
7694     {
7695         bmtProp->dwNonGCRegularStaticFieldBytes = 0; // Non dynamics shouldnt be using this
7696     }
7697     LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Static field bytes needed (0 is normal for non dynamic case)%i\n", bmtProp->dwNonGCRegularStaticFieldBytes));
7698 }
7699
7700
7701 VOID MethodTableBuilder::PlaceThreadStaticFields()
7702 {
7703     STANDARD_VM_CONTRACT;
7704
7705     DWORD i;
7706
7707     LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Placing ThreadStatics for %s\n", this->GetDebugClassName()));
7708
7709     //
7710     // Place gc refs and value types first, as they need to have handles created for them.
7711     // (Placing them together allows us to easily create the handles when Restoring the class,
7712     // and when initializing new DLS for the class.)
7713     //
7714
7715     DWORD   dwCumulativeStaticFieldPos = 0 ;
7716     DWORD   dwCumulativeStaticGCFieldPos = 0;
7717     DWORD   dwCumulativeStaticBoxFieldPos = 0;
7718
7719     // We don't need to do any calculations for the gc refs or valuetypes, as they're
7720     // guaranteed to be aligned in ModuleStaticsInfo
7721     bmtFP->NumThreadStaticFieldsOfSize[LOG2_PTRSIZE] -=
7722         bmtFP->NumThreadStaticGCBoxedFields + bmtFP->NumThreadStaticGCPointerFields;
7723
7724     // Place fields, largest first, padding so that each group is aligned to its natural size
7725     for (i = MAX_LOG2_PRIMITIVE_FIELD_SIZE; (signed int) i >= 0; i--)
7726     {
7727         // Fields of this size start at the next available location
7728         bmtFP->ThreadStaticFieldStart[i] = dwCumulativeStaticFieldPos;
7729         dwCumulativeStaticFieldPos += (bmtFP->NumThreadStaticFieldsOfSize[i] << i);
7730
7731         // Reset counters for the loop after this one
7732         bmtFP->NumThreadStaticFieldsOfSize[i]    = 0;
7733     }
7734
7735
7736     if (dwCumulativeStaticFieldPos > FIELD_OFFSET_LAST_REAL_OFFSET)
7737         BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
7738
7739     DWORD dwNumHandleStatics = bmtFP->NumThreadStaticGCBoxedFields + bmtFP->NumThreadStaticGCPointerFields;
7740     if (!FitsIn<WORD>(dwNumHandleStatics))
7741     {   // Overflow.
7742         BuildMethodTableThrowException(IDS_EE_TOOMANYFIELDS);
7743     }
7744
7745     SetNumHandleThreadStatics(static_cast<WORD>(dwNumHandleStatics));
7746
7747     if (!FitsIn<WORD>(bmtFP->NumThreadStaticGCBoxedFields))
7748     {   // Overflow.
7749         BuildMethodTableThrowException(IDS_EE_TOOMANYFIELDS);
7750     }
7751
7752     SetNumBoxedThreadStatics(static_cast<WORD>(bmtFP->NumThreadStaticGCBoxedFields));
7753
7754     // Tell the module to give us the offsets we'll be using and commit space for us
7755     // if necessary
7756     DWORD dwNonGCOffset, dwGCOffset;
7757
7758     GetModule()->GetOffsetsForThreadStaticData(bmtInternal->pType->GetTypeDefToken(),
7759                                                bmtProp->fDynamicStatics,
7760                                                GetNumHandleThreadStatics(), dwCumulativeStaticFieldPos,
7761                                                &dwGCOffset, &dwNonGCOffset);
7762
7763     // Allocate boxed statics first ("x << LOG2_PTRSIZE" is equivalent to "x * sizeof(void *)")
7764     dwCumulativeStaticGCFieldPos = bmtFP->NumThreadStaticGCBoxedFields<<LOG2_PTRSIZE;
7765
7766     FieldDesc *pFieldDescList = GetHalfBakedClass()->GetFieldDescList();
7767     // Place static fields
7768     for (i = 0; i < bmtEnumFields->dwNumThreadStaticFields; i++)
7769     {
7770         FieldDesc * pCurField   = &pFieldDescList[bmtEnumFields->dwNumInstanceFields + bmtEnumFields->dwNumStaticFields - bmtEnumFields->dwNumThreadStaticFields + i];
7771         DWORD dwLog2FieldSize   = (DWORD)(DWORD_PTR&)pCurField->m_pMTOfEnclosingClass; // log2(field size)
7772         DWORD dwOffset          = (DWORD) pCurField->m_dwOffset; // offset or type of field
7773
7774         switch (dwOffset)
7775         {
7776         case FIELD_OFFSET_UNPLACED_GC_PTR:
7777             // Place GC reference static field
7778             pCurField->SetOffset(dwCumulativeStaticGCFieldPos + dwGCOffset);
7779             dwCumulativeStaticGCFieldPos += 1<<LOG2_PTRSIZE;
7780             LOG((LF_CLASSLOADER, LL_INFO10000, "THREAD STATICS: Field placed at GC offset 0x%x\n", pCurField->GetOffset_NoLogging()));
7781
7782             break;
7783
7784         case FIELD_OFFSET_VALUE_CLASS:
7785             // Place boxed GC reference static field
7786             pCurField->SetOffset(dwCumulativeStaticBoxFieldPos + dwGCOffset);
7787             dwCumulativeStaticBoxFieldPos += 1<<LOG2_PTRSIZE;
7788             LOG((LF_CLASSLOADER, LL_INFO10000, "THREAD STATICS: Field placed at GC offset 0x%x\n", pCurField->GetOffset_NoLogging()));
7789
7790             break;
7791
7792         case FIELD_OFFSET_UNPLACED:
7793             // Place non-GC static field
7794             pCurField->SetOffset(bmtFP->ThreadStaticFieldStart[dwLog2FieldSize] +
7795                                  (bmtFP->NumThreadStaticFieldsOfSize[dwLog2FieldSize] << dwLog2FieldSize) +
7796                                  dwNonGCOffset);
7797             bmtFP->NumThreadStaticFieldsOfSize[dwLog2FieldSize]++;
7798             LOG((LF_CLASSLOADER, LL_INFO10000, "THREAD STATICS: Field placed at non GC offset 0x%x\n", pCurField->GetOffset_NoLogging()));
7799             break;
7800
7801         default:
7802             // RVA field
7803             break;
7804         }
7805
7806         LOG((LF_CLASSLOADER, LL_INFO1000000, "Offset of %s: %i\n", pCurField->m_debugName, pCurField->GetOffset_NoLogging()));
7807     }
7808
7809     if (bmtProp->fDynamicStatics)
7810     {
7811         _ASSERTE(dwNonGCOffset == 0 ||  // no thread statics at all
7812                  dwNonGCOffset == OFFSETOF__ThreadLocalModule__DynamicEntry__m_pDataBlob); // We need space to point to the GC statics
7813         bmtProp->dwNonGCThreadStaticFieldBytes = dwCumulativeStaticFieldPos;
7814     }
7815     else
7816     {
7817         bmtProp->dwNonGCThreadStaticFieldBytes = 0; // Non dynamics shouldnt be using this
7818     }
7819     LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: ThreadStatic field bytes needed (0 is normal for non dynamic case)%i\n", bmtProp->dwNonGCThreadStaticFieldBytes));
7820 }
7821
7822 //*******************************************************************************
7823 //
7824 // Used by BuildMethodTable
7825 //
7826 // Place instance fields
7827 //
7828 VOID    MethodTableBuilder::PlaceInstanceFields(MethodTable ** pByValueClassCache)
7829 {
7830     STANDARD_VM_CONTRACT;
7831
7832
7833     DWORD i;
7834
7835         //===============================================================
7836         // BEGIN: Place instance fields
7837         //===============================================================
7838
7839         FieldDesc *pFieldDescList = GetHalfBakedClass()->GetFieldDescList();
7840         DWORD   dwCumulativeInstanceFieldPos;
7841
7842         // Instance fields start right after the parent
7843         dwCumulativeInstanceFieldPos    = HasParent() ? GetParentMethodTable()->GetNumInstanceFieldBytes() : 0;
7844
7845         DWORD dwOffsetBias = 0;
7846 #ifdef FEATURE_64BIT_ALIGNMENT
7847         // On platforms where the alignment of 64-bit primitives is a requirement (but we're not guaranteed
7848         // this implicitly by the GC) field offset 0 is actually not 8-byte aligned in reference classes.
7849         // That's because all such platforms are currently 32-bit and the 4-byte MethodTable pointer pushes us
7850         // out of alignment. Ideally we'd solve this by arranging to have the object header allocated at a
7851         // 4-byte offset from an 8-byte boundary, but this is difficult to achieve for objects allocated on
7852         // the large object heap (which actually requires headers to be 8-byte aligned).
7853         //
7854         // So we adjust dwCumulativeInstanceFieldPos to account for the MethodTable* and our alignment
7855         // calculations will automatically adjust and add padding as necessary. We need to remove this
7856         // adjustment when setting the field offset in the field desc, however, since the rest of the system
7857         // expects that value to not include the MethodTable*.
7858         //
7859         // This happens only for reference classes: value type field 0 really does lie at offset 0 for unboxed
7860         // value types. We deal with boxed value types by allocating their headers mis-aligned (luckily for us
7861         // value types can never get large enough to allocate on the LOH). 
7862         if (!IsValueClass())
7863         {
7864             dwOffsetBias = TARGET_POINTER_SIZE;
7865             dwCumulativeInstanceFieldPos += dwOffsetBias;
7866         }
7867 #endif // FEATURE_64BIT_ALIGNMENT
7868
7869 #ifdef FEATURE_READYTORUN
7870         if (NeedsAlignedBaseOffset())
7871         {
7872             // READYTORUN: FUTURE: Use the minimum possible alignment, reduce padding when inheriting within same bubble
7873             DWORD dwAlignment = DATA_ALIGNMENT;
7874 #ifdef FEATURE_64BIT_ALIGNMENT
7875             if (GetHalfBakedClass()->IsAlign8Candidate())
7876                 dwAlignment = 8;
7877 #endif
7878             dwCumulativeInstanceFieldPos = (DWORD)ALIGN_UP(dwCumulativeInstanceFieldPos, dwAlignment);
7879         }
7880 #endif // FEATURE_READYTORUN
7881
7882         // place small fields first if the parent have a number of field bytes that is not aligned
7883         if (!IS_ALIGNED(dwCumulativeInstanceFieldPos, DATA_ALIGNMENT))
7884         {
7885             for (i = 0; i < MAX_LOG2_PRIMITIVE_FIELD_SIZE; i++) {
7886                 DWORD j;
7887
7888                 if (IS_ALIGNED(dwCumulativeInstanceFieldPos, size_t{ 1 } << (i + 1)))
7889                     continue;
7890
7891                 // check whether there are any bigger fields
7892                 for (j = i + 1; j <= MAX_LOG2_PRIMITIVE_FIELD_SIZE; j++) {
7893                     if (bmtFP->NumInstanceFieldsOfSize[j] != 0)
7894                         break;
7895                 }
7896                 // nothing to gain if there are no bigger fields
7897                 // (the subsequent loop will place fields from large to small fields)
7898                 if (j > MAX_LOG2_PRIMITIVE_FIELD_SIZE)
7899                     break;
7900
7901                 // check whether there are any small enough fields
7902                 for (j = i; (signed int) j >= 0; j--) {
7903                     if (bmtFP->NumInstanceFieldsOfSize[j] != 0)
7904                         break;
7905                     // TODO: since we will refuse to place GC references we should filter them out here.
7906                     // otherwise the "back-filling" process stops completely.
7907                     // (PlaceInstanceFields)
7908                     // the following code would fix the issue (a replacement for the code above this comment):
7909                     // if (bmtFP->NumInstanceFieldsOfSize[j] != 0 &&
7910                     //     (j != LOG2SLOT || bmtFP->NumInstanceFieldsOfSize[j] > bmtFP->NumInstanceGCPointerFields))
7911                     // {
7912                     //     break;
7913                     // }
7914
7915                 }
7916                 // nothing to play with if there are no smaller fields
7917                 if ((signed int) j < 0)
7918                     break;
7919                 // eventually go back and use the smaller field as filling
7920                 i = j;
7921
7922                 CONSISTENCY_CHECK(bmtFP->NumInstanceFieldsOfSize[i] != 0);
7923
7924                 j = bmtFP->FirstInstanceFieldOfSize[i];
7925
7926                 // Avoid reordering of gcfields
7927                 if (i == LOG2SLOT) {
7928                     for ( ; j < bmtEnumFields->dwNumInstanceFields; j++) {
7929                         if ((pFieldDescList[j].GetOffset_NoLogging() == FIELD_OFFSET_UNPLACED) &&
7930                             ((DWORD_PTR&)pFieldDescList[j].m_pMTOfEnclosingClass == (size_t)i))
7931                             break;
7932                     }
7933
7934                     // out of luck - can't reorder gc fields
7935                     if (j >= bmtEnumFields->dwNumInstanceFields)
7936                         break;
7937                 }
7938
7939                 // Place the field
7940                 dwCumulativeInstanceFieldPos = (DWORD)ALIGN_UP(dwCumulativeInstanceFieldPos, size_t{ 1 } << i);
7941
7942                 pFieldDescList[j].SetOffset(dwCumulativeInstanceFieldPos - dwOffsetBias);
7943                 dwCumulativeInstanceFieldPos += (1 << i);
7944
7945                 // We've placed this field now, so there is now one less of this size field to place
7946                 if (--bmtFP->NumInstanceFieldsOfSize[i] == 0)
7947                     continue;
7948
7949                 // We are done in this round if we haven't picked the first field
7950                 if (bmtFP->FirstInstanceFieldOfSize[i] != j)
7951                     continue;
7952
7953                 // Update FirstInstanceFieldOfSize[i] to point to the next such field
7954                 for (j = j+1; j < bmtEnumFields->dwNumInstanceFields; j++)
7955                 {
7956                     // The log of the field size is stored in the method table
7957                     if ((DWORD_PTR&)pFieldDescList[j].m_pMTOfEnclosingClass == (size_t)i)
7958                     {
7959                         bmtFP->FirstInstanceFieldOfSize[i] = j;
7960                         break;
7961                     }
7962                 }
7963                 _ASSERTE(j < bmtEnumFields->dwNumInstanceFields);
7964             }
7965         }
7966
7967         // Place fields, largest first
7968         for (i = MAX_LOG2_PRIMITIVE_FIELD_SIZE; (signed int) i >= 0; i--)
7969         {
7970             if (bmtFP->NumInstanceFieldsOfSize[i] == 0)
7971                 continue;
7972
7973             // Align instance fields if we aren't already
7974 #ifdef FEATURE_64BIT_ALIGNMENT
7975             DWORD dwDataAlignment = 1 << i;
7976 #else
7977             DWORD dwDataAlignment = min(1 << i, DATA_ALIGNMENT);
7978 #endif
7979             dwCumulativeInstanceFieldPos = (DWORD)ALIGN_UP(dwCumulativeInstanceFieldPos, dwDataAlignment);
7980
7981             // Fields of this size start at the next available location
7982             bmtFP->InstanceFieldStart[i] = dwCumulativeInstanceFieldPos;
7983             dwCumulativeInstanceFieldPos += (bmtFP->NumInstanceFieldsOfSize[i] << i);
7984
7985             // Reset counters for the loop after this one
7986             bmtFP->NumInstanceFieldsOfSize[i]  = 0;
7987         }
7988
7989
7990         // Make corrections to reserve space for GC Pointer Fields
7991         //
7992         // The GC Pointers simply take up the top part of the region associated
7993         // with fields of that size (GC pointers can be 64 bit on certain systems)
7994         if (bmtFP->NumInstanceGCPointerFields)
7995         {
7996             bmtFP->GCPointerFieldStart = bmtFP->InstanceFieldStart[LOG2SLOT] - dwOffsetBias;
7997             bmtFP->InstanceFieldStart[LOG2SLOT] = bmtFP->InstanceFieldStart[LOG2SLOT] + (bmtFP->NumInstanceGCPointerFields << LOG2SLOT);
7998             bmtFP->NumInstanceGCPointerFields = 0;     // reset to zero here, counts up as pointer slots are assigned below
7999         }
8000
8001         // Place instance fields - be careful not to place any already-placed fields
8002         for (i = 0; i < bmtEnumFields->dwNumInstanceFields; i++)
8003         {
8004             DWORD dwFieldSize   = (DWORD)(DWORD_PTR&)pFieldDescList[i].m_pMTOfEnclosingClass;
8005             DWORD dwOffset;
8006
8007             dwOffset = pFieldDescList[i].GetOffset_NoLogging();
8008
8009             // Don't place already-placed fields
8010             if ((dwOffset == FIELD_OFFSET_UNPLACED || dwOffset == FIELD_OFFSET_UNPLACED_GC_PTR || dwOffset == FIELD_OFFSET_VALUE_CLASS))
8011             {
8012                 if (dwOffset == FIELD_OFFSET_UNPLACED_GC_PTR)
8013                 {
8014                     pFieldDescList[i].SetOffset(bmtFP->GCPointerFieldStart + (bmtFP->NumInstanceGCPointerFields << LOG2SLOT));
8015                     bmtFP->NumInstanceGCPointerFields++;
8016                 }
8017                 else if (pFieldDescList[i].IsByValue() == FALSE) // it's a regular field
8018                 {
8019                     pFieldDescList[i].SetOffset(bmtFP->InstanceFieldStart[dwFieldSize] + (bmtFP->NumInstanceFieldsOfSize[dwFieldSize] << dwFieldSize) - dwOffsetBias);
8020                     bmtFP->NumInstanceFieldsOfSize[dwFieldSize]++;
8021                 }
8022             }
8023         }
8024
8025         DWORD dwNumGCPointerSeries;
8026         // Save Number of pointer series
8027         if (bmtFP->NumInstanceGCPointerFields)
8028             dwNumGCPointerSeries = bmtParent->NumParentPointerSeries + 1;
8029         else
8030             dwNumGCPointerSeries = bmtParent->NumParentPointerSeries;
8031
8032         // Place by value class fields last
8033         // Update the number of GC pointer series
8034         for (i = 0; i < bmtEnumFields->dwNumInstanceFields; i++)
8035         {
8036             if (pFieldDescList[i].IsByValue())
8037             {
8038                 MethodTable * pByValueMT = pByValueClassCache[i];
8039
8040                     // value classes could have GC pointers in them, which need to be pointer-size aligned
8041                     // so do this if it has not been done already
8042
8043 #if !defined(_TARGET_64BIT_) && (DATA_ALIGNMENT > 4) 
8044                 dwCumulativeInstanceFieldPos = (DWORD)ALIGN_UP(dwCumulativeInstanceFieldPos,
8045                     (pByValueMT->GetNumInstanceFieldBytes() >= DATA_ALIGNMENT) ? DATA_ALIGNMENT : TARGET_POINTER_SIZE);
8046 #else // !(!defined(_TARGET_64BIT_) && (DATA_ALIGNMENT > 4))
8047 #ifdef FEATURE_64BIT_ALIGNMENT
8048                 if (pByValueMT->RequiresAlign8())
8049                     dwCumulativeInstanceFieldPos = (DWORD)ALIGN_UP(dwCumulativeInstanceFieldPos, 8);
8050                 else
8051 #endif // FEATURE_64BIT_ALIGNMENT
8052                     dwCumulativeInstanceFieldPos = (DWORD)ALIGN_UP(dwCumulativeInstanceFieldPos, TARGET_POINTER_SIZE);
8053 #endif // !(!defined(_TARGET_64BIT_) && (DATA_ALIGNMENT > 4))
8054
8055                 pFieldDescList[i].SetOffset(dwCumulativeInstanceFieldPos - dwOffsetBias);
8056                 dwCumulativeInstanceFieldPos += pByValueMT->GetAlignedNumInstanceFieldBytes();
8057
8058                 // Add pointer series for by-value classes
8059                 dwNumGCPointerSeries += pByValueMT->ContainsPointers() ?
8060                     (DWORD)CGCDesc::GetCGCDescFromMT(pByValueMT)->GetNumSeries() : 0;
8061             }
8062         }
8063
8064             // Can be unaligned
8065         DWORD dwNumInstanceFieldBytes = dwCumulativeInstanceFieldPos - dwOffsetBias;
8066
8067         if (IsValueClass())
8068         {
8069                  // Like C++ we enforce that there can be no 0 length structures.
8070                 // Thus for a value class with no fields, we 'pad' the length to be 1
8071             if (dwNumInstanceFieldBytes == 0)
8072                 dwNumInstanceFieldBytes = 1;
8073
8074                 // The JITs like to copy full machine words,
8075                 //  so if the size is bigger than a void* round it up to minAlign
8076                 // and if the size is smaller than void* round it up to next power of two
8077             unsigned minAlign;
8078
8079 #ifdef FEATURE_64BIT_ALIGNMENT
8080             if (GetHalfBakedClass()->IsAlign8Candidate()) {
8081                 minAlign = 8;
8082             }
8083             else
8084 #endif // FEATURE_64BIT_ALIGNMENT
8085             if (dwNumInstanceFieldBytes > TARGET_POINTER_SIZE) {
8086                 minAlign = TARGET_POINTER_SIZE;
8087             }
8088             else {
8089                 minAlign = 1;
8090                 while (minAlign < dwNumInstanceFieldBytes)
8091                     minAlign *= 2;
8092             }
8093
8094             dwNumInstanceFieldBytes = (dwNumInstanceFieldBytes + minAlign-1) & ~(minAlign-1);
8095         }
8096
8097         if (dwNumInstanceFieldBytes > FIELD_OFFSET_LAST_REAL_OFFSET) {
8098             BuildMethodTableThrowException(IDS_CLASSLOAD_FIELDTOOLARGE);
8099         }
8100
8101         bmtFP->NumInstanceFieldBytes = dwNumInstanceFieldBytes;
8102
8103         bmtFP->NumGCPointerSeries = dwNumGCPointerSeries;
8104
8105         //===============================================================
8106         // END: Place instance fields
8107         //===============================================================
8108 }
8109
8110 //*******************************************************************************
8111 // this accesses the field size which is temporarily stored in m_pMTOfEnclosingClass
8112 // during class loading. Don't use any other time
8113 DWORD MethodTableBuilder::GetFieldSize(FieldDesc *pFD)
8114 {
8115     STATIC_CONTRACT_NOTHROW;
8116     STATIC_CONTRACT_GC_NOTRIGGER;
8117     STATIC_CONTRACT_FORBID_FAULT;
8118
8119         // We should only be calling this while this class is being built.
8120     _ASSERTE(GetHalfBakedMethodTable() == 0);
8121     BAD_FORMAT_NOTHROW_ASSERT(! pFD->IsByValue() || HasExplicitFieldOffsetLayout());
8122
8123     if (pFD->IsByValue())
8124         return (DWORD)(DWORD_PTR&)(pFD->m_pMTOfEnclosingClass);
8125     return (1 << (DWORD)(DWORD_PTR&)(pFD->m_pMTOfEnclosingClass));
8126 }
8127
8128 #ifdef UNIX_AMD64_ABI
8129 // checks whether the struct is enregisterable.
8130 void MethodTableBuilder::SystemVAmd64CheckForPassStructInRegister()
8131 {
8132     STANDARD_VM_CONTRACT;
8133
8134     // This method should be called for valuetypes only
8135     _ASSERTE(IsValueClass());
8136
8137     TypeHandle th(GetHalfBakedMethodTable());
8138
8139     if (th.IsTypeDesc())
8140     {
8141         // Not an enregisterable managed structure.
8142         return;
8143     }
8144
8145     DWORD totalStructSize = bmtFP->NumInstanceFieldBytes;
8146
8147     // If num of bytes for the fields is bigger than CLR_SYSTEMV_MAX_STRUCT_BYTES_TO_PASS_IN_REGISTERS
8148     // pass through stack
8149     if (totalStructSize > CLR_SYSTEMV_MAX_STRUCT_BYTES_TO_PASS_IN_REGISTERS)
8150     {
8151         LOG((LF_JIT, LL_EVERYTHING, "**** SystemVAmd64CheckForPassStructInRegister: struct %s is too big to pass in registers (%d bytes)\n",
8152                this->GetDebugClassName(), totalStructSize));
8153         return;
8154     }
8155
8156     const bool useNativeLayout = false;
8157     // Iterate through the fields and make sure they meet requirements to pass in registers
8158     SystemVStructRegisterPassingHelper helper((unsigned int)totalStructSize);
8159     if (GetHalfBakedMethodTable()->ClassifyEightBytes(&helper, 0, 0, useNativeLayout))
8160     {
8161         // All the above tests passed. It's registers passed struct!
8162         GetHalfBakedMethodTable()->SetRegPassedStruct();
8163
8164         StoreEightByteClassification(&helper);
8165     }
8166 }
8167
8168 // checks whether the struct is enregisterable.
8169 void MethodTableBuilder::SystemVAmd64CheckForPassNativeStructInRegister()
8170 {
8171     STANDARD_VM_CONTRACT;
8172     DWORD totalStructSize = 0;
8173
8174     // If not a native value type, return.
8175     if (!IsValueClass())
8176     {
8177         return;
8178     }
8179
8180     totalStructSize = GetLayoutInfo()->GetNativeSize();
8181
8182     // If num of bytes for the fields is bigger than CLR_SYSTEMV_MAX_STRUCT_BYTES_TO_PASS_IN_REGISTERS
8183     // pass through stack
8184     if (totalStructSize > CLR_SYSTEMV_MAX_STRUCT_BYTES_TO_PASS_IN_REGISTERS)
8185     {
8186         LOG((LF_JIT, LL_EVERYTHING, "**** SystemVAmd64CheckForPassNativeStructInRegister: struct %s is too big to pass in registers (%d bytes)\n",
8187             this->GetDebugClassName(), totalStructSize));
8188         return;
8189     }
8190
8191     _ASSERTE(HasLayout());
8192
8193     // Classify the native layout for this struct.
8194     const bool useNativeLayout = true;
8195     // Iterate through the fields and make sure they meet requirements to pass in registers
8196     SystemVStructRegisterPassingHelper helper((unsigned int)totalStructSize);
8197     if (GetHalfBakedMethodTable()->ClassifyEightBytes(&helper, 0, 0, useNativeLayout))
8198     {
8199         GetLayoutInfo()->SetNativeStructPassedInRegisters();
8200     }
8201 }
8202
8203 // Store the eightbyte classification into the EEClass
8204 void MethodTableBuilder::StoreEightByteClassification(SystemVStructRegisterPassingHelper* helper)
8205 {
8206     EEClass* eeClass = GetHalfBakedMethodTable()->GetClass();
8207     LoaderAllocator* pAllocator = MethodTableBuilder::GetLoaderAllocator();
8208     AllocMemTracker* pamTracker = MethodTableBuilder::GetMemTracker();
8209     EnsureOptionalFieldsAreAllocated(eeClass, pamTracker, pAllocator->GetLowFrequencyHeap());
8210     eeClass->SetEightByteClassification(helper->eightByteCount, helper->eightByteClassifications, helper->eightByteSizes);
8211 }
8212
8213 #endif // UNIX_AMD64_ABI
8214
8215 //---------------------------------------------------------------------------------------
8216 //
8217 // make sure that no object fields are overlapped incorrectly and define the
8218 // GC pointer series for the class. We are assuming that this class will always be laid out within
8219 // its enclosing class by the compiler in such a way that offset 0 will be the correct alignment
8220 // for object ref fields so we don't need to try to align it
8221 // 
8222 VOID 
8223 MethodTableBuilder::HandleExplicitLayout(
8224     MethodTable ** pByValueClassCache)
8225 {
8226     STANDARD_VM_CONTRACT;
8227
8228
8229     // Instance slice size is the total size of an instance, and is calculated as
8230     // the field whose offset and size add to the greatest number.
8231     UINT instanceSliceSize = 0;
8232     DWORD firstObjectOverlapOffset = ((DWORD)(-1));
8233
8234
8235     UINT i;
8236     for (i = 0; i < bmtMetaData->cFields; i++)
8237     {
8238         FieldDesc *pFD = bmtMFDescs->ppFieldDescList[i];
8239         if (pFD == NULL || pFD->IsStatic())
8240         {
8241             continue;
8242         }
8243
8244         UINT fieldExtent = 0;
8245         if (!ClrSafeInt<UINT>::addition(pFD->GetOffset_NoLogging(), GetFieldSize(pFD), fieldExtent))
8246         {
8247             BuildMethodTableThrowException(COR_E_OVERFLOW);
8248         }
8249
8250         if (fieldExtent > instanceSliceSize)
8251         {
8252             instanceSliceSize = fieldExtent;
8253         }
8254     }
8255
8256     CQuickBytes qb;
8257     PREFIX_ASSUME(sizeof(BYTE) == 1);
8258     BYTE *pFieldLayout = (BYTE*) qb.AllocThrows(instanceSliceSize * sizeof(BYTE));
8259     for (i=0; i < instanceSliceSize; i++)
8260     {
8261         pFieldLayout[i] = empty;
8262     }
8263
8264     // go through each field and look for invalid layout
8265     // (note that we are more permissive than what Ecma allows. We only disallow the minimum set necessary to
8266     // close security holes.)
8267     //
8268     // This is what we implment:
8269     //
8270     // 1. Verify that every OREF is on a valid alignment
8271     // 2. Verify that OREFs only overlap with other OREFs.
8272     // 3. If an OREF does overlap with another OREF, the class is marked unverifiable.
8273     // 4. If an overlap of any kind occurs, the class will be marked NotTightlyPacked (affects ValueType.Equals()).
8274     //
8275     char emptyObject[TARGET_POINTER_SIZE];
8276     char isObject[TARGET_POINTER_SIZE];
8277     for (i = 0; i < TARGET_POINTER_SIZE; i++)
8278     {
8279         emptyObject[i] = empty;
8280         isObject[i]    = oref;
8281     }
8282
8283
8284     ExplicitClassTrust explicitClassTrust;
8285
8286     UINT valueClassCacheIndex = ((UINT)(-1));
8287     UINT badOffset = 0;
8288     FieldDesc * pFD = NULL;
8289     for (i = 0; i < bmtMetaData->cFields; i++)
8290     {
8291         // Note about this loop body:
8292         //
8293         // This loop is coded to make it as hard as possible to allow a field to be trusted when it shouldn't.
8294         //
8295         // Every path in this loop body must lead to an explicit decision as to whether the field nonoverlaps,
8296         // overlaps in a verifiable fashion, overlaps in a nonverifiable fashion or overlaps in a completely illegal fashion.
8297         //
8298         // It must call fieldTrust.SetTrust() with the appropriate result. If you don't call it, fieldTrust's destructor
8299         // will intentionally default to kNone and mark the entire class illegal.
8300         //
8301         // If your result is anything but kNone (class is illegal), you must also explicitly "continue" the loop.
8302         // There is a "break" at end of this loop body that will abort the loop if you don't do this. And
8303         // if you don't finish iterating through all the fields, this function will automatically mark the entire
8304         // class illegal. This rule is a vestige of an earlier version of this function.
8305
8306         // This object's dtor will aggregate the trust decision for this field into the trust level for the class as a whole.
8307         ExplicitFieldTrustHolder fieldTrust(&explicitClassTrust);
8308
8309         pFD = bmtMFDescs->ppFieldDescList[i];
8310         if (pFD == NULL || pFD->IsStatic())
8311         {
8312             fieldTrust.SetTrust(ExplicitFieldTrust::kNonOverLayed);
8313             continue;
8314         }
8315
8316         // "i" indexes all fields, valueClassCacheIndex indexes non-static fields only. Don't get them confused!
8317         valueClassCacheIndex++;
8318
8319         if (CorTypeInfo::IsObjRef(pFD->GetFieldType()))
8320         {
8321             // Check that the ref offset is pointer aligned
8322             if ((pFD->GetOffset_NoLogging() & ((ULONG)TARGET_POINTER_SIZE - 1)) != 0)
8323             {
8324                 badOffset = pFD->GetOffset_NoLogging();
8325                 fieldTrust.SetTrust(ExplicitFieldTrust::kNone);
8326
8327                 // If we got here, OREF field was not pointer aligned. THROW.
8328                 break;
8329             }
8330             // check if overlaps another object
8331             if (memcmp((void *)&pFieldLayout[pFD->GetOffset_NoLogging()], (void *)isObject, sizeof(isObject)) == 0)
8332             {
8333                 // If we got here, an OREF overlapped another OREF. We permit this but mark the class unverifiable.
8334                 fieldTrust.SetTrust(ExplicitFieldTrust::kLegal);
8335
8336                 if (firstObjectOverlapOffset == ((DWORD)(-1)))
8337                 {
8338                     firstObjectOverlapOffset = pFD->GetOffset_NoLogging();
8339                 }
8340
8341                 continue;
8342             }
8343             // check if is empty at this point
8344             if (memcmp((void *)&pFieldLayout[pFD->GetOffset_NoLogging()], (void *)emptyObject, sizeof(emptyObject)) == 0)
8345             {
8346                 // If we got here, this OREF is overlapping no other fields (yet). Record that these bytes now contain an OREF.
8347                 memset((void *)&pFieldLayout[pFD->GetOffset_NoLogging()], oref, sizeof(isObject));
8348                 fieldTrust.SetTrust(ExplicitFieldTrust::kNonOverLayed);
8349                 continue;
8350             }
8351
8352             // If we got here, the OREF overlaps a non-OREF. THROW.
8353             badOffset = pFD->GetOffset_NoLogging();
8354             fieldTrust.SetTrust(ExplicitFieldTrust::kNone);
8355             break;
8356         }
8357         else
8358         {
8359             UINT fieldSize;
8360             if (pFD->IsByValue())
8361             {
8362                 MethodTable *pByValueMT = pByValueClassCache[valueClassCacheIndex];
8363                 if (pByValueMT->ContainsPointers())
8364                 {
8365                     if ((pFD->GetOffset_NoLogging() & ((ULONG)TARGET_POINTER_SIZE - 1)) == 0)
8366                     {
8367                         ExplicitFieldTrust::TrustLevel trust;
8368                         DWORD firstObjectOverlapOffsetInsideValueClass = ((DWORD)(-1));
8369                         trust = CheckValueClassLayout(pByValueMT, &pFieldLayout[pFD->GetOffset_NoLogging()], &firstObjectOverlapOffsetInsideValueClass);
8370                         fieldTrust.SetTrust(trust);
8371                         if (firstObjectOverlapOffsetInsideValueClass != ((DWORD)(-1)))
8372                         {
8373                             if (firstObjectOverlapOffset == ((DWORD)(-1)))
8374                             {
8375                                 firstObjectOverlapOffset = pFD->GetOffset_NoLogging() + firstObjectOverlapOffsetInsideValueClass;
8376                             }
8377                         }
8378
8379                         if (trust != ExplicitFieldTrust::kNone)
8380                         {
8381                             continue;
8382                         }
8383                         else
8384                         {
8385                             // If we got here, then an OREF inside the valuetype illegally overlapped a non-OREF field. THROW.
8386                             badOffset = pFD->GetOffset_NoLogging();
8387                             break;
8388                         }
8389                     }
8390                     // If we got here, then a valuetype containing an OREF was misaligned.
8391                     badOffset = pFD->GetOffset_NoLogging();
8392                     fieldTrust.SetTrust(ExplicitFieldTrust::kNone);
8393                     break;
8394                 }
8395                 // no pointers so fall through to do standard checking
8396                 fieldSize = pByValueMT->GetNumInstanceFieldBytes();
8397             }
8398             else
8399             {
8400                 // field size temporarily stored in pInterface field
8401                 fieldSize = GetFieldSize(pFD);
8402             }
8403
8404             // If we got here, we are trying to place a non-OREF (or a valuetype composed of non-OREFs.)
8405             // Look for any orefs under this field
8406             BYTE *loc;
8407             if ((loc = (BYTE*)memchr((void*)&pFieldLayout[pFD->GetOffset_NoLogging()], oref, fieldSize)) == NULL)
8408             {
8409                 // If we have a nonoref in the range then we are doing an overlay
8410                 if(memchr((void*)&pFieldLayout[pFD->GetOffset_NoLogging()], nonoref, fieldSize))
8411                 {
8412                     fieldTrust.SetTrust(ExplicitFieldTrust::kVerifiable);
8413                 }
8414                 else
8415                 {
8416                     fieldTrust.SetTrust(ExplicitFieldTrust::kNonOverLayed);
8417                 }
8418                 memset((void*)&pFieldLayout[pFD->GetOffset_NoLogging()], nonoref, fieldSize);
8419                 continue;
8420             }
8421
8422             // If we got here, we tried to place a non-OREF (or a valuetype composed of non-OREFs)
8423             // on top of an OREF. THROW.
8424             badOffset = (UINT)(loc - pFieldLayout);
8425             fieldTrust.SetTrust(ExplicitFieldTrust::kNone);
8426             break;
8427             // anything else is an error
8428         }
8429
8430         // We have to comment out this assert because otherwise, the compiler refuses to build because the _ASSERT is unreachable
8431         // (Thanks for nothing, compiler, that's what the assert is trying to enforce!) But the intent of the assert is correct.
8432         //_ASSERTE(!"You aren't supposed to be here. Some path inside the loop body did not execute an explicit break or continue.");
8433
8434
8435         // If we got here, some code above failed to execute an explicit "break" or "continue." This is a bug! To be safe,
8436         // we will put a catchall "break" here which will cause the typeload to abort (albeit with a probably misleading
8437         // error message.)
8438         break;
8439     } // for(;;)
8440
8441     // We only break out of the loop above if we detected an error.
8442     if (i < bmtMetaData->cFields || !explicitClassTrust.IsLegal())
8443     {
8444         ThrowFieldLayoutError(GetCl(),
8445                               GetModule(),
8446                               badOffset,
8447                               IDS_CLASSLOAD_EXPLICIT_LAYOUT);
8448     }
8449
8450     if (!explicitClassTrust.IsNonOverLayed())
8451     {
8452         SetHasOverLayedFields();
8453     }
8454
8455     if (IsBlittable() || IsManagedSequential())
8456     {
8457         // Bug 849333: We shouldn't update "bmtFP->NumInstanceFieldBytes" 
8458         // for Blittable/ManagedSequential types.  As this will break backward compatiblity
8459         // for the size of types that return true for HasExplicitFieldOffsetLayout()
8460         // 
8461         return;
8462     }
8463
8464     FindPointerSeriesExplicit(instanceSliceSize, pFieldLayout);
8465
8466     // Fixup the offset to include parent as current offsets are relative to instance slice
8467     // Could do this earlier, but it's just easier to assume instance relative for most
8468     // of the earlier calculations
8469
8470     // Instance fields start right after the parent
8471     S_UINT32 dwInstanceSliceOffset = S_UINT32(HasParent() ? GetParentMethodTable()->GetNumInstanceFieldBytes() : 0);
8472     if (bmtGCSeries->numSeries != 0)
8473     {
8474         dwInstanceSliceOffset.AlignUp(TARGET_POINTER_SIZE);
8475     }
8476     if (dwInstanceSliceOffset.IsOverflow())
8477     {
8478         // addition overflow or cast truncation
8479         BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
8480     }
8481
8482     S_UINT32 numInstanceFieldBytes = dwInstanceSliceOffset + S_UINT32(instanceSliceSize);
8483
8484     if (IsValueClass())
8485     {
8486         ULONG clstotalsize;
8487         if (FAILED(GetMDImport()->GetClassTotalSize(GetCl(), &clstotalsize)))
8488         {
8489             clstotalsize = 0;
8490         }
8491         
8492         if (clstotalsize != 0)
8493         {
8494             // size must be large enough to accomodate layout. If not, we use the layout size instead.
8495             if (!numInstanceFieldBytes.IsOverflow() && clstotalsize >= numInstanceFieldBytes.Value())
8496             {
8497                 numInstanceFieldBytes = S_UINT32(clstotalsize);
8498             }
8499         }
8500     }
8501     
8502     // The GC requires that all valuetypes containing orefs be sized to a multiple of TARGET_POINTER_SIZE.
8503     if (bmtGCSeries->numSeries != 0)
8504     {
8505         numInstanceFieldBytes.AlignUp(TARGET_POINTER_SIZE);
8506     }
8507     if (numInstanceFieldBytes.IsOverflow())
8508     {
8509         // addition overflow or cast truncation
8510         BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
8511     }
8512
8513     // Set the total size
8514     bmtFP->NumInstanceFieldBytes = numInstanceFieldBytes.Value();
8515
8516     for (i = 0; i < bmtMetaData->cFields; i++)
8517     {
8518         FieldDesc * pTempFD = bmtMFDescs->ppFieldDescList[i];
8519         if ((pTempFD == NULL) || pTempFD->IsStatic())
8520         {
8521             continue;
8522         }
8523         HRESULT hr = pTempFD->SetOffset(pTempFD->GetOffset_NoLogging() + dwInstanceSliceOffset.Value());
8524         if (FAILED(hr))
8525         {
8526             BuildMethodTableThrowException(hr, *bmtError);
8527         }
8528     }
8529 } // MethodTableBuilder::HandleExplicitLayout
8530
8531 //*******************************************************************************
8532 // make sure that no object fields are overlapped incorrectly, returns S_FALSE if
8533 // there overlap but nothing illegal, S_OK if there is no overlap
8534 /*static*/ ExplicitFieldTrust::TrustLevel MethodTableBuilder::CheckValueClassLayout(MethodTable * pMT, BYTE *pFieldLayout, DWORD *pFirstObjectOverlapOffset)
8535 {
8536     STANDARD_VM_CONTRACT;
8537
8538
8539     *pFirstObjectOverlapOffset = (DWORD)(-1);
8540
8541     // Build a layout of the value class. Don't know the sizes of all the fields easily, but
8542     // do know a) vc is already consistent so don't need to check it's overlaps and
8543     // b) size and location of all objectrefs. So build it by setting all non-oref
8544     // then fill in the orefs later
8545     UINT fieldSize = pMT->GetNumInstanceFieldBytes();
8546     CQuickBytes qb;
8547     BYTE *vcLayout = (BYTE*) qb.AllocThrows(fieldSize * sizeof(BYTE));
8548
8549     memset((void*)vcLayout, nonoref, fieldSize);
8550
8551     // use pointer series to locate the orefs
8552
8553     CGCDesc* map = CGCDesc::GetCGCDescFromMT(pMT);
8554     CGCDescSeries *pSeries = map->GetLowestSeries();
8555
8556     for (SIZE_T j = 0; j < map->GetNumSeries(); j++)
8557     {
8558         CONSISTENCY_CHECK(pSeries <= map->GetHighestSeries());
8559
8560         memset((void*)&vcLayout[pSeries->GetSeriesOffset() - OBJECT_SIZE], oref, pSeries->GetSeriesSize() + pMT->GetBaseSize());
8561         pSeries++;
8562     }
8563
8564
8565     ExplicitClassTrust explicitClassTrust;
8566
8567     for (UINT i=0; i < fieldSize; i++) {
8568
8569         ExplicitFieldTrustHolder fieldTrust(&explicitClassTrust);
8570
8571         if (vcLayout[i] == oref) {
8572             switch (pFieldLayout[i]) {
8573                 // oref <--> empty
8574                 case empty:
8575                     pFieldLayout[i] = oref;
8576                     fieldTrust.SetTrust(ExplicitFieldTrust::kNonOverLayed);
8577                     break;
8578
8579                 // oref <--> nonoref
8580                 case nonoref:
8581                     fieldTrust.SetTrust(ExplicitFieldTrust::kNone);
8582                     break;
8583
8584                 // oref <--> oref
8585                 case oref:
8586                     fieldTrust.SetTrust(ExplicitFieldTrust::kLegal);
8587                     if ((*pFirstObjectOverlapOffset) == ((DWORD)(-1)))
8588                     {
8589                         *pFirstObjectOverlapOffset = (DWORD)i;
8590                     }
8591                     break;
8592
8593                 default:
8594                     _ASSERTE(!"Can't get here.");
8595                 }
8596         } else if (vcLayout[i] == nonoref) {
8597             switch (pFieldLayout[i]) {
8598                 // nonoref <--> empty
8599                 case empty:
8600                     pFieldLayout[i] = nonoref;
8601                     fieldTrust.SetTrust(ExplicitFieldTrust::kNonOverLayed);
8602                     break;
8603
8604                 // nonoref <--> nonoref
8605                 case nonoref:
8606                     fieldTrust.SetTrust(ExplicitFieldTrust::kVerifiable);
8607                     break;
8608
8609                 // nonoref <--> oref
8610                 case oref:
8611                     fieldTrust.SetTrust(ExplicitFieldTrust::kNone);
8612                     break;
8613
8614                 default:
8615                     _ASSERTE(!"Can't get here.");
8616             }
8617         } else {
8618             _ASSERTE(!"Can't get here.");
8619         }
8620     }
8621
8622     return explicitClassTrust.GetTrustLevel();
8623 }
8624
8625
8626
8627
8628
8629
8630
8631 //*******************************************************************************
8632 void MethodTableBuilder::FindPointerSeriesExplicit(UINT instanceSliceSize,
8633                                                    BYTE *pFieldLayout)
8634 {
8635     STANDARD_VM_CONTRACT;
8636
8637
8638     // Allocate a structure to track the series. We know that the worst case is a
8639     // ref-non-ref-non, and since only ref series are recorded and non-ref series
8640     // are skipped, the max number of series is total instance size / 2 / sizeof(ref).
8641     // But watch out for the case where we have e.g. an instanceSlizeSize of 4.
8642     DWORD sz = (instanceSliceSize + (2 * TARGET_POINTER_SIZE) - 1);
8643     bmtGCSeries->pSeries = new bmtGCSeriesInfo::Series[sz/2/ TARGET_POINTER_SIZE];
8644
8645     BYTE *loc = pFieldLayout;
8646     BYTE *layoutEnd = pFieldLayout + instanceSliceSize;
8647     while (loc < layoutEnd)
8648     {
8649         // Find the next OREF entry.
8650         loc = (BYTE*)memchr((void*)loc, oref, layoutEnd-loc);
8651         if (loc == NULL)
8652         {
8653             break;
8654         }
8655
8656         // Find the next non-OREF entry
8657         BYTE *cur = loc;
8658         while(cur < layoutEnd && *cur == oref)
8659         {
8660             cur++;
8661         }
8662
8663         // so we have a GC series at loc for cur-loc bytes
8664         bmtGCSeries->pSeries[bmtGCSeries->numSeries].offset = (DWORD)(loc - pFieldLayout);
8665         bmtGCSeries->pSeries[bmtGCSeries->numSeries].len = (DWORD)(cur - loc);
8666
8667         CONSISTENCY_CHECK(IS_ALIGNED(cur - loc, TARGET_POINTER_SIZE));
8668
8669         bmtGCSeries->numSeries++;
8670         loc = cur;
8671     }
8672
8673     // Calculate the total series count including the parent, if a parent exists.
8674
8675     bmtFP->NumGCPointerSeries = bmtParent->NumParentPointerSeries + bmtGCSeries->numSeries;
8676
8677 }
8678
8679 //*******************************************************************************
8680 VOID 
8681 MethodTableBuilder::HandleGCForExplicitLayout()
8682 {
8683     STANDARD_VM_CONTRACT;
8684
8685     MethodTable *pMT = GetHalfBakedMethodTable();
8686
8687 #ifdef FEATURE_COLLECTIBLE_TYPES
8688     if (bmtFP->NumGCPointerSeries == 0 && pMT->Collectible())
8689     {
8690         // For collectible types, insert empty gc series
8691         CGCDescSeries *pSeries;
8692
8693         CGCDesc::Init( (PVOID) pMT, 1);
8694         pSeries = ((CGCDesc*)pMT)->GetLowestSeries();
8695         pSeries->SetSeriesSize( (size_t) (0) - (size_t) pMT->GetBaseSize());
8696         pSeries->SetSeriesOffset(OBJECT_SIZE);
8697     }
8698     else
8699 #endif // FEATURE_COLLECTIBLE_TYPES
8700     if (bmtFP->NumGCPointerSeries != 0)
8701     {
8702         pMT->SetContainsPointers();
8703
8704         // Copy the pointer series map from the parent
8705         CGCDesc::Init( (PVOID) pMT, bmtFP->NumGCPointerSeries );
8706         if (bmtParent->NumParentPointerSeries != 0)
8707         {
8708             size_t ParentGCSize = CGCDesc::ComputeSize(bmtParent->NumParentPointerSeries);
8709             memcpy( (PVOID) (((BYTE*) pMT) - ParentGCSize),  (PVOID) (((BYTE*) GetParentMethodTable()) - ParentGCSize), ParentGCSize - sizeof(UINT) );
8710
8711         }
8712
8713         UINT32 dwInstanceSliceOffset = AlignUp(HasParent() ? GetParentMethodTable()->GetNumInstanceFieldBytes() : 0, TARGET_POINTER_SIZE);
8714
8715         // Build the pointer series map for this pointers in this instance
8716         CGCDescSeries *pSeries = ((CGCDesc*)pMT)->GetLowestSeries();
8717         for (UINT i=0; i < bmtGCSeries->numSeries; i++) {
8718             // See gcdesc.h for an explanation of why we adjust by subtracting BaseSize
8719             BAD_FORMAT_NOTHROW_ASSERT(pSeries <= CGCDesc::GetCGCDescFromMT(pMT)->GetHighestSeries());
8720
8721             pSeries->SetSeriesSize( (size_t) bmtGCSeries->pSeries[i].len - (size_t) pMT->GetBaseSize() );
8722             pSeries->SetSeriesOffset(bmtGCSeries->pSeries[i].offset + OBJECT_SIZE + dwInstanceSliceOffset);
8723             pSeries++;
8724         }
8725     }
8726
8727     delete [] bmtGCSeries->pSeries;
8728     bmtGCSeries->pSeries = NULL;
8729 } // MethodTableBuilder::HandleGCForExplicitLayout
8730
8731 static 
8732 BOOL 
8733 InsertMethodTable(
8734     MethodTable  *pNew, 
8735     MethodTable **pArray, 
8736     DWORD         nArraySizeMax, 
8737     DWORD        *pNumAssigned)
8738 {
8739     LIMITED_METHOD_CONTRACT;
8740
8741     for (DWORD j = 0; j < (*pNumAssigned); j++)
8742     {
8743         if (pNew == pArray[j])
8744         {
8745 #ifdef _DEBUG
8746             LOG((LF_CLASSLOADER, LL_INFO1000, "GENERICS: Found duplicate interface %s (%p) at position %d out of %d\n", pNew->GetDebugClassName(), pNew, j, *pNumAssigned));
8747 #endif
8748             return pNew->HasInstantiation(); // bail out - we found a duplicate instantiated interface
8749         }
8750         else
8751         {
8752 #ifdef _DEBUG 
8753             LOG((LF_CLASSLOADER, LL_INFO1000, "  GENERICS: InsertMethodTable ignored interface %s (%p) at position %d out of %d\n", pArray[j]->GetDebugClassName(), pArray[j], j, *pNumAssigned));
8754 #endif
8755         }
8756     }
8757     if (*pNumAssigned >= nArraySizeMax)
8758     {
8759         LOG((LF_CLASSLOADER, LL_INFO1000, "GENERICS: Found interface %s (%p) exceeding size %d of interface array\n", pNew->GetDebugClassName(), pNew, nArraySizeMax));
8760         return TRUE;
8761     }
8762     LOG((LF_CLASSLOADER, LL_INFO1000, "GENERICS: Inserting interface %s (%p) at position %d\n", pNew->GetDebugClassName(), pNew, *pNumAssigned));
8763     pArray[(*pNumAssigned)++] = pNew;
8764     return FALSE;
8765 } // InsertMethodTable
8766
8767
8768 //*******************************************************************************
8769 // --------------------------------------------------------------------------------------------
8770 // Copy virtual slots inherited from parent:
8771 //
8772 // In types created at runtime, inherited virtual slots are initialized using approximate parent 
8773 // during method table building. This method will update them based on the exact parent.
8774 // In types loaded from NGen image, inherited virtual slots from cross-module parents are not 
8775 // initialized. This method will initialize them based on the actually loaded exact parent
8776 // if necessary.
8777 /* static */
8778 void MethodTableBuilder::CopyExactParentSlots(MethodTable *pMT, MethodTable *pApproxParentMT)
8779 {
8780     CONTRACTL
8781     {
8782         STANDARD_VM_CHECK;
8783         PRECONDITION(CheckPointer(pMT));
8784     }
8785     CONTRACTL_END;
8786
8787     if (pMT->IsZapped())
8788         return;
8789
8790     DWORD nParentVirtuals = pMT->GetNumParentVirtuals();
8791     if (nParentVirtuals == 0)
8792         return;
8793
8794     _ASSERTE(nParentVirtuals == pApproxParentMT->GetNumVirtuals());
8795
8796     //
8797     // Update all inherited virtual slots to match exact parent
8798     //
8799
8800     if (!pMT->IsCanonicalMethodTable())
8801     {
8802         //
8803         // Copy all slots for non-canonical methodtables to avoid touching methoddescs.
8804         //
8805         MethodTable * pCanonMT = pMT->GetCanonicalMethodTable();
8806
8807         // Do not write into vtable chunks shared with parent. It would introduce race 
8808         // with code:MethodDesc::SetStableEntryPointInterlocked.
8809         //
8810         // Non-canonical method tables either share everything or nothing so it is sufficient to check
8811         // just the first indirection to detect sharing.
8812         if (pMT->GetVtableIndirections()[0].GetValueMaybeNull() != pCanonMT->GetVtableIndirections()[0].GetValueMaybeNull())
8813         {
8814             MethodTable::MethodDataWrapper hCanonMTData(MethodTable::GetMethodData(pCanonMT, FALSE));
8815             for (DWORD i = 0; i < nParentVirtuals; i++)
8816             {
8817                 pMT->CopySlotFrom(i, hCanonMTData, pCanonMT);
8818             }
8819         }
8820     }
8821     else
8822     {
8823         MethodTable::MethodDataWrapper hMTData(MethodTable::GetMethodData(pMT, FALSE));
8824
8825         MethodTable * pParentMT = pMT->GetParentMethodTable();
8826         MethodTable::MethodDataWrapper hParentMTData(MethodTable::GetMethodData(pParentMT, FALSE));
8827
8828         for (DWORD i = 0; i < nParentVirtuals; i++)
8829         {
8830             // fix up wrongly-inherited method descriptors
8831             MethodDesc* pMD = hMTData->GetImplMethodDesc(i);
8832             CONSISTENCY_CHECK(CheckPointer(pMD));
8833             CONSISTENCY_CHECK(pMD == pMT->GetMethodDescForSlot(i));
8834
8835             if (pMD->GetMethodTable() == pMT)
8836                 continue;
8837
8838             // We need to re-inherit this slot from the exact parent.
8839
8840             DWORD indirectionIndex = MethodTable::GetIndexOfVtableIndirection(i);
8841             if (pMT->GetVtableIndirections()[indirectionIndex].GetValueMaybeNull() == pApproxParentMT->GetVtableIndirections()[indirectionIndex].GetValueMaybeNull())
8842             {
8843                 // The slot lives in a chunk shared from the approximate parent MT
8844                 // If so, we need to change to share the chunk from the exact parent MT
8845
8846 #ifdef FEATURE_PREJIT
8847                 _ASSERTE(MethodTable::CanShareVtableChunksFrom(pParentMT, pMT->GetLoaderModule(), Module::GetPreferredZapModuleForMethodTable(pMT)));
8848 #else
8849                 _ASSERTE(MethodTable::CanShareVtableChunksFrom(pParentMT, pMT->GetLoaderModule()));
8850 #endif
8851
8852                 pMT->GetVtableIndirections()[indirectionIndex].SetValueMaybeNull(pParentMT->GetVtableIndirections()[indirectionIndex].GetValueMaybeNull());
8853
8854                 i = MethodTable::GetEndSlotForVtableIndirection(indirectionIndex, nParentVirtuals) - 1;
8855                 continue;
8856             }
8857
8858             // The slot lives in an unshared chunk. We need to update the slot contents
8859             pMT->CopySlotFrom(i, hParentMTData, pParentMT);
8860         }
8861     }
8862 } // MethodTableBuilder::CopyExactParentSlots
8863
8864 //*******************************************************************************
8865 /* static */
8866 void 
8867 MethodTableBuilder::LoadExactInterfaceMap(MethodTable *pMT)
8868 {
8869     CONTRACTL
8870     {
8871         STANDARD_VM_CHECK;
8872         PRECONDITION(CheckPointer(pMT));
8873     }
8874     CONTRACTL_END;
8875
8876     BOOL hasInstantiatedInterfaces = FALSE;
8877     MethodTable::InterfaceMapIterator it = pMT->IterateInterfaceMap();
8878     while (it.Next())
8879     {
8880         if (it.GetInterface()->HasInstantiation())
8881         {
8882             hasInstantiatedInterfaces = TRUE;
8883             break;
8884         }
8885     }
8886
8887     // If we have some instantiated interfaces, then we have lots more work to do...
8888
8889     // In the worst case we have to use the metadata to
8890     //  (a) load the exact interfaces and determine the order in which they
8891     //      go.  We do those by re-running the interface layout algorithm
8892     //      and using metadata-comparisons to place interfaces in the list.
8893     //  (b) do a check to see if any ambiguity in the interface dispatch map is introduced
8894     //      by the instantiation
8895     // See code:#LoadExactInterfaceMap_Algorithm2
8896     //
8897     // However, we can do something simpler: we just use
8898     // the loaded interface method tables to determine ordering.  This can be done
8899     // if there are no duplicate instantiated interfaces in the interface
8900     // set.
8901     // See code:#LoadExactInterfaceMap_Algorithm1.
8902
8903     if (!hasInstantiatedInterfaces)
8904     {
8905         return;
8906     }
8907
8908     HRESULT hr;
8909     TypeHandle thisTH(pMT);
8910     SigTypeContext typeContext(thisTH);
8911     MethodTable *pParentMT = pMT->GetParentMethodTable();
8912
8913     //#LoadExactInterfaceMap_Algorithm1
8914     // Exact interface instantiation loading TECHNIQUE 1.
8915     // (a) For interfaces inherited from an instantiated parent class, just copy down from exact parent
8916     // (b) Grab newly declared interfaces by loading and then copying down all their inherited parents
8917     // (c) But check for any exact duplicates along the way
8918     // (d) If no duplicates then we can use the computed interface map we've created
8919     // (e) If duplicates found then use the slow metadata-based technique code:#LoadExactInterfaceMap_Algorithm2
8920     DWORD nInterfacesCount = pMT->GetNumInterfaces();
8921     MethodTable **pExactMTs = (MethodTable**) _alloca(sizeof(MethodTable *) * nInterfacesCount);
8922     DWORD nAssigned = 0;
8923     BOOL duplicates = false;
8924     if (pParentMT != NULL)
8925     {
8926         MethodTable::InterfaceMapIterator parentIt = pParentMT->IterateInterfaceMap();
8927         while (parentIt.Next())
8928         {
8929             duplicates |= InsertMethodTable(parentIt.GetInterface(), pExactMTs, nInterfacesCount, &nAssigned);
8930         }
8931     }
8932     InterfaceImplEnum ie(pMT->GetModule(), pMT->GetCl(), NULL);
8933     while ((hr = ie.Next()) == S_OK)
8934     {
8935         MethodTable *pNewIntfMT = ClassLoader::LoadTypeDefOrRefOrSpecThrowing(pMT->GetModule(),
8936                                                                               ie.CurrentToken(),
8937                                                                               &typeContext,
8938                                                                               ClassLoader::ThrowIfNotFound,
8939                                                                               ClassLoader::FailIfUninstDefOrRef,
8940                                                                               ClassLoader::LoadTypes,
8941                                                                               CLASS_LOAD_EXACTPARENTS,
8942                                                                               TRUE).GetMethodTable();
8943
8944         duplicates |= InsertMethodTable(pNewIntfMT, pExactMTs, nInterfacesCount, &nAssigned);
8945         MethodTable::InterfaceMapIterator intIt = pNewIntfMT->IterateInterfaceMap();
8946         while (intIt.Next())
8947         {
8948             duplicates |= InsertMethodTable(intIt.GetInterface(), pExactMTs, nInterfacesCount, &nAssigned);
8949         }
8950     }
8951     if (FAILED(hr))
8952     {
8953         pMT->GetAssembly()->ThrowTypeLoadException(pMT->GetMDImport(), pMT->GetCl(), IDS_CLASSLOAD_BADFORMAT);
8954     }
8955 #ifdef _DEBUG 
8956     duplicates |= EEConfig::GetConfigDWORD_DontUse_(CLRConfig::INTERNAL_AlwaysUseMetadataInterfaceMapLayout, FALSE);
8957     
8958     //#InjectInterfaceDuplicates_LoadExactInterfaceMap
8959     // If we are injecting duplicates also for non-generic interfaces in check builds, we have to use 
8960     // algorithm code:#LoadExactInterfaceMap_Algorithm2.
8961     // Has to be in sync with code:#InjectInterfaceDuplicates_Main.
8962     duplicates |= pMT->Debug_HasInjectedInterfaceDuplicates();
8963 #endif
8964     CONSISTENCY_CHECK(duplicates || (nAssigned == pMT->GetNumInterfaces()));
8965     if (duplicates)
8966     {
8967         //#LoadExactInterfaceMap_Algorithm2
8968         // Exact interface instantiation loading TECHNIQUE 2 - The exact instantiation has caused some duplicates to
8969         // appear in the interface map!  This may not be an error: if the duplicates
8970         // were ones that arose because because of inheritance from
8971         // a parent type then we accept that.  For example
8972         //     class C<T> : I<T>
8973         //     class D<T> : C<T>, I<string>
8974         // is acceptable even when loading D<string>.  Note that in such a case
8975         // there will be two entries for I<string> in the final interface map for D<string>.
8976         // For dispatch the mappings in D take precedence.
8977         //
8978         // However we consider it an error if there is real ambiguity within
8979         // the interface definitions within the one class, e.g.
8980         //     class E<T> : I<T>, I<string>
8981         // In this situation it is not defined how to dispatch calls to I<string>: would
8982         // we use the bindings for I<T> or I<string>?
8983         //
8984         // Because we may had duplicates the interface map we created above may not
8985         // be the correct one: for example for D<string> above we would have computed
8986         // a map with only one entry.  This is incorrect: an exact instantiation's interface
8987         // map must have entries that match the ordering of the interface map in the generic case
8988         // (this is because code:#InterfaceMap_SupersetOfParent).
8989         //
8990         // So, in order to determine how to place the interfaces we need go back to
8991         // the metadata. We also do this to check if the presence of duplicates
8992         // has caused any potential ambiguity, i.e. the E<string> case above.
8993
8994         // First we do a GetCheckpoint for the thread-based allocator.  ExpandExactInheritedInterfaces allocates substitution chains
8995         // on the thread allocator rather than on the stack.
8996         Thread * pThread = GetThread();
8997         CheckPointHolder cph(pThread->m_MarshalAlloc.GetCheckpoint()); //hold checkpoint for autorelease
8998
8999         // ***********************************************************
9000         // ****** This must be consistent with code:ExpandApproxInterface etc. *******
9001         //
9002         // The correlation to ExpandApproxInterfaces etc. simply drops out by how we
9003         // traverse interfaces.
9004         // ***********************************************************
9005
9006         bmtExactInterfaceInfo bmtExactInterface;
9007         bmtExactInterface.pInterfaceSubstitution = new (&pThread->m_MarshalAlloc) Substitution[pMT->GetNumInterfaces()];
9008         bmtExactInterface.pExactMTs = pExactMTs;
9009         bmtExactInterface.nAssigned = 0;
9010         bmtExactInterface.typeContext = typeContext;
9011
9012         // Do the interfaces inherited from a parent class
9013         if ((pParentMT != NULL) && (pParentMT->GetNumInterfaces() > 0))
9014         {
9015             Substitution * pParentSubstForTypeLoad = new (&pThread->m_MarshalAlloc) Substitution(
9016                 pMT->GetSubstitutionForParent(NULL));
9017             Substitution * pParentSubstForComparing = new (&pThread->m_MarshalAlloc) Substitution(
9018                 pMT->GetSubstitutionForParent(NULL));
9019             ExpandExactInheritedInterfaces(
9020                 &bmtExactInterface, 
9021                 pParentMT, 
9022                 pParentSubstForTypeLoad, 
9023                 pParentSubstForComparing);
9024         }
9025 #ifdef _DEBUG
9026         //#ExactInterfaceMap_SupersetOfParent
9027         // Check that parent's interface map is subset of this interface map
9028         // See code:#InterfaceMap_SupersetOfParent
9029         {
9030             _ASSERTE(pParentMT->GetNumInterfaces() == bmtExactInterface.nAssigned);
9031             
9032             MethodTable::InterfaceMapIterator parentInterfacesIterator = pParentMT->IterateInterfaceMap();
9033             UINT32 nInterfaceIndex = 0;
9034             while (parentInterfacesIterator.Next())
9035             {
9036                 if (pMT->IsSharedByGenericInstantiations())
9037                 {   // The type is a canonical instantiation (contains _Canon)
9038                     // The interface instantiations of parent can be different (see 
9039                     // code:#InterfaceMap_CanonicalSupersetOfParent), therefore we cannot compare 
9040                     // MethodTables
9041                     _ASSERTE(parentInterfacesIterator.GetInterfaceInfo()->GetApproxMethodTable(pParentMT->GetLoaderModule())->HasSameTypeDefAs(
9042                         bmtExactInterface.pExactMTs[nInterfaceIndex]));
9043                 }
9044                 else
9045                 {   // It is not canonical instantiation, we can compare MethodTables
9046                     _ASSERTE(parentInterfacesIterator.GetInterface() == bmtExactInterface.pExactMTs[nInterfaceIndex]);
9047                 }
9048                 nInterfaceIndex++;
9049             }
9050             _ASSERTE(nInterfaceIndex == bmtExactInterface.nAssigned);
9051         }
9052 #endif //_DEBUG
9053
9054         // If there are any __Canon instances in the type argument list, then we defer the
9055         // ambiguity checking until an exact instantiation.
9056         if (!pMT->IsSharedByGenericInstantiations())
9057         {
9058             // There are no __Canon types in the instantiation, so do ambiguity check.
9059             bmtInterfaceAmbiguityCheckInfo bmtCheckInfo;
9060             bmtCheckInfo.pMT = pMT;
9061             bmtCheckInfo.ppInterfaceSubstitutionChains = new (&pThread->m_MarshalAlloc) Substitution *[pMT->GetNumInterfaces()];
9062             bmtCheckInfo.ppExactDeclaredInterfaces = new (&pThread->m_MarshalAlloc) MethodTable *[pMT->GetNumInterfaces()];
9063             bmtCheckInfo.nAssigned = 0;
9064             bmtCheckInfo.typeContext = typeContext;
9065             MethodTableBuilder::InterfacesAmbiguityCheck(&bmtCheckInfo, pMT->GetModule(), pMT->GetCl(), NULL);
9066         }
9067
9068         // OK, there is no ambiguity amongst the instantiated interfaces declared on this class.
9069         MethodTableBuilder::ExpandExactDeclaredInterfaces(
9070             &bmtExactInterface, 
9071             pMT->GetModule(), 
9072             pMT->GetCl(), 
9073             NULL, 
9074             NULL 
9075             COMMA_INDEBUG(pMT));
9076         CONSISTENCY_CHECK(bmtExactInterface.nAssigned == pMT->GetNumInterfaces());
9077         
9078         // We cannot process interface duplicates on types with __Canon. The duplicates are processed on 
9079         // exact types only
9080         if (!pMT->IsSharedByGenericInstantiations())
9081         {
9082             // Process all pairs of duplicates in the interface map:
9083             //     i.e. If there are 3 duplicates of the same interface at indexes: i1, i2 and i3, then 
9084             //     process pairs of indexes [i1,i2], [i1,i3] and [i2,i3].
9085             //  - Update 'declared on type' flag for those interfaces which duplicate is 'declared on type'
9086             //  - Check interface method implementation ambiguity code:#DuplicateInterface_MethodAmbiguity
9087             for (DWORD nOriginalIndex = 0; nOriginalIndex < nInterfacesCount; nOriginalIndex++)
9088             {
9089                 // Search for duplicates further in the interface map
9090                 for (DWORD nDuplicateIndex = nOriginalIndex + 1; nDuplicateIndex < nInterfacesCount; nDuplicateIndex++)
9091                 {
9092                     if (pExactMTs[nOriginalIndex] != pExactMTs[nDuplicateIndex])
9093                     {   // It's not a duplicate of original interface, skip it
9094                         continue;
9095                     }
9096                     // We found a duplicate
9097                     
9098                     // Set 'declared on type' flag if either original or duplicate interface is 
9099                     // 'declared on type'
9100                     if (pMT->IsInterfaceDeclaredOnClass(nOriginalIndex) || 
9101                         pMT->IsInterfaceDeclaredOnClass(nDuplicateIndex))
9102                     {
9103                         // 
9104                         // Note that both checks are needed:
9105                         //     A<T> : I<T>
9106                         //     B<T,U> : A<T>, I<U>
9107                         //     C<T,U> : B<T,U>, I<T>   // Reimplements interface from A<T>
9108                         // After code:BuildMethodTableThrowing algorithm, this will happen:
9109                         // B<int,int> will have interface map similar to B<T,U>:
9110                         //     I<int> ... not 'declared on type'
9111                         //     I<int> ... 'declared on type'
9112                         // C<int,int> will have interface map similar to C<T,U>:
9113                         //     I<int> ... 'declared on type'
9114                         //     I<int> ... not 'declared on type'
9115                         // 
9116                         
9117                         pMT->SetInterfaceDeclaredOnClass(nOriginalIndex);
9118                         pMT->SetInterfaceDeclaredOnClass(nDuplicateIndex);
9119                     }
9120                     
9121                     //#DuplicateInterface_MethodAmbiguity
9122                     // 
9123                     // In the ideal world we would now check for interface method implementation 
9124                     // ambiguity in the instantiation, but that would be a technical breaking change 
9125                     // (against 2.0 RTM/SP1).
9126                     // Therefore we ALLOW when interface method is implemented twice through this 
9127                     // original and duplicate interface.
9128                     // 
9129                     // This ambiguity pattern is therefore ALLOWED (can be expressed only in IL, not in C#):
9130                     //     I<T>
9131                     //         void Print(T t);
9132                     //     A<T> : I<T>    // abstract class
9133                     //     B<T,U> : A<T>, I<U>
9134                     //         void Print(T t) { ... }
9135                     //         void Print(U u) { ... }
9136                     //     Now B<int,int> has 2 implementations of I<int>.Print(int), while B<int,char> is 
9137                     //     fine. Therefore an instantiation can introduce ambiguity.
9138                     
9139 #if 0 // Removing this code for now as it is a technical breaking change (against CLR 2.0 RTM/SP1).
9140       // We might decide later that we want to take this breaking change.
9141                     // 
9142                     // Note that dispatch map entries are sorted by interface index and then interface 
9143                     // method slot index.
9144                     // 
9145                     DispatchMapTypeID originalTypeID = DispatchMapTypeID::InterfaceClassID(nOriginalIndex);
9146                     DispatchMap::EncodedMapIterator originalIt(pMT);
9147                     // Find first entry for original interface
9148                     while (originalIt.IsValid())
9149                     {
9150                         DispatchMapEntry *pEntry = originalIt.Entry();
9151                         if (pEntry->GetTypeID().ToUINT32() >= originalTypeID.ToUINT32())
9152                         {   // Found the place where original interface entries should be (dispatch map is 
9153                             // sorted)
9154                             break;
9155                         }
9156                         originalIt.Next();
9157                     }
9158                     
9159                     DispatchMapTypeID duplicateTypeID = DispatchMapTypeID::InterfaceClassID(nDuplicateIndex);
9160                     DispatchMap::EncodedMapIterator duplicateIt(pMT);
9161                     // Find first entry for duplicate interface
9162                     while (duplicateIt.IsValid())
9163                     {
9164                         DispatchMapEntry *pEntry = duplicateIt.Entry();
9165                         if (pEntry->GetTypeID().ToUINT32() >= duplicateTypeID.ToUINT32())
9166                         {   // Found the place where original interface entries should be (dispatch map is 
9167                             // sorted)
9168                             break;
9169                         }
9170                         duplicateIt.Next();
9171                     }
9172                     
9173                     // Compare original and duplicate interface entries in the dispatch map if they contain 
9174                     // different implementation for the same interface method
9175                     for (;;)
9176                     {
9177                         if (!originalIt.IsValid() || !duplicateIt.IsValid())
9178                         {   // We reached end of one dispatch map iterator
9179                             break;
9180                         }
9181                         DispatchMapEntry *pOriginalEntry = originalIt.Entry();
9182                         if (pOriginalEntry->GetTypeID().ToUINT32() != originalTypeID.ToUINT32())
9183                         {   // We reached behind original interface entries
9184                             break;
9185                         }
9186                         DispatchMapEntry *pDuplicateEntry = duplicateIt.Entry();
9187                         if (pDuplicateEntry->GetTypeID().ToUINT32() != duplicateTypeID.ToUINT32())
9188                         {   // We reached behind duplicate interface entries
9189                             break;
9190                         }
9191                         
9192                         if (pOriginalEntry->GetSlotNumber() == pDuplicateEntry->GetSlotNumber())
9193                         {   // Found duplicate implementation of interface method
9194                             if (pOriginalEntry->GetTargetSlotNumber() != pDuplicateEntry->GetTargetSlotNumber())
9195                             {   // Implementation of the slots is different
9196                                 bmtErrorInfo bmtError;
9197                                 
9198                                 bmtError.pModule = pMT->GetModule();
9199                                 bmtError.cl = pMT->GetCl();
9200                                 bmtError.resIDWhy = IDS_CLASSLOAD_MI_MULTIPLEOVERRIDES;
9201                                 bmtError.szMethodNameForError = NULL;
9202                                 bmtError.pThrowable = NULL;
9203                                 
9204                                 MethodDesc *pMD = pMT->GetMethodDescForSlot(pDuplicateEntry->GetTargetSlotNumber());
9205                                 bmtError.dMethodDefInError = pMD->GetMemberDef();
9206                                 
9207                                 BuildMethodTableThrowException(COR_E_TYPELOAD, bmtError);
9208                             }
9209                             // The method is implemented by the same slot on both interfaces (original and 
9210                             // duplicate)
9211                             
9212                             // Process next dispatch map entry
9213                             originalIt.Next();
9214                             duplicateIt.Next();
9215                             continue;
9216                         }
9217                         // Move iterator representing smaller interface method slot index (the dispatch map 
9218                         // is sorted by slot indexes)
9219                         if (pOriginalEntry->GetSlotNumber() < pDuplicateEntry->GetSlotNumber())
9220                         {
9221                             originalIt.Next();
9222                             continue;
9223                         }
9224                         _ASSERTE(pOriginalEntry->GetSlotNumber() > pDuplicateEntry->GetSlotNumber());
9225                         duplicateIt.Next();
9226                     }
9227 #endif //0
9228                 }
9229                 // All duplicates of this original interface were processed
9230             }
9231             // All pairs of duplicates in the interface map are processed
9232         }
9233     }
9234     // Duplicates in the interface map are resolved
9235     
9236     // OK, if we've got this far then pExactMTs should now hold the array of exact instantiated interfaces.
9237     MethodTable::InterfaceMapIterator thisIt = pMT->IterateInterfaceMap();
9238     DWORD i = 0;
9239     while (thisIt.Next())
9240     {
9241 #ifdef _DEBUG 
9242         MethodTable*pOldMT = thisIt.GetInterface();
9243         MethodTable *pNewMT = pExactMTs[i];
9244         CONSISTENCY_CHECK(pOldMT->HasSameTypeDefAs(pNewMT));
9245 #endif // _DEBUG
9246         thisIt.SetInterface(pExactMTs[i]);
9247         i++;
9248     }
9249
9250 } // MethodTableBuilder::LoadExactInterfaceMap
9251
9252 //*******************************************************************************
9253 void 
9254 MethodTableBuilder::ExpandExactInheritedInterfaces(
9255     bmtExactInterfaceInfo * bmtInfo, 
9256     MethodTable *           pMT, 
9257     const Substitution *    pSubstForTypeLoad, 
9258     Substitution *          pSubstForComparing)
9259 {
9260     STANDARD_VM_CONTRACT;
9261
9262     MethodTable *pParentMT = pMT->GetParentMethodTable();
9263     
9264     // Backup type's substitution chain for comparing interfaces
9265     Substitution substForComparingBackup = *pSubstForComparing;
9266     // Make type an open type for comparing interfaces
9267     *pSubstForComparing = Substitution();
9268     
9269     if (pParentMT)
9270     {
9271         // Chain parent's substitution for exact type load
9272         Substitution * pParentSubstForTypeLoad = new (&GetThread()->m_MarshalAlloc) Substitution(
9273             pMT->GetSubstitutionForParent(pSubstForTypeLoad));
9274         
9275         // Chain parent's substitution for comparing interfaces (note that this type is temporarily 
9276         // considered as open type)
9277         Substitution * pParentSubstForComparing = new (&GetThread()->m_MarshalAlloc) Substitution(
9278             pMT->GetSubstitutionForParent(pSubstForComparing));
9279         
9280         ExpandExactInheritedInterfaces(
9281             bmtInfo, 
9282             pParentMT, 
9283             pParentSubstForTypeLoad, 
9284             pParentSubstForComparing);
9285     }
9286     ExpandExactDeclaredInterfaces(
9287         bmtInfo, 
9288         pMT->GetModule(), 
9289         pMT->GetCl(), 
9290         pSubstForTypeLoad, 
9291         pSubstForComparing 
9292         COMMA_INDEBUG(pMT));
9293     
9294     // Restore type's subsitution chain for comparing interfaces
9295     *pSubstForComparing = substForComparingBackup;
9296 } // MethodTableBuilder::ExpandExactInheritedInterfaces
9297
9298 //*******************************************************************************
9299 /* static */
9300 void 
9301 MethodTableBuilder::ExpandExactDeclaredInterfaces(
9302     bmtExactInterfaceInfo *     bmtInfo, 
9303     Module *                    pModule, 
9304     mdToken                     typeDef, 
9305     const Substitution *        pSubstForTypeLoad, 
9306     Substitution *              pSubstForComparing 
9307     COMMA_INDEBUG(MethodTable * dbg_pClassMT))
9308 {
9309     STANDARD_VM_CONTRACT;
9310
9311     HRESULT hr;
9312     InterfaceImplEnum ie(pModule, typeDef, NULL);
9313     while ((hr = ie.Next()) == S_OK)
9314     {
9315         MethodTable * pInterface = ClassLoader::LoadTypeDefOrRefOrSpecThrowing(
9316             pModule, 
9317             ie.CurrentToken(), 
9318             &bmtInfo->typeContext,
9319             ClassLoader::ThrowIfNotFound,
9320             ClassLoader::FailIfUninstDefOrRef,
9321             ClassLoader::LoadTypes,
9322             CLASS_LOAD_EXACTPARENTS,
9323             TRUE,
9324             pSubstForTypeLoad).GetMethodTable();
9325         
9326         Substitution ifaceSubstForTypeLoad(ie.CurrentToken(), pModule, pSubstForTypeLoad);
9327         Substitution ifaceSubstForComparing(ie.CurrentToken(), pModule, pSubstForComparing);
9328         ExpandExactInterface(
9329             bmtInfo, 
9330             pInterface, 
9331             &ifaceSubstForTypeLoad, 
9332             &ifaceSubstForComparing 
9333             COMMA_INDEBUG(dbg_pClassMT));
9334     }
9335     if (FAILED(hr))
9336     {
9337         pModule->GetAssembly()->ThrowTypeLoadException(pModule->GetMDImport(), typeDef, IDS_CLASSLOAD_BADFORMAT);
9338     }
9339 } // MethodTableBuilder::ExpandExactDeclaredInterfaces
9340
9341 //*******************************************************************************
9342 void 
9343 MethodTableBuilder::ExpandExactInterface(
9344     bmtExactInterfaceInfo *     bmtInfo, 
9345     MethodTable *               pIntf, 
9346     const Substitution *        pSubstForTypeLoad_OnStack,   // Allocated on stack!
9347     const Substitution *        pSubstForComparing_OnStack   // Allocated on stack!
9348     COMMA_INDEBUG(MethodTable * dbg_pClassMT))
9349 {
9350     STANDARD_VM_CONTRACT;
9351
9352     // ****** This must be consistent with code:MethodTableBuilder::ExpandApproxInterface ******
9353
9354     // Is it already present according to the "generic" layout of the interfaces.
9355     // Note we use exactly the same algorithm as when we
9356     // determined the layout of the interface map for the "generic" version of the class.
9357     for (DWORD i = 0; i < bmtInfo->nAssigned; i++)
9358     {
9359         // Type Equivalence is not respected for this comparision as you can have multiple type equivalent interfaces on a class
9360         TokenPairList newVisited = TokenPairList::AdjustForTypeEquivalenceForbiddenScope(NULL);
9361         if (MetaSig::CompareTypeDefsUnderSubstitutions(bmtInfo->pExactMTs[i],
9362                                                        pIntf,
9363                                                        &bmtInfo->pInterfaceSubstitution[i],
9364                                                        pSubstForComparing_OnStack,
9365                                                        &newVisited))
9366         {
9367 #ifdef _DEBUG
9368             //#InjectInterfaceDuplicates_ExactInterfaces
9369             // We will inject duplicate interfaces in check builds.
9370             // Has to be in sync with code:#InjectInterfaceDuplicates_Main.
9371             if (dbg_pClassMT->Debug_HasInjectedInterfaceDuplicates())
9372             {   // Just pretend we didn't find this match
9373                 break;
9374             }
9375 #endif //_DEBUG
9376             return; // found it, don't add it again
9377         }
9378     }
9379
9380     // Add the interface and its sub-interfaces
9381     DWORD n = bmtInfo->nAssigned;
9382     bmtInfo->pExactMTs[n] = pIntf;
9383     bmtInfo->pInterfaceSubstitution[n] = *pSubstForComparing_OnStack;
9384     bmtInfo->nAssigned++;
9385     
9386     Substitution * pSubstForTypeLoad = new (&GetThread()->m_MarshalAlloc) Substitution(*pSubstForTypeLoad_OnStack);
9387     
9388     ExpandExactDeclaredInterfaces(
9389         bmtInfo, 
9390         pIntf->GetModule(), 
9391         pIntf->GetCl(), 
9392         pSubstForTypeLoad, 
9393         &bmtInfo->pInterfaceSubstitution[n] 
9394         COMMA_INDEBUG(dbg_pClassMT));
9395 } // MethodTableBuilder::ExpandExactInterface
9396
9397 //*******************************************************************************
9398 /* static */
9399 void MethodTableBuilder::InterfacesAmbiguityCheck(bmtInterfaceAmbiguityCheckInfo *bmtCheckInfo,
9400                                                   Module *pModule,
9401                                                   mdToken typeDef,
9402                                                   const Substitution *pSubstChain)
9403 {
9404     STANDARD_VM_CONTRACT;
9405
9406     HRESULT hr;
9407     InterfaceImplEnum ie(pModule, typeDef, pSubstChain);
9408     while ((hr = ie.Next()) == S_OK)
9409     {
9410         MethodTable *pInterface =
9411             ClassLoader::LoadTypeDefOrRefOrSpecThrowing(pModule, ie.CurrentToken(),
9412                                                         &bmtCheckInfo->typeContext,
9413                                                         ClassLoader::ThrowIfNotFound,
9414                                                         ClassLoader::FailIfUninstDefOrRef,
9415                                                         ClassLoader::LoadTypes,
9416                                                         CLASS_LOAD_EXACTPARENTS,
9417                                                         TRUE,
9418                                                         pSubstChain).GetMethodTable();
9419         InterfaceAmbiguityCheck(bmtCheckInfo, ie.CurrentSubst(), pInterface);
9420     }
9421     if (FAILED(hr))
9422     {
9423         pModule->GetAssembly()->ThrowTypeLoadException(pModule->GetMDImport(), typeDef, IDS_CLASSLOAD_BADFORMAT);
9424     }
9425 }
9426
9427 //*******************************************************************************
9428 void MethodTableBuilder::InterfaceAmbiguityCheck(bmtInterfaceAmbiguityCheckInfo *bmtCheckInfo,
9429                                                  const Substitution *pItfSubstChain,
9430                                                  MethodTable *pIntf)
9431 {
9432     STANDARD_VM_CONTRACT;
9433
9434     // Is it already in the generic version of the freshly declared interfaces. We
9435     // do this based on metadata, i.e. via the substitution chains.
9436     // Note we use exactly the same algorithm as when we
9437     // determined the layout of the interface map for the "generic" version of the class.
9438     for (DWORD i = 0; i < bmtCheckInfo->nAssigned; i++)
9439     {
9440         // Type Equivalence is not respected for this comparision as you can have multiple type equivalent interfaces on a class
9441         TokenPairList newVisited = TokenPairList::AdjustForTypeEquivalenceForbiddenScope(NULL);
9442         if (MetaSig::CompareTypeDefsUnderSubstitutions(bmtCheckInfo->ppExactDeclaredInterfaces[i],
9443                                                        pIntf,
9444                                                        bmtCheckInfo->ppInterfaceSubstitutionChains[i],
9445                                                        pItfSubstChain,
9446                                                        &newVisited))
9447             return; // found it, don't add it again
9448     }
9449
9450     // OK, so it isn't a duplicate based on the generic IL, now check if the instantiation
9451     // makes it a duplicate.
9452     for (DWORD i = 0; i < bmtCheckInfo->nAssigned; i++)
9453     {
9454         if (bmtCheckInfo->ppExactDeclaredInterfaces[i] == pIntf)
9455         {
9456                 bmtCheckInfo->pMT->GetModule()->GetAssembly()->ThrowTypeLoadException(bmtCheckInfo->pMT->GetMDImport(),
9457                                                                                       bmtCheckInfo->pMT->GetCl(),
9458                                                                                       IDS_CLASSLOAD_OVERLAPPING_INTERFACES);
9459         }
9460     }
9461
9462     DWORD n = bmtCheckInfo->nAssigned;
9463     bmtCheckInfo->ppExactDeclaredInterfaces[n] = pIntf;
9464     bmtCheckInfo->ppInterfaceSubstitutionChains[n] = new (&GetThread()->m_MarshalAlloc) Substitution[pItfSubstChain->GetLength()];
9465     pItfSubstChain->CopyToArray(bmtCheckInfo->ppInterfaceSubstitutionChains[n]);
9466
9467     bmtCheckInfo->nAssigned++;
9468     InterfacesAmbiguityCheck(bmtCheckInfo,pIntf->GetModule(),pIntf->GetCl(),pItfSubstChain);
9469 }
9470
9471
9472 //*******************************************************************************
9473 void MethodTableBuilder::CheckForSystemTypes()
9474 {
9475     STANDARD_VM_CONTRACT;
9476
9477     LPCUTF8 name, nameSpace;
9478
9479     MethodTable * pMT = GetHalfBakedMethodTable();
9480     EEClass * pClass = GetHalfBakedClass();
9481
9482     // We can exit early for generic types - there are just a few cases to check for.
9483     if (bmtGenerics->HasInstantiation())
9484     {
9485         if (pMT->IsIntrinsicType() && pClass->HasLayout())
9486         {
9487             if (FAILED(GetMDImport()->GetNameOfTypeDef(GetCl(), &name, &nameSpace)))
9488             {
9489                 BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
9490             }
9491
9492             if (strcmp(nameSpace, g_IntrinsicsNS) == 0)
9493             {
9494                 EEClassLayoutInfo * pLayout = pClass->GetLayoutInfo();
9495
9496                 // The SIMD Hardware Intrinsic types correspond to fundamental data types in the underlying ABIs:
9497                 // * Vector64<T>:  __m64
9498                 // * Vector128<T>: __m128
9499                 // * Vector256<T>: __m256
9500
9501                 // These __m128 and __m256 types, among other requirements, are special in that they must always
9502                 // be aligned properly.
9503
9504                 if (IsCompilationProcess())
9505                 {
9506                     // Disable AOT compiling for the SIMD hardware intrinsic types. These types require special
9507                     // ABI handling as they represent fundamental data types (__m64, __m128, and __m256) and not
9508                     // aggregate or union types. See https://github.com/dotnet/coreclr/issues/15943
9509                     //
9510                     // Once they are properly handled according to the ABI requirements, we can remove this check
9511                     // and allow them to be used in crossgen/AOT scenarios.
9512                     COMPlusThrow(kTypeLoadException, IDS_EE_HWINTRINSIC_NGEN_DISALLOWED);
9513                 }
9514
9515                 if (strcmp(name, g_Vector64Name) == 0)
9516                 {
9517                     // The System V ABI for i386 defaults to 8-byte alignment for __m64, except for parameter passing,
9518                     // where it has an alignment of 4.
9519
9520                     pLayout->m_LargestAlignmentRequirementOfAllMembers        = 8; // sizeof(__m64)
9521                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 8; // sizeof(__m64)
9522                 }
9523                 else if (strcmp(name, g_Vector128Name) == 0)
9524                 {
9525     #ifdef _TARGET_ARM_
9526                     // The Procedure Call Standard for ARM defaults to 8-byte alignment for __m128
9527
9528                     pLayout->m_LargestAlignmentRequirementOfAllMembers        = 8;
9529                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 8;
9530     #else
9531                     pLayout->m_LargestAlignmentRequirementOfAllMembers        = 16; // sizeof(__m128)
9532                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 16; // sizeof(__m128)
9533     #endif // _TARGET_ARM_
9534                 }
9535                 else if (strcmp(name, g_Vector256Name) == 0)
9536                 {
9537     #ifdef _TARGET_ARM_
9538                     // No such type exists for the Procedure Call Standard for ARM. We will default
9539                     // to the same alignment as __m128, which is supported by the ABI.
9540
9541                     pLayout->m_LargestAlignmentRequirementOfAllMembers        = 8;
9542                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 8;
9543     #elif defined(_TARGET_ARM64_)
9544                     // The Procedure Call Standard for ARM 64-bit (with SVE support) defaults to
9545                     // 16-byte alignment for __m256.
9546
9547                     pLayout->m_LargestAlignmentRequirementOfAllMembers        = 16;
9548                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 16;
9549     #else
9550                     pLayout->m_LargestAlignmentRequirementOfAllMembers        = 32; // sizeof(__m256)
9551                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 32; // sizeof(__m256)
9552     #endif // _TARGET_ARM_ elif _TARGET_ARM64_
9553                 }
9554                 else
9555                 {
9556                     // These types should be handled or explicitly skipped below to ensure that we don't
9557                     // miss adding required ABI support for future types.
9558
9559                     _ASSERTE_MSG(FALSE, "Unhandled Hardware Intrinsic Type.");
9560                 }
9561
9562                 return;
9563             }
9564         }
9565
9566         if (g_pNullableClass != NULL)
9567         {
9568             _ASSERTE(g_pByReferenceClass != NULL);
9569             _ASSERTE(g_pByReferenceClass->IsByRefLike());
9570
9571 #ifdef _TARGET_X86_
9572             if (GetCl() == g_pByReferenceClass->GetCl())
9573             {
9574                 // x86 by default treats the type of ByReference<T> as the actual type of its IntPtr field, see calls to
9575                 // ComputeInternalCorElementTypeForValueType in this file. This is a special case where the struct needs to be
9576                 // treated as a value type so that its field can be considered as a byref pointer.
9577                 _ASSERTE(pMT->GetFlag(MethodTable::enum_flag_Category_Mask) == MethodTable::enum_flag_Category_PrimitiveValueType);
9578                 pMT->ClearFlag(MethodTable::enum_flag_Category_Mask);
9579                 pMT->SetInternalCorElementType(ELEMENT_TYPE_VALUETYPE);
9580                 return;
9581             }
9582 #endif
9583
9584             _ASSERTE(g_pNullableClass->IsNullable());
9585
9586             // Pre-compute whether the class is a Nullable<T> so that code:Nullable::IsNullableType is efficient
9587             // This is useful to the performance of boxing/unboxing a Nullable
9588             if (GetCl() == g_pNullableClass->GetCl())
9589                 pMT->SetIsNullable();
9590
9591             return;
9592         }
9593     }
9594
9595     if (IsNested() || IsEnum())
9596         return;
9597
9598     if (FAILED(GetMDImport()->GetNameOfTypeDef(GetCl(), &name, &nameSpace)))
9599     {
9600         BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
9601     }
9602
9603     if (IsValueClass())
9604     {
9605         //
9606         // Value types 
9607         // 
9608
9609         // All special value types are in the system namespace
9610         if (strcmp(nameSpace, g_SystemNS) != 0)
9611             return;
9612
9613         // Check if it is a primitive type 
9614         CorElementType type = CorTypeInfo::FindPrimitiveType(name);
9615         if (type != ELEMENT_TYPE_END)
9616         {
9617             pMT->SetInternalCorElementType(type);
9618             pMT->SetIsTruePrimitive();
9619
9620 #if defined(_TARGET_X86_) && defined(UNIX_X86_ABI)
9621             switch (type)
9622             {
9623                 // The System V ABI for i386 defines different packing for these types.
9624
9625                 case ELEMENT_TYPE_I8:
9626                 case ELEMENT_TYPE_U8:
9627                 case ELEMENT_TYPE_R8:
9628                 {
9629                     EEClassLayoutInfo * pLayout = pClass->GetLayoutInfo();
9630                     pLayout->m_LargestAlignmentRequirementOfAllMembers        = 4;
9631                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 4;
9632                     break;
9633                 }
9634
9635                 default:
9636                     break;
9637             }
9638 #endif // _TARGET_X86_ && UNIX_X86_ABI
9639
9640 #ifdef _DEBUG 
9641             if (FAILED(GetMDImport()->GetNameOfTypeDef(GetCl(), &name, &nameSpace)))
9642             {
9643                 name = nameSpace = "Invalid TypeDef record";
9644             }
9645             LOG((LF_CLASSLOADER, LL_INFO10000, "%s::%s marked as primitive type %i\n", nameSpace, name, type));
9646 #endif // _DEBUG
9647         }
9648         else if (strcmp(name, g_NullableName) == 0)
9649         {
9650             pMT->SetIsNullable();
9651         }
9652 #ifdef _TARGET_X86_
9653         else if (strcmp(name, g_ByReferenceName) == 0)
9654         {
9655             // x86 by default treats the type of ByReference<T> as the actual type of its IntPtr field, see calls to
9656             // ComputeInternalCorElementTypeForValueType in this file. This is a special case where the struct needs to be
9657             // treated as a value type so that its field can be considered as a byref pointer.
9658             _ASSERTE(pMT->GetFlag(MethodTable::enum_flag_Category_Mask) == MethodTable::enum_flag_Category_PrimitiveValueType);
9659             pMT->ClearFlag(MethodTable::enum_flag_Category_Mask);
9660             pMT->SetInternalCorElementType(ELEMENT_TYPE_VALUETYPE);
9661         }
9662 #endif
9663 #ifndef _TARGET_X86_ 
9664         else if (strcmp(name, g_RuntimeArgumentHandleName) == 0)
9665         {
9666             pMT->SetInternalCorElementType (ELEMENT_TYPE_I);
9667         }
9668         else if (strcmp(name, g_RuntimeMethodHandleInternalName) == 0)
9669         {
9670             pMT->SetInternalCorElementType (ELEMENT_TYPE_I);
9671         }
9672 #endif
9673 #if defined(ALIGN_ACCESS) || defined(FEATURE_64BIT_ALIGNMENT)
9674         else if (strcmp(name, g_DecimalName) == 0)
9675         {
9676             // This is required because native layout of System.Decimal causes it to be aligned
9677             // differently to the layout of the native DECIMAL structure, which will cause
9678             // data misalignent exceptions if Decimal is embedded in another type.
9679
9680             EEClassLayoutInfo* pLayout = pClass->GetLayoutInfo();
9681             pLayout->m_LargestAlignmentRequirementOfAllMembers        = sizeof(ULONGLONG);
9682             pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = sizeof(ULONGLONG);
9683
9684 #ifdef FEATURE_64BIT_ALIGNMENT
9685             // Also need to mark the type so it will be allocated on a 64-bit boundary for
9686             // platforms that won't do this naturally.
9687             SetAlign8Candidate();
9688 #endif
9689         }
9690 #endif // ALIGN_ACCESS || FEATURE_64BIT_ALIGNMENT
9691     }
9692     else
9693     {
9694         //
9695         // Reference types
9696         // 
9697         if (strcmp(name, g_StringName) == 0 && strcmp(nameSpace, g_SystemNS) == 0)
9698         {
9699             // Strings are not "normal" objects, so we need to mess with their method table a bit
9700             // so that the GC can figure out how big each string is...
9701             DWORD baseSize = StringObject::GetBaseSize();
9702             pMT->SetBaseSize(baseSize);
9703
9704             GetHalfBakedClass()->SetBaseSizePadding(baseSize - bmtFP->NumInstanceFieldBytes);
9705
9706             pMT->SetComponentSize(2);
9707         }
9708         else if (strcmp(name, g_CriticalFinalizerObjectName) == 0 && strcmp(nameSpace, g_ConstrainedExecutionNS) == 0)
9709         {
9710             // To introduce a class with a critical finalizer,
9711             // we'll set the bit here.
9712             pMT->SetHasCriticalFinalizer();
9713         }
9714 #ifdef FEATURE_COMINTEROP 
9715         else
9716         {
9717             bool bIsComObject = false;
9718             bool bIsRuntimeClass = false;
9719
9720             if (strcmp(name, g_ComObjectName) == 0 && strcmp(nameSpace, g_SystemNS) == 0)
9721                 bIsComObject = true;
9722             
9723             if (strcmp(name, g_RuntimeClassName) == 0 && strcmp(nameSpace, g_WinRTNS) == 0)
9724                 bIsRuntimeClass = true;
9725
9726             if (bIsComObject || bIsRuntimeClass)
9727             {
9728                 // Make System.__ComObject/System.Runtime.InteropServices.WindowsRuntime.RuntimeClass a ComImport type
9729                 // We can't do it using attribute as C# won't allow putting code in ComImport types
9730                 pMT->SetComObjectType();
9731
9732                 // COM objects need an optional field on the EEClass, so ensure this class instance has allocated
9733                 // the optional field descriptor.
9734                 EnsureOptionalFieldsAreAllocated(pClass, m_pAllocMemTracker, GetLoaderAllocator()->GetLowFrequencyHeap());            
9735             }            
9736             
9737             if (bIsRuntimeClass)            
9738             {
9739                 // Note that we set it here to avoid type loader considering RuntimeClass as a normal WindowsImportType 
9740                 // as functions in RuntimeClass doesn't go through COM interop
9741                 GetHalfBakedClass()->SetProjectedFromWinRT();
9742             }
9743         }
9744 #endif // FEATURE_COMINTEROP
9745     }
9746 }
9747
9748 //==========================================================================================
9749 // Helper to create a new method table. This is the only
9750 // way to allocate a new MT. Don't try calling new / ctor.
9751 // Called from SetupMethodTable
9752 // This needs to be kept consistent with MethodTable::GetSavedExtent()
9753 MethodTable * MethodTableBuilder::AllocateNewMT(Module *pLoaderModule,
9754                                          DWORD dwVtableSlots,
9755                                          DWORD dwVirtuals,
9756                                          DWORD dwGCSize,
9757                                          DWORD dwNumInterfaces,
9758                                          DWORD dwNumDicts,
9759                                          DWORD cbInstAndDict,
9760                                          MethodTable *pMTParent,
9761                                          ClassLoader *pClassLoader,
9762                                          LoaderAllocator *pAllocator,
9763                                          BOOL isInterface,
9764                                          BOOL fDynamicStatics,
9765                                          BOOL fHasGenericsStaticsInfo,
9766                                          BOOL fNeedsRCWPerTypeData
9767 #ifdef FEATURE_COMINTEROP
9768         , BOOL fHasDynamicInterfaceMap
9769 #endif
9770 #ifdef FEATURE_PREJIT
9771         , Module *pComputedPZM
9772 #endif // FEATURE_PREJIT
9773         , AllocMemTracker *pamTracker
9774     )
9775 {
9776     CONTRACT (MethodTable*)
9777     {
9778         THROWS;
9779         GC_TRIGGERS;
9780         MODE_ANY;
9781         POSTCONDITION(CheckPointer(RETVAL));
9782     }
9783     CONTRACT_END;
9784
9785     DWORD dwNonVirtualSlots = dwVtableSlots - dwVirtuals;
9786
9787     // GCSize must be aligned
9788     _ASSERTE(IS_ALIGNED(dwGCSize, sizeof(void*)));
9789
9790     // size without the interface map
9791     S_SIZE_T cbTotalSize = S_SIZE_T(dwGCSize) + S_SIZE_T(sizeof(MethodTable));
9792
9793     // vtable
9794     cbTotalSize += MethodTable::GetNumVtableIndirections(dwVirtuals) * sizeof(MethodTable::VTableIndir_t);
9795
9796
9797     DWORD dwMultipurposeSlotsMask = 0;
9798     if (dwNumInterfaces != 0)
9799         dwMultipurposeSlotsMask |= MethodTable::enum_flag_HasInterfaceMap;
9800     if (dwNumDicts != 0)
9801         dwMultipurposeSlotsMask |= MethodTable::enum_flag_HasPerInstInfo;
9802     if (bmtVT->pDispatchMapBuilder->Count() > 0)
9803         dwMultipurposeSlotsMask |= MethodTable::enum_flag_HasDispatchMapSlot;
9804     if (dwNonVirtualSlots != 0)
9805         dwMultipurposeSlotsMask |= MethodTable::enum_flag_HasNonVirtualSlots;
9806     if (pLoaderModule != GetModule())
9807         dwMultipurposeSlotsMask |= MethodTable::enum_flag_HasModuleOverride;
9808
9809     // Add space for optional members here. Same as GetOptionalMembersSize()
9810     cbTotalSize += MethodTable::GetOptionalMembersAllocationSize(dwMultipurposeSlotsMask,
9811                                                       fHasGenericsStaticsInfo,
9812                                                       FALSE, // no GuidInfo needed for canonical instantiations
9813                                                       FALSE, // no CCW template needed for canonical instantiations
9814                                                       fNeedsRCWPerTypeData,
9815                                                       RidFromToken(GetCl()) >= METHODTABLE_TOKEN_OVERFLOW);
9816
9817     // Interface map starts here
9818     S_SIZE_T offsetOfInterfaceMap = cbTotalSize;
9819
9820     cbTotalSize += S_SIZE_T(dwNumInterfaces) * S_SIZE_T(sizeof(InterfaceInfo_t));
9821
9822 #ifdef FEATURE_COMINTEROP
9823     // DynamicInterfaceMap have an extra DWORD added to the end of the normal interface
9824     // map. This will be used to store the count of dynamically added interfaces
9825     // (the ones that are not in  the metadata but are QI'ed for at runtime).
9826     cbTotalSize += S_SIZE_T(fHasDynamicInterfaceMap ? sizeof(DWORD_PTR) : 0);
9827 #endif
9828
9829     // Dictionary pointers start here
9830     S_SIZE_T offsetOfInstAndDict = cbTotalSize;
9831
9832     if (dwNumDicts != 0)
9833     {
9834         cbTotalSize += sizeof(GenericsDictInfo);
9835         cbTotalSize += S_SIZE_T(dwNumDicts) * S_SIZE_T(sizeof(MethodTable::PerInstInfoElem_t));
9836         cbTotalSize += cbInstAndDict;
9837     }
9838
9839     S_SIZE_T offsetOfUnsharedVtableChunks = cbTotalSize;
9840
9841     BOOL canShareVtableChunks = pMTParent && MethodTable::CanShareVtableChunksFrom(pMTParent, pLoaderModule
9842 #ifdef FEATURE_PREJIT
9843         , pComputedPZM
9844 #endif //FEATURE_PREJIT
9845         );
9846
9847     // If pMTParent has a generic instantiation, we cannot share its vtable chunks
9848     // This is because pMTParent is only approximate at this point, and MethodTableBuilder::CopyExactParentSlots
9849     // may swap in an exact parent that does not satisfy CanShareVtableChunksFrom
9850     if (pMTParent && pMTParent->HasInstantiation())
9851     {
9852         canShareVtableChunks = FALSE;
9853     }
9854
9855     // We will share any parent vtable chunk that does not contain a method we overrode (or introduced)
9856     // For the rest, we need to allocate space
9857     for (DWORD i = 0; i < dwVirtuals; i++)
9858     {
9859         if (!canShareVtableChunks || ChangesImplementationOfVirtualSlot(static_cast<SLOT_INDEX>(i)))
9860         {
9861             DWORD chunkStart = MethodTable::GetStartSlotForVtableIndirection(MethodTable::GetIndexOfVtableIndirection(i), dwVirtuals);
9862             DWORD chunkEnd = MethodTable::GetEndSlotForVtableIndirection(MethodTable::GetIndexOfVtableIndirection(i), dwVirtuals);
9863
9864             cbTotalSize += S_SIZE_T(chunkEnd - chunkStart) * S_SIZE_T(sizeof(PCODE));
9865
9866             i = chunkEnd - 1;
9867         }
9868     }
9869
9870     // Add space for the non-virtual slots array (pointed to by an optional member) if required
9871     // If there is only one non-virtual slot, we store it directly in the optional member and need no array
9872     S_SIZE_T offsetOfNonVirtualSlots = cbTotalSize;
9873     if (dwNonVirtualSlots > 1)
9874     {
9875         cbTotalSize += S_SIZE_T(dwNonVirtualSlots) * S_SIZE_T(sizeof(PCODE));
9876     }
9877
9878     BYTE *pData = (BYTE *)pamTracker->Track(pAllocator->GetHighFrequencyHeap()->AllocMem(cbTotalSize));
9879
9880     _ASSERTE(IS_ALIGNED(pData, TARGET_POINTER_SIZE));
9881     
9882     // There should be no overflows if we have allocated the memory succesfully
9883     _ASSERTE(!cbTotalSize.IsOverflow());
9884
9885     MethodTable* pMT = (MethodTable*)(pData + dwGCSize);
9886
9887     pMT->SetMultipurposeSlotsMask(dwMultipurposeSlotsMask);
9888
9889     MethodTableWriteableData * pMTWriteableData = (MethodTableWriteableData *) (BYTE *)
9890         pamTracker->Track(pAllocator->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(MethodTableWriteableData))));
9891     // Note: Memory allocated on loader heap is zero filled
9892     pMT->SetWriteableData(pMTWriteableData);
9893
9894     // This also disables IBC logging until the type is sufficiently intitialized so
9895     // it needs to be done early
9896     pMTWriteableData->SetIsNotFullyLoadedForBuildMethodTable();
9897
9898 #ifdef _DEBUG
9899     pClassLoader->m_dwGCSize += dwGCSize;
9900     pClassLoader->m_dwInterfaceMapSize += (dwNumInterfaces * sizeof(InterfaceInfo_t));
9901     pClassLoader->m_dwMethodTableSize += (DWORD)cbTotalSize.Value();
9902     pClassLoader->m_dwVtableData += (dwVtableSlots * sizeof(PCODE));
9903 #endif // _DEBUG
9904
9905     // There should be no overflows if we have allocated the memory succesfully
9906     _ASSERTE(!offsetOfUnsharedVtableChunks.IsOverflow());
9907     _ASSERTE(!offsetOfNonVirtualSlots.IsOverflow());
9908     _ASSERTE(!offsetOfInterfaceMap.IsOverflow());
9909     _ASSERTE(!offsetOfInstAndDict.IsOverflow());
9910
9911     // initialize the total number of slots
9912     pMT->SetNumVirtuals(static_cast<WORD>(dwVirtuals));
9913
9914     pMT->SetParentMethodTable(pMTParent);
9915
9916     // Fill out the vtable indirection slots
9917     SIZE_T dwCurrentUnsharedSlotOffset = offsetOfUnsharedVtableChunks.Value();
9918     MethodTable::VtableIndirectionSlotIterator it = pMT->IterateVtableIndirectionSlots();
9919     while (it.Next())
9920     {
9921         BOOL shared = canShareVtableChunks;
9922
9923         // Recalculate whether we will share this chunk
9924         if (canShareVtableChunks)
9925         {
9926             for (DWORD i = it.GetStartSlot(); i < it.GetEndSlot(); i++)
9927             {
9928                 if (ChangesImplementationOfVirtualSlot(static_cast<SLOT_INDEX>(i)))
9929                 {
9930                     shared = FALSE;
9931                     break;
9932                 }
9933             }
9934         }
9935
9936         if (shared)
9937         {
9938             // Share the parent chunk
9939             _ASSERTE(it.GetEndSlot() <= pMTParent->GetNumVirtuals());
9940             it.SetIndirectionSlot(pMTParent->GetVtableIndirections()[it.GetIndex()].GetValueMaybeNull());
9941         }
9942         else
9943         {
9944             // Use the locally allocated chunk
9945             it.SetIndirectionSlot((MethodTable::VTableIndir2_t *)(pData+dwCurrentUnsharedSlotOffset));
9946             dwCurrentUnsharedSlotOffset += it.GetSize();
9947         }
9948     }
9949
9950 #ifdef FEATURE_COMINTEROP
9951     // Extensible RCW's are prefixed with the count of dynamic interfaces.
9952     if (fHasDynamicInterfaceMap)
9953     {
9954         _ASSERTE (dwNumInterfaces > 0);
9955         pMT->SetInterfaceMap ((WORD) (dwNumInterfaces), (InterfaceInfo_t*)(pData+offsetOfInterfaceMap.Value()+sizeof(DWORD_PTR)));
9956
9957         *(((DWORD_PTR *)pMT->GetInterfaceMap()) - 1) = 0;
9958     }
9959     else
9960 #endif // FEATURE_COMINTEROP
9961     {
9962         // interface map is at the end of the vtable
9963         pMT->SetInterfaceMap ((WORD) dwNumInterfaces, (InterfaceInfo_t *)(pData+offsetOfInterfaceMap.Value()));
9964     }
9965
9966     _ASSERTE(((WORD) dwNumInterfaces) == dwNumInterfaces);
9967
9968     if (fDynamicStatics)
9969     {
9970         pMT->SetDynamicStatics(fHasGenericsStaticsInfo);
9971     }
9972
9973     if (dwNonVirtualSlots > 0)
9974     {
9975         if (dwNonVirtualSlots > 1)
9976         {
9977             pMT->SetNonVirtualSlotsArray((PTR_PCODE)(pData+offsetOfNonVirtualSlots.Value()));
9978         }
9979         else
9980         {
9981             pMT->SetHasSingleNonVirtualSlot();
9982         }
9983     }
9984
9985     // the dictionary pointers follow the interface map
9986     if (dwNumDicts)
9987     {
9988         MethodTable::PerInstInfoElem_t *pPerInstInfo = (MethodTable::PerInstInfoElem_t *)(pData + offsetOfInstAndDict.Value() + sizeof(GenericsDictInfo));
9989
9990         pMT->SetPerInstInfo ( pPerInstInfo);
9991
9992         // Fill in the dictionary for this type, if it's instantiated
9993         if (cbInstAndDict)
9994         {
9995             MethodTable::PerInstInfoElem_t *pPInstInfo = (MethodTable::PerInstInfoElem_t *)(pPerInstInfo + (dwNumDicts-1));
9996             pPInstInfo->SetValueMaybeNull((Dictionary*) (pPerInstInfo + dwNumDicts));
9997         }
9998     }
9999
10000 #ifdef _DEBUG
10001     pMT->m_pWriteableData.GetValue()->m_dwLastVerifedGCCnt = (DWORD)-1;
10002 #endif // _DEBUG
10003
10004     RETURN(pMT);
10005 }
10006
10007     
10008 //*******************************************************************************
10009 //
10010 // Used by BuildMethodTable
10011 //
10012 // Setup the method table
10013 //
10014 #ifdef _PREFAST_ 
10015 #pragma warning(push)
10016 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
10017 #endif // _PREFAST_
10018
10019 VOID
10020 MethodTableBuilder::SetupMethodTable2(
10021         Module * pLoaderModule 
10022 #ifdef FEATURE_PREJIT
10023         , Module * pComputedPZM 
10024 #endif // FEATURE_PREJIT
10025     )
10026 {
10027     CONTRACTL
10028     {
10029         STANDARD_VM_CHECK;
10030         PRECONDITION(CheckPointer(this));
10031         PRECONDITION(CheckPointer(bmtVT));
10032         PRECONDITION(CheckPointer(bmtInterface));
10033         PRECONDITION(CheckPointer(bmtInternal));
10034         PRECONDITION(CheckPointer(bmtProp));
10035         PRECONDITION(CheckPointer(bmtMFDescs));
10036         PRECONDITION(CheckPointer(bmtEnumFields));
10037         PRECONDITION(CheckPointer(bmtError));
10038         PRECONDITION(CheckPointer(bmtMetaData));
10039         PRECONDITION(CheckPointer(bmtParent));
10040         PRECONDITION(CheckPointer(bmtGenerics));
10041     }
10042     CONTRACTL_END;
10043
10044     DWORD i;
10045
10046 #ifdef FEATURE_COMINTEROP 
10047     BOOL fHasDynamicInterfaceMap = bmtInterface->dwInterfaceMapSize > 0 &&
10048                                    bmtProp->fIsComObjectType &&
10049                                    (GetParentMethodTable() != g_pObjectClass);
10050     BOOL fNeedsRCWPerTypeData = bmtProp->fNeedsRCWPerTypeData;
10051 #else // FEATURE_COMINTEROP
10052     BOOL fNeedsRCWPerTypeData = FALSE;
10053 #endif // FEATURE_COMINTEROP
10054
10055     EEClass *pClass = GetHalfBakedClass();
10056
10057     DWORD cbDict = bmtGenerics->HasInstantiation()
10058                    ?  DictionaryLayout::GetFirstDictionaryBucketSize(
10059                           bmtGenerics->GetNumGenericArgs(), pClass->GetDictionaryLayout())
10060                    : 0;
10061
10062 #ifdef FEATURE_COLLECTIBLE_TYPES
10063     BOOL fCollectible = pLoaderModule->IsCollectible();
10064 #endif // FEATURE_COLLECTIBLE_TYPES
10065
10066     DWORD dwGCSize;
10067     
10068     if (bmtFP->NumGCPointerSeries > 0)
10069     {
10070         dwGCSize = (DWORD)CGCDesc::ComputeSize(bmtFP->NumGCPointerSeries);
10071     }
10072     else
10073     {
10074 #ifdef FEATURE_COLLECTIBLE_TYPES
10075         if (fCollectible)
10076             dwGCSize = (DWORD)CGCDesc::ComputeSize(1);
10077         else
10078 #endif // FEATURE_COLLECTIBLE_TYPES
10079             dwGCSize = 0;
10080     }
10081
10082     pClass->SetNumMethods(bmtVT->cTotalSlots);
10083     pClass->SetNumNonVirtualSlots(bmtVT->cVtableSlots - bmtVT->cVirtualSlots);
10084
10085     // Now setup the method table
10086     // interface map is allocated along with the method table
10087     MethodTable *pMT = AllocateNewMT(pLoaderModule,
10088                                    bmtVT->cVtableSlots,
10089                                    bmtVT->cVirtualSlots,
10090                                    dwGCSize,
10091                                    bmtInterface->dwInterfaceMapSize,
10092                                    bmtGenerics->numDicts,
10093                                    cbDict,
10094                                    GetParentMethodTable(),
10095                                    GetClassLoader(),
10096                                    bmtAllocator,
10097                                    IsInterface(),
10098                                    bmtProp->fDynamicStatics,
10099                                    bmtProp->fGenericsStatics,
10100                                    fNeedsRCWPerTypeData,
10101 #ifdef FEATURE_COMINTEROP 
10102                                    fHasDynamicInterfaceMap,
10103 #endif
10104 #ifdef FEATURE_PREJIT
10105                                    pComputedPZM,
10106 #endif //FEATURE_PREJIT
10107                                    GetMemTracker());
10108
10109     pMT->SetClass(pClass);
10110     pClass->m_pMethodTable.SetValue(pMT);
10111     m_pHalfBakedMT = pMT;
10112
10113 #ifdef _DEBUG 
10114     pMT->SetDebugClassName(GetDebugClassName());
10115 #endif
10116
10117 #ifdef FEATURE_COMINTEROP
10118     if (fNeedsRCWPerTypeData)
10119         pMT->SetHasRCWPerTypeData();
10120 #endif // FEATURE_COMINTEROP
10121
10122
10123     if (IsInterface())
10124         pMT->SetIsInterface();
10125
10126     if (GetParentMethodTable() != NULL)
10127     {
10128         if (GetParentMethodTable()->HasModuleDependencies())
10129         {
10130             pMT->SetHasModuleDependencies();
10131         }
10132         else
10133         {
10134             Module * pModule = GetModule();
10135             Module * pParentModule = GetParentMethodTable()->GetModule();
10136             if (pModule != pParentModule)
10137             {
10138                 pMT->SetHasModuleDependencies();
10139             }
10140         }
10141
10142         if (GetParentMethodTable()->HasPreciseInitCctors() || !pClass->IsBeforeFieldInit())
10143         {
10144             pMT->SetHasPreciseInitCctors();
10145         }
10146     }
10147
10148     // Must be done early because various methods test HasInstantiation() and ContainsGenericVariables()
10149     if (bmtGenerics->GetNumGenericArgs() != 0)
10150     {
10151         pMT->SetHasInstantiation(bmtGenerics->fTypicalInstantiation, bmtGenerics->fSharedByGenericInstantiations);
10152
10153         if (bmtGenerics->fContainsGenericVariables)
10154             pMT->SetContainsGenericVariables();
10155     }
10156
10157     if (bmtGenerics->numDicts != 0)
10158     {
10159         if (!FitsIn<WORD>(bmtGenerics->GetNumGenericArgs()))
10160         {
10161             BuildMethodTableThrowException(IDS_CLASSLOAD_TOOMANYGENERICARGS);
10162         }
10163
10164         pMT->SetDictInfo(bmtGenerics->numDicts,
10165             static_cast<WORD>(bmtGenerics->GetNumGenericArgs()));
10166     }
10167
10168     CONSISTENCY_CHECK(pMT->GetNumGenericArgs() == bmtGenerics->GetNumGenericArgs());
10169     CONSISTENCY_CHECK(pMT->GetNumDicts() == bmtGenerics->numDicts);
10170     CONSISTENCY_CHECK(pMT->HasInstantiation() == bmtGenerics->HasInstantiation());
10171     CONSISTENCY_CHECK(pMT->HasInstantiation() == !pMT->GetInstantiation().IsEmpty());
10172
10173     pMT->SetLoaderModule(pLoaderModule);
10174     pMT->SetLoaderAllocator(bmtAllocator);
10175
10176     pMT->SetModule(GetModule());
10177
10178     pMT->SetInternalCorElementType (ELEMENT_TYPE_CLASS);
10179
10180     SetNonGCRegularStaticFieldBytes (bmtProp->dwNonGCRegularStaticFieldBytes);
10181     SetNonGCThreadStaticFieldBytes (bmtProp->dwNonGCThreadStaticFieldBytes);
10182
10183 #ifdef FEATURE_TYPEEQUIVALENCE
10184     if (bmtProp->fHasTypeEquivalence)
10185     {
10186         pMT->SetHasTypeEquivalence();
10187     }
10188 #endif //FEATURE_TYPEEQUIVALENCE
10189
10190 #ifdef FEATURE_COMINTEROP 
10191     if (bmtProp->fSparse)
10192         pClass->SetSparseForCOMInterop();
10193
10194     if (IsInterface() && IsComImport())
10195     {
10196         // Determine if we are creating an interface methodtable that may be used to dispatch through VSD
10197         // on an object that has the methodtable of __ComObject.
10198
10199         // This is done to allow COM tearoff interfaces, but as a side-effect of this feature,
10200         // we end up using a domain-shared type (__ComObject) with a domain-specific dispatch token.
10201         // This is a problem because the same domain-specific dispatch token value can appear in
10202         // multiple unshared domains (VSD takes advantage of the fact that in general a shared type
10203         // cannot implement an unshared interface). This means that the same <token, __ComObject> pair
10204         // value can mean different things in different domains (since the token could represent
10205         // IFoo in one domain and IBar in another). This is a problem because the
10206         // VSD polymorphic lookup mechanism relies on a process-wide cache table, and as a result
10207         // these duplicate values would collide if we didn't use fat dispatch token to ensure uniqueness
10208         // and the interface methodtable is not in the shared domain.
10209
10210         pMT->SetRequiresFatDispatchTokens();
10211     }
10212 #endif // FEATURE_COMINTEROP
10213
10214     if (bmtVT->pCCtor != NULL)
10215     {
10216         pMT->SetHasClassConstructor();
10217         CONSISTENCY_CHECK(pMT->GetClassConstructorSlot() == bmtVT->pCCtor->GetSlotIndex());
10218     }
10219     if (bmtVT->pDefaultCtor != NULL)
10220     {
10221         pMT->SetHasDefaultConstructor();
10222         CONSISTENCY_CHECK(pMT->GetDefaultConstructorSlot() == bmtVT->pDefaultCtor->GetSlotIndex());
10223     }
10224
10225     for (MethodDescChunk *pChunk = GetHalfBakedClass()->GetChunks(); pChunk != NULL; pChunk = pChunk->GetNextChunk())
10226     {
10227         pChunk->SetMethodTable(pMT);
10228     }
10229
10230 #ifdef _DEBUG 
10231     {
10232         // disable ibc logging because we can assert in ComputerPreferredZapModule for partially constructed
10233         // generic types 
10234         IBCLoggingDisabler disableLogging;
10235
10236         DeclaredMethodIterator it(*this);
10237         while (it.Next())
10238         {
10239             MethodDesc *pMD = it->GetMethodDesc();
10240             if (pMD != NULL)
10241             {
10242                 pMD->m_pDebugMethodTable.SetValue(pMT);
10243                 pMD->m_pszDebugMethodSignature = FormatSig(pMD, GetLoaderAllocator()->GetLowFrequencyHeap(), GetMemTracker());
10244             }
10245             MethodDesc *pUnboxedMD = it->GetUnboxedMethodDesc();
10246             if (pUnboxedMD != NULL)
10247             {
10248                 pUnboxedMD->m_pDebugMethodTable.SetValue(pMT);
10249                 pUnboxedMD->m_pszDebugMethodSignature = FormatSig(pUnboxedMD, GetLoaderAllocator()->GetLowFrequencyHeap(), GetMemTracker());
10250             }
10251         }
10252     }
10253 #endif // _DEBUG
10254
10255     // Note that for value classes, the following calculation is only appropriate
10256     // when the instance is in its "boxed" state.
10257     if (!IsInterface())
10258     {
10259         DWORD baseSize = Max<DWORD>(bmtFP->NumInstanceFieldBytes + OBJECT_BASESIZE, MIN_OBJECT_SIZE);
10260         baseSize = (baseSize + ALLOC_ALIGN_CONSTANT) & ~ALLOC_ALIGN_CONSTANT;  // m_BaseSize must be aligned
10261         pMT->SetBaseSize(baseSize);
10262
10263         GetHalfBakedClass()->SetBaseSizePadding(baseSize - bmtFP->NumInstanceFieldBytes);
10264
10265         if (bmtProp->fIsComObjectType)
10266         {   // Propagate the com specific info
10267             pMT->SetComObjectType();
10268 #ifdef FEATURE_COMINTEROP 
10269             // COM objects need an optional field on the EEClass, so ensure this class instance has allocated
10270             // the optional field descriptor.
10271             EnsureOptionalFieldsAreAllocated(pClass, m_pAllocMemTracker, GetLoaderAllocator()->GetLowFrequencyHeap());
10272 #endif // FEATURE_COMINTEROP
10273         }
10274
10275 #ifdef FEATURE_COMINTEROP 
10276         if (pMT->GetAssembly()->IsManagedWinMD())
10277         {
10278             // We need to mark classes that are implementations of managed WinRT runtime classes with
10279             // the "exported to WinRT" flag. It's not quite possible to tell which ones these are by
10280             // reading metadata so we ask the adapter.
10281
10282             IWinMDImport *pWinMDImport = pMT->GetAssembly()->GetManifestWinMDImport();
10283             _ASSERTE(pWinMDImport != NULL);
10284
10285             BOOL bResult;
10286             IfFailThrow(pWinMDImport->IsRuntimeClassImplementation(GetCl(), &bResult));
10287                 
10288             if (bResult)
10289             {
10290                 pClass->SetExportedToWinRT();
10291
10292                 // We need optional fields for activation from WinRT.
10293                 EnsureOptionalFieldsAreAllocated(pClass, m_pAllocMemTracker, GetLoaderAllocator()->GetLowFrequencyHeap());
10294             }
10295         }
10296
10297         if (pClass->IsProjectedFromWinRT() || pClass->IsExportedToWinRT())
10298         {
10299             const BYTE *        pVal;                 
10300             ULONG               cbVal;        
10301             HRESULT hr = GetMDImport()->GetCustomAttributeByName(GetCl(), g_WindowsFoundationMarshalingBehaviorAttributeClassName, (const void **) &pVal, &cbVal);
10302             if (hr == S_OK)
10303             {
10304                 CustomAttributeParser cap(pVal, cbVal);
10305                 IfFailThrow(cap.SkipProlog());
10306                 UINT32 u = 0;
10307                 IfFailThrow(cap.GetU4(&u));
10308                 if(u > 0)
10309                     pClass->SetMarshalingType(u);
10310             }
10311         }
10312 #endif // FEATURE_COMINTEROP
10313     }
10314     else
10315     {
10316 #ifdef FEATURE_COMINTEROP 
10317         // If this is an interface then we need to set the ComInterfaceType to
10318         // -1 to indicate we have not yet determined the interface type.
10319         pClass->SetComInterfaceType((CorIfaceAttr)-1);
10320
10321         // If this is a special COM event interface, then mark the MT as such.
10322         if (bmtProp->fComEventItfType)
10323         {
10324             pClass->SetComEventItfType();
10325         }
10326 #endif // FEATURE_COMINTEROP
10327     }
10328     _ASSERTE((pMT->IsInterface() == 0) == (IsInterface() == 0));
10329
10330     if (HasLayout())
10331     {
10332         pClass->SetNativeSize(GetLayoutInfo()->GetNativeSize());
10333     }
10334
10335     FieldDesc *pFieldDescList = pClass->GetFieldDescList();
10336     // Set all field slots to point to the newly created MethodTable
10337     for (i = 0; i < (bmtEnumFields->dwNumStaticFields + bmtEnumFields->dwNumInstanceFields); i++)
10338     {
10339         pFieldDescList[i].m_pMTOfEnclosingClass.SetValue(pMT);
10340     }
10341
10342     // Fill in type parameters before looking up exact parent or fetching the types of any field descriptors!
10343     // This must come before the use of GetFieldType in the value class representation optimization below.
10344     if (bmtGenerics->GetNumGenericArgs() != 0)
10345     {
10346         // Space has already been allocated for the instantiation but the parameters haven't been filled in
10347         Instantiation destInst = pMT->GetInstantiation();
10348         Instantiation inst = bmtGenerics->GetInstantiation();
10349
10350         // So fill them in...
10351         TypeHandle * pInstDest = (TypeHandle *)destInst.GetRawArgs();
10352         for (DWORD j = 0; j < bmtGenerics->GetNumGenericArgs(); j++)
10353         {
10354             pInstDest[j] = inst[j];
10355         }
10356     }
10357
10358     CorElementType normalizedType = ELEMENT_TYPE_CLASS;
10359     if (IsValueClass())
10360     {
10361         if (IsEnum())
10362         {
10363             if (GetNumInstanceFields() != 1 ||
10364                 !CorTypeInfo::IsPrimitiveType(pFieldDescList[0].GetFieldType()))
10365             {
10366                 BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil);
10367             }
10368             CONSISTENCY_CHECK(!pFieldDescList[0].IsStatic());
10369             normalizedType = pFieldDescList->GetFieldType();
10370         }
10371         else
10372         {
10373 #ifdef _TARGET_X86_ 
10374             // JIT64 is not aware of normalized value types and this
10375             // optimization (return small value types by value in registers)
10376             // is already done in JIT64.
10377             OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOADED);
10378             normalizedType = EEClass::ComputeInternalCorElementTypeForValueType(pMT);
10379 #else
10380             normalizedType = ELEMENT_TYPE_VALUETYPE;
10381 #endif
10382         }
10383     }
10384     pMT->SetInternalCorElementType(normalizedType);
10385
10386     if (bmtProp->fIsIntrinsicType)
10387     {
10388         pMT->SetIsIntrinsicType();
10389     }
10390
10391     if (GetModule()->IsSystem())
10392     {
10393         // we are in mscorlib
10394         CheckForSystemTypes();
10395     }
10396
10397     // Now fill in the real interface map with the approximate interfaces
10398     if (bmtInterface->dwInterfaceMapSize > 0)
10399     {
10400         // First ensure we have enough space to record extra flag information for each interface (we don't
10401         // record this directly into each interface map entry since these flags don't pack well due to
10402         // alignment).
10403         PVOID pExtraInterfaceInfo = NULL;
10404         SIZE_T cbExtraInterfaceInfo = MethodTable::GetExtraInterfaceInfoSize(bmtInterface->dwInterfaceMapSize);
10405         if (cbExtraInterfaceInfo)
10406             pExtraInterfaceInfo = GetMemTracker()->Track(GetLoaderAllocator()->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(cbExtraInterfaceInfo)));
10407
10408         // Call this even in the case where pExtraInterfaceInfo == NULL (certain cases are optimized and don't
10409         // require extra buffer space).
10410         pMT->InitializeExtraInterfaceInfo(pExtraInterfaceInfo);
10411
10412         InterfaceInfo_t *pInterfaces = pMT->GetInterfaceMap();
10413
10414         CONSISTENCY_CHECK(CheckPointer(pInterfaces));
10415
10416         // Copy the interface map member by member so there is no junk in the padding.
10417         for (i = 0; i < bmtInterface->dwInterfaceMapSize; i++)
10418         {
10419             bmtInterfaceEntry * pEntry = &bmtInterface->pInterfaceMap[i];
10420
10421             if (pEntry->IsDeclaredOnType())
10422                 pMT->SetInterfaceDeclaredOnClass(i);
10423             _ASSERTE(!!pEntry->IsDeclaredOnType() == !!pMT->IsInterfaceDeclaredOnClass(i));
10424
10425             pInterfaces[i].SetMethodTable(pEntry->GetInterfaceType()->GetMethodTable());
10426         }
10427     }
10428
10429     pMT->SetCl(GetCl());
10430
10431     // The type is sufficiently initialized for most general purpose accessor methods to work.
10432     // Mark the type as restored to avoid avoid asserts. Note that this also enables IBC logging.
10433     pMT->GetWriteableDataForWrite_NoLogging()->SetIsRestoredForBuildMethodTable();
10434
10435 #ifdef _DEBUG
10436     // Store status if we tried to inject duplicate interfaces
10437     if (bmtInterface->dbg_fShouldInjectInterfaceDuplicates)
10438         pMT->Debug_SetHasInjectedInterfaceDuplicates();
10439 #endif //_DEBUG
10440
10441     // Keep bmtInterface data around since we no longer write the flags (IsDeclaredOnType and
10442     // IsImplementedByParent) into the interface map (these flags are only required during type loading).
10443
10444     {
10445         for (MethodDescChunk *pChunk = GetHalfBakedClass()->GetChunks(); pChunk != NULL; pChunk = pChunk->GetNextChunk())
10446         {
10447             // Make sure that temporary entrypoints are create for methods. NGEN uses temporary
10448             // entrypoints as surrogate keys for precodes.
10449             pChunk->EnsureTemporaryEntryPointsCreated(GetLoaderAllocator(), GetMemTracker());
10450         }
10451     }
10452
10453     {   // copy onto the real vtable (methods only)
10454         //@GENERICS: Because we sometimes load an inexact parent (see ClassLoader::GetParent) the inherited slots might
10455         // come from the wrong place and need fixing up once we know the exact parent
10456
10457         for (bmtVtable::Iterator slotIt = bmtVT->IterateSlots(); !slotIt.AtEnd(); ++slotIt)
10458         {
10459             SLOT_INDEX iCurSlot = static_cast<SLOT_INDEX>(slotIt.CurrentIndex());
10460
10461             // We want the unboxed MethodDesc if we're out of the virtual method range
10462             // and the method we're dealing with has an unboxing method. If so, then
10463             // the unboxing method was placed in the virtual section of the vtable and
10464             // we now need to place the unboxed version.
10465             MethodDesc * pMD = NULL;
10466             if (iCurSlot < bmtVT->cVirtualSlots || !slotIt->Impl().AsMDMethod()->IsUnboxing())
10467             {
10468                 pMD = slotIt->Impl().GetMethodDesc();
10469                 CONSISTENCY_CHECK(slotIt->Decl().GetSlotIndex() == iCurSlot);
10470             }
10471             else
10472             {
10473                 pMD = slotIt->Impl().AsMDMethod()->GetUnboxedMethodDesc();
10474                 CONSISTENCY_CHECK(pMD->GetSlot() == iCurSlot);
10475             }
10476
10477             CONSISTENCY_CHECK(CheckPointer(pMD));
10478
10479             if (pMD->GetMethodTable() != pMT)
10480             {
10481                 //
10482                 // Inherited slots
10483                 //
10484                 // Do not write into vtable chunks shared with parent. It would introduce race 
10485                 // with code:MethodDesc::SetStableEntryPointInterlocked.
10486                 //
10487                 DWORD indirectionIndex = MethodTable::GetIndexOfVtableIndirection(iCurSlot);
10488                 if (GetParentMethodTable()->GetVtableIndirections()[indirectionIndex].GetValueMaybeNull() != pMT->GetVtableIndirections()[indirectionIndex].GetValueMaybeNull())
10489                     pMT->SetSlot(iCurSlot, pMD->GetInitialEntryPointForCopiedSlot());
10490             }
10491             else
10492             {
10493                 //
10494                 // Owned slots
10495                 //
10496                 _ASSERTE(iCurSlot >= bmtVT->cVirtualSlots || ChangesImplementationOfVirtualSlot(iCurSlot));
10497
10498                 PCODE addr = pMD->GetTemporaryEntryPoint();
10499                 _ASSERTE(addr != NULL);
10500
10501                 if (pMD->HasNonVtableSlot())
10502                 {
10503                     *((PCODE *)pMD->GetAddrOfSlot()) = addr;
10504                 }
10505                 else
10506                 {
10507                     pMT->SetSlot(iCurSlot, addr);
10508                 }
10509
10510                 if (pMD->GetSlot() == iCurSlot && pMD->RequiresStableEntryPoint())
10511                 {
10512                     // The rest of the system assumes that certain methods always have stable entrypoints.
10513                     // Create them now.
10514                     pMD->GetOrCreatePrecode();
10515                 }
10516             }
10517         }
10518     }
10519
10520     // If we have any entries, then finalize them and allocate the object in class loader heap
10521     DispatchMap                 *pDispatchMap        = NULL;
10522     DispatchMapBuilder          *pDispatchMapBuilder = bmtVT->pDispatchMapBuilder;
10523     CONSISTENCY_CHECK(CheckPointer(pDispatchMapBuilder));
10524
10525     if (pDispatchMapBuilder->Count() > 0)
10526     {
10527         // Create a map in stacking memory.
10528         BYTE * pbMap;
10529         UINT32 cbMap;
10530         DispatchMap::CreateEncodedMapping(
10531             pMT, 
10532             pDispatchMapBuilder, 
10533             pDispatchMapBuilder->GetAllocator(), 
10534             &pbMap, 
10535             &cbMap);
10536
10537         // Now finalize the impltable and allocate the block in the low frequency loader heap
10538         size_t objSize = (size_t) DispatchMap::GetObjectSize(cbMap);
10539         void * pv = AllocateFromLowFrequencyHeap(S_SIZE_T(objSize));
10540         _ASSERTE(pv != NULL);
10541
10542         // Use placement new
10543         pDispatchMap = new (pv) DispatchMap(pbMap, cbMap);
10544         pMT->SetDispatchMap(pDispatchMap);
10545
10546 #ifdef LOGGING 
10547         g_sdStats.m_cDispatchMap++;
10548         g_sdStats.m_cbDispatchMap += (UINT32) objSize;
10549         LOG((LF_LOADER, LL_INFO1000, "SD: Dispatch map for %s: %d bytes for map, %d bytes total for object.\n",
10550             pMT->GetDebugClassName(), cbMap, objSize));
10551 #endif // LOGGING
10552
10553     }
10554
10555     // GetMethodData by default will cache its result. However, in the case that we're
10556     // building a MethodTable, we aren't guaranteed that this type is going to successfully
10557     // load and so caching it would result in errors down the road since the memory and
10558     // type occupying the same memory location would very likely be incorrect. The second
10559     // argument specifies that GetMethodData should not cache the returned object.
10560     MethodTable::MethodDataWrapper hMTData(MethodTable::GetMethodData(pMT, FALSE));
10561
10562     if (!IsInterface())
10563     {
10564         // Propagate inheritance.
10565
10566         // NOTE: In the world of unfolded interface this was used to propagate overrides into
10567         //       the unfolded interface vtables to make sure that overrides of virtual methods
10568         //       also overrode the interface methods that they contributed to. This had the
10569         //       unfortunate side-effect of also overwriting regular vtable slots that had been
10570         //       methodimpl'd and as a result changed the meaning of methodimpl from "substitute
10571         //       the body of method A with the body of method B" to "unify the slots of methods
10572         //       A and B". But now compilers have come to rely on this side-effect and it can
10573         //       not be brought back to its originally intended behaviour.
10574
10575         // For every slot whose body comes from another slot (determined by getting the MethodDesc
10576         // for a slot and seeing if MethodDesc::GetSlot returns a different value than the slot
10577         // from which the MethodDesc was recovered), copy the value of the slot stated by the
10578         // MethodDesc over top of the current slot.
10579
10580         // Because of the way slot unification works, we need to iterate the enture vtable until
10581         // no slots need updated. To understand this, imagine the following:
10582         //      C1::M1 is overridden by C2::M2
10583         //      C1::M2 is methodImpled by C1::M3
10584         //      C1::M3 is overridden by C2::M3
10585         // This should mean that C1::M1 is implemented by C2::M3, but if we didn't run the below
10586         // for loop a second time, this would not be propagated properly - it would only be placed
10587         // into the slot for C1::M2 and never make its way up to C1::M1.
10588         
10589         BOOL fChangeMade;
10590         do
10591         {
10592             fChangeMade = FALSE;
10593             for (i = 0; i < pMT->GetNumVirtuals(); i++)
10594             {
10595                 MethodDesc* pMD = hMTData->GetImplMethodDesc(i);
10596
10597                 CONSISTENCY_CHECK(CheckPointer(pMD));
10598                 CONSISTENCY_CHECK(pMD == pMT->GetMethodDescForSlot(i));
10599
10600                 // This indicates that the method body in this slot was copied here through a methodImpl.
10601                 // Thus, copy the value of the slot from which the body originally came, in case it was
10602                 // overridden, to make sure the two slots stay in sync.
10603                 DWORD originalIndex = pMD->GetSlot();
10604                 if (originalIndex != i)
10605                 {
10606                     MethodDesc *pOriginalMD = hMTData->GetImplMethodDesc(originalIndex);
10607                     CONSISTENCY_CHECK(CheckPointer(pOriginalMD));
10608                     CONSISTENCY_CHECK(pOriginalMD == pMT->GetMethodDescForSlot(originalIndex));
10609                     if (pMD != pOriginalMD)
10610                     {
10611                         // Copy the slot value in the method's original slot.
10612                         pMT->SetSlot(i, pOriginalMD->GetInitialEntryPointForCopiedSlot());
10613                         hMTData->InvalidateCachedVirtualSlot(i);
10614
10615                         // Update the pMD to the new method desc we just copied over ourselves with. This will
10616                         // be used in the check for missing method block below.
10617                         pMD = pOriginalMD;
10618
10619                         // This method is now duplicate
10620                         pMD->SetDuplicate();
10621                         INDEBUG(g_dupMethods++;)
10622                         fChangeMade = TRUE;
10623                     }
10624                 }
10625             }
10626         }
10627         while (fChangeMade);
10628     }
10629
10630     if (!bmtProp->fNoSanityChecks)
10631         VerifyVirtualMethodsImplemented(hMTData);
10632
10633 #ifdef _DEBUG 
10634     {
10635         for (bmtVtable::Iterator i = bmtVT->IterateSlots();
10636              !i.AtEnd(); ++i)
10637         {
10638             _ASSERTE(i->Impl().GetMethodDesc() != NULL);
10639         }
10640     }
10641 #endif // _DEBUG
10642
10643
10644 #ifdef FEATURE_COMINTEROP 
10645     // for ComObject types, i.e. if the class extends from a COM Imported
10646     // class
10647     // make sure any interface implementated by the COM Imported class
10648     // is overridden fully, (OR) not overridden at all..
10649     // We relax this for WinRT where we want to be able to override individual methods.
10650     if (bmtProp->fIsComObjectType && !pMT->IsWinRTObjectType())
10651     {
10652         MethodTable::InterfaceMapIterator intIt = pMT->IterateInterfaceMap();
10653         while (intIt.Next())
10654         {
10655             MethodTable* pIntfMT = intIt.GetInterface();
10656             if (pIntfMT->GetNumVirtuals() != 0)
10657             {
10658                 BOOL hasComImportMethod = FALSE;
10659                 BOOL hasManagedMethod = FALSE;
10660
10661                 // NOTE: Avoid caching the MethodData object for the type being built.
10662                 MethodTable::MethodDataWrapper hItfImplData(MethodTable::GetMethodData(pIntfMT, pMT, FALSE));
10663                 MethodTable::MethodIterator it(hItfImplData);
10664                 for (;it.IsValid(); it.Next())
10665                 {
10666                     MethodDesc *pClsMD = NULL;
10667                     // If we fail to find an _IMPLEMENTATION_ for the interface MD, then
10668                     // we are a ComImportMethod, otherwise we still be a ComImportMethod or
10669                     // we can be a ManagedMethod.
10670                     DispatchSlot impl(it.GetTarget());
10671                     if (!impl.IsNull())
10672                     {
10673                         pClsMD = it.GetMethodDesc();
10674
10675                         CONSISTENCY_CHECK(!pClsMD->IsInterface());
10676                         if (pClsMD->GetClass()->IsComImport())
10677                         {
10678                             hasComImportMethod = TRUE;
10679                         }
10680                         else
10681                         {
10682                             hasManagedMethod = TRUE;
10683                         }
10684                     }
10685                     else
10686                     {
10687                         // Need to set the pClsMD for the error reporting below.
10688                         pClsMD = it.GetDeclMethodDesc();
10689                         CONSISTENCY_CHECK(CheckPointer(pClsMD));
10690                         hasComImportMethod = TRUE;
10691                     }
10692
10693                     // One and only one of the two must be set.
10694                     if ((hasComImportMethod && hasManagedMethod) ||
10695                         (!hasComImportMethod && !hasManagedMethod))
10696                     {
10697                         BuildMethodTableThrowException(IDS_EE_BAD_COMEXTENDS_CLASS, pClsMD->GetNameOnNonArrayClass());
10698                     }
10699                 }
10700             }
10701         }
10702     }
10703
10704     // For COM event interfaces, we need to make sure that all the methods are
10705     // methods to add or remove events. This means that they all need to take
10706     // a delegate derived class and have a void return type.
10707     if (bmtProp->fComEventItfType)
10708     {
10709         // COM event interfaces had better be interfaces.
10710         CONSISTENCY_CHECK(IsInterface());
10711
10712         // Go through all the methods and check the validity of the signature.
10713         // NOTE: Uses hMTData to avoid caching a MethodData object for the type being built.
10714         MethodTable::MethodIterator it(hMTData);
10715         for (;it.IsValid(); it.Next())
10716         {
10717             MethodDesc* pMD = it.GetMethodDesc();
10718             _ASSERTE(pMD);
10719
10720             MetaSig Sig(pMD);
10721
10722             {
10723                 CONTRACT_VIOLATION(LoadsTypeViolation);
10724                 if (Sig.GetReturnType() != ELEMENT_TYPE_VOID ||
10725                     Sig.NumFixedArgs() != 1 ||
10726                     Sig.NextArg() != ELEMENT_TYPE_CLASS ||
10727                     !Sig.GetLastTypeHandleThrowing().CanCastTo(TypeHandle(g_pDelegateClass)))
10728                 {
10729                     BuildMethodTableThrowException(IDS_EE_BAD_COMEVENTITF_CLASS, pMD->GetNameOnNonArrayClass());
10730                 }
10731             }
10732         }
10733     }
10734 #endif // FEATURE_COMINTEROP
10735
10736     // If this class uses any VTS (Version Tolerant Serialization) features
10737     // (event callbacks or OptionalField attributes) we've previously cached the
10738     // additional information in the bmtMFDescs structure. Now it's time to add
10739     // this information as an optional extension to the MethodTable.
10740 }
10741 #ifdef _PREFAST_ 
10742 #pragma warning(pop)
10743 #endif
10744
10745 // Returns true if there is at least one default implementation for this interface method
10746 // We don't care about conflicts at this stage in order to avoid impact type load performance
10747 BOOL MethodTableBuilder::HasDefaultInterfaceImplementation(bmtRTType *pDeclType, MethodDesc *pDeclMD)
10748 {
10749     STANDARD_VM_CONTRACT;
10750
10751 #ifdef FEATURE_DEFAULT_INTERFACES
10752     // If the interface method is already non-abstract, we are done
10753     if (!pDeclMD->IsAbstract())
10754         return TRUE;
10755
10756     int targetSlot = pDeclMD->GetSlot();
10757
10758     // Iterate over all the interfaces this type implements
10759     bmtInterfaceEntry * pItfEntry = NULL;
10760     for (DWORD i = 0; i < bmtInterface->dwInterfaceMapSize; i++)
10761     {
10762         bmtRTType * pCurItf = bmtInterface->pInterfaceMap[i].GetInterfaceType();
10763
10764         Module * pCurIntfModule = pCurItf->GetMethodTable()->GetModule();
10765
10766         // Go over the methods on the interface
10767         MethodTable::IntroducedMethodIterator methIt(pCurItf->GetMethodTable());
10768         for (; methIt.IsValid(); methIt.Next())
10769         {
10770             MethodDesc * pPotentialImpl = methIt.GetMethodDesc();
10771
10772             // If this interface method is not a MethodImpl, it can't possibly implement
10773             // the interface method we are looking for
10774             if (!pPotentialImpl->IsMethodImpl())
10775                 continue;
10776
10777             // Go over all the decls this MethodImpl is implementing
10778             MethodImpl::Iterator it(pPotentialImpl);
10779             for (; it.IsValid(); it.Next())
10780             {
10781                 MethodDesc *pPotentialDecl = it.GetMethodDesc();
10782
10783                 // Check this is a decl with the right slot
10784                 if (pPotentialDecl->GetSlot() != targetSlot)
10785                     continue;
10786
10787                 // Find out what interface this default implementation is implementing
10788                 mdToken tkParent;
10789                 IfFailThrow(pCurIntfModule->GetMDImport()->GetParentToken(it.GetToken(), &tkParent));
10790
10791                 // We can only load the approximate interface at this point
10792                 MethodTable * pPotentialInterfaceMT = ClassLoader::LoadTypeDefOrRefOrSpecThrowing(
10793                     pCurIntfModule,
10794                     tkParent,
10795                     &bmtGenerics->typeContext,
10796                     ClassLoader::ThrowIfNotFound,
10797                     ClassLoader::PermitUninstDefOrRef,
10798                     ClassLoader::LoadTypes,
10799                     CLASS_LOAD_APPROXPARENTS,
10800                     TRUE).GetMethodTable()->GetCanonicalMethodTable();
10801
10802                 // Is this a default implementation for the interface we are looking for?
10803                 if (pDeclType->GetMethodTable()->HasSameTypeDefAs(pPotentialInterfaceMT))
10804                 {
10805                     // If the type is not generic, matching defs are all we need
10806                     if (!pDeclType->GetMethodTable()->HasInstantiation())
10807                         return TRUE;
10808
10809                     // If this is generic, we need to compare under substitutions
10810                     Substitution curItfSubs(tkParent, pCurIntfModule, &pCurItf->GetSubstitution());
10811
10812                     // Type Equivalence is not respected for this comparision as you can have multiple type equivalent interfaces on a class
10813                     TokenPairList newVisited = TokenPairList::AdjustForTypeEquivalenceForbiddenScope(NULL);
10814                     if (MetaSig::CompareTypeDefsUnderSubstitutions(
10815                         pPotentialInterfaceMT, pDeclType->GetMethodTable(),
10816                         &curItfSubs, &pDeclType->GetSubstitution(),
10817                         &newVisited))
10818                     {
10819                         return TRUE;
10820                     }
10821                 }
10822             }
10823         }        
10824     }
10825 #endif // FEATURE_DEFAULT_INTERFACES
10826
10827     return FALSE;
10828 }
10829
10830 void MethodTableBuilder::VerifyVirtualMethodsImplemented(MethodTable::MethodData * hMTData)
10831 {
10832     STANDARD_VM_CONTRACT;
10833
10834     //
10835     // This verification is not applicable or required in many cases
10836     //
10837
10838     if (IsAbstract() || IsInterface())
10839         return;
10840
10841 #ifdef FEATURE_COMINTEROP
10842     // Note that this is important for WinRT where redirected .NET interfaces appear on the interface
10843     // impl list but their methods are not implemented (the adapter only hides the WinRT methods, it
10844     // does not make up the .NET ones).
10845     if (bmtProp->fIsComObjectType)
10846         return;
10847 #endif // FEATURE_COMINTEROP
10848
10849     // Since interfaces aren't laid out in the vtable for stub dispatch, what we need to do
10850     // is try to find an implementation for every interface contract by iterating through
10851     // the interfaces not declared on a parent.
10852     BOOL fParentIsAbstract = FALSE;
10853     if (HasParent())
10854     {
10855         fParentIsAbstract = GetParentMethodTable()->IsAbstract();
10856     }
10857
10858     // If the parent is abstract, we need to check that each virtual method is implemented
10859     if (fParentIsAbstract)
10860     {
10861         // NOTE: Uses hMTData to avoid caching a MethodData object for the type being built.
10862         MethodTable::MethodIterator it(hMTData);
10863         for (; it.IsValid() && it.IsVirtual(); it.Next())
10864         {
10865             MethodDesc *pMD = it.GetMethodDesc();
10866             if (pMD->IsAbstract())
10867             {
10868                 MethodDesc *pDeclMD = it.GetDeclMethodDesc();
10869                 BuildMethodTableThrowException(IDS_CLASSLOAD_NOTIMPLEMENTED, pDeclMD->GetNameOnNonArrayClass());
10870             }
10871         }
10872     }
10873         
10874     DispatchMapTypeID * rgInterfaceDispatchMapTypeIDs = 
10875         new (GetStackingAllocator()) DispatchMapTypeID[bmtInterface->dwInterfaceMapSize];
10876         
10877     bmtInterfaceInfo::MapIterator intIt = bmtInterface->IterateInterfaceMap();
10878     for (; !intIt.AtEnd(); intIt.Next())
10879     {
10880         if (fParentIsAbstract || !intIt->IsImplementedByParent())
10881         {
10882             // Compute all TypeIDs for this interface (all duplicates in the interface map)
10883             UINT32 cInterfaceDuplicates;
10884             ComputeDispatchMapTypeIDs(
10885                 intIt->GetInterfaceType()->GetMethodTable(), 
10886                 &intIt->GetInterfaceType()->GetSubstitution(), 
10887                 rgInterfaceDispatchMapTypeIDs, 
10888                 bmtInterface->dwInterfaceMapSize, 
10889                 &cInterfaceDuplicates);
10890             _ASSERTE(cInterfaceDuplicates <= bmtInterface->dwInterfaceMapSize);
10891             _ASSERTE(cInterfaceDuplicates > 0);
10892                 
10893             // NOTE: This override does not cache the resulting MethodData object.
10894             MethodTable::MethodDataWrapper hData(MethodTable::GetMethodData(
10895                 rgInterfaceDispatchMapTypeIDs, 
10896                 cInterfaceDuplicates, 
10897                 intIt->GetInterfaceType()->GetMethodTable(), 
10898                 GetHalfBakedMethodTable()));
10899             MethodTable::MethodIterator it(hData);
10900             for (; it.IsValid() && it.IsVirtual(); it.Next())
10901             {
10902                 if (it.GetTarget().IsNull())
10903                 {
10904                     MethodDesc *pMD = it.GetDeclMethodDesc();
10905
10906                     if (!HasDefaultInterfaceImplementation(intIt->GetInterfaceType(), pMD))
10907                         BuildMethodTableThrowException(IDS_CLASSLOAD_NOTIMPLEMENTED, pMD->GetNameOnNonArrayClass());
10908                 }
10909             }
10910         }
10911     }
10912 }
10913
10914 INT32 __stdcall IsDefined(Module *pModule, mdToken token, TypeHandle attributeClass)
10915 {
10916     CONTRACTL
10917     {
10918         THROWS;
10919         GC_TRIGGERS;
10920     }
10921     CONTRACTL_END;
10922
10923     BOOL isDefined = FALSE;
10924
10925     IMDInternalImport *pInternalImport = pModule->GetMDImport();
10926     BOOL isSealed = FALSE;
10927
10928     HENUMInternalHolder hEnum(pInternalImport);
10929     TypeHandle caTH;
10930
10931     // Get the enum first but don't get any values
10932     hEnum.EnumInit(mdtCustomAttribute, token);
10933
10934     ULONG cMax = pInternalImport->EnumGetCount(&hEnum);
10935     if (cMax)
10936     {
10937         // we have something to look at
10938
10939
10940         if (!attributeClass.IsNull())
10941             isSealed = attributeClass.GetMethodTable()->IsSealed();
10942
10943         // Loop through the Attributes and look for the requested one
10944         mdCustomAttribute cv;
10945         while (pInternalImport->EnumNext(&hEnum, &cv))
10946         {
10947             //
10948             // fetch the ctor
10949             mdToken     tkCtor;
10950             IfFailThrow(pInternalImport->GetCustomAttributeProps(cv, &tkCtor));
10951             
10952             mdToken tkType = TypeFromToken(tkCtor);
10953             if(tkType != mdtMemberRef && tkType != mdtMethodDef)
10954                 continue; // we only deal with the ctor case
10955
10956             //
10957             // get the info to load the type, so we can check whether the current
10958             // attribute is a subtype of the requested attribute
10959             IfFailThrow(pInternalImport->GetParentToken(tkCtor, &tkType));
10960             
10961             _ASSERTE(TypeFromToken(tkType) == mdtTypeRef || TypeFromToken(tkType) == mdtTypeDef);
10962             // load the type
10963             if (isSealed)
10964             {
10965                 caTH=ClassLoader::LoadTypeDefOrRefThrowing(pModule, tkType,
10966                                                            ClassLoader::ReturnNullIfNotFound,
10967                                                            ClassLoader::FailIfUninstDefOrRef,
10968                                                            TypeFromToken(tkType) == mdtTypeDef ? tdAllTypes : tdNoTypes);
10969             }
10970             else
10971             {
10972                 caTH = ClassLoader::LoadTypeDefOrRefThrowing(pModule, tkType,
10973                                                              ClassLoader::ReturnNullIfNotFound,
10974                                                              ClassLoader::FailIfUninstDefOrRef);
10975             }
10976             if (caTH.IsNull())
10977                 continue;
10978
10979             // a null class implies all custom attribute
10980             if (!attributeClass.IsNull())
10981             {
10982                 if (isSealed)
10983                 {
10984                     if (attributeClass != caTH)
10985                         continue;
10986                 }
10987                 else
10988                 {
10989                     if (!caTH.CanCastTo(attributeClass))
10990                         continue;
10991                 }
10992             }
10993
10994             //
10995             // if we are here we got one
10996             isDefined = TRUE;
10997             break;
10998         }
10999     }
11000
11001     return isDefined;
11002 }
11003
11004 //*******************************************************************************
11005 VOID MethodTableBuilder::CheckForRemotingProxyAttrib()
11006 {
11007     STANDARD_VM_CONTRACT;
11008
11009 }
11010
11011
11012 //*******************************************************************************
11013 // Checks for a bunch of special interface names and if it matches then it sets
11014 // bmtProp->fIsMngStandardItf to TRUE. Additionally, it checks to see if the
11015 // type is an interface and if it has ComEventInterfaceAttribute custom attribute
11016 // set, then it sets bmtProp->fComEventItfType to true.
11017 //
11018 // NOTE: This only does anything when COM interop is enabled.
11019
11020 VOID MethodTableBuilder::CheckForSpecialTypes()
11021 {
11022 #ifdef FEATURE_COMINTEROP
11023     STANDARD_VM_CONTRACT;
11024
11025
11026     Module *pModule = GetModule();
11027     IMDInternalImport *pMDImport = pModule->GetMDImport();
11028
11029     // Check to see if this type is a managed standard interface. All the managed
11030     // standard interfaces live in mscorlib.dll so checking for that first
11031     // makes the strcmp that comes afterwards acceptable.
11032     if (pModule->IsSystem())
11033     {
11034         if (IsInterface())
11035         {
11036             LPCUTF8 pszClassName;
11037             LPCUTF8 pszClassNamespace;
11038             if (FAILED(pMDImport->GetNameOfTypeDef(GetCl(), &pszClassName, &pszClassNamespace)))
11039             {
11040                 pszClassName = pszClassNamespace = NULL;
11041             }
11042             if ((pszClassName != NULL) && (pszClassNamespace != NULL))
11043             {
11044                 LPUTF8 pszFullyQualifiedName = NULL;
11045                 MAKE_FULLY_QUALIFIED_NAME(pszFullyQualifiedName, pszClassNamespace, pszClassName);
11046
11047                 // This is just to give us a scope to break out of.
11048                 do
11049                 {
11050
11051 #define MNGSTDITF_BEGIN_INTERFACE(FriendlyName, strMngItfName, strUCOMMngItfName, strCustomMarshalerName, strCustomMarshalerCookie, strManagedViewName, NativeItfIID, bCanCastOnNativeItfQI) \
11052                     if (strcmp(strMngItfName, pszFullyQualifiedName) == 0) \
11053                     { \
11054                         bmtProp->fIsMngStandardItf = true; \
11055                         break; \
11056                     }
11057
11058 #define MNGSTDITF_DEFINE_METH_IMPL(FriendlyName, ECallMethName, MethName, MethSig, FcallDecl)
11059
11060 #define MNGSTDITF_END_INTERFACE(FriendlyName)
11061
11062 #include "mngstditflist.h"
11063
11064 #undef MNGSTDITF_BEGIN_INTERFACE
11065 #undef MNGSTDITF_DEFINE_METH_IMPL
11066 #undef MNGSTDITF_END_INTERFACE
11067
11068                 } while (FALSE);
11069
11070                 if (strcmp(pszFullyQualifiedName, g_CollectionsGenericCollectionItfName) == 0 ||
11071                     strcmp(pszFullyQualifiedName, g_CollectionsGenericReadOnlyCollectionItfName) == 0 ||
11072                     strcmp(pszFullyQualifiedName, g_CollectionsCollectionItfName) == 0)
11073                 {
11074                     // ICollection`1, ICollection and IReadOnlyCollection`1 are special cases the adapter is unaware of
11075                     bmtProp->fIsRedirectedInterface = true;
11076                 }
11077                 else
11078                 {
11079                     if (strcmp(pszFullyQualifiedName, WinMDAdapter::GetRedirectedTypeFullCLRName(WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_IEnumerable)) == 0 ||
11080                         strcmp(pszFullyQualifiedName, WinMDAdapter::GetRedirectedTypeFullCLRName(WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_IList)) == 0 ||
11081                         strcmp(pszFullyQualifiedName, WinMDAdapter::GetRedirectedTypeFullCLRName(WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_IDictionary)) == 0 ||
11082                         strcmp(pszFullyQualifiedName, WinMDAdapter::GetRedirectedTypeFullCLRName(WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_IReadOnlyList)) == 0 ||
11083                         strcmp(pszFullyQualifiedName, WinMDAdapter::GetRedirectedTypeFullCLRName(WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_IReadOnlyDictionary)) == 0 ||
11084                         strcmp(pszFullyQualifiedName, WinMDAdapter::GetRedirectedTypeFullCLRName(WinMDAdapter::RedirectedTypeIndex_System_Collections_IEnumerable)) == 0 ||
11085                         strcmp(pszFullyQualifiedName, WinMDAdapter::GetRedirectedTypeFullCLRName(WinMDAdapter::RedirectedTypeIndex_System_Collections_IList)) == 0 ||
11086                         strcmp(pszFullyQualifiedName, WinMDAdapter::GetRedirectedTypeFullCLRName(WinMDAdapter::RedirectedTypeIndex_System_IDisposable)) == 0)
11087                     {
11088                         bmtProp->fIsRedirectedInterface = true;
11089                     }
11090                 }
11091
11092                 // We want to allocate the per-type RCW data optional MethodTable field for
11093                 // 1. Redirected interfaces
11094                 // 2. Mscorlib-declared [WindowsRuntimeImport] interfaces
11095                 bmtProp->fNeedsRCWPerTypeData = (bmtProp->fIsRedirectedInterface || GetHalfBakedClass()->IsProjectedFromWinRT());
11096
11097                 if (!bmtProp->fNeedsRCWPerTypeData)
11098                 {
11099                     // 3. Non-generic IEnumerable
11100                     if (strcmp(pszFullyQualifiedName, g_CollectionsEnumerableItfName) == 0)
11101                     {
11102                         bmtProp->fNeedsRCWPerTypeData = true;
11103                     }
11104                 }
11105             }
11106         }
11107         else if (IsDelegate() && bmtGenerics->HasInstantiation())
11108         {
11109             // 4. Redirected delegates
11110             if (GetHalfBakedClass()->GetWinRTRedirectedTypeIndex()
11111                 != WinMDAdapter::RedirectedTypeIndex_Invalid)
11112             {
11113                 bmtProp->fNeedsRCWPerTypeData = true;
11114             }
11115         }
11116     }
11117     else if (bmtGenerics->HasInstantiation() && pModule->GetAssembly()->IsWinMD())
11118     {
11119         // 5. WinRT types with variance
11120         if (bmtGenerics->pVarianceInfo != NULL)
11121         {
11122             bmtProp->fNeedsRCWPerTypeData = true;
11123         }
11124         else if (IsInterface())
11125         {
11126             // 6. Windows.Foundation.Collections.IIterator`1
11127             LPCUTF8 pszClassName;
11128             LPCUTF8 pszClassNamespace;
11129             if (SUCCEEDED(pMDImport->GetNameOfTypeDef(GetCl(), &pszClassName, &pszClassNamespace)))
11130             {
11131                 LPUTF8 pszFullyQualifiedName = NULL;
11132                 MAKE_FULLY_QUALIFIED_NAME(pszFullyQualifiedName, pszClassNamespace, pszClassName);
11133
11134                 if (strcmp(pszFullyQualifiedName, g_WinRTIIteratorClassName) == 0)
11135                 {
11136                     bmtProp->fNeedsRCWPerTypeData = true;
11137                 }
11138             }
11139         }
11140     }
11141     else if ((IsInterface() || IsDelegate()) && 
11142         IsTdPublic(GetHalfBakedClass()->GetAttrClass()) && 
11143         GetHalfBakedClass()->GetWinRTRedirectedTypeIndex() != WinMDAdapter::RedirectedTypeIndex_Invalid)
11144     {
11145         // 7. System.Collections.Specialized.INotifyCollectionChanged
11146         // 8. System.Collections.Specialized.NotifyCollectionChangedEventHandler
11147         // 9. System.ComponentModel.INotifyPropertyChanged
11148         // 10. System.ComponentModel.PropertyChangedEventHandler
11149         // 11. System.Windows.Input.ICommand
11150         LPCUTF8 pszClassName;
11151         LPCUTF8 pszClassNamespace;
11152         if (SUCCEEDED(pMDImport->GetNameOfTypeDef(GetCl(), &pszClassName, &pszClassNamespace)))
11153         {
11154             LPUTF8 pszFullyQualifiedName = NULL;
11155             MAKE_FULLY_QUALIFIED_NAME(pszFullyQualifiedName, pszClassNamespace, pszClassName);
11156
11157             if (strcmp(pszFullyQualifiedName, g_INotifyCollectionChangedName) == 0 ||
11158                 strcmp(pszFullyQualifiedName, g_NotifyCollectionChangedEventHandlerName) == 0 ||
11159                 strcmp(pszFullyQualifiedName, g_INotifyPropertyChangedName) == 0 ||
11160                 strcmp(pszFullyQualifiedName, g_PropertyChangedEventHandlerName) == 0 ||
11161                 strcmp(pszFullyQualifiedName, g_ICommandName) == 0)
11162             {
11163                 bmtProp->fNeedsRCWPerTypeData = true;
11164             }
11165         }
11166     }
11167
11168     // Check to see if the type is a COM event interface (classic COM interop only).
11169     if (IsInterface() && !GetHalfBakedClass()->IsProjectedFromWinRT())
11170     {
11171         HRESULT hr = pMDImport->GetCustomAttributeByName(GetCl(), INTEROP_COMEVENTINTERFACE_TYPE, NULL, NULL);
11172         if (hr == S_OK)
11173         {
11174             bmtProp->fComEventItfType = true;
11175         }
11176     }
11177 #endif // FEATURE_COMINTEROP
11178 }
11179
11180 #ifdef FEATURE_READYTORUN
11181 //*******************************************************************************
11182 VOID MethodTableBuilder::CheckLayoutDependsOnOtherModules(MethodTable * pDependencyMT)
11183 {
11184     STANDARD_VM_CONTRACT;
11185
11186     // These cases are expected to be handled by the caller
11187     _ASSERTE(!(pDependencyMT == g_pObjectClass || pDependencyMT->IsTruePrimitive() || ((g_pEnumClass != NULL) && pDependencyMT->IsEnum())));
11188
11189     //
11190     // WARNING: Changes in this algorithm are potential ReadyToRun breaking changes !!!
11191     //
11192     // Track whether field layout of this type depend on information outside its containing module
11193     //
11194     // It is a stronger condition than MethodTable::IsInheritanceChainLayoutFixedInCurrentVersionBubble(). 
11195     // It has to remain fixed accross versioning changes in the module dependencies. In particular, it does 
11196     // not take into account NonVersionable attribute. Otherwise, adding NonVersionable attribute to existing
11197     // type would be ReadyToRun incompatible change.
11198     //
11199     if (pDependencyMT->GetModule() == GetModule())
11200     {
11201         if (!pDependencyMT->GetClass()->HasLayoutDependsOnOtherModules())
11202             return;
11203     }
11204
11205     GetHalfBakedClass()->SetHasLayoutDependsOnOtherModules();
11206 }
11207
11208 BOOL MethodTableBuilder::NeedsAlignedBaseOffset()
11209 {
11210     STANDARD_VM_CONTRACT;
11211
11212     //
11213     // WARNING: Changes in this algorithm are potential ReadyToRun breaking changes !!!
11214     //
11215     // This method returns whether the type needs aligned base offset in order to have layout resilient to 
11216     // base class layout changes.
11217     //
11218     if (IsValueClass())
11219         return FALSE;
11220
11221     // Always use the ReadyToRun field layout algorithm if the source IL image was ReadyToRun, independent on
11222     // whether ReadyToRun is actually enabled for the module. It is required to allow mixing and matching 
11223     // ReadyToRun images with NGen.
11224     if (!GetModule()->GetFile()->IsILImageReadyToRun())
11225     {
11226         // Always use ReadyToRun field layout algorithm to produce ReadyToRun images
11227         if (!IsReadyToRunCompilation())
11228             return FALSE;
11229     }
11230
11231     MethodTable * pParentMT = GetParentMethodTable();
11232
11233     // Trivial parents
11234     if (pParentMT == NULL || pParentMT == g_pObjectClass)
11235         return FALSE;
11236
11237     if (pParentMT->GetModule() == GetModule())
11238     {
11239         if (!pParentMT->GetClass()->HasLayoutDependsOnOtherModules())
11240             return FALSE;
11241     }
11242
11243     return TRUE;
11244 }
11245 #endif // FEATURE_READYTORUN
11246
11247 //*******************************************************************************
11248 //
11249 // Used by BuildMethodTable
11250 //
11251 // Set the HasFinalizer and HasCriticalFinalizer flags
11252 //
11253 VOID MethodTableBuilder::SetFinalizationSemantics()
11254 {
11255     STANDARD_VM_CONTRACT;
11256
11257     if (g_pObjectFinalizerMD && !IsInterface() && !IsValueClass())
11258     {
11259         WORD slot = g_pObjectFinalizerMD->GetSlot();
11260
11261         // Objects not derived from Object will get marked as having a finalizer, if they have 
11262         // sufficient virtual methods.  This will only be an issue if they can be allocated 
11263         // in the GC heap (which will cause all sorts of other problems).
11264         if (slot < bmtVT->cVirtualSlots && (*bmtVT)[slot].Impl().GetMethodDesc() != g_pObjectFinalizerMD)
11265         {
11266             GetHalfBakedMethodTable()->SetHasFinalizer();
11267
11268             // The need for a critical finalizer can be inherited from a parent.
11269             // Since we set this automatically for CriticalFinalizerObject
11270             // elsewhere, the code below is the means by which any derived class
11271             // picks up the attribute.
11272             if (HasParent() && GetParentMethodTable()->HasCriticalFinalizer())
11273             {
11274                 GetHalfBakedMethodTable()->SetHasCriticalFinalizer();
11275             }
11276         }
11277     }
11278 }
11279
11280 //*******************************************************************************
11281 //
11282 // Used by BuildMethodTable
11283 //
11284 // Perform relevant GC calculations for value classes
11285 //
11286 VOID MethodTableBuilder::HandleGCForValueClasses(MethodTable ** pByValueClassCache)
11287 {
11288     STANDARD_VM_CONTRACT;
11289
11290     DWORD i;
11291
11292     EEClass *pClass = GetHalfBakedClass();
11293     MethodTable *pMT = GetHalfBakedMethodTable();
11294
11295     FieldDesc *pFieldDescList = pClass->GetFieldDescList();
11296
11297     // Note that for value classes, the following calculation is only appropriate
11298     // when the instance is in its "boxed" state.
11299 #ifdef FEATURE_COLLECTIBLE_TYPES
11300     if (bmtFP->NumGCPointerSeries == 0 && pMT->Collectible())
11301     {
11302         // For collectible types, insert empty gc series
11303         CGCDescSeries *pSeries;
11304
11305         CGCDesc::Init( (PVOID) pMT, 1);
11306         pSeries = ((CGCDesc*)pMT)->GetLowestSeries();
11307         pSeries->SetSeriesSize( (size_t) (0) - (size_t) pMT->GetBaseSize());
11308         pSeries->SetSeriesOffset(OBJECT_SIZE);
11309     }
11310     else
11311 #endif // FEATURE_COLLECTIBLE_TYPES
11312     if (bmtFP->NumGCPointerSeries != 0)
11313     {
11314         CGCDescSeries *pSeries;
11315         CGCDescSeries *pHighest;
11316
11317         pMT->SetContainsPointers();
11318
11319         // Copy the pointer series map from the parent
11320         CGCDesc::Init( (PVOID) pMT, bmtFP->NumGCPointerSeries );
11321         if (bmtParent->NumParentPointerSeries != 0)
11322         {
11323             size_t ParentGCSize = CGCDesc::ComputeSize(bmtParent->NumParentPointerSeries);
11324             memcpy( (PVOID) (((BYTE*) pMT) - ParentGCSize),
11325                     (PVOID) (((BYTE*) GetParentMethodTable()) - ParentGCSize),
11326                     ParentGCSize - sizeof(size_t)   // sizeof(size_t) is the NumSeries count
11327                   );
11328
11329         }
11330
11331         // Build the pointer series map for this pointers in this instance
11332         pSeries = ((CGCDesc*)pMT)->GetLowestSeries();
11333         if (bmtFP->NumInstanceGCPointerFields)
11334         {
11335             // See gcdesc.h for an explanation of why we adjust by subtracting BaseSize
11336             pSeries->SetSeriesSize( (size_t) (bmtFP->NumInstanceGCPointerFields * TARGET_POINTER_SIZE) - (size_t) pMT->GetBaseSize());
11337             pSeries->SetSeriesOffset(bmtFP->GCPointerFieldStart + OBJECT_SIZE);
11338             pSeries++;
11339         }
11340
11341         // Insert GC info for fields which are by-value classes
11342         for (i = 0; i < bmtEnumFields->dwNumInstanceFields; i++)
11343         {
11344             if (pFieldDescList[i].IsByValue())
11345             {
11346                 MethodTable *pByValueMT = pByValueClassCache[i];
11347
11348                 if (pByValueMT->ContainsPointers())
11349                 {
11350                     // Offset of the by value class in the class we are building, does NOT include Object
11351                     DWORD       dwCurrentOffset = pFieldDescList[i].GetOffset_NoLogging();
11352
11353                     // The by value class may have more than one pointer series
11354                     CGCDescSeries * pByValueSeries = CGCDesc::GetCGCDescFromMT(pByValueMT)->GetLowestSeries();
11355                     SIZE_T dwNumByValueSeries = CGCDesc::GetCGCDescFromMT(pByValueMT)->GetNumSeries();
11356
11357                     for (SIZE_T j = 0; j < dwNumByValueSeries; j++)
11358                     {
11359                         size_t cbSeriesSize;
11360                         size_t cbSeriesOffset;
11361
11362                         _ASSERTE(pSeries <= CGCDesc::GetCGCDescFromMT(pMT)->GetHighestSeries());
11363
11364                         cbSeriesSize = pByValueSeries->GetSeriesSize();
11365
11366                         // Add back the base size of the by value class, since it's being transplanted to this class
11367                         cbSeriesSize += pByValueMT->GetBaseSize();
11368
11369                         // Subtract the base size of the class we're building
11370                         cbSeriesSize -= pMT->GetBaseSize();
11371
11372                         // Set current series we're building
11373                         pSeries->SetSeriesSize(cbSeriesSize);
11374
11375                         // Get offset into the value class of the first pointer field (includes a +Object)
11376                         cbSeriesOffset = pByValueSeries->GetSeriesOffset();
11377
11378                         // Add it to the offset of the by value class in our class
11379                         cbSeriesOffset += dwCurrentOffset;
11380
11381                         pSeries->SetSeriesOffset(cbSeriesOffset); // Offset of field
11382                         pSeries++;
11383                         pByValueSeries++;
11384                     }
11385                 }
11386             }
11387         }
11388
11389         // Adjust the inherited series - since the base size has increased by "# new field instance bytes", we need to
11390         // subtract that from all the series (since the series always has BaseSize subtracted for it - see gcdesc.h)
11391         pHighest = CGCDesc::GetCGCDescFromMT(pMT)->GetHighestSeries();
11392         while (pSeries <= pHighest)
11393         {
11394             CONSISTENCY_CHECK(CheckPointer(GetParentMethodTable()));
11395             pSeries->SetSeriesSize( pSeries->GetSeriesSize() - ((size_t) pMT->GetBaseSize() - (size_t) GetParentMethodTable()->GetBaseSize()) );
11396             pSeries++;
11397         }
11398
11399         _ASSERTE(pSeries-1 <= CGCDesc::GetCGCDescFromMT(pMT)->GetHighestSeries());
11400     }
11401
11402 }
11403
11404 //*******************************************************************************
11405 //
11406 // Used by BuildMethodTable
11407 //
11408 // Check for the presence of type equivalence. If present, make sure
11409 // it is permitted to be on this type.
11410 //
11411
11412 void MethodTableBuilder::CheckForTypeEquivalence(
11413     WORD                     cBuildingInterfaceList,
11414     BuildingInterfaceInfo_t *pBuildingInterfaceList)
11415 {
11416     STANDARD_VM_CONTRACT;
11417
11418 #ifdef FEATURE_TYPEEQUIVALENCE
11419     bmtProp->fIsTypeEquivalent = !!IsTypeDefEquivalent(GetCl(), GetModule());
11420
11421     if (bmtProp->fIsTypeEquivalent)
11422     {
11423         BOOL comImportOrEventInterface = IsComImport();
11424 #ifdef FEATURE_COMINTEROP
11425         comImportOrEventInterface = comImportOrEventInterface || bmtProp->fComEventItfType;
11426 #endif // FEATURE_COMINTEROP
11427
11428         BOOL fTypeEquivalentNotPermittedDueToType = !((comImportOrEventInterface && IsInterface()) || IsValueClass() || IsDelegate());
11429         BOOL fTypeEquivalentNotPermittedDueToGenerics = bmtGenerics->HasInstantiation();
11430
11431         if (fTypeEquivalentNotPermittedDueToType || fTypeEquivalentNotPermittedDueToGenerics)
11432         {
11433             BuildMethodTableThrowException(IDS_CLASSLOAD_EQUIVALENTBADTYPE);
11434         }
11435
11436         GetHalfBakedClass()->SetIsEquivalentType();
11437     }
11438
11439     bmtProp->fHasTypeEquivalence = bmtProp->fIsTypeEquivalent;
11440
11441     if (!bmtProp->fHasTypeEquivalence)
11442     {
11443         // fHasTypeEquivalence flag is inherited from interfaces so we can quickly detect
11444         // types that implement type equivalent interfaces
11445         for (WORD i = 0; i < cBuildingInterfaceList; i++)
11446         {
11447             MethodTable *pItfMT = pBuildingInterfaceList[i].m_pMethodTable;
11448             if (pItfMT->HasTypeEquivalence())
11449             {
11450                 bmtProp->fHasTypeEquivalence = true;
11451                 break;
11452             }
11453         }
11454     }
11455
11456     if (!bmtProp->fHasTypeEquivalence)
11457     {
11458         // fHasTypeEquivalence flag is "inherited" from generic arguments so we can quickly detect
11459         // types like List<Str> where Str is a structure with the TypeIdentifierAttribute.
11460         if (bmtGenerics->HasInstantiation() && !bmtGenerics->IsTypicalTypeDefinition())
11461         {
11462             Instantiation inst = bmtGenerics->GetInstantiation();
11463             for (DWORD i = 0; i < inst.GetNumArgs(); i++) 
11464             {
11465                 if (inst[i].HasTypeEquivalence())
11466                 {
11467                     bmtProp->fHasTypeEquivalence = true;
11468                     break;
11469                 }
11470             }
11471         }
11472     }
11473 #endif //FEATURE_TYPEEQUIVALENCE
11474 }
11475
11476 //*******************************************************************************
11477 //
11478 // Used by BuildMethodTable
11479 //
11480 // Before we make the final leap, make sure we've allocated all memory needed to
11481 // fill out the RID maps.
11482 //
11483 VOID MethodTableBuilder::EnsureRIDMapsCanBeFilled()
11484 {
11485     STANDARD_VM_CONTRACT;
11486
11487
11488     DWORD i;
11489
11490
11491     // Rather than call Ensure***CanBeStored() hundreds of times, we
11492     // will call it once on the largest token we find. This relies
11493     // on an invariant that RidMaps don't use some kind of sparse
11494     // allocation.
11495
11496     {
11497         mdMethodDef largest = mdMethodDefNil;
11498
11499         DeclaredMethodIterator it(*this);
11500         while (it.Next())
11501         {
11502             if (it.Token() > largest)
11503             {
11504                 largest = it.Token();
11505             }
11506         }
11507         if ( largest != mdMethodDefNil )
11508         {
11509             GetModule()->EnsureMethodDefCanBeStored(largest);
11510         }
11511     }
11512
11513     {
11514         mdFieldDef largest = mdFieldDefNil;
11515
11516         for (i = 0; i < bmtMetaData->cFields; i++)
11517         {
11518             if (bmtMetaData->pFields[i] > largest)
11519             {
11520                 largest = bmtMetaData->pFields[i];
11521             }
11522         }
11523         if ( largest != mdFieldDefNil )
11524         {
11525             GetModule()->EnsureFieldDefCanBeStored(largest);
11526         }
11527     }
11528 }
11529
11530 #ifdef FEATURE_COMINTEROP
11531 //*******************************************************************************
11532 void MethodTableBuilder::GetCoClassAttribInfo()
11533 {
11534     STANDARD_VM_CONTRACT;
11535
11536     if (!GetHalfBakedClass()->IsProjectedFromWinRT()) // ignore classic COM interop CA on WinRT interfaces
11537     {
11538         // Retrieve the CoClassAttribute CA.
11539         HRESULT hr = GetMDImport()->GetCustomAttributeByName(GetCl(), INTEROP_COCLASS_TYPE, NULL, NULL);
11540         if (hr == S_OK)
11541         {
11542             // COM class interfaces may lazily populate the m_pCoClassForIntf field of EEClass. This field is
11543             // optional so we must ensure the optional field descriptor has been allocated.
11544             EnsureOptionalFieldsAreAllocated(GetHalfBakedClass(), m_pAllocMemTracker, GetLoaderAllocator()->GetLowFrequencyHeap());
11545             SetIsComClassInterface();
11546         }
11547     }
11548 }
11549 #endif // FEATURE_COMINTEROP
11550
11551 //*******************************************************************************
11552 void MethodTableBuilder::bmtMethodImplInfo::AddMethodImpl(
11553     bmtMDMethod * pImplMethod, bmtMethodHandle declMethod, mdToken declToken,
11554     StackingAllocator * pStackingAllocator)
11555 {
11556     STANDARD_VM_CONTRACT;
11557
11558     CONSISTENCY_CHECK(CheckPointer(pImplMethod));
11559     CONSISTENCY_CHECK(!declMethod.IsNull());
11560     if (pIndex >= cMaxIndex)
11561     {
11562         DWORD newEntriesCount = 0;
11563
11564         if (!ClrSafeInt<DWORD>::multiply(cMaxIndex, 2, newEntriesCount))
11565             ThrowHR(COR_E_OVERFLOW);
11566
11567         if (newEntriesCount == 0)
11568             newEntriesCount = 10;
11569
11570         // If we have to grow this array, we will not free the old array before we clean up the BuildMethodTable operation
11571         // because this is a stacking allocator. However, the old array will get freed when all the stack allocator is freed.
11572         Entry *rgEntriesNew = new (pStackingAllocator) Entry[newEntriesCount];
11573         memcpy(rgEntriesNew, rgEntries, sizeof(Entry) * cMaxIndex);
11574
11575         // Start using newly allocated array.
11576         rgEntries = rgEntriesNew;
11577         cMaxIndex = newEntriesCount;
11578     }
11579     rgEntries[pIndex++] = Entry(pImplMethod, declMethod, declToken);
11580 }
11581
11582 //*******************************************************************************
11583 // Returns TRUE if tok acts as a body for any methodImpl entry. FALSE, otherwise.
11584 BOOL MethodTableBuilder::bmtMethodImplInfo::IsBody(mdToken tok)
11585 {
11586     LIMITED_METHOD_CONTRACT;
11587     CONSISTENCY_CHECK(TypeFromToken(tok) == mdtMethodDef);
11588     for (DWORD i = 0; i < pIndex; i++)
11589     {
11590         if (GetBodyMethodDesc(i)->GetMemberDef() == tok)
11591         {
11592             return TRUE;
11593         }
11594     }
11595     return FALSE;
11596 }
11597
11598 //*******************************************************************************
11599 BYTE *
11600 MethodTableBuilder::AllocateFromHighFrequencyHeap(S_SIZE_T cbMem)
11601 {
11602     CONTRACTL
11603     {
11604         THROWS;
11605         GC_NOTRIGGER;
11606         MODE_ANY;
11607     }
11608     CONTRACTL_END;
11609     return (BYTE *)GetMemTracker()->Track(
11610         GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem(cbMem));
11611 }
11612
11613 //*******************************************************************************
11614 BYTE *
11615 MethodTableBuilder::AllocateFromLowFrequencyHeap(S_SIZE_T cbMem)
11616 {
11617     CONTRACTL
11618     {
11619         THROWS;
11620         GC_NOTRIGGER;
11621         MODE_ANY;
11622     }
11623     CONTRACTL_END;
11624     return (BYTE *)GetMemTracker()->Track(
11625         GetLoaderAllocator()->GetLowFrequencyHeap()->AllocMem(cbMem));
11626 }
11627
11628 //-------------------------------------------------------------------------------
11629 // Make best-case effort to obtain an image name for use in an error message.
11630 //
11631 // This routine must expect to be called before the this object is fully loaded.
11632 // It can return an empty if the name isn't available or the object isn't initialized
11633 // enough to get a name, but it mustn't crash.
11634 //-------------------------------------------------------------------------------
11635 LPCWSTR MethodTableBuilder::GetPathForErrorMessages()
11636 {
11637     STANDARD_VM_CONTRACT;
11638
11639     return GetModule()->GetPathForErrorMessages();
11640 }
11641
11642 BOOL MethodTableBuilder::ChangesImplementationOfVirtualSlot(SLOT_INDEX idx)
11643 {
11644     STANDARD_VM_CONTRACT;
11645
11646     BOOL fChangesImplementation = TRUE;
11647
11648     _ASSERTE(idx < bmtVT->cVirtualSlots);
11649
11650     if (HasParent() && idx < GetParentMethodTable()->GetNumVirtuals())
11651     {
11652         _ASSERTE(idx < bmtParent->pSlotTable->GetSlotCount());
11653         bmtMethodHandle VTImpl = (*bmtVT)[idx].Impl();
11654         bmtMethodHandle ParentImpl = (*bmtParent)[idx].Impl();
11655
11656         fChangesImplementation = VTImpl != ParentImpl;
11657
11658         // See code:MethodTableBuilder::SetupMethodTable2 and its logic
11659         // for handling MethodImpl's on parent classes which affect non interface
11660         // methods.
11661         if (!fChangesImplementation && (ParentImpl.GetSlotIndex() != idx))
11662             fChangesImplementation = TRUE;
11663     }
11664
11665     return fChangesImplementation;
11666 }
11667
11668 // Must be called prior to setting the value of any optional field on EEClass (on a debug build an assert will
11669 // fire if this invariant is violated).
11670 void MethodTableBuilder::EnsureOptionalFieldsAreAllocated(EEClass *pClass, AllocMemTracker *pamTracker, LoaderHeap *pHeap)
11671 {
11672     STANDARD_VM_CONTRACT;
11673
11674     if (pClass->HasOptionalFields())
11675         return;
11676
11677     EEClassOptionalFields *pOptFields = (EEClassOptionalFields*)
11678         pamTracker->Track(pHeap->AllocMem(S_SIZE_T(sizeof(EEClassOptionalFields))));
11679
11680     // Initialize default values for all optional fields.
11681     pOptFields->Init();
11682
11683     // Attach optional fields to the class.
11684     pClass->AttachOptionalFields(pOptFields);
11685 }
11686
11687 //---------------------------------------------------------------------------------------
11688 // 
11689 // Gather information about a generic type
11690 // - number of parameters
11691 // - variance annotations
11692 // - dictionaries
11693 // - sharability
11694 // 
11695 //static
11696 void 
11697 MethodTableBuilder::GatherGenericsInfo(
11698     Module *          pModule, 
11699     mdTypeDef         cl, 
11700     Instantiation     inst, 
11701     bmtGenericsInfo * bmtGenericsInfo)
11702 {
11703     CONTRACTL
11704     {
11705         STANDARD_VM_CHECK;
11706         PRECONDITION(GetThread() != NULL);
11707         PRECONDITION(CheckPointer(pModule));
11708         PRECONDITION(CheckPointer(bmtGenericsInfo));
11709     }
11710     CONTRACTL_END;
11711
11712     IMDInternalImport * pInternalImport = pModule->GetMDImport();
11713
11714     // Enumerate the formal type parameters
11715     HENUMInternal   hEnumGenericPars;
11716     HRESULT hr = pInternalImport->EnumInit(mdtGenericParam, cl, &hEnumGenericPars);
11717     if (FAILED(hr))
11718         pModule->GetAssembly()->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
11719
11720     DWORD numGenericArgs = pInternalImport->EnumGetCount(&hEnumGenericPars);
11721
11722     // Work out what kind of EEClass we're creating w.r.t. generics.  If there
11723     // are no generics involved this will be a VMFLAG_NONGENERIC.
11724     BOOL fHasVariance = FALSE;
11725     if (numGenericArgs > 0)
11726     {
11727         // Generic type verification
11728         {
11729             DWORD   dwAttr;
11730             mdToken tkParent;
11731             if (FAILED(pInternalImport->GetTypeDefProps(cl, &dwAttr, &tkParent)))
11732             {
11733                 pModule->GetAssembly()->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
11734             }
11735             // A generic with explicit layout is not allowed.
11736             if (IsTdExplicitLayout(dwAttr))
11737             {
11738                 pModule->GetAssembly()->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_EXPLICIT_GENERIC);
11739             }
11740         }
11741         
11742         bmtGenericsInfo->numDicts = 1;
11743         
11744         mdGenericParam tkTyPar;
11745         bmtGenericsInfo->pVarianceInfo = new (&GetThread()->m_MarshalAlloc) BYTE[numGenericArgs];
11746
11747         // If it has generic arguments but none have been specified, then load the instantiation at the formals
11748         if (inst.IsEmpty())
11749         {
11750             bmtGenericsInfo->fTypicalInstantiation = TRUE;
11751             S_UINT32 scbAllocSize = S_UINT32(numGenericArgs) * S_UINT32(sizeof(TypeHandle));
11752             TypeHandle * genericArgs = (TypeHandle *) GetThread()->m_MarshalAlloc.Alloc(scbAllocSize);
11753
11754             inst = Instantiation(genericArgs, numGenericArgs);
11755
11756             bmtGenericsInfo->fSharedByGenericInstantiations = FALSE;
11757         }
11758         else
11759         {
11760             bmtGenericsInfo->fTypicalInstantiation = FALSE;
11761
11762             bmtGenericsInfo->fSharedByGenericInstantiations = TypeHandle::IsCanonicalSubtypeInstantiation(inst);
11763             _ASSERTE(bmtGenericsInfo->fSharedByGenericInstantiations == ClassLoader::IsSharableInstantiation(inst));
11764
11765 #ifdef _DEBUG
11766             // Set typical instantiation MethodTable
11767             {
11768                 MethodTable * pTypicalInstantiationMT = pModule->LookupTypeDef(cl).AsMethodTable();
11769                 // Typical instantiation was already loaded by code:ClassLoader::LoadApproxTypeThrowing
11770                 _ASSERTE(pTypicalInstantiationMT != NULL);
11771                 bmtGenericsInfo->dbg_pTypicalInstantiationMT = pTypicalInstantiationMT;
11772             }
11773 #endif //_DEBUG
11774         }
11775         
11776         TypeHandle * pDestInst = (TypeHandle *)inst.GetRawArgs();
11777         for (unsigned int i = 0; i < numGenericArgs; i++)
11778         {
11779             pInternalImport->EnumNext(&hEnumGenericPars, &tkTyPar);
11780             DWORD flags;
11781             if (FAILED(pInternalImport->GetGenericParamProps(tkTyPar, NULL, &flags, NULL, NULL, NULL)))
11782             {
11783                 pModule->GetAssembly()->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
11784             }
11785             
11786             if (bmtGenericsInfo->fTypicalInstantiation)
11787             {
11788                 // code:Module.m_GenericParamToDescMap maps generic parameter RIDs to TypeVarTypeDesc
11789                 // instances so that we do not leak by allocating them all over again, if the type
11790                 // repeatedly fails to load.
11791                 TypeVarTypeDesc *pTypeVarTypeDesc = pModule->LookupGenericParam(tkTyPar);
11792                 if (pTypeVarTypeDesc == NULL)
11793                 {
11794                     // Do NOT use the alloc tracker for this memory as we need it stay allocated even if the load fails.
11795                     void *mem = (void *)pModule->GetLoaderAllocator()->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(TypeVarTypeDesc)));
11796                     pTypeVarTypeDesc = new (mem) TypeVarTypeDesc(pModule, cl, i, tkTyPar);
11797
11798                     // No race here - the row in GenericParam table is owned exclusively by this type and we
11799                     // are holding a lock preventing other threads from concurrently loading it.
11800                     pModule->StoreGenericParamThrowing(tkTyPar, pTypeVarTypeDesc);
11801                 }
11802                 pDestInst[i] = TypeHandle(pTypeVarTypeDesc);
11803             }
11804
11805             DWORD varianceAnnotation = flags & gpVarianceMask;
11806             bmtGenericsInfo->pVarianceInfo[i] = static_cast<BYTE>(varianceAnnotation);
11807             if (varianceAnnotation != gpNonVariant)               
11808             {
11809                 if (varianceAnnotation != gpContravariant && varianceAnnotation != gpCovariant)
11810                 {
11811                     pModule->GetAssembly()->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADVARIANCE);
11812                 }
11813                 else
11814                 {
11815                     fHasVariance = TRUE;
11816                 }
11817             }
11818         }
11819
11820         if (!fHasVariance)
11821             bmtGenericsInfo->pVarianceInfo = NULL;
11822     }
11823     else
11824     {
11825         bmtGenericsInfo->fTypicalInstantiation = FALSE;
11826         bmtGenericsInfo->fSharedByGenericInstantiations = FALSE;
11827         bmtGenericsInfo->numDicts = 0;
11828     }
11829
11830     bmtGenericsInfo->fContainsGenericVariables = MethodTable::ComputeContainsGenericVariables(inst);
11831
11832     SigTypeContext typeContext(inst, Instantiation());
11833     bmtGenericsInfo->typeContext = typeContext;
11834 } // MethodTableBuilder::GatherGenericsInfo
11835
11836 //---------------------------------------------------------------------------------------
11837 // 
11838 // This service is called for normal classes -- and for the pseudo class we invent to
11839 // hold the module's public members.
11840 // 
11841 //static
11842 TypeHandle 
11843 ClassLoader::CreateTypeHandleForTypeDefThrowing(
11844     Module *          pModule, 
11845     mdTypeDef         cl, 
11846     Instantiation     inst, 
11847     AllocMemTracker * pamTracker)
11848 {
11849     CONTRACT(TypeHandle)
11850     {
11851         STANDARD_VM_CHECK;
11852         PRECONDITION(GetThread() != NULL);
11853         PRECONDITION(CheckPointer(pModule));
11854         POSTCONDITION(!RETVAL.IsNull());
11855         POSTCONDITION(CheckPointer(RETVAL.GetMethodTable()));
11856     }
11857     CONTRACT_END;
11858
11859     MethodTable * pMT = NULL;
11860
11861     Thread * pThread = GetThread();
11862
11863     MethodTable * pParentMethodTable = NULL;
11864     SigPointer    parentInst;
11865     mdTypeDef     tdEnclosing = mdTypeDefNil;
11866     DWORD         cInterfaces;
11867     BuildingInterfaceInfo_t * pInterfaceBuildInfo = NULL;
11868     IMDInternalImport *       pInternalImport = NULL;
11869     LayoutRawFieldInfo *      pLayoutRawFieldInfos = NULL;
11870     MethodTableBuilder::bmtGenericsInfo genericsInfo;
11871     
11872     Assembly * pAssembly = pModule->GetAssembly();
11873     pInternalImport = pModule->GetMDImport();
11874
11875     if (TypeFromToken(cl) != mdtTypeDef || !pInternalImport->IsValidToken(cl))
11876     {
11877         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
11878     }
11879
11880     // GetCheckpoint for the thread-based allocator
11881     // This checkpoint provides a scope for all transient allocations of data structures
11882     // used during class loading.
11883     // <NICE> Ideally a debug/checked build should pass around tokens indicating the Checkpoint
11884     // being used and check these dynamically </NICE>
11885     CheckPointHolder cph(pThread->m_MarshalAlloc.GetCheckpoint()); //hold checkpoint for autorelease
11886     
11887     // Gather up generics info
11888     MethodTableBuilder::GatherGenericsInfo(pModule, cl, inst, &genericsInfo);
11889
11890     Module * pLoaderModule = pModule;
11891     if (!inst.IsEmpty())
11892     {
11893         pLoaderModule = ClassLoader::ComputeLoaderModuleWorker(
11894             pModule, 
11895             cl, 
11896             inst, 
11897             Instantiation());
11898         pLoaderModule->GetLoaderAllocator()->EnsureInstantiation(pModule, inst);
11899     }
11900
11901     LoaderAllocator * pAllocator = pLoaderModule->GetLoaderAllocator();
11902
11903     {
11904         // As this is loading a parent type, we are allowed to override the load type limit.
11905         OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOAD_APPROXPARENTS);
11906         pParentMethodTable = LoadApproxParentThrowing(pModule, cl, &parentInst, &genericsInfo.typeContext);
11907     }
11908
11909     if (pParentMethodTable != NULL)
11910     {
11911         // Since methods on System.Array assume the layout of arrays, we can not allow
11912         // subclassing of arrays, it is sealed from the users point of view.
11913         // Value types and enums should be sealed - disable inheritting from them (we cannot require sealed 
11914         // flag because of AppCompat)
11915         if (pParentMethodTable->IsSealed() || 
11916             (pParentMethodTable == g_pArrayClass) || 
11917             pParentMethodTable->IsValueType())
11918         {
11919             pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_SEALEDPARENT);
11920         }
11921
11922         DWORD dwTotalDicts = genericsInfo.numDicts + pParentMethodTable->GetNumDicts();
11923         if (!FitsIn<WORD>(dwTotalDicts))
11924         {
11925             pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_TOOMANYGENERICARGS);
11926         }
11927         genericsInfo.numDicts = static_cast<WORD>(dwTotalDicts);
11928     }
11929
11930     GetEnclosingClassThrowing(pInternalImport, pModule, cl, &tdEnclosing);
11931
11932     BYTE nstructPackingSize = 0, nstructNLT = 0;
11933     BOOL fExplicitOffsets = FALSE;
11934     // NOTE: HasLayoutMetadata does not load classes
11935     BOOL fHasLayout = 
11936         !genericsInfo.fContainsGenericVariables && 
11937         HasLayoutMetadata(
11938             pModule->GetAssembly(), 
11939             pInternalImport, 
11940             cl, 
11941             pParentMethodTable, 
11942             &nstructPackingSize, 
11943             &nstructNLT, 
11944             &fExplicitOffsets);
11945
11946     BOOL fIsEnum = ((g_pEnumClass != NULL) && (pParentMethodTable == g_pEnumClass));
11947
11948     // enums may not have layout because they derive from g_pEnumClass and that has no layout
11949     // this is enforced by HasLayoutMetadata above
11950     _ASSERTE(!(fIsEnum && fHasLayout));
11951
11952     // This is a delegate class if it derives from MulticastDelegate (we do not allow single cast delegates)
11953     BOOL fIsDelegate = pParentMethodTable && pParentMethodTable == g_pMulticastDelegateClass;
11954
11955     // Create a EEClass entry for it, filling out a few fields, such as the parent class token
11956     // (and the generic type should we be creating an instantiation)
11957     EEClass * pClass = MethodTableBuilder::CreateClass(
11958         pModule, 
11959         cl, 
11960         fHasLayout, 
11961         fIsDelegate, 
11962         fIsEnum, 
11963         &genericsInfo, 
11964         pAllocator, 
11965         pamTracker);
11966
11967     if ((pParentMethodTable != NULL) && (pParentMethodTable == g_pDelegateClass))
11968     {
11969         // Note we do not allow single cast delegates
11970         if (pModule->GetAssembly() != SystemDomain::SystemAssembly())
11971         {
11972             pAssembly->ThrowTypeLoadException(pInternalImport, cl, BFA_CANNOT_INHERIT_FROM_DELEGATE);
11973         }
11974
11975 #ifdef _DEBUG
11976         // Only MultiCastDelegate should inherit from Delegate
11977         LPCUTF8 className;
11978         LPCUTF8 nameSpace;
11979         if (FAILED(pInternalImport->GetNameOfTypeDef(cl, &className, &nameSpace)))
11980         {
11981             className = nameSpace = "Invalid TypeDef record";
11982         }
11983         BAD_FORMAT_NOTHROW_ASSERT(strcmp(className, "MulticastDelegate") == 0);
11984 #endif
11985     }
11986
11987     if (fIsDelegate)
11988     {
11989         if (!pClass->IsSealed())
11990         {
11991             pAssembly->ThrowTypeLoadException(pInternalImport, cl, BFA_DELEGATE_CLASS_NOTSEALED);
11992         }
11993
11994         pClass->SetIsDelegate();
11995     }
11996
11997     if (tdEnclosing != mdTypeDefNil)
11998     {
11999         pClass->SetIsNested();
12000         THROW_BAD_FORMAT_MAYBE(IsTdNested(pClass->GetProtection()), VLDTR_E_TD_ENCLNOTNESTED, pModule);
12001     }
12002     else if (IsTdNested(pClass->GetProtection()))
12003     {
12004         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12005     }
12006     
12007     // We only permit generic interfaces and delegates to have variant type parameters
12008     if (genericsInfo.pVarianceInfo != NULL && !pClass->IsInterface() && !fIsDelegate)
12009     {
12010         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_VARIANCE_CLASS);
12011     }
12012     
12013     // Now load all the interfaces
12014     HENUMInternalHolder hEnumInterfaceImpl(pInternalImport);
12015     hEnumInterfaceImpl.EnumInit(mdtInterfaceImpl, cl);
12016     
12017     cInterfaces = pInternalImport->EnumGetCount(&hEnumInterfaceImpl);
12018     
12019     if (cInterfaces != 0)
12020     {
12021         DWORD i;
12022         
12023         // Allocate the BuildingInterfaceList table
12024         pInterfaceBuildInfo = new (&GetThread()->m_MarshalAlloc) BuildingInterfaceInfo_t[cInterfaces];
12025         
12026         mdInterfaceImpl ii;
12027         for (i = 0; pInternalImport->EnumNext(&hEnumInterfaceImpl, &ii); i++)
12028         {
12029             // Get properties on this interface
12030             mdTypeRef crInterface;
12031             if (FAILED(pInternalImport->GetTypeOfInterfaceImpl(ii, &crInterface)))
12032             {
12033                 pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12034             }
12035             // validate the token
12036             mdToken crIntType = 
12037                 (RidFromToken(crInterface) && pInternalImport->IsValidToken(crInterface)) ? 
12038                 TypeFromToken(crInterface) : 
12039                 0;
12040             switch (crIntType)
12041             {
12042                 case mdtTypeDef:
12043                 case mdtTypeRef:
12044                 case mdtTypeSpec:
12045                     break;
12046                 default:
12047                     pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_INTERFACENULL);
12048             }
12049             
12050             TypeHandle intType;
12051             
12052             {
12053                 OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOAD_APPROXPARENTS);
12054                 intType = LoadApproxTypeThrowing(pModule, crInterface, NULL, &genericsInfo.typeContext);
12055             }
12056             
12057             pInterfaceBuildInfo[i].m_pMethodTable = intType.AsMethodTable();
12058             if (pInterfaceBuildInfo[i].m_pMethodTable == NULL)
12059             {
12060                 pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_INTERFACENULL);
12061             }
12062             
12063             // Ensure this is an interface
12064             if (!pInterfaceBuildInfo[i].m_pMethodTable->IsInterface())
12065             {
12066                  pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_NOTINTERFACE);
12067             }
12068             
12069             // Check interface for use of variant type parameters
12070             if ((genericsInfo.pVarianceInfo != NULL) && (TypeFromToken(crInterface) == mdtTypeSpec))
12071             {
12072                 ULONG cSig;
12073                 PCCOR_SIGNATURE pSig;
12074                 if (FAILED(pInternalImport->GetTypeSpecFromToken(crInterface, &pSig, &cSig)))
12075                 {
12076                     pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12077                 }
12078                 // Interfaces behave covariantly
12079                 if (!EEClass::CheckVarianceInSig(
12080                         genericsInfo.GetNumGenericArgs(), 
12081                         genericsInfo.pVarianceInfo, 
12082                         pModule, 
12083                         SigPointer(pSig, cSig), 
12084                         gpCovariant))
12085                 {
12086                     pAssembly->ThrowTypeLoadException(
12087                         pInternalImport, 
12088                         cl, 
12089                         IDS_CLASSLOAD_VARIANCE_IN_INTERFACE);
12090                 }
12091             }
12092         }
12093         _ASSERTE(i == cInterfaces);
12094     }
12095     
12096     if (fHasLayout ||
12097         /* Variant delegates should not have any instance fields of the variant.
12098            type parameter. For now, we just completely disallow all fields even
12099            if they are non-variant or static, as it is not a useful scenario.
12100            @TODO: A more logical place for this check would be in 
12101            MethodTableBuilder::EnumerateClassMembers() */
12102         (fIsDelegate && genericsInfo.pVarianceInfo))
12103     {
12104         // check for fields and variance
12105         ULONG               cFields;
12106         HENUMInternalHolder hEnumField(pInternalImport);
12107         hEnumField.EnumInit(mdtFieldDef, cl);
12108
12109         cFields = pInternalImport->EnumGetCount(&hEnumField);
12110
12111         if ((cFields != 0) && fIsDelegate && (genericsInfo.pVarianceInfo != NULL))
12112         {
12113             pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_VARIANCE_IN_DELEGATE);
12114         }
12115
12116         if (fHasLayout)
12117         {
12118             // Though we fail on this condition, we should never run into it.
12119             CONSISTENCY_CHECK(nstructPackingSize != 0);
12120             // MD Val check: PackingSize
12121             if((nstructPackingSize == 0)  || 
12122                (nstructPackingSize > 128) || 
12123                (nstructPackingSize & (nstructPackingSize-1)))
12124             {
12125                 THROW_BAD_FORMAT_MAYBE(!"ClassLayout:Invalid PackingSize", BFA_BAD_PACKING_SIZE, pModule);
12126                 pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12127             }
12128
12129             pLayoutRawFieldInfos = (LayoutRawFieldInfo *)GetThread()->m_MarshalAlloc.Alloc(
12130                 (S_UINT32(1) + S_UINT32(cFields)) * S_UINT32(sizeof(LayoutRawFieldInfo)));
12131             
12132             {
12133                 // Warning: this can load classes
12134                 CONTRACT_VIOLATION(LoadsTypeViolation);
12135
12136                 // Set a flag that allows us to break dead-locks that are result of the LoadsTypeViolation
12137                 ThreadStateNCStackHolder tsNC(TRUE, Thread::TSNC_LoadsTypeViolation);
12138
12139                 EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing(
12140                     cl, 
12141                     nstructPackingSize, 
12142                     nstructNLT, 
12143 #ifdef FEATURE_COMINTEROP
12144                     pClass->IsProjectedFromWinRT(),
12145 #endif // FEATURE_COMINTEROP
12146                     fExplicitOffsets, 
12147                     pParentMethodTable, 
12148                     cFields, 
12149                     &hEnumField, 
12150                     pModule, 
12151                     &genericsInfo.typeContext, 
12152                     &(((LayoutEEClass *)pClass)->m_LayoutInfo), 
12153                     pLayoutRawFieldInfos, 
12154                     pAllocator, 
12155                     pamTracker);
12156             }
12157         }
12158     }
12159
12160     // Resolve this class, given that we know now that all of its dependencies are loaded and resolved.
12161     // !!! This must be the last thing in this TRY block: if MethodTableBuilder succeeds, it has published the class
12162     // and there is no going back.
12163     MethodTableBuilder builder(
12164         NULL,
12165         pClass,
12166         &GetThread()->m_MarshalAlloc, 
12167         pamTracker);
12168
12169     pMT = builder.BuildMethodTableThrowing(
12170         pAllocator, 
12171         pLoaderModule, 
12172         pModule, 
12173         cl, 
12174         pInterfaceBuildInfo, 
12175         pLayoutRawFieldInfos, 
12176         pParentMethodTable, 
12177         &genericsInfo, 
12178         parentInst, 
12179         (WORD)cInterfaces);
12180
12181     RETURN(TypeHandle(pMT));
12182 } // ClassLoader::CreateTypeHandleForTypeDefThrowing