d4ce5b0df0d2b9a4ce054344e75bcc8f555cad61
[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         // Some interface checks.
2896         // We only need them if default interface method support is disabled or if this is fragile crossgen
2897 #if !defined(FEATURE_DEFAULT_INTERFACES) || defined(FEATURE_NATIVE_IMAGE_GENERATION)
2898         if (fIsClassInterface
2899 #if defined(FEATURE_DEFAULT_INTERFACES)
2900             // Only fragile crossgen wasn't upgraded to deal with default interface methods.
2901             && !IsReadyToRunCompilation()
2902 #endif
2903             )
2904         {
2905             if (IsMdVirtual(dwMemberAttrs))
2906             {
2907                 if (!IsMdAbstract(dwMemberAttrs))
2908                 {
2909                     BuildMethodTableThrowException(BFA_VIRTUAL_NONAB_INT_METHOD);
2910                 }
2911             }
2912             else
2913             {
2914                 // Instance method
2915                 if (!IsMdStatic(dwMemberAttrs))
2916                 {
2917                     BuildMethodTableThrowException(BFA_NONVIRT_INST_INT_METHOD);
2918                 }
2919             }
2920         }
2921 #endif // !defined(FEATURE_DEFAULT_INTERFACES) || defined(FEATURE_NATIVE_IMAGE_GENERATION)
2922
2923         // No synchronized methods in ValueTypes
2924         if(fIsClassValueType && IsMiSynchronized(dwImplFlags))
2925         {
2926             BuildMethodTableThrowException(BFA_SYNC_METHOD_IN_VT);
2927         }
2928
2929         // Global methods:
2930         if(IsGlobalClass())
2931         {
2932             if(!IsMdStatic(dwMemberAttrs))
2933             {
2934                 BuildMethodTableThrowException(BFA_NONSTATIC_GLOBAL_METHOD);
2935             }
2936             if (strMethodName)  //<TODO>@todo: investigate mc++ generating null name</TODO>
2937             {
2938                 if(0==strcmp(strMethodName, COR_CTOR_METHOD_NAME))
2939                 {
2940                     BuildMethodTableThrowException(BFA_GLOBAL_INST_CTOR);
2941                 }
2942             }
2943         }
2944         //@GENERICS:
2945         // Generic methods or methods in generic classes
2946         // may not be part of a COM Import class (except for WinRT), PInvoke, internal call outside mscorlib.
2947         if ((bmtGenerics->GetNumGenericArgs() != 0 || numGenericMethodArgs != 0) &&
2948             (
2949 #ifdef FEATURE_COMINTEROP 
2950              fIsClassComImport ||
2951              bmtProp->fComEventItfType ||
2952 #endif // FEATURE_COMINTEROP
2953              IsMdPinvokeImpl(dwMemberAttrs) ||
2954              (IsMiInternalCall(dwImplFlags) && !GetModule()->IsSystem())))
2955         {
2956 #ifdef FEATURE_COMINTEROP
2957             if (!GetHalfBakedClass()->IsProjectedFromWinRT())
2958 #endif // FEATURE_COMINTEROP
2959             {
2960                 BuildMethodTableThrowException(BFA_BAD_PLACE_FOR_GENERIC_METHOD);
2961             }
2962         }
2963
2964         // Generic methods may not be marked "runtime".  However note that
2965         // methods in generic delegate classes are, hence we don't apply this to
2966         // methods in generic classes in general.
2967         if (numGenericMethodArgs != 0 && IsMiRuntime(dwImplFlags))
2968         {
2969             BuildMethodTableThrowException(BFA_GENERIC_METHOD_RUNTIME_IMPL);
2970         }
2971
2972
2973         // Signature validation
2974         if (FAILED(pMDInternalImport->GetSigOfMethodDef(tok, &cMemberSignature, &pMemberSignature)))
2975         {
2976             BuildMethodTableThrowException(hr, BFA_BAD_SIGNATURE, mdMethodDefNil);
2977         }
2978         hr = validateTokenSig(tok,pMemberSignature,cMemberSignature,dwMemberAttrs,pMDInternalImport);
2979         if (FAILED(hr))
2980         {
2981             BuildMethodTableThrowException(hr, BFA_BAD_SIGNATURE, mdMethodDefNil);
2982         }
2983
2984         // Check the appearance of covariant and contravariant in the method signature
2985         // Note that variance is only supported for interfaces
2986         if (bmtGenerics->pVarianceInfo != NULL)
2987         {
2988             SigPointer sp(pMemberSignature, cMemberSignature);
2989             ULONG callConv;
2990             IfFailThrow(sp.GetCallingConvInfo(&callConv));
2991
2992             if (callConv & IMAGE_CEE_CS_CALLCONV_GENERIC)
2993                 IfFailThrow(sp.GetData(NULL));
2994
2995             DWORD numArgs;
2996             IfFailThrow(sp.GetData(&numArgs));
2997
2998             // Return type behaves covariantly
2999             if (!EEClass::CheckVarianceInSig(
3000                     bmtGenerics->GetNumGenericArgs(), 
3001                     bmtGenerics->pVarianceInfo, 
3002                     GetModule(), 
3003                     sp, 
3004                     gpCovariant))
3005             {
3006                 BuildMethodTableThrowException(IDS_CLASSLOAD_VARIANCE_IN_METHOD_RESULT, tok);
3007             }
3008             IfFailThrow(sp.SkipExactlyOne());
3009             for (DWORD j = 0; j < numArgs; j++)
3010             {
3011                 // Argument types behave contravariantly
3012                 if (!EEClass::CheckVarianceInSig(bmtGenerics->GetNumGenericArgs(),
3013                                                  bmtGenerics->pVarianceInfo,
3014                                                  GetModule(),
3015                                                  sp,
3016                                                  gpContravariant))
3017                 {
3018                     BuildMethodTableThrowException(IDS_CLASSLOAD_VARIANCE_IN_METHOD_ARG, tok);
3019                 }
3020                 IfFailThrow(sp.SkipExactlyOne());
3021             }
3022         }
3023
3024         //
3025         // Determine the method's type
3026         //
3027
3028         if (IsReallyMdPinvokeImpl(dwMemberAttrs) || IsMiInternalCall(dwImplFlags))
3029         {
3030             hr = NDirect::HasNAT_LAttribute(pMDInternalImport, tok, dwMemberAttrs);
3031
3032             // There was a problem querying for the attribute
3033             if (FAILED(hr))
3034             {
3035                 BuildMethodTableThrowException(hr, IDS_CLASSLOAD_BADPINVOKE, tok);
3036             }
3037
3038             // The attribute is not present
3039             if (hr == S_FALSE)
3040             {
3041 #ifdef FEATURE_COMINTEROP
3042                 if (fIsClassComImport
3043                     || GetHalfBakedClass()->IsProjectedFromWinRT()
3044                     || bmtProp->fComEventItfType
3045                     )
3046                 {
3047                     // ComImport classes have methods which are just used
3048                     // for implementing all interfaces the class supports
3049                     type = METHOD_TYPE_COMINTEROP;
3050
3051                     // constructor is special
3052                     if (IsMdRTSpecialName(dwMemberAttrs))
3053                     {
3054                         // Note: Method name (.ctor) will be checked in code:ValidateMethods
3055                         
3056                         // WinRT ctors are interop calls via stubs
3057                         if (!GetHalfBakedClass()->IsProjectedFromWinRT())
3058                         {
3059                             // Ctor on a non-WinRT class
3060                             type = METHOD_TYPE_FCALL;
3061                         }
3062                     }
3063                 }
3064                 else 
3065 #endif //FEATURE_COMINTEROP
3066                 if (dwMethodRVA == 0)
3067                 {
3068                     type = METHOD_TYPE_FCALL;
3069                 }
3070                 else
3071                 {
3072                     type = METHOD_TYPE_NDIRECT;
3073                 }
3074             }
3075             // The NAT_L attribute is present, marking this method as NDirect
3076             else
3077             {
3078                 CONSISTENCY_CHECK(hr == S_OK);
3079                 type = METHOD_TYPE_NDIRECT;
3080             }
3081         }
3082         else if (IsMiRuntime(dwImplFlags))
3083         {
3084                 // currently the only runtime implemented functions are delegate instance methods
3085             if (!IsDelegate() || IsMdStatic(dwMemberAttrs) || IsMdAbstract(dwMemberAttrs))
3086             {
3087                 BuildMethodTableThrowException(BFA_BAD_RUNTIME_IMPL);
3088             }
3089
3090             unsigned newDelegateMethodSeen = 0;
3091
3092             if (IsMdRTSpecialName(dwMemberAttrs))   // .ctor
3093             {
3094                 if (strcmp(strMethodName, COR_CTOR_METHOD_NAME) != 0 || IsMdVirtual(dwMemberAttrs))
3095                 {
3096                     BuildMethodTableThrowException(BFA_BAD_FLAGS_ON_DELEGATE);
3097                 }
3098                 newDelegateMethodSeen = SeenCtor;
3099                 type = METHOD_TYPE_FCALL;
3100             }
3101             else
3102             {
3103                 if (strcmp(strMethodName, "Invoke") == 0)
3104                     newDelegateMethodSeen = SeenInvoke;
3105                 else if (strcmp(strMethodName, "BeginInvoke") == 0)
3106                     newDelegateMethodSeen = SeenBeginInvoke;
3107                 else if (strcmp(strMethodName, "EndInvoke") == 0)
3108                     newDelegateMethodSeen = SeenEndInvoke;
3109                 else
3110                 {
3111                     BuildMethodTableThrowException(BFA_UNKNOWN_DELEGATE_METHOD);
3112                 }
3113                 type = METHOD_TYPE_EEIMPL;
3114             }
3115
3116             // If we get here we have either set newDelegateMethodSeen or we have thrown a BMT exception
3117             _ASSERTE(newDelegateMethodSeen != 0);
3118
3119             if ((delegateMethodsSeen & newDelegateMethodSeen) != 0)
3120             {
3121                 BuildMethodTableThrowException(BFA_DUPLICATE_DELEGATE_METHOD);
3122             }
3123
3124             delegateMethodsSeen |= newDelegateMethodSeen;
3125         }
3126         else if (numGenericMethodArgs != 0)
3127         {
3128             //We use an instantiated method desc to represent a generic method
3129             type = METHOD_TYPE_INSTANTIATED;
3130         }
3131         else if (fIsClassInterface)
3132         {
3133 #ifdef FEATURE_COMINTEROP 
3134             if (IsMdStatic(dwMemberAttrs))
3135             {
3136                 // Static methods in interfaces need nothing special.
3137                 type = METHOD_TYPE_NORMAL;
3138             }
3139             else if (bmtGenerics->GetNumGenericArgs() != 0 &&
3140                 (bmtGenerics->fSharedByGenericInstantiations || (!bmtProp->fIsRedirectedInterface && !GetHalfBakedClass()->IsProjectedFromWinRT())))
3141             {
3142                 // Methods in instantiated interfaces need nothing special - they are not visible from COM etc.
3143                 // mcComInterop is only useful for unshared instantiated WinRT interfaces. If the interface is
3144                 // shared by multiple instantiations, the MD would be useless for interop anyway.
3145                 type = METHOD_TYPE_NORMAL;
3146             }
3147             else if (bmtProp->fIsMngStandardItf)
3148             {
3149                 // If the interface is a standard managed interface then allocate space for an FCall method desc.
3150                 type = METHOD_TYPE_FCALL;
3151             }
3152             else if (IsMdAbstract(dwMemberAttrs))
3153             {
3154                 // If COM interop is supported then all other interface MDs may be
3155                 // accessed via COM interop. mcComInterop MDs have an additional
3156                 // pointer-sized field pointing to COM interop data which are
3157                 // allocated lazily when/if the MD actually gets used for interop.
3158                 type = METHOD_TYPE_COMINTEROP;
3159             }
3160             else
3161 #endif // !FEATURE_COMINTEROP
3162             {
3163                 // This codepath is used by remoting
3164                 type = METHOD_TYPE_NORMAL;
3165             }
3166         }
3167         else
3168         {
3169             type = METHOD_TYPE_NORMAL;
3170         }
3171
3172         // Generic methods should always be METHOD_TYPE_INSTANTIATED
3173         if ((numGenericMethodArgs != 0) && (type != METHOD_TYPE_INSTANTIATED))
3174         {
3175             BuildMethodTableThrowException(BFA_GENERIC_METHODS_INST);
3176         }
3177
3178         // count how many overrides this method does All methods bodies are defined
3179         // on this type so we can just compare the tok with the body token found
3180         // from the overrides.
3181         implType = METHOD_IMPL_NOT;
3182         for (DWORD impls = 0; impls < bmtMethod->dwNumberMethodImpls; impls++)
3183         {
3184             if (bmtMetaData->rgMethodImplTokens[impls].methodBody == tok)
3185             {
3186                 implType = METHOD_IMPL;
3187                 break;
3188             }
3189         }
3190
3191         // For delegates we don't allow any non-runtime implemented bodies
3192         // for any of the four special methods
3193         if (IsDelegate() && !IsMiRuntime(dwImplFlags))
3194         {
3195             if ((strcmp(strMethodName, COR_CTOR_METHOD_NAME) == 0) ||
3196                 (strcmp(strMethodName, "Invoke")             == 0) ||
3197                 (strcmp(strMethodName, "BeginInvoke")        == 0) ||
3198                 (strcmp(strMethodName, "EndInvoke")          == 0)   )
3199             {
3200                 BuildMethodTableThrowException(BFA_ILLEGAL_DELEGATE_METHOD);
3201             }
3202         }
3203
3204         //
3205         // Create a new bmtMDMethod representing this method and add it to the
3206         // declared method list.
3207         //
3208
3209         bmtMDMethod * pNewMethod = new (GetStackingAllocator()) bmtMDMethod(
3210             bmtInternal->pType,
3211             tok,
3212             dwMemberAttrs,
3213             dwImplFlags,
3214             dwMethodRVA,
3215             type,
3216             implType);
3217
3218         bmtMethod->AddDeclaredMethod(pNewMethod);
3219
3220         //
3221         // Update the count of the various types of methods.
3222         //
3223
3224         bmtVT->dwMaxVtableSize++;
3225
3226         // Increment the number of non-abstract declared methods
3227         if (!IsMdAbstract(dwMemberAttrs))
3228         {
3229             bmtMethod->dwNumDeclaredNonAbstractMethods++;
3230         }
3231     }
3232
3233     // Check to see that we have all of the required delegate methods (ECMA 13.6 Delegates)
3234     if (IsDelegate())
3235     {
3236         // Do we have all four special delegate methods
3237         // or just the two special delegate methods
3238         if ((delegateMethodsSeen != (SeenCtor | SeenInvoke | SeenBeginInvoke | SeenEndInvoke)) &&
3239             (delegateMethodsSeen != (SeenCtor | SeenInvoke)) )
3240         {
3241             BuildMethodTableThrowException(BFA_MISSING_DELEGATE_METHOD);
3242         }
3243     }
3244
3245     if (i != cMethAndGaps)
3246     {
3247         BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_METHOD_COUNT, mdTokenNil);
3248     }
3249
3250 #ifdef FEATURE_COMINTEROP 
3251     //
3252     // If the interface is sparse, we need to finalize the mapping list by
3253     // telling it how many real methods we found.
3254     //
3255
3256     if (bmtProp->fSparse)
3257     {
3258         GetHalfBakedClass()->GetSparseCOMInteropVTableMap()->FinalizeMapping(NumDeclaredMethods());
3259     }
3260 #endif // FEATURE_COMINTEROP
3261 } // MethodTableBuilder::EnumerateClassMethods
3262 #ifdef _PREFAST_ 
3263 #pragma warning(pop)
3264 #endif
3265
3266 //*******************************************************************************
3267 //
3268 // Run through the field list and calculate the following:
3269 // # static fields
3270 // # static fields that contain object refs.
3271 // # instance fields
3272 //
3273 VOID
3274 MethodTableBuilder::EnumerateClassFields()
3275 {
3276     STANDARD_VM_CONTRACT;
3277
3278     HRESULT hr = S_OK;
3279     DWORD i;
3280     IMDInternalImport *pMDInternalImport = GetMDImport();
3281     mdToken tok;
3282     DWORD dwMemberAttrs;
3283
3284     bmtEnumFields->dwNumStaticFields        = 0;
3285     bmtEnumFields->dwNumStaticObjRefFields  = 0;
3286     bmtEnumFields->dwNumStaticBoxedFields   = 0;
3287
3288     bmtEnumFields->dwNumThreadStaticFields  = 0;
3289     bmtEnumFields->dwNumThreadStaticObjRefFields  = 0;
3290     bmtEnumFields->dwNumThreadStaticBoxedFields   = 0;
3291
3292     bmtEnumFields->dwNumInstanceFields      = 0;
3293
3294     HENUMInternalHolder hEnumField(pMDInternalImport);
3295     hr = hEnumField.EnumInitNoThrow(mdtFieldDef, GetCl());
3296     if (FAILED(hr))
3297     {
3298         BuildMethodTableThrowException(hr, *bmtError);
3299     }
3300
3301     bmtMetaData->cFields = hEnumField.EnumGetCount();
3302
3303     // Retrieve the fields and store them in a temp array.
3304     bmtMetaData->pFields = new (GetStackingAllocator()) mdToken[bmtMetaData->cFields];
3305     bmtMetaData->pFieldAttrs = new (GetStackingAllocator()) DWORD[bmtMetaData->cFields];
3306
3307     DWORD   dwFieldLiteralInitOnly = fdLiteral | fdInitOnly;
3308     DWORD   dwMaxFieldDefRid = pMDInternalImport->GetCountWithTokenKind(mdtFieldDef);
3309
3310     for (i = 0; hEnumField.EnumNext(&tok); i++)
3311     {
3312         //
3313         // Retrieve the attributes of the field.
3314         //
3315         DWORD rid = RidFromToken(tok);
3316         if ((rid == 0)||(rid > dwMaxFieldDefRid))
3317         {
3318             BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, BFA_BAD_FIELD_TOKEN, mdTokenNil);
3319         }
3320         
3321         if (FAILED(pMDInternalImport->GetFieldDefProps(tok, &dwMemberAttrs)))
3322         {
3323             BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, BFA_BAD_FIELD_TOKEN, tok);
3324         }
3325         
3326         //
3327         // Store the field and its attributes in the bmtMetaData structure for later use.
3328         //
3329
3330         bmtMetaData->pFields[i] = tok;
3331         bmtMetaData->pFieldAttrs[i] = dwMemberAttrs;
3332
3333         if((dwMemberAttrs & fdFieldAccessMask)==fdFieldAccessMask)
3334         {
3335             BuildMethodTableThrowException(BFA_INVALID_FIELD_ACC_FLAGS);
3336         }
3337         if((dwMemberAttrs & dwFieldLiteralInitOnly)==dwFieldLiteralInitOnly)
3338         {
3339             BuildMethodTableThrowException(BFA_FIELD_LITERAL_AND_INIT);
3340         }
3341
3342         // can only have static global fields
3343         if(IsGlobalClass())
3344         {
3345             if(!IsFdStatic(dwMemberAttrs))
3346             {
3347                 BuildMethodTableThrowException(BFA_NONSTATIC_GLOBAL_FIELD);
3348             }
3349         }
3350
3351         //
3352         // Update the count of the various types of fields.
3353         //
3354
3355         if (IsFdStatic(dwMemberAttrs))
3356         {
3357             if (!IsFdLiteral(dwMemberAttrs))
3358             {
3359 #ifdef FEATURE_TYPEEQUIVALENCE
3360                 if (bmtProp->fIsTypeEquivalent)
3361                 {
3362                     BuildMethodTableThrowException(IDS_CLASSLOAD_EQUIVALENTSTRUCTFIELDS);
3363                 }
3364 #endif
3365
3366                 bmtEnumFields->dwNumStaticFields++;
3367
3368                 // If this static field is thread static, then we need
3369                 // to increment bmtEnumFields->dwNumThreadStaticFields
3370                 hr = pMDInternalImport->GetCustomAttributeByName(tok,
3371                                                                  g_ThreadStaticAttributeClassName,
3372                                                                  NULL, NULL);
3373                 IfFailThrow(hr);
3374                 if (hr == S_OK)
3375                 {
3376                     // It's a thread static, so increment the count
3377                     bmtEnumFields->dwNumThreadStaticFields++;
3378                 }
3379             }
3380         }
3381         else
3382         {
3383 #ifdef FEATURE_TYPEEQUIVALENCE
3384             if (!IsFdPublic(dwMemberAttrs) && bmtProp->fIsTypeEquivalent)
3385             {
3386                 BuildMethodTableThrowException(IDS_CLASSLOAD_EQUIVALENTSTRUCTFIELDS);
3387             }
3388 #endif
3389
3390             if (!IsFdLiteral(dwMemberAttrs))
3391             {
3392                 bmtEnumFields->dwNumInstanceFields++;
3393             }
3394             if(IsInterface())
3395             {
3396                 BuildMethodTableThrowException(BFA_INSTANCE_FIELD_IN_INT);
3397             }
3398         }
3399     }
3400
3401     if (i != bmtMetaData->cFields)
3402     {
3403         BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD_COUNT, mdTokenNil);
3404     }
3405
3406     if(IsEnum() && (bmtEnumFields->dwNumInstanceFields==0))
3407     {
3408         BuildMethodTableThrowException(BFA_INSTANCE_FIELD_IN_ENUM);
3409     }
3410
3411     bmtEnumFields->dwNumDeclaredFields = bmtEnumFields->dwNumStaticFields + bmtEnumFields->dwNumInstanceFields;
3412 }
3413
3414 //*******************************************************************************
3415 //
3416 // Used by BuildMethodTable
3417 //
3418 // Determines the maximum size of the vtable and allocates the temporary storage arrays
3419 // Also copies the parent's vtable into the working vtable.
3420 //
3421 VOID    MethodTableBuilder::AllocateWorkingSlotTables()
3422 {
3423     CONTRACTL
3424     {
3425         STANDARD_VM_CHECK;
3426         PRECONDITION(CheckPointer(this));
3427         PRECONDITION(CheckPointer(bmtAllocator));
3428         PRECONDITION(CheckPointer(bmtMFDescs));
3429         PRECONDITION(CheckPointer(bmtMetaData));
3430         PRECONDITION(CheckPointer(bmtVT));
3431         PRECONDITION(CheckPointer(bmtEnumFields));
3432         PRECONDITION(CheckPointer(bmtInterface));
3433         PRECONDITION(CheckPointer(bmtFP));
3434         PRECONDITION(CheckPointer(bmtParent));
3435
3436     }
3437     CONTRACTL_END;
3438
3439     // Allocate a FieldDesc* for each field
3440     bmtMFDescs->ppFieldDescList = new (GetStackingAllocator()) FieldDesc*[bmtMetaData->cFields];
3441     ZeroMemory(bmtMFDescs->ppFieldDescList, bmtMetaData->cFields * sizeof(FieldDesc *));
3442
3443     // Create a temporary function table (we don't know how large the vtable will be until the very end,
3444     // since we don't yet know how many declared methods are overrides vs. newslots).
3445
3446     if (IsValueClass())
3447     {   // ValueClass virtuals are converted into non-virtual methods and the virtual slots
3448         // become unboxing stubs that forward to these new non-virtual methods. This has the
3449         // side effect of doubling the number of slots introduced by newslot virtuals.
3450         bmtVT->dwMaxVtableSize += NumDeclaredMethods();
3451     }
3452
3453     _ASSERTE(!HasParent() || (bmtInterface->dwInterfaceMapSize - GetParentMethodTable()->GetNumInterfaces()) >= 0);
3454
3455     if (HasParent())
3456     {   // Add parent vtable size. <TODO> This should actually be the parent's virtual method count. </TODO>
3457         bmtVT->dwMaxVtableSize += bmtParent->pSlotTable->GetSlotCount();
3458     }
3459
3460     S_SLOT_INDEX cMaxSlots = AsClrSafeInt(bmtVT->dwMaxVtableSize) + AsClrSafeInt(NumDeclaredMethods());
3461
3462     if (cMaxSlots.IsOverflow() || MAX_SLOT_INDEX < cMaxSlots.Value())
3463         cMaxSlots = S_SLOT_INDEX(MAX_SLOT_INDEX);
3464
3465     // Allocate the temporary vtable
3466     bmtVT->pSlotTable = new (GetStackingAllocator())
3467         bmtMethodSlotTable(cMaxSlots.Value(), GetStackingAllocator());
3468
3469     if (HasParent())
3470     {
3471 #if 0 
3472         // @<TODO>todo: Figure out the right way to override Equals for value
3473         // types only.
3474         //
3475         // This is broken because
3476         // (a) g_pObjectClass->FindMethod("Equals", &gsig_IM_Obj_RetBool); will return
3477         //      the EqualsValue method
3478         // (b) When mscorlib has been preloaded (and thus the munge already done
3479         //      ahead of time), we cannot easily find both methods
3480         //      to compute EqualsAddr & EqualsSlot
3481         //
3482         // For now, the Equals method has a runtime check to see if it's
3483         // comparing value types.
3484         //</TODO>
3485
3486         // If it is a value type, over ride a few of the base class methods.
3487         if (IsValueClass())
3488         {
3489             static WORD EqualsSlot;
3490
3491             // If we haven't been through here yet, get some stuff from the Object class definition.
3492             if (EqualsSlot == NULL)
3493             {
3494                 // Get the slot of the Equals method.
3495                 MethodDesc *pEqualsMD = g_pObjectClass->FindMethod("Equals", &gsig_IM_Obj_RetBool);
3496                 THROW_BAD_FORMAT_MAYBE(pEqualsMD != NULL, 0, this);
3497                 EqualsSlot = pEqualsMD->GetSlot();
3498
3499                 // Get the address of the EqualsValue method.
3500                 MethodDesc *pEqualsValueMD = g_pObjectClass->FindMethod("EqualsValue", &gsig_IM_Obj_RetBool);
3501                 THROW_BAD_FORMAT_MAYBE(pEqualsValueMD != NULL, 0, this);
3502
3503                 // Patch the EqualsValue method desc in a dangerous way to
3504                 // look like the Equals method desc.
3505                 pEqualsValueMD->SetSlot(EqualsSlot);
3506                 pEqualsValueMD->SetMemberDef(pEqualsMD->GetMemberDef());
3507             }
3508
3509             // Override the valuetype "Equals" with "EqualsValue".
3510             bmtVT->SetMethodDescForSlot(EqualsSlot, EqualsSlot);
3511         }
3512 #endif // 0
3513     }
3514
3515     S_UINT32 cEntries = S_UINT32(2) * S_UINT32(NumDeclaredMethods());
3516     if (cEntries.IsOverflow())
3517     {
3518         ThrowHR(COR_E_OVERFLOW);
3519     }
3520 }
3521
3522 //*******************************************************************************
3523 //
3524 // Used by BuildMethodTable
3525 //
3526 // Allocate a MethodDesc* for each method (needed later when doing interfaces), and a FieldDesc* for each field
3527 //
3528 VOID MethodTableBuilder::AllocateFieldDescs()
3529 {
3530     CONTRACTL
3531     {
3532         STANDARD_VM_CHECK;
3533         PRECONDITION(CheckPointer(this));
3534         PRECONDITION(CheckPointer(bmtAllocator));
3535         PRECONDITION(CheckPointer(bmtMFDescs));
3536         PRECONDITION(CheckPointer(bmtMetaData));
3537         PRECONDITION(CheckPointer(bmtVT));
3538         PRECONDITION(CheckPointer(bmtEnumFields));
3539         PRECONDITION(CheckPointer(bmtFP));
3540         PRECONDITION(CheckPointer(bmtParent));
3541
3542     }
3543     CONTRACTL_END;
3544
3545     // We'll be counting the # fields of each size as we go along
3546     for (DWORD i = 0; i <= MAX_LOG2_PRIMITIVE_FIELD_SIZE; i++)
3547     {
3548         bmtFP->NumRegularStaticFieldsOfSize[i]    = 0;
3549         bmtFP->NumThreadStaticFieldsOfSize[i]    = 0;
3550         bmtFP->NumInstanceFieldsOfSize[i]  = 0;
3551     }
3552
3553     //
3554     // Allocate blocks of MethodDescs and FieldDescs for all declared methods and fields
3555     //
3556     // In order to avoid allocating a field pointing back to the method
3557     // table in every single method desc, we allocate memory in the
3558     // following manner:
3559     //   o  Field descs get a single contiguous block.
3560     //   o  Method descs of different sizes (normal vs NDirect) are
3561     //      allocated in different MethodDescChunks.
3562     //   o  Each method desc chunk starts with a header, and has
3563     //      at most MAX_ method descs (if there are more
3564     //      method descs of a given size, multiple chunks are allocated).
3565     // This way method descs can use an 8-bit offset field to locate the
3566     // pointer to their method table.
3567     //
3568
3569     /////////////////////////////////////////////////////////////////
3570     // Allocate fields
3571     if (NumDeclaredFields() > 0)
3572     {
3573         GetHalfBakedClass()->SetFieldDescList((FieldDesc *)
3574             AllocateFromHighFrequencyHeap(S_SIZE_T(NumDeclaredFields()) * S_SIZE_T(sizeof(FieldDesc))));
3575         INDEBUG(GetClassLoader()->m_dwDebugFieldDescs += NumDeclaredFields();)
3576         INDEBUG(GetClassLoader()->m_dwFieldDescData += (NumDeclaredFields() * sizeof(FieldDesc));)
3577     }
3578 }
3579
3580 #ifdef FEATURE_DOUBLE_ALIGNMENT_HINT
3581 //*******************************************************************************
3582 //
3583 // Heuristic to determine if we should have instances of this class 8 byte aligned
3584 //
3585 BOOL MethodTableBuilder::ShouldAlign8(DWORD dwR8Fields, DWORD dwTotalFields)
3586 {
3587     LIMITED_METHOD_CONTRACT;
3588
3589     return dwR8Fields*2>dwTotalFields && dwR8Fields>=2;
3590 }
3591 #endif
3592
3593 //*******************************************************************************
3594 BOOL MethodTableBuilder::IsSelfReferencingStaticValueTypeField(mdToken     dwByValueClassToken,
3595                                                                bmtInternalInfo* bmtInternal,
3596                                                                const bmtGenericsInfo *bmtGenerics,
3597                                                                PCCOR_SIGNATURE pMemberSignature,
3598                                                                DWORD       cMemberSignature)
3599 {
3600     STANDARD_VM_CONTRACT;
3601
3602     if (dwByValueClassToken != this->GetCl())
3603     {
3604         return FALSE;
3605     }
3606
3607     if (!bmtGenerics->HasInstantiation())
3608     {
3609         return TRUE;
3610     }
3611
3612     // The value class is generic.  Check that the signature of the field
3613     // is _exactly_ equivalent to VC<!0, !1, !2, ...>.  Do this by consing up a fake
3614     // signature.
3615     DWORD nGenericArgs = bmtGenerics->GetNumGenericArgs();
3616     CONSISTENCY_CHECK(nGenericArgs != 0);
3617
3618     SigBuilder sigBuilder;
3619
3620     sigBuilder.AppendElementType(ELEMENT_TYPE_GENERICINST);
3621     sigBuilder.AppendElementType(ELEMENT_TYPE_VALUETYPE);
3622     sigBuilder.AppendToken(dwByValueClassToken);
3623     sigBuilder.AppendData(nGenericArgs);
3624     for (unsigned int typearg = 0; typearg < nGenericArgs; typearg++)
3625     {
3626         sigBuilder.AppendElementType(ELEMENT_TYPE_VAR);
3627         sigBuilder.AppendData(typearg);
3628     }
3629
3630     DWORD cFakeSig;
3631     PCCOR_SIGNATURE pFakeSig = (PCCOR_SIGNATURE)sigBuilder.GetSignature(&cFakeSig);
3632
3633     PCCOR_SIGNATURE pFieldSig = pMemberSignature + 1; // skip the CALLCONV_FIELD
3634
3635     return MetaSig::CompareElementType(pFakeSig,             pFieldSig,
3636                                        pFakeSig + cFakeSig,  pMemberSignature + cMemberSignature,
3637                                        GetModule(), GetModule(),
3638                                        NULL,                 NULL);
3639
3640 }
3641
3642 //*******************************************************************************
3643 //
3644 // Used pByValueClass cache to mark self-references
3645 //
3646 static BOOL IsSelfRef(MethodTable * pMT)
3647 {
3648     return pMT == (MethodTable *)-1;
3649 }
3650
3651 //*******************************************************************************
3652 //
3653 // Used by BuildMethodTable
3654 //
3655 // Go thru all fields and initialize their FieldDescs.
3656 //
3657 #ifdef _PREFAST_ 
3658 #pragma warning(push)
3659 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
3660 #endif // _PREFAST_
3661
3662 VOID    MethodTableBuilder::InitializeFieldDescs(FieldDesc *pFieldDescList,
3663                                                  const LayoutRawFieldInfo* pLayoutRawFieldInfos,
3664                                                  bmtInternalInfo* bmtInternal,
3665                                                  const bmtGenericsInfo* bmtGenerics,
3666                                                  bmtMetaDataInfo* bmtMetaData,
3667                                                  bmtEnumFieldInfo* bmtEnumFields,
3668                                                  bmtErrorInfo* bmtError,
3669                                                  MethodTable *** pByValueClassCache,
3670                                                  bmtMethAndFieldDescs* bmtMFDescs,
3671                                                  bmtFieldPlacement* bmtFP,
3672                                                  unsigned* totalDeclaredSize)
3673 {
3674     CONTRACTL
3675     {
3676         STANDARD_VM_CHECK;
3677         PRECONDITION(CheckPointer(this));
3678         PRECONDITION(CheckPointer(bmtInternal));
3679         PRECONDITION(CheckPointer(bmtGenerics));
3680         PRECONDITION(CheckPointer(bmtMetaData));
3681         PRECONDITION(CheckPointer(bmtEnumFields));
3682         PRECONDITION(CheckPointer(bmtError));
3683         PRECONDITION(CheckPointer(pByValueClassCache));
3684         PRECONDITION(CheckPointer(bmtMFDescs));
3685         PRECONDITION(CheckPointer(bmtFP));
3686         PRECONDITION(CheckPointer(totalDeclaredSize));
3687     }
3688     CONTRACTL_END;
3689
3690     DWORD i;
3691     IMDInternalImport * pInternalImport = GetMDImport(); // to avoid multiple dereferencings
3692
3693     FieldMarshaler * pNextFieldMarshaler = NULL;
3694     if (HasLayout())
3695     {
3696         pNextFieldMarshaler = (FieldMarshaler*)(GetLayoutInfo()->GetFieldMarshalers());
3697     }
3698
3699
3700 //========================================================================
3701 // BEGIN:
3702 //    Go thru all fields and initialize their FieldDescs.
3703 //========================================================================
3704
3705     DWORD   dwCurrentDeclaredField = 0;
3706     DWORD   dwCurrentStaticField   = 0;
3707     DWORD   dwCurrentThreadStaticField = 0;
3708
3709
3710     DWORD   dwR8Fields              = 0;        // Number of R8's the class has
3711
3712 #ifdef FEATURE_64BIT_ALIGNMENT
3713     // Track whether any field in this type requires 8-byte alignment
3714     BOOL    fFieldRequiresAlign8 = HasParent() ? GetParentMethodTable()->RequiresAlign8() : FALSE;
3715 #endif
3716
3717     for (i = 0; i < bmtMetaData->cFields; i++)
3718     {
3719         PCCOR_SIGNATURE pMemberSignature;
3720         DWORD       cMemberSignature;
3721         DWORD       dwMemberAttrs;
3722
3723         dwMemberAttrs = bmtMetaData->pFieldAttrs[i];
3724
3725         BOOL fIsStatic = IsFdStatic(dwMemberAttrs);
3726
3727         // We don't store static final primitive fields in the class layout
3728         if (IsFdLiteral(dwMemberAttrs))
3729             continue;
3730
3731         if (!IsFdPublic(dwMemberAttrs))
3732             SetHasNonPublicFields();
3733
3734         if (IsFdNotSerialized(dwMemberAttrs))
3735             SetCannotBeBlittedByObjectCloner();
3736
3737         IfFailThrow(pInternalImport->GetSigOfFieldDef(bmtMetaData->pFields[i], &cMemberSignature, &pMemberSignature));
3738         // Signature validation
3739         IfFailThrow(validateTokenSig(bmtMetaData->pFields[i],pMemberSignature,cMemberSignature,dwMemberAttrs,pInternalImport));
3740
3741         FieldDesc * pFD;
3742         DWORD       dwLog2FieldSize = 0;
3743         BOOL        bCurrentFieldIsGCPointer = FALSE;
3744         mdToken     dwByValueClassToken = 0;
3745         MethodTable * pByValueClass = NULL;
3746         BOOL        fIsByValue = FALSE;
3747         BOOL        fIsThreadStatic = FALSE;
3748         BOOL        fHasRVA = FALSE;
3749
3750         MetaSig fsig(pMemberSignature,
3751                      cMemberSignature,
3752                      GetModule(),
3753                      &bmtGenerics->typeContext,
3754                      MetaSig::sigField);
3755         CorElementType ElementType = fsig.NextArg();
3756
3757
3758         // Get type
3759         if (!isCallConv(fsig.GetCallingConvention(), IMAGE_CEE_CS_CALLCONV_FIELD))
3760         {
3761             IfFailThrow(COR_E_TYPELOAD);
3762         }
3763
3764         // Determine if a static field is special i.e. RVA based, local to
3765         // a thread or a context
3766         if (fIsStatic)
3767         {
3768             if (IsFdHasFieldRVA(dwMemberAttrs))
3769             {
3770                 fHasRVA = TRUE;
3771             }
3772
3773             HRESULT hr;
3774  
3775             hr = pInternalImport->GetCustomAttributeByName(bmtMetaData->pFields[i],
3776                                                            g_ThreadStaticAttributeClassName,
3777                                                            NULL, NULL);
3778             IfFailThrow(hr);
3779             if (hr == S_OK)
3780             {
3781                 fIsThreadStatic = TRUE;
3782             }
3783
3784
3785             if (ElementType == ELEMENT_TYPE_VALUETYPE)
3786             {
3787                 hr = pInternalImport->GetCustomAttributeByName(bmtMetaData->pFields[i],
3788                                                                g_CompilerServicesFixedAddressValueTypeAttribute,
3789                                                                NULL, NULL);
3790                 IfFailThrow(hr);
3791                 if (hr == S_OK)
3792                 {
3793                     bmtFP->fHasFixedAddressValueTypes = true;
3794                 }
3795             }
3796
3797
3798             // Do some sanity checks that we are not mixing context and thread
3799             // relative statics.
3800             if (fHasRVA && fIsThreadStatic)
3801             {
3802                 IfFailThrow(COR_E_TYPELOAD);
3803             }
3804
3805             if (bmtFP->fHasFixedAddressValueTypes && GetAssembly()->IsCollectible())
3806             {
3807                 BuildMethodTableThrowException(IDS_CLASSLOAD_COLLECTIBLEFIXEDVTATTR);
3808             }
3809         }
3810
3811
3812     GOT_ELEMENT_TYPE:
3813         // Type to store in FieldDesc - we don't want to have extra case statements for
3814         // ELEMENT_TYPE_STRING, SDARRAY etc., so we convert all object types to CLASS.
3815         // Also, BOOLEAN, CHAR are converted to U1, I2.
3816         CorElementType FieldDescElementType = ElementType;
3817
3818         switch (ElementType)
3819         {
3820         case ELEMENT_TYPE_I1:
3821         case ELEMENT_TYPE_U1:
3822             {
3823                 dwLog2FieldSize = 0;
3824                 break;
3825             }
3826
3827         case ELEMENT_TYPE_I2:
3828         case ELEMENT_TYPE_U2:
3829             {
3830                 dwLog2FieldSize = 1;
3831                 break;
3832             }
3833
3834         case ELEMENT_TYPE_I4:
3835         case ELEMENT_TYPE_U4:
3836         IN_TARGET_32BIT(case ELEMENT_TYPE_I:)
3837         IN_TARGET_32BIT(case ELEMENT_TYPE_U:)
3838         case ELEMENT_TYPE_R4:
3839             {
3840                 dwLog2FieldSize = 2;
3841                 break;
3842             }
3843
3844         case ELEMENT_TYPE_BOOLEAN:
3845             {
3846                 //                FieldDescElementType = ELEMENT_TYPE_U1;
3847                 dwLog2FieldSize = 0;
3848                 break;
3849             }
3850
3851         case ELEMENT_TYPE_CHAR:
3852             {
3853                 //                FieldDescElementType = ELEMENT_TYPE_U2;
3854                 dwLog2FieldSize = 1;
3855                 break;
3856             }
3857
3858         case ELEMENT_TYPE_R8:
3859             {
3860                 dwR8Fields++;
3861
3862                 // Deliberate fall through...
3863             }
3864        
3865         case ELEMENT_TYPE_I8:
3866         case ELEMENT_TYPE_U8:
3867         IN_TARGET_64BIT(case ELEMENT_TYPE_I:)
3868         IN_TARGET_64BIT(case ELEMENT_TYPE_U:)
3869             {
3870 #ifdef FEATURE_64BIT_ALIGNMENT
3871                 // Record that this field requires alignment for Int64/UInt64.
3872                 if(!fIsStatic)
3873                     fFieldRequiresAlign8 = true;
3874 #endif                
3875                 dwLog2FieldSize = 3;
3876                 break;
3877             }
3878
3879         case ELEMENT_TYPE_FNPTR:
3880         case ELEMENT_TYPE_PTR:   // ptrs are unmanaged scalars, for layout
3881             {
3882                 dwLog2FieldSize = LOG2_PTRSIZE;
3883                 break;
3884             }
3885
3886         // Class type variable (method type variables aren't allowed in fields)
3887         // These only occur in open types used for verification/reflection.
3888         case ELEMENT_TYPE_VAR:
3889         case ELEMENT_TYPE_MVAR:
3890            // deliberate drop through - do fake field layout
3891         case ELEMENT_TYPE_STRING:
3892         case ELEMENT_TYPE_SZARRAY:      // single dim, zero
3893         case ELEMENT_TYPE_ARRAY:        // all other arrays
3894         case ELEMENT_TYPE_CLASS: // objectrefs
3895         case ELEMENT_TYPE_OBJECT:
3896             {
3897                 dwLog2FieldSize = LOG2_PTRSIZE;
3898                 bCurrentFieldIsGCPointer = TRUE;
3899                 FieldDescElementType = ELEMENT_TYPE_CLASS;
3900
3901                 if (!fIsStatic)
3902                 {
3903                     SetHasFieldsWhichMustBeInited();
3904                     if (ElementType != ELEMENT_TYPE_STRING)
3905                         SetCannotBeBlittedByObjectCloner();
3906                 }
3907                 else
3908                 {   // EnumerateFieldDescs already counted the total number of static vs. instance
3909                     // fields, now we're further subdividing the static field count by GC and non-GC.
3910                     bmtEnumFields->dwNumStaticObjRefFields++;
3911                     if (fIsThreadStatic)
3912                         bmtEnumFields->dwNumThreadStaticObjRefFields++;
3913                 }
3914                 break;
3915             }
3916
3917         case ELEMENT_TYPE_VALUETYPE: // a byvalue class field
3918             {
3919                 Module * pTokenModule;
3920                 dwByValueClassToken = fsig.GetArgProps().PeekValueTypeTokenClosed(GetModule(), &bmtGenerics->typeContext, &pTokenModule);
3921                 fIsByValue = TRUE;
3922
3923                 // By-value class
3924                 BAD_FORMAT_NOTHROW_ASSERT(dwByValueClassToken != 0);
3925                 
3926                 if (this->IsValueClass() && (pTokenModule == GetModule()))
3927                 {
3928                     if (TypeFromToken(dwByValueClassToken) == mdtTypeRef)
3929                     {
3930                         // It's a typeref - check if it's a class that has a static field of itself
3931                         LPCUTF8 pszNameSpace;
3932                         LPCUTF8 pszClassName;
3933                         if (FAILED(pInternalImport->GetNameOfTypeRef(dwByValueClassToken, &pszNameSpace, &pszClassName)))
3934                         {
3935                             BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
3936                         }
3937                         
3938                         if (IsStrLongerThan((char *)pszClassName, MAX_CLASS_NAME)
3939                             || IsStrLongerThan((char *)pszNameSpace, MAX_CLASS_NAME)
3940                             || (strlen(pszClassName) + strlen(pszNameSpace) + 1 >= MAX_CLASS_NAME))
3941                         {
3942                             BuildMethodTableThrowException(BFA_TYPEREG_NAME_TOO_LONG, mdMethodDefNil);
3943                         }
3944
3945                         mdToken tkRes;
3946                         if (FAILED(pInternalImport->GetResolutionScopeOfTypeRef(dwByValueClassToken, &tkRes)))
3947                         {
3948                             BuildMethodTableThrowException(BFA_BAD_TYPEREF_TOKEN, dwByValueClassToken);
3949                         }
3950                         
3951                         if (TypeFromToken(tkRes) == mdtTypeRef)
3952                         {
3953                             if (!pInternalImport->IsValidToken(tkRes))
3954                             {
3955                                 BuildMethodTableThrowException(BFA_BAD_TYPEREF_TOKEN, mdMethodDefNil);
3956                             }
3957                         }
3958                         else
3959                         {
3960                             tkRes = mdTokenNil;
3961                         }
3962                         
3963                         if (FAILED(pInternalImport->FindTypeDef(pszNameSpace,
3964                                                                 pszClassName,
3965                                                                 tkRes,
3966                                                                 &dwByValueClassToken)))
3967                         {
3968                             dwByValueClassToken = mdTokenNil;
3969                         }
3970                     } // If field is static typeref
3971
3972                     BOOL selfref = IsSelfReferencingStaticValueTypeField(dwByValueClassToken,
3973                                                                     bmtInternal,
3974                                                                     bmtGenerics,
3975                                                                     pMemberSignature,
3976                                                                     cMemberSignature);
3977
3978                     if (selfref)
3979                     {   // immediately self-referential fields must be static.
3980                         if (!fIsStatic)
3981                         {
3982                             BuildMethodTableThrowException(IDS_CLASSLOAD_VALUEINSTANCEFIELD, mdMethodDefNil);
3983                         }
3984
3985                         if (!IsValueClass())
3986                         {
3987                             BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_MUST_BE_BYVAL, mdTokenNil);
3988                         }
3989
3990                         pByValueClass = (MethodTable *)-1;
3991                     }
3992                 } // If 'this' is a value class
3993
3994                 // It's not self-referential so try to load it
3995                 if (pByValueClass == NULL)
3996                 {
3997                     // Loading a non-self-ref valuetype field.
3998                     OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOAD_APPROXPARENTS);
3999                     // We load the approximate type of the field to avoid recursion problems.
4000                     // MethodTable::DoFullyLoad() will later load it fully
4001                     pByValueClass = fsig.GetArgProps().GetTypeHandleThrowing(GetModule(),
4002                                                                             &bmtGenerics->typeContext,
4003                                                                              ClassLoader::LoadTypes,
4004                                                                              CLASS_LOAD_APPROXPARENTS,
4005                                                                              TRUE
4006                                                                              ).GetMethodTable();
4007                 }
4008                 
4009                 // #FieldDescTypeMorph  IF it is an enum, strip it down to its underlying type
4010                 if (IsSelfRef(pByValueClass) ? IsEnum() : pByValueClass->IsEnum())
4011                 {
4012                     if (IsSelfRef(pByValueClass))
4013                     {   // It is self-referencing enum (ValueType) static field - it is forbidden in the ECMA spec, but supported by CLR since v1
4014                         // Note: literal static fields are skipped early in this loop
4015                         if (bmtMFDescs->ppFieldDescList[0] == NULL)
4016                         {   // The field is defined before (the only) instance field
4017                             // AppCompat with 3.5 SP1 and 4.0 RTM behavior
4018                             BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil);
4019                         }
4020                         // 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 
4021                         // later in this method)
4022                         // Therefore we do not have to run code:VerifySelfReferencingStaticValueTypeFields_WithRVA or code:#SelfReferencingStaticValueTypeField_Checks
4023                     }
4024                     BAD_FORMAT_NOTHROW_ASSERT((IsSelfRef(pByValueClass) ? 
4025                             bmtEnumFields->dwNumInstanceFields : pByValueClass->GetNumInstanceFields())
4026                                 == 1); // enums must have exactly one field
4027                     FieldDesc * enumField = IsSelfRef(pByValueClass) ?
4028                             bmtMFDescs->ppFieldDescList[0] : pByValueClass->GetApproxFieldDescListRaw();
4029                     BAD_FORMAT_NOTHROW_ASSERT(!enumField->IsStatic());   // no real static fields on enums
4030                     ElementType = enumField->GetFieldType();
4031                     BAD_FORMAT_NOTHROW_ASSERT(ElementType != ELEMENT_TYPE_VALUETYPE);
4032                     fIsByValue = FALSE; // we're going to treat it as the underlying type now
4033                     goto GOT_ELEMENT_TYPE;
4034                 }
4035                 
4036                 // Check ByRefLike fields
4037                 if (!IsSelfRef(pByValueClass) && pByValueClass->IsByRefLike())
4038                 {
4039                     if (fIsStatic)
4040                     {
4041                         // Byref-like types cannot be used for static fields
4042                         BuildMethodTableThrowException(IDS_CLASSLOAD_BYREFLIKE_STATICFIELD);
4043                     }
4044                     if (!bmtFP->fIsByRefLikeType)
4045                     {
4046                         // Non-byref-like types cannot contain byref-like instance fields
4047                         BuildMethodTableThrowException(IDS_CLASSLOAD_BYREFLIKE_INSTANCEFIELD);
4048                     }
4049                 }
4050
4051                 if (!IsSelfRef(pByValueClass) && pByValueClass->GetClass()->HasNonPublicFields())
4052                 {   // If a class has a field of type ValueType with non-public fields in it,
4053                     // the class must "inherit" this characteristic
4054                     SetHasNonPublicFields();
4055                 }
4056
4057                 if (!fHasRVA)
4058                 {
4059                     if (!fIsStatic)
4060                     {
4061                         // Inherit instance attributes
4062                         EEClass * pFieldClass = pByValueClass->GetClass();
4063
4064 #ifdef FEATURE_64BIT_ALIGNMENT
4065                         // If a value type requires 8-byte alignment this requirement must be inherited by any
4066                         // class/struct that embeds it as a field.
4067                         if (pFieldClass->IsAlign8Candidate())
4068                             fFieldRequiresAlign8 = true;
4069 #endif
4070                         if (pFieldClass->HasNonPublicFields())
4071                             SetHasNonPublicFields();
4072                         if (pFieldClass->HasFieldsWhichMustBeInited())
4073                             SetHasFieldsWhichMustBeInited();
4074
4075 #ifdef FEATURE_READYTORUN
4076                         if (!(pByValueClass->IsTruePrimitive() || pByValueClass->IsEnum()))
4077                         {
4078                             CheckLayoutDependsOnOtherModules(pByValueClass);
4079                         }
4080 #endif
4081                     }
4082                     else
4083                     {   // Increment the number of static fields that contain object references.
4084                         bmtEnumFields->dwNumStaticBoxedFields++;
4085                         if (fIsThreadStatic)
4086                             bmtEnumFields->dwNumThreadStaticBoxedFields++;
4087                     }
4088                 }
4089                 
4090                 if (*pByValueClassCache == NULL)
4091                 {
4092                     DWORD dwNumFields = bmtEnumFields->dwNumInstanceFields + bmtEnumFields->dwNumStaticFields;
4093                     
4094                     *pByValueClassCache = new (GetStackingAllocator()) MethodTable * [dwNumFields];
4095                     memset (*pByValueClassCache, 0, dwNumFields * sizeof(MethodTable **));
4096                 }
4097                 
4098                 // Thread static fields come after instance fields and regular static fields in this list
4099                 if (fIsThreadStatic)
4100                 {
4101                     (*pByValueClassCache)[bmtEnumFields->dwNumInstanceFields + bmtEnumFields->dwNumStaticFields - bmtEnumFields->dwNumThreadStaticFields + dwCurrentThreadStaticField] = pByValueClass;
4102                     // make sure to record the correct size for static field
4103                     // layout
4104                     dwLog2FieldSize = LOG2_PTRSIZE; // handle
4105                 }
4106                 // Regular static fields come after instance fields in this list
4107                 else if (fIsStatic)
4108                 {
4109                     (*pByValueClassCache)[bmtEnumFields->dwNumInstanceFields + dwCurrentStaticField] = pByValueClass;
4110                     // make sure to record the correct size for static field
4111                     // layout
4112                     dwLog2FieldSize = LOG2_PTRSIZE; // handle
4113                 }
4114                 else
4115                 {
4116                     (*pByValueClassCache)[dwCurrentDeclaredField] = pByValueClass;
4117                     dwLog2FieldSize = 0; // unused
4118                 }
4119                 
4120                 break;
4121             }
4122         default:
4123             {
4124                 BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil);
4125             }
4126         }
4127
4128         if (!fIsStatic)
4129         {
4130             pFD = &pFieldDescList[dwCurrentDeclaredField];
4131             *totalDeclaredSize += (1 << dwLog2FieldSize);
4132         }
4133         else /* (dwMemberAttrs & mdStatic) */
4134         {
4135             if (fIsThreadStatic)
4136             {
4137                 pFD = &pFieldDescList[bmtEnumFields->dwNumInstanceFields + bmtEnumFields->dwNumStaticFields - bmtEnumFields->dwNumThreadStaticFields + dwCurrentThreadStaticField];
4138             }
4139             else
4140             {
4141                 pFD = &pFieldDescList[bmtEnumFields->dwNumInstanceFields + dwCurrentStaticField];
4142             }
4143         }
4144
4145         bmtMFDescs->ppFieldDescList[i] = pFD;
4146
4147         const LayoutRawFieldInfo *pLayoutFieldInfo = NULL;
4148
4149         if (HasLayout())
4150         {
4151             const LayoutRawFieldInfo *pwalk = pLayoutRawFieldInfos;
4152             while (pwalk->m_MD != mdFieldDefNil)
4153             {
4154                 if (pwalk->m_MD == bmtMetaData->pFields[i])
4155                 {
4156                     pLayoutFieldInfo = pwalk;
4157
4158                     const FieldMarshaler *pSrcFieldMarshaler = (const FieldMarshaler *) &pwalk->m_FieldMarshaler;
4159
4160                     pSrcFieldMarshaler->CopyTo(pNextFieldMarshaler, MAXFIELDMARSHALERSIZE);
4161
4162                     pNextFieldMarshaler->SetFieldDesc(pFD);
4163                     pNextFieldMarshaler->SetExternalOffset(pwalk->m_offset);
4164
4165                     ((BYTE*&)pNextFieldMarshaler) += MAXFIELDMARSHALERSIZE;
4166                     break;
4167                 }
4168                 pwalk++;
4169             }
4170         }
4171
4172         LPCSTR pszFieldName = NULL;
4173 #ifdef _DEBUG 
4174         if (FAILED(pInternalImport->GetNameOfFieldDef(bmtMetaData->pFields[i], &pszFieldName)))
4175         {
4176             pszFieldName = "Invalid FieldDef record";
4177         }
4178 #endif
4179         // #InitCall Initialize contents of the field descriptor called from 
4180         pFD->Init(
4181                   bmtMetaData->pFields[i],
4182                   FieldDescElementType,
4183                   dwMemberAttrs,
4184                   fIsStatic,
4185                   fHasRVA,
4186                   fIsThreadStatic,
4187                   pszFieldName
4188                   );
4189
4190         // We're using FieldDesc::m_pMTOfEnclosingClass to temporarily store the field's size.
4191         // 
4192         if (fIsByValue)
4193         {
4194             if (!fIsStatic &&
4195                 (IsBlittable() || HasExplicitFieldOffsetLayout()))
4196             {
4197                 (DWORD_PTR &)pFD->m_pMTOfEnclosingClass =
4198                     (*pByValueClassCache)[dwCurrentDeclaredField]->GetNumInstanceFieldBytes();
4199
4200                 if (pLayoutFieldInfo)
4201                     IfFailThrow(pFD->SetOffset(pLayoutFieldInfo->m_offset));
4202                 else
4203                     pFD->SetOffset(FIELD_OFFSET_VALUE_CLASS);
4204             }
4205             else if (!fIsStatic && IsManagedSequential())
4206             {
4207                 (DWORD_PTR &)pFD->m_pMTOfEnclosingClass =
4208                     (*pByValueClassCache)[dwCurrentDeclaredField]->GetNumInstanceFieldBytes();
4209
4210                 IfFailThrow(pFD->SetOffset(pLayoutFieldInfo->m_managedOffset));
4211             }
4212             else
4213             {
4214                 // static value class fields hold a handle, which is ptr sized
4215                 // (instance field layout ignores this value)
4216                 (DWORD_PTR&)(pFD->m_pMTOfEnclosingClass) = LOG2_PTRSIZE;
4217                 pFD->SetOffset(FIELD_OFFSET_VALUE_CLASS);
4218             }
4219         }
4220         else
4221         {
4222             (DWORD_PTR &)(pFD->m_pMTOfEnclosingClass) = (size_t)dwLog2FieldSize;
4223
4224             // -1 (FIELD_OFFSET_UNPLACED) means that this is a non-GC field that has not yet been placed
4225             // -2 (FIELD_OFFSET_UNPLACED_GC_PTR) means that this is a GC pointer field that has not yet been placed
4226
4227             // If there is any kind of explicit layout information for this field, use it. If not, then
4228             // mark it as either GC or non-GC and as unplaced; it will get placed later on in an optimized way.
4229
4230             if ((IsBlittable() || HasExplicitFieldOffsetLayout()) && !fIsStatic)
4231                 IfFailThrow(pFD->SetOffset(pLayoutFieldInfo->m_offset));
4232             else if (IsManagedSequential() && !fIsStatic)
4233                 IfFailThrow(pFD->SetOffset(pLayoutFieldInfo->m_managedOffset));
4234             else if (bCurrentFieldIsGCPointer)
4235                 pFD->SetOffset(FIELD_OFFSET_UNPLACED_GC_PTR);
4236             else
4237                 pFD->SetOffset(FIELD_OFFSET_UNPLACED);
4238         }
4239
4240         if (!fIsStatic)
4241         {
4242             if (!fIsByValue)
4243             {
4244                 if (++bmtFP->NumInstanceFieldsOfSize[dwLog2FieldSize] == 1)
4245                     bmtFP->FirstInstanceFieldOfSize[dwLog2FieldSize] = dwCurrentDeclaredField;
4246             }
4247
4248             dwCurrentDeclaredField++;
4249
4250             if (bCurrentFieldIsGCPointer)
4251             {
4252                 bmtFP->NumInstanceGCPointerFields++;
4253             }
4254         }
4255         else /* static fields */
4256         {
4257             // Static fields are stored in the vtable after the vtable and interface slots.  We don't
4258             // know how large the vtable will be, so we will have to fixup the slot number by
4259             // <vtable + interface size> later.
4260
4261             if (fIsThreadStatic)
4262             {
4263                 dwCurrentThreadStaticField++;
4264             }
4265             else
4266             {
4267                 dwCurrentStaticField++;
4268             }
4269
4270             if (fHasRVA)
4271             {
4272                 if (FieldDescElementType == ELEMENT_TYPE_CLASS)
4273                 {   // RVA fields are not allowed to have GC pointers.
4274                     BAD_FORMAT_NOTHROW_ASSERT(!"ObjectRef in an RVA field");
4275                     BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil);
4276                 }
4277                 if (FieldDescElementType == ELEMENT_TYPE_VALUETYPE)
4278                 {
4279                     if (IsSelfRef(pByValueClass))
4280                     {   // We will verify self-referencing statics after the loop through all fields - see code:#SelfReferencingStaticValueTypeField_Checks
4281                         bmtFP->fHasSelfReferencingStaticValueTypeField_WithRVA = TRUE;
4282                     }
4283                     else
4284                     {
4285                         if (pByValueClass->GetClass()->HasFieldsWhichMustBeInited())
4286                         {   // RVA fields are not allowed to have GC pointers.
4287                             BAD_FORMAT_NOTHROW_ASSERT(!"ObjectRef in an RVA field");
4288                             BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil);
4289                         }
4290                     }
4291                 }
4292                 
4293                 // Set the field offset
4294                 DWORD rva;
4295                 IfFailThrow(pInternalImport->GetFieldRVA(pFD->GetMemberDef(), &rva));
4296                 
4297                 // Ensure that the IL image is loaded. Note that this assembly may
4298                 // have an ngen image, but this type may have failed to load during ngen.
4299                 GetModule()->GetFile()->LoadLibrary(FALSE);
4300                 
4301                 DWORD fldSize;
4302                 if (FieldDescElementType == ELEMENT_TYPE_VALUETYPE)
4303                 {
4304                     if (IsSelfRef(pByValueClass))
4305                     {
4306                         _ASSERTE(bmtFP->fHasSelfReferencingStaticValueTypeField_WithRVA);
4307                         
4308                         // We do not known the size yet
4309                         _ASSERTE(bmtFP->NumInstanceFieldBytes == 0);
4310                         // We will check just the RVA with size 0 now, the full size verification will happen in code:VerifySelfReferencingStaticValueTypeFields_WithRVA
4311                         fldSize = 0;
4312                     }
4313                     else
4314                     {
4315                         fldSize = pByValueClass->GetNumInstanceFieldBytes();
4316                     }
4317                 }
4318                 else
4319                 {
4320                     fldSize = GetSizeForCorElementType(FieldDescElementType);
4321                 }
4322                 
4323                 pFD->SetOffsetRVA(rva);
4324             }
4325             else if (fIsThreadStatic)
4326             {
4327                 bmtFP->NumThreadStaticFieldsOfSize[dwLog2FieldSize]++;
4328
4329                 if (bCurrentFieldIsGCPointer)
4330                     bmtFP->NumThreadStaticGCPointerFields++;
4331
4332                 if (fIsByValue)
4333                     bmtFP->NumThreadStaticGCBoxedFields++;
4334             }
4335             else
4336             {
4337                 bmtFP->NumRegularStaticFieldsOfSize[dwLog2FieldSize]++;
4338
4339                 if (bCurrentFieldIsGCPointer)
4340                     bmtFP->NumRegularStaticGCPointerFields++;
4341
4342                 if (fIsByValue)
4343                     bmtFP->NumRegularStaticGCBoxedFields++;
4344             }
4345         }
4346     }
4347     // We processed all fields
4348     
4349     //#SelfReferencingStaticValueTypeField_Checks
4350     if (bmtFP->fHasSelfReferencingStaticValueTypeField_WithRVA)
4351     {   // The type has self-referencing static ValueType field with RVA, do more checks now that depend on all fields being processed
4352         
4353         // For enums we already checked its underlying type, we should not get here
4354         _ASSERTE(!IsEnum());
4355         
4356         if (HasFieldsWhichMustBeInited())
4357         {   // RVA fields are not allowed to have GC pointers.
4358             BAD_FORMAT_NOTHROW_ASSERT(!"ObjectRef in an RVA self-referencing static field");
4359             BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil);
4360         }
4361     }
4362     
4363     DWORD dwNumInstanceFields = dwCurrentDeclaredField + (HasParent() ? GetParentMethodTable()->GetNumInstanceFields() : 0);
4364     DWORD dwNumStaticFields = bmtEnumFields->dwNumStaticFields;
4365     DWORD dwNumThreadStaticFields = bmtEnumFields->dwNumThreadStaticFields;
4366
4367     if (!FitsIn<WORD>(dwNumInstanceFields) ||
4368         !FitsIn<WORD>(dwNumStaticFields))
4369     {   // An implementation limitation means that it's an error if there are greater that MAX_WORD fields.
4370         BuildMethodTableThrowException(IDS_EE_TOOMANYFIELDS);
4371     }
4372
4373     GetHalfBakedClass()->SetNumInstanceFields((WORD)dwNumInstanceFields);
4374     GetHalfBakedClass()->SetNumStaticFields((WORD)dwNumStaticFields);
4375     GetHalfBakedClass()->SetNumThreadStaticFields((WORD)dwNumThreadStaticFields);
4376
4377     if (bmtFP->fHasFixedAddressValueTypes)
4378     {
4379         // To make things simpler, if the class has any field with this requirement, we'll set
4380         // all the statics to have this property. This allows us to only need to persist one bit
4381         // for the ngen case.
4382         GetHalfBakedClass()->SetHasFixedAddressVTStatics();
4383     }
4384
4385 #ifdef FEATURE_64BIT_ALIGNMENT
4386     // For types with layout we drop any 64-bit alignment requirement if the packing size was less than 8
4387     // bytes (this mimics what the native compiler does and ensures we match up calling conventions during
4388     // interop).
4389     if (HasLayout() && GetLayoutInfo()->GetPackingSize() < 8)
4390     {
4391         fFieldRequiresAlign8 = false;
4392     }
4393
4394     if (fFieldRequiresAlign8)
4395     {
4396         SetAlign8Candidate();
4397     }
4398 #endif // FEATURE_64BIT_ALIGNMENT
4399
4400 #ifdef FEATURE_DOUBLE_ALIGNMENT_HINT
4401     if (ShouldAlign8(dwR8Fields, dwNumInstanceFields))
4402     {
4403         SetAlign8Candidate();
4404     }
4405 #endif // FEATURE_DOUBLE_ALIGNMENT_HINT
4406
4407
4408     //========================================================================
4409     // END:
4410     //    Go thru all fields and initialize their FieldDescs.
4411     //========================================================================
4412
4413     return;
4414 } // MethodTableBuilder::InitializeFieldDescs
4415
4416 #ifdef _PREFAST_ 
4417 #pragma warning(pop)
4418 #endif
4419
4420 //*******************************************************************************
4421 // Verify self-referencing static ValueType fields with RVA (when the size of the ValueType is known).
4422 void 
4423 MethodTableBuilder::VerifySelfReferencingStaticValueTypeFields_WithRVA(
4424     MethodTable ** pByValueClassCache)
4425 {
4426     STANDARD_VM_CONTRACT;
4427     
4428     _ASSERTE(bmtFP->fHasSelfReferencingStaticValueTypeField_WithRVA);
4429     // Enum's static self-referencing fields have been verified as the underlying type of the enum, we should not get here for them
4430     _ASSERTE(!IsEnum());
4431     // The size of the ValueType should be known at this point (the caller throws if it is 0)
4432     _ASSERTE(bmtFP->NumInstanceFieldBytes != 0);
4433     
4434     FieldDesc * pFieldDescList = GetApproxFieldDescListRaw();
4435     DWORD nFirstThreadStaticFieldIndex = bmtEnumFields->dwNumInstanceFields + bmtEnumFields->dwNumStaticFields - bmtEnumFields->dwNumThreadStaticFields;
4436     for (DWORD i = bmtEnumFields->dwNumInstanceFields; i < nFirstThreadStaticFieldIndex; i++)
4437     {
4438         FieldDesc * pFD = &pFieldDescList[i];
4439         _ASSERTE(pFD->IsStatic());
4440         
4441         if (pFD->IsRVA() && pFD->IsByValue())
4442         {
4443             _ASSERTE(pByValueClassCache[i] != NULL);
4444             
4445             if (IsSelfRef(pByValueClassCache[i]))
4446             {
4447                 DWORD rva;
4448                 IfFailThrow(GetMDImport()->GetFieldRVA(pFD->GetMemberDef(), &rva));
4449             }
4450         }
4451     }
4452 } // MethodTableBuilder::VerifySelfReferencingStaticValueTypeFields_WithRVA
4453
4454 //*******************************************************************************
4455 // Returns true if hEnclosingTypeCandidate encloses, at any arbitrary depth,
4456 // hNestedTypeCandidate; returns false otherwise.
4457
4458 bool MethodTableBuilder::IsEnclosingNestedTypePair(
4459     bmtTypeHandle hEnclosingTypeCandidate,
4460     bmtTypeHandle hNestedTypeCandidate)
4461 {
4462     STANDARD_VM_CONTRACT;
4463
4464     CONSISTENCY_CHECK(!hEnclosingTypeCandidate.IsNull());
4465     CONSISTENCY_CHECK(!hNestedTypeCandidate.IsNull());
4466     CONSISTENCY_CHECK(!bmtTypeHandle::Equal(hEnclosingTypeCandidate, hNestedTypeCandidate));
4467
4468     Module * pModule = hEnclosingTypeCandidate.GetModule();
4469
4470     if (pModule != hNestedTypeCandidate.GetModule())
4471     {   // If the modules aren't the same, then there's no way
4472         // hBase could be an enclosing type of hChild. We make
4473         // this check early so that the code can deal with only
4474         // one Module and IMDInternalImport instance and can avoid
4475         // extra checks.
4476         return false;
4477     }
4478
4479     IMDInternalImport * pMDImport = pModule->GetMDImport();
4480
4481     mdTypeDef tkEncl = hEnclosingTypeCandidate.GetTypeDefToken();
4482     mdTypeDef tkNest = hNestedTypeCandidate.GetTypeDefToken();
4483
4484     while (tkEncl != tkNest)
4485     {   // Do this using the metadata APIs because MethodTableBuilder does
4486         // not construct type representations for enclosing type chains.
4487         if (FAILED(pMDImport->GetNestedClassProps(tkNest, &tkNest)))
4488         {   // tokNest is not a nested type.
4489             return false;
4490         }
4491     }
4492
4493     // tkNest's enclosing type is tkEncl, so we've shown that
4494     // hEnclosingTypeCandidate encloses hNestedTypeCandidate
4495     return true;
4496 }
4497
4498 //*******************************************************************************
4499 // Given an arbitrary nesting+subclassing pattern like this:
4500 //
4501 // class C1 {
4502 //     private virtual void Foo() { ... }
4503 //     class C2 : C1 {
4504 //       ...
4505 //         class CN : CN-1 {
4506 //             private override void Foo() { ... }
4507 //         }
4508 //       ...
4509 //     }
4510 // }
4511 //
4512 // this method will return true, where hChild == N and hBase == C1
4513 //
4514 // Note that there is no requirement that a type derive from its immediately
4515 // enclosing type, but can skip a level, such as this example:
4516 //
4517 // class A
4518 // {
4519 //     private virtual void Foo() { }
4520 //     public class B
4521 //     {
4522 //         public class C : A
4523 //         {
4524 //             private override void Foo() { }
4525 //         }
4526 //     }
4527 // }
4528 //
4529 // NOTE: IMPORTANT: This code assumes that hBase is indeed a base type of hChild,
4530 //                  and behaviour is undefined if this is not the case.
4531
4532 bool MethodTableBuilder::IsBaseTypeAlsoEnclosingType(
4533     bmtTypeHandle hBase,
4534     bmtTypeHandle hChild)
4535 {
4536     STANDARD_VM_CONTRACT;
4537
4538     CONSISTENCY_CHECK(!hBase.IsNull());
4539     CONSISTENCY_CHECK(!hChild.IsNull());
4540     CONSISTENCY_CHECK(!bmtTypeHandle::Equal(hBase, hChild));
4541
4542     // The idea of this algorithm is that if we climb the inheritance chain
4543     // starting at hChild then we'll eventually hit hBase. If we check that
4544     // for every (hParent, hChild) pair in the chain that hParent encloses
4545     // hChild, then we've shown that hBase encloses hChild.
4546
4547     while (!bmtTypeHandle::Equal(hBase, hChild))
4548     {
4549         CONSISTENCY_CHECK(!hChild.GetParentType().IsNull());
4550         bmtTypeHandle hParent(hChild.GetParentType());
4551
4552         if (!IsEnclosingNestedTypePair(hParent, hChild))
4553         {   // First, the parent type must enclose the child type.
4554             // If this is not the case we fail immediately.
4555             return false;
4556         }
4557
4558         // Move up one in the inheritance chain, and try again.
4559         hChild = hParent;
4560     }
4561
4562     // If the loop worked itself from the original hChild all the way
4563     // up to hBase, then we know that for every (hParent, hChild)
4564     // pair in the chain that hParent enclosed hChild, and so we know
4565     // that hBase encloses the original hChild
4566     return true;
4567 }
4568
4569 //*******************************************************************************
4570 BOOL MethodTableBuilder::TestOverrideForAccessibility(
4571     bmtMethodHandle hParentMethod,
4572     bmtTypeHandle   hChildType)
4573 {
4574     STANDARD_VM_CONTRACT;
4575
4576     bmtTypeHandle hParentType(hParentMethod.GetOwningType());
4577
4578     Module * pParentModule = hParentType.GetModule();
4579     Module * pChildModule = hChildType.GetModule();
4580
4581     Assembly * pParentAssembly = pParentModule->GetAssembly();
4582     Assembly * pChildAssembly = pChildModule->GetAssembly();
4583
4584     BOOL isSameAssembly = (pChildAssembly == pParentAssembly);
4585
4586     DWORD dwParentAttrs = hParentMethod.GetDeclAttrs();
4587
4588     // AKA "strict bit". This means that overridability is tightly bound to accessibility.
4589     if (IsMdCheckAccessOnOverride(dwParentAttrs))
4590     {
4591         // Same Assembly
4592         if (isSameAssembly || pParentAssembly->GrantsFriendAccessTo(pChildAssembly, hParentMethod.GetMethodDesc())
4593             || pChildAssembly->IgnoresAccessChecksTo(pParentAssembly))
4594         {
4595             // Can always override any method that has accessibility greater than mdPrivate
4596             if ((dwParentAttrs & mdMemberAccessMask) > mdPrivate)
4597             {   // Fall through
4598             }
4599             // Generally, types cannot override inherited mdPrivate methods, except:
4600             // Types can access enclosing type's private members, so it can
4601             // override them if the nested type extends its enclosing type.
4602             else if ((dwParentAttrs & mdMemberAccessMask) == mdPrivate &&
4603                      IsBaseTypeAlsoEnclosingType(hParentType, hChildType))
4604             {   // Fall through
4605             }
4606             else
4607             {
4608                 return FALSE;
4609             }
4610         }
4611         // Cross-Assembly
4612         else
4613         {
4614             // If the method marks itself as check visibility the the method must be
4615             // public, FamORAssem, or family
4616             if((dwParentAttrs & mdMemberAccessMask) <= mdAssem)
4617             {
4618                 return FALSE;
4619             }
4620         }
4621     }
4622     return TRUE;
4623 }
4624
4625 //*******************************************************************************
4626 VOID MethodTableBuilder::TestOverRide(bmtMethodHandle hParentMethod,
4627                                       bmtMethodHandle hChildMethod)
4628 {
4629     CONTRACTL {
4630         STANDARD_VM_CHECK;
4631         PRECONDITION(IsMdVirtual(hParentMethod.GetDeclAttrs()));
4632         PRECONDITION(IsMdVirtual(hChildMethod.GetDeclAttrs()));
4633     } CONTRACTL_END;
4634
4635     DWORD dwAttrs = hChildMethod.GetDeclAttrs();
4636     DWORD dwParentAttrs = hParentMethod.GetDeclAttrs();
4637
4638     Module *pModule = hChildMethod.GetOwningType().GetModule();
4639     Module *pParentModule = hParentMethod.GetOwningType().GetModule();
4640
4641     Assembly *pAssembly = pModule->GetAssembly();
4642     Assembly *pParentAssembly = pParentModule->GetAssembly();
4643
4644     BOOL isSameModule = (pModule == pParentModule);
4645     BOOL isSameAssembly = (pAssembly == pParentAssembly);
4646
4647     if (!TestOverrideForAccessibility(hParentMethod, hChildMethod.GetOwningType()))
4648     {
4649         BuildMethodTableThrowException(IDS_CLASSLOAD_MI_ACCESS_FAILURE, hChildMethod.GetMethodSignature().GetToken());
4650     }
4651
4652     //
4653     // Refer to Partition II, 9.3.3 for more information on what is permitted.
4654     //
4655
4656     enum WIDENING_STATUS
4657     {
4658         e_NO,       // NO
4659         e_YES,      // YES
4660         e_SA,       // YES, but only when same assembly
4661         e_NSA,      // YES, but only when NOT same assembly
4662         e_SM,       // YES, but only when same module
4663     };
4664
4665     static_assert_no_msg(mdPrivateScope == 0x00);
4666     static_assert_no_msg(mdPrivate      == 0x01);
4667     static_assert_no_msg(mdFamANDAssem  == 0x02);
4668     static_assert_no_msg(mdAssem        == 0x03);
4669     static_assert_no_msg(mdFamily       == 0x04);
4670     static_assert_no_msg(mdFamORAssem   == 0x05);
4671     static_assert_no_msg(mdPublic       == 0x06);
4672
4673     static const DWORD dwCount = mdPublic - mdPrivateScope + 1;
4674     static const WIDENING_STATUS rgWideningTable[dwCount][dwCount] =
4675
4676     //               |        Base type
4677     // Subtype       |        mdPrivateScope  mdPrivate   mdFamANDAssem   mdAssem     mdFamily    mdFamORAssem    mdPublic
4678     // --------------+-------------------------------------------------------------------------------------------------------
4679     /*mdPrivateScope | */ { { e_SM,           e_NO,       e_NO,           e_NO,       e_NO,       e_NO,           e_NO    },
4680     /*mdPrivate      | */   { e_SM,           e_YES,      e_NO,           e_NO,       e_NO,       e_NO,           e_NO    },
4681     /*mdFamANDAssem  | */   { e_SM,           e_YES,      e_SA,           e_NO,       e_NO,       e_NO,           e_NO    },
4682     /*mdAssem        | */   { e_SM,           e_YES,      e_SA,           e_SA,       e_NO,       e_NO,           e_NO    },
4683     /*mdFamily       | */   { e_SM,           e_YES,      e_YES,          e_NO,       e_YES,      e_NSA,          e_NO    },
4684     /*mdFamORAssem   | */   { e_SM,           e_YES,      e_YES,          e_SA,       e_YES,      e_YES,          e_NO    },
4685     /*mdPublic       | */   { e_SM,           e_YES,      e_YES,          e_YES,      e_YES,      e_YES,          e_YES   } };
4686
4687     DWORD idxParent = (dwParentAttrs & mdMemberAccessMask) - mdPrivateScope;
4688     DWORD idxMember = (dwAttrs & mdMemberAccessMask) - mdPrivateScope;
4689     CONSISTENCY_CHECK(idxParent < dwCount);
4690     CONSISTENCY_CHECK(idxMember < dwCount);
4691
4692     WIDENING_STATUS entry = rgWideningTable[idxMember][idxParent];
4693
4694     if (entry == e_NO ||
4695         (entry == e_SA && !isSameAssembly && !pParentAssembly->GrantsFriendAccessTo(pAssembly, hParentMethod.GetMethodDesc())
4696          && !pAssembly->IgnoresAccessChecksTo(pParentAssembly)) ||
4697         (entry == e_NSA && isSameAssembly) ||
4698         (entry == e_SM && !isSameModule)
4699        )
4700     {
4701         BuildMethodTableThrowException(IDS_CLASSLOAD_REDUCEACCESS, hChildMethod.GetMethodSignature().GetToken());
4702     }
4703
4704     return;
4705 }
4706
4707 //*******************************************************************************
4708 VOID MethodTableBuilder::TestMethodImpl(
4709     bmtMethodHandle hDeclMethod,
4710     bmtMethodHandle hImplMethod)
4711 {
4712     CONTRACTL
4713     {
4714         STANDARD_VM_CHECK;
4715         PRECONDITION(!hDeclMethod.IsNull());
4716         PRECONDITION(!hImplMethod.IsNull());
4717     }
4718     CONTRACTL_END
4719
4720     Module * pDeclModule = hDeclMethod.GetOwningType().GetModule();
4721     Module * pImplModule = hImplMethod.GetOwningType().GetModule();
4722
4723     mdTypeDef tokDecl = hDeclMethod.GetMethodSignature().GetToken();
4724     mdTypeDef tokImpl = hImplMethod.GetMethodSignature().GetToken();
4725
4726     BOOL isSameModule = pDeclModule->Equals(pImplModule);
4727
4728     IMDInternalImport *pIMDDecl = pDeclModule->GetMDImport();
4729     IMDInternalImport *pIMDImpl = pImplModule->GetMDImport();
4730
4731     DWORD dwDeclAttrs;
4732     if (FAILED(pIMDDecl->GetMethodDefProps(tokDecl, &dwDeclAttrs)))
4733     {
4734         BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
4735     }
4736     DWORD dwImplAttrs;
4737     if (FAILED(pIMDImpl->GetMethodDefProps(tokImpl, &dwImplAttrs)))
4738     {
4739         BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
4740     }
4741     
4742     HRESULT hr = COR_E_TYPELOAD;
4743
4744     if (!IsMdVirtual(dwDeclAttrs))
4745     {
4746         BuildMethodTableThrowException(IDS_CLASSLOAD_MI_NONVIRTUAL_DECL);
4747     }
4748     if (!IsMdVirtual(dwImplAttrs))
4749     {
4750         BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MUSTBEVIRTUAL);
4751     }
4752     // Virtual methods cannot be static
4753     if (IsMdStatic(dwDeclAttrs))
4754     {
4755         BuildMethodTableThrowException(IDS_CLASSLOAD_STATICVIRTUAL);
4756     }
4757     if (IsMdStatic(dwImplAttrs))
4758     {
4759         BuildMethodTableThrowException(IDS_CLASSLOAD_STATICVIRTUAL);
4760     }
4761     if (IsMdFinal(dwDeclAttrs))
4762     {
4763         BuildMethodTableThrowException(IDS_CLASSLOAD_MI_FINAL_DECL);
4764     }
4765
4766     // Interface method body that has methodimpl should always be final
4767     if (IsInterface() && !IsMdFinal(dwImplAttrs))
4768     {
4769         BuildMethodTableThrowException(IDS_CLASSLOAD_MI_FINAL_IMPL);
4770     }
4771
4772     // Since MethodImpl's do not affect the visibility of the Decl method, there's
4773     // no need to check.
4774
4775     // If Decl's parent is other than this class, Decl must not be private
4776     mdTypeDef tkImplParent = mdTypeDefNil;
4777     mdTypeDef tkDeclParent = mdTypeDefNil;
4778
4779     if (FAILED(hr = pIMDDecl->GetParentToken(tokDecl, &tkDeclParent)))
4780     {
4781         BuildMethodTableThrowException(hr, *bmtError);
4782     }
4783     if (FAILED(hr = pIMDImpl->GetParentToken(tokImpl, &tkImplParent)))
4784     {
4785         BuildMethodTableThrowException(hr, *bmtError);
4786     }
4787
4788     // Make sure that we test for accessibility restrictions only if the decl is
4789     // not within our own type, as we are allowed to methodImpl a private with the
4790     // strict bit set if it is in our own type.
4791     if (!isSameModule || tkDeclParent != tkImplParent)
4792     {
4793         if (!TestOverrideForAccessibility(hDeclMethod, hImplMethod.GetOwningType()))
4794         {
4795             BuildMethodTableThrowException(IDS_CLASSLOAD_MI_ACCESS_FAILURE, tokImpl);
4796         }
4797
4798         // Decl's parent must not be tdSealed
4799         mdToken tkGrandParentDummyVar;
4800         DWORD dwDeclTypeAttrs;
4801         if (FAILED(hr = pIMDDecl->GetTypeDefProps(tkDeclParent, &dwDeclTypeAttrs, &tkGrandParentDummyVar)))
4802         {
4803             BuildMethodTableThrowException(hr, *bmtError);
4804         }
4805         if (IsTdSealed(dwDeclTypeAttrs))
4806         {
4807             BuildMethodTableThrowException(IDS_CLASSLOAD_MI_SEALED_DECL);
4808         }
4809     }
4810     
4811     return;
4812 }
4813
4814
4815 //*******************************************************************************
4816 //
4817 // Used by BuildMethodTable
4818 //
4819 VOID
4820 MethodTableBuilder::ValidateMethods()
4821 {
4822     CONTRACTL
4823     {
4824         STANDARD_VM_CHECK;
4825
4826         PRECONDITION(CheckPointer(this));
4827         PRECONDITION(CheckPointer(bmtInternal));
4828         PRECONDITION(CheckPointer(bmtMetaData));
4829         PRECONDITION(CheckPointer(bmtError));
4830         PRECONDITION(CheckPointer(bmtProp));
4831         PRECONDITION(CheckPointer(bmtInterface));
4832         PRECONDITION(CheckPointer(bmtParent));
4833         PRECONDITION(CheckPointer(bmtMFDescs));
4834         PRECONDITION(CheckPointer(bmtEnumFields));
4835         PRECONDITION(CheckPointer(bmtMethodImpl));
4836         PRECONDITION(CheckPointer(bmtVT));
4837     }
4838     CONTRACTL_END;
4839
4840     // Used to keep track of located default and type constructors.
4841     CONSISTENCY_CHECK(bmtVT->pCCtor == NULL);
4842     CONSISTENCY_CHECK(bmtVT->pDefaultCtor == NULL);
4843
4844     // Fetch the hard-coded signatures for the type constructor and the
4845     // default constructor and create MethodSignature objects for both at
4846     // the method level so this does not happen for every specialname
4847     // method.
4848
4849     Signature sig;
4850     
4851     sig = MscorlibBinder::GetSignature(&gsig_SM_RetVoid);
4852
4853     MethodSignature cctorSig(MscorlibBinder::GetModule(),
4854                              COR_CCTOR_METHOD_NAME,
4855                              sig.GetRawSig(), sig.GetRawSigLen());
4856
4857     sig = MscorlibBinder::GetSignature(&gsig_IM_RetVoid);
4858
4859     MethodSignature defaultCtorSig(MscorlibBinder::GetModule(),
4860                                    COR_CTOR_METHOD_NAME,
4861                                    sig.GetRawSig(), sig.GetRawSigLen());
4862
4863     Module * pModule = GetModule();
4864     DeclaredMethodIterator it(*this);
4865     while (it.Next())
4866     {
4867         // The RVA is only valid/testable if it has not been overwritten
4868         // for something like edit-and-continue
4869         // Complete validation of non-zero RVAs is done later inside MethodDesc::GetILHeader.
4870         if ((it.RVA() == 0) && (pModule->GetDynamicIL(it.Token(), FALSE) == NULL))
4871         {
4872             // for IL code that is implemented here must have a valid code RVA
4873             // this came up due to a linker bug where the ImplFlags/DescrOffset were
4874             // being set to null and we weren't coping with it
4875             if((IsMiIL(it.ImplFlags()) || IsMiOPTIL(it.ImplFlags())) &&
4876                    !IsMdAbstract(it.Attrs()) &&
4877                    !IsReallyMdPinvokeImpl(it.Attrs()) &&
4878                 !IsMiInternalCall(it.ImplFlags()))
4879             {
4880                 BuildMethodTableThrowException(IDS_CLASSLOAD_MISSINGMETHODRVA, it.Token());
4881             }
4882         }
4883
4884         if (IsMdRTSpecialName(it.Attrs()))
4885         {
4886             if (IsMdVirtual(it.Attrs()))
4887             {   // Virtual specialname methods are illegal
4888                 BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
4889             }
4890
4891             // Constructors (.ctor) and class initialisers (.cctor) are special
4892             const MethodSignature &curSig(it->GetMethodSignature());
4893
4894             if (IsMdStatic(it.Attrs()))
4895             {   // The only rtSpecialName static method allowed is the .cctor
4896                 if (!curSig.ExactlyEqual(cctorSig))
4897                 {   // Bad method
4898                     BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
4899                 }
4900
4901                 // Remember it for later
4902                 bmtVT->pCCtor = *it;
4903             }
4904             else
4905             {
4906                 if(!MethodSignature::NamesEqual(curSig, defaultCtorSig))
4907                 {   // The only rtSpecialName instance methods allowed are .ctors
4908                     BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
4909                 }
4910
4911                 // .ctor must return void
4912                 MetaSig methodMetaSig(curSig.GetSignature(),
4913                                         static_cast<DWORD>(curSig.GetSignatureLength()),
4914                                         curSig.GetModule(),
4915                                         NULL);
4916
4917                 if (methodMetaSig.GetReturnType() != ELEMENT_TYPE_VOID)
4918                 {   // All constructors must have a void return type
4919                     BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
4920                 }
4921
4922                 // See if this is a default constructor.  If so, remember it for later.
4923                 if (curSig.ExactlyEqual(defaultCtorSig))
4924                 {
4925                     bmtVT->pDefaultCtor = *it;
4926                 }
4927             }
4928         }
4929
4930         // Make sure that fcalls have a 0 rva.  This is assumed by the prejit fixup logic
4931         if (it.MethodType() == METHOD_TYPE_FCALL && it.RVA() != 0)
4932         {
4933             BuildMethodTableThrowException(BFA_ECALLS_MUST_HAVE_ZERO_RVA, it.Token());
4934         }
4935
4936         // check for proper use of the Managed and native flags
4937         if (IsMiManaged(it.ImplFlags()))
4938         {
4939             if (IsMiIL(it.ImplFlags()) || IsMiRuntime(it.ImplFlags())) // IsMiOPTIL(it.ImplFlags()) no longer supported
4940             {
4941                 // No need to set code address, pre stub used automatically.
4942             }
4943             else
4944             {
4945                 if (IsMiNative(it.ImplFlags()))
4946                 {
4947                     // For now simply disallow managed native code if you turn this on you have to at least
4948                     // insure that we have SkipVerificationPermission or equivalent
4949                     BuildMethodTableThrowException(BFA_MANAGED_NATIVE_NYI, it.Token());
4950                 }
4951                 else
4952                 {
4953                     BuildMethodTableThrowException(BFA_BAD_IMPL_FLAGS, it.Token());
4954                 }
4955             }
4956         }
4957         else
4958         {
4959             if (IsMiNative(it.ImplFlags()) && IsGlobalClass())
4960             {
4961                 // global function unmanaged entrypoint via IJW thunk was handled
4962                 // above.
4963             }
4964             else
4965             {
4966                 BuildMethodTableThrowException(IDS_CLASSLOAD_BAD_UNMANAGED_RVA, it.Token());
4967             }
4968             if (it.MethodType() != METHOD_TYPE_NDIRECT)
4969             {
4970                 BuildMethodTableThrowException(BFA_BAD_UNMANAGED_ENTRY_POINT);
4971             }
4972         }
4973
4974         // Vararg methods are not allowed inside generic classes
4975         // and nor can they be generic methods.
4976         if (bmtGenerics->GetNumGenericArgs() > 0 || (it.MethodType() == METHOD_TYPE_INSTANTIATED) )
4977         {
4978             DWORD cMemberSignature;
4979             PCCOR_SIGNATURE pMemberSignature = it.GetSig(&cMemberSignature);
4980             // We've been trying to avoid asking for the signature - now we need it
4981             if (pMemberSignature == NULL)
4982             {
4983                 pMemberSignature = it.GetSig(&cMemberSignature);
4984             }
4985
4986             if (MetaSig::IsVarArg(pModule, Signature(pMemberSignature, cMemberSignature)))
4987             {
4988                 BuildMethodTableThrowException(BFA_GENCODE_NOT_BE_VARARG);
4989             }
4990         }
4991
4992         if (IsMdVirtual(it.Attrs()) && IsMdPublic(it.Attrs()) && it.Name() == NULL)
4993         {
4994             BuildMethodTableThrowException(IDS_CLASSLOAD_NOMETHOD_NAME);
4995         }
4996
4997         if (it.IsMethodImpl())
4998         {
4999             if (!IsMdVirtual(it.Attrs()))
5000             {   // Non-virtual methods cannot participate in a methodImpl pair.
5001                 BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MUSTBEVIRTUAL, it.Token());
5002             }
5003         }
5004
5005         // Virtual static methods are not allowed.
5006         if (IsMdStatic(it.Attrs()) && IsMdVirtual(it.Attrs()))
5007         {
5008             BuildMethodTableThrowException(IDS_CLASSLOAD_STATICVIRTUAL, it.Token());
5009         }
5010     }
5011 }
5012
5013 //*******************************************************************************
5014 // Essentially, this is a helper method that combines calls to InitMethodDesc and 
5015 // SetSecurityFlagsOnMethod. It then assigns the newly initialized MethodDesc to 
5016 // the bmtMDMethod.
5017 VOID
5018 MethodTableBuilder::InitNewMethodDesc(
5019     bmtMDMethod * pMethod,
5020     MethodDesc * pNewMD)
5021 {
5022     STANDARD_VM_CONTRACT;
5023
5024     //
5025     // First, set all flags that control layout of optional slots
5026     //
5027     pNewMD->SetClassification(GetMethodClassification(pMethod->GetMethodType()));
5028
5029     if (pMethod->GetMethodImplType() == METHOD_IMPL)
5030         pNewMD->SetHasMethodImplSlot();
5031
5032     if (pMethod->GetSlotIndex() >= bmtVT->cVtableSlots)
5033         pNewMD->SetHasNonVtableSlot();
5034
5035     if (NeedsNativeCodeSlot(pMethod))
5036         pNewMD->SetHasNativeCodeSlot();
5037
5038     // Now we know the classification we can allocate the correct type of
5039     // method desc and perform any classification specific initialization.
5040
5041     LPCSTR pName = pMethod->GetMethodSignature().GetName();
5042     if (pName == NULL)
5043     {
5044         if (FAILED(GetMDImport()->GetNameOfMethodDef(pMethod->GetMethodSignature().GetToken(), &pName)))
5045         {
5046             BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
5047         }
5048     }
5049     
5050 #ifdef _DEBUG 
5051     LPCUTF8 pszDebugMethodName;
5052     if (FAILED(GetMDImport()->GetNameOfMethodDef(pMethod->GetMethodSignature().GetToken(), &pszDebugMethodName)))
5053     {
5054         pszDebugMethodName = "Invalid MethodDef record";
5055     }
5056     S_SIZE_T safeLen = S_SIZE_T(strlen(pszDebugMethodName)) + S_SIZE_T(1);
5057     if(safeLen.IsOverflow())
5058         COMPlusThrowHR(COR_E_OVERFLOW);
5059
5060     size_t len = safeLen.Value();
5061     LPCUTF8 pszDebugMethodNameCopy = (char*) AllocateFromLowFrequencyHeap(safeLen);
5062     strcpy_s((char *) pszDebugMethodNameCopy, len, pszDebugMethodName);
5063 #endif // _DEBUG
5064
5065     // Do the init specific to each classification of MethodDesc & assign some common fields
5066     InitMethodDesc(pNewMD,
5067                    GetMethodClassification(pMethod->GetMethodType()),
5068                    pMethod->GetMethodSignature().GetToken(),
5069                    pMethod->GetImplAttrs(),
5070                    pMethod->GetDeclAttrs(),
5071                    FALSE,
5072                    pMethod->GetRVA(),
5073                    GetMDImport(),
5074                    pName
5075                    COMMA_INDEBUG(pszDebugMethodNameCopy)
5076                    COMMA_INDEBUG(GetDebugClassName())
5077                    COMMA_INDEBUG("") // FIX this happens on global methods, give better info
5078                   );
5079
5080     pMethod->SetMethodDesc(pNewMD);
5081
5082     bmtRTMethod * pParentMethod = NULL;
5083
5084     if (HasParent())
5085     {
5086         SLOT_INDEX idx = pMethod->GetSlotIndex();
5087         CONSISTENCY_CHECK(idx != INVALID_SLOT_INDEX);
5088
5089         if (idx < GetParentMethodTable()->GetNumVirtuals())
5090         {
5091             pParentMethod = (*bmtParent->pSlotTable)[idx].Decl().AsRTMethod();
5092         }
5093     }
5094
5095     // Turn off inlining for any calls
5096     // that are marked in the metadata as not being inlineable.
5097     if(IsMiNoInlining(pMethod->GetImplAttrs()))
5098     {
5099         pNewMD->SetNotInline(true);
5100     }
5101
5102     // Check for methods marked as [Intrinsic]
5103     if (GetModule()->IsSystem() || GetAssembly()->IsSIMDVectorAssembly())
5104     {
5105         HRESULT hr = GetMDImport()->GetCustomAttributeByName(pMethod->GetMethodSignature().GetToken(),
5106             g_CompilerServicesIntrinsicAttribute,
5107             NULL,
5108             NULL);
5109
5110         if (hr == S_OK || bmtProp->fIsHardwareIntrinsic)
5111         {
5112             pNewMD->SetIsJitIntrinsic();
5113         }
5114
5115     }
5116
5117     pNewMD->SetSlot(pMethod->GetSlotIndex());
5118 }
5119
5120 //*******************************************************************************
5121 // Determine vtable placement for each non-virtual in the class, while also
5122 // looking for default and type constructors.
5123 VOID
5124 MethodTableBuilder::PlaceNonVirtualMethods()
5125 {
5126     CONTRACTL
5127     {
5128         STANDARD_VM_CHECK;
5129
5130         PRECONDITION(CheckPointer(this));
5131         PRECONDITION(CheckPointer(bmtInternal));
5132         PRECONDITION(CheckPointer(bmtMetaData));
5133         PRECONDITION(CheckPointer(bmtError));
5134         PRECONDITION(CheckPointer(bmtProp));
5135         PRECONDITION(CheckPointer(bmtInterface));
5136         PRECONDITION(CheckPointer(bmtParent));
5137         PRECONDITION(CheckPointer(bmtMFDescs));
5138         PRECONDITION(CheckPointer(bmtEnumFields));
5139         PRECONDITION(CheckPointer(bmtMethodImpl));
5140         PRECONDITION(CheckPointer(bmtVT));
5141     }
5142     CONTRACTL_END;
5143
5144     INDEBUG(bmtVT->SealVirtualSlotSection();)
5145
5146     //
5147     // For each non-virtual method, place the method in the next available non-virtual method slot.
5148     //
5149
5150     // Place the cctor and default ctor first. code::MethodTableGetCCtorSlot and code:MethodTable::GetDefaultCtorSlot 
5151     // depends on this.
5152     if (bmtVT->pCCtor != NULL)
5153     {
5154         if (!bmtVT->AddNonVirtualMethod(bmtVT->pCCtor))
5155             BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
5156     }
5157
5158     if (bmtVT->pDefaultCtor != NULL)
5159     {
5160         if (!bmtVT->AddNonVirtualMethod(bmtVT->pDefaultCtor))
5161             BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
5162     }
5163
5164     // We use slot during remoting and to map methods between generic instantiations
5165     // (see MethodTable::GetParallelMethodDesc). The current implementation
5166     // of this mechanism requires real slots.
5167     BOOL fCanHaveNonVtableSlots = (bmtGenerics->GetNumGenericArgs() == 0) && !IsInterface();
5168
5169     // Flag to avoid second pass when possible
5170     BOOL fHasNonVtableSlots = FALSE;
5171
5172     //
5173     // Place all methods that require real vtable slot first. This is necessary so
5174     // that they get consequitive slot numbers right after virtual slots.
5175     //
5176
5177     DeclaredMethodIterator it(*this);
5178     while (it.Next())
5179     {
5180         // Skip methods that are placed already
5181         if (it->GetSlotIndex() != INVALID_SLOT_INDEX)
5182             continue;
5183
5184 #ifdef _DEBUG 
5185         if(GetHalfBakedClass()->m_fDebuggingClass && g_pConfig->ShouldBreakOnMethod(it.Name()))
5186             CONSISTENCY_CHECK_MSGF(false, ("BreakOnMethodName: '%s' ", it.Name()));
5187 #endif // _DEBUG
5188
5189         if (!fCanHaveNonVtableSlots ||
5190             it->GetMethodType() == METHOD_TYPE_INSTANTIATED)
5191         {
5192             // We use slot during remoting and to map methods between generic instantiations
5193             // (see MethodTable::GetParallelMethodDesc). The current implementation
5194             // of this mechanism requires real slots.
5195         }
5196         else
5197         {
5198             // This method does not need real vtable slot
5199             fHasNonVtableSlots = TRUE;
5200             continue;
5201         }
5202
5203         // This will update slot index in bmtMDMethod
5204         if (!bmtVT->AddNonVirtualMethod(*it))
5205             BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
5206     }
5207
5208     // Remeber last real vtable slot
5209     bmtVT->cVtableSlots = bmtVT->cTotalSlots;
5210
5211     // Are there any Non-vtable slots to place?
5212     if (!fHasNonVtableSlots)
5213         return;
5214
5215     //
5216     // Now, place the remaining methods. They will get non-vtable slot.
5217     //
5218
5219     DeclaredMethodIterator it2(*this);
5220     while (it2.Next())
5221     {
5222         // Skip methods that are placed already
5223         if (it2->GetSlotIndex() != INVALID_SLOT_INDEX)
5224             continue;
5225
5226         if (!bmtVT->AddNonVirtualMethod(*it2))
5227             BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
5228     }
5229
5230 }
5231
5232 //*******************************************************************************
5233 // Determine vtable placement for each virtual member in this class.
5234 VOID
5235 MethodTableBuilder::PlaceVirtualMethods()
5236 {
5237     CONTRACTL
5238     {
5239         STANDARD_VM_CHECK;
5240
5241         PRECONDITION(CheckPointer(this));
5242         PRECONDITION(CheckPointer(bmtInternal));
5243         PRECONDITION(CheckPointer(bmtMetaData));
5244         PRECONDITION(CheckPointer(bmtError));
5245         PRECONDITION(CheckPointer(bmtProp));
5246         PRECONDITION(CheckPointer(bmtInterface));
5247         PRECONDITION(CheckPointer(bmtParent));
5248         PRECONDITION(CheckPointer(bmtMFDescs));
5249         PRECONDITION(CheckPointer(bmtEnumFields));
5250         PRECONDITION(CheckPointer(bmtMethodImpl));
5251         PRECONDITION(CheckPointer(bmtVT));
5252     }
5253     CONTRACTL_END;
5254
5255 #ifdef _DEBUG 
5256     LPCUTF8 pszDebugName, pszDebugNamespace;
5257     if (FAILED(GetMDImport()->GetNameOfTypeDef(GetCl(), &pszDebugName, &pszDebugNamespace)))
5258     {
5259         pszDebugName = pszDebugNamespace = "Invalid TypeDef record";
5260     }
5261 #endif // _DEBUG
5262
5263     //
5264     // For each virtual method
5265     //  - If the method is not declared as newslot, search all virtual methods in the parent
5266     //    type for an override candidate.
5267     //      - If such a candidate is found, test to see if the override is valid. If
5268     //        the override is not valid, throw TypeLoadException
5269     //  - If a candidate is found above, place the method in the inherited slot as both
5270     //    the Decl and the Impl.
5271     //  - Else, place the method in the next available empty vtable slot.
5272     //
5273
5274     DeclaredMethodIterator it(*this);
5275     while (it.Next())
5276     {
5277         if (!IsMdVirtual(it.Attrs()))
5278         {   // Only processing declared virtual methods
5279             continue;
5280         }
5281
5282 #ifdef _DEBUG 
5283         if(GetHalfBakedClass()->m_fDebuggingClass && g_pConfig->ShouldBreakOnMethod(it.Name()))
5284             CONSISTENCY_CHECK_MSGF(false, ("BreakOnMethodName: '%s' ", it.Name()));
5285 #endif // _DEBUG
5286
5287         // If this member is a method which overrides a parent method, it will be set to non-NULL
5288         bmtRTMethod * pParentMethod = NULL;
5289
5290         // Hash that a method with this name exists in this class
5291         // Note that ctors and static ctors are not added to the table
5292         BOOL fMethodConstraintsMatch = FALSE;
5293
5294         // If the member is marked with a new slot we do not need to find it in the parent
5295         if (HasParent() && !IsMdNewSlot(it.Attrs()))
5296         {
5297             // Attempt to find the method with this name and signature in the parent class.
5298             // This method may or may not create pParentMethodHash (if it does not already exist).
5299             // It also may or may not fill in pMemberSignature/cMemberSignature.
5300             // An error is only returned when we can not create the hash.
5301             // NOTE: This operation touches metadata
5302             pParentMethod = LoaderFindMethodInParentClass(
5303                 it->GetMethodSignature(), bmtProp->fNoSanityChecks ? NULL : &fMethodConstraintsMatch);
5304
5305             if (pParentMethod != NULL)
5306             {   // Found an override candidate
5307                 DWORD dwParentAttrs = pParentMethod->GetDeclAttrs();
5308
5309                 if (!IsMdVirtual(dwParentAttrs))
5310                 {   // Can't override a non-virtual methods
5311                     BuildMethodTableThrowException(BFA_NONVIRT_NO_SEARCH, it.Token());
5312                 }
5313
5314                 if(IsMdFinal(dwParentAttrs))
5315                 {   // Can't override a final methods
5316                     BuildMethodTableThrowException(IDS_CLASSLOAD_MI_FINAL_DECL, it.Token());
5317                 }
5318
5319                 if(!bmtProp->fNoSanityChecks)
5320                 {
5321                     TestOverRide(bmtMethodHandle(pParentMethod),
5322                                  bmtMethodHandle(*it));
5323
5324                     if (!fMethodConstraintsMatch)
5325                     {
5326                         BuildMethodTableThrowException(
5327                                 IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_IMPLICIT_OVERRIDE,
5328                                 it.Token());
5329                     }
5330                 }
5331             }
5332         }
5333
5334         // vtable method
5335         if (IsInterface())
5336         {
5337             CONSISTENCY_CHECK(pParentMethod == NULL);
5338             // Also sets new slot number on bmtRTMethod and MethodDesc
5339             if (!bmtVT->AddVirtualMethod(*it))
5340                 BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
5341         }
5342         else if (pParentMethod != NULL)
5343         {
5344             bmtVT->SetVirtualMethodOverride(pParentMethod->GetSlotIndex(), *it);
5345         }
5346         else
5347         {
5348             if (!bmtVT->AddVirtualMethod(*it))
5349                 BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
5350         }
5351     }
5352 }
5353
5354 // Given an interface map entry, and a name+signature, compute the method on the interface
5355 // that the name+signature corresponds to. Used by ProcessMethodImpls and ProcessInexactMethodImpls
5356 // Always returns the first match that it finds. Affects the ambiguities in code:#ProcessInexactMethodImpls_Ambiguities
5357 MethodTableBuilder::bmtMethodHandle 
5358 MethodTableBuilder::FindDeclMethodOnInterfaceEntry(bmtInterfaceEntry *pItfEntry, MethodSignature &declSig)
5359 {
5360     STANDARD_VM_CONTRACT;
5361
5362     bmtMethodHandle declMethod;
5363
5364     bmtInterfaceEntry::InterfaceSlotIterator slotIt =
5365         pItfEntry->IterateInterfaceSlots(GetStackingAllocator());
5366     // Check for exact match
5367     for (; !slotIt.AtEnd(); slotIt.Next())
5368     {
5369         bmtRTMethod * pCurDeclMethod = slotIt->Decl().AsRTMethod();
5370
5371         if (declSig.ExactlyEqual(pCurDeclMethod->GetMethodSignature()))
5372         {
5373             declMethod = slotIt->Decl();
5374             break;
5375         }
5376     }
5377     slotIt.ResetToStart();
5378
5379     // Check for equivalent match if exact match wasn't found
5380     if (declMethod.IsNull())
5381     {
5382         for (; !slotIt.AtEnd(); slotIt.Next())
5383         {
5384             bmtRTMethod * pCurDeclMethod = slotIt->Decl().AsRTMethod();
5385
5386             // Type Equivalence is forbidden in MethodImpl MemberRefs
5387             if (declSig.Equivalent(pCurDeclMethod->GetMethodSignature()))
5388             {
5389                 declMethod = slotIt->Decl();
5390                 break;
5391             }
5392         }
5393     }
5394
5395     return declMethod;
5396 }
5397
5398 //*******************************************************************************
5399 //
5400 // Used by BuildMethodTable
5401 // Process the list of inexact method impls generated during ProcessMethodImpls.
5402 // This list is used to cause a methodImpl to an interface to override
5403 // methods on several equivalent interfaces in the interface map. This logic is necessary
5404 // so that in the presence of an embedded interface the behavior appears to mimic
5405 // the behavior if the interface was not embedded.
5406 //
5407 // In particular, the logic here is to handle cases such as
5408 //
5409 //  Assembly A
5410 // [TypeIdentifier("x","y")]
5411 // interface I'
5412 // {  void Method(); }
5413 // interface IOther : I' {}
5414 //
5415 //  Assembly B
5416 // [TypeIdentifier("x","y")]
5417 // interface I
5418 // {  void Method(); }
5419 // class Test : I, IOther
5420 // {
5421 //     void I.Method()
5422 //     {}
5423 // }
5424 // 
5425 // In this case, there is one method, and one methodimpl, but there are 2 interfaces on the class that both
5426 // require an implementation of their method. The correct semantic for type equivalence, is that any
5427 // methodimpl directly targeting a method on an interface must be respected, and if it also applies to a type
5428 // equivalent interface method, then if that method was not methodimpl'd directly, then the methodimpl should apply
5429 // there as well. The ProcessInexactMethodImpls function does this secondary MethodImpl mapping.
5430 //
5431 //#ProcessInexactMethodImpls_Ambiguities
5432 // In the presence of ambiguities, such as there are 3 equivalent interfaces implemented on a class and 2 methodimpls,
5433 // we will apply the 2 method impls exactly to appropriate interface methods, and arbitrarily pick one to apply to the
5434 // other interface. This is clearly ambiguous, but tricky to detect in the type loader efficiently, and should hopefully
5435 // not cause too many problems.
5436 //
5437 VOID
5438 MethodTableBuilder::ProcessInexactMethodImpls()
5439 {
5440     STANDARD_VM_CONTRACT;
5441
5442     if (bmtMethod->dwNumberInexactMethodImplCandidates == 0)
5443         return;
5444
5445     DeclaredMethodIterator it(*this);
5446     while (it.Next())
5447     {
5448         // Non-virtual methods cannot be classified as methodImpl - we should have thrown an
5449         // error before reaching this point.
5450         CONSISTENCY_CHECK(!(!IsMdVirtual(it.Attrs()) && it.IsMethodImpl()));
5451
5452         if (!IsMdVirtual(it.Attrs()))
5453         {   // Only virtual methods can participate in methodImpls
5454             continue;
5455         }
5456
5457         if(!it.IsMethodImpl())
5458         {
5459             // Skip methods which are not the bodies of MethodImpl specifications
5460             continue;
5461         }
5462
5463         // If this method serves as the BODY of a MethodImpl specification, then
5464         // we should iterate all the MethodImpl's for this class and see just how many
5465         // of them this method participates in as the BODY.
5466         for(DWORD m = 0; m < bmtMethod->dwNumberMethodImpls; m++)
5467         {
5468             // Inexact matching logic only works on MethodImpls that have been opted into inexactness by ProcessMethodImpls.
5469             if (!bmtMetaData->rgMethodImplTokens[m].fConsiderDuringInexactMethodImplProcessing)
5470             {
5471                 continue;
5472             }
5473
5474             // If the methodimpl we are working with does not match this method, continue to next methodimpl
5475             if(it.Token() != bmtMetaData->rgMethodImplTokens[m].methodBody)
5476             {
5477                 continue;
5478             }
5479
5480             bool fMatchFound = false;
5481
5482             LPCUTF8 szName = NULL;
5483             PCCOR_SIGNATURE pSig = NULL;
5484             ULONG cbSig;
5485
5486             mdToken mdDecl = bmtMetaData->rgMethodImplTokens[m].methodDecl;
5487             
5488             if (TypeFromToken(mdDecl) == mdtMethodDef)
5489             {   // Different methods are aused to access MethodDef and MemberRef
5490                 // names and signatures.
5491                 if (FAILED(GetMDImport()->GetNameOfMethodDef(mdDecl, &szName)) || 
5492                     FAILED(GetMDImport()->GetSigOfMethodDef(mdDecl, &cbSig, &pSig)))
5493                 {
5494                     BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
5495                 }
5496             }
5497             else
5498             {
5499                 if (FAILED(GetMDImport()->GetNameAndSigOfMemberRef(mdDecl, &pSig, &cbSig, &szName)))
5500                 {
5501                     BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
5502                 }
5503             }
5504
5505             Substitution *pDeclSubst = &bmtMetaData->pMethodDeclSubsts[m];
5506             MethodSignature declSig(GetModule(), szName, pSig, cbSig, pDeclSubst);
5507             bmtInterfaceEntry * pItfEntry = NULL;
5508
5509             for (DWORD i = 0; i < bmtInterface->dwInterfaceMapSize; i++)
5510             {
5511                 if (bmtInterface->pInterfaceMap[i].GetInterfaceEquivalenceSet() != bmtMetaData->rgMethodImplTokens[m].interfaceEquivalenceSet)
5512                     continue;
5513
5514                 bmtMethodHandle declMethod;
5515                 pItfEntry = &bmtInterface->pInterfaceMap[i];
5516
5517                 // Search for declmethod on this interface
5518                 declMethod = FindDeclMethodOnInterfaceEntry(pItfEntry, declSig);
5519
5520                 // If we didn't find a match, continue on to next interface in the equivalence set
5521                 if (declMethod.IsNull())
5522                     continue;
5523
5524                 if (!IsMdVirtual(declMethod.GetDeclAttrs()))
5525                 {   // Make sure the decl is virtual
5526                     BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MUSTBEVIRTUAL, it.Token());
5527                 }
5528
5529                 fMatchFound = true;
5530
5531                 bool fPreexistingImplFound = false;
5532
5533                 // Check to ensure there isn't already a matching declMethod in the method impl list
5534                 for (DWORD iMethodImpl = 0; iMethodImpl < bmtMethodImpl->pIndex; iMethodImpl++)
5535                 {
5536                     if (bmtMethodImpl->GetDeclarationMethod(iMethodImpl) == declMethod)
5537                     {
5538                         fPreexistingImplFound = true;
5539                         break;
5540                     }
5541                 }
5542
5543                 // Search for other matches
5544                 if (fPreexistingImplFound)
5545                     continue;
5546
5547                 // Otherwise, record the method impl discovery if the match is 
5548                 bmtMethodImpl->AddMethodImpl(*it, declMethod, bmtMetaData->rgMethodImplTokens[m].methodDecl, GetStackingAllocator());
5549             }
5550
5551             if (!fMatchFound && bmtMetaData->rgMethodImplTokens[m].fThrowIfUnmatchedDuringInexactMethodImplProcessing)
5552             {
5553                 BuildMethodTableThrowException(IDS_CLASSLOAD_MI_DECLARATIONNOTFOUND, it.Token());
5554             }
5555         }
5556     }
5557 }
5558
5559 //*******************************************************************************
5560 //
5561 // Used by BuildMethodTable
5562 //
5563 VOID
5564 MethodTableBuilder::ProcessMethodImpls()
5565 {
5566     STANDARD_VM_CONTRACT;
5567
5568     if (bmtMethod->dwNumberMethodImpls == 0)
5569         return;
5570
5571     HRESULT hr = S_OK;
5572
5573     DeclaredMethodIterator it(*this);
5574     while (it.Next())
5575     {
5576         // Non-virtual methods cannot be classified as methodImpl - we should have thrown an
5577         // error before reaching this point.
5578         CONSISTENCY_CHECK(!(!IsMdVirtual(it.Attrs()) && it.IsMethodImpl()));
5579
5580         if (!IsMdVirtual(it.Attrs()))
5581         {   // Only virtual methods can participate in methodImpls
5582             continue;
5583         }
5584
5585         // If this method serves as the BODY of a MethodImpl specification, then
5586         // we should iterate all the MethodImpl's for this class and see just how many
5587         // of them this method participates in as the BODY.
5588         if(it.IsMethodImpl())
5589         {
5590             for(DWORD m = 0; m < bmtMethod->dwNumberMethodImpls; m++)
5591             {
5592                 if(it.Token() == bmtMetaData->rgMethodImplTokens[m].methodBody)
5593                 {
5594                     mdToken mdDecl = bmtMetaData->rgMethodImplTokens[m].methodDecl;
5595                     bmtMethodHandle declMethod;
5596
5597                     // Get the parent token for the decl method token
5598                     mdToken tkParent = mdTypeDefNil;
5599                     if (TypeFromToken(mdDecl) == mdtMethodDef || TypeFromToken(mdDecl) == mdtMemberRef)
5600                     {
5601                         if (FAILED(hr = GetMDImport()->GetParentToken(mdDecl,&tkParent)))
5602                         {
5603                             BuildMethodTableThrowException(hr, *bmtError);
5604                         }
5605                     }
5606
5607                     if (GetCl() == tkParent)
5608                     {   // The DECL has been declared within the class that we're currently building.
5609                         hr = S_OK;
5610
5611                         if(bmtError->pThrowable != NULL)
5612                         {
5613                             *(bmtError->pThrowable) = NULL;
5614                         }
5615
5616                         if(TypeFromToken(mdDecl) != mdtMethodDef)
5617                         {
5618                             if (FAILED(hr = FindMethodDeclarationForMethodImpl(
5619                                                 mdDecl, &mdDecl, TRUE)))
5620                             {
5621                                 BuildMethodTableThrowException(hr, *bmtError);
5622                             }
5623                         }
5624
5625                         CONSISTENCY_CHECK(TypeFromToken(mdDecl) == mdtMethodDef);
5626                         declMethod = bmtMethod->FindDeclaredMethodByToken(mdDecl);
5627                     }
5628                     else
5629                     {   // We can't call GetDescFromMemberDefOrRef here because this
5630                         // method depends on a fully-loaded type, including parent types,
5631                         // which is not always guaranteed. In particular, it requires that
5632                         // the instantiation dictionary be filled. The solution is the following:
5633                         //   1. Load the approximate type that the method belongs to.
5634                         //   2. Get or create the correct substitution for the type involved
5635                         //   3. Iterate the introduced methods on that type looking for a matching
5636                         //      method.
5637
5638                         LPCUTF8 szName = NULL;
5639                         PCCOR_SIGNATURE pSig = NULL;
5640                         ULONG cbSig;
5641                         if (TypeFromToken(mdDecl) == mdtMethodDef)
5642                         {   // Different methods are aused to access MethodDef and MemberRef
5643                             // names and signatures.
5644                             if (FAILED(GetMDImport()->GetNameOfMethodDef(mdDecl, &szName)) || 
5645                                 FAILED(GetMDImport()->GetSigOfMethodDef(mdDecl, &cbSig, &pSig)))
5646                             {
5647                                 BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
5648                             }
5649                         }
5650                         else
5651                         {
5652                             if (FAILED(GetMDImport()->GetNameAndSigOfMemberRef(mdDecl, &pSig, &cbSig, &szName)))
5653                             {
5654                                 BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
5655                             }
5656                         }
5657                         
5658                         Substitution *pDeclSubst = &bmtMetaData->pMethodDeclSubsts[m];
5659                         MethodTable * pDeclMT = NULL;
5660                         MethodSignature declSig(GetModule(), szName, pSig, cbSig, pDeclSubst);
5661
5662                         {   // 1. Load the approximate type.
5663                             // Block for the LoadsTypeViolation.
5664                             CONTRACT_VIOLATION(LoadsTypeViolation);
5665                             pDeclMT = ClassLoader::LoadTypeDefOrRefOrSpecThrowing(
5666                                 GetModule(),
5667                                 tkParent,
5668                                 &bmtGenerics->typeContext,
5669                                 ClassLoader::ThrowIfNotFound,
5670                                 ClassLoader::PermitUninstDefOrRef,
5671                                 ClassLoader::LoadTypes,
5672                                 CLASS_LOAD_APPROXPARENTS,
5673                                 TRUE).GetMethodTable()->GetCanonicalMethodTable();
5674                         }
5675
5676                         {   // 2. Get or create the correct substitution
5677                             bmtRTType * pDeclType = NULL;
5678
5679                             if (pDeclMT->IsInterface())
5680                             {   // If the declaration method is a part of an interface, search through
5681                                 // the interface map to find the matching interface so we can provide
5682                                 // the correct substitution chain.
5683                                 pDeclType = NULL;
5684
5685                                 bmtInterfaceEntry * pItfEntry = NULL;
5686                                 for (DWORD i = 0; i < bmtInterface->dwInterfaceMapSize; i++)
5687                                 {
5688                                     bmtRTType * pCurItf = bmtInterface->pInterfaceMap[i].GetInterfaceType();
5689                                     // Type Equivalence is not respected for this comparision as you can have multiple type equivalent interfaces on a class
5690                                     TokenPairList newVisited = TokenPairList::AdjustForTypeEquivalenceForbiddenScope(NULL);
5691                                     if (MetaSig::CompareTypeDefsUnderSubstitutions(
5692                                         pCurItf->GetMethodTable(),      pDeclMT,
5693                                         &pCurItf->GetSubstitution(),    pDeclSubst,
5694                                         &newVisited))
5695                                     {
5696                                         pItfEntry = &bmtInterface->pInterfaceMap[i];
5697                                         pDeclType = pCurItf;
5698                                         break;
5699                                     }
5700                                 }
5701
5702                                 if (IsInterface())
5703                                 {
5704                                     if (pDeclType == NULL)
5705                                     {
5706                                         // Interface is not implemented by this type.
5707                                         BuildMethodTableThrowException(IDS_CLASSLOAD_MI_NOTIMPLEMENTED, it.Token());
5708                                     }
5709                                 }
5710                                 else
5711                                 {
5712                                     if (pDeclType == NULL)
5713                                     {
5714                                         DWORD equivalenceSet = 0;
5715
5716                                         for (DWORD i = 0; i < bmtInterface->dwInterfaceMapSize; i++)
5717                                         {
5718                                             bmtRTType * pCurItf = bmtInterface->pInterfaceMap[i].GetInterfaceType();
5719                                             // Type Equivalence is respected for this comparision as we just need to find an 
5720                                             // equivalent interface, the particular interface is unimportant
5721                                             if (MetaSig::CompareTypeDefsUnderSubstitutions(
5722                                                 pCurItf->GetMethodTable(), pDeclMT,
5723                                                 &pCurItf->GetSubstitution(), pDeclSubst,
5724                                                 NULL))
5725                                             {
5726                                                 equivalenceSet = bmtInterface->pInterfaceMap[i].GetInterfaceEquivalenceSet();
5727                                                 pItfEntry = &bmtInterface->pInterfaceMap[i];
5728                                                 break;
5729                                             }
5730                                         }
5731
5732                                         if (equivalenceSet == 0)
5733                                         {
5734                                             // Interface is not implemented by this type.
5735                                             BuildMethodTableThrowException(IDS_CLASSLOAD_MI_NOTIMPLEMENTED, it.Token());
5736                                         }
5737
5738                                         // Interface is not implemented by this type exactly. We need to consider this MethodImpl on non exact interface matches,
5739                                         // as the only match may be one of the non-exact matches
5740                                         bmtMetaData->rgMethodImplTokens[m].fConsiderDuringInexactMethodImplProcessing = true;
5741                                         bmtMetaData->rgMethodImplTokens[m].fThrowIfUnmatchedDuringInexactMethodImplProcessing = true;
5742                                         bmtMetaData->rgMethodImplTokens[m].interfaceEquivalenceSet = equivalenceSet;
5743                                         bmtMethod->dwNumberInexactMethodImplCandidates++;
5744                                         continue; // Move on to other MethodImpls
5745                                     }
5746                                     else
5747                                     {
5748                                         // This method impl may need to match other methods during inexact processing
5749                                         if (pItfEntry->InEquivalenceSetWithMultipleEntries())
5750                                         {
5751                                             bmtMetaData->rgMethodImplTokens[m].fConsiderDuringInexactMethodImplProcessing = true;
5752                                             bmtMetaData->rgMethodImplTokens[m].fThrowIfUnmatchedDuringInexactMethodImplProcessing = false;
5753                                             bmtMetaData->rgMethodImplTokens[m].interfaceEquivalenceSet = pItfEntry->GetInterfaceEquivalenceSet();
5754                                             bmtMethod->dwNumberInexactMethodImplCandidates++;
5755                                         }
5756                                     }
5757                                 }
5758
5759                                 // 3. Find the matching method.
5760                                 declMethod = FindDeclMethodOnInterfaceEntry(pItfEntry, declSig);
5761                             }
5762                             else
5763                             {   // Assume the MethodTable is a parent of the current type,
5764                                 // and create the substitution chain to match it.
5765
5766                                 pDeclType = NULL;
5767
5768                                 for (bmtRTType *pCur = GetParentType();
5769                                      pCur != NULL;
5770                                      pCur = pCur->GetParentType())
5771                                 {
5772                                     if (pCur->GetMethodTable() == pDeclMT)
5773                                     {
5774                                         pDeclType = pCur;
5775                                         break;
5776                                     }
5777                                 }
5778
5779                                 if (pDeclType == NULL)
5780                                 {   // Method's type is not a parent.
5781                                     BuildMethodTableThrowException(IDS_CLASSLOAD_MI_DECLARATIONNOTFOUND, it.Token());
5782                                 }
5783
5784                                 // 3. Find the matching method.
5785                                 bmtRTType *pCurDeclType = pDeclType;
5786                                 do
5787                                 {
5788                                     // two pass algorithm. search for exact matches followed
5789                                     // by equivalent matches.
5790                                     for (int iPass = 0; (iPass < 2) && (declMethod.IsNull()); iPass++)
5791                                     {
5792                                         MethodTable *pCurDeclMT = pCurDeclType->GetMethodTable();
5793     
5794                                         MethodTable::IntroducedMethodIterator methIt(pCurDeclMT);
5795                                         for(; methIt.IsValid(); methIt.Next())
5796                                         {
5797                                             MethodDesc * pCurMD = methIt.GetMethodDesc();
5798     
5799                                             if (pCurDeclMT != pDeclMT)
5800                                             {
5801                                                 // If the method isn't on the declaring type, then it must be virtual.
5802                                                 if (!pCurMD->IsVirtual())
5803                                                     continue;
5804                                             }
5805                                             if (strcmp(szName, pCurMD->GetName()) == 0)
5806                                             {
5807                                                 PCCOR_SIGNATURE pCurMDSig;
5808                                                 DWORD cbCurMDSig;
5809                                                 pCurMD->GetSig(&pCurMDSig, &cbCurMDSig);
5810
5811                                                 // First pass searches for declaration methods should not use type equivalence
5812                                                 TokenPairList newVisited = TokenPairList::AdjustForTypeEquivalenceForbiddenScope(NULL);
5813
5814                                                 if (MetaSig::CompareMethodSigs(
5815                                                     declSig.GetSignature(),
5816                                                     static_cast<DWORD>(declSig.GetSignatureLength()),
5817                                                     declSig.GetModule(),
5818                                                     &declSig.GetSubstitution(),
5819                                                     pCurMDSig,
5820                                                     cbCurMDSig,
5821                                                     pCurMD->GetModule(),
5822                                                     &pCurDeclType->GetSubstitution(),
5823                                                     iPass == 0 ? &newVisited : NULL))
5824                                                 {
5825                                                     declMethod = (*bmtParent->pSlotTable)[pCurMD->GetSlot()].Decl();
5826                                                     break;
5827                                                 }
5828                                             }
5829                                         }
5830                                     }
5831
5832                                     pCurDeclType = pCurDeclType->GetParentType();
5833                                 } while ((pCurDeclType != NULL) && (declMethod.IsNull()));
5834                             }
5835
5836                             if (declMethod.IsNull())
5837                             {   // Would prefer to let this fall out to the BuildMethodTableThrowException
5838                                 // below, but due to v2.0 and earlier behaviour throwing a MissingMethodException,
5839                                 // primarily because this code used to be a simple call to
5840                                 // MemberLoader::GetDescFromMemberDefOrRef (see above for reason why),
5841                                 // we must continue to do the same.
5842                                 MemberLoader::ThrowMissingMethodException(
5843                                     pDeclMT,
5844                                     declSig.GetName(),
5845                                     declSig.GetModule(),
5846                                     declSig.GetSignature(),
5847                                     static_cast<DWORD>(declSig.GetSignatureLength()),
5848                                     &bmtGenerics->typeContext);
5849                             }
5850                         }
5851                     }
5852
5853                     if (declMethod.IsNull())
5854                     {   // Method not found, throw.
5855                         BuildMethodTableThrowException(IDS_CLASSLOAD_MI_DECLARATIONNOTFOUND, it.Token());
5856                     }
5857                     
5858                     if (!IsMdVirtual(declMethod.GetDeclAttrs()))
5859                     {   // Make sure the decl is virtual
5860                         BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MUSTBEVIRTUAL, it.Token());
5861                     }
5862
5863                     bmtMethodImpl->AddMethodImpl(*it, declMethod, mdDecl, GetStackingAllocator());
5864                 }
5865             }
5866         }
5867     } /* end ... for each member */
5868 }
5869
5870 //*******************************************************************************
5871 // InitMethodDesc takes a pointer to space that's already allocated for the
5872 // particular type of MethodDesc, and initializes based on the other info.
5873 // This factors logic between PlaceMembers (the regular code path) & AddMethod
5874 // (Edit & Continue (EnC) code path) so we don't have to maintain separate copies.
5875 VOID 
5876 MethodTableBuilder::InitMethodDesc(
5877     MethodDesc *        pNewMD, // This is should actually be of the correct sub-type, based on Classification
5878     DWORD               Classification,
5879     mdToken             tok,
5880     DWORD               dwImplFlags,
5881     DWORD               dwMemberAttrs,
5882     BOOL                fEnC,
5883     DWORD               RVA,        // Only needed for NDirect case
5884     IMDInternalImport * pIMDII,     // Needed for NDirect, EEImpl(Delegate) cases
5885     LPCSTR              pMethodName // Only needed for mcEEImpl (Delegate) case
5886     COMMA_INDEBUG(LPCUTF8 pszDebugMethodName)
5887     COMMA_INDEBUG(LPCUTF8 pszDebugClassName)
5888     COMMA_INDEBUG(LPCUTF8 pszDebugMethodSignature)
5889     )
5890 {
5891     CONTRACTL
5892     {
5893         THROWS;
5894         if (fEnC) { GC_NOTRIGGER; } else { GC_TRIGGERS; }
5895         MODE_ANY;
5896     }
5897     CONTRACTL_END;
5898
5899     LOG((LF_CORDB, LL_EVERYTHING, "EEC::IMD: pNewMD:0x%x for tok:0x%x (%s::%s)\n",
5900         pNewMD, tok, pszDebugClassName, pszDebugMethodName));
5901
5902     // Now we know the classification we can perform any classification specific initialization.
5903
5904     // The method desc is zero inited by the caller.
5905
5906     switch (Classification)
5907     {
5908     case mcNDirect:
5909         {
5910             // NDirect specific initialization.
5911             NDirectMethodDesc *pNewNMD = (NDirectMethodDesc*)pNewMD;
5912
5913             // Allocate writeable data
5914             pNewNMD->ndirect.m_pWriteableData.SetValue((NDirectWriteableData*)
5915                 AllocateFromHighFrequencyHeap(S_SIZE_T(sizeof(NDirectWriteableData))));
5916
5917 #ifdef HAS_NDIRECT_IMPORT_PRECODE 
5918             pNewNMD->ndirect.m_pImportThunkGlue.SetValue(Precode::Allocate(PRECODE_NDIRECT_IMPORT, pNewMD,
5919                 GetLoaderAllocator(), GetMemTracker())->AsNDirectImportPrecode());
5920 #else // !HAS_NDIRECT_IMPORT_PRECODE
5921             pNewNMD->GetNDirectImportThunkGlue()->Init(pNewNMD);
5922 #endif // !HAS_NDIRECT_IMPORT_PRECODE
5923
5924 #if defined(_TARGET_X86_)
5925             pNewNMD->ndirect.m_cbStackArgumentSize = 0xFFFF;
5926 #endif // defined(_TARGET_X86_)
5927
5928             // If the RVA of a native method is set, this is an early-bound IJW call
5929             if (RVA != 0 && IsMiUnmanaged(dwImplFlags) && IsMiNative(dwImplFlags))
5930             {
5931                 // Note that we cannot initialize the stub directly now in the general case,
5932                 // as LoadLibrary may not have been performed yet.
5933                 pNewNMD->SetIsEarlyBound();
5934             }
5935
5936             pNewNMD->GetWriteableData()->m_pNDirectTarget = pNewNMD->GetNDirectImportThunkGlue()->GetEntrypoint();
5937         }
5938         break;
5939
5940     case mcFCall:
5941         break;
5942
5943     case mcEEImpl:
5944         // For the Invoke method we will set a standard invoke method.
5945         BAD_FORMAT_NOTHROW_ASSERT(IsDelegate());
5946
5947         // For the asserts, either the pointer is NULL (since the class hasn't
5948         // been constructed yet), or we're in EnC mode, meaning that the class
5949         // does exist, but we may be re-assigning the field to point to an
5950         // updated MethodDesc
5951
5952         // It is not allowed for EnC to replace one of the runtime builtin methods
5953
5954         if (strcmp(pMethodName, "Invoke") == 0)
5955         {
5956             BAD_FORMAT_NOTHROW_ASSERT(((DelegateEEClass*)GetHalfBakedClass())->m_pInvokeMethod.IsNull());
5957             ((DelegateEEClass*)GetHalfBakedClass())->m_pInvokeMethod.SetValue(pNewMD);
5958         }
5959         else if (strcmp(pMethodName, "BeginInvoke") == 0)
5960         {
5961             BAD_FORMAT_NOTHROW_ASSERT(((DelegateEEClass*)GetHalfBakedClass())->m_pBeginInvokeMethod.IsNull());
5962             ((DelegateEEClass*)GetHalfBakedClass())->m_pBeginInvokeMethod.SetValue(pNewMD);
5963         }
5964         else if (strcmp(pMethodName, "EndInvoke") == 0)
5965         {
5966             BAD_FORMAT_NOTHROW_ASSERT(((DelegateEEClass*)GetHalfBakedClass())->m_pEndInvokeMethod.IsNull());
5967             ((DelegateEEClass*)GetHalfBakedClass())->m_pEndInvokeMethod.SetValue(pNewMD);
5968         }
5969         else
5970         {
5971             BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
5972         }
5973
5974         // StoredSig specific intialization
5975         {
5976             StoredSigMethodDesc *pNewSMD = (StoredSigMethodDesc*) pNewMD;;
5977             DWORD cSig;
5978             PCCOR_SIGNATURE pSig;
5979             if (FAILED(pIMDII->GetSigOfMethodDef(tok, &cSig, &pSig)))
5980             {
5981                 BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
5982             }
5983             pNewSMD->SetStoredMethodSig(pSig, cSig);
5984         }
5985         break;
5986
5987 #ifdef FEATURE_COMINTEROP
5988     case mcComInterop:
5989 #endif // FEATURE_COMINTEROP
5990     case mcIL:
5991         break;
5992
5993     case mcInstantiated:
5994 #ifdef EnC_SUPPORTED 
5995         if (fEnC)
5996         {
5997             // We reuse the instantiated methoddescs to get the slot
5998             InstantiatedMethodDesc* pNewIMD = (InstantiatedMethodDesc*) pNewMD;
5999             pNewIMD->SetupEnCAddedMethod();
6000         }
6001         else
6002 #endif // EnC_SUPPORTED
6003         {
6004             // Initialize the typical instantiation.
6005             InstantiatedMethodDesc* pNewIMD = (InstantiatedMethodDesc*) pNewMD;
6006             //data has the same lifetime as method table, use our allocator
6007             pNewIMD->SetupGenericMethodDefinition(pIMDII, GetLoaderAllocator(), GetMemTracker(), GetModule(),
6008                                                   tok);
6009         }
6010         break;
6011
6012     default:
6013         BAD_FORMAT_NOTHROW_ASSERT(!"Failed to set a method desc classification");
6014     }
6015
6016     // Check the method desc's classification.
6017     _ASSERTE(pNewMD->GetClassification() == Classification);
6018
6019     pNewMD->SetMemberDef(tok);
6020
6021     if (IsMdStatic(dwMemberAttrs))
6022         pNewMD->SetStatic();
6023
6024     // Set suppress unmanaged code access permission attribute
6025
6026     if (pNewMD->IsNDirect())
6027         pNewMD->ComputeSuppressUnmanagedCodeAccessAttr(pIMDII);
6028
6029 #ifdef _DEBUG 
6030     // Mark as many methods as synchronized as possible.
6031     //
6032     // Note that this can easily cause programs to deadlock, and that
6033     // should not be treated as a bug in the program.
6034
6035     static ConfigDWORD stressSynchronized;
6036     DWORD stressSynchronizedVal = stressSynchronized.val(CLRConfig::INTERNAL_stressSynchronized);
6037
6038     bool isStressSynchronized =  stressSynchronizedVal &&
6039         pNewMD->IsIL() && // Synchronized is not supported on Ecalls, NDirect method, etc
6040         // IsValueClass() and IsEnum() do not work for System.ValueType and System.Enum themselves
6041         ((g_pValueTypeClass != NULL && g_pEnumClass != NULL &&
6042           !IsValueClass()) || // Can not synchronize on byref "this"
6043           IsMdStatic(dwMemberAttrs)) && // IsStatic() blows up in _DEBUG as pNewMD is not fully inited
6044         g_pObjectClass != NULL; // Ignore Object:* since "this" could be a boxed object
6045
6046     // stressSynchronized=1 turns off the stress in the system domain to reduce
6047     // the chances of spurious deadlocks. Deadlocks in user code can still occur.
6048     // stressSynchronized=2 will probably cause more deadlocks, and is not recommended
6049     if (stressSynchronizedVal == 1 && GetAssembly()->IsSystem())
6050         isStressSynchronized = false;
6051
6052     if (IsMiSynchronized(dwImplFlags) || isStressSynchronized)
6053 #else // !_DEBUG
6054     if (IsMiSynchronized(dwImplFlags))
6055 #endif // !_DEBUG
6056         pNewMD->SetSynchronized();
6057
6058 #ifdef _DEBUG 
6059     pNewMD->m_pszDebugMethodName = (LPUTF8)pszDebugMethodName;
6060     pNewMD->m_pszDebugClassName  = (LPUTF8)pszDebugClassName;
6061     pNewMD->m_pDebugMethodTable.SetValue(GetHalfBakedMethodTable());
6062
6063     if (pszDebugMethodSignature == NULL)
6064         pNewMD->m_pszDebugMethodSignature = FormatSig(pNewMD,pNewMD->GetLoaderAllocator()->GetLowFrequencyHeap(),GetMemTracker());
6065     else
6066         pNewMD->m_pszDebugMethodSignature = pszDebugMethodSignature;
6067 #endif // _DEBUG
6068 } // MethodTableBuilder::InitMethodDesc
6069
6070 //*******************************************************************************
6071 //
6072 // Used by BuildMethodTable
6073 //
6074 VOID 
6075 MethodTableBuilder::AddMethodImplDispatchMapping(
6076     DispatchMapTypeID typeID,
6077     SLOT_INDEX        slotNumber,
6078     bmtMDMethod *     pImplMethod)
6079 {
6080     STANDARD_VM_CONTRACT;
6081
6082     MethodDesc * pMDImpl = pImplMethod->GetMethodDesc();
6083
6084     // Look for an existing entry in the map.
6085     DispatchMapBuilder::Iterator it(bmtVT->pDispatchMapBuilder);
6086     if (bmtVT->pDispatchMapBuilder->Find(typeID, slotNumber, it))
6087     {
6088         // Throw if this entry has already previously been MethodImpl'd.
6089         if (it.IsMethodImpl())
6090         {
6091             // NOTE: This is where we check for duplicate overrides. This is the easiest place to check
6092             //       because duplicate overrides could in fact have separate MemberRefs to the same
6093             //       member and so just comparing tokens at the very start would not be enough.
6094             if (it.GetTargetMD() != pMDImpl)
6095             {
6096                 BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MULTIPLEOVERRIDES, pMDImpl->GetMemberDef());
6097             }
6098         }
6099         // This is the first MethodImpl. That's ok.
6100         else
6101         {
6102             it.SetTarget(pMDImpl);
6103             it.SetIsMethodImpl();
6104         }
6105     }
6106     // A mapping for this interface method does not exist, so insert it.
6107     else
6108     {
6109         bmtVT->pDispatchMapBuilder->InsertMDMapping(
6110             typeID, 
6111             slotNumber, 
6112             pMDImpl, 
6113             TRUE);
6114     }
6115
6116     // Save the entry into the vtable as well, if it isn't an interface methodImpl
6117     if (typeID == DispatchMapTypeID::ThisClassID())
6118     {
6119         bmtVT->SetVirtualMethodImpl(slotNumber, pImplMethod);
6120     }
6121 } // MethodTableBuilder::AddMethodImplDispatchMapping
6122
6123 //*******************************************************************************
6124 VOID
6125 MethodTableBuilder::MethodImplCompareSignatures(
6126     bmtMethodHandle     hDecl,
6127     bmtMethodHandle     hImpl,
6128     DWORD               dwConstraintErrorCode)
6129 {
6130     CONTRACTL {
6131         STANDARD_VM_CHECK;
6132         PRECONDITION(!hDecl.IsNull());
6133         PRECONDITION(!hImpl.IsNull());
6134         PRECONDITION(TypeFromToken(hDecl.GetMethodSignature().GetToken()) == mdtMethodDef);
6135         PRECONDITION(TypeFromToken(hImpl.GetMethodSignature().GetToken()) == mdtMethodDef);
6136     } CONTRACTL_END;
6137
6138     const MethodSignature &declSig(hDecl.GetMethodSignature());
6139     const MethodSignature &implSig(hImpl.GetMethodSignature());
6140
6141     if (!MethodSignature::SignaturesEquivalent(declSig, implSig))
6142     {
6143         LOG((LF_CLASSLOADER, LL_INFO1000, "BADSIG placing MethodImpl: %x\n", declSig.GetToken()));
6144         BuildMethodTableThrowException(COR_E_TYPELOAD, IDS_CLASSLOAD_MI_BADSIGNATURE, declSig.GetToken());
6145     }
6146
6147     //now compare the method constraints
6148     if (!MetaSig::CompareMethodConstraints(&implSig.GetSubstitution(), implSig.GetModule(), implSig.GetToken(),
6149                                            &declSig.GetSubstitution(), declSig.GetModule(), declSig.GetToken()))
6150     {
6151         BuildMethodTableThrowException(dwConstraintErrorCode, implSig.GetToken());
6152     }
6153 }
6154
6155 //*******************************************************************************
6156 // We should have collected all the method impls. Cycle through them creating the method impl
6157 // structure that holds the information about which slots are overridden.
6158 VOID
6159 MethodTableBuilder::PlaceMethodImpls()
6160 {
6161     STANDARD_VM_CONTRACT;
6162
6163     if(bmtMethodImpl->pIndex == 0)
6164     {
6165         return;
6166     }
6167
6168     // Allocate some temporary storage. The number of overrides for a single method impl
6169     // cannot be greater then the number of vtable slots for classes. But for interfaces
6170     // it might contain overrides for other interface methods.
6171     DWORD dwMaxSlotSize = IsInterface() ? bmtMethod->dwNumberMethodImpls : bmtVT->cVirtualSlots;
6172
6173     DWORD * slots = new (&GetThread()->m_MarshalAlloc) DWORD[dwMaxSlotSize];
6174     mdToken * tokens = new (&GetThread()->m_MarshalAlloc) mdToken[dwMaxSlotSize];
6175     RelativePointer<MethodDesc *> * replaced = new (&GetThread()->m_MarshalAlloc) RelativePointer<MethodDesc*>[dwMaxSlotSize];
6176
6177     DWORD iEntry = 0;
6178     bmtMDMethod * pCurImplMethod = bmtMethodImpl->GetImplementationMethod(iEntry);
6179
6180     DWORD slotIndex = 0;
6181
6182     // The impls are sorted according to the method descs for the body of the method impl.
6183     // Loop through the impls until the next body is found. When a single body
6184     // has been done move the slots implemented and method descs replaced into the storage
6185     // found on the body method desc.
6186     while (true)
6187     {   // collect information until we reach the next body
6188
6189         tokens[slotIndex] = bmtMethodImpl->GetDeclarationToken(iEntry);
6190
6191         // Get the declaration part of the method impl. It will either be a token
6192         // (declaration is on this type) or a method desc.
6193         bmtMethodHandle hDeclMethod = bmtMethodImpl->GetDeclarationMethod(iEntry);
6194         if(hDeclMethod.IsMDMethod())
6195         {   
6196             // The declaration is on the type being built
6197             bmtMDMethod * pCurDeclMethod = hDeclMethod.AsMDMethod();
6198
6199             mdToken mdef = pCurDeclMethod->GetMethodSignature().GetToken();
6200             if (bmtMethodImpl->IsBody(mdef))
6201             {   // A method declared on this class cannot be both a decl and an impl
6202                 BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MULTIPLEOVERRIDES, mdef);
6203             }
6204
6205             if (IsInterface())
6206             {
6207                 // Throws
6208                 PlaceInterfaceDeclarationOnInterface(
6209                     hDeclMethod,
6210                     pCurImplMethod,
6211                     slots,              // Adds override to the slot and replaced arrays.
6212                     replaced,
6213                     &slotIndex,
6214                     dwMaxSlotSize);     // Increments count                
6215             }
6216             else
6217             {
6218                 // Throws
6219                 PlaceLocalDeclarationOnClass(
6220                     pCurDeclMethod,
6221                     pCurImplMethod,
6222                     slots,              // Adds override to the slot and replaced arrays.
6223                     replaced,
6224                     &slotIndex,
6225                     dwMaxSlotSize);     // Increments count
6226             }
6227         }
6228         else
6229         {
6230             bmtRTMethod * pCurDeclMethod = hDeclMethod.AsRTMethod();
6231
6232             if (IsInterface())
6233             {
6234                 // Throws
6235                 PlaceInterfaceDeclarationOnInterface(
6236                     hDeclMethod,
6237                     pCurImplMethod,
6238                     slots,              // Adds override to the slot and replaced arrays.
6239                     replaced,
6240                     &slotIndex,
6241                     dwMaxSlotSize);     // Increments count     
6242             }
6243             else
6244             {
6245                 // Do not use pDecl->IsInterface here as that asks the method table and the MT may not yet be set up.
6246                 if (pCurDeclMethod->GetOwningType()->IsInterface())
6247                 {
6248                     // Throws
6249                     PlaceInterfaceDeclarationOnClass(
6250                         pCurDeclMethod,
6251                         pCurImplMethod);
6252                 }
6253                 else
6254                 {
6255                     // Throws
6256                     PlaceParentDeclarationOnClass(
6257                         pCurDeclMethod,
6258                         pCurImplMethod,
6259                         slots,
6260                         replaced,
6261                         &slotIndex,
6262                         dwMaxSlotSize);        // Increments count
6263                 }
6264             }
6265         }
6266
6267         iEntry++;
6268
6269         if(iEntry == bmtMethodImpl->pIndex)
6270         {
6271             // We hit the end of the list so dump the current data and leave
6272             WriteMethodImplData(pCurImplMethod, slotIndex, slots, tokens, replaced);
6273             break;
6274         }
6275         else
6276         {
6277             bmtMDMethod * pNextImplMethod = bmtMethodImpl->GetImplementationMethod(iEntry);
6278
6279             if (pNextImplMethod != pCurImplMethod)
6280             {
6281                 // If we're moving on to a new body, dump the current data and reset the counter
6282                 WriteMethodImplData(pCurImplMethod, slotIndex, slots, tokens, replaced);
6283                 slotIndex = 0;
6284             }
6285
6286             pCurImplMethod = pNextImplMethod;
6287         }
6288     }  // while(next != NULL)
6289 } // MethodTableBuilder::PlaceMethodImpls
6290
6291 //*******************************************************************************
6292 VOID
6293 MethodTableBuilder::WriteMethodImplData(
6294     bmtMDMethod * pImplMethod, 
6295     DWORD         cSlots, 
6296     DWORD *       rgSlots, 
6297     mdToken *     rgTokens,
6298     RelativePointer<MethodDesc *> * rgDeclMD)
6299 {
6300     STANDARD_VM_CONTRACT;
6301     
6302     // Use the number of overrides to
6303     // push information on to the method desc. We store the slots that
6304     // are overridden and the method desc that is replaced. That way
6305     // when derived classes need to determine if the method is to be
6306     // overridden then it can check the name against the replaced
6307     // method desc not the bodies name.
6308     if (cSlots == 0)
6309     {
6310         //@TODO:NEWVTWORK: Determine methodImpl status so that we don't need this workaround.
6311         //@TODO:NEWVTWORK: This occurs when only interface decls are involved, since
6312         //@TODO:NEWVTWORK: these are stored in the dispatch map and not on the methoddesc.
6313     }
6314     else
6315     {
6316         MethodImpl * pImpl = pImplMethod->GetMethodDesc()->GetMethodImpl();
6317
6318         // Set the size of the info the MethodImpl needs to keep track of.
6319         pImpl->SetSize(GetLoaderAllocator()->GetHighFrequencyHeap(), GetMemTracker(), cSlots);
6320
6321         if (!IsInterface())
6322         {
6323             // If we are currently builting an interface, the slots here has no meaning and we can skip it
6324             // Sort the two arrays in slot index order
6325             // This is required in MethodImpl::FindSlotIndex and MethodImpl::Iterator as we'll be using 
6326             // binary search later
6327             for (DWORD i = 0; i < cSlots; i++)
6328             {
6329                 unsigned int min = i;
6330                 for (DWORD j = i + 1; j < cSlots; j++)
6331                 {
6332                     if (rgSlots[j] < rgSlots[min])
6333                     {
6334                         min = j;
6335                     }
6336                 }
6337
6338                 if (min != i)
6339                 {
6340                     MethodDesc * mTmp = rgDeclMD[i].GetValue();
6341                     rgDeclMD[i].SetValue(rgDeclMD[min].GetValue());
6342                     rgDeclMD[min].SetValue(mTmp);
6343
6344                     DWORD sTmp = rgSlots[i];
6345                     rgSlots[i] = rgSlots[min];
6346                     rgSlots[min] = sTmp;
6347
6348                     mdToken tTmp = rgTokens[i];
6349                     rgTokens[i] = rgTokens[min];
6350                     rgTokens[min] = tTmp;
6351                 }
6352             }
6353         }
6354
6355         // Go and set the method impl
6356         pImpl->SetData(rgSlots, rgTokens, rgDeclMD);
6357
6358         GetHalfBakedClass()->SetContainsMethodImpls();
6359     }
6360 } // MethodTableBuilder::WriteMethodImplData
6361
6362 //*******************************************************************************
6363 VOID
6364 MethodTableBuilder::PlaceLocalDeclarationOnClass(
6365     bmtMDMethod * pDecl, 
6366     bmtMDMethod * pImpl, 
6367     DWORD *       slots, 
6368     RelativePointer<MethodDesc *> * replaced,
6369     DWORD *       pSlotIndex,
6370     DWORD         dwMaxSlotSize)
6371 {
6372     CONTRACTL
6373     {
6374         STANDARD_VM_CHECK;
6375         PRECONDITION(CheckPointer(bmtVT->pDispatchMapBuilder));
6376         PRECONDITION(CheckPointer(pDecl));
6377         PRECONDITION(CheckPointer(pImpl));
6378     }
6379     CONTRACTL_END
6380
6381     if (!bmtProp->fNoSanityChecks)
6382     {
6383         ///////////////////////////////
6384         // Verify the signatures match
6385
6386         MethodImplCompareSignatures(
6387             pDecl,
6388             pImpl,
6389             IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_LOCAL_METHOD_IMPL);
6390
6391         ///////////////////////////////
6392         // Validate the method impl.
6393
6394         TestMethodImpl(
6395             bmtMethodHandle(pDecl),
6396             bmtMethodHandle(pImpl));
6397     }
6398
6399     // Don't allow overrides for any of the four special runtime implemented delegate methods
6400     if (IsDelegate())
6401     {
6402         LPCUTF8 strMethodName = pDecl->GetMethodSignature().GetName();
6403         if ((strcmp(strMethodName, COR_CTOR_METHOD_NAME) == 0) || 
6404             (strcmp(strMethodName, "Invoke")             == 0) || 
6405             (strcmp(strMethodName, "BeginInvoke")        == 0) || 
6406             (strcmp(strMethodName, "EndInvoke")          == 0))
6407         {
6408             BuildMethodTableThrowException(
6409                 IDS_CLASSLOAD_MI_CANNOT_OVERRIDE, 
6410                 pDecl->GetMethodSignature().GetToken());
6411         }
6412     }
6413
6414     ///////////////////
6415     // Add the mapping
6416
6417     // Call helper to add it. Will throw if decl is already MethodImpl'd
6418     CONSISTENCY_CHECK(pDecl->GetSlotIndex() == static_cast<SLOT_INDEX>(pDecl->GetMethodDesc()->GetSlot()));
6419     AddMethodImplDispatchMapping(
6420         DispatchMapTypeID::ThisClassID(), 
6421         pDecl->GetSlotIndex(), 
6422         pImpl);
6423
6424     // We implement this slot, record it
6425     ASSERT(*pSlotIndex < dwMaxSlotSize);
6426     slots[*pSlotIndex] = pDecl->GetSlotIndex();
6427     replaced[*pSlotIndex].SetValue(pDecl->GetMethodDesc());
6428
6429     // increment the counter
6430     (*pSlotIndex)++;
6431 } // MethodTableBuilder::PlaceLocalDeclarationOnClass
6432
6433 //*******************************************************************************
6434 VOID MethodTableBuilder::PlaceInterfaceDeclarationOnClass(
6435     bmtRTMethod *     pDecl,
6436     bmtMDMethod *     pImpl)
6437 {
6438     CONTRACTL {
6439         STANDARD_VM_CHECK;
6440         PRECONDITION(CheckPointer(pDecl));
6441         PRECONDITION(CheckPointer(pImpl));
6442         PRECONDITION(pDecl->GetMethodDesc()->IsInterface());
6443         PRECONDITION(CheckPointer(bmtVT->pDispatchMapBuilder));
6444     } CONTRACTL_END;
6445
6446     MethodDesc *  pDeclMD = pDecl->GetMethodDesc();
6447     MethodTable * pDeclMT = pDeclMD->GetMethodTable();
6448
6449     // Note that the fact that pDecl is non-NULL means that we found the
6450     // declaration token to be owned by a declared interface for this type.
6451
6452     if (!bmtProp->fNoSanityChecks)
6453     {
6454         ///////////////////////////////
6455         // Verify the signatures match
6456
6457         MethodImplCompareSignatures(
6458             pDecl,
6459             pImpl,
6460             IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_INTERFACE_METHOD_IMPL);
6461
6462         ///////////////////////////////
6463         // Validate the method impl.
6464
6465         TestMethodImpl(
6466             bmtMethodHandle(pDecl),
6467             bmtMethodHandle(pImpl));
6468     }
6469
6470     ///////////////////
6471     // Add the mapping
6472
6473     // Note that we need only one DispatchMapTypeID for this interface (though there might be more if there 
6474     // are duplicates). The first one is easy to get, but we could (in theory) use the last one or a random 
6475     // one.
6476     // Q: Why don't we have to place this method for all duplicate interfaces? Because VSD knows about 
6477     // duplicates and finds the right (latest) implementation for us - see 
6478     // code:MethodTable::MethodDataInterfaceImpl::PopulateNextLevel#ProcessAllDuplicates.
6479     UINT32 cInterfaceDuplicates;
6480     DispatchMapTypeID firstDispatchMapTypeID;
6481     ComputeDispatchMapTypeIDs(
6482         pDeclMT, 
6483         &pDecl->GetMethodSignature().GetSubstitution(), 
6484         &firstDispatchMapTypeID, 
6485         1, 
6486         &cInterfaceDuplicates);
6487     CONSISTENCY_CHECK(cInterfaceDuplicates >= 1);
6488     CONSISTENCY_CHECK(firstDispatchMapTypeID.IsImplementedInterface());
6489
6490     // Call helper to add it. Will throw if decl is already MethodImpl'd
6491     CONSISTENCY_CHECK(pDecl->GetSlotIndex() == static_cast<SLOT_INDEX>(pDecl->GetMethodDesc()->GetSlot()));
6492     AddMethodImplDispatchMapping(
6493         firstDispatchMapTypeID, 
6494         pDecl->GetSlotIndex(), 
6495         pImpl);
6496
6497 #ifdef FEATURE_PREJIT
6498     if (IsCompilationProcess())
6499     {
6500         //
6501         // Mark this interface as overridable. It is used to skip generation of
6502         // CCWs stubs during NGen (see code:MethodNeedsReverseComStub)
6503         //
6504         if (!IsMdFinal(pImpl->GetDeclAttrs()))
6505         {
6506             pDeclMT->GetWriteableDataForWrite()->SetIsOverridingInterface();
6507         }
6508     }
6509 #endif
6510
6511 #ifdef _DEBUG
6512     if (bmtInterface->dbg_fShouldInjectInterfaceDuplicates)
6513     {   // We injected interface duplicates
6514         
6515         // We have to MethodImpl all interface duplicates as all duplicates are 'declared on type' (see 
6516         // code:#InjectInterfaceDuplicates_ApproxInterfaces)
6517         DispatchMapTypeID * rgDispatchMapTypeIDs = (DispatchMapTypeID *)_alloca(sizeof(DispatchMapTypeID) * cInterfaceDuplicates);
6518         ComputeDispatchMapTypeIDs(
6519             pDeclMT, 
6520             &pDecl->GetMethodSignature().GetSubstitution(), 
6521             rgDispatchMapTypeIDs, 
6522             cInterfaceDuplicates, 
6523             &cInterfaceDuplicates);
6524         for (UINT32 nInterfaceDuplicate = 1; nInterfaceDuplicate < cInterfaceDuplicates; nInterfaceDuplicate++)
6525         {
6526             // Add MethodImpl record for each injected interface duplicate
6527             AddMethodImplDispatchMapping(
6528                 rgDispatchMapTypeIDs[nInterfaceDuplicate], 
6529                 pDecl->GetSlotIndex(), 
6530                 pImpl);
6531         }
6532     }
6533 #endif //_DEBUG
6534 } // MethodTableBuilder::PlaceInterfaceDeclarationOnClass
6535
6536 //*******************************************************************************
6537 VOID MethodTableBuilder::PlaceInterfaceDeclarationOnInterface(
6538     bmtMethodHandle hDecl, 
6539     bmtMDMethod   *pImpl, 
6540     DWORD *       slots, 
6541     RelativePointer<MethodDesc *> * replaced,
6542     DWORD *       pSlotIndex,
6543     DWORD         dwMaxSlotSize)
6544 {
6545     CONTRACTL {
6546         STANDARD_VM_CHECK;
6547         PRECONDITION(CheckPointer(pImpl));
6548         PRECONDITION(IsInterface());
6549         PRECONDITION(hDecl.GetMethodDesc()->IsInterface());
6550     } CONTRACTL_END;
6551
6552     MethodDesc *  pDeclMD = hDecl.GetMethodDesc();
6553
6554     if (!bmtProp->fNoSanityChecks)
6555     {
6556         ///////////////////////////////
6557         // Verify the signatures match
6558
6559         MethodImplCompareSignatures(
6560             hDecl,
6561             bmtMethodHandle(pImpl),
6562             IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_INTERFACE_METHOD_IMPL);
6563
6564         ///////////////////////////////
6565         // Validate the method impl.
6566
6567         TestMethodImpl(hDecl, bmtMethodHandle(pImpl));
6568     }
6569
6570     // We implement this slot, record it
6571     ASSERT(*pSlotIndex < dwMaxSlotSize);
6572     slots[*pSlotIndex] = hDecl.GetSlotIndex();
6573     replaced[*pSlotIndex].SetValue(pDeclMD);
6574
6575     // increment the counter
6576     (*pSlotIndex)++;
6577 } // MethodTableBuilder::PlaceInterfaceDeclarationOnInterface
6578
6579 //*******************************************************************************
6580 VOID
6581 MethodTableBuilder::PlaceParentDeclarationOnClass(
6582     bmtRTMethod * pDecl, 
6583     bmtMDMethod * pImpl, 
6584     DWORD *       slots, 
6585     RelativePointer<MethodDesc *> * replaced,
6586     DWORD *       pSlotIndex,
6587     DWORD         dwMaxSlotSize)
6588 {
6589     CONTRACTL {
6590         STANDARD_VM_CHECK;
6591         PRECONDITION(CheckPointer(pDecl));
6592         PRECONDITION(CheckPointer(pImpl));
6593         PRECONDITION(CheckPointer(bmtVT->pDispatchMapBuilder));
6594         PRECONDITION(CheckPointer(GetParentMethodTable()));
6595     } CONTRACTL_END;
6596
6597     MethodDesc * pDeclMD = pDecl->GetMethodDesc();
6598
6599     // Note that the fact that pDecl is non-NULL means that we found the
6600     // declaration token to be owned by a parent type.
6601
6602     if (!bmtProp->fNoSanityChecks)
6603     {
6604         /////////////////////////////////////////
6605         // Verify that the signatures match
6606
6607         MethodImplCompareSignatures(
6608             pDecl,
6609             pImpl,
6610             IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_PARENT_METHOD_IMPL);
6611
6612         ////////////////////////////////
6613         // Verify rules of method impls
6614
6615         TestMethodImpl(
6616             bmtMethodHandle(pDecl),
6617             bmtMethodHandle(pImpl));
6618     }
6619
6620     ///////////////////
6621     // Add the mapping
6622
6623     // Call helper to add it. Will throw if DECL is already MethodImpl'd
6624     AddMethodImplDispatchMapping(
6625         DispatchMapTypeID::ThisClassID(), 
6626         pDeclMD->GetSlot(), 
6627         pImpl);
6628
6629     // We implement this slot, record it
6630     ASSERT(*pSlotIndex < dwMaxSlotSize);
6631     slots[*pSlotIndex] = pDeclMD->GetSlot();
6632     replaced[*pSlotIndex].SetValue(pDeclMD);
6633
6634     // increment the counter
6635     (*pSlotIndex)++;
6636 } // MethodTableBuilder::PlaceParentDeclarationOnClass
6637
6638 //*******************************************************************************
6639 // This will validate that all interface methods that were matched during
6640 // layout also validate against type constraints.
6641
6642 VOID MethodTableBuilder::ValidateInterfaceMethodConstraints()
6643 {
6644     STANDARD_VM_CONTRACT;
6645
6646     DispatchMapBuilder::Iterator it(bmtVT->pDispatchMapBuilder);
6647     for (; it.IsValid(); it.Next())
6648     {
6649         if (it.GetTypeID() != DispatchMapTypeID::ThisClassID())
6650         {
6651             bmtRTType * pItf = bmtInterface->pInterfaceMap[it.GetTypeID().GetInterfaceNum()].GetInterfaceType();
6652
6653             // Grab the method token
6654             MethodTable * pMTItf = pItf->GetMethodTable();
6655             CONSISTENCY_CHECK(CheckPointer(pMTItf->GetMethodDescForSlot(it.GetSlotNumber())));
6656             mdMethodDef mdTok = pItf->GetMethodTable()->GetMethodDescForSlot(it.GetSlotNumber())->GetMemberDef();
6657
6658             // Default to the current module. The code immediately below determines if this
6659             // assumption is incorrect.
6660             Module *          pTargetModule          = GetModule();
6661
6662             // Get the module of the target method. Get it through the chunk to
6663             // avoid triggering the assert that MethodTable is non-NULL. It may
6664             // be null since it may belong to the type we're building right now.
6665             MethodDesc *      pTargetMD              = it.GetTargetMD();
6666
6667             // If pTargetMT is null, this indicates that the target MethodDesc belongs
6668             // to the current type. Otherwise, the MethodDesc MUST be owned by a parent
6669             // of the type we're building.
6670             BOOL              fTargetIsOwnedByParent = !pTargetMD->GetMethodTablePtr()->IsNull();        
6671             
6672             // If the method is owned by a parent, we need to use the parent's module,
6673             // and we must construct the substitution chain all the way up to the parent.
6674             const Substitution *pSubstTgt = NULL;
6675             if (fTargetIsOwnedByParent)
6676             {
6677                 CONSISTENCY_CHECK(CheckPointer(GetParentType()));
6678                 bmtRTType *pTargetType = bmtRTType::FindType(GetParentType(), pTargetMD->GetMethodTable());
6679                 pSubstTgt = &pTargetType->GetSubstitution();
6680                 pTargetModule = pTargetType->GetModule();
6681             }
6682
6683             // Now compare the method constraints.
6684             if (!MetaSig::CompareMethodConstraints(pSubstTgt,
6685                                                    pTargetModule,
6686                                                    pTargetMD->GetMemberDef(),
6687                                                    &pItf->GetSubstitution(),
6688                                                    pMTItf->GetModule(),
6689                                                    mdTok))
6690             {
6691                 LOG((LF_CLASSLOADER, LL_INFO1000,
6692                      "BADCONSTRAINTS on interface method implementation: %x\n", pTargetMD));
6693                 // This exception will be due to an implicit implementation, since explicit errors
6694                 // will be detected in MethodImplCompareSignatures (for now, anyway).
6695                 CONSISTENCY_CHECK(!it.IsMethodImpl());
6696                 DWORD idsError = it.IsMethodImpl() ?
6697                                  IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_INTERFACE_METHOD_IMPL :
6698                                  IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_IMPLICIT_IMPLEMENTATION;
6699                 if (fTargetIsOwnedByParent)
6700                 {
6701                     DefineFullyQualifiedNameForClass();
6702                     LPCUTF8 szClassName = GetFullyQualifiedNameForClassNestedAware(pTargetMD->GetMethodTable());
6703                     LPCUTF8 szMethodName = pTargetMD->GetName();
6704
6705                     CQuickBytes qb;
6706                     // allocate enough room for "<class>.<method>\0"
6707                     size_t cchFullName = strlen(szClassName) + 1 + strlen(szMethodName) + 1;
6708                     LPUTF8 szFullName = (LPUTF8) qb.AllocThrows(cchFullName);
6709                     strcpy_s(szFullName, cchFullName, szClassName);
6710                     strcat_s(szFullName, cchFullName, ".");
6711                     strcat_s(szFullName, cchFullName, szMethodName);
6712
6713                     BuildMethodTableThrowException(idsError, szFullName);
6714                 }
6715                 else
6716                 {
6717                     BuildMethodTableThrowException(idsError, pTargetMD->GetMemberDef());
6718                 }
6719             }
6720         }
6721     }
6722 } // MethodTableBuilder::ValidateInterfaceMethodConstraints
6723
6724 //*******************************************************************************
6725 // Used to allocate and initialize MethodDescs (both the boxed and unboxed entrypoints)
6726 VOID MethodTableBuilder::AllocAndInitMethodDescs()
6727 {
6728     STANDARD_VM_CONTRACT;
6729
6730     //
6731     // Go over all MethodDescs and create smallest number of MethodDescChunks possible.
6732     //
6733     // Iterate over all methods and start a new chunk only if:
6734     //  - Token range (upper 24 bits of the method token) has changed.
6735     //  - The maximum size of the chunk has been reached.
6736     //
6737
6738     int currentTokenRange = -1; // current token range
6739     SIZE_T sizeOfMethodDescs = 0; // current running size of methodDesc chunk
6740     int startIndex = 0; // start of the current chunk (index into bmtMethod array)
6741
6742     DeclaredMethodIterator it(*this);
6743     while (it.Next())
6744     {
6745         int tokenRange = GetTokenRange(it.Token());
6746
6747         // This code assumes that iterator returns tokens in ascending order. If this assumption does not hold, 
6748         // the code will still work with small performance penalty (method desc chunk layout will be less efficient).
6749         _ASSERTE(tokenRange >= currentTokenRange);
6750
6751         SIZE_T size = MethodDesc::GetBaseSize(GetMethodClassification(it->GetMethodType()));
6752
6753         // Add size of optional slots
6754
6755         if (it->GetMethodImplType() == METHOD_IMPL)
6756             size += sizeof(MethodImpl);
6757
6758         if (it->GetSlotIndex() >= bmtVT->cVtableSlots)
6759             size += sizeof(MethodDesc::NonVtableSlot); // slot
6760
6761         if (NeedsNativeCodeSlot(*it))
6762             size += sizeof(MethodDesc::NativeCodeSlot);
6763
6764         // See comment in AllocAndInitMethodDescChunk
6765         if (NeedsTightlyBoundUnboxingStub(*it))
6766         {
6767             size *= 2;
6768
6769             if (bmtGenerics->GetNumGenericArgs() == 0) {
6770                 size += sizeof(MethodDesc::NonVtableSlot);
6771             }
6772             else {
6773                 bmtVT->cVtableSlots++;
6774             }
6775         }
6776
6777 #ifndef CROSSGEN_COMPILE
6778         if (tokenRange != currentTokenRange ||
6779             sizeOfMethodDescs + size > MethodDescChunk::MaxSizeOfMethodDescs)
6780 #endif // CROSSGEN_COMPILE
6781         {
6782             if (sizeOfMethodDescs != 0)
6783             {
6784                 AllocAndInitMethodDescChunk(startIndex, it.CurrentIndex() - startIndex, sizeOfMethodDescs);
6785                 startIndex = it.CurrentIndex();
6786             }
6787
6788             currentTokenRange = tokenRange;
6789             sizeOfMethodDescs = 0;
6790         }
6791
6792         sizeOfMethodDescs += size;
6793     }
6794
6795     if (sizeOfMethodDescs != 0)
6796     {
6797         AllocAndInitMethodDescChunk(startIndex, NumDeclaredMethods() - startIndex, sizeOfMethodDescs);
6798     }
6799 }
6800
6801 //*******************************************************************************
6802 // Allocates and initializes one method desc chunk.
6803 //
6804 // Arguments:
6805 //    startIndex - index of first method in bmtMethod array.
6806 //    count - number of methods in this chunk (contiguous region from startIndex)
6807 //    sizeOfMethodDescs - total expected size of MethodDescs in this chunk
6808 //
6809 // Used by AllocAndInitMethodDescs.
6810 //
6811 VOID MethodTableBuilder::AllocAndInitMethodDescChunk(COUNT_T startIndex, COUNT_T count, SIZE_T sizeOfMethodDescs)
6812 {
6813     CONTRACTL {
6814         STANDARD_VM_CHECK;
6815         PRECONDITION(sizeOfMethodDescs <= MethodDescChunk::MaxSizeOfMethodDescs);
6816     } CONTRACTL_END;
6817
6818     void * pMem = GetMemTracker()->Track(
6819         GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(TADDR) + sizeof(MethodDescChunk) + sizeOfMethodDescs)));
6820
6821     // Skip pointer to temporary entrypoints
6822     MethodDescChunk * pChunk = (MethodDescChunk *)((BYTE*)pMem + sizeof(TADDR));
6823
6824     COUNT_T methodDescCount = 0;
6825
6826     SIZE_T offset = sizeof(MethodDescChunk);
6827
6828 #ifdef _PREFAST_ 
6829 #pragma warning(push)
6830 #pragma warning(disable:22019) // Suppress PREFast warning about integer underflow
6831 #endif // _PREFAST_
6832     for (COUNT_T i = 0; i < count; i++)
6833 #ifdef _PREFAST_ 
6834 #pragma warning(pop)
6835 #endif // _PREFAST_
6836
6837     {
6838         bmtMDMethod * pMDMethod = (*bmtMethod)[static_cast<SLOT_INDEX>(startIndex + i)];
6839
6840         MethodDesc * pMD = (MethodDesc *)((BYTE *)pChunk + offset); 
6841
6842         pMD->SetChunkIndex(pChunk);
6843
6844         InitNewMethodDesc(pMDMethod, pMD);
6845
6846 #ifdef _PREFAST_ 
6847 #pragma warning(push)
6848 #pragma warning(disable:22018) // Suppress PREFast warning about integer underflow
6849 #endif // _PREFAST_
6850         offset += pMD->SizeOf();
6851 #ifdef _PREFAST_ 
6852 #pragma warning(pop)
6853 #endif // _PREFAST_
6854
6855         methodDescCount++;
6856
6857         // If we're a value class, we want to create duplicate slots
6858         // and MethodDescs for all methods in the vtable
6859         // section (i.e. not non-virtual instance methods or statics).
6860         // In the name of uniformity it would be much nicer
6861         // if we created _all_ value class BoxedEntryPointStubs at this point.
6862         // However, non-virtual instance methods only require unboxing
6863         // stubs in the rare case that we create a delegate to such a
6864         // method, and thus it would be inefficient to create them on
6865         // loading: after all typical structs will have many non-virtual
6866         // instance methods.
6867         //
6868         // Unboxing stubs for non-virtual instance methods are created
6869         // in code:MethodDesc::FindOrCreateAssociatedMethodDesc.
6870
6871         if (NeedsTightlyBoundUnboxingStub(pMDMethod))
6872         {
6873             MethodDesc * pUnboxedMD = (MethodDesc *)((BYTE *)pChunk + offset); 
6874
6875             //////////////////////////////////
6876             // Initialize the new MethodDesc
6877
6878             // <NICE> memcpy operations on data structures like MethodDescs are extremely fragile
6879             // and should not be used.  We should go to the effort of having proper constructors
6880             // in the MethodDesc class. </NICE>
6881
6882             memcpy(pUnboxedMD, pMD, pMD->SizeOf());
6883
6884             // Reset the chunk index
6885             pUnboxedMD->SetChunkIndex(pChunk);
6886
6887             if (bmtGenerics->GetNumGenericArgs() == 0) {
6888                 pUnboxedMD->SetHasNonVtableSlot();
6889             }
6890
6891             //////////////////////////////////////////////////////////
6892             // Modify the original MethodDesc to be an unboxing stub
6893
6894             pMD->SetIsUnboxingStub();
6895
6896             ////////////////////////////////////////////////////////////////////
6897             // Add the new MethodDesc to the non-virtual portion of the vtable
6898
6899             if (!bmtVT->AddUnboxedMethod(pMDMethod))
6900                 BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
6901
6902             pUnboxedMD->SetSlot(pMDMethod->GetUnboxedSlotIndex());
6903             pMDMethod->SetUnboxedMethodDesc(pUnboxedMD);
6904
6905             offset += pUnboxedMD->SizeOf();
6906             methodDescCount++;
6907         }
6908     }
6909     _ASSERTE(offset == sizeof(MethodDescChunk) + sizeOfMethodDescs);
6910
6911     pChunk->SetSizeAndCount((ULONG)sizeOfMethodDescs, methodDescCount);
6912
6913     GetHalfBakedClass()->AddChunk(pChunk);
6914 }
6915
6916 //*******************************************************************************
6917 BOOL
6918 MethodTableBuilder::NeedsTightlyBoundUnboxingStub(bmtMDMethod * pMDMethod)
6919 {
6920     STANDARD_VM_CONTRACT;
6921
6922     return IsValueClass() &&
6923            !IsMdStatic(pMDMethod->GetDeclAttrs()) &&
6924            IsMdVirtual(pMDMethod->GetDeclAttrs()) &&
6925            (pMDMethod->GetMethodType() != METHOD_TYPE_INSTANTIATED) &&
6926            !IsMdRTSpecialName(pMDMethod->GetDeclAttrs());
6927 }
6928
6929 //*******************************************************************************
6930 BOOL
6931 MethodTableBuilder::NeedsNativeCodeSlot(bmtMDMethod * pMDMethod)
6932 {
6933     LIMITED_METHOD_CONTRACT;
6934
6935
6936 #ifdef FEATURE_TIERED_COMPILATION
6937     // Keep in-sync with MethodDesc::DetermineAndSetIsEligibleForTieredCompilation()
6938     if (g_pConfig->TieredCompilation() &&
6939         (pMDMethod->GetMethodType() == METHOD_TYPE_NORMAL || pMDMethod->GetMethodType() == METHOD_TYPE_INSTANTIATED))
6940     {
6941         return TRUE;
6942     }
6943 #endif
6944
6945 #if defined(FEATURE_JIT_PITCHING)
6946     if ((CLRConfig::GetConfigValue(CLRConfig::INTERNAL_JitPitchEnabled) != 0) &&
6947         (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_JitPitchMemThreshold) != 0))
6948         return TRUE;
6949 #endif
6950
6951     return GetModule()->IsEditAndContinueEnabled();
6952 }
6953
6954 //*******************************************************************************
6955 VOID
6956 MethodTableBuilder::AllocAndInitDictionary()
6957 {
6958     STANDARD_VM_CONTRACT;
6959
6960     // Allocate dictionary layout used by all compatible instantiations
6961
6962     if (bmtGenerics->fSharedByGenericInstantiations && !bmtGenerics->fContainsGenericVariables)
6963     {
6964         // We use the number of methods as a heuristic for the number of slots in the dictionary
6965         // attached to shared class method tables.
6966         // If there are no declared methods then we have no slots, and we will never do any token lookups
6967         //
6968         // Heuristics
6969         //  - Classes with a small number of methods (2-3) tend to be more likely to use new slots,
6970         //    i.e. further methods tend to reuse slots from previous methods.
6971         //      = treat all classes with only 2-3 methods as if they have an extra method.
6972         //  - Classes with more generic parameters tend to use more slots.
6973         //      = multiply by 1.5 for 2 params or more
6974
6975         DWORD numMethodsAdjusted =
6976             (bmtMethod->dwNumDeclaredNonAbstractMethods == 0)
6977             ? 0
6978             : (bmtMethod->dwNumDeclaredNonAbstractMethods < 3)
6979             ? 3
6980             : bmtMethod->dwNumDeclaredNonAbstractMethods;
6981
6982         _ASSERTE(bmtGenerics->GetNumGenericArgs() != 0);
6983         DWORD nTypeFactorBy2 = (bmtGenerics->GetNumGenericArgs() == 1)
6984                                ? 2
6985                                : 3;
6986
6987         DWORD estNumTypeSlots = (numMethodsAdjusted * nTypeFactorBy2 + 2) / 3;
6988         // estNumTypeSlots should fit in a WORD as long as we maintain the current
6989         // limit on the number of methods in a type (approx 2^16).
6990         _ASSERTE(FitsIn<WORD>(estNumTypeSlots));
6991         WORD numTypeSlots = static_cast<WORD>(estNumTypeSlots);
6992
6993         if (numTypeSlots > 0)
6994         {
6995             // Dictionary layout is an optional field on EEClass, so ensure the optional field descriptor has
6996             // been allocated.
6997             EnsureOptionalFieldsAreAllocated(GetHalfBakedClass(), m_pAllocMemTracker, GetLoaderAllocator()->GetLowFrequencyHeap());
6998             GetHalfBakedClass()->SetDictionaryLayout(DictionaryLayout::Allocate(numTypeSlots, bmtAllocator, m_pAllocMemTracker));
6999         }
7000     }
7001
7002 }
7003
7004 //*******************************************************************************
7005 //
7006 // Used by BuildMethodTable
7007 //
7008 // Compute the set of interfaces which are equivalent. Duplicates in the interface map
7009 // will be placed into different equivalence sets unless they participate in type equivalence.
7010 // This is a bit odd, but it turns out we only need to know about equivalence classes if
7011 // there is type equivalence involved in the interface, and not detecting, or detecting equivalence
7012 // in other cases does not result in differing behavior.
7013 // 
7014 // By restricting the reasons for having equivalence matches, we reduce the algorithm from one which
7015 // is O(n*n) best case to an algorithm which will typically execute something more like O(m*n) best case time 
7016 // where m is the number of generic interface (although still n*n in worst case). The assumption is that equivalent
7017 // and generic interfaces are relatively rare.
7018 VOID
7019 MethodTableBuilder::ComputeInterfaceMapEquivalenceSet()
7020 {
7021     STANDARD_VM_CONTRACT;
7022
7023     UINT32 nextEquivalenceSet = 1;
7024
7025     for (DWORD dwCurInterface = 0;
7026          dwCurInterface < bmtInterface->dwInterfaceMapSize;
7027          dwCurInterface++)
7028     {
7029         // Keep track of the current interface we are trying to calculate the equivalence set of
7030         bmtInterfaceEntry *     pCurItfEntry = &bmtInterface->pInterfaceMap[dwCurInterface];
7031         bmtRTType *             pCurItf      = pCurItfEntry->GetInterfaceType();
7032         MethodTable *           pCurItfMT    = pCurItf->GetMethodTable();
7033         const Substitution *    pCurItfSubst = &pCurItf->GetSubstitution();
7034
7035         UINT32 currentEquivalenceSet = 0;
7036
7037         // Only interfaces with type equivalence, or that are generic need to be compared for equivalence
7038         if (pCurItfMT->HasTypeEquivalence() || pCurItfMT->HasInstantiation())
7039         {
7040             for (DWORD dwCurInterfaceCompare = 0;
7041                  dwCurInterfaceCompare < dwCurInterface;
7042                  dwCurInterfaceCompare++)
7043             {
7044                 // Keep track of the current interface we are trying to calculate the equivalence set of
7045                 bmtInterfaceEntry *     pCompareItfEntry = &bmtInterface->pInterfaceMap[dwCurInterfaceCompare];
7046                 bmtRTType *             pCompareItf      = pCompareItfEntry->GetInterfaceType();
7047                 MethodTable *           pCompareItfMT    = pCompareItf->GetMethodTable();
7048                 const Substitution *    pCompareItfSubst = &pCompareItf->GetSubstitution();
7049
7050                 // Only interfaces with type equivalence, or that are generic need to be compared for equivalence
7051                 if (pCompareItfMT->HasTypeEquivalence() || pCompareItfMT->HasInstantiation())
7052                 {
7053                     if (MetaSig::CompareTypeDefsUnderSubstitutions(pCurItfMT,
7054                                                                    pCompareItfMT,
7055                                                                    pCurItfSubst,
7056                                                                    pCompareItfSubst,
7057                                                                    NULL))
7058                     {
7059                         currentEquivalenceSet = pCompareItfEntry->GetInterfaceEquivalenceSet();
7060                         // Use the equivalence set of the interface map entry we just found
7061                         pCurItfEntry->SetInterfaceEquivalenceSet(currentEquivalenceSet, true);
7062                         // Update the interface map entry we just found to indicate that it is part of an equivalence
7063                         // set with multiple entries.
7064                         pCompareItfEntry->SetInterfaceEquivalenceSet(currentEquivalenceSet, true);
7065                         break;
7066                     }
7067                 }
7068             }
7069         }
7070
7071         // If we did not find an equivalent interface above, use the next available equivalence set indicator
7072         if (currentEquivalenceSet == 0)
7073         {
7074             pCurItfEntry->SetInterfaceEquivalenceSet(nextEquivalenceSet, false);
7075             nextEquivalenceSet++;
7076         }
7077     }
7078 }
7079
7080 //*******************************************************************************
7081 //
7082 // Used by PlaceInterfaceMethods
7083 //
7084 // Given an interface in our interface map, and a particular method on that interface, place
7085 // a method from the parent types implementation of an equivalent interface into that method 
7086 // slot. Used by PlaceInterfaceMethods to make equivalent interface implementations have the 
7087 // same behavior as if the parent interface was implemented on this type instead of an equivalent interface.
7088 //
7089 // This logic is used in situations such as below. I and I' are equivalent interfaces
7090 //
7091 //#
7092 // class Base : I
7093 // {void I.Method() { } }
7094 // interface IOther : I' {}
7095 // class Derived : IOther
7096 // { virtual void Method() {}}
7097 //
7098 // We should Map I'.Method to Base.Method, not Derived.Method
7099 // 
7100 // Another example
7101 // class Base : I
7102 // { virtual void Method() }
7103 // interface IOther : I' {}
7104 // class Derived : IOther
7105 // { virtual void Method() {}}
7106 //
7107 // We should map I'.Method to Base.Method, not Derived.Method
7108 //
7109 // class Base : I
7110 // {void I.Method() { } }
7111 // class Derived : I'
7112 // {}
7113 //
7114 // We should Map I'.Method to Base.Method, and not throw TypeLoadException
7115 //
7116 #ifdef FEATURE_COMINTEROP
7117 VOID 
7118 MethodTableBuilder::PlaceMethodFromParentEquivalentInterfaceIntoInterfaceSlot(
7119     bmtInterfaceEntry::InterfaceSlotIterator & itfSlotIt, 
7120     bmtInterfaceEntry *                        pCurItfEntry, 
7121     DispatchMapTypeID **                       prgInterfaceDispatchMapTypeIDs, 
7122     DWORD                                      dwCurInterface)
7123 {
7124     STANDARD_VM_CONTRACT;
7125
7126     bmtRTMethod * pCurItfMethod = itfSlotIt->Decl().AsRTMethod();
7127
7128     if (itfSlotIt->Impl() != INVALID_SLOT_INDEX)
7129     {
7130         return;
7131     }
7132
7133     // For every equivalent interface entry that was actually implemented by parent, then look at equivalent method slot on that entry
7134     // and if it matches and has a slot implementation, then record and continue
7135     for (DWORD dwEquivalentInterface = 0;
7136          (dwEquivalentInterface < bmtInterface->dwInterfaceMapSize) && (itfSlotIt->Impl() == INVALID_SLOT_INDEX);
7137          dwEquivalentInterface++)
7138     {
7139         bmtInterfaceEntry *  pEquivItfEntry = &bmtInterface->pInterfaceMap[dwEquivalentInterface];
7140         bmtRTType *          pEquivItf      = pEquivItfEntry->GetInterfaceType();
7141         MethodTable *        pEquivItfMT    = pEquivItf->GetMethodTable();
7142         const Substitution * pEquivItfSubst = &pEquivItf->GetSubstitution();
7143         if (pEquivItfEntry->GetInterfaceEquivalenceSet() != pCurItfEntry->GetInterfaceEquivalenceSet())
7144         {
7145             // Not equivalent
7146             continue;
7147         }
7148         if (!pEquivItfEntry->IsImplementedByParent())
7149         {
7150             // Not implemented by parent
7151             continue;
7152         }
7153         
7154         WORD slot = static_cast<WORD>(itfSlotIt.CurrentIndex());
7155         BOOL fFound = FALSE;
7156
7157         // Determine which slot on the equivalent interface would map to the slot we are attempting to fill
7158         // in with an implementation.
7159         WORD otherMTSlot = GetEquivalentMethodSlot(pCurItfEntry->GetInterfaceType()->GetMethodTable(), 
7160                                                    pEquivItfEntry->GetInterfaceType()->GetMethodTable(), 
7161                                                    slot, 
7162                                                    &fFound);
7163
7164         if (fFound)
7165         {
7166             UINT32 cInterfaceDuplicates;
7167             if (*prgInterfaceDispatchMapTypeIDs == NULL)
7168             {
7169                 *prgInterfaceDispatchMapTypeIDs = 
7170                     new (GetStackingAllocator()) DispatchMapTypeID[bmtInterface->dwInterfaceMapSize];
7171             }
7172
7173             // Compute all TypeIDs for this interface (all duplicates in the interface map)
7174             ComputeDispatchMapTypeIDs(
7175                 pEquivItfMT, 
7176                 pEquivItfSubst, 
7177                 *prgInterfaceDispatchMapTypeIDs, 
7178                 bmtInterface->dwInterfaceMapSize, 
7179                 &cInterfaceDuplicates);
7180             // There cannot be more duplicates than number of interfaces
7181             _ASSERTE(cInterfaceDuplicates <= bmtInterface->dwInterfaceMapSize);
7182             _ASSERTE(cInterfaceDuplicates > 0);
7183             
7184             // NOTE: This override does not cache the resulting MethodData object
7185             MethodTable::MethodDataWrapper hParentData;
7186             hParentData = MethodTable::GetMethodData(
7187                     *prgInterfaceDispatchMapTypeIDs, 
7188                     cInterfaceDuplicates, 
7189                     pEquivItfMT, 
7190                     GetParentMethodTable());
7191
7192             SLOT_INDEX slotIndex = static_cast<SLOT_INDEX>
7193                 (hParentData->GetImplSlotNumber(static_cast<UINT32>(otherMTSlot)));
7194
7195             // Interface is implemented on parent abstract type and this particular slot was not implemented
7196             if (slotIndex == INVALID_SLOT_INDEX)
7197             {
7198                 continue;
7199             }
7200
7201             bmtMethodSlot & parentSlotImplementation = (*bmtParent->pSlotTable)[slotIndex];
7202             bmtMethodHandle & parentImplementation = parentSlotImplementation.Impl();
7203
7204             // Check to verify that the equivalent slot on the equivalent interface actually matches the method
7205             // on the current interface. If not, then the slot is not a match, and we should search other interfaces
7206             // for an implementation of the method.
7207             if (!MethodSignature::SignaturesEquivalent(pCurItfMethod->GetMethodSignature(), parentImplementation.GetMethodSignature()))
7208             {
7209                 continue;
7210             }
7211
7212             itfSlotIt->Impl() = slotIndex;
7213
7214             MethodDesc * pMD = hParentData->GetImplMethodDesc(static_cast<UINT32>(otherMTSlot));
7215
7216             DispatchMapTypeID dispatchMapTypeID =
7217                 DispatchMapTypeID::InterfaceClassID(dwCurInterface);
7218             bmtVT->pDispatchMapBuilder->InsertMDMapping(
7219                 dispatchMapTypeID, 
7220                 static_cast<UINT32>(itfSlotIt.CurrentIndex()), 
7221                 pMD, 
7222                 FALSE);
7223         }
7224     }
7225 } // MethodTableBuilder::PlaceMethodFromParentEquivalentInterfaceIntoInterfaceSlot
7226 #endif // FEATURE_COMINTEROP
7227
7228 //*******************************************************************************
7229 //
7230 // Used by BuildMethodTable
7231 //
7232 //
7233 // If we are a class, then there may be some unplaced vtable methods (which are by definition
7234 // interface methods, otherwise they'd already have been placed).  Place as many unplaced methods
7235 // as possible, in the order preferred by interfaces.  However, do not allow any duplicates - once
7236 // a method has been placed, it cannot be placed again - if we are unable to neatly place an interface,
7237 // create duplicate slots for it starting at dwCurrentDuplicateVtableSlot.  Fill out the interface
7238 // map for all interfaces as they are placed.
7239 //
7240 // If we are an interface, then all methods are already placed.  Fill out the interface map for
7241 // interfaces as they are placed.
7242 //
7243 // BEHAVIOUR (based on Partition II: 11.2, not including MethodImpls)
7244 //   C is current class, P is a parent class, I is the interface being implemented
7245 //
7246 //   FOREACH interface I implemented by this class C
7247 //     FOREACH method I::M
7248 //       IF I is EXPLICITLY implemented by C
7249 //         IF some method C::M matches I::M
7250 //           USE C::M as implementation for I::M
7251 //         ELIF we inherit a method P::M that matches I::M
7252 //           USE P::M as implementation for I::M
7253 //         ENDIF
7254 //       ELSE
7255 //         IF I::M lacks implementation
7256 //           IF some method C::M matches I::M
7257 //             USE C::M as implementation for I::M
7258 //           ELIF we inherit a method P::M that matches I::M
7259 //             USE P::M as implementation for I::M
7260 //           ELIF I::M was implemented by the parent type with method Parent::M
7261 //             USE Parent::M for the implementation of I::M // VSD does this by default if we really 
7262 //                                                           // implemented I on the parent type, but 
7263 //                                                           // equivalent interfaces need to make this 
7264 //                                                           // explicit
7265 //           ENDIF
7266 //         ENDIF
7267 //       ENDIF
7268 //     ENDFOR
7269 //   ENDFOR
7270 //
7271
7272 VOID
7273 MethodTableBuilder::PlaceInterfaceMethods()
7274 {
7275     STANDARD_VM_CONTRACT;
7276
7277     BOOL fParentInterface;
7278     DispatchMapTypeID * rgInterfaceDispatchMapTypeIDs = NULL;
7279
7280     for (DWORD dwCurInterface = 0;
7281          dwCurInterface < bmtInterface->dwInterfaceMapSize;
7282          dwCurInterface++)
7283     {
7284         // Default to being implemented by the current class
7285         fParentInterface = FALSE;
7286
7287         // Keep track of the current interface we are trying to place
7288         bmtInterfaceEntry *     pCurItfEntry = &bmtInterface->pInterfaceMap[dwCurInterface];
7289         bmtRTType *             pCurItf      = pCurItfEntry->GetInterfaceType();
7290         MethodTable *           pCurItfMT    = pCurItf->GetMethodTable();
7291         const Substitution *    pCurItfSubst = &pCurItf->GetSubstitution();
7292
7293         //
7294         // There are three reasons why an interface could be in the implementation list
7295         // 1. Inherited from parent
7296         // 2. Explicitly declared in the implements list
7297         // 3. Implicitly declared through the implements list of an explicitly declared interface
7298         //
7299         // The reason these cases need to be distinguished is that an inherited interface that is
7300         // also explicitly redeclared in the implements list must be fully reimplemented using the
7301         // virtual methods of this type (thereby using matching methods in this type that may have
7302         // a different slot than an inherited method, but hidden it by name & sig); however all
7303         // implicitly redeclared interfaces should not be fully reimplemented if they were also
7304         // inherited from the parent.
7305         //
7306         // Example:
7307         //   interface I1 : I2
7308         //   class A : I1
7309         //   class B : A, I1
7310         //
7311         // In this example I1 must be fully reimplemented on B, but B can inherit the implementation
7312         // of I2.
7313         //
7314
7315         if (pCurItfEntry->IsImplementedByParent())
7316         {
7317             if (!pCurItfEntry->IsDeclaredOnType())
7318             {
7319                 fParentInterface = TRUE;
7320             }
7321         }
7322
7323         bool fEquivalentInterfaceImplementedByParent = pCurItfEntry->IsImplementedByParent();
7324         bool fEquivalentInterfaceDeclaredOnType = pCurItfEntry->IsDeclaredOnType();
7325
7326         if (pCurItfEntry->InEquivalenceSetWithMultipleEntries())
7327         {
7328             for (DWORD dwEquivalentInterface = 0;
7329                  dwEquivalentInterface < bmtInterface->dwInterfaceMapSize;
7330                  dwEquivalentInterface++)
7331             {
7332                 bmtInterfaceEntry *     pEquivItfEntry = &bmtInterface->pInterfaceMap[dwEquivalentInterface];
7333                 if (pEquivItfEntry->GetInterfaceEquivalenceSet() != pCurItfEntry->GetInterfaceEquivalenceSet())
7334                 {
7335                     // Not equivalent
7336                     continue;
7337                 }
7338                 if (pEquivItfEntry->IsImplementedByParent())
7339                 {
7340                     fEquivalentInterfaceImplementedByParent = true;
7341                 }
7342                 if (pEquivItfEntry->IsDeclaredOnType())
7343                 {
7344                     fEquivalentInterfaceDeclaredOnType = true;
7345                 }
7346
7347                 if (fEquivalentInterfaceDeclaredOnType && fEquivalentInterfaceImplementedByParent)
7348                     break;
7349             }
7350         }
7351
7352         bool fParentInterfaceEquivalent = fEquivalentInterfaceImplementedByParent && !fEquivalentInterfaceDeclaredOnType;
7353
7354         CONSISTENCY_CHECK(!fParentInterfaceEquivalent || HasParent());
7355
7356         if (fParentInterfaceEquivalent)
7357         {
7358             // In the case the fParentInterface is TRUE, virtual overrides are enough and the interface
7359             // does not have to be explicitly (re)implemented. The only exception is if the parent is
7360             // abstract, in which case an inherited interface may not be fully implemented yet.
7361             // This is an optimization that allows us to skip the more expensive slot filling in below.
7362             // Note that the check here is for fParentInterface and not for fParentInterfaceEquivalent.
7363             // This is necessary as if the interface is not actually implemented on the parent type we will
7364             // need to fill in the slot table below.
7365             if (fParentInterface && !GetParentMethodTable()->IsAbstract())
7366             {
7367                 continue;
7368             }
7369
7370             {
7371                 // We will reach here in two cases.
7372                 // 1 .The parent is abstract and the interface has been declared on the parent,
7373                 // and possibly partially implemented, so we need to populate the
7374                 // bmtInterfaceSlotImpl table for this interface with the implementation slot
7375                 // information.
7376                 // 2 .The the interface has not been declared on the parent,
7377                 // but an equivalent interface has been. So we need to populate the
7378                 // bmtInterfaceSlotImpl table for this interface with the implementation slot
7379                 // information from one of the parent equivalent interfaces. We may or may not
7380                 // find implementations for all of the methods on the interface on the parent type.
7381                 // The parent type may or may not be abstract.
7382
7383                 MethodTable::MethodDataWrapper hParentData;
7384                 CONSISTENCY_CHECK(CheckPointer(GetParentMethodTable()));
7385                 
7386                 if (rgInterfaceDispatchMapTypeIDs == NULL)
7387                 {
7388                     rgInterfaceDispatchMapTypeIDs = 
7389                         new (GetStackingAllocator()) DispatchMapTypeID[bmtInterface->dwInterfaceMapSize];
7390                 }
7391                 
7392                 if (pCurItfEntry->IsImplementedByParent())
7393                 {
7394                     UINT32 cInterfaceDuplicates;
7395                     // Compute all TypeIDs for this interface (all duplicates in the interface map)
7396                     ComputeDispatchMapTypeIDs(
7397                         pCurItfMT, 
7398                         pCurItfSubst, 
7399                         rgInterfaceDispatchMapTypeIDs, 
7400                         bmtInterface->dwInterfaceMapSize, 
7401                         &cInterfaceDuplicates);
7402                     // There cannot be more duplicates than number of interfaces
7403                     _ASSERTE(cInterfaceDuplicates <= bmtInterface->dwInterfaceMapSize);
7404                     _ASSERTE(cInterfaceDuplicates > 0);
7405                     
7406                     //#InterfaceMap_UseParentInterfaceImplementations
7407                     // We rely on the fact that interface map of parent type is subset of this type (incl. 
7408                     // duplicates), see code:#InterfaceMap_SupersetOfParent
7409                     // NOTE: This override does not cache the resulting MethodData object
7410                     hParentData = MethodTable::GetMethodData(
7411                             rgInterfaceDispatchMapTypeIDs, 
7412                             cInterfaceDuplicates, 
7413                             pCurItfMT, 
7414                             GetParentMethodTable());
7415
7416                     bmtInterfaceEntry::InterfaceSlotIterator itfSlotIt =
7417                         pCurItfEntry->IterateInterfaceSlots(GetStackingAllocator());
7418                     for (; !itfSlotIt.AtEnd(); itfSlotIt.Next())
7419                     {
7420                         itfSlotIt->Impl() = static_cast<SLOT_INDEX>
7421                             (hParentData->GetImplSlotNumber(static_cast<UINT32>(itfSlotIt.CurrentIndex())));
7422                     }
7423                 }
7424 #ifdef FEATURE_COMINTEROP
7425                 else
7426                 {
7427                     // Iterate through the methods on the interface, and if they have a slot which was filled in
7428                     // on an equivalent interface inherited from the parent fill in the appropriate slot.
7429                     // This code path is only used when there is an implicit implementation of an interface
7430                     // that was not implemented on a parent type, but there was an equivalent interface implemented
7431                     // on a parent type.
7432                     bmtInterfaceEntry::InterfaceSlotIterator itfSlotIt =
7433                         pCurItfEntry->IterateInterfaceSlots(GetStackingAllocator());
7434                     for (; !itfSlotIt.AtEnd(); itfSlotIt.Next())
7435                     {
7436                         PlaceMethodFromParentEquivalentInterfaceIntoInterfaceSlot(itfSlotIt, pCurItfEntry, &rgInterfaceDispatchMapTypeIDs, dwCurInterface);
7437                     }
7438                 }
7439 #endif // FEATURE_COMINTEROP
7440             }
7441         }
7442
7443 #ifdef FEATURE_COMINTEROP
7444         // WinRT types always use methodimpls to line up methods with interface implementations, so we do not want to allow implicit
7445         // interface implementations to kick in.   This can especially cause problems with redirected interfaces, where the underlying
7446         // runtimeclass doesn't actually implement the interfaces we claim it does.   For example, a WinRT class which implements both
7447         // IVector<int> and ICalculator will be projected as implementing IList<int> and ICalculator.  In this case, we do not want the
7448         // ICalculator Add(int) method to get lined up with the ICollection<int> Add method, since that will cause us to dispatch to the
7449         // wrong underlying COM interface.
7450         //
7451         // There are a special WinRT types in mscorlib (notably DisposableRuntimeClass) which do implement interfaces in the normal way
7452         // so we skip this check for them.  (Note that we can't use a methodimpl directly in mscorlib, since ComImport classes are
7453         // forbidden from having implementation code by the C# compiler).
7454         if (GetHalfBakedClass()->IsProjectedFromWinRT() && !GetModule()->IsSystem())
7455         {
7456             continue;
7457         }
7458 #endif // FEATURE_COMINTEROP
7459
7460         // For each method declared in this interface
7461         bmtInterfaceEntry::InterfaceSlotIterator itfSlotIt =
7462             pCurItfEntry->IterateInterfaceSlots(GetStackingAllocator());
7463         for (; !itfSlotIt.AtEnd(); ++itfSlotIt)
7464         {
7465             if (fParentInterfaceEquivalent)
7466             {
7467                 if (itfSlotIt->Impl() != INVALID_SLOT_INDEX)
7468                 {   // If this interface is not explicitly declared on this class, and the interface slot has already been
7469                     // given an implementation, then the only way to provide a new implementation is through an override
7470                     // or through a MethodImpl. This is necessary in addition to the continue statement before this for
7471                     // loop because an abstract interface can still have a partial implementation and it is necessary to
7472                     // skip those interface slots that have already been satisfied.
7473                     continue;
7474                 }
7475             }
7476
7477             BOOL                    fFoundMatchInBuildingClass = FALSE;
7478             bmtInterfaceSlotImpl &  curItfSlot = *itfSlotIt;
7479             bmtRTMethod *           pCurItfMethod = curItfSlot.Decl().AsRTMethod();
7480             const MethodSignature & curItfMethodSig = pCurItfMethod->GetMethodSignature();
7481
7482             //
7483             // First, try to find the method explicitly declared in our class
7484             //
7485
7486             DeclaredMethodIterator methIt(*this);
7487             while (methIt.Next())
7488             {
7489                 // Note that non-publics can legally be exposed via an interface, but only
7490                 // through methodImpls.
7491                 if (IsMdVirtual(methIt.Attrs()) && IsMdPublic(methIt.Attrs()))
7492                 {
7493 #ifdef _DEBUG 
7494                     if(GetHalfBakedClass()->m_fDebuggingClass && g_pConfig->ShouldBreakOnMethod(methIt.Name()))
7495                         CONSISTENCY_CHECK_MSGF(false, ("BreakOnMethodName: '%s' ", methIt.Name()));
7496 #endif // _DEBUG
7497
7498                     if (pCurItfMethod->GetMethodSignature().Equivalent(methIt->GetMethodSignature()))
7499                     {
7500                         fFoundMatchInBuildingClass = TRUE;
7501                         curItfSlot.Impl() = methIt->GetSlotIndex();
7502
7503                         DispatchMapTypeID dispatchMapTypeID =
7504                             DispatchMapTypeID::InterfaceClassID(dwCurInterface);
7505                         bmtVT->pDispatchMapBuilder->InsertMDMapping(
7506                             dispatchMapTypeID, 
7507                             static_cast<UINT32>(itfSlotIt.CurrentIndex()), 
7508                             methIt->GetMethodDesc(),
7509                             FALSE);
7510
7511                         break;
7512                     }
7513                 }
7514             } // end ... try to find method
7515
7516             //
7517             // The ECMA CLR spec states that a type will inherit interface implementations
7518             // and that explicit re-declaration of an inherited interface will try to match
7519             // only newslot methods with methods in the re-declared interface (note that
7520             // this also takes care of matching against unsatisfied interface methods in
7521             // the abstract parent type scenario).
7522             //
7523             // So, if the interface was not declared on a parent and we haven't found a
7524             // newslot method declared on this type as a match, search all remaining
7525             // public virtual methods (including overrides declared on this type) for a
7526             // match.
7527             //
7528             // Please see bug VSW577403 and VSW593884 for details of this breaking change.
7529             //
7530             if (!fFoundMatchInBuildingClass &&
7531                 !fEquivalentInterfaceImplementedByParent)
7532             {
7533                 if (HasParent())
7534                 {
7535                     // Iterate backward through the parent's method table. This is important to 
7536                     // find the most derived method.
7537                     bmtParentInfo::Iterator parentMethodIt = bmtParent->IterateSlots();
7538                     parentMethodIt.ResetToEnd();
7539                     while (parentMethodIt.Prev())
7540                     {
7541                         bmtRTMethod * pCurParentMethod = parentMethodIt->Decl().AsRTMethod();
7542                         DWORD dwAttrs = pCurParentMethod->GetDeclAttrs();
7543                         if (!IsMdVirtual(dwAttrs) || !IsMdPublic(dwAttrs))
7544                         {   // Only match mdPublic mdVirtual methods for interface implementation
7545                             continue;
7546                         }
7547
7548                         if (curItfMethodSig.Equivalent(pCurParentMethod->GetMethodSignature()))
7549                         {
7550                             fFoundMatchInBuildingClass = TRUE;
7551                             curItfSlot.Impl() = pCurParentMethod->GetSlotIndex();
7552
7553                             DispatchMapTypeID dispatchMapTypeID =
7554                                 DispatchMapTypeID::InterfaceClassID(dwCurInterface);
7555                             bmtVT->pDispatchMapBuilder->InsertMDMapping(
7556                                 dispatchMapTypeID, 
7557                                 static_cast<UINT32>(itfSlotIt.CurrentIndex()), 
7558                                 pCurParentMethod->GetMethodDesc(), 
7559                                 FALSE);
7560
7561                             break;
7562                         }
7563                     } // end ... try to find parent method
7564                 }
7565             }
7566
7567             // For type equivalent interfaces that had an equivalent interface implemented by their parent
7568             // and where the previous logic to fill in the method based on the virtual mappings on the type have
7569             // failed, we should attempt to get the mappings from the equivalent interfaces declared on parent types
7570             // of the type we are currently building.
7571 #ifdef FEATURE_COMINTEROP
7572             if (!fFoundMatchInBuildingClass && fEquivalentInterfaceImplementedByParent && !pCurItfEntry->IsImplementedByParent())
7573             {
7574                 PlaceMethodFromParentEquivalentInterfaceIntoInterfaceSlot(itfSlotIt, pCurItfEntry, &rgInterfaceDispatchMapTypeIDs, dwCurInterface);
7575             }
7576 #endif
7577         }
7578     }
7579 } // MethodTableBuilder::PlaceInterfaceMethods
7580
7581
7582 //*******************************************************************************
7583 //
7584 // Used by BuildMethodTable
7585 //
7586 // Place static fields
7587 //
7588 VOID MethodTableBuilder::PlaceRegularStaticFields()
7589 {
7590     STANDARD_VM_CONTRACT;
7591
7592     DWORD i;
7593
7594     LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Placing statics for %s\n", this->GetDebugClassName()));
7595
7596     //
7597     // Place gc refs and value types first, as they need to have handles created for them.
7598     // (Placing them together allows us to easily create the handles when Restoring the class,
7599     // and when initializing new DLS for the class.)
7600     //
7601
7602     DWORD   dwCumulativeStaticFieldPos = 0 ;
7603     DWORD   dwCumulativeStaticGCFieldPos = 0;
7604     DWORD   dwCumulativeStaticBoxFieldPos = 0;
7605
7606     // We don't need to do any calculations for the gc refs or valuetypes, as they're
7607     // guaranteed to be aligned in ModuleStaticsInfo
7608     bmtFP->NumRegularStaticFieldsOfSize[LOG2_PTRSIZE] -=
7609         bmtFP->NumRegularStaticGCBoxedFields + bmtFP->NumRegularStaticGCPointerFields;
7610
7611     // Place fields, largest first, padding so that each group is aligned to its natural size
7612     for (i = MAX_LOG2_PRIMITIVE_FIELD_SIZE; (signed int) i >= 0; i--)
7613     {
7614         // Fields of this size start at the next available location
7615         bmtFP->RegularStaticFieldStart[i] = dwCumulativeStaticFieldPos;
7616         dwCumulativeStaticFieldPos += (bmtFP->NumRegularStaticFieldsOfSize[i] << i);
7617
7618         // Reset counters for the loop after this one
7619         bmtFP->NumRegularStaticFieldsOfSize[i]    = 0;
7620     }
7621
7622
7623     if (dwCumulativeStaticFieldPos > FIELD_OFFSET_LAST_REAL_OFFSET)
7624         BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
7625
7626     DWORD dwNumHandleStatics = bmtFP->NumRegularStaticGCBoxedFields + bmtFP->NumRegularStaticGCPointerFields;
7627     if (!FitsIn<WORD>(dwNumHandleStatics))
7628     {   // Overflow.
7629         BuildMethodTableThrowException(IDS_EE_TOOMANYFIELDS);
7630     }
7631     SetNumHandleRegularStatics(static_cast<WORD>(dwNumHandleStatics));
7632
7633     if (!FitsIn<WORD>(bmtFP->NumRegularStaticGCBoxedFields))
7634     {   // Overflow.
7635         BuildMethodTableThrowException(IDS_EE_TOOMANYFIELDS);
7636     }
7637     SetNumBoxedRegularStatics(static_cast<WORD>(bmtFP->NumRegularStaticGCBoxedFields));
7638
7639     // Tell the module to give us the offsets we'll be using and commit space for us
7640     // if necessary
7641     DWORD dwNonGCOffset, dwGCOffset;
7642     GetModule()->GetOffsetsForRegularStaticData(bmtInternal->pType->GetTypeDefToken(),
7643                                                 bmtProp->fDynamicStatics,
7644                                                 GetNumHandleRegularStatics(), dwCumulativeStaticFieldPos,
7645                                                 &dwGCOffset, &dwNonGCOffset);
7646
7647     // Allocate boxed statics first ("x << LOG2_PTRSIZE" is equivalent to "x * sizeof(void *)")
7648     dwCumulativeStaticGCFieldPos = bmtFP->NumRegularStaticGCBoxedFields<<LOG2_PTRSIZE;
7649
7650     FieldDesc *pFieldDescList = GetApproxFieldDescListRaw();
7651     // Place static fields
7652     for (i = 0; i < bmtEnumFields->dwNumStaticFields - bmtEnumFields->dwNumThreadStaticFields; i++)
7653     {
7654         FieldDesc * pCurField   = &pFieldDescList[bmtEnumFields->dwNumInstanceFields+i];
7655         DWORD dwLog2FieldSize   = (DWORD)(DWORD_PTR&)pCurField->m_pMTOfEnclosingClass; // log2(field size)
7656         DWORD dwOffset          = (DWORD) pCurField->m_dwOffset; // offset or type of field
7657
7658         switch (dwOffset)
7659         {
7660         case FIELD_OFFSET_UNPLACED_GC_PTR:
7661             // Place GC reference static field
7662             pCurField->SetOffset(dwCumulativeStaticGCFieldPos + dwGCOffset);
7663             dwCumulativeStaticGCFieldPos += 1<<LOG2_PTRSIZE;
7664             LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Field placed at GC offset 0x%x\n", pCurField->GetOffset_NoLogging()));
7665
7666             break;
7667
7668         case FIELD_OFFSET_VALUE_CLASS:
7669             // Place boxed GC reference static field
7670             pCurField->SetOffset(dwCumulativeStaticBoxFieldPos + dwGCOffset);
7671             dwCumulativeStaticBoxFieldPos += 1<<LOG2_PTRSIZE;
7672             LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Field placed at GC offset 0x%x\n", pCurField->GetOffset_NoLogging()));
7673
7674             break;
7675
7676         case FIELD_OFFSET_UNPLACED:
7677             // Place non-GC static field
7678             pCurField->SetOffset(bmtFP->RegularStaticFieldStart[dwLog2FieldSize] +
7679                                  (bmtFP->NumRegularStaticFieldsOfSize[dwLog2FieldSize] << dwLog2FieldSize) +
7680                                  dwNonGCOffset);
7681             bmtFP->NumRegularStaticFieldsOfSize[dwLog2FieldSize]++;
7682             LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Field placed at non GC offset 0x%x\n", pCurField->GetOffset_NoLogging()));
7683             break;
7684
7685         default:
7686             // RVA field
7687             break;
7688         }
7689
7690         LOG((LF_CLASSLOADER, LL_INFO1000000, "Offset of %s: %i\n", pCurField->m_debugName, pCurField->GetOffset_NoLogging()));
7691     }
7692
7693     if (bmtProp->fDynamicStatics)
7694     {
7695         _ASSERTE(dwNonGCOffset == 0 ||  // no statics at all
7696                  dwNonGCOffset == OFFSETOF__DomainLocalModule__NormalDynamicEntry__m_pDataBlob); // We need space to point to the GC statics
7697         bmtProp->dwNonGCRegularStaticFieldBytes = dwCumulativeStaticFieldPos;
7698     }
7699     else
7700     {
7701         bmtProp->dwNonGCRegularStaticFieldBytes = 0; // Non dynamics shouldnt be using this
7702     }
7703     LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Static field bytes needed (0 is normal for non dynamic case)%i\n", bmtProp->dwNonGCRegularStaticFieldBytes));
7704 }
7705
7706
7707 VOID MethodTableBuilder::PlaceThreadStaticFields()
7708 {
7709     STANDARD_VM_CONTRACT;
7710
7711     DWORD i;
7712
7713     LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Placing ThreadStatics for %s\n", this->GetDebugClassName()));
7714
7715     //
7716     // Place gc refs and value types first, as they need to have handles created for them.
7717     // (Placing them together allows us to easily create the handles when Restoring the class,
7718     // and when initializing new DLS for the class.)
7719     //
7720
7721     DWORD   dwCumulativeStaticFieldPos = 0 ;
7722     DWORD   dwCumulativeStaticGCFieldPos = 0;
7723     DWORD   dwCumulativeStaticBoxFieldPos = 0;
7724
7725     // We don't need to do any calculations for the gc refs or valuetypes, as they're
7726     // guaranteed to be aligned in ModuleStaticsInfo
7727     bmtFP->NumThreadStaticFieldsOfSize[LOG2_PTRSIZE] -=
7728         bmtFP->NumThreadStaticGCBoxedFields + bmtFP->NumThreadStaticGCPointerFields;
7729
7730     // Place fields, largest first, padding so that each group is aligned to its natural size
7731     for (i = MAX_LOG2_PRIMITIVE_FIELD_SIZE; (signed int) i >= 0; i--)
7732     {
7733         // Fields of this size start at the next available location
7734         bmtFP->ThreadStaticFieldStart[i] = dwCumulativeStaticFieldPos;
7735         dwCumulativeStaticFieldPos += (bmtFP->NumThreadStaticFieldsOfSize[i] << i);
7736
7737         // Reset counters for the loop after this one
7738         bmtFP->NumThreadStaticFieldsOfSize[i]    = 0;
7739     }
7740
7741
7742     if (dwCumulativeStaticFieldPos > FIELD_OFFSET_LAST_REAL_OFFSET)
7743         BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
7744
7745     DWORD dwNumHandleStatics = bmtFP->NumThreadStaticGCBoxedFields + bmtFP->NumThreadStaticGCPointerFields;
7746     if (!FitsIn<WORD>(dwNumHandleStatics))
7747     {   // Overflow.
7748         BuildMethodTableThrowException(IDS_EE_TOOMANYFIELDS);
7749     }
7750
7751     SetNumHandleThreadStatics(static_cast<WORD>(dwNumHandleStatics));
7752
7753     if (!FitsIn<WORD>(bmtFP->NumThreadStaticGCBoxedFields))
7754     {   // Overflow.
7755         BuildMethodTableThrowException(IDS_EE_TOOMANYFIELDS);
7756     }
7757
7758     SetNumBoxedThreadStatics(static_cast<WORD>(bmtFP->NumThreadStaticGCBoxedFields));
7759
7760     // Tell the module to give us the offsets we'll be using and commit space for us
7761     // if necessary
7762     DWORD dwNonGCOffset, dwGCOffset;
7763
7764     GetModule()->GetOffsetsForThreadStaticData(bmtInternal->pType->GetTypeDefToken(),
7765                                                bmtProp->fDynamicStatics,
7766                                                GetNumHandleThreadStatics(), dwCumulativeStaticFieldPos,
7767                                                &dwGCOffset, &dwNonGCOffset);
7768
7769     // Allocate boxed statics first ("x << LOG2_PTRSIZE" is equivalent to "x * sizeof(void *)")
7770     dwCumulativeStaticGCFieldPos = bmtFP->NumThreadStaticGCBoxedFields<<LOG2_PTRSIZE;
7771
7772     FieldDesc *pFieldDescList = GetHalfBakedClass()->GetFieldDescList();
7773     // Place static fields
7774     for (i = 0; i < bmtEnumFields->dwNumThreadStaticFields; i++)
7775     {
7776         FieldDesc * pCurField   = &pFieldDescList[bmtEnumFields->dwNumInstanceFields + bmtEnumFields->dwNumStaticFields - bmtEnumFields->dwNumThreadStaticFields + i];
7777         DWORD dwLog2FieldSize   = (DWORD)(DWORD_PTR&)pCurField->m_pMTOfEnclosingClass; // log2(field size)
7778         DWORD dwOffset          = (DWORD) pCurField->m_dwOffset; // offset or type of field
7779
7780         switch (dwOffset)
7781         {
7782         case FIELD_OFFSET_UNPLACED_GC_PTR:
7783             // Place GC reference static field
7784             pCurField->SetOffset(dwCumulativeStaticGCFieldPos + dwGCOffset);
7785             dwCumulativeStaticGCFieldPos += 1<<LOG2_PTRSIZE;
7786             LOG((LF_CLASSLOADER, LL_INFO10000, "THREAD STATICS: Field placed at GC offset 0x%x\n", pCurField->GetOffset_NoLogging()));
7787
7788             break;
7789
7790         case FIELD_OFFSET_VALUE_CLASS:
7791             // Place boxed GC reference static field
7792             pCurField->SetOffset(dwCumulativeStaticBoxFieldPos + dwGCOffset);
7793             dwCumulativeStaticBoxFieldPos += 1<<LOG2_PTRSIZE;
7794             LOG((LF_CLASSLOADER, LL_INFO10000, "THREAD STATICS: Field placed at GC offset 0x%x\n", pCurField->GetOffset_NoLogging()));
7795
7796             break;
7797
7798         case FIELD_OFFSET_UNPLACED:
7799             // Place non-GC static field
7800             pCurField->SetOffset(bmtFP->ThreadStaticFieldStart[dwLog2FieldSize] +
7801                                  (bmtFP->NumThreadStaticFieldsOfSize[dwLog2FieldSize] << dwLog2FieldSize) +
7802                                  dwNonGCOffset);
7803             bmtFP->NumThreadStaticFieldsOfSize[dwLog2FieldSize]++;
7804             LOG((LF_CLASSLOADER, LL_INFO10000, "THREAD STATICS: Field placed at non GC offset 0x%x\n", pCurField->GetOffset_NoLogging()));
7805             break;
7806
7807         default:
7808             // RVA field
7809             break;
7810         }
7811
7812         LOG((LF_CLASSLOADER, LL_INFO1000000, "Offset of %s: %i\n", pCurField->m_debugName, pCurField->GetOffset_NoLogging()));
7813     }
7814
7815     if (bmtProp->fDynamicStatics)
7816     {
7817         _ASSERTE(dwNonGCOffset == 0 ||  // no thread statics at all
7818                  dwNonGCOffset == OFFSETOF__ThreadLocalModule__DynamicEntry__m_pDataBlob); // We need space to point to the GC statics
7819         bmtProp->dwNonGCThreadStaticFieldBytes = dwCumulativeStaticFieldPos;
7820     }
7821     else
7822     {
7823         bmtProp->dwNonGCThreadStaticFieldBytes = 0; // Non dynamics shouldnt be using this
7824     }
7825     LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: ThreadStatic field bytes needed (0 is normal for non dynamic case)%i\n", bmtProp->dwNonGCThreadStaticFieldBytes));
7826 }
7827
7828 //*******************************************************************************
7829 //
7830 // Used by BuildMethodTable
7831 //
7832 // Place instance fields
7833 //
7834 VOID    MethodTableBuilder::PlaceInstanceFields(MethodTable ** pByValueClassCache)
7835 {
7836     STANDARD_VM_CONTRACT;
7837
7838
7839     DWORD i;
7840
7841         //===============================================================
7842         // BEGIN: Place instance fields
7843         //===============================================================
7844
7845         FieldDesc *pFieldDescList = GetHalfBakedClass()->GetFieldDescList();
7846         DWORD   dwCumulativeInstanceFieldPos;
7847
7848         // Instance fields start right after the parent
7849         dwCumulativeInstanceFieldPos    = HasParent() ? GetParentMethodTable()->GetNumInstanceFieldBytes() : 0;
7850
7851         DWORD dwOffsetBias = 0;
7852 #ifdef FEATURE_64BIT_ALIGNMENT
7853         // On platforms where the alignment of 64-bit primitives is a requirement (but we're not guaranteed
7854         // this implicitly by the GC) field offset 0 is actually not 8-byte aligned in reference classes.
7855         // That's because all such platforms are currently 32-bit and the 4-byte MethodTable pointer pushes us
7856         // out of alignment. Ideally we'd solve this by arranging to have the object header allocated at a
7857         // 4-byte offset from an 8-byte boundary, but this is difficult to achieve for objects allocated on
7858         // the large object heap (which actually requires headers to be 8-byte aligned).
7859         //
7860         // So we adjust dwCumulativeInstanceFieldPos to account for the MethodTable* and our alignment
7861         // calculations will automatically adjust and add padding as necessary. We need to remove this
7862         // adjustment when setting the field offset in the field desc, however, since the rest of the system
7863         // expects that value to not include the MethodTable*.
7864         //
7865         // This happens only for reference classes: value type field 0 really does lie at offset 0 for unboxed
7866         // value types. We deal with boxed value types by allocating their headers mis-aligned (luckily for us
7867         // value types can never get large enough to allocate on the LOH). 
7868         if (!IsValueClass())
7869         {
7870             dwOffsetBias = TARGET_POINTER_SIZE;
7871             dwCumulativeInstanceFieldPos += dwOffsetBias;
7872         }
7873 #endif // FEATURE_64BIT_ALIGNMENT
7874
7875 #ifdef FEATURE_READYTORUN
7876         if (NeedsAlignedBaseOffset())
7877         {
7878             // READYTORUN: FUTURE: Use the minimum possible alignment, reduce padding when inheriting within same bubble
7879             DWORD dwAlignment = DATA_ALIGNMENT;
7880 #ifdef FEATURE_64BIT_ALIGNMENT
7881             if (GetHalfBakedClass()->IsAlign8Candidate())
7882                 dwAlignment = 8;
7883 #endif
7884             dwCumulativeInstanceFieldPos = (DWORD)ALIGN_UP(dwCumulativeInstanceFieldPos, dwAlignment);
7885         }
7886 #endif // FEATURE_READYTORUN
7887
7888         // place small fields first if the parent have a number of field bytes that is not aligned
7889         if (!IS_ALIGNED(dwCumulativeInstanceFieldPos, DATA_ALIGNMENT))
7890         {
7891             for (i = 0; i < MAX_LOG2_PRIMITIVE_FIELD_SIZE; i++) {
7892                 DWORD j;
7893
7894                 if (IS_ALIGNED(dwCumulativeInstanceFieldPos, size_t{ 1 } << (i + 1)))
7895                     continue;
7896
7897                 // check whether there are any bigger fields
7898                 for (j = i + 1; j <= MAX_LOG2_PRIMITIVE_FIELD_SIZE; j++) {
7899                     if (bmtFP->NumInstanceFieldsOfSize[j] != 0)
7900                         break;
7901                 }
7902                 // nothing to gain if there are no bigger fields
7903                 // (the subsequent loop will place fields from large to small fields)
7904                 if (j > MAX_LOG2_PRIMITIVE_FIELD_SIZE)
7905                     break;
7906
7907                 // check whether there are any small enough fields
7908                 for (j = i; (signed int) j >= 0; j--) {
7909                     if (bmtFP->NumInstanceFieldsOfSize[j] != 0)
7910                         break;
7911                     // TODO: since we will refuse to place GC references we should filter them out here.
7912                     // otherwise the "back-filling" process stops completely.
7913                     // (PlaceInstanceFields)
7914                     // the following code would fix the issue (a replacement for the code above this comment):
7915                     // if (bmtFP->NumInstanceFieldsOfSize[j] != 0 &&
7916                     //     (j != LOG2SLOT || bmtFP->NumInstanceFieldsOfSize[j] > bmtFP->NumInstanceGCPointerFields))
7917                     // {
7918                     //     break;
7919                     // }
7920
7921                 }
7922                 // nothing to play with if there are no smaller fields
7923                 if ((signed int) j < 0)
7924                     break;
7925                 // eventually go back and use the smaller field as filling
7926                 i = j;
7927
7928                 CONSISTENCY_CHECK(bmtFP->NumInstanceFieldsOfSize[i] != 0);
7929
7930                 j = bmtFP->FirstInstanceFieldOfSize[i];
7931
7932                 // Avoid reordering of gcfields
7933                 if (i == LOG2SLOT) {
7934                     for ( ; j < bmtEnumFields->dwNumInstanceFields; j++) {
7935                         if ((pFieldDescList[j].GetOffset_NoLogging() == FIELD_OFFSET_UNPLACED) &&
7936                             ((DWORD_PTR&)pFieldDescList[j].m_pMTOfEnclosingClass == (size_t)i))
7937                             break;
7938                     }
7939
7940                     // out of luck - can't reorder gc fields
7941                     if (j >= bmtEnumFields->dwNumInstanceFields)
7942                         break;
7943                 }
7944
7945                 // Place the field
7946                 dwCumulativeInstanceFieldPos = (DWORD)ALIGN_UP(dwCumulativeInstanceFieldPos, size_t{ 1 } << i);
7947
7948                 pFieldDescList[j].SetOffset(dwCumulativeInstanceFieldPos - dwOffsetBias);
7949                 dwCumulativeInstanceFieldPos += (1 << i);
7950
7951                 // We've placed this field now, so there is now one less of this size field to place
7952                 if (--bmtFP->NumInstanceFieldsOfSize[i] == 0)
7953                     continue;
7954
7955                 // We are done in this round if we haven't picked the first field
7956                 if (bmtFP->FirstInstanceFieldOfSize[i] != j)
7957                     continue;
7958
7959                 // Update FirstInstanceFieldOfSize[i] to point to the next such field
7960                 for (j = j+1; j < bmtEnumFields->dwNumInstanceFields; j++)
7961                 {
7962                     // The log of the field size is stored in the method table
7963                     if ((DWORD_PTR&)pFieldDescList[j].m_pMTOfEnclosingClass == (size_t)i)
7964                     {
7965                         bmtFP->FirstInstanceFieldOfSize[i] = j;
7966                         break;
7967                     }
7968                 }
7969                 _ASSERTE(j < bmtEnumFields->dwNumInstanceFields);
7970             }
7971         }
7972
7973         // Place fields, largest first
7974         for (i = MAX_LOG2_PRIMITIVE_FIELD_SIZE; (signed int) i >= 0; i--)
7975         {
7976             if (bmtFP->NumInstanceFieldsOfSize[i] == 0)
7977                 continue;
7978
7979             // Align instance fields if we aren't already
7980 #ifdef FEATURE_64BIT_ALIGNMENT
7981             DWORD dwDataAlignment = 1 << i;
7982 #else
7983             DWORD dwDataAlignment = min(1 << i, DATA_ALIGNMENT);
7984 #endif
7985             dwCumulativeInstanceFieldPos = (DWORD)ALIGN_UP(dwCumulativeInstanceFieldPos, dwDataAlignment);
7986
7987             // Fields of this size start at the next available location
7988             bmtFP->InstanceFieldStart[i] = dwCumulativeInstanceFieldPos;
7989             dwCumulativeInstanceFieldPos += (bmtFP->NumInstanceFieldsOfSize[i] << i);
7990
7991             // Reset counters for the loop after this one
7992             bmtFP->NumInstanceFieldsOfSize[i]  = 0;
7993         }
7994
7995
7996         // Make corrections to reserve space for GC Pointer Fields
7997         //
7998         // The GC Pointers simply take up the top part of the region associated
7999         // with fields of that size (GC pointers can be 64 bit on certain systems)
8000         if (bmtFP->NumInstanceGCPointerFields)
8001         {
8002             bmtFP->GCPointerFieldStart = bmtFP->InstanceFieldStart[LOG2SLOT] - dwOffsetBias;
8003             bmtFP->InstanceFieldStart[LOG2SLOT] = bmtFP->InstanceFieldStart[LOG2SLOT] + (bmtFP->NumInstanceGCPointerFields << LOG2SLOT);
8004             bmtFP->NumInstanceGCPointerFields = 0;     // reset to zero here, counts up as pointer slots are assigned below
8005         }
8006
8007         // Place instance fields - be careful not to place any already-placed fields
8008         for (i = 0; i < bmtEnumFields->dwNumInstanceFields; i++)
8009         {
8010             DWORD dwFieldSize   = (DWORD)(DWORD_PTR&)pFieldDescList[i].m_pMTOfEnclosingClass;
8011             DWORD dwOffset;
8012
8013             dwOffset = pFieldDescList[i].GetOffset_NoLogging();
8014
8015             // Don't place already-placed fields
8016             if ((dwOffset == FIELD_OFFSET_UNPLACED || dwOffset == FIELD_OFFSET_UNPLACED_GC_PTR || dwOffset == FIELD_OFFSET_VALUE_CLASS))
8017             {
8018                 if (dwOffset == FIELD_OFFSET_UNPLACED_GC_PTR)
8019                 {
8020                     pFieldDescList[i].SetOffset(bmtFP->GCPointerFieldStart + (bmtFP->NumInstanceGCPointerFields << LOG2SLOT));
8021                     bmtFP->NumInstanceGCPointerFields++;
8022                 }
8023                 else if (pFieldDescList[i].IsByValue() == FALSE) // it's a regular field
8024                 {
8025                     pFieldDescList[i].SetOffset(bmtFP->InstanceFieldStart[dwFieldSize] + (bmtFP->NumInstanceFieldsOfSize[dwFieldSize] << dwFieldSize) - dwOffsetBias);
8026                     bmtFP->NumInstanceFieldsOfSize[dwFieldSize]++;
8027                 }
8028             }
8029         }
8030
8031         DWORD dwNumGCPointerSeries;
8032         // Save Number of pointer series
8033         if (bmtFP->NumInstanceGCPointerFields)
8034             dwNumGCPointerSeries = bmtParent->NumParentPointerSeries + 1;
8035         else
8036             dwNumGCPointerSeries = bmtParent->NumParentPointerSeries;
8037
8038         // Place by value class fields last
8039         // Update the number of GC pointer series
8040         for (i = 0; i < bmtEnumFields->dwNumInstanceFields; i++)
8041         {
8042             if (pFieldDescList[i].IsByValue())
8043             {
8044                 MethodTable * pByValueMT = pByValueClassCache[i];
8045
8046                     // value classes could have GC pointers in them, which need to be pointer-size aligned
8047                     // so do this if it has not been done already
8048
8049 #if !defined(_TARGET_64BIT_) && (DATA_ALIGNMENT > 4) 
8050                 dwCumulativeInstanceFieldPos = (DWORD)ALIGN_UP(dwCumulativeInstanceFieldPos,
8051                     (pByValueMT->GetNumInstanceFieldBytes() >= DATA_ALIGNMENT) ? DATA_ALIGNMENT : TARGET_POINTER_SIZE);
8052 #else // !(!defined(_TARGET_64BIT_) && (DATA_ALIGNMENT > 4))
8053 #ifdef FEATURE_64BIT_ALIGNMENT
8054                 if (pByValueMT->RequiresAlign8())
8055                     dwCumulativeInstanceFieldPos = (DWORD)ALIGN_UP(dwCumulativeInstanceFieldPos, 8);
8056                 else
8057 #endif // FEATURE_64BIT_ALIGNMENT
8058                     dwCumulativeInstanceFieldPos = (DWORD)ALIGN_UP(dwCumulativeInstanceFieldPos, TARGET_POINTER_SIZE);
8059 #endif // !(!defined(_TARGET_64BIT_) && (DATA_ALIGNMENT > 4))
8060
8061                 pFieldDescList[i].SetOffset(dwCumulativeInstanceFieldPos - dwOffsetBias);
8062                 dwCumulativeInstanceFieldPos += pByValueMT->GetAlignedNumInstanceFieldBytes();
8063
8064                 // Add pointer series for by-value classes
8065                 dwNumGCPointerSeries += pByValueMT->ContainsPointers() ?
8066                     (DWORD)CGCDesc::GetCGCDescFromMT(pByValueMT)->GetNumSeries() : 0;
8067             }
8068         }
8069
8070             // Can be unaligned
8071         DWORD dwNumInstanceFieldBytes = dwCumulativeInstanceFieldPos - dwOffsetBias;
8072
8073         if (IsValueClass())
8074         {
8075                  // Like C++ we enforce that there can be no 0 length structures.
8076                 // Thus for a value class with no fields, we 'pad' the length to be 1
8077             if (dwNumInstanceFieldBytes == 0)
8078                 dwNumInstanceFieldBytes = 1;
8079
8080                 // The JITs like to copy full machine words,
8081                 //  so if the size is bigger than a void* round it up to minAlign
8082                 // and if the size is smaller than void* round it up to next power of two
8083             unsigned minAlign;
8084
8085 #ifdef FEATURE_64BIT_ALIGNMENT
8086             if (GetHalfBakedClass()->IsAlign8Candidate()) {
8087                 minAlign = 8;
8088             }
8089             else
8090 #endif // FEATURE_64BIT_ALIGNMENT
8091             if (dwNumInstanceFieldBytes > TARGET_POINTER_SIZE) {
8092                 minAlign = TARGET_POINTER_SIZE;
8093             }
8094             else {
8095                 minAlign = 1;
8096                 while (minAlign < dwNumInstanceFieldBytes)
8097                     minAlign *= 2;
8098             }
8099
8100             dwNumInstanceFieldBytes = (dwNumInstanceFieldBytes + minAlign-1) & ~(minAlign-1);
8101         }
8102
8103         if (dwNumInstanceFieldBytes > FIELD_OFFSET_LAST_REAL_OFFSET) {
8104             BuildMethodTableThrowException(IDS_CLASSLOAD_FIELDTOOLARGE);
8105         }
8106
8107         bmtFP->NumInstanceFieldBytes = dwNumInstanceFieldBytes;
8108
8109         bmtFP->NumGCPointerSeries = dwNumGCPointerSeries;
8110
8111         //===============================================================
8112         // END: Place instance fields
8113         //===============================================================
8114 }
8115
8116 //*******************************************************************************
8117 // this accesses the field size which is temporarily stored in m_pMTOfEnclosingClass
8118 // during class loading. Don't use any other time
8119 DWORD MethodTableBuilder::GetFieldSize(FieldDesc *pFD)
8120 {
8121     STATIC_CONTRACT_NOTHROW;
8122     STATIC_CONTRACT_GC_NOTRIGGER;
8123     STATIC_CONTRACT_FORBID_FAULT;
8124
8125         // We should only be calling this while this class is being built.
8126     _ASSERTE(GetHalfBakedMethodTable() == 0);
8127     BAD_FORMAT_NOTHROW_ASSERT(! pFD->IsByValue() || HasExplicitFieldOffsetLayout());
8128
8129     if (pFD->IsByValue())
8130         return (DWORD)(DWORD_PTR&)(pFD->m_pMTOfEnclosingClass);
8131     return (1 << (DWORD)(DWORD_PTR&)(pFD->m_pMTOfEnclosingClass));
8132 }
8133
8134 #ifdef UNIX_AMD64_ABI
8135 // checks whether the struct is enregisterable.
8136 void MethodTableBuilder::SystemVAmd64CheckForPassStructInRegister()
8137 {
8138     STANDARD_VM_CONTRACT;
8139
8140     // This method should be called for valuetypes only
8141     _ASSERTE(IsValueClass());
8142
8143     TypeHandle th(GetHalfBakedMethodTable());
8144
8145     if (th.IsTypeDesc())
8146     {
8147         // Not an enregisterable managed structure.
8148         return;
8149     }
8150
8151     DWORD totalStructSize = bmtFP->NumInstanceFieldBytes;
8152
8153     // If num of bytes for the fields is bigger than CLR_SYSTEMV_MAX_STRUCT_BYTES_TO_PASS_IN_REGISTERS
8154     // pass through stack
8155     if (totalStructSize > CLR_SYSTEMV_MAX_STRUCT_BYTES_TO_PASS_IN_REGISTERS)
8156     {
8157         LOG((LF_JIT, LL_EVERYTHING, "**** SystemVAmd64CheckForPassStructInRegister: struct %s is too big to pass in registers (%d bytes)\n",
8158                this->GetDebugClassName(), totalStructSize));
8159         return;
8160     }
8161
8162     const bool useNativeLayout = false;
8163     // Iterate through the fields and make sure they meet requirements to pass in registers
8164     SystemVStructRegisterPassingHelper helper((unsigned int)totalStructSize);
8165     if (GetHalfBakedMethodTable()->ClassifyEightBytes(&helper, 0, 0, useNativeLayout))
8166     {
8167         // All the above tests passed. It's registers passed struct!
8168         GetHalfBakedMethodTable()->SetRegPassedStruct();
8169
8170         StoreEightByteClassification(&helper);
8171     }
8172 }
8173
8174 // checks whether the struct is enregisterable.
8175 void MethodTableBuilder::SystemVAmd64CheckForPassNativeStructInRegister()
8176 {
8177     STANDARD_VM_CONTRACT;
8178     DWORD totalStructSize = 0;
8179
8180     // If not a native value type, return.
8181     if (!IsValueClass())
8182     {
8183         return;
8184     }
8185
8186     totalStructSize = GetLayoutInfo()->GetNativeSize();
8187
8188     // If num of bytes for the fields is bigger than CLR_SYSTEMV_MAX_STRUCT_BYTES_TO_PASS_IN_REGISTERS
8189     // pass through stack
8190     if (totalStructSize > CLR_SYSTEMV_MAX_STRUCT_BYTES_TO_PASS_IN_REGISTERS)
8191     {
8192         LOG((LF_JIT, LL_EVERYTHING, "**** SystemVAmd64CheckForPassNativeStructInRegister: struct %s is too big to pass in registers (%d bytes)\n",
8193             this->GetDebugClassName(), totalStructSize));
8194         return;
8195     }
8196
8197     _ASSERTE(HasLayout());
8198
8199     // Classify the native layout for this struct.
8200     const bool useNativeLayout = true;
8201     // Iterate through the fields and make sure they meet requirements to pass in registers
8202     SystemVStructRegisterPassingHelper helper((unsigned int)totalStructSize);
8203     if (GetHalfBakedMethodTable()->ClassifyEightBytes(&helper, 0, 0, useNativeLayout))
8204     {
8205         GetLayoutInfo()->SetNativeStructPassedInRegisters();
8206     }
8207 }
8208
8209 // Store the eightbyte classification into the EEClass
8210 void MethodTableBuilder::StoreEightByteClassification(SystemVStructRegisterPassingHelper* helper)
8211 {
8212     EEClass* eeClass = GetHalfBakedMethodTable()->GetClass();
8213     LoaderAllocator* pAllocator = MethodTableBuilder::GetLoaderAllocator();
8214     AllocMemTracker* pamTracker = MethodTableBuilder::GetMemTracker();
8215     EnsureOptionalFieldsAreAllocated(eeClass, pamTracker, pAllocator->GetLowFrequencyHeap());
8216     eeClass->SetEightByteClassification(helper->eightByteCount, helper->eightByteClassifications, helper->eightByteSizes);
8217 }
8218
8219 #endif // UNIX_AMD64_ABI
8220
8221 //---------------------------------------------------------------------------------------
8222 //
8223 // make sure that no object fields are overlapped incorrectly and define the
8224 // GC pointer series for the class. We are assuming that this class will always be laid out within
8225 // its enclosing class by the compiler in such a way that offset 0 will be the correct alignment
8226 // for object ref fields so we don't need to try to align it
8227 // 
8228 VOID 
8229 MethodTableBuilder::HandleExplicitLayout(
8230     MethodTable ** pByValueClassCache)
8231 {
8232     STANDARD_VM_CONTRACT;
8233
8234
8235     // Instance slice size is the total size of an instance, and is calculated as
8236     // the field whose offset and size add to the greatest number.
8237     UINT instanceSliceSize = 0;
8238     DWORD firstObjectOverlapOffset = ((DWORD)(-1));
8239
8240
8241     UINT i;
8242     for (i = 0; i < bmtMetaData->cFields; i++)
8243     {
8244         FieldDesc *pFD = bmtMFDescs->ppFieldDescList[i];
8245         if (pFD == NULL || pFD->IsStatic())
8246         {
8247             continue;
8248         }
8249
8250         UINT fieldExtent = 0;
8251         if (!ClrSafeInt<UINT>::addition(pFD->GetOffset_NoLogging(), GetFieldSize(pFD), fieldExtent))
8252         {
8253             BuildMethodTableThrowException(COR_E_OVERFLOW);
8254         }
8255
8256         if (fieldExtent > instanceSliceSize)
8257         {
8258             instanceSliceSize = fieldExtent;
8259         }
8260     }
8261
8262     CQuickBytes qb;
8263     PREFIX_ASSUME(sizeof(BYTE) == 1);
8264     BYTE *pFieldLayout = (BYTE*) qb.AllocThrows(instanceSliceSize * sizeof(BYTE));
8265     for (i=0; i < instanceSliceSize; i++)
8266     {
8267         pFieldLayout[i] = empty;
8268     }
8269
8270     // go through each field and look for invalid layout
8271     // (note that we are more permissive than what Ecma allows. We only disallow the minimum set necessary to
8272     // close security holes.)
8273     //
8274     // This is what we implment:
8275     //
8276     // 1. Verify that every OREF is on a valid alignment
8277     // 2. Verify that OREFs only overlap with other OREFs.
8278     // 3. If an OREF does overlap with another OREF, the class is marked unverifiable.
8279     // 4. If an overlap of any kind occurs, the class will be marked NotTightlyPacked (affects ValueType.Equals()).
8280     //
8281     char emptyObject[TARGET_POINTER_SIZE];
8282     char isObject[TARGET_POINTER_SIZE];
8283     for (i = 0; i < TARGET_POINTER_SIZE; i++)
8284     {
8285         emptyObject[i] = empty;
8286         isObject[i]    = oref;
8287     }
8288
8289
8290     ExplicitClassTrust explicitClassTrust;
8291
8292     UINT valueClassCacheIndex = ((UINT)(-1));
8293     UINT badOffset = 0;
8294     FieldDesc * pFD = NULL;
8295     for (i = 0; i < bmtMetaData->cFields; i++)
8296     {
8297         // Note about this loop body:
8298         //
8299         // This loop is coded to make it as hard as possible to allow a field to be trusted when it shouldn't.
8300         //
8301         // Every path in this loop body must lead to an explicit decision as to whether the field nonoverlaps,
8302         // overlaps in a verifiable fashion, overlaps in a nonverifiable fashion or overlaps in a completely illegal fashion.
8303         //
8304         // It must call fieldTrust.SetTrust() with the appropriate result. If you don't call it, fieldTrust's destructor
8305         // will intentionally default to kNone and mark the entire class illegal.
8306         //
8307         // If your result is anything but kNone (class is illegal), you must also explicitly "continue" the loop.
8308         // There is a "break" at end of this loop body that will abort the loop if you don't do this. And
8309         // if you don't finish iterating through all the fields, this function will automatically mark the entire
8310         // class illegal. This rule is a vestige of an earlier version of this function.
8311
8312         // This object's dtor will aggregate the trust decision for this field into the trust level for the class as a whole.
8313         ExplicitFieldTrustHolder fieldTrust(&explicitClassTrust);
8314
8315         pFD = bmtMFDescs->ppFieldDescList[i];
8316         if (pFD == NULL || pFD->IsStatic())
8317         {
8318             fieldTrust.SetTrust(ExplicitFieldTrust::kNonOverLayed);
8319             continue;
8320         }
8321
8322         // "i" indexes all fields, valueClassCacheIndex indexes non-static fields only. Don't get them confused!
8323         valueClassCacheIndex++;
8324
8325         if (CorTypeInfo::IsObjRef(pFD->GetFieldType()))
8326         {
8327             // Check that the ref offset is pointer aligned
8328             if ((pFD->GetOffset_NoLogging() & ((ULONG)TARGET_POINTER_SIZE - 1)) != 0)
8329             {
8330                 badOffset = pFD->GetOffset_NoLogging();
8331                 fieldTrust.SetTrust(ExplicitFieldTrust::kNone);
8332
8333                 // If we got here, OREF field was not pointer aligned. THROW.
8334                 break;
8335             }
8336             // check if overlaps another object
8337             if (memcmp((void *)&pFieldLayout[pFD->GetOffset_NoLogging()], (void *)isObject, sizeof(isObject)) == 0)
8338             {
8339                 // If we got here, an OREF overlapped another OREF. We permit this but mark the class unverifiable.
8340                 fieldTrust.SetTrust(ExplicitFieldTrust::kLegal);
8341
8342                 if (firstObjectOverlapOffset == ((DWORD)(-1)))
8343                 {
8344                     firstObjectOverlapOffset = pFD->GetOffset_NoLogging();
8345                 }
8346
8347                 continue;
8348             }
8349             // check if is empty at this point
8350             if (memcmp((void *)&pFieldLayout[pFD->GetOffset_NoLogging()], (void *)emptyObject, sizeof(emptyObject)) == 0)
8351             {
8352                 // If we got here, this OREF is overlapping no other fields (yet). Record that these bytes now contain an OREF.
8353                 memset((void *)&pFieldLayout[pFD->GetOffset_NoLogging()], oref, sizeof(isObject));
8354                 fieldTrust.SetTrust(ExplicitFieldTrust::kNonOverLayed);
8355                 continue;
8356             }
8357
8358             // If we got here, the OREF overlaps a non-OREF. THROW.
8359             badOffset = pFD->GetOffset_NoLogging();
8360             fieldTrust.SetTrust(ExplicitFieldTrust::kNone);
8361             break;
8362         }
8363         else
8364         {
8365             UINT fieldSize;
8366             if (pFD->IsByValue())
8367             {
8368                 MethodTable *pByValueMT = pByValueClassCache[valueClassCacheIndex];
8369                 if (pByValueMT->ContainsPointers())
8370                 {
8371                     if ((pFD->GetOffset_NoLogging() & ((ULONG)TARGET_POINTER_SIZE - 1)) == 0)
8372                     {
8373                         ExplicitFieldTrust::TrustLevel trust;
8374                         DWORD firstObjectOverlapOffsetInsideValueClass = ((DWORD)(-1));
8375                         trust = CheckValueClassLayout(pByValueMT, &pFieldLayout[pFD->GetOffset_NoLogging()], &firstObjectOverlapOffsetInsideValueClass);
8376                         fieldTrust.SetTrust(trust);
8377                         if (firstObjectOverlapOffsetInsideValueClass != ((DWORD)(-1)))
8378                         {
8379                             if (firstObjectOverlapOffset == ((DWORD)(-1)))
8380                             {
8381                                 firstObjectOverlapOffset = pFD->GetOffset_NoLogging() + firstObjectOverlapOffsetInsideValueClass;
8382                             }
8383                         }
8384
8385                         if (trust != ExplicitFieldTrust::kNone)
8386                         {
8387                             continue;
8388                         }
8389                         else
8390                         {
8391                             // If we got here, then an OREF inside the valuetype illegally overlapped a non-OREF field. THROW.
8392                             badOffset = pFD->GetOffset_NoLogging();
8393                             break;
8394                         }
8395                     }
8396                     // If we got here, then a valuetype containing an OREF was misaligned.
8397                     badOffset = pFD->GetOffset_NoLogging();
8398                     fieldTrust.SetTrust(ExplicitFieldTrust::kNone);
8399                     break;
8400                 }
8401                 // no pointers so fall through to do standard checking
8402                 fieldSize = pByValueMT->GetNumInstanceFieldBytes();
8403             }
8404             else
8405             {
8406                 // field size temporarily stored in pInterface field
8407                 fieldSize = GetFieldSize(pFD);
8408             }
8409
8410             // If we got here, we are trying to place a non-OREF (or a valuetype composed of non-OREFs.)
8411             // Look for any orefs under this field
8412             BYTE *loc;
8413             if ((loc = (BYTE*)memchr((void*)&pFieldLayout[pFD->GetOffset_NoLogging()], oref, fieldSize)) == NULL)
8414             {
8415                 // If we have a nonoref in the range then we are doing an overlay
8416                 if(memchr((void*)&pFieldLayout[pFD->GetOffset_NoLogging()], nonoref, fieldSize))
8417                 {
8418                     fieldTrust.SetTrust(ExplicitFieldTrust::kVerifiable);
8419                 }
8420                 else
8421                 {
8422                     fieldTrust.SetTrust(ExplicitFieldTrust::kNonOverLayed);
8423                 }
8424                 memset((void*)&pFieldLayout[pFD->GetOffset_NoLogging()], nonoref, fieldSize);
8425                 continue;
8426             }
8427
8428             // If we got here, we tried to place a non-OREF (or a valuetype composed of non-OREFs)
8429             // on top of an OREF. THROW.
8430             badOffset = (UINT)(loc - pFieldLayout);
8431             fieldTrust.SetTrust(ExplicitFieldTrust::kNone);
8432             break;
8433             // anything else is an error
8434         }
8435
8436         // We have to comment out this assert because otherwise, the compiler refuses to build because the _ASSERT is unreachable
8437         // (Thanks for nothing, compiler, that's what the assert is trying to enforce!) But the intent of the assert is correct.
8438         //_ASSERTE(!"You aren't supposed to be here. Some path inside the loop body did not execute an explicit break or continue.");
8439
8440
8441         // If we got here, some code above failed to execute an explicit "break" or "continue." This is a bug! To be safe,
8442         // we will put a catchall "break" here which will cause the typeload to abort (albeit with a probably misleading
8443         // error message.)
8444         break;
8445     } // for(;;)
8446
8447     // We only break out of the loop above if we detected an error.
8448     if (i < bmtMetaData->cFields || !explicitClassTrust.IsLegal())
8449     {
8450         ThrowFieldLayoutError(GetCl(),
8451                               GetModule(),
8452                               badOffset,
8453                               IDS_CLASSLOAD_EXPLICIT_LAYOUT);
8454     }
8455
8456     if (!explicitClassTrust.IsNonOverLayed())
8457     {
8458         SetHasOverLayedFields();
8459     }
8460
8461     if (IsBlittable() || IsManagedSequential())
8462     {
8463         // Bug 849333: We shouldn't update "bmtFP->NumInstanceFieldBytes" 
8464         // for Blittable/ManagedSequential types.  As this will break backward compatiblity
8465         // for the size of types that return true for HasExplicitFieldOffsetLayout()
8466         // 
8467         return;
8468     }
8469
8470     FindPointerSeriesExplicit(instanceSliceSize, pFieldLayout);
8471
8472     // Fixup the offset to include parent as current offsets are relative to instance slice
8473     // Could do this earlier, but it's just easier to assume instance relative for most
8474     // of the earlier calculations
8475
8476     // Instance fields start right after the parent
8477     S_UINT32 dwInstanceSliceOffset = S_UINT32(HasParent() ? GetParentMethodTable()->GetNumInstanceFieldBytes() : 0);
8478     if (bmtGCSeries->numSeries != 0)
8479     {
8480         dwInstanceSliceOffset.AlignUp(TARGET_POINTER_SIZE);
8481     }
8482     if (dwInstanceSliceOffset.IsOverflow())
8483     {
8484         // addition overflow or cast truncation
8485         BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
8486     }
8487
8488     S_UINT32 numInstanceFieldBytes = dwInstanceSliceOffset + S_UINT32(instanceSliceSize);
8489
8490     if (IsValueClass())
8491     {
8492         ULONG clstotalsize;
8493         if (FAILED(GetMDImport()->GetClassTotalSize(GetCl(), &clstotalsize)))
8494         {
8495             clstotalsize = 0;
8496         }
8497         
8498         if (clstotalsize != 0)
8499         {
8500             // size must be large enough to accomodate layout. If not, we use the layout size instead.
8501             if (!numInstanceFieldBytes.IsOverflow() && clstotalsize >= numInstanceFieldBytes.Value())
8502             {
8503                 numInstanceFieldBytes = S_UINT32(clstotalsize);
8504             }
8505         }
8506     }
8507     
8508     // The GC requires that all valuetypes containing orefs be sized to a multiple of TARGET_POINTER_SIZE.
8509     if (bmtGCSeries->numSeries != 0)
8510     {
8511         numInstanceFieldBytes.AlignUp(TARGET_POINTER_SIZE);
8512     }
8513     if (numInstanceFieldBytes.IsOverflow())
8514     {
8515         // addition overflow or cast truncation
8516         BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
8517     }
8518
8519     // Set the total size
8520     bmtFP->NumInstanceFieldBytes = numInstanceFieldBytes.Value();
8521
8522     for (i = 0; i < bmtMetaData->cFields; i++)
8523     {
8524         FieldDesc * pTempFD = bmtMFDescs->ppFieldDescList[i];
8525         if ((pTempFD == NULL) || pTempFD->IsStatic())
8526         {
8527             continue;
8528         }
8529         HRESULT hr = pTempFD->SetOffset(pTempFD->GetOffset_NoLogging() + dwInstanceSliceOffset.Value());
8530         if (FAILED(hr))
8531         {
8532             BuildMethodTableThrowException(hr, *bmtError);
8533         }
8534     }
8535 } // MethodTableBuilder::HandleExplicitLayout
8536
8537 //*******************************************************************************
8538 // make sure that no object fields are overlapped incorrectly, returns S_FALSE if
8539 // there overlap but nothing illegal, S_OK if there is no overlap
8540 /*static*/ ExplicitFieldTrust::TrustLevel MethodTableBuilder::CheckValueClassLayout(MethodTable * pMT, BYTE *pFieldLayout, DWORD *pFirstObjectOverlapOffset)
8541 {
8542     STANDARD_VM_CONTRACT;
8543
8544
8545     *pFirstObjectOverlapOffset = (DWORD)(-1);
8546
8547     // Build a layout of the value class. Don't know the sizes of all the fields easily, but
8548     // do know a) vc is already consistent so don't need to check it's overlaps and
8549     // b) size and location of all objectrefs. So build it by setting all non-oref
8550     // then fill in the orefs later
8551     UINT fieldSize = pMT->GetNumInstanceFieldBytes();
8552     CQuickBytes qb;
8553     BYTE *vcLayout = (BYTE*) qb.AllocThrows(fieldSize * sizeof(BYTE));
8554
8555     memset((void*)vcLayout, nonoref, fieldSize);
8556
8557     // use pointer series to locate the orefs
8558
8559     CGCDesc* map = CGCDesc::GetCGCDescFromMT(pMT);
8560     CGCDescSeries *pSeries = map->GetLowestSeries();
8561
8562     for (SIZE_T j = 0; j < map->GetNumSeries(); j++)
8563     {
8564         CONSISTENCY_CHECK(pSeries <= map->GetHighestSeries());
8565
8566         memset((void*)&vcLayout[pSeries->GetSeriesOffset() - OBJECT_SIZE], oref, pSeries->GetSeriesSize() + pMT->GetBaseSize());
8567         pSeries++;
8568     }
8569
8570
8571     ExplicitClassTrust explicitClassTrust;
8572
8573     for (UINT i=0; i < fieldSize; i++) {
8574
8575         ExplicitFieldTrustHolder fieldTrust(&explicitClassTrust);
8576
8577         if (vcLayout[i] == oref) {
8578             switch (pFieldLayout[i]) {
8579                 // oref <--> empty
8580                 case empty:
8581                     pFieldLayout[i] = oref;
8582                     fieldTrust.SetTrust(ExplicitFieldTrust::kNonOverLayed);
8583                     break;
8584
8585                 // oref <--> nonoref
8586                 case nonoref:
8587                     fieldTrust.SetTrust(ExplicitFieldTrust::kNone);
8588                     break;
8589
8590                 // oref <--> oref
8591                 case oref:
8592                     fieldTrust.SetTrust(ExplicitFieldTrust::kLegal);
8593                     if ((*pFirstObjectOverlapOffset) == ((DWORD)(-1)))
8594                     {
8595                         *pFirstObjectOverlapOffset = (DWORD)i;
8596                     }
8597                     break;
8598
8599                 default:
8600                     _ASSERTE(!"Can't get here.");
8601                 }
8602         } else if (vcLayout[i] == nonoref) {
8603             switch (pFieldLayout[i]) {
8604                 // nonoref <--> empty
8605                 case empty:
8606                     pFieldLayout[i] = nonoref;
8607                     fieldTrust.SetTrust(ExplicitFieldTrust::kNonOverLayed);
8608                     break;
8609
8610                 // nonoref <--> nonoref
8611                 case nonoref:
8612                     fieldTrust.SetTrust(ExplicitFieldTrust::kVerifiable);
8613                     break;
8614
8615                 // nonoref <--> oref
8616                 case oref:
8617                     fieldTrust.SetTrust(ExplicitFieldTrust::kNone);
8618                     break;
8619
8620                 default:
8621                     _ASSERTE(!"Can't get here.");
8622             }
8623         } else {
8624             _ASSERTE(!"Can't get here.");
8625         }
8626     }
8627
8628     return explicitClassTrust.GetTrustLevel();
8629 }
8630
8631
8632
8633
8634
8635
8636
8637 //*******************************************************************************
8638 void MethodTableBuilder::FindPointerSeriesExplicit(UINT instanceSliceSize,
8639                                                    BYTE *pFieldLayout)
8640 {
8641     STANDARD_VM_CONTRACT;
8642
8643
8644     // Allocate a structure to track the series. We know that the worst case is a
8645     // ref-non-ref-non, and since only ref series are recorded and non-ref series
8646     // are skipped, the max number of series is total instance size / 2 / sizeof(ref).
8647     // But watch out for the case where we have e.g. an instanceSlizeSize of 4.
8648     DWORD sz = (instanceSliceSize + (2 * TARGET_POINTER_SIZE) - 1);
8649     bmtGCSeries->pSeries = new bmtGCSeriesInfo::Series[sz/2/ TARGET_POINTER_SIZE];
8650
8651     BYTE *loc = pFieldLayout;
8652     BYTE *layoutEnd = pFieldLayout + instanceSliceSize;
8653     while (loc < layoutEnd)
8654     {
8655         // Find the next OREF entry.
8656         loc = (BYTE*)memchr((void*)loc, oref, layoutEnd-loc);
8657         if (loc == NULL)
8658         {
8659             break;
8660         }
8661
8662         // Find the next non-OREF entry
8663         BYTE *cur = loc;
8664         while(cur < layoutEnd && *cur == oref)
8665         {
8666             cur++;
8667         }
8668
8669         // so we have a GC series at loc for cur-loc bytes
8670         bmtGCSeries->pSeries[bmtGCSeries->numSeries].offset = (DWORD)(loc - pFieldLayout);
8671         bmtGCSeries->pSeries[bmtGCSeries->numSeries].len = (DWORD)(cur - loc);
8672
8673         CONSISTENCY_CHECK(IS_ALIGNED(cur - loc, TARGET_POINTER_SIZE));
8674
8675         bmtGCSeries->numSeries++;
8676         loc = cur;
8677     }
8678
8679     // Calculate the total series count including the parent, if a parent exists.
8680
8681     bmtFP->NumGCPointerSeries = bmtParent->NumParentPointerSeries + bmtGCSeries->numSeries;
8682
8683 }
8684
8685 //*******************************************************************************
8686 VOID 
8687 MethodTableBuilder::HandleGCForExplicitLayout()
8688 {
8689     STANDARD_VM_CONTRACT;
8690
8691     MethodTable *pMT = GetHalfBakedMethodTable();
8692
8693 #ifdef FEATURE_COLLECTIBLE_TYPES
8694     if (bmtFP->NumGCPointerSeries == 0 && pMT->Collectible())
8695     {
8696         // For collectible types, insert empty gc series
8697         CGCDescSeries *pSeries;
8698
8699         CGCDesc::Init( (PVOID) pMT, 1);
8700         pSeries = ((CGCDesc*)pMT)->GetLowestSeries();
8701         pSeries->SetSeriesSize( (size_t) (0) - (size_t) pMT->GetBaseSize());
8702         pSeries->SetSeriesOffset(OBJECT_SIZE);
8703     }
8704     else
8705 #endif // FEATURE_COLLECTIBLE_TYPES
8706     if (bmtFP->NumGCPointerSeries != 0)
8707     {
8708         pMT->SetContainsPointers();
8709
8710         // Copy the pointer series map from the parent
8711         CGCDesc::Init( (PVOID) pMT, bmtFP->NumGCPointerSeries );
8712         if (bmtParent->NumParentPointerSeries != 0)
8713         {
8714             size_t ParentGCSize = CGCDesc::ComputeSize(bmtParent->NumParentPointerSeries);
8715             memcpy( (PVOID) (((BYTE*) pMT) - ParentGCSize),  (PVOID) (((BYTE*) GetParentMethodTable()) - ParentGCSize), ParentGCSize - sizeof(UINT) );
8716
8717         }
8718
8719         UINT32 dwInstanceSliceOffset = AlignUp(HasParent() ? GetParentMethodTable()->GetNumInstanceFieldBytes() : 0, TARGET_POINTER_SIZE);
8720
8721         // Build the pointer series map for this pointers in this instance
8722         CGCDescSeries *pSeries = ((CGCDesc*)pMT)->GetLowestSeries();
8723         for (UINT i=0; i < bmtGCSeries->numSeries; i++) {
8724             // See gcdesc.h for an explanation of why we adjust by subtracting BaseSize
8725             BAD_FORMAT_NOTHROW_ASSERT(pSeries <= CGCDesc::GetCGCDescFromMT(pMT)->GetHighestSeries());
8726
8727             pSeries->SetSeriesSize( (size_t) bmtGCSeries->pSeries[i].len - (size_t) pMT->GetBaseSize() );
8728             pSeries->SetSeriesOffset(bmtGCSeries->pSeries[i].offset + OBJECT_SIZE + dwInstanceSliceOffset);
8729             pSeries++;
8730         }
8731     }
8732
8733     delete [] bmtGCSeries->pSeries;
8734     bmtGCSeries->pSeries = NULL;
8735 } // MethodTableBuilder::HandleGCForExplicitLayout
8736
8737 static 
8738 BOOL 
8739 InsertMethodTable(
8740     MethodTable  *pNew, 
8741     MethodTable **pArray, 
8742     DWORD         nArraySizeMax, 
8743     DWORD        *pNumAssigned)
8744 {
8745     LIMITED_METHOD_CONTRACT;
8746
8747     for (DWORD j = 0; j < (*pNumAssigned); j++)
8748     {
8749         if (pNew == pArray[j])
8750         {
8751 #ifdef _DEBUG
8752             LOG((LF_CLASSLOADER, LL_INFO1000, "GENERICS: Found duplicate interface %s (%p) at position %d out of %d\n", pNew->GetDebugClassName(), pNew, j, *pNumAssigned));
8753 #endif
8754             return pNew->HasInstantiation(); // bail out - we found a duplicate instantiated interface
8755         }
8756         else
8757         {
8758 #ifdef _DEBUG 
8759             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));
8760 #endif
8761         }
8762     }
8763     if (*pNumAssigned >= nArraySizeMax)
8764     {
8765         LOG((LF_CLASSLOADER, LL_INFO1000, "GENERICS: Found interface %s (%p) exceeding size %d of interface array\n", pNew->GetDebugClassName(), pNew, nArraySizeMax));
8766         return TRUE;
8767     }
8768     LOG((LF_CLASSLOADER, LL_INFO1000, "GENERICS: Inserting interface %s (%p) at position %d\n", pNew->GetDebugClassName(), pNew, *pNumAssigned));
8769     pArray[(*pNumAssigned)++] = pNew;
8770     return FALSE;
8771 } // InsertMethodTable
8772
8773
8774 //*******************************************************************************
8775 // --------------------------------------------------------------------------------------------
8776 // Copy virtual slots inherited from parent:
8777 //
8778 // In types created at runtime, inherited virtual slots are initialized using approximate parent 
8779 // during method table building. This method will update them based on the exact parent.
8780 // In types loaded from NGen image, inherited virtual slots from cross-module parents are not 
8781 // initialized. This method will initialize them based on the actually loaded exact parent
8782 // if necessary.
8783 /* static */
8784 void MethodTableBuilder::CopyExactParentSlots(MethodTable *pMT, MethodTable *pApproxParentMT)
8785 {
8786     CONTRACTL
8787     {
8788         STANDARD_VM_CHECK;
8789         PRECONDITION(CheckPointer(pMT));
8790     }
8791     CONTRACTL_END;
8792
8793     if (pMT->IsZapped())
8794         return;
8795
8796     DWORD nParentVirtuals = pMT->GetNumParentVirtuals();
8797     if (nParentVirtuals == 0)
8798         return;
8799
8800     _ASSERTE(nParentVirtuals == pApproxParentMT->GetNumVirtuals());
8801
8802     //
8803     // Update all inherited virtual slots to match exact parent
8804     //
8805
8806     if (!pMT->IsCanonicalMethodTable())
8807     {
8808         //
8809         // Copy all slots for non-canonical methodtables to avoid touching methoddescs.
8810         //
8811         MethodTable * pCanonMT = pMT->GetCanonicalMethodTable();
8812
8813         // Do not write into vtable chunks shared with parent. It would introduce race 
8814         // with code:MethodDesc::SetStableEntryPointInterlocked.
8815         //
8816         // Non-canonical method tables either share everything or nothing so it is sufficient to check
8817         // just the first indirection to detect sharing.
8818         if (pMT->GetVtableIndirections()[0].GetValueMaybeNull() != pCanonMT->GetVtableIndirections()[0].GetValueMaybeNull())
8819         {
8820             MethodTable::MethodDataWrapper hCanonMTData(MethodTable::GetMethodData(pCanonMT, FALSE));
8821             for (DWORD i = 0; i < nParentVirtuals; i++)
8822             {
8823                 pMT->CopySlotFrom(i, hCanonMTData, pCanonMT);
8824             }
8825         }
8826     }
8827     else
8828     {
8829         MethodTable::MethodDataWrapper hMTData(MethodTable::GetMethodData(pMT, FALSE));
8830
8831         MethodTable * pParentMT = pMT->GetParentMethodTable();
8832         MethodTable::MethodDataWrapper hParentMTData(MethodTable::GetMethodData(pParentMT, FALSE));
8833
8834         for (DWORD i = 0; i < nParentVirtuals; i++)
8835         {
8836             // fix up wrongly-inherited method descriptors
8837             MethodDesc* pMD = hMTData->GetImplMethodDesc(i);
8838             CONSISTENCY_CHECK(CheckPointer(pMD));
8839             CONSISTENCY_CHECK(pMD == pMT->GetMethodDescForSlot(i));
8840
8841             if (pMD->GetMethodTable() == pMT)
8842                 continue;
8843
8844             // We need to re-inherit this slot from the exact parent.
8845
8846             DWORD indirectionIndex = MethodTable::GetIndexOfVtableIndirection(i);
8847             if (pMT->GetVtableIndirections()[indirectionIndex].GetValueMaybeNull() == pApproxParentMT->GetVtableIndirections()[indirectionIndex].GetValueMaybeNull())
8848             {
8849                 // The slot lives in a chunk shared from the approximate parent MT
8850                 // If so, we need to change to share the chunk from the exact parent MT
8851
8852 #ifdef FEATURE_PREJIT
8853                 _ASSERTE(MethodTable::CanShareVtableChunksFrom(pParentMT, pMT->GetLoaderModule(), Module::GetPreferredZapModuleForMethodTable(pMT)));
8854 #else
8855                 _ASSERTE(MethodTable::CanShareVtableChunksFrom(pParentMT, pMT->GetLoaderModule()));
8856 #endif
8857
8858                 pMT->GetVtableIndirections()[indirectionIndex].SetValueMaybeNull(pParentMT->GetVtableIndirections()[indirectionIndex].GetValueMaybeNull());
8859
8860                 i = MethodTable::GetEndSlotForVtableIndirection(indirectionIndex, nParentVirtuals) - 1;
8861                 continue;
8862             }
8863
8864             // The slot lives in an unshared chunk. We need to update the slot contents
8865             pMT->CopySlotFrom(i, hParentMTData, pParentMT);
8866         }
8867     }
8868 } // MethodTableBuilder::CopyExactParentSlots
8869
8870 //*******************************************************************************
8871 /* static */
8872 void 
8873 MethodTableBuilder::LoadExactInterfaceMap(MethodTable *pMT)
8874 {
8875     CONTRACTL
8876     {
8877         STANDARD_VM_CHECK;
8878         PRECONDITION(CheckPointer(pMT));
8879     }
8880     CONTRACTL_END;
8881
8882     BOOL hasInstantiatedInterfaces = FALSE;
8883     MethodTable::InterfaceMapIterator it = pMT->IterateInterfaceMap();
8884     while (it.Next())
8885     {
8886         if (it.GetInterface()->HasInstantiation())
8887         {
8888             hasInstantiatedInterfaces = TRUE;
8889             break;
8890         }
8891     }
8892
8893     // If we have some instantiated interfaces, then we have lots more work to do...
8894
8895     // In the worst case we have to use the metadata to
8896     //  (a) load the exact interfaces and determine the order in which they
8897     //      go.  We do those by re-running the interface layout algorithm
8898     //      and using metadata-comparisons to place interfaces in the list.
8899     //  (b) do a check to see if any ambiguity in the interface dispatch map is introduced
8900     //      by the instantiation
8901     // See code:#LoadExactInterfaceMap_Algorithm2
8902     //
8903     // However, we can do something simpler: we just use
8904     // the loaded interface method tables to determine ordering.  This can be done
8905     // if there are no duplicate instantiated interfaces in the interface
8906     // set.
8907     // See code:#LoadExactInterfaceMap_Algorithm1.
8908
8909     if (!hasInstantiatedInterfaces)
8910     {
8911         return;
8912     }
8913
8914     HRESULT hr;
8915     TypeHandle thisTH(pMT);
8916     SigTypeContext typeContext(thisTH);
8917     MethodTable *pParentMT = pMT->GetParentMethodTable();
8918
8919     //#LoadExactInterfaceMap_Algorithm1
8920     // Exact interface instantiation loading TECHNIQUE 1.
8921     // (a) For interfaces inherited from an instantiated parent class, just copy down from exact parent
8922     // (b) Grab newly declared interfaces by loading and then copying down all their inherited parents
8923     // (c) But check for any exact duplicates along the way
8924     // (d) If no duplicates then we can use the computed interface map we've created
8925     // (e) If duplicates found then use the slow metadata-based technique code:#LoadExactInterfaceMap_Algorithm2
8926     DWORD nInterfacesCount = pMT->GetNumInterfaces();
8927     MethodTable **pExactMTs = (MethodTable**) _alloca(sizeof(MethodTable *) * nInterfacesCount);
8928     DWORD nAssigned = 0;
8929     BOOL duplicates = false;
8930     if (pParentMT != NULL)
8931     {
8932         MethodTable::InterfaceMapIterator parentIt = pParentMT->IterateInterfaceMap();
8933         while (parentIt.Next())
8934         {
8935             duplicates |= InsertMethodTable(parentIt.GetInterface(), pExactMTs, nInterfacesCount, &nAssigned);
8936         }
8937     }
8938     InterfaceImplEnum ie(pMT->GetModule(), pMT->GetCl(), NULL);
8939     while ((hr = ie.Next()) == S_OK)
8940     {
8941         MethodTable *pNewIntfMT = ClassLoader::LoadTypeDefOrRefOrSpecThrowing(pMT->GetModule(),
8942                                                                               ie.CurrentToken(),
8943                                                                               &typeContext,
8944                                                                               ClassLoader::ThrowIfNotFound,
8945                                                                               ClassLoader::FailIfUninstDefOrRef,
8946                                                                               ClassLoader::LoadTypes,
8947                                                                               CLASS_LOAD_EXACTPARENTS,
8948                                                                               TRUE).GetMethodTable();
8949
8950         duplicates |= InsertMethodTable(pNewIntfMT, pExactMTs, nInterfacesCount, &nAssigned);
8951         MethodTable::InterfaceMapIterator intIt = pNewIntfMT->IterateInterfaceMap();
8952         while (intIt.Next())
8953         {
8954             duplicates |= InsertMethodTable(intIt.GetInterface(), pExactMTs, nInterfacesCount, &nAssigned);
8955         }
8956     }
8957     if (FAILED(hr))
8958     {
8959         pMT->GetAssembly()->ThrowTypeLoadException(pMT->GetMDImport(), pMT->GetCl(), IDS_CLASSLOAD_BADFORMAT);
8960     }
8961 #ifdef _DEBUG 
8962     duplicates |= EEConfig::GetConfigDWORD_DontUse_(CLRConfig::INTERNAL_AlwaysUseMetadataInterfaceMapLayout, FALSE);
8963     
8964     //#InjectInterfaceDuplicates_LoadExactInterfaceMap
8965     // If we are injecting duplicates also for non-generic interfaces in check builds, we have to use 
8966     // algorithm code:#LoadExactInterfaceMap_Algorithm2.
8967     // Has to be in sync with code:#InjectInterfaceDuplicates_Main.
8968     duplicates |= pMT->Debug_HasInjectedInterfaceDuplicates();
8969 #endif
8970     CONSISTENCY_CHECK(duplicates || (nAssigned == pMT->GetNumInterfaces()));
8971     if (duplicates)
8972     {
8973         //#LoadExactInterfaceMap_Algorithm2
8974         // Exact interface instantiation loading TECHNIQUE 2 - The exact instantiation has caused some duplicates to
8975         // appear in the interface map!  This may not be an error: if the duplicates
8976         // were ones that arose because because of inheritance from
8977         // a parent type then we accept that.  For example
8978         //     class C<T> : I<T>
8979         //     class D<T> : C<T>, I<string>
8980         // is acceptable even when loading D<string>.  Note that in such a case
8981         // there will be two entries for I<string> in the final interface map for D<string>.
8982         // For dispatch the mappings in D take precedence.
8983         //
8984         // However we consider it an error if there is real ambiguity within
8985         // the interface definitions within the one class, e.g.
8986         //     class E<T> : I<T>, I<string>
8987         // In this situation it is not defined how to dispatch calls to I<string>: would
8988         // we use the bindings for I<T> or I<string>?
8989         //
8990         // Because we may had duplicates the interface map we created above may not
8991         // be the correct one: for example for D<string> above we would have computed
8992         // a map with only one entry.  This is incorrect: an exact instantiation's interface
8993         // map must have entries that match the ordering of the interface map in the generic case
8994         // (this is because code:#InterfaceMap_SupersetOfParent).
8995         //
8996         // So, in order to determine how to place the interfaces we need go back to
8997         // the metadata. We also do this to check if the presence of duplicates
8998         // has caused any potential ambiguity, i.e. the E<string> case above.
8999
9000         // First we do a GetCheckpoint for the thread-based allocator.  ExpandExactInheritedInterfaces allocates substitution chains
9001         // on the thread allocator rather than on the stack.
9002         Thread * pThread = GetThread();
9003         CheckPointHolder cph(pThread->m_MarshalAlloc.GetCheckpoint()); //hold checkpoint for autorelease
9004
9005         // ***********************************************************
9006         // ****** This must be consistent with code:ExpandApproxInterface etc. *******
9007         //
9008         // The correlation to ExpandApproxInterfaces etc. simply drops out by how we
9009         // traverse interfaces.
9010         // ***********************************************************
9011
9012         bmtExactInterfaceInfo bmtExactInterface;
9013         bmtExactInterface.pInterfaceSubstitution = new (&pThread->m_MarshalAlloc) Substitution[pMT->GetNumInterfaces()];
9014         bmtExactInterface.pExactMTs = pExactMTs;
9015         bmtExactInterface.nAssigned = 0;
9016         bmtExactInterface.typeContext = typeContext;
9017
9018         // Do the interfaces inherited from a parent class
9019         if ((pParentMT != NULL) && (pParentMT->GetNumInterfaces() > 0))
9020         {
9021             Substitution * pParentSubstForTypeLoad = new (&pThread->m_MarshalAlloc) Substitution(
9022                 pMT->GetSubstitutionForParent(NULL));
9023             Substitution * pParentSubstForComparing = new (&pThread->m_MarshalAlloc) Substitution(
9024                 pMT->GetSubstitutionForParent(NULL));
9025             ExpandExactInheritedInterfaces(
9026                 &bmtExactInterface, 
9027                 pParentMT, 
9028                 pParentSubstForTypeLoad, 
9029                 pParentSubstForComparing);
9030         }
9031 #ifdef _DEBUG
9032         //#ExactInterfaceMap_SupersetOfParent
9033         // Check that parent's interface map is subset of this interface map
9034         // See code:#InterfaceMap_SupersetOfParent
9035         {
9036             _ASSERTE(pParentMT->GetNumInterfaces() == bmtExactInterface.nAssigned);
9037             
9038             MethodTable::InterfaceMapIterator parentInterfacesIterator = pParentMT->IterateInterfaceMap();
9039             UINT32 nInterfaceIndex = 0;
9040             while (parentInterfacesIterator.Next())
9041             {
9042                 if (pMT->IsSharedByGenericInstantiations())
9043                 {   // The type is a canonical instantiation (contains _Canon)
9044                     // The interface instantiations of parent can be different (see 
9045                     // code:#InterfaceMap_CanonicalSupersetOfParent), therefore we cannot compare 
9046                     // MethodTables
9047                     _ASSERTE(parentInterfacesIterator.GetInterfaceInfo()->GetApproxMethodTable(pParentMT->GetLoaderModule())->HasSameTypeDefAs(
9048                         bmtExactInterface.pExactMTs[nInterfaceIndex]));
9049                 }
9050                 else
9051                 {   // It is not canonical instantiation, we can compare MethodTables
9052                     _ASSERTE(parentInterfacesIterator.GetInterface() == bmtExactInterface.pExactMTs[nInterfaceIndex]);
9053                 }
9054                 nInterfaceIndex++;
9055             }
9056             _ASSERTE(nInterfaceIndex == bmtExactInterface.nAssigned);
9057         }
9058 #endif //_DEBUG
9059
9060         // If there are any __Canon instances in the type argument list, then we defer the
9061         // ambiguity checking until an exact instantiation.
9062         if (!pMT->IsSharedByGenericInstantiations())
9063         {
9064             // There are no __Canon types in the instantiation, so do ambiguity check.
9065             bmtInterfaceAmbiguityCheckInfo bmtCheckInfo;
9066             bmtCheckInfo.pMT = pMT;
9067             bmtCheckInfo.ppInterfaceSubstitutionChains = new (&pThread->m_MarshalAlloc) Substitution *[pMT->GetNumInterfaces()];
9068             bmtCheckInfo.ppExactDeclaredInterfaces = new (&pThread->m_MarshalAlloc) MethodTable *[pMT->GetNumInterfaces()];
9069             bmtCheckInfo.nAssigned = 0;
9070             bmtCheckInfo.typeContext = typeContext;
9071             MethodTableBuilder::InterfacesAmbiguityCheck(&bmtCheckInfo, pMT->GetModule(), pMT->GetCl(), NULL);
9072         }
9073
9074         // OK, there is no ambiguity amongst the instantiated interfaces declared on this class.
9075         MethodTableBuilder::ExpandExactDeclaredInterfaces(
9076             &bmtExactInterface, 
9077             pMT->GetModule(), 
9078             pMT->GetCl(), 
9079             NULL, 
9080             NULL 
9081             COMMA_INDEBUG(pMT));
9082         CONSISTENCY_CHECK(bmtExactInterface.nAssigned == pMT->GetNumInterfaces());
9083         
9084         // We cannot process interface duplicates on types with __Canon. The duplicates are processed on 
9085         // exact types only
9086         if (!pMT->IsSharedByGenericInstantiations())
9087         {
9088             // Process all pairs of duplicates in the interface map:
9089             //     i.e. If there are 3 duplicates of the same interface at indexes: i1, i2 and i3, then 
9090             //     process pairs of indexes [i1,i2], [i1,i3] and [i2,i3].
9091             //  - Update 'declared on type' flag for those interfaces which duplicate is 'declared on type'
9092             //  - Check interface method implementation ambiguity code:#DuplicateInterface_MethodAmbiguity
9093             for (DWORD nOriginalIndex = 0; nOriginalIndex < nInterfacesCount; nOriginalIndex++)
9094             {
9095                 // Search for duplicates further in the interface map
9096                 for (DWORD nDuplicateIndex = nOriginalIndex + 1; nDuplicateIndex < nInterfacesCount; nDuplicateIndex++)
9097                 {
9098                     if (pExactMTs[nOriginalIndex] != pExactMTs[nDuplicateIndex])
9099                     {   // It's not a duplicate of original interface, skip it
9100                         continue;
9101                     }
9102                     // We found a duplicate
9103                     
9104                     // Set 'declared on type' flag if either original or duplicate interface is 
9105                     // 'declared on type'
9106                     if (pMT->IsInterfaceDeclaredOnClass(nOriginalIndex) || 
9107                         pMT->IsInterfaceDeclaredOnClass(nDuplicateIndex))
9108                     {
9109                         // 
9110                         // Note that both checks are needed:
9111                         //     A<T> : I<T>
9112                         //     B<T,U> : A<T>, I<U>
9113                         //     C<T,U> : B<T,U>, I<T>   // Reimplements interface from A<T>
9114                         // After code:BuildMethodTableThrowing algorithm, this will happen:
9115                         // B<int,int> will have interface map similar to B<T,U>:
9116                         //     I<int> ... not 'declared on type'
9117                         //     I<int> ... 'declared on type'
9118                         // C<int,int> will have interface map similar to C<T,U>:
9119                         //     I<int> ... 'declared on type'
9120                         //     I<int> ... not 'declared on type'
9121                         // 
9122                         
9123                         pMT->SetInterfaceDeclaredOnClass(nOriginalIndex);
9124                         pMT->SetInterfaceDeclaredOnClass(nDuplicateIndex);
9125                     }
9126                     
9127                     //#DuplicateInterface_MethodAmbiguity
9128                     // 
9129                     // In the ideal world we would now check for interface method implementation 
9130                     // ambiguity in the instantiation, but that would be a technical breaking change 
9131                     // (against 2.0 RTM/SP1).
9132                     // Therefore we ALLOW when interface method is implemented twice through this 
9133                     // original and duplicate interface.
9134                     // 
9135                     // This ambiguity pattern is therefore ALLOWED (can be expressed only in IL, not in C#):
9136                     //     I<T>
9137                     //         void Print(T t);
9138                     //     A<T> : I<T>    // abstract class
9139                     //     B<T,U> : A<T>, I<U>
9140                     //         void Print(T t) { ... }
9141                     //         void Print(U u) { ... }
9142                     //     Now B<int,int> has 2 implementations of I<int>.Print(int), while B<int,char> is 
9143                     //     fine. Therefore an instantiation can introduce ambiguity.
9144                     
9145 #if 0 // Removing this code for now as it is a technical breaking change (against CLR 2.0 RTM/SP1).
9146       // We might decide later that we want to take this breaking change.
9147                     // 
9148                     // Note that dispatch map entries are sorted by interface index and then interface 
9149                     // method slot index.
9150                     // 
9151                     DispatchMapTypeID originalTypeID = DispatchMapTypeID::InterfaceClassID(nOriginalIndex);
9152                     DispatchMap::EncodedMapIterator originalIt(pMT);
9153                     // Find first entry for original interface
9154                     while (originalIt.IsValid())
9155                     {
9156                         DispatchMapEntry *pEntry = originalIt.Entry();
9157                         if (pEntry->GetTypeID().ToUINT32() >= originalTypeID.ToUINT32())
9158                         {   // Found the place where original interface entries should be (dispatch map is 
9159                             // sorted)
9160                             break;
9161                         }
9162                         originalIt.Next();
9163                     }
9164                     
9165                     DispatchMapTypeID duplicateTypeID = DispatchMapTypeID::InterfaceClassID(nDuplicateIndex);
9166                     DispatchMap::EncodedMapIterator duplicateIt(pMT);
9167                     // Find first entry for duplicate interface
9168                     while (duplicateIt.IsValid())
9169                     {
9170                         DispatchMapEntry *pEntry = duplicateIt.Entry();
9171                         if (pEntry->GetTypeID().ToUINT32() >= duplicateTypeID.ToUINT32())
9172                         {   // Found the place where original interface entries should be (dispatch map is 
9173                             // sorted)
9174                             break;
9175                         }
9176                         duplicateIt.Next();
9177                     }
9178                     
9179                     // Compare original and duplicate interface entries in the dispatch map if they contain 
9180                     // different implementation for the same interface method
9181                     for (;;)
9182                     {
9183                         if (!originalIt.IsValid() || !duplicateIt.IsValid())
9184                         {   // We reached end of one dispatch map iterator
9185                             break;
9186                         }
9187                         DispatchMapEntry *pOriginalEntry = originalIt.Entry();
9188                         if (pOriginalEntry->GetTypeID().ToUINT32() != originalTypeID.ToUINT32())
9189                         {   // We reached behind original interface entries
9190                             break;
9191                         }
9192                         DispatchMapEntry *pDuplicateEntry = duplicateIt.Entry();
9193                         if (pDuplicateEntry->GetTypeID().ToUINT32() != duplicateTypeID.ToUINT32())
9194                         {   // We reached behind duplicate interface entries
9195                             break;
9196                         }
9197                         
9198                         if (pOriginalEntry->GetSlotNumber() == pDuplicateEntry->GetSlotNumber())
9199                         {   // Found duplicate implementation of interface method
9200                             if (pOriginalEntry->GetTargetSlotNumber() != pDuplicateEntry->GetTargetSlotNumber())
9201                             {   // Implementation of the slots is different
9202                                 bmtErrorInfo bmtError;
9203                                 
9204                                 bmtError.pModule = pMT->GetModule();
9205                                 bmtError.cl = pMT->GetCl();
9206                                 bmtError.resIDWhy = IDS_CLASSLOAD_MI_MULTIPLEOVERRIDES;
9207                                 bmtError.szMethodNameForError = NULL;
9208                                 bmtError.pThrowable = NULL;
9209                                 
9210                                 MethodDesc *pMD = pMT->GetMethodDescForSlot(pDuplicateEntry->GetTargetSlotNumber());
9211                                 bmtError.dMethodDefInError = pMD->GetMemberDef();
9212                                 
9213                                 BuildMethodTableThrowException(COR_E_TYPELOAD, bmtError);
9214                             }
9215                             // The method is implemented by the same slot on both interfaces (original and 
9216                             // duplicate)
9217                             
9218                             // Process next dispatch map entry
9219                             originalIt.Next();
9220                             duplicateIt.Next();
9221                             continue;
9222                         }
9223                         // Move iterator representing smaller interface method slot index (the dispatch map 
9224                         // is sorted by slot indexes)
9225                         if (pOriginalEntry->GetSlotNumber() < pDuplicateEntry->GetSlotNumber())
9226                         {
9227                             originalIt.Next();
9228                             continue;
9229                         }
9230                         _ASSERTE(pOriginalEntry->GetSlotNumber() > pDuplicateEntry->GetSlotNumber());
9231                         duplicateIt.Next();
9232                     }
9233 #endif //0
9234                 }
9235                 // All duplicates of this original interface were processed
9236             }
9237             // All pairs of duplicates in the interface map are processed
9238         }
9239     }
9240     // Duplicates in the interface map are resolved
9241     
9242     // OK, if we've got this far then pExactMTs should now hold the array of exact instantiated interfaces.
9243     MethodTable::InterfaceMapIterator thisIt = pMT->IterateInterfaceMap();
9244     DWORD i = 0;
9245     while (thisIt.Next())
9246     {
9247 #ifdef _DEBUG 
9248         MethodTable*pOldMT = thisIt.GetInterface();
9249         MethodTable *pNewMT = pExactMTs[i];
9250         CONSISTENCY_CHECK(pOldMT->HasSameTypeDefAs(pNewMT));
9251 #endif // _DEBUG
9252         thisIt.SetInterface(pExactMTs[i]);
9253         i++;
9254     }
9255
9256 } // MethodTableBuilder::LoadExactInterfaceMap
9257
9258 //*******************************************************************************
9259 void 
9260 MethodTableBuilder::ExpandExactInheritedInterfaces(
9261     bmtExactInterfaceInfo * bmtInfo, 
9262     MethodTable *           pMT, 
9263     const Substitution *    pSubstForTypeLoad, 
9264     Substitution *          pSubstForComparing)
9265 {
9266     STANDARD_VM_CONTRACT;
9267
9268     MethodTable *pParentMT = pMT->GetParentMethodTable();
9269     
9270     // Backup type's substitution chain for comparing interfaces
9271     Substitution substForComparingBackup = *pSubstForComparing;
9272     // Make type an open type for comparing interfaces
9273     *pSubstForComparing = Substitution();
9274     
9275     if (pParentMT)
9276     {
9277         // Chain parent's substitution for exact type load
9278         Substitution * pParentSubstForTypeLoad = new (&GetThread()->m_MarshalAlloc) Substitution(
9279             pMT->GetSubstitutionForParent(pSubstForTypeLoad));
9280         
9281         // Chain parent's substitution for comparing interfaces (note that this type is temporarily 
9282         // considered as open type)
9283         Substitution * pParentSubstForComparing = new (&GetThread()->m_MarshalAlloc) Substitution(
9284             pMT->GetSubstitutionForParent(pSubstForComparing));
9285         
9286         ExpandExactInheritedInterfaces(
9287             bmtInfo, 
9288             pParentMT, 
9289             pParentSubstForTypeLoad, 
9290             pParentSubstForComparing);
9291     }
9292     ExpandExactDeclaredInterfaces(
9293         bmtInfo, 
9294         pMT->GetModule(), 
9295         pMT->GetCl(), 
9296         pSubstForTypeLoad, 
9297         pSubstForComparing 
9298         COMMA_INDEBUG(pMT));
9299     
9300     // Restore type's subsitution chain for comparing interfaces
9301     *pSubstForComparing = substForComparingBackup;
9302 } // MethodTableBuilder::ExpandExactInheritedInterfaces
9303
9304 //*******************************************************************************
9305 /* static */
9306 void 
9307 MethodTableBuilder::ExpandExactDeclaredInterfaces(
9308     bmtExactInterfaceInfo *     bmtInfo, 
9309     Module *                    pModule, 
9310     mdToken                     typeDef, 
9311     const Substitution *        pSubstForTypeLoad, 
9312     Substitution *              pSubstForComparing 
9313     COMMA_INDEBUG(MethodTable * dbg_pClassMT))
9314 {
9315     STANDARD_VM_CONTRACT;
9316
9317     HRESULT hr;
9318     InterfaceImplEnum ie(pModule, typeDef, NULL);
9319     while ((hr = ie.Next()) == S_OK)
9320     {
9321         MethodTable * pInterface = ClassLoader::LoadTypeDefOrRefOrSpecThrowing(
9322             pModule, 
9323             ie.CurrentToken(), 
9324             &bmtInfo->typeContext,
9325             ClassLoader::ThrowIfNotFound,
9326             ClassLoader::FailIfUninstDefOrRef,
9327             ClassLoader::LoadTypes,
9328             CLASS_LOAD_EXACTPARENTS,
9329             TRUE,
9330             pSubstForTypeLoad).GetMethodTable();
9331         
9332         Substitution ifaceSubstForTypeLoad(ie.CurrentToken(), pModule, pSubstForTypeLoad);
9333         Substitution ifaceSubstForComparing(ie.CurrentToken(), pModule, pSubstForComparing);
9334         ExpandExactInterface(
9335             bmtInfo, 
9336             pInterface, 
9337             &ifaceSubstForTypeLoad, 
9338             &ifaceSubstForComparing 
9339             COMMA_INDEBUG(dbg_pClassMT));
9340     }
9341     if (FAILED(hr))
9342     {
9343         pModule->GetAssembly()->ThrowTypeLoadException(pModule->GetMDImport(), typeDef, IDS_CLASSLOAD_BADFORMAT);
9344     }
9345 } // MethodTableBuilder::ExpandExactDeclaredInterfaces
9346
9347 //*******************************************************************************
9348 void 
9349 MethodTableBuilder::ExpandExactInterface(
9350     bmtExactInterfaceInfo *     bmtInfo, 
9351     MethodTable *               pIntf, 
9352     const Substitution *        pSubstForTypeLoad_OnStack,   // Allocated on stack!
9353     const Substitution *        pSubstForComparing_OnStack   // Allocated on stack!
9354     COMMA_INDEBUG(MethodTable * dbg_pClassMT))
9355 {
9356     STANDARD_VM_CONTRACT;
9357
9358     // ****** This must be consistent with code:MethodTableBuilder::ExpandApproxInterface ******
9359
9360     // Is it already present according to the "generic" layout of the interfaces.
9361     // Note we use exactly the same algorithm as when we
9362     // determined the layout of the interface map for the "generic" version of the class.
9363     for (DWORD i = 0; i < bmtInfo->nAssigned; i++)
9364     {
9365         // Type Equivalence is not respected for this comparision as you can have multiple type equivalent interfaces on a class
9366         TokenPairList newVisited = TokenPairList::AdjustForTypeEquivalenceForbiddenScope(NULL);
9367         if (MetaSig::CompareTypeDefsUnderSubstitutions(bmtInfo->pExactMTs[i],
9368                                                        pIntf,
9369                                                        &bmtInfo->pInterfaceSubstitution[i],
9370                                                        pSubstForComparing_OnStack,
9371                                                        &newVisited))
9372         {
9373 #ifdef _DEBUG
9374             //#InjectInterfaceDuplicates_ExactInterfaces
9375             // We will inject duplicate interfaces in check builds.
9376             // Has to be in sync with code:#InjectInterfaceDuplicates_Main.
9377             if (dbg_pClassMT->Debug_HasInjectedInterfaceDuplicates())
9378             {   // Just pretend we didn't find this match
9379                 break;
9380             }
9381 #endif //_DEBUG
9382             return; // found it, don't add it again
9383         }
9384     }
9385
9386     // Add the interface and its sub-interfaces
9387     DWORD n = bmtInfo->nAssigned;
9388     bmtInfo->pExactMTs[n] = pIntf;
9389     bmtInfo->pInterfaceSubstitution[n] = *pSubstForComparing_OnStack;
9390     bmtInfo->nAssigned++;
9391     
9392     Substitution * pSubstForTypeLoad = new (&GetThread()->m_MarshalAlloc) Substitution(*pSubstForTypeLoad_OnStack);
9393     
9394     ExpandExactDeclaredInterfaces(
9395         bmtInfo, 
9396         pIntf->GetModule(), 
9397         pIntf->GetCl(), 
9398         pSubstForTypeLoad, 
9399         &bmtInfo->pInterfaceSubstitution[n] 
9400         COMMA_INDEBUG(dbg_pClassMT));
9401 } // MethodTableBuilder::ExpandExactInterface
9402
9403 //*******************************************************************************
9404 /* static */
9405 void MethodTableBuilder::InterfacesAmbiguityCheck(bmtInterfaceAmbiguityCheckInfo *bmtCheckInfo,
9406                                                   Module *pModule,
9407                                                   mdToken typeDef,
9408                                                   const Substitution *pSubstChain)
9409 {
9410     STANDARD_VM_CONTRACT;
9411
9412     HRESULT hr;
9413     InterfaceImplEnum ie(pModule, typeDef, pSubstChain);
9414     while ((hr = ie.Next()) == S_OK)
9415     {
9416         MethodTable *pInterface =
9417             ClassLoader::LoadTypeDefOrRefOrSpecThrowing(pModule, ie.CurrentToken(),
9418                                                         &bmtCheckInfo->typeContext,
9419                                                         ClassLoader::ThrowIfNotFound,
9420                                                         ClassLoader::FailIfUninstDefOrRef,
9421                                                         ClassLoader::LoadTypes,
9422                                                         CLASS_LOAD_EXACTPARENTS,
9423                                                         TRUE,
9424                                                         pSubstChain).GetMethodTable();
9425         InterfaceAmbiguityCheck(bmtCheckInfo, ie.CurrentSubst(), pInterface);
9426     }
9427     if (FAILED(hr))
9428     {
9429         pModule->GetAssembly()->ThrowTypeLoadException(pModule->GetMDImport(), typeDef, IDS_CLASSLOAD_BADFORMAT);
9430     }
9431 }
9432
9433 //*******************************************************************************
9434 void MethodTableBuilder::InterfaceAmbiguityCheck(bmtInterfaceAmbiguityCheckInfo *bmtCheckInfo,
9435                                                  const Substitution *pItfSubstChain,
9436                                                  MethodTable *pIntf)
9437 {
9438     STANDARD_VM_CONTRACT;
9439
9440     // Is it already in the generic version of the freshly declared interfaces. We
9441     // do this based on metadata, i.e. via the substitution chains.
9442     // Note we use exactly the same algorithm as when we
9443     // determined the layout of the interface map for the "generic" version of the class.
9444     for (DWORD i = 0; i < bmtCheckInfo->nAssigned; i++)
9445     {
9446         // Type Equivalence is not respected for this comparision as you can have multiple type equivalent interfaces on a class
9447         TokenPairList newVisited = TokenPairList::AdjustForTypeEquivalenceForbiddenScope(NULL);
9448         if (MetaSig::CompareTypeDefsUnderSubstitutions(bmtCheckInfo->ppExactDeclaredInterfaces[i],
9449                                                        pIntf,
9450                                                        bmtCheckInfo->ppInterfaceSubstitutionChains[i],
9451                                                        pItfSubstChain,
9452                                                        &newVisited))
9453             return; // found it, don't add it again
9454     }
9455
9456     // OK, so it isn't a duplicate based on the generic IL, now check if the instantiation
9457     // makes it a duplicate.
9458     for (DWORD i = 0; i < bmtCheckInfo->nAssigned; i++)
9459     {
9460         if (bmtCheckInfo->ppExactDeclaredInterfaces[i] == pIntf)
9461         {
9462                 bmtCheckInfo->pMT->GetModule()->GetAssembly()->ThrowTypeLoadException(bmtCheckInfo->pMT->GetMDImport(),
9463                                                                                       bmtCheckInfo->pMT->GetCl(),
9464                                                                                       IDS_CLASSLOAD_OVERLAPPING_INTERFACES);
9465         }
9466     }
9467
9468     DWORD n = bmtCheckInfo->nAssigned;
9469     bmtCheckInfo->ppExactDeclaredInterfaces[n] = pIntf;
9470     bmtCheckInfo->ppInterfaceSubstitutionChains[n] = new (&GetThread()->m_MarshalAlloc) Substitution[pItfSubstChain->GetLength()];
9471     pItfSubstChain->CopyToArray(bmtCheckInfo->ppInterfaceSubstitutionChains[n]);
9472
9473     bmtCheckInfo->nAssigned++;
9474     InterfacesAmbiguityCheck(bmtCheckInfo,pIntf->GetModule(),pIntf->GetCl(),pItfSubstChain);
9475 }
9476
9477
9478 //*******************************************************************************
9479 void MethodTableBuilder::CheckForSystemTypes()
9480 {
9481     STANDARD_VM_CONTRACT;
9482
9483     LPCUTF8 name, nameSpace;
9484
9485     MethodTable * pMT = GetHalfBakedMethodTable();
9486     EEClass * pClass = GetHalfBakedClass();
9487
9488     // We can exit early for generic types - there are just a few cases to check for.
9489     if (bmtGenerics->HasInstantiation())
9490     {
9491         if (pMT->IsIntrinsicType() && pClass->HasLayout())
9492         {
9493             if (FAILED(GetMDImport()->GetNameOfTypeDef(GetCl(), &name, &nameSpace)))
9494             {
9495                 BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
9496             }
9497
9498             if (strcmp(nameSpace, g_IntrinsicsNS) == 0)
9499             {
9500                 EEClassLayoutInfo * pLayout = pClass->GetLayoutInfo();
9501
9502                 // The SIMD Hardware Intrinsic types correspond to fundamental data types in the underlying ABIs:
9503                 // * Vector64<T>:  __m64
9504                 // * Vector128<T>: __m128
9505                 // * Vector256<T>: __m256
9506
9507                 // These __m128 and __m256 types, among other requirements, are special in that they must always
9508                 // be aligned properly.
9509
9510                 if (IsCompilationProcess())
9511                 {
9512                     // Disable AOT compiling for the SIMD hardware intrinsic types. These types require special
9513                     // ABI handling as they represent fundamental data types (__m64, __m128, and __m256) and not
9514                     // aggregate or union types. See https://github.com/dotnet/coreclr/issues/15943
9515                     //
9516                     // Once they are properly handled according to the ABI requirements, we can remove this check
9517                     // and allow them to be used in crossgen/AOT scenarios.
9518                     COMPlusThrow(kTypeLoadException, IDS_EE_HWINTRINSIC_NGEN_DISALLOWED);
9519                 }
9520
9521                 if (strcmp(name, g_Vector64Name) == 0)
9522                 {
9523                     // The System V ABI for i386 defaults to 8-byte alignment for __m64, except for parameter passing,
9524                     // where it has an alignment of 4.
9525
9526                     pLayout->m_LargestAlignmentRequirementOfAllMembers        = 8; // sizeof(__m64)
9527                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 8; // sizeof(__m64)
9528                 }
9529                 else if (strcmp(name, g_Vector128Name) == 0)
9530                 {
9531     #ifdef _TARGET_ARM_
9532                     // The Procedure Call Standard for ARM defaults to 8-byte alignment for __m128
9533
9534                     pLayout->m_LargestAlignmentRequirementOfAllMembers        = 8;
9535                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 8;
9536     #else
9537                     pLayout->m_LargestAlignmentRequirementOfAllMembers        = 16; // sizeof(__m128)
9538                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 16; // sizeof(__m128)
9539     #endif // _TARGET_ARM_
9540                 }
9541                 else if (strcmp(name, g_Vector256Name) == 0)
9542                 {
9543     #ifdef _TARGET_ARM_
9544                     // No such type exists for the Procedure Call Standard for ARM. We will default
9545                     // to the same alignment as __m128, which is supported by the ABI.
9546
9547                     pLayout->m_LargestAlignmentRequirementOfAllMembers        = 8;
9548                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 8;
9549     #elif defined(_TARGET_ARM64_)
9550                     // The Procedure Call Standard for ARM 64-bit (with SVE support) defaults to
9551                     // 16-byte alignment for __m256.
9552
9553                     pLayout->m_LargestAlignmentRequirementOfAllMembers        = 16;
9554                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 16;
9555     #else
9556                     pLayout->m_LargestAlignmentRequirementOfAllMembers        = 32; // sizeof(__m256)
9557                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 32; // sizeof(__m256)
9558     #endif // _TARGET_ARM_ elif _TARGET_ARM64_
9559                 }
9560                 else
9561                 {
9562                     // These types should be handled or explicitly skipped below to ensure that we don't
9563                     // miss adding required ABI support for future types.
9564
9565                     _ASSERTE_MSG(FALSE, "Unhandled Hardware Intrinsic Type.");
9566                 }
9567
9568                 return;
9569             }
9570         }
9571
9572         if (g_pNullableClass != NULL)
9573         {
9574             _ASSERTE(g_pByReferenceClass != NULL);
9575             _ASSERTE(g_pByReferenceClass->IsByRefLike());
9576
9577 #ifdef _TARGET_X86_
9578             if (GetCl() == g_pByReferenceClass->GetCl())
9579             {
9580                 // x86 by default treats the type of ByReference<T> as the actual type of its IntPtr field, see calls to
9581                 // ComputeInternalCorElementTypeForValueType in this file. This is a special case where the struct needs to be
9582                 // treated as a value type so that its field can be considered as a byref pointer.
9583                 _ASSERTE(pMT->GetFlag(MethodTable::enum_flag_Category_Mask) == MethodTable::enum_flag_Category_PrimitiveValueType);
9584                 pMT->ClearFlag(MethodTable::enum_flag_Category_Mask);
9585                 pMT->SetInternalCorElementType(ELEMENT_TYPE_VALUETYPE);
9586                 return;
9587             }
9588 #endif
9589
9590             _ASSERTE(g_pNullableClass->IsNullable());
9591
9592             // Pre-compute whether the class is a Nullable<T> so that code:Nullable::IsNullableType is efficient
9593             // This is useful to the performance of boxing/unboxing a Nullable
9594             if (GetCl() == g_pNullableClass->GetCl())
9595                 pMT->SetIsNullable();
9596
9597             return;
9598         }
9599     }
9600
9601     if (IsNested() || IsEnum())
9602         return;
9603
9604     if (FAILED(GetMDImport()->GetNameOfTypeDef(GetCl(), &name, &nameSpace)))
9605     {
9606         BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
9607     }
9608
9609     if (IsValueClass())
9610     {
9611         //
9612         // Value types 
9613         // 
9614
9615         // All special value types are in the system namespace
9616         if (strcmp(nameSpace, g_SystemNS) != 0)
9617             return;
9618
9619         // Check if it is a primitive type 
9620         CorElementType type = CorTypeInfo::FindPrimitiveType(name);
9621         if (type != ELEMENT_TYPE_END)
9622         {
9623             pMT->SetInternalCorElementType(type);
9624             pMT->SetIsTruePrimitive();
9625
9626 #if defined(_TARGET_X86_) && defined(UNIX_X86_ABI)
9627             switch (type)
9628             {
9629                 // The System V ABI for i386 defines different packing for these types.
9630
9631                 case ELEMENT_TYPE_I8:
9632                 case ELEMENT_TYPE_U8:
9633                 case ELEMENT_TYPE_R8:
9634                 {
9635                     EEClassLayoutInfo * pLayout = pClass->GetLayoutInfo();
9636                     pLayout->m_LargestAlignmentRequirementOfAllMembers        = 4;
9637                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 4;
9638                     break;
9639                 }
9640
9641                 default:
9642                     break;
9643             }
9644 #endif // _TARGET_X86_ && UNIX_X86_ABI
9645
9646 #ifdef _DEBUG 
9647             if (FAILED(GetMDImport()->GetNameOfTypeDef(GetCl(), &name, &nameSpace)))
9648             {
9649                 name = nameSpace = "Invalid TypeDef record";
9650             }
9651             LOG((LF_CLASSLOADER, LL_INFO10000, "%s::%s marked as primitive type %i\n", nameSpace, name, type));
9652 #endif // _DEBUG
9653         }
9654         else if (strcmp(name, g_NullableName) == 0)
9655         {
9656             pMT->SetIsNullable();
9657         }
9658 #ifdef _TARGET_X86_
9659         else if (strcmp(name, g_ByReferenceName) == 0)
9660         {
9661             // x86 by default treats the type of ByReference<T> as the actual type of its IntPtr field, see calls to
9662             // ComputeInternalCorElementTypeForValueType in this file. This is a special case where the struct needs to be
9663             // treated as a value type so that its field can be considered as a byref pointer.
9664             _ASSERTE(pMT->GetFlag(MethodTable::enum_flag_Category_Mask) == MethodTable::enum_flag_Category_PrimitiveValueType);
9665             pMT->ClearFlag(MethodTable::enum_flag_Category_Mask);
9666             pMT->SetInternalCorElementType(ELEMENT_TYPE_VALUETYPE);
9667         }
9668 #endif
9669 #ifndef _TARGET_X86_ 
9670         else if (strcmp(name, g_RuntimeArgumentHandleName) == 0)
9671         {
9672             pMT->SetInternalCorElementType (ELEMENT_TYPE_I);
9673         }
9674         else if (strcmp(name, g_RuntimeMethodHandleInternalName) == 0)
9675         {
9676             pMT->SetInternalCorElementType (ELEMENT_TYPE_I);
9677         }
9678 #endif
9679 #if defined(ALIGN_ACCESS) || defined(FEATURE_64BIT_ALIGNMENT)
9680         else if (strcmp(name, g_DecimalName) == 0)
9681         {
9682             // This is required because native layout of System.Decimal causes it to be aligned
9683             // differently to the layout of the native DECIMAL structure, which will cause
9684             // data misalignent exceptions if Decimal is embedded in another type.
9685
9686             EEClassLayoutInfo* pLayout = pClass->GetLayoutInfo();
9687             pLayout->m_LargestAlignmentRequirementOfAllMembers        = sizeof(ULONGLONG);
9688             pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = sizeof(ULONGLONG);
9689
9690 #ifdef FEATURE_64BIT_ALIGNMENT
9691             // Also need to mark the type so it will be allocated on a 64-bit boundary for
9692             // platforms that won't do this naturally.
9693             SetAlign8Candidate();
9694 #endif
9695         }
9696 #endif // ALIGN_ACCESS || FEATURE_64BIT_ALIGNMENT
9697     }
9698     else
9699     {
9700         //
9701         // Reference types
9702         // 
9703         if (strcmp(name, g_StringName) == 0 && strcmp(nameSpace, g_SystemNS) == 0)
9704         {
9705             // Strings are not "normal" objects, so we need to mess with their method table a bit
9706             // so that the GC can figure out how big each string is...
9707             DWORD baseSize = StringObject::GetBaseSize();
9708             pMT->SetBaseSize(baseSize);
9709
9710             GetHalfBakedClass()->SetBaseSizePadding(baseSize - bmtFP->NumInstanceFieldBytes);
9711
9712             pMT->SetComponentSize(2);
9713         }
9714 #ifdef FEATURE_UTF8STRING
9715         else if (strcmp(name, g_Utf8StringName) == 0 && strcmp(nameSpace, g_SystemNS) == 0)
9716         {
9717             // Utf8Strings are not "normal" objects, so we need to mess with their method table a bit
9718             // so that the GC can figure out how big each string is...
9719             DWORD baseSize = Utf8StringObject::GetBaseSize();
9720             pMT->SetBaseSize(baseSize); // NULL character included
9721
9722             GetHalfBakedClass()->SetBaseSizePadding(baseSize - bmtFP->NumInstanceFieldBytes);
9723
9724             pMT->SetComponentSize(1);
9725         }
9726 #endif // FEATURE_UTF8STRING
9727         else if (strcmp(name, g_CriticalFinalizerObjectName) == 0 && strcmp(nameSpace, g_ConstrainedExecutionNS) == 0)
9728         {
9729             // To introduce a class with a critical finalizer,
9730             // we'll set the bit here.
9731             pMT->SetHasCriticalFinalizer();
9732         }
9733 #ifdef FEATURE_COMINTEROP 
9734         else
9735         {
9736             bool bIsComObject = false;
9737             bool bIsRuntimeClass = false;
9738
9739             if (strcmp(name, g_ComObjectName) == 0 && strcmp(nameSpace, g_SystemNS) == 0)
9740                 bIsComObject = true;
9741             
9742             if (strcmp(name, g_RuntimeClassName) == 0 && strcmp(nameSpace, g_WinRTNS) == 0)
9743                 bIsRuntimeClass = true;
9744
9745             if (bIsComObject || bIsRuntimeClass)
9746             {
9747                 // Make System.__ComObject/System.Runtime.InteropServices.WindowsRuntime.RuntimeClass a ComImport type
9748                 // We can't do it using attribute as C# won't allow putting code in ComImport types
9749                 pMT->SetComObjectType();
9750
9751                 // COM objects need an optional field on the EEClass, so ensure this class instance has allocated
9752                 // the optional field descriptor.
9753                 EnsureOptionalFieldsAreAllocated(pClass, m_pAllocMemTracker, GetLoaderAllocator()->GetLowFrequencyHeap());            
9754             }            
9755             
9756             if (bIsRuntimeClass)            
9757             {
9758                 // Note that we set it here to avoid type loader considering RuntimeClass as a normal WindowsImportType 
9759                 // as functions in RuntimeClass doesn't go through COM interop
9760                 GetHalfBakedClass()->SetProjectedFromWinRT();
9761             }
9762         }
9763 #endif // FEATURE_COMINTEROP
9764     }
9765 }
9766
9767 //==========================================================================================
9768 // Helper to create a new method table. This is the only
9769 // way to allocate a new MT. Don't try calling new / ctor.
9770 // Called from SetupMethodTable
9771 // This needs to be kept consistent with MethodTable::GetSavedExtent()
9772 MethodTable * MethodTableBuilder::AllocateNewMT(Module *pLoaderModule,
9773                                          DWORD dwVtableSlots,
9774                                          DWORD dwVirtuals,
9775                                          DWORD dwGCSize,
9776                                          DWORD dwNumInterfaces,
9777                                          DWORD dwNumDicts,
9778                                          DWORD cbInstAndDict,
9779                                          MethodTable *pMTParent,
9780                                          ClassLoader *pClassLoader,
9781                                          LoaderAllocator *pAllocator,
9782                                          BOOL isInterface,
9783                                          BOOL fDynamicStatics,
9784                                          BOOL fHasGenericsStaticsInfo,
9785                                          BOOL fNeedsRCWPerTypeData
9786 #ifdef FEATURE_COMINTEROP
9787         , BOOL fHasDynamicInterfaceMap
9788 #endif
9789 #ifdef FEATURE_PREJIT
9790         , Module *pComputedPZM
9791 #endif // FEATURE_PREJIT
9792         , AllocMemTracker *pamTracker
9793     )
9794 {
9795     CONTRACT (MethodTable*)
9796     {
9797         THROWS;
9798         GC_TRIGGERS;
9799         MODE_ANY;
9800         POSTCONDITION(CheckPointer(RETVAL));
9801     }
9802     CONTRACT_END;
9803
9804     DWORD dwNonVirtualSlots = dwVtableSlots - dwVirtuals;
9805
9806     // GCSize must be aligned
9807     _ASSERTE(IS_ALIGNED(dwGCSize, sizeof(void*)));
9808
9809     // size without the interface map
9810     S_SIZE_T cbTotalSize = S_SIZE_T(dwGCSize) + S_SIZE_T(sizeof(MethodTable));
9811
9812     // vtable
9813     cbTotalSize += MethodTable::GetNumVtableIndirections(dwVirtuals) * sizeof(MethodTable::VTableIndir_t);
9814
9815
9816     DWORD dwMultipurposeSlotsMask = 0;
9817     if (dwNumInterfaces != 0)
9818         dwMultipurposeSlotsMask |= MethodTable::enum_flag_HasInterfaceMap;
9819     if (dwNumDicts != 0)
9820         dwMultipurposeSlotsMask |= MethodTable::enum_flag_HasPerInstInfo;
9821     if (bmtVT->pDispatchMapBuilder->Count() > 0)
9822         dwMultipurposeSlotsMask |= MethodTable::enum_flag_HasDispatchMapSlot;
9823     if (dwNonVirtualSlots != 0)
9824         dwMultipurposeSlotsMask |= MethodTable::enum_flag_HasNonVirtualSlots;
9825     if (pLoaderModule != GetModule())
9826         dwMultipurposeSlotsMask |= MethodTable::enum_flag_HasModuleOverride;
9827
9828     // Add space for optional members here. Same as GetOptionalMembersSize()
9829     cbTotalSize += MethodTable::GetOptionalMembersAllocationSize(dwMultipurposeSlotsMask,
9830                                                       fHasGenericsStaticsInfo,
9831                                                       FALSE, // no GuidInfo needed for canonical instantiations
9832                                                       FALSE, // no CCW template needed for canonical instantiations
9833                                                       fNeedsRCWPerTypeData,
9834                                                       RidFromToken(GetCl()) >= METHODTABLE_TOKEN_OVERFLOW);
9835
9836     // Interface map starts here
9837     S_SIZE_T offsetOfInterfaceMap = cbTotalSize;
9838
9839     cbTotalSize += S_SIZE_T(dwNumInterfaces) * S_SIZE_T(sizeof(InterfaceInfo_t));
9840
9841 #ifdef FEATURE_COMINTEROP
9842     // DynamicInterfaceMap have an extra DWORD added to the end of the normal interface
9843     // map. This will be used to store the count of dynamically added interfaces
9844     // (the ones that are not in  the metadata but are QI'ed for at runtime).
9845     cbTotalSize += S_SIZE_T(fHasDynamicInterfaceMap ? sizeof(DWORD_PTR) : 0);
9846 #endif
9847
9848     // Dictionary pointers start here
9849     S_SIZE_T offsetOfInstAndDict = cbTotalSize;
9850
9851     if (dwNumDicts != 0)
9852     {
9853         cbTotalSize += sizeof(GenericsDictInfo);
9854         cbTotalSize += S_SIZE_T(dwNumDicts) * S_SIZE_T(sizeof(MethodTable::PerInstInfoElem_t));
9855         cbTotalSize += cbInstAndDict;
9856     }
9857
9858     S_SIZE_T offsetOfUnsharedVtableChunks = cbTotalSize;
9859
9860     BOOL canShareVtableChunks = pMTParent && MethodTable::CanShareVtableChunksFrom(pMTParent, pLoaderModule
9861 #ifdef FEATURE_PREJIT
9862         , pComputedPZM
9863 #endif //FEATURE_PREJIT
9864         );
9865
9866     // If pMTParent has a generic instantiation, we cannot share its vtable chunks
9867     // This is because pMTParent is only approximate at this point, and MethodTableBuilder::CopyExactParentSlots
9868     // may swap in an exact parent that does not satisfy CanShareVtableChunksFrom
9869     if (pMTParent && pMTParent->HasInstantiation())
9870     {
9871         canShareVtableChunks = FALSE;
9872     }
9873
9874     // We will share any parent vtable chunk that does not contain a method we overrode (or introduced)
9875     // For the rest, we need to allocate space
9876     for (DWORD i = 0; i < dwVirtuals; i++)
9877     {
9878         if (!canShareVtableChunks || ChangesImplementationOfVirtualSlot(static_cast<SLOT_INDEX>(i)))
9879         {
9880             DWORD chunkStart = MethodTable::GetStartSlotForVtableIndirection(MethodTable::GetIndexOfVtableIndirection(i), dwVirtuals);
9881             DWORD chunkEnd = MethodTable::GetEndSlotForVtableIndirection(MethodTable::GetIndexOfVtableIndirection(i), dwVirtuals);
9882
9883             cbTotalSize += S_SIZE_T(chunkEnd - chunkStart) * S_SIZE_T(sizeof(PCODE));
9884
9885             i = chunkEnd - 1;
9886         }
9887     }
9888
9889     // Add space for the non-virtual slots array (pointed to by an optional member) if required
9890     // If there is only one non-virtual slot, we store it directly in the optional member and need no array
9891     S_SIZE_T offsetOfNonVirtualSlots = cbTotalSize;
9892     if (dwNonVirtualSlots > 1)
9893     {
9894         cbTotalSize += S_SIZE_T(dwNonVirtualSlots) * S_SIZE_T(sizeof(PCODE));
9895     }
9896
9897     BYTE *pData = (BYTE *)pamTracker->Track(pAllocator->GetHighFrequencyHeap()->AllocMem(cbTotalSize));
9898
9899     _ASSERTE(IS_ALIGNED(pData, TARGET_POINTER_SIZE));
9900     
9901     // There should be no overflows if we have allocated the memory succesfully
9902     _ASSERTE(!cbTotalSize.IsOverflow());
9903
9904     MethodTable* pMT = (MethodTable*)(pData + dwGCSize);
9905
9906     pMT->SetMultipurposeSlotsMask(dwMultipurposeSlotsMask);
9907
9908     MethodTableWriteableData * pMTWriteableData = (MethodTableWriteableData *) (BYTE *)
9909         pamTracker->Track(pAllocator->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(MethodTableWriteableData))));
9910     // Note: Memory allocated on loader heap is zero filled
9911     pMT->SetWriteableData(pMTWriteableData);
9912
9913     // This also disables IBC logging until the type is sufficiently intitialized so
9914     // it needs to be done early
9915     pMTWriteableData->SetIsNotFullyLoadedForBuildMethodTable();
9916
9917 #ifdef _DEBUG
9918     pClassLoader->m_dwGCSize += dwGCSize;
9919     pClassLoader->m_dwInterfaceMapSize += (dwNumInterfaces * sizeof(InterfaceInfo_t));
9920     pClassLoader->m_dwMethodTableSize += (DWORD)cbTotalSize.Value();
9921     pClassLoader->m_dwVtableData += (dwVtableSlots * sizeof(PCODE));
9922 #endif // _DEBUG
9923
9924     // There should be no overflows if we have allocated the memory succesfully
9925     _ASSERTE(!offsetOfUnsharedVtableChunks.IsOverflow());
9926     _ASSERTE(!offsetOfNonVirtualSlots.IsOverflow());
9927     _ASSERTE(!offsetOfInterfaceMap.IsOverflow());
9928     _ASSERTE(!offsetOfInstAndDict.IsOverflow());
9929
9930     // initialize the total number of slots
9931     pMT->SetNumVirtuals(static_cast<WORD>(dwVirtuals));
9932
9933     pMT->SetParentMethodTable(pMTParent);
9934
9935     // Fill out the vtable indirection slots
9936     SIZE_T dwCurrentUnsharedSlotOffset = offsetOfUnsharedVtableChunks.Value();
9937     MethodTable::VtableIndirectionSlotIterator it = pMT->IterateVtableIndirectionSlots();
9938     while (it.Next())
9939     {
9940         BOOL shared = canShareVtableChunks;
9941
9942         // Recalculate whether we will share this chunk
9943         if (canShareVtableChunks)
9944         {
9945             for (DWORD i = it.GetStartSlot(); i < it.GetEndSlot(); i++)
9946             {
9947                 if (ChangesImplementationOfVirtualSlot(static_cast<SLOT_INDEX>(i)))
9948                 {
9949                     shared = FALSE;
9950                     break;
9951                 }
9952             }
9953         }
9954
9955         if (shared)
9956         {
9957             // Share the parent chunk
9958             _ASSERTE(it.GetEndSlot() <= pMTParent->GetNumVirtuals());
9959             it.SetIndirectionSlot(pMTParent->GetVtableIndirections()[it.GetIndex()].GetValueMaybeNull());
9960         }
9961         else
9962         {
9963             // Use the locally allocated chunk
9964             it.SetIndirectionSlot((MethodTable::VTableIndir2_t *)(pData+dwCurrentUnsharedSlotOffset));
9965             dwCurrentUnsharedSlotOffset += it.GetSize();
9966         }
9967     }
9968
9969 #ifdef FEATURE_COMINTEROP
9970     // Extensible RCW's are prefixed with the count of dynamic interfaces.
9971     if (fHasDynamicInterfaceMap)
9972     {
9973         _ASSERTE (dwNumInterfaces > 0);
9974         pMT->SetInterfaceMap ((WORD) (dwNumInterfaces), (InterfaceInfo_t*)(pData+offsetOfInterfaceMap.Value()+sizeof(DWORD_PTR)));
9975
9976         *(((DWORD_PTR *)pMT->GetInterfaceMap()) - 1) = 0;
9977     }
9978     else
9979 #endif // FEATURE_COMINTEROP
9980     {
9981         // interface map is at the end of the vtable
9982         pMT->SetInterfaceMap ((WORD) dwNumInterfaces, (InterfaceInfo_t *)(pData+offsetOfInterfaceMap.Value()));
9983     }
9984
9985     _ASSERTE(((WORD) dwNumInterfaces) == dwNumInterfaces);
9986
9987     if (fDynamicStatics)
9988     {
9989         pMT->SetDynamicStatics(fHasGenericsStaticsInfo);
9990     }
9991
9992     if (dwNonVirtualSlots > 0)
9993     {
9994         if (dwNonVirtualSlots > 1)
9995         {
9996             pMT->SetNonVirtualSlotsArray((PTR_PCODE)(pData+offsetOfNonVirtualSlots.Value()));
9997         }
9998         else
9999         {
10000             pMT->SetHasSingleNonVirtualSlot();
10001         }
10002     }
10003
10004     // the dictionary pointers follow the interface map
10005     if (dwNumDicts)
10006     {
10007         MethodTable::PerInstInfoElem_t *pPerInstInfo = (MethodTable::PerInstInfoElem_t *)(pData + offsetOfInstAndDict.Value() + sizeof(GenericsDictInfo));
10008
10009         pMT->SetPerInstInfo ( pPerInstInfo);
10010
10011         // Fill in the dictionary for this type, if it's instantiated
10012         if (cbInstAndDict)
10013         {
10014             MethodTable::PerInstInfoElem_t *pPInstInfo = (MethodTable::PerInstInfoElem_t *)(pPerInstInfo + (dwNumDicts-1));
10015             pPInstInfo->SetValueMaybeNull((Dictionary*) (pPerInstInfo + dwNumDicts));
10016         }
10017     }
10018
10019 #ifdef _DEBUG
10020     pMT->m_pWriteableData.GetValue()->m_dwLastVerifedGCCnt = (DWORD)-1;
10021 #endif // _DEBUG
10022
10023     RETURN(pMT);
10024 }
10025
10026     
10027 //*******************************************************************************
10028 //
10029 // Used by BuildMethodTable
10030 //
10031 // Setup the method table
10032 //
10033 #ifdef _PREFAST_ 
10034 #pragma warning(push)
10035 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
10036 #endif // _PREFAST_
10037
10038 VOID
10039 MethodTableBuilder::SetupMethodTable2(
10040         Module * pLoaderModule 
10041 #ifdef FEATURE_PREJIT
10042         , Module * pComputedPZM 
10043 #endif // FEATURE_PREJIT
10044     )
10045 {
10046     CONTRACTL
10047     {
10048         STANDARD_VM_CHECK;
10049         PRECONDITION(CheckPointer(this));
10050         PRECONDITION(CheckPointer(bmtVT));
10051         PRECONDITION(CheckPointer(bmtInterface));
10052         PRECONDITION(CheckPointer(bmtInternal));
10053         PRECONDITION(CheckPointer(bmtProp));
10054         PRECONDITION(CheckPointer(bmtMFDescs));
10055         PRECONDITION(CheckPointer(bmtEnumFields));
10056         PRECONDITION(CheckPointer(bmtError));
10057         PRECONDITION(CheckPointer(bmtMetaData));
10058         PRECONDITION(CheckPointer(bmtParent));
10059         PRECONDITION(CheckPointer(bmtGenerics));
10060     }
10061     CONTRACTL_END;
10062
10063     DWORD i;
10064
10065 #ifdef FEATURE_COMINTEROP 
10066     BOOL fHasDynamicInterfaceMap = bmtInterface->dwInterfaceMapSize > 0 &&
10067                                    bmtProp->fIsComObjectType &&
10068                                    (GetParentMethodTable() != g_pObjectClass);
10069     BOOL fNeedsRCWPerTypeData = bmtProp->fNeedsRCWPerTypeData;
10070 #else // FEATURE_COMINTEROP
10071     BOOL fNeedsRCWPerTypeData = FALSE;
10072 #endif // FEATURE_COMINTEROP
10073
10074     EEClass *pClass = GetHalfBakedClass();
10075
10076     DWORD cbDict = bmtGenerics->HasInstantiation()
10077                    ?  DictionaryLayout::GetFirstDictionaryBucketSize(
10078                           bmtGenerics->GetNumGenericArgs(), pClass->GetDictionaryLayout())
10079                    : 0;
10080
10081 #ifdef FEATURE_COLLECTIBLE_TYPES
10082     BOOL fCollectible = pLoaderModule->IsCollectible();
10083 #endif // FEATURE_COLLECTIBLE_TYPES
10084
10085     DWORD dwGCSize;
10086     
10087     if (bmtFP->NumGCPointerSeries > 0)
10088     {
10089         dwGCSize = (DWORD)CGCDesc::ComputeSize(bmtFP->NumGCPointerSeries);
10090     }
10091     else
10092     {
10093 #ifdef FEATURE_COLLECTIBLE_TYPES
10094         if (fCollectible)
10095             dwGCSize = (DWORD)CGCDesc::ComputeSize(1);
10096         else
10097 #endif // FEATURE_COLLECTIBLE_TYPES
10098             dwGCSize = 0;
10099     }
10100
10101     pClass->SetNumMethods(bmtVT->cTotalSlots);
10102     pClass->SetNumNonVirtualSlots(bmtVT->cVtableSlots - bmtVT->cVirtualSlots);
10103
10104     // Now setup the method table
10105     // interface map is allocated along with the method table
10106     MethodTable *pMT = AllocateNewMT(pLoaderModule,
10107                                    bmtVT->cVtableSlots,
10108                                    bmtVT->cVirtualSlots,
10109                                    dwGCSize,
10110                                    bmtInterface->dwInterfaceMapSize,
10111                                    bmtGenerics->numDicts,
10112                                    cbDict,
10113                                    GetParentMethodTable(),
10114                                    GetClassLoader(),
10115                                    bmtAllocator,
10116                                    IsInterface(),
10117                                    bmtProp->fDynamicStatics,
10118                                    bmtProp->fGenericsStatics,
10119                                    fNeedsRCWPerTypeData,
10120 #ifdef FEATURE_COMINTEROP 
10121                                    fHasDynamicInterfaceMap,
10122 #endif
10123 #ifdef FEATURE_PREJIT
10124                                    pComputedPZM,
10125 #endif //FEATURE_PREJIT
10126                                    GetMemTracker());
10127
10128     pMT->SetClass(pClass);
10129     pClass->m_pMethodTable.SetValue(pMT);
10130     m_pHalfBakedMT = pMT;
10131
10132 #ifdef _DEBUG 
10133     pMT->SetDebugClassName(GetDebugClassName());
10134 #endif
10135
10136 #ifdef FEATURE_COMINTEROP
10137     if (fNeedsRCWPerTypeData)
10138         pMT->SetHasRCWPerTypeData();
10139 #endif // FEATURE_COMINTEROP
10140
10141
10142     if (IsInterface())
10143         pMT->SetIsInterface();
10144
10145     if (GetParentMethodTable() != NULL)
10146     {
10147         if (GetParentMethodTable()->HasModuleDependencies())
10148         {
10149             pMT->SetHasModuleDependencies();
10150         }
10151         else
10152         {
10153             Module * pModule = GetModule();
10154             Module * pParentModule = GetParentMethodTable()->GetModule();
10155             if (pModule != pParentModule)
10156             {
10157                 pMT->SetHasModuleDependencies();
10158             }
10159         }
10160
10161         if (GetParentMethodTable()->HasPreciseInitCctors() || !pClass->IsBeforeFieldInit())
10162         {
10163             pMT->SetHasPreciseInitCctors();
10164         }
10165     }
10166
10167     // Must be done early because various methods test HasInstantiation() and ContainsGenericVariables()
10168     if (bmtGenerics->GetNumGenericArgs() != 0)
10169     {
10170         pMT->SetHasInstantiation(bmtGenerics->fTypicalInstantiation, bmtGenerics->fSharedByGenericInstantiations);
10171
10172         if (bmtGenerics->fContainsGenericVariables)
10173             pMT->SetContainsGenericVariables();
10174     }
10175
10176     if (bmtGenerics->numDicts != 0)
10177     {
10178         if (!FitsIn<WORD>(bmtGenerics->GetNumGenericArgs()))
10179         {
10180             BuildMethodTableThrowException(IDS_CLASSLOAD_TOOMANYGENERICARGS);
10181         }
10182
10183         pMT->SetDictInfo(bmtGenerics->numDicts,
10184             static_cast<WORD>(bmtGenerics->GetNumGenericArgs()));
10185     }
10186
10187     CONSISTENCY_CHECK(pMT->GetNumGenericArgs() == bmtGenerics->GetNumGenericArgs());
10188     CONSISTENCY_CHECK(pMT->GetNumDicts() == bmtGenerics->numDicts);
10189     CONSISTENCY_CHECK(pMT->HasInstantiation() == bmtGenerics->HasInstantiation());
10190     CONSISTENCY_CHECK(pMT->HasInstantiation() == !pMT->GetInstantiation().IsEmpty());
10191
10192     pMT->SetLoaderModule(pLoaderModule);
10193     pMT->SetLoaderAllocator(bmtAllocator);
10194
10195     pMT->SetModule(GetModule());
10196
10197     pMT->SetInternalCorElementType (ELEMENT_TYPE_CLASS);
10198
10199     SetNonGCRegularStaticFieldBytes (bmtProp->dwNonGCRegularStaticFieldBytes);
10200     SetNonGCThreadStaticFieldBytes (bmtProp->dwNonGCThreadStaticFieldBytes);
10201
10202 #ifdef FEATURE_TYPEEQUIVALENCE
10203     if (bmtProp->fHasTypeEquivalence)
10204     {
10205         pMT->SetHasTypeEquivalence();
10206     }
10207 #endif //FEATURE_TYPEEQUIVALENCE
10208
10209 #ifdef FEATURE_COMINTEROP 
10210     if (bmtProp->fSparse)
10211         pClass->SetSparseForCOMInterop();
10212
10213     if (IsInterface() && IsComImport())
10214     {
10215         // Determine if we are creating an interface methodtable that may be used to dispatch through VSD
10216         // on an object that has the methodtable of __ComObject.
10217
10218         // This is done to allow COM tearoff interfaces, but as a side-effect of this feature,
10219         // we end up using a domain-shared type (__ComObject) with a domain-specific dispatch token.
10220         // This is a problem because the same domain-specific dispatch token value can appear in
10221         // multiple unshared domains (VSD takes advantage of the fact that in general a shared type
10222         // cannot implement an unshared interface). This means that the same <token, __ComObject> pair
10223         // value can mean different things in different domains (since the token could represent
10224         // IFoo in one domain and IBar in another). This is a problem because the
10225         // VSD polymorphic lookup mechanism relies on a process-wide cache table, and as a result
10226         // these duplicate values would collide if we didn't use fat dispatch token to ensure uniqueness
10227         // and the interface methodtable is not in the shared domain.
10228
10229         pMT->SetRequiresFatDispatchTokens();
10230     }
10231 #endif // FEATURE_COMINTEROP
10232
10233     if (bmtVT->pCCtor != NULL)
10234     {
10235         pMT->SetHasClassConstructor();
10236         CONSISTENCY_CHECK(pMT->GetClassConstructorSlot() == bmtVT->pCCtor->GetSlotIndex());
10237     }
10238     if (bmtVT->pDefaultCtor != NULL)
10239     {
10240         pMT->SetHasDefaultConstructor();
10241         CONSISTENCY_CHECK(pMT->GetDefaultConstructorSlot() == bmtVT->pDefaultCtor->GetSlotIndex());
10242     }
10243
10244     for (MethodDescChunk *pChunk = GetHalfBakedClass()->GetChunks(); pChunk != NULL; pChunk = pChunk->GetNextChunk())
10245     {
10246         pChunk->SetMethodTable(pMT);
10247     }
10248
10249 #ifdef _DEBUG 
10250     {
10251         // disable ibc logging because we can assert in ComputerPreferredZapModule for partially constructed
10252         // generic types 
10253         IBCLoggingDisabler disableLogging;
10254
10255         DeclaredMethodIterator it(*this);
10256         while (it.Next())
10257         {
10258             MethodDesc *pMD = it->GetMethodDesc();
10259             if (pMD != NULL)
10260             {
10261                 pMD->m_pDebugMethodTable.SetValue(pMT);
10262                 pMD->m_pszDebugMethodSignature = FormatSig(pMD, GetLoaderAllocator()->GetLowFrequencyHeap(), GetMemTracker());
10263             }
10264             MethodDesc *pUnboxedMD = it->GetUnboxedMethodDesc();
10265             if (pUnboxedMD != NULL)
10266             {
10267                 pUnboxedMD->m_pDebugMethodTable.SetValue(pMT);
10268                 pUnboxedMD->m_pszDebugMethodSignature = FormatSig(pUnboxedMD, GetLoaderAllocator()->GetLowFrequencyHeap(), GetMemTracker());
10269             }
10270         }
10271     }
10272 #endif // _DEBUG
10273
10274     // Note that for value classes, the following calculation is only appropriate
10275     // when the instance is in its "boxed" state.
10276     if (!IsInterface())
10277     {
10278         DWORD baseSize = Max<DWORD>(bmtFP->NumInstanceFieldBytes + OBJECT_BASESIZE, MIN_OBJECT_SIZE);
10279         baseSize = (baseSize + ALLOC_ALIGN_CONSTANT) & ~ALLOC_ALIGN_CONSTANT;  // m_BaseSize must be aligned
10280         pMT->SetBaseSize(baseSize);
10281
10282         GetHalfBakedClass()->SetBaseSizePadding(baseSize - bmtFP->NumInstanceFieldBytes);
10283
10284         if (bmtProp->fIsComObjectType)
10285         {   // Propagate the com specific info
10286             pMT->SetComObjectType();
10287 #ifdef FEATURE_COMINTEROP 
10288             // COM objects need an optional field on the EEClass, so ensure this class instance has allocated
10289             // the optional field descriptor.
10290             EnsureOptionalFieldsAreAllocated(pClass, m_pAllocMemTracker, GetLoaderAllocator()->GetLowFrequencyHeap());
10291 #endif // FEATURE_COMINTEROP
10292         }
10293
10294 #ifdef FEATURE_COMINTEROP 
10295         if (pMT->GetAssembly()->IsManagedWinMD())
10296         {
10297             // We need to mark classes that are implementations of managed WinRT runtime classes with
10298             // the "exported to WinRT" flag. It's not quite possible to tell which ones these are by
10299             // reading metadata so we ask the adapter.
10300
10301             IWinMDImport *pWinMDImport = pMT->GetAssembly()->GetManifestWinMDImport();
10302             _ASSERTE(pWinMDImport != NULL);
10303
10304             BOOL bResult;
10305             IfFailThrow(pWinMDImport->IsRuntimeClassImplementation(GetCl(), &bResult));
10306                 
10307             if (bResult)
10308             {
10309                 pClass->SetExportedToWinRT();
10310
10311                 // We need optional fields for activation from WinRT.
10312                 EnsureOptionalFieldsAreAllocated(pClass, m_pAllocMemTracker, GetLoaderAllocator()->GetLowFrequencyHeap());
10313             }
10314         }
10315
10316         if (pClass->IsProjectedFromWinRT() || pClass->IsExportedToWinRT())
10317         {
10318             const BYTE *        pVal;                 
10319             ULONG               cbVal;        
10320             HRESULT hr = GetMDImport()->GetCustomAttributeByName(GetCl(), g_WindowsFoundationMarshalingBehaviorAttributeClassName, (const void **) &pVal, &cbVal);
10321             if (hr == S_OK)
10322             {
10323                 CustomAttributeParser cap(pVal, cbVal);
10324                 IfFailThrow(cap.SkipProlog());
10325                 UINT32 u = 0;
10326                 IfFailThrow(cap.GetU4(&u));
10327                 if(u > 0)
10328                     pClass->SetMarshalingType(u);
10329             }
10330         }
10331 #endif // FEATURE_COMINTEROP
10332     }
10333     else
10334     {
10335 #ifdef FEATURE_COMINTEROP 
10336         // If this is an interface then we need to set the ComInterfaceType to
10337         // -1 to indicate we have not yet determined the interface type.
10338         pClass->SetComInterfaceType((CorIfaceAttr)-1);
10339
10340         // If this is a special COM event interface, then mark the MT as such.
10341         if (bmtProp->fComEventItfType)
10342         {
10343             pClass->SetComEventItfType();
10344         }
10345 #endif // FEATURE_COMINTEROP
10346     }
10347     _ASSERTE((pMT->IsInterface() == 0) == (IsInterface() == 0));
10348
10349     if (HasLayout())
10350     {
10351         pClass->SetNativeSize(GetLayoutInfo()->GetNativeSize());
10352     }
10353
10354     FieldDesc *pFieldDescList = pClass->GetFieldDescList();
10355     // Set all field slots to point to the newly created MethodTable
10356     for (i = 0; i < (bmtEnumFields->dwNumStaticFields + bmtEnumFields->dwNumInstanceFields); i++)
10357     {
10358         pFieldDescList[i].m_pMTOfEnclosingClass.SetValue(pMT);
10359     }
10360
10361     // Fill in type parameters before looking up exact parent or fetching the types of any field descriptors!
10362     // This must come before the use of GetFieldType in the value class representation optimization below.
10363     if (bmtGenerics->GetNumGenericArgs() != 0)
10364     {
10365         // Space has already been allocated for the instantiation but the parameters haven't been filled in
10366         Instantiation destInst = pMT->GetInstantiation();
10367         Instantiation inst = bmtGenerics->GetInstantiation();
10368
10369         // So fill them in...
10370         TypeHandle * pInstDest = (TypeHandle *)destInst.GetRawArgs();
10371         for (DWORD j = 0; j < bmtGenerics->GetNumGenericArgs(); j++)
10372         {
10373             pInstDest[j] = inst[j];
10374         }
10375     }
10376
10377     CorElementType normalizedType = ELEMENT_TYPE_CLASS;
10378     if (IsValueClass())
10379     {
10380         if (IsEnum())
10381         {
10382             if (GetNumInstanceFields() != 1 ||
10383                 !CorTypeInfo::IsPrimitiveType(pFieldDescList[0].GetFieldType()))
10384             {
10385                 BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil);
10386             }
10387             CONSISTENCY_CHECK(!pFieldDescList[0].IsStatic());
10388             normalizedType = pFieldDescList->GetFieldType();
10389         }
10390         else
10391         {
10392 #ifdef _TARGET_X86_ 
10393             // JIT64 is not aware of normalized value types and this
10394             // optimization (return small value types by value in registers)
10395             // is already done in JIT64.
10396             OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOADED);
10397             normalizedType = EEClass::ComputeInternalCorElementTypeForValueType(pMT);
10398 #else
10399             normalizedType = ELEMENT_TYPE_VALUETYPE;
10400 #endif
10401         }
10402     }
10403     pMT->SetInternalCorElementType(normalizedType);
10404
10405     if (bmtProp->fIsIntrinsicType)
10406     {
10407         pMT->SetIsIntrinsicType();
10408     }
10409
10410     if (GetModule()->IsSystem())
10411     {
10412         // we are in mscorlib
10413         CheckForSystemTypes();
10414     }
10415
10416     // Now fill in the real interface map with the approximate interfaces
10417     if (bmtInterface->dwInterfaceMapSize > 0)
10418     {
10419         // First ensure we have enough space to record extra flag information for each interface (we don't
10420         // record this directly into each interface map entry since these flags don't pack well due to
10421         // alignment).
10422         PVOID pExtraInterfaceInfo = NULL;
10423         SIZE_T cbExtraInterfaceInfo = MethodTable::GetExtraInterfaceInfoSize(bmtInterface->dwInterfaceMapSize);
10424         if (cbExtraInterfaceInfo)
10425             pExtraInterfaceInfo = GetMemTracker()->Track(GetLoaderAllocator()->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(cbExtraInterfaceInfo)));
10426
10427         // Call this even in the case where pExtraInterfaceInfo == NULL (certain cases are optimized and don't
10428         // require extra buffer space).
10429         pMT->InitializeExtraInterfaceInfo(pExtraInterfaceInfo);
10430
10431         InterfaceInfo_t *pInterfaces = pMT->GetInterfaceMap();
10432
10433         CONSISTENCY_CHECK(CheckPointer(pInterfaces));
10434
10435         // Copy the interface map member by member so there is no junk in the padding.
10436         for (i = 0; i < bmtInterface->dwInterfaceMapSize; i++)
10437         {
10438             bmtInterfaceEntry * pEntry = &bmtInterface->pInterfaceMap[i];
10439
10440             if (pEntry->IsDeclaredOnType())
10441                 pMT->SetInterfaceDeclaredOnClass(i);
10442             _ASSERTE(!!pEntry->IsDeclaredOnType() == !!pMT->IsInterfaceDeclaredOnClass(i));
10443
10444             pInterfaces[i].SetMethodTable(pEntry->GetInterfaceType()->GetMethodTable());
10445         }
10446     }
10447
10448     pMT->SetCl(GetCl());
10449
10450     // The type is sufficiently initialized for most general purpose accessor methods to work.
10451     // Mark the type as restored to avoid avoid asserts. Note that this also enables IBC logging.
10452     pMT->GetWriteableDataForWrite_NoLogging()->SetIsRestoredForBuildMethodTable();
10453
10454 #ifdef _DEBUG
10455     // Store status if we tried to inject duplicate interfaces
10456     if (bmtInterface->dbg_fShouldInjectInterfaceDuplicates)
10457         pMT->Debug_SetHasInjectedInterfaceDuplicates();
10458 #endif //_DEBUG
10459
10460     // Keep bmtInterface data around since we no longer write the flags (IsDeclaredOnType and
10461     // IsImplementedByParent) into the interface map (these flags are only required during type loading).
10462
10463     {
10464         for (MethodDescChunk *pChunk = GetHalfBakedClass()->GetChunks(); pChunk != NULL; pChunk = pChunk->GetNextChunk())
10465         {
10466             // Make sure that temporary entrypoints are create for methods. NGEN uses temporary
10467             // entrypoints as surrogate keys for precodes.
10468             pChunk->EnsureTemporaryEntryPointsCreated(GetLoaderAllocator(), GetMemTracker());
10469         }
10470     }
10471
10472     {   // copy onto the real vtable (methods only)
10473         //@GENERICS: Because we sometimes load an inexact parent (see ClassLoader::GetParent) the inherited slots might
10474         // come from the wrong place and need fixing up once we know the exact parent
10475
10476         for (bmtVtable::Iterator slotIt = bmtVT->IterateSlots(); !slotIt.AtEnd(); ++slotIt)
10477         {
10478             SLOT_INDEX iCurSlot = static_cast<SLOT_INDEX>(slotIt.CurrentIndex());
10479
10480             // We want the unboxed MethodDesc if we're out of the virtual method range
10481             // and the method we're dealing with has an unboxing method. If so, then
10482             // the unboxing method was placed in the virtual section of the vtable and
10483             // we now need to place the unboxed version.
10484             MethodDesc * pMD = NULL;
10485             if (iCurSlot < bmtVT->cVirtualSlots || !slotIt->Impl().AsMDMethod()->IsUnboxing())
10486             {
10487                 pMD = slotIt->Impl().GetMethodDesc();
10488                 CONSISTENCY_CHECK(slotIt->Decl().GetSlotIndex() == iCurSlot);
10489             }
10490             else
10491             {
10492                 pMD = slotIt->Impl().AsMDMethod()->GetUnboxedMethodDesc();
10493                 CONSISTENCY_CHECK(pMD->GetSlot() == iCurSlot);
10494             }
10495
10496             CONSISTENCY_CHECK(CheckPointer(pMD));
10497
10498             if (pMD->GetMethodTable() != pMT)
10499             {
10500                 //
10501                 // Inherited slots
10502                 //
10503                 // Do not write into vtable chunks shared with parent. It would introduce race 
10504                 // with code:MethodDesc::SetStableEntryPointInterlocked.
10505                 //
10506                 DWORD indirectionIndex = MethodTable::GetIndexOfVtableIndirection(iCurSlot);
10507                 if (GetParentMethodTable()->GetVtableIndirections()[indirectionIndex].GetValueMaybeNull() != pMT->GetVtableIndirections()[indirectionIndex].GetValueMaybeNull())
10508                     pMT->SetSlot(iCurSlot, pMD->GetInitialEntryPointForCopiedSlot());
10509             }
10510             else
10511             {
10512                 //
10513                 // Owned slots
10514                 //
10515                 _ASSERTE(iCurSlot >= bmtVT->cVirtualSlots || ChangesImplementationOfVirtualSlot(iCurSlot));
10516
10517                 PCODE addr = pMD->GetTemporaryEntryPoint();
10518                 _ASSERTE(addr != NULL);
10519
10520                 if (pMD->HasNonVtableSlot())
10521                 {
10522                     *((PCODE *)pMD->GetAddrOfSlot()) = addr;
10523                 }
10524                 else
10525                 {
10526                     pMT->SetSlot(iCurSlot, addr);
10527                 }
10528
10529                 if (pMD->GetSlot() == iCurSlot && pMD->RequiresStableEntryPoint())
10530                 {
10531                     // The rest of the system assumes that certain methods always have stable entrypoints.
10532                     // Create them now.
10533                     pMD->GetOrCreatePrecode();
10534                 }
10535             }
10536         }
10537     }
10538
10539     // If we have any entries, then finalize them and allocate the object in class loader heap
10540     DispatchMap                 *pDispatchMap        = NULL;
10541     DispatchMapBuilder          *pDispatchMapBuilder = bmtVT->pDispatchMapBuilder;
10542     CONSISTENCY_CHECK(CheckPointer(pDispatchMapBuilder));
10543
10544     if (pDispatchMapBuilder->Count() > 0)
10545     {
10546         // Create a map in stacking memory.
10547         BYTE * pbMap;
10548         UINT32 cbMap;
10549         DispatchMap::CreateEncodedMapping(
10550             pMT, 
10551             pDispatchMapBuilder, 
10552             pDispatchMapBuilder->GetAllocator(), 
10553             &pbMap, 
10554             &cbMap);
10555
10556         // Now finalize the impltable and allocate the block in the low frequency loader heap
10557         size_t objSize = (size_t) DispatchMap::GetObjectSize(cbMap);
10558         void * pv = AllocateFromLowFrequencyHeap(S_SIZE_T(objSize));
10559         _ASSERTE(pv != NULL);
10560
10561         // Use placement new
10562         pDispatchMap = new (pv) DispatchMap(pbMap, cbMap);
10563         pMT->SetDispatchMap(pDispatchMap);
10564
10565 #ifdef LOGGING 
10566         g_sdStats.m_cDispatchMap++;
10567         g_sdStats.m_cbDispatchMap += (UINT32) objSize;
10568         LOG((LF_LOADER, LL_INFO1000, "SD: Dispatch map for %s: %d bytes for map, %d bytes total for object.\n",
10569             pMT->GetDebugClassName(), cbMap, objSize));
10570 #endif // LOGGING
10571
10572     }
10573
10574     // GetMethodData by default will cache its result. However, in the case that we're
10575     // building a MethodTable, we aren't guaranteed that this type is going to successfully
10576     // load and so caching it would result in errors down the road since the memory and
10577     // type occupying the same memory location would very likely be incorrect. The second
10578     // argument specifies that GetMethodData should not cache the returned object.
10579     MethodTable::MethodDataWrapper hMTData(MethodTable::GetMethodData(pMT, FALSE));
10580
10581     if (!IsInterface())
10582     {
10583         // Propagate inheritance.
10584
10585         // NOTE: In the world of unfolded interface this was used to propagate overrides into
10586         //       the unfolded interface vtables to make sure that overrides of virtual methods
10587         //       also overrode the interface methods that they contributed to. This had the
10588         //       unfortunate side-effect of also overwriting regular vtable slots that had been
10589         //       methodimpl'd and as a result changed the meaning of methodimpl from "substitute
10590         //       the body of method A with the body of method B" to "unify the slots of methods
10591         //       A and B". But now compilers have come to rely on this side-effect and it can
10592         //       not be brought back to its originally intended behaviour.
10593
10594         // For every slot whose body comes from another slot (determined by getting the MethodDesc
10595         // for a slot and seeing if MethodDesc::GetSlot returns a different value than the slot
10596         // from which the MethodDesc was recovered), copy the value of the slot stated by the
10597         // MethodDesc over top of the current slot.
10598
10599         // Because of the way slot unification works, we need to iterate the enture vtable until
10600         // no slots need updated. To understand this, imagine the following:
10601         //      C1::M1 is overridden by C2::M2
10602         //      C1::M2 is methodImpled by C1::M3
10603         //      C1::M3 is overridden by C2::M3
10604         // This should mean that C1::M1 is implemented by C2::M3, but if we didn't run the below
10605         // for loop a second time, this would not be propagated properly - it would only be placed
10606         // into the slot for C1::M2 and never make its way up to C1::M1.
10607         
10608         BOOL fChangeMade;
10609         do
10610         {
10611             fChangeMade = FALSE;
10612             for (i = 0; i < pMT->GetNumVirtuals(); i++)
10613             {
10614                 MethodDesc* pMD = hMTData->GetImplMethodDesc(i);
10615
10616                 CONSISTENCY_CHECK(CheckPointer(pMD));
10617                 CONSISTENCY_CHECK(pMD == pMT->GetMethodDescForSlot(i));
10618
10619                 // This indicates that the method body in this slot was copied here through a methodImpl.
10620                 // Thus, copy the value of the slot from which the body originally came, in case it was
10621                 // overridden, to make sure the two slots stay in sync.
10622                 DWORD originalIndex = pMD->GetSlot();
10623                 if (originalIndex != i)
10624                 {
10625                     MethodDesc *pOriginalMD = hMTData->GetImplMethodDesc(originalIndex);
10626                     CONSISTENCY_CHECK(CheckPointer(pOriginalMD));
10627                     CONSISTENCY_CHECK(pOriginalMD == pMT->GetMethodDescForSlot(originalIndex));
10628                     if (pMD != pOriginalMD)
10629                     {
10630                         // Copy the slot value in the method's original slot.
10631                         pMT->SetSlot(i, pOriginalMD->GetInitialEntryPointForCopiedSlot());
10632                         hMTData->InvalidateCachedVirtualSlot(i);
10633
10634                         // Update the pMD to the new method desc we just copied over ourselves with. This will
10635                         // be used in the check for missing method block below.
10636                         pMD = pOriginalMD;
10637
10638                         // This method is now duplicate
10639                         pMD->SetDuplicate();
10640                         INDEBUG(g_dupMethods++;)
10641                         fChangeMade = TRUE;
10642                     }
10643                 }
10644             }
10645         }
10646         while (fChangeMade);
10647     }
10648
10649     if (!bmtProp->fNoSanityChecks)
10650         VerifyVirtualMethodsImplemented(hMTData);
10651
10652 #ifdef _DEBUG 
10653     {
10654         for (bmtVtable::Iterator i = bmtVT->IterateSlots();
10655              !i.AtEnd(); ++i)
10656         {
10657             _ASSERTE(i->Impl().GetMethodDesc() != NULL);
10658         }
10659     }
10660 #endif // _DEBUG
10661
10662
10663 #ifdef FEATURE_COMINTEROP 
10664     // for ComObject types, i.e. if the class extends from a COM Imported
10665     // class
10666     // make sure any interface implementated by the COM Imported class
10667     // is overridden fully, (OR) not overridden at all..
10668     // We relax this for WinRT where we want to be able to override individual methods.
10669     if (bmtProp->fIsComObjectType && !pMT->IsWinRTObjectType())
10670     {
10671         MethodTable::InterfaceMapIterator intIt = pMT->IterateInterfaceMap();
10672         while (intIt.Next())
10673         {
10674             MethodTable* pIntfMT = intIt.GetInterface();
10675             if (pIntfMT->GetNumVirtuals() != 0)
10676             {
10677                 BOOL hasComImportMethod = FALSE;
10678                 BOOL hasManagedMethod = FALSE;
10679
10680                 // NOTE: Avoid caching the MethodData object for the type being built.
10681                 MethodTable::MethodDataWrapper hItfImplData(MethodTable::GetMethodData(pIntfMT, pMT, FALSE));
10682                 MethodTable::MethodIterator it(hItfImplData);
10683                 for (;it.IsValid(); it.Next())
10684                 {
10685                     MethodDesc *pClsMD = NULL;
10686                     // If we fail to find an _IMPLEMENTATION_ for the interface MD, then
10687                     // we are a ComImportMethod, otherwise we still be a ComImportMethod or
10688                     // we can be a ManagedMethod.
10689                     DispatchSlot impl(it.GetTarget());
10690                     if (!impl.IsNull())
10691                     {
10692                         pClsMD = it.GetMethodDesc();
10693
10694                         CONSISTENCY_CHECK(!pClsMD->IsInterface());
10695                         if (pClsMD->GetClass()->IsComImport())
10696                         {
10697                             hasComImportMethod = TRUE;
10698                         }
10699                         else
10700                         {
10701                             hasManagedMethod = TRUE;
10702                         }
10703                     }
10704                     else
10705                     {
10706                         // Need to set the pClsMD for the error reporting below.
10707                         pClsMD = it.GetDeclMethodDesc();
10708                         CONSISTENCY_CHECK(CheckPointer(pClsMD));
10709                         hasComImportMethod = TRUE;
10710                     }
10711
10712                     // One and only one of the two must be set.
10713                     if ((hasComImportMethod && hasManagedMethod) ||
10714                         (!hasComImportMethod && !hasManagedMethod))
10715                     {
10716                         BuildMethodTableThrowException(IDS_EE_BAD_COMEXTENDS_CLASS, pClsMD->GetNameOnNonArrayClass());
10717                     }
10718                 }
10719             }
10720         }
10721     }
10722
10723     // For COM event interfaces, we need to make sure that all the methods are
10724     // methods to add or remove events. This means that they all need to take
10725     // a delegate derived class and have a void return type.
10726     if (bmtProp->fComEventItfType)
10727     {
10728         // COM event interfaces had better be interfaces.
10729         CONSISTENCY_CHECK(IsInterface());
10730
10731         // Go through all the methods and check the validity of the signature.
10732         // NOTE: Uses hMTData to avoid caching a MethodData object for the type being built.
10733         MethodTable::MethodIterator it(hMTData);
10734         for (;it.IsValid(); it.Next())
10735         {
10736             MethodDesc* pMD = it.GetMethodDesc();
10737             _ASSERTE(pMD);
10738
10739             MetaSig Sig(pMD);
10740
10741             {
10742                 CONTRACT_VIOLATION(LoadsTypeViolation);
10743                 if (Sig.GetReturnType() != ELEMENT_TYPE_VOID ||
10744                     Sig.NumFixedArgs() != 1 ||
10745                     Sig.NextArg() != ELEMENT_TYPE_CLASS ||
10746                     !Sig.GetLastTypeHandleThrowing().CanCastTo(TypeHandle(g_pDelegateClass)))
10747                 {
10748                     BuildMethodTableThrowException(IDS_EE_BAD_COMEVENTITF_CLASS, pMD->GetNameOnNonArrayClass());
10749                 }
10750             }
10751         }
10752     }
10753 #endif // FEATURE_COMINTEROP
10754
10755     // If this class uses any VTS (Version Tolerant Serialization) features
10756     // (event callbacks or OptionalField attributes) we've previously cached the
10757     // additional information in the bmtMFDescs structure. Now it's time to add
10758     // this information as an optional extension to the MethodTable.
10759 }
10760 #ifdef _PREFAST_ 
10761 #pragma warning(pop)
10762 #endif
10763
10764 // Returns true if there is at least one default implementation for this interface method
10765 // We don't care about conflicts at this stage in order to avoid impact type load performance
10766 BOOL MethodTableBuilder::HasDefaultInterfaceImplementation(bmtRTType *pDeclType, MethodDesc *pDeclMD)
10767 {
10768     STANDARD_VM_CONTRACT;
10769
10770 #ifdef FEATURE_DEFAULT_INTERFACES
10771     // If the interface method is already non-abstract, we are done
10772     if (!pDeclMD->IsAbstract())
10773         return TRUE;
10774
10775     int targetSlot = pDeclMD->GetSlot();
10776
10777     // Iterate over all the interfaces this type implements
10778     bmtInterfaceEntry * pItfEntry = NULL;
10779     for (DWORD i = 0; i < bmtInterface->dwInterfaceMapSize; i++)
10780     {
10781         bmtRTType * pCurItf = bmtInterface->pInterfaceMap[i].GetInterfaceType();
10782
10783         Module * pCurIntfModule = pCurItf->GetMethodTable()->GetModule();
10784
10785         // Go over the methods on the interface
10786         MethodTable::IntroducedMethodIterator methIt(pCurItf->GetMethodTable());
10787         for (; methIt.IsValid(); methIt.Next())
10788         {
10789             MethodDesc * pPotentialImpl = methIt.GetMethodDesc();
10790
10791             // If this interface method is not a MethodImpl, it can't possibly implement
10792             // the interface method we are looking for
10793             if (!pPotentialImpl->IsMethodImpl())
10794                 continue;
10795
10796             // Go over all the decls this MethodImpl is implementing
10797             MethodImpl::Iterator it(pPotentialImpl);
10798             for (; it.IsValid(); it.Next())
10799             {
10800                 MethodDesc *pPotentialDecl = it.GetMethodDesc();
10801
10802                 // Check this is a decl with the right slot
10803                 if (pPotentialDecl->GetSlot() != targetSlot)
10804                     continue;
10805
10806                 // Find out what interface this default implementation is implementing
10807                 mdToken tkParent;
10808                 IfFailThrow(pCurIntfModule->GetMDImport()->GetParentToken(it.GetToken(), &tkParent));
10809
10810                 // We can only load the approximate interface at this point
10811                 MethodTable * pPotentialInterfaceMT = ClassLoader::LoadTypeDefOrRefOrSpecThrowing(
10812                     pCurIntfModule,
10813                     tkParent,
10814                     &bmtGenerics->typeContext,
10815                     ClassLoader::ThrowIfNotFound,
10816                     ClassLoader::PermitUninstDefOrRef,
10817                     ClassLoader::LoadTypes,
10818                     CLASS_LOAD_APPROXPARENTS,
10819                     TRUE).GetMethodTable()->GetCanonicalMethodTable();
10820
10821                 // Is this a default implementation for the interface we are looking for?
10822                 if (pDeclType->GetMethodTable()->HasSameTypeDefAs(pPotentialInterfaceMT))
10823                 {
10824                     // If the type is not generic, matching defs are all we need
10825                     if (!pDeclType->GetMethodTable()->HasInstantiation())
10826                         return TRUE;
10827
10828                     // If this is generic, we need to compare under substitutions
10829                     Substitution curItfSubs(tkParent, pCurIntfModule, &pCurItf->GetSubstitution());
10830
10831                     // Type Equivalence is not respected for this comparision as you can have multiple type equivalent interfaces on a class
10832                     TokenPairList newVisited = TokenPairList::AdjustForTypeEquivalenceForbiddenScope(NULL);
10833                     if (MetaSig::CompareTypeDefsUnderSubstitutions(
10834                         pPotentialInterfaceMT, pDeclType->GetMethodTable(),
10835                         &curItfSubs, &pDeclType->GetSubstitution(),
10836                         &newVisited))
10837                     {
10838                         return TRUE;
10839                     }
10840                 }
10841             }
10842         }        
10843     }
10844 #endif // FEATURE_DEFAULT_INTERFACES
10845
10846     return FALSE;
10847 }
10848
10849 void MethodTableBuilder::VerifyVirtualMethodsImplemented(MethodTable::MethodData * hMTData)
10850 {
10851     STANDARD_VM_CONTRACT;
10852
10853     //
10854     // This verification is not applicable or required in many cases
10855     //
10856
10857     if (IsAbstract() || IsInterface())
10858         return;
10859
10860 #ifdef FEATURE_COMINTEROP
10861     // Note that this is important for WinRT where redirected .NET interfaces appear on the interface
10862     // impl list but their methods are not implemented (the adapter only hides the WinRT methods, it
10863     // does not make up the .NET ones).
10864     if (bmtProp->fIsComObjectType)
10865         return;
10866 #endif // FEATURE_COMINTEROP
10867
10868     // Since interfaces aren't laid out in the vtable for stub dispatch, what we need to do
10869     // is try to find an implementation for every interface contract by iterating through
10870     // the interfaces not declared on a parent.
10871     BOOL fParentIsAbstract = FALSE;
10872     if (HasParent())
10873     {
10874         fParentIsAbstract = GetParentMethodTable()->IsAbstract();
10875     }
10876
10877     // If the parent is abstract, we need to check that each virtual method is implemented
10878     if (fParentIsAbstract)
10879     {
10880         // NOTE: Uses hMTData to avoid caching a MethodData object for the type being built.
10881         MethodTable::MethodIterator it(hMTData);
10882         for (; it.IsValid() && it.IsVirtual(); it.Next())
10883         {
10884             MethodDesc *pMD = it.GetMethodDesc();
10885             if (pMD->IsAbstract())
10886             {
10887                 MethodDesc *pDeclMD = it.GetDeclMethodDesc();
10888                 BuildMethodTableThrowException(IDS_CLASSLOAD_NOTIMPLEMENTED, pDeclMD->GetNameOnNonArrayClass());
10889             }
10890         }
10891     }
10892         
10893     DispatchMapTypeID * rgInterfaceDispatchMapTypeIDs = 
10894         new (GetStackingAllocator()) DispatchMapTypeID[bmtInterface->dwInterfaceMapSize];
10895         
10896     bmtInterfaceInfo::MapIterator intIt = bmtInterface->IterateInterfaceMap();
10897     for (; !intIt.AtEnd(); intIt.Next())
10898     {
10899         if (fParentIsAbstract || !intIt->IsImplementedByParent())
10900         {
10901             // Compute all TypeIDs for this interface (all duplicates in the interface map)
10902             UINT32 cInterfaceDuplicates;
10903             ComputeDispatchMapTypeIDs(
10904                 intIt->GetInterfaceType()->GetMethodTable(), 
10905                 &intIt->GetInterfaceType()->GetSubstitution(), 
10906                 rgInterfaceDispatchMapTypeIDs, 
10907                 bmtInterface->dwInterfaceMapSize, 
10908                 &cInterfaceDuplicates);
10909             _ASSERTE(cInterfaceDuplicates <= bmtInterface->dwInterfaceMapSize);
10910             _ASSERTE(cInterfaceDuplicates > 0);
10911                 
10912             // NOTE: This override does not cache the resulting MethodData object.
10913             MethodTable::MethodDataWrapper hData(MethodTable::GetMethodData(
10914                 rgInterfaceDispatchMapTypeIDs, 
10915                 cInterfaceDuplicates, 
10916                 intIt->GetInterfaceType()->GetMethodTable(), 
10917                 GetHalfBakedMethodTable()));
10918             MethodTable::MethodIterator it(hData);
10919             for (; it.IsValid() && it.IsVirtual(); it.Next())
10920             {
10921                 if (it.GetTarget().IsNull())
10922                 {
10923                     MethodDesc *pMD = it.GetDeclMethodDesc();
10924
10925                     if (!HasDefaultInterfaceImplementation(intIt->GetInterfaceType(), pMD))
10926                         BuildMethodTableThrowException(IDS_CLASSLOAD_NOTIMPLEMENTED, pMD->GetNameOnNonArrayClass());
10927                 }
10928             }
10929         }
10930     }
10931 }
10932
10933 INT32 __stdcall IsDefined(Module *pModule, mdToken token, TypeHandle attributeClass)
10934 {
10935     CONTRACTL
10936     {
10937         THROWS;
10938         GC_TRIGGERS;
10939     }
10940     CONTRACTL_END;
10941
10942     BOOL isDefined = FALSE;
10943
10944     IMDInternalImport *pInternalImport = pModule->GetMDImport();
10945     BOOL isSealed = FALSE;
10946
10947     HENUMInternalHolder hEnum(pInternalImport);
10948     TypeHandle caTH;
10949
10950     // Get the enum first but don't get any values
10951     hEnum.EnumInit(mdtCustomAttribute, token);
10952
10953     ULONG cMax = pInternalImport->EnumGetCount(&hEnum);
10954     if (cMax)
10955     {
10956         // we have something to look at
10957
10958
10959         if (!attributeClass.IsNull())
10960             isSealed = attributeClass.GetMethodTable()->IsSealed();
10961
10962         // Loop through the Attributes and look for the requested one
10963         mdCustomAttribute cv;
10964         while (pInternalImport->EnumNext(&hEnum, &cv))
10965         {
10966             //
10967             // fetch the ctor
10968             mdToken     tkCtor;
10969             IfFailThrow(pInternalImport->GetCustomAttributeProps(cv, &tkCtor));
10970             
10971             mdToken tkType = TypeFromToken(tkCtor);
10972             if(tkType != mdtMemberRef && tkType != mdtMethodDef)
10973                 continue; // we only deal with the ctor case
10974
10975             //
10976             // get the info to load the type, so we can check whether the current
10977             // attribute is a subtype of the requested attribute
10978             IfFailThrow(pInternalImport->GetParentToken(tkCtor, &tkType));
10979             
10980             _ASSERTE(TypeFromToken(tkType) == mdtTypeRef || TypeFromToken(tkType) == mdtTypeDef);
10981             // load the type
10982             if (isSealed)
10983             {
10984                 caTH=ClassLoader::LoadTypeDefOrRefThrowing(pModule, tkType,
10985                                                            ClassLoader::ReturnNullIfNotFound,
10986                                                            ClassLoader::FailIfUninstDefOrRef,
10987                                                            TypeFromToken(tkType) == mdtTypeDef ? tdAllTypes : tdNoTypes);
10988             }
10989             else
10990             {
10991                 caTH = ClassLoader::LoadTypeDefOrRefThrowing(pModule, tkType,
10992                                                              ClassLoader::ReturnNullIfNotFound,
10993                                                              ClassLoader::FailIfUninstDefOrRef);
10994             }
10995             if (caTH.IsNull())
10996                 continue;
10997
10998             // a null class implies all custom attribute
10999             if (!attributeClass.IsNull())
11000             {
11001                 if (isSealed)
11002                 {
11003                     if (attributeClass != caTH)
11004                         continue;
11005                 }
11006                 else
11007                 {
11008                     if (!caTH.CanCastTo(attributeClass))
11009                         continue;
11010                 }
11011             }
11012
11013             //
11014             // if we are here we got one
11015             isDefined = TRUE;
11016             break;
11017         }
11018     }
11019
11020     return isDefined;
11021 }
11022
11023 //*******************************************************************************
11024 VOID MethodTableBuilder::CheckForRemotingProxyAttrib()
11025 {
11026     STANDARD_VM_CONTRACT;
11027
11028 }
11029
11030
11031 //*******************************************************************************
11032 // Checks for a bunch of special interface names and if it matches then it sets
11033 // bmtProp->fIsMngStandardItf to TRUE. Additionally, it checks to see if the
11034 // type is an interface and if it has ComEventInterfaceAttribute custom attribute
11035 // set, then it sets bmtProp->fComEventItfType to true.
11036 //
11037 // NOTE: This only does anything when COM interop is enabled.
11038
11039 VOID MethodTableBuilder::CheckForSpecialTypes()
11040 {
11041 #ifdef FEATURE_COMINTEROP
11042     STANDARD_VM_CONTRACT;
11043
11044
11045     Module *pModule = GetModule();
11046     IMDInternalImport *pMDImport = pModule->GetMDImport();
11047
11048     // Check to see if this type is a managed standard interface. All the managed
11049     // standard interfaces live in mscorlib.dll so checking for that first
11050     // makes the strcmp that comes afterwards acceptable.
11051     if (pModule->IsSystem())
11052     {
11053         if (IsInterface())
11054         {
11055             LPCUTF8 pszClassName;
11056             LPCUTF8 pszClassNamespace;
11057             if (FAILED(pMDImport->GetNameOfTypeDef(GetCl(), &pszClassName, &pszClassNamespace)))
11058             {
11059                 pszClassName = pszClassNamespace = NULL;
11060             }
11061             if ((pszClassName != NULL) && (pszClassNamespace != NULL))
11062             {
11063                 LPUTF8 pszFullyQualifiedName = NULL;
11064                 MAKE_FULLY_QUALIFIED_NAME(pszFullyQualifiedName, pszClassNamespace, pszClassName);
11065
11066                 // This is just to give us a scope to break out of.
11067                 do
11068                 {
11069
11070 #define MNGSTDITF_BEGIN_INTERFACE(FriendlyName, strMngItfName, strUCOMMngItfName, strCustomMarshalerName, strCustomMarshalerCookie, strManagedViewName, NativeItfIID, bCanCastOnNativeItfQI) \
11071                     if (strcmp(strMngItfName, pszFullyQualifiedName) == 0) \
11072                     { \
11073                         bmtProp->fIsMngStandardItf = true; \
11074                         break; \
11075                     }
11076
11077 #define MNGSTDITF_DEFINE_METH_IMPL(FriendlyName, ECallMethName, MethName, MethSig, FcallDecl)
11078
11079 #define MNGSTDITF_END_INTERFACE(FriendlyName)
11080
11081 #include "mngstditflist.h"
11082
11083 #undef MNGSTDITF_BEGIN_INTERFACE
11084 #undef MNGSTDITF_DEFINE_METH_IMPL
11085 #undef MNGSTDITF_END_INTERFACE
11086
11087                 } while (FALSE);
11088
11089                 if (strcmp(pszFullyQualifiedName, g_CollectionsGenericCollectionItfName) == 0 ||
11090                     strcmp(pszFullyQualifiedName, g_CollectionsGenericReadOnlyCollectionItfName) == 0 ||
11091                     strcmp(pszFullyQualifiedName, g_CollectionsCollectionItfName) == 0)
11092                 {
11093                     // ICollection`1, ICollection and IReadOnlyCollection`1 are special cases the adapter is unaware of
11094                     bmtProp->fIsRedirectedInterface = true;
11095                 }
11096                 else
11097                 {
11098                     if (strcmp(pszFullyQualifiedName, WinMDAdapter::GetRedirectedTypeFullCLRName(WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_IEnumerable)) == 0 ||
11099                         strcmp(pszFullyQualifiedName, WinMDAdapter::GetRedirectedTypeFullCLRName(WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_IList)) == 0 ||
11100                         strcmp(pszFullyQualifiedName, WinMDAdapter::GetRedirectedTypeFullCLRName(WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_IDictionary)) == 0 ||
11101                         strcmp(pszFullyQualifiedName, WinMDAdapter::GetRedirectedTypeFullCLRName(WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_IReadOnlyList)) == 0 ||
11102                         strcmp(pszFullyQualifiedName, WinMDAdapter::GetRedirectedTypeFullCLRName(WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_IReadOnlyDictionary)) == 0 ||
11103                         strcmp(pszFullyQualifiedName, WinMDAdapter::GetRedirectedTypeFullCLRName(WinMDAdapter::RedirectedTypeIndex_System_Collections_IEnumerable)) == 0 ||
11104                         strcmp(pszFullyQualifiedName, WinMDAdapter::GetRedirectedTypeFullCLRName(WinMDAdapter::RedirectedTypeIndex_System_Collections_IList)) == 0 ||
11105                         strcmp(pszFullyQualifiedName, WinMDAdapter::GetRedirectedTypeFullCLRName(WinMDAdapter::RedirectedTypeIndex_System_IDisposable)) == 0)
11106                     {
11107                         bmtProp->fIsRedirectedInterface = true;
11108                     }
11109                 }
11110
11111                 // We want to allocate the per-type RCW data optional MethodTable field for
11112                 // 1. Redirected interfaces
11113                 // 2. Mscorlib-declared [WindowsRuntimeImport] interfaces
11114                 bmtProp->fNeedsRCWPerTypeData = (bmtProp->fIsRedirectedInterface || GetHalfBakedClass()->IsProjectedFromWinRT());
11115
11116                 if (!bmtProp->fNeedsRCWPerTypeData)
11117                 {
11118                     // 3. Non-generic IEnumerable
11119                     if (strcmp(pszFullyQualifiedName, g_CollectionsEnumerableItfName) == 0)
11120                     {
11121                         bmtProp->fNeedsRCWPerTypeData = true;
11122                     }
11123                 }
11124             }
11125         }
11126         else if (IsDelegate() && bmtGenerics->HasInstantiation())
11127         {
11128             // 4. Redirected delegates
11129             if (GetHalfBakedClass()->GetWinRTRedirectedTypeIndex()
11130                 != WinMDAdapter::RedirectedTypeIndex_Invalid)
11131             {
11132                 bmtProp->fNeedsRCWPerTypeData = true;
11133             }
11134         }
11135     }
11136     else if (bmtGenerics->HasInstantiation() && pModule->GetAssembly()->IsWinMD())
11137     {
11138         // 5. WinRT types with variance
11139         if (bmtGenerics->pVarianceInfo != NULL)
11140         {
11141             bmtProp->fNeedsRCWPerTypeData = true;
11142         }
11143         else if (IsInterface())
11144         {
11145             // 6. Windows.Foundation.Collections.IIterator`1
11146             LPCUTF8 pszClassName;
11147             LPCUTF8 pszClassNamespace;
11148             if (SUCCEEDED(pMDImport->GetNameOfTypeDef(GetCl(), &pszClassName, &pszClassNamespace)))
11149             {
11150                 LPUTF8 pszFullyQualifiedName = NULL;
11151                 MAKE_FULLY_QUALIFIED_NAME(pszFullyQualifiedName, pszClassNamespace, pszClassName);
11152
11153                 if (strcmp(pszFullyQualifiedName, g_WinRTIIteratorClassName) == 0)
11154                 {
11155                     bmtProp->fNeedsRCWPerTypeData = true;
11156                 }
11157             }
11158         }
11159     }
11160     else if ((IsInterface() || IsDelegate()) && 
11161         IsTdPublic(GetHalfBakedClass()->GetAttrClass()) && 
11162         GetHalfBakedClass()->GetWinRTRedirectedTypeIndex() != WinMDAdapter::RedirectedTypeIndex_Invalid)
11163     {
11164         // 7. System.Collections.Specialized.INotifyCollectionChanged
11165         // 8. System.Collections.Specialized.NotifyCollectionChangedEventHandler
11166         // 9. System.ComponentModel.INotifyPropertyChanged
11167         // 10. System.ComponentModel.PropertyChangedEventHandler
11168         // 11. System.Windows.Input.ICommand
11169         LPCUTF8 pszClassName;
11170         LPCUTF8 pszClassNamespace;
11171         if (SUCCEEDED(pMDImport->GetNameOfTypeDef(GetCl(), &pszClassName, &pszClassNamespace)))
11172         {
11173             LPUTF8 pszFullyQualifiedName = NULL;
11174             MAKE_FULLY_QUALIFIED_NAME(pszFullyQualifiedName, pszClassNamespace, pszClassName);
11175
11176             if (strcmp(pszFullyQualifiedName, g_INotifyCollectionChangedName) == 0 ||
11177                 strcmp(pszFullyQualifiedName, g_NotifyCollectionChangedEventHandlerName) == 0 ||
11178                 strcmp(pszFullyQualifiedName, g_INotifyPropertyChangedName) == 0 ||
11179                 strcmp(pszFullyQualifiedName, g_PropertyChangedEventHandlerName) == 0 ||
11180                 strcmp(pszFullyQualifiedName, g_ICommandName) == 0)
11181             {
11182                 bmtProp->fNeedsRCWPerTypeData = true;
11183             }
11184         }
11185     }
11186
11187     // Check to see if the type is a COM event interface (classic COM interop only).
11188     if (IsInterface() && !GetHalfBakedClass()->IsProjectedFromWinRT())
11189     {
11190         HRESULT hr = pMDImport->GetCustomAttributeByName(GetCl(), INTEROP_COMEVENTINTERFACE_TYPE, NULL, NULL);
11191         if (hr == S_OK)
11192         {
11193             bmtProp->fComEventItfType = true;
11194         }
11195     }
11196 #endif // FEATURE_COMINTEROP
11197 }
11198
11199 #ifdef FEATURE_READYTORUN
11200 //*******************************************************************************
11201 VOID MethodTableBuilder::CheckLayoutDependsOnOtherModules(MethodTable * pDependencyMT)
11202 {
11203     STANDARD_VM_CONTRACT;
11204
11205     // These cases are expected to be handled by the caller
11206     _ASSERTE(!(pDependencyMT == g_pObjectClass || pDependencyMT->IsTruePrimitive() || ((g_pEnumClass != NULL) && pDependencyMT->IsEnum())));
11207
11208     //
11209     // WARNING: Changes in this algorithm are potential ReadyToRun breaking changes !!!
11210     //
11211     // Track whether field layout of this type depend on information outside its containing module
11212     //
11213     // It is a stronger condition than MethodTable::IsInheritanceChainLayoutFixedInCurrentVersionBubble(). 
11214     // It has to remain fixed accross versioning changes in the module dependencies. In particular, it does 
11215     // not take into account NonVersionable attribute. Otherwise, adding NonVersionable attribute to existing
11216     // type would be ReadyToRun incompatible change.
11217     //
11218     if (pDependencyMT->GetModule() == GetModule())
11219     {
11220         if (!pDependencyMT->GetClass()->HasLayoutDependsOnOtherModules())
11221             return;
11222     }
11223
11224     GetHalfBakedClass()->SetHasLayoutDependsOnOtherModules();
11225 }
11226
11227 BOOL MethodTableBuilder::NeedsAlignedBaseOffset()
11228 {
11229     STANDARD_VM_CONTRACT;
11230
11231     //
11232     // WARNING: Changes in this algorithm are potential ReadyToRun breaking changes !!!
11233     //
11234     // This method returns whether the type needs aligned base offset in order to have layout resilient to 
11235     // base class layout changes.
11236     //
11237     if (IsValueClass())
11238         return FALSE;
11239
11240     // Always use the ReadyToRun field layout algorithm if the source IL image was ReadyToRun, independent on
11241     // whether ReadyToRun is actually enabled for the module. It is required to allow mixing and matching 
11242     // ReadyToRun images with NGen.
11243     if (!GetModule()->GetFile()->IsILImageReadyToRun())
11244     {
11245         // Always use ReadyToRun field layout algorithm to produce ReadyToRun images
11246         if (!IsReadyToRunCompilation())
11247             return FALSE;
11248     }
11249
11250     MethodTable * pParentMT = GetParentMethodTable();
11251
11252     // Trivial parents
11253     if (pParentMT == NULL || pParentMT == g_pObjectClass)
11254         return FALSE;
11255
11256     if (pParentMT->GetModule() == GetModule())
11257     {
11258         if (!pParentMT->GetClass()->HasLayoutDependsOnOtherModules())
11259             return FALSE;
11260     }
11261
11262     return TRUE;
11263 }
11264 #endif // FEATURE_READYTORUN
11265
11266 //*******************************************************************************
11267 //
11268 // Used by BuildMethodTable
11269 //
11270 // Set the HasFinalizer and HasCriticalFinalizer flags
11271 //
11272 VOID MethodTableBuilder::SetFinalizationSemantics()
11273 {
11274     STANDARD_VM_CONTRACT;
11275
11276     if (g_pObjectFinalizerMD && !IsInterface() && !IsValueClass())
11277     {
11278         WORD slot = g_pObjectFinalizerMD->GetSlot();
11279
11280         // Objects not derived from Object will get marked as having a finalizer, if they have 
11281         // sufficient virtual methods.  This will only be an issue if they can be allocated 
11282         // in the GC heap (which will cause all sorts of other problems).
11283         if (slot < bmtVT->cVirtualSlots && (*bmtVT)[slot].Impl().GetMethodDesc() != g_pObjectFinalizerMD)
11284         {
11285             GetHalfBakedMethodTable()->SetHasFinalizer();
11286
11287             // The need for a critical finalizer can be inherited from a parent.
11288             // Since we set this automatically for CriticalFinalizerObject
11289             // elsewhere, the code below is the means by which any derived class
11290             // picks up the attribute.
11291             if (HasParent() && GetParentMethodTable()->HasCriticalFinalizer())
11292             {
11293                 GetHalfBakedMethodTable()->SetHasCriticalFinalizer();
11294             }
11295         }
11296     }
11297 }
11298
11299 //*******************************************************************************
11300 //
11301 // Used by BuildMethodTable
11302 //
11303 // Perform relevant GC calculations for value classes
11304 //
11305 VOID MethodTableBuilder::HandleGCForValueClasses(MethodTable ** pByValueClassCache)
11306 {
11307     STANDARD_VM_CONTRACT;
11308
11309     DWORD i;
11310
11311     EEClass *pClass = GetHalfBakedClass();
11312     MethodTable *pMT = GetHalfBakedMethodTable();
11313
11314     FieldDesc *pFieldDescList = pClass->GetFieldDescList();
11315
11316     // Note that for value classes, the following calculation is only appropriate
11317     // when the instance is in its "boxed" state.
11318 #ifdef FEATURE_COLLECTIBLE_TYPES
11319     if (bmtFP->NumGCPointerSeries == 0 && pMT->Collectible())
11320     {
11321         // For collectible types, insert empty gc series
11322         CGCDescSeries *pSeries;
11323
11324         CGCDesc::Init( (PVOID) pMT, 1);
11325         pSeries = ((CGCDesc*)pMT)->GetLowestSeries();
11326         pSeries->SetSeriesSize( (size_t) (0) - (size_t) pMT->GetBaseSize());
11327         pSeries->SetSeriesOffset(OBJECT_SIZE);
11328     }
11329     else
11330 #endif // FEATURE_COLLECTIBLE_TYPES
11331     if (bmtFP->NumGCPointerSeries != 0)
11332     {
11333         CGCDescSeries *pSeries;
11334         CGCDescSeries *pHighest;
11335
11336         pMT->SetContainsPointers();
11337
11338         // Copy the pointer series map from the parent
11339         CGCDesc::Init( (PVOID) pMT, bmtFP->NumGCPointerSeries );
11340         if (bmtParent->NumParentPointerSeries != 0)
11341         {
11342             size_t ParentGCSize = CGCDesc::ComputeSize(bmtParent->NumParentPointerSeries);
11343             memcpy( (PVOID) (((BYTE*) pMT) - ParentGCSize),
11344                     (PVOID) (((BYTE*) GetParentMethodTable()) - ParentGCSize),
11345                     ParentGCSize - sizeof(size_t)   // sizeof(size_t) is the NumSeries count
11346                   );
11347
11348         }
11349
11350         // Build the pointer series map for this pointers in this instance
11351         pSeries = ((CGCDesc*)pMT)->GetLowestSeries();
11352         if (bmtFP->NumInstanceGCPointerFields)
11353         {
11354             // See gcdesc.h for an explanation of why we adjust by subtracting BaseSize
11355             pSeries->SetSeriesSize( (size_t) (bmtFP->NumInstanceGCPointerFields * TARGET_POINTER_SIZE) - (size_t) pMT->GetBaseSize());
11356             pSeries->SetSeriesOffset(bmtFP->GCPointerFieldStart + OBJECT_SIZE);
11357             pSeries++;
11358         }
11359
11360         // Insert GC info for fields which are by-value classes
11361         for (i = 0; i < bmtEnumFields->dwNumInstanceFields; i++)
11362         {
11363             if (pFieldDescList[i].IsByValue())
11364             {
11365                 MethodTable *pByValueMT = pByValueClassCache[i];
11366
11367                 if (pByValueMT->ContainsPointers())
11368                 {
11369                     // Offset of the by value class in the class we are building, does NOT include Object
11370                     DWORD       dwCurrentOffset = pFieldDescList[i].GetOffset_NoLogging();
11371
11372                     // The by value class may have more than one pointer series
11373                     CGCDescSeries * pByValueSeries = CGCDesc::GetCGCDescFromMT(pByValueMT)->GetLowestSeries();
11374                     SIZE_T dwNumByValueSeries = CGCDesc::GetCGCDescFromMT(pByValueMT)->GetNumSeries();
11375
11376                     for (SIZE_T j = 0; j < dwNumByValueSeries; j++)
11377                     {
11378                         size_t cbSeriesSize;
11379                         size_t cbSeriesOffset;
11380
11381                         _ASSERTE(pSeries <= CGCDesc::GetCGCDescFromMT(pMT)->GetHighestSeries());
11382
11383                         cbSeriesSize = pByValueSeries->GetSeriesSize();
11384
11385                         // Add back the base size of the by value class, since it's being transplanted to this class
11386                         cbSeriesSize += pByValueMT->GetBaseSize();
11387
11388                         // Subtract the base size of the class we're building
11389                         cbSeriesSize -= pMT->GetBaseSize();
11390
11391                         // Set current series we're building
11392                         pSeries->SetSeriesSize(cbSeriesSize);
11393
11394                         // Get offset into the value class of the first pointer field (includes a +Object)
11395                         cbSeriesOffset = pByValueSeries->GetSeriesOffset();
11396
11397                         // Add it to the offset of the by value class in our class
11398                         cbSeriesOffset += dwCurrentOffset;
11399
11400                         pSeries->SetSeriesOffset(cbSeriesOffset); // Offset of field
11401                         pSeries++;
11402                         pByValueSeries++;
11403                     }
11404                 }
11405             }
11406         }
11407
11408         // Adjust the inherited series - since the base size has increased by "# new field instance bytes", we need to
11409         // subtract that from all the series (since the series always has BaseSize subtracted for it - see gcdesc.h)
11410         pHighest = CGCDesc::GetCGCDescFromMT(pMT)->GetHighestSeries();
11411         while (pSeries <= pHighest)
11412         {
11413             CONSISTENCY_CHECK(CheckPointer(GetParentMethodTable()));
11414             pSeries->SetSeriesSize( pSeries->GetSeriesSize() - ((size_t) pMT->GetBaseSize() - (size_t) GetParentMethodTable()->GetBaseSize()) );
11415             pSeries++;
11416         }
11417
11418         _ASSERTE(pSeries-1 <= CGCDesc::GetCGCDescFromMT(pMT)->GetHighestSeries());
11419     }
11420
11421 }
11422
11423 //*******************************************************************************
11424 //
11425 // Used by BuildMethodTable
11426 //
11427 // Check for the presence of type equivalence. If present, make sure
11428 // it is permitted to be on this type.
11429 //
11430
11431 void MethodTableBuilder::CheckForTypeEquivalence(
11432     WORD                     cBuildingInterfaceList,
11433     BuildingInterfaceInfo_t *pBuildingInterfaceList)
11434 {
11435     STANDARD_VM_CONTRACT;
11436
11437 #ifdef FEATURE_TYPEEQUIVALENCE
11438     bmtProp->fIsTypeEquivalent = !!IsTypeDefEquivalent(GetCl(), GetModule());
11439
11440     if (bmtProp->fIsTypeEquivalent)
11441     {
11442         BOOL comImportOrEventInterface = IsComImport();
11443 #ifdef FEATURE_COMINTEROP
11444         comImportOrEventInterface = comImportOrEventInterface || bmtProp->fComEventItfType;
11445 #endif // FEATURE_COMINTEROP
11446
11447         BOOL fTypeEquivalentNotPermittedDueToType = !((comImportOrEventInterface && IsInterface()) || IsValueClass() || IsDelegate());
11448         BOOL fTypeEquivalentNotPermittedDueToGenerics = bmtGenerics->HasInstantiation();
11449
11450         if (fTypeEquivalentNotPermittedDueToType || fTypeEquivalentNotPermittedDueToGenerics)
11451         {
11452             BuildMethodTableThrowException(IDS_CLASSLOAD_EQUIVALENTBADTYPE);
11453         }
11454
11455         GetHalfBakedClass()->SetIsEquivalentType();
11456     }
11457
11458     bmtProp->fHasTypeEquivalence = bmtProp->fIsTypeEquivalent;
11459
11460     if (!bmtProp->fHasTypeEquivalence)
11461     {
11462         // fHasTypeEquivalence flag is inherited from interfaces so we can quickly detect
11463         // types that implement type equivalent interfaces
11464         for (WORD i = 0; i < cBuildingInterfaceList; i++)
11465         {
11466             MethodTable *pItfMT = pBuildingInterfaceList[i].m_pMethodTable;
11467             if (pItfMT->HasTypeEquivalence())
11468             {
11469                 bmtProp->fHasTypeEquivalence = true;
11470                 break;
11471             }
11472         }
11473     }
11474
11475     if (!bmtProp->fHasTypeEquivalence)
11476     {
11477         // fHasTypeEquivalence flag is "inherited" from generic arguments so we can quickly detect
11478         // types like List<Str> where Str is a structure with the TypeIdentifierAttribute.
11479         if (bmtGenerics->HasInstantiation() && !bmtGenerics->IsTypicalTypeDefinition())
11480         {
11481             Instantiation inst = bmtGenerics->GetInstantiation();
11482             for (DWORD i = 0; i < inst.GetNumArgs(); i++) 
11483             {
11484                 if (inst[i].HasTypeEquivalence())
11485                 {
11486                     bmtProp->fHasTypeEquivalence = true;
11487                     break;
11488                 }
11489             }
11490         }
11491     }
11492 #endif //FEATURE_TYPEEQUIVALENCE
11493 }
11494
11495 //*******************************************************************************
11496 //
11497 // Used by BuildMethodTable
11498 //
11499 // Before we make the final leap, make sure we've allocated all memory needed to
11500 // fill out the RID maps.
11501 //
11502 VOID MethodTableBuilder::EnsureRIDMapsCanBeFilled()
11503 {
11504     STANDARD_VM_CONTRACT;
11505
11506
11507     DWORD i;
11508
11509
11510     // Rather than call Ensure***CanBeStored() hundreds of times, we
11511     // will call it once on the largest token we find. This relies
11512     // on an invariant that RidMaps don't use some kind of sparse
11513     // allocation.
11514
11515     {
11516         mdMethodDef largest = mdMethodDefNil;
11517
11518         DeclaredMethodIterator it(*this);
11519         while (it.Next())
11520         {
11521             if (it.Token() > largest)
11522             {
11523                 largest = it.Token();
11524             }
11525         }
11526         if ( largest != mdMethodDefNil )
11527         {
11528             GetModule()->EnsureMethodDefCanBeStored(largest);
11529         }
11530     }
11531
11532     {
11533         mdFieldDef largest = mdFieldDefNil;
11534
11535         for (i = 0; i < bmtMetaData->cFields; i++)
11536         {
11537             if (bmtMetaData->pFields[i] > largest)
11538             {
11539                 largest = bmtMetaData->pFields[i];
11540             }
11541         }
11542         if ( largest != mdFieldDefNil )
11543         {
11544             GetModule()->EnsureFieldDefCanBeStored(largest);
11545         }
11546     }
11547 }
11548
11549 #ifdef FEATURE_COMINTEROP
11550 //*******************************************************************************
11551 void MethodTableBuilder::GetCoClassAttribInfo()
11552 {
11553     STANDARD_VM_CONTRACT;
11554
11555     if (!GetHalfBakedClass()->IsProjectedFromWinRT()) // ignore classic COM interop CA on WinRT interfaces
11556     {
11557         // Retrieve the CoClassAttribute CA.
11558         HRESULT hr = GetMDImport()->GetCustomAttributeByName(GetCl(), INTEROP_COCLASS_TYPE, NULL, NULL);
11559         if (hr == S_OK)
11560         {
11561             // COM class interfaces may lazily populate the m_pCoClassForIntf field of EEClass. This field is
11562             // optional so we must ensure the optional field descriptor has been allocated.
11563             EnsureOptionalFieldsAreAllocated(GetHalfBakedClass(), m_pAllocMemTracker, GetLoaderAllocator()->GetLowFrequencyHeap());
11564             SetIsComClassInterface();
11565         }
11566     }
11567 }
11568 #endif // FEATURE_COMINTEROP
11569
11570 //*******************************************************************************
11571 void MethodTableBuilder::bmtMethodImplInfo::AddMethodImpl(
11572     bmtMDMethod * pImplMethod, bmtMethodHandle declMethod, mdToken declToken,
11573     StackingAllocator * pStackingAllocator)
11574 {
11575     STANDARD_VM_CONTRACT;
11576
11577     CONSISTENCY_CHECK(CheckPointer(pImplMethod));
11578     CONSISTENCY_CHECK(!declMethod.IsNull());
11579     if (pIndex >= cMaxIndex)
11580     {
11581         DWORD newEntriesCount = 0;
11582
11583         if (!ClrSafeInt<DWORD>::multiply(cMaxIndex, 2, newEntriesCount))
11584             ThrowHR(COR_E_OVERFLOW);
11585
11586         if (newEntriesCount == 0)
11587             newEntriesCount = 10;
11588
11589         // If we have to grow this array, we will not free the old array before we clean up the BuildMethodTable operation
11590         // because this is a stacking allocator. However, the old array will get freed when all the stack allocator is freed.
11591         Entry *rgEntriesNew = new (pStackingAllocator) Entry[newEntriesCount];
11592         memcpy(rgEntriesNew, rgEntries, sizeof(Entry) * cMaxIndex);
11593
11594         // Start using newly allocated array.
11595         rgEntries = rgEntriesNew;
11596         cMaxIndex = newEntriesCount;
11597     }
11598     rgEntries[pIndex++] = Entry(pImplMethod, declMethod, declToken);
11599 }
11600
11601 //*******************************************************************************
11602 // Returns TRUE if tok acts as a body for any methodImpl entry. FALSE, otherwise.
11603 BOOL MethodTableBuilder::bmtMethodImplInfo::IsBody(mdToken tok)
11604 {
11605     LIMITED_METHOD_CONTRACT;
11606     CONSISTENCY_CHECK(TypeFromToken(tok) == mdtMethodDef);
11607     for (DWORD i = 0; i < pIndex; i++)
11608     {
11609         if (GetBodyMethodDesc(i)->GetMemberDef() == tok)
11610         {
11611             return TRUE;
11612         }
11613     }
11614     return FALSE;
11615 }
11616
11617 //*******************************************************************************
11618 BYTE *
11619 MethodTableBuilder::AllocateFromHighFrequencyHeap(S_SIZE_T cbMem)
11620 {
11621     CONTRACTL
11622     {
11623         THROWS;
11624         GC_NOTRIGGER;
11625         MODE_ANY;
11626     }
11627     CONTRACTL_END;
11628     return (BYTE *)GetMemTracker()->Track(
11629         GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem(cbMem));
11630 }
11631
11632 //*******************************************************************************
11633 BYTE *
11634 MethodTableBuilder::AllocateFromLowFrequencyHeap(S_SIZE_T cbMem)
11635 {
11636     CONTRACTL
11637     {
11638         THROWS;
11639         GC_NOTRIGGER;
11640         MODE_ANY;
11641     }
11642     CONTRACTL_END;
11643     return (BYTE *)GetMemTracker()->Track(
11644         GetLoaderAllocator()->GetLowFrequencyHeap()->AllocMem(cbMem));
11645 }
11646
11647 //-------------------------------------------------------------------------------
11648 // Make best-case effort to obtain an image name for use in an error message.
11649 //
11650 // This routine must expect to be called before the this object is fully loaded.
11651 // It can return an empty if the name isn't available or the object isn't initialized
11652 // enough to get a name, but it mustn't crash.
11653 //-------------------------------------------------------------------------------
11654 LPCWSTR MethodTableBuilder::GetPathForErrorMessages()
11655 {
11656     STANDARD_VM_CONTRACT;
11657
11658     return GetModule()->GetPathForErrorMessages();
11659 }
11660
11661 BOOL MethodTableBuilder::ChangesImplementationOfVirtualSlot(SLOT_INDEX idx)
11662 {
11663     STANDARD_VM_CONTRACT;
11664
11665     BOOL fChangesImplementation = TRUE;
11666
11667     _ASSERTE(idx < bmtVT->cVirtualSlots);
11668
11669     if (HasParent() && idx < GetParentMethodTable()->GetNumVirtuals())
11670     {
11671         _ASSERTE(idx < bmtParent->pSlotTable->GetSlotCount());
11672         bmtMethodHandle VTImpl = (*bmtVT)[idx].Impl();
11673         bmtMethodHandle ParentImpl = (*bmtParent)[idx].Impl();
11674
11675         fChangesImplementation = VTImpl != ParentImpl;
11676
11677         // See code:MethodTableBuilder::SetupMethodTable2 and its logic
11678         // for handling MethodImpl's on parent classes which affect non interface
11679         // methods.
11680         if (!fChangesImplementation && (ParentImpl.GetSlotIndex() != idx))
11681             fChangesImplementation = TRUE;
11682     }
11683
11684     return fChangesImplementation;
11685 }
11686
11687 // Must be called prior to setting the value of any optional field on EEClass (on a debug build an assert will
11688 // fire if this invariant is violated).
11689 void MethodTableBuilder::EnsureOptionalFieldsAreAllocated(EEClass *pClass, AllocMemTracker *pamTracker, LoaderHeap *pHeap)
11690 {
11691     STANDARD_VM_CONTRACT;
11692
11693     if (pClass->HasOptionalFields())
11694         return;
11695
11696     EEClassOptionalFields *pOptFields = (EEClassOptionalFields*)
11697         pamTracker->Track(pHeap->AllocMem(S_SIZE_T(sizeof(EEClassOptionalFields))));
11698
11699     // Initialize default values for all optional fields.
11700     pOptFields->Init();
11701
11702     // Attach optional fields to the class.
11703     pClass->AttachOptionalFields(pOptFields);
11704 }
11705
11706 //---------------------------------------------------------------------------------------
11707 // 
11708 // Gather information about a generic type
11709 // - number of parameters
11710 // - variance annotations
11711 // - dictionaries
11712 // - sharability
11713 // 
11714 //static
11715 void 
11716 MethodTableBuilder::GatherGenericsInfo(
11717     Module *          pModule, 
11718     mdTypeDef         cl, 
11719     Instantiation     inst, 
11720     bmtGenericsInfo * bmtGenericsInfo)
11721 {
11722     CONTRACTL
11723     {
11724         STANDARD_VM_CHECK;
11725         PRECONDITION(GetThread() != NULL);
11726         PRECONDITION(CheckPointer(pModule));
11727         PRECONDITION(CheckPointer(bmtGenericsInfo));
11728     }
11729     CONTRACTL_END;
11730
11731     IMDInternalImport * pInternalImport = pModule->GetMDImport();
11732
11733     // Enumerate the formal type parameters
11734     HENUMInternal   hEnumGenericPars;
11735     HRESULT hr = pInternalImport->EnumInit(mdtGenericParam, cl, &hEnumGenericPars);
11736     if (FAILED(hr))
11737         pModule->GetAssembly()->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
11738
11739     DWORD numGenericArgs = pInternalImport->EnumGetCount(&hEnumGenericPars);
11740
11741     // Work out what kind of EEClass we're creating w.r.t. generics.  If there
11742     // are no generics involved this will be a VMFLAG_NONGENERIC.
11743     BOOL fHasVariance = FALSE;
11744     if (numGenericArgs > 0)
11745     {
11746         // Generic type verification
11747         {
11748             DWORD   dwAttr;
11749             mdToken tkParent;
11750             if (FAILED(pInternalImport->GetTypeDefProps(cl, &dwAttr, &tkParent)))
11751             {
11752                 pModule->GetAssembly()->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
11753             }
11754             // A generic with explicit layout is not allowed.
11755             if (IsTdExplicitLayout(dwAttr))
11756             {
11757                 pModule->GetAssembly()->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_EXPLICIT_GENERIC);
11758             }
11759         }
11760         
11761         bmtGenericsInfo->numDicts = 1;
11762         
11763         mdGenericParam tkTyPar;
11764         bmtGenericsInfo->pVarianceInfo = new (&GetThread()->m_MarshalAlloc) BYTE[numGenericArgs];
11765
11766         // If it has generic arguments but none have been specified, then load the instantiation at the formals
11767         if (inst.IsEmpty())
11768         {
11769             bmtGenericsInfo->fTypicalInstantiation = TRUE;
11770             S_UINT32 scbAllocSize = S_UINT32(numGenericArgs) * S_UINT32(sizeof(TypeHandle));
11771             TypeHandle * genericArgs = (TypeHandle *) GetThread()->m_MarshalAlloc.Alloc(scbAllocSize);
11772
11773             inst = Instantiation(genericArgs, numGenericArgs);
11774
11775             bmtGenericsInfo->fSharedByGenericInstantiations = FALSE;
11776         }
11777         else
11778         {
11779             bmtGenericsInfo->fTypicalInstantiation = FALSE;
11780
11781             bmtGenericsInfo->fSharedByGenericInstantiations = TypeHandle::IsCanonicalSubtypeInstantiation(inst);
11782             _ASSERTE(bmtGenericsInfo->fSharedByGenericInstantiations == ClassLoader::IsSharableInstantiation(inst));
11783
11784 #ifdef _DEBUG
11785             // Set typical instantiation MethodTable
11786             {
11787                 MethodTable * pTypicalInstantiationMT = pModule->LookupTypeDef(cl).AsMethodTable();
11788                 // Typical instantiation was already loaded by code:ClassLoader::LoadApproxTypeThrowing
11789                 _ASSERTE(pTypicalInstantiationMT != NULL);
11790                 bmtGenericsInfo->dbg_pTypicalInstantiationMT = pTypicalInstantiationMT;
11791             }
11792 #endif //_DEBUG
11793         }
11794         
11795         TypeHandle * pDestInst = (TypeHandle *)inst.GetRawArgs();
11796         for (unsigned int i = 0; i < numGenericArgs; i++)
11797         {
11798             pInternalImport->EnumNext(&hEnumGenericPars, &tkTyPar);
11799             DWORD flags;
11800             if (FAILED(pInternalImport->GetGenericParamProps(tkTyPar, NULL, &flags, NULL, NULL, NULL)))
11801             {
11802                 pModule->GetAssembly()->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
11803             }
11804             
11805             if (bmtGenericsInfo->fTypicalInstantiation)
11806             {
11807                 // code:Module.m_GenericParamToDescMap maps generic parameter RIDs to TypeVarTypeDesc
11808                 // instances so that we do not leak by allocating them all over again, if the type
11809                 // repeatedly fails to load.
11810                 TypeVarTypeDesc *pTypeVarTypeDesc = pModule->LookupGenericParam(tkTyPar);
11811                 if (pTypeVarTypeDesc == NULL)
11812                 {
11813                     // Do NOT use the alloc tracker for this memory as we need it stay allocated even if the load fails.
11814                     void *mem = (void *)pModule->GetLoaderAllocator()->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(TypeVarTypeDesc)));
11815                     pTypeVarTypeDesc = new (mem) TypeVarTypeDesc(pModule, cl, i, tkTyPar);
11816
11817                     // No race here - the row in GenericParam table is owned exclusively by this type and we
11818                     // are holding a lock preventing other threads from concurrently loading it.
11819                     pModule->StoreGenericParamThrowing(tkTyPar, pTypeVarTypeDesc);
11820                 }
11821                 pDestInst[i] = TypeHandle(pTypeVarTypeDesc);
11822             }
11823
11824             DWORD varianceAnnotation = flags & gpVarianceMask;
11825             bmtGenericsInfo->pVarianceInfo[i] = static_cast<BYTE>(varianceAnnotation);
11826             if (varianceAnnotation != gpNonVariant)               
11827             {
11828                 if (varianceAnnotation != gpContravariant && varianceAnnotation != gpCovariant)
11829                 {
11830                     pModule->GetAssembly()->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADVARIANCE);
11831                 }
11832                 else
11833                 {
11834                     fHasVariance = TRUE;
11835                 }
11836             }
11837         }
11838
11839         if (!fHasVariance)
11840             bmtGenericsInfo->pVarianceInfo = NULL;
11841     }
11842     else
11843     {
11844         bmtGenericsInfo->fTypicalInstantiation = FALSE;
11845         bmtGenericsInfo->fSharedByGenericInstantiations = FALSE;
11846         bmtGenericsInfo->numDicts = 0;
11847     }
11848
11849     bmtGenericsInfo->fContainsGenericVariables = MethodTable::ComputeContainsGenericVariables(inst);
11850
11851     SigTypeContext typeContext(inst, Instantiation());
11852     bmtGenericsInfo->typeContext = typeContext;
11853 } // MethodTableBuilder::GatherGenericsInfo
11854
11855 //=======================================================================
11856 // This is invoked from the class loader while building the internal structures for a type
11857 // This function should check if explicit layout metadata exists.
11858 //
11859 // Returns:
11860 //  TRUE    - yes, there's layout metadata
11861 //  FALSE   - no, there's no layout.
11862 //  fail    - throws a typeload exception
11863 //
11864 // If TRUE,
11865 //   *pNLType            gets set to nltAnsi or nltUnicode
11866 //   *pPackingSize       declared packing size
11867 //   *pfExplicitoffsets  offsets explicit in metadata or computed?
11868 //=======================================================================
11869 BOOL HasLayoutMetadata(Assembly* pAssembly, IMDInternalImport* pInternalImport, mdTypeDef cl, MethodTable* pParentMT, BYTE* pPackingSize, BYTE* pNLTType, BOOL* pfExplicitOffsets)
11870 {
11871     CONTRACTL
11872     {
11873         THROWS;
11874         GC_TRIGGERS;
11875         MODE_ANY;
11876         PRECONDITION(CheckPointer(pInternalImport));
11877         PRECONDITION(CheckPointer(pPackingSize));
11878         PRECONDITION(CheckPointer(pNLTType));
11879         PRECONDITION(CheckPointer(pfExplicitOffsets));
11880     }
11881     CONTRACTL_END;
11882
11883     HRESULT hr;
11884     ULONG clFlags;
11885
11886     if (FAILED(pInternalImport->GetTypeDefProps(cl, &clFlags, NULL)))
11887     {
11888         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
11889     }
11890
11891     if (IsTdAutoLayout(clFlags))
11892     {
11893         return FALSE;
11894     }
11895     else if (IsTdSequentialLayout(clFlags))
11896     {
11897         *pfExplicitOffsets = FALSE;
11898     }
11899     else if (IsTdExplicitLayout(clFlags))
11900     {
11901         *pfExplicitOffsets = TRUE;
11902     }
11903     else
11904     {
11905         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
11906     }
11907
11908     // We now know this class has seq. or explicit layout. Ensure the parent does too.
11909     if (pParentMT && !(pParentMT->IsObjectClass() || pParentMT->IsValueTypeClass()) && !(pParentMT->HasLayout()))
11910         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
11911
11912     if (IsTdAnsiClass(clFlags))
11913     {
11914         *pNLTType = nltAnsi;
11915     }
11916     else if (IsTdUnicodeClass(clFlags) || IsTdAutoClass(clFlags))
11917     {
11918         *pNLTType = nltUnicode;
11919     }
11920     else
11921     {
11922         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
11923     }
11924
11925     DWORD dwPackSize;
11926     hr = pInternalImport->GetClassPackSize(cl, &dwPackSize);
11927     if (FAILED(hr) || dwPackSize == 0)
11928         dwPackSize = DEFAULT_PACKING_SIZE;
11929
11930     // This has to be reduced to a BYTE value, so we had better make sure it fits. If
11931     // not, we'll throw an exception instead of trying to munge the value to what we
11932     // think the user might want.
11933     if (!FitsInU1((UINT64)(dwPackSize)))
11934     {
11935         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
11936     }
11937
11938     *pPackingSize = (BYTE)dwPackSize;
11939
11940     return TRUE;
11941 }
11942
11943 //---------------------------------------------------------------------------------------
11944 // 
11945 // This service is called for normal classes -- and for the pseudo class we invent to
11946 // hold the module's public members.
11947 // 
11948 //static
11949 TypeHandle 
11950 ClassLoader::CreateTypeHandleForTypeDefThrowing(
11951     Module *          pModule, 
11952     mdTypeDef         cl, 
11953     Instantiation     inst, 
11954     AllocMemTracker * pamTracker)
11955 {
11956     CONTRACT(TypeHandle)
11957     {
11958         STANDARD_VM_CHECK;
11959         PRECONDITION(GetThread() != NULL);
11960         PRECONDITION(CheckPointer(pModule));
11961         POSTCONDITION(!RETVAL.IsNull());
11962         POSTCONDITION(CheckPointer(RETVAL.GetMethodTable()));
11963     }
11964     CONTRACT_END;
11965
11966     MethodTable * pMT = NULL;
11967
11968     Thread * pThread = GetThread();
11969
11970     MethodTable * pParentMethodTable = NULL;
11971     SigPointer    parentInst;
11972     mdTypeDef     tdEnclosing = mdTypeDefNil;
11973     DWORD         cInterfaces;
11974     BuildingInterfaceInfo_t * pInterfaceBuildInfo = NULL;
11975     IMDInternalImport *       pInternalImport = NULL;
11976     LayoutRawFieldInfo *      pLayoutRawFieldInfos = NULL;
11977     MethodTableBuilder::bmtGenericsInfo genericsInfo;
11978     
11979     Assembly * pAssembly = pModule->GetAssembly();
11980     pInternalImport = pModule->GetMDImport();
11981
11982     if (TypeFromToken(cl) != mdtTypeDef || !pInternalImport->IsValidToken(cl))
11983     {
11984         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
11985     }
11986
11987     // GetCheckpoint for the thread-based allocator
11988     // This checkpoint provides a scope for all transient allocations of data structures
11989     // used during class loading.
11990     // <NICE> Ideally a debug/checked build should pass around tokens indicating the Checkpoint
11991     // being used and check these dynamically </NICE>
11992     CheckPointHolder cph(pThread->m_MarshalAlloc.GetCheckpoint()); //hold checkpoint for autorelease
11993     
11994     // Gather up generics info
11995     MethodTableBuilder::GatherGenericsInfo(pModule, cl, inst, &genericsInfo);
11996
11997     Module * pLoaderModule = pModule;
11998     if (!inst.IsEmpty())
11999     {
12000         pLoaderModule = ClassLoader::ComputeLoaderModuleWorker(
12001             pModule, 
12002             cl, 
12003             inst, 
12004             Instantiation());
12005         pLoaderModule->GetLoaderAllocator()->EnsureInstantiation(pModule, inst);
12006     }
12007
12008     LoaderAllocator * pAllocator = pLoaderModule->GetLoaderAllocator();
12009
12010     {
12011         // As this is loading a parent type, we are allowed to override the load type limit.
12012         OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOAD_APPROXPARENTS);
12013         pParentMethodTable = LoadApproxParentThrowing(pModule, cl, &parentInst, &genericsInfo.typeContext);
12014     }
12015
12016     if (pParentMethodTable != NULL)
12017     {
12018         // Since methods on System.Array assume the layout of arrays, we can not allow
12019         // subclassing of arrays, it is sealed from the users point of view.
12020         // Value types and enums should be sealed - disable inheritting from them (we cannot require sealed 
12021         // flag because of AppCompat)
12022         if (pParentMethodTable->IsSealed() || 
12023             (pParentMethodTable == g_pArrayClass) || 
12024             pParentMethodTable->IsValueType())
12025         {
12026             pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_SEALEDPARENT);
12027         }
12028
12029         DWORD dwTotalDicts = genericsInfo.numDicts + pParentMethodTable->GetNumDicts();
12030         if (!FitsIn<WORD>(dwTotalDicts))
12031         {
12032             pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_TOOMANYGENERICARGS);
12033         }
12034         genericsInfo.numDicts = static_cast<WORD>(dwTotalDicts);
12035     }
12036
12037     GetEnclosingClassThrowing(pInternalImport, pModule, cl, &tdEnclosing);
12038
12039     BYTE nstructPackingSize = 0, nstructNLT = 0;
12040     BOOL fExplicitOffsets = FALSE;
12041     // NOTE: HasLayoutMetadata does not load classes
12042     BOOL fHasLayout = 
12043         !genericsInfo.fContainsGenericVariables && 
12044         HasLayoutMetadata(
12045             pModule->GetAssembly(), 
12046             pInternalImport, 
12047             cl, 
12048             pParentMethodTable, 
12049             &nstructPackingSize, 
12050             &nstructNLT, 
12051             &fExplicitOffsets);
12052
12053     BOOL fIsEnum = ((g_pEnumClass != NULL) && (pParentMethodTable == g_pEnumClass));
12054
12055     // enums may not have layout because they derive from g_pEnumClass and that has no layout
12056     // this is enforced by HasLayoutMetadata above
12057     _ASSERTE(!(fIsEnum && fHasLayout));
12058
12059     // This is a delegate class if it derives from MulticastDelegate (we do not allow single cast delegates)
12060     BOOL fIsDelegate = pParentMethodTable && pParentMethodTable == g_pMulticastDelegateClass;
12061
12062     // Create a EEClass entry for it, filling out a few fields, such as the parent class token
12063     // (and the generic type should we be creating an instantiation)
12064     EEClass * pClass = MethodTableBuilder::CreateClass(
12065         pModule, 
12066         cl, 
12067         fHasLayout, 
12068         fIsDelegate, 
12069         fIsEnum, 
12070         &genericsInfo, 
12071         pAllocator, 
12072         pamTracker);
12073
12074     if ((pParentMethodTable != NULL) && (pParentMethodTable == g_pDelegateClass))
12075     {
12076         // Note we do not allow single cast delegates
12077         if (pModule->GetAssembly() != SystemDomain::SystemAssembly())
12078         {
12079             pAssembly->ThrowTypeLoadException(pInternalImport, cl, BFA_CANNOT_INHERIT_FROM_DELEGATE);
12080         }
12081
12082 #ifdef _DEBUG
12083         // Only MultiCastDelegate should inherit from Delegate
12084         LPCUTF8 className;
12085         LPCUTF8 nameSpace;
12086         if (FAILED(pInternalImport->GetNameOfTypeDef(cl, &className, &nameSpace)))
12087         {
12088             className = nameSpace = "Invalid TypeDef record";
12089         }
12090         BAD_FORMAT_NOTHROW_ASSERT(strcmp(className, "MulticastDelegate") == 0);
12091 #endif
12092     }
12093
12094     if (fIsDelegate)
12095     {
12096         if (!pClass->IsSealed())
12097         {
12098             pAssembly->ThrowTypeLoadException(pInternalImport, cl, BFA_DELEGATE_CLASS_NOTSEALED);
12099         }
12100
12101         pClass->SetIsDelegate();
12102     }
12103
12104     if (tdEnclosing != mdTypeDefNil)
12105     {
12106         pClass->SetIsNested();
12107         THROW_BAD_FORMAT_MAYBE(IsTdNested(pClass->GetProtection()), VLDTR_E_TD_ENCLNOTNESTED, pModule);
12108     }
12109     else if (IsTdNested(pClass->GetProtection()))
12110     {
12111         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12112     }
12113     
12114     // We only permit generic interfaces and delegates to have variant type parameters
12115     if (genericsInfo.pVarianceInfo != NULL && !pClass->IsInterface() && !fIsDelegate)
12116     {
12117         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_VARIANCE_CLASS);
12118     }
12119     
12120     // Now load all the interfaces
12121     HENUMInternalHolder hEnumInterfaceImpl(pInternalImport);
12122     hEnumInterfaceImpl.EnumInit(mdtInterfaceImpl, cl);
12123     
12124     cInterfaces = pInternalImport->EnumGetCount(&hEnumInterfaceImpl);
12125     
12126     if (cInterfaces != 0)
12127     {
12128         DWORD i;
12129         
12130         // Allocate the BuildingInterfaceList table
12131         pInterfaceBuildInfo = new (&GetThread()->m_MarshalAlloc) BuildingInterfaceInfo_t[cInterfaces];
12132         
12133         mdInterfaceImpl ii;
12134         for (i = 0; pInternalImport->EnumNext(&hEnumInterfaceImpl, &ii); i++)
12135         {
12136             // Get properties on this interface
12137             mdTypeRef crInterface;
12138             if (FAILED(pInternalImport->GetTypeOfInterfaceImpl(ii, &crInterface)))
12139             {
12140                 pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12141             }
12142             // validate the token
12143             mdToken crIntType = 
12144                 (RidFromToken(crInterface) && pInternalImport->IsValidToken(crInterface)) ? 
12145                 TypeFromToken(crInterface) : 
12146                 0;
12147             switch (crIntType)
12148             {
12149                 case mdtTypeDef:
12150                 case mdtTypeRef:
12151                 case mdtTypeSpec:
12152                     break;
12153                 default:
12154                     pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_INTERFACENULL);
12155             }
12156             
12157             TypeHandle intType;
12158             
12159             {
12160                 OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOAD_APPROXPARENTS);
12161                 intType = LoadApproxTypeThrowing(pModule, crInterface, NULL, &genericsInfo.typeContext);
12162             }
12163             
12164             pInterfaceBuildInfo[i].m_pMethodTable = intType.AsMethodTable();
12165             if (pInterfaceBuildInfo[i].m_pMethodTable == NULL)
12166             {
12167                 pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_INTERFACENULL);
12168             }
12169             
12170             // Ensure this is an interface
12171             if (!pInterfaceBuildInfo[i].m_pMethodTable->IsInterface())
12172             {
12173                  pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_NOTINTERFACE);
12174             }
12175             
12176             // Check interface for use of variant type parameters
12177             if ((genericsInfo.pVarianceInfo != NULL) && (TypeFromToken(crInterface) == mdtTypeSpec))
12178             {
12179                 ULONG cSig;
12180                 PCCOR_SIGNATURE pSig;
12181                 if (FAILED(pInternalImport->GetTypeSpecFromToken(crInterface, &pSig, &cSig)))
12182                 {
12183                     pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12184                 }
12185                 // Interfaces behave covariantly
12186                 if (!EEClass::CheckVarianceInSig(
12187                         genericsInfo.GetNumGenericArgs(), 
12188                         genericsInfo.pVarianceInfo, 
12189                         pModule, 
12190                         SigPointer(pSig, cSig), 
12191                         gpCovariant))
12192                 {
12193                     pAssembly->ThrowTypeLoadException(
12194                         pInternalImport, 
12195                         cl, 
12196                         IDS_CLASSLOAD_VARIANCE_IN_INTERFACE);
12197                 }
12198             }
12199         }
12200         _ASSERTE(i == cInterfaces);
12201     }
12202     
12203     if (fHasLayout ||
12204         /* Variant delegates should not have any instance fields of the variant.
12205            type parameter. For now, we just completely disallow all fields even
12206            if they are non-variant or static, as it is not a useful scenario.
12207            @TODO: A more logical place for this check would be in 
12208            MethodTableBuilder::EnumerateClassMembers() */
12209         (fIsDelegate && genericsInfo.pVarianceInfo))
12210     {
12211         // check for fields and variance
12212         ULONG               cFields;
12213         HENUMInternalHolder hEnumField(pInternalImport);
12214         hEnumField.EnumInit(mdtFieldDef, cl);
12215
12216         cFields = pInternalImport->EnumGetCount(&hEnumField);
12217
12218         if ((cFields != 0) && fIsDelegate && (genericsInfo.pVarianceInfo != NULL))
12219         {
12220             pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_VARIANCE_IN_DELEGATE);
12221         }
12222
12223         if (fHasLayout)
12224         {
12225             // Though we fail on this condition, we should never run into it.
12226             CONSISTENCY_CHECK(nstructPackingSize != 0);
12227             // MD Val check: PackingSize
12228             if((nstructPackingSize == 0)  || 
12229                (nstructPackingSize > 128) || 
12230                (nstructPackingSize & (nstructPackingSize-1)))
12231             {
12232                 THROW_BAD_FORMAT_MAYBE(!"ClassLayout:Invalid PackingSize", BFA_BAD_PACKING_SIZE, pModule);
12233                 pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12234             }
12235
12236             pLayoutRawFieldInfos = (LayoutRawFieldInfo *)GetThread()->m_MarshalAlloc.Alloc(
12237                 (S_UINT32(1) + S_UINT32(cFields)) * S_UINT32(sizeof(LayoutRawFieldInfo)));
12238             
12239             {
12240                 // Warning: this can load classes
12241                 CONTRACT_VIOLATION(LoadsTypeViolation);
12242
12243                 // Set a flag that allows us to break dead-locks that are result of the LoadsTypeViolation
12244                 ThreadStateNCStackHolder tsNC(TRUE, Thread::TSNC_LoadsTypeViolation);
12245
12246                 EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing(
12247                     cl, 
12248                     nstructPackingSize, 
12249                     nstructNLT, 
12250 #ifdef FEATURE_COMINTEROP
12251                     pClass->IsProjectedFromWinRT(),
12252 #endif // FEATURE_COMINTEROP
12253                     fExplicitOffsets, 
12254                     pParentMethodTable, 
12255                     cFields, 
12256                     &hEnumField, 
12257                     pModule, 
12258                     &genericsInfo.typeContext, 
12259                     &(((LayoutEEClass *)pClass)->m_LayoutInfo), 
12260                     pLayoutRawFieldInfos, 
12261                     pAllocator, 
12262                     pamTracker);
12263             }
12264         }
12265     }
12266
12267     // Resolve this class, given that we know now that all of its dependencies are loaded and resolved.
12268     // !!! This must be the last thing in this TRY block: if MethodTableBuilder succeeds, it has published the class
12269     // and there is no going back.
12270     MethodTableBuilder builder(
12271         NULL,
12272         pClass,
12273         &GetThread()->m_MarshalAlloc, 
12274         pamTracker);
12275
12276     pMT = builder.BuildMethodTableThrowing(
12277         pAllocator, 
12278         pLoaderModule, 
12279         pModule, 
12280         cl, 
12281         pInterfaceBuildInfo, 
12282         pLayoutRawFieldInfos, 
12283         pParentMethodTable, 
12284         &genericsInfo, 
12285         parentInst, 
12286         (WORD)cInterfaces);
12287
12288     RETURN(TypeHandle(pMT));
12289 } // ClassLoader::CreateTypeHandleForTypeDefThrowing