9308844ac977383200173a6b4a816432e332dc65
[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     HRESULT hrToThrow;
93
94     //<TODO>============================================================================
95     // vtabsize and static size need to be converted from pointer sizes to #'s
96     // of bytes this will be very important for 64 bit NT!
97     // We will need to call on IMetaDataLoad to get these sizes and fill out the
98     // tables
99
100     // From the classref call on metadata to resolve the classref and check scope
101     // to make sure that this class is in the same scope otherwise we need to open
102     // a new scope and possibly file.
103
104     // if the scopes are different call the code to load a new file and get the new scope
105
106     // scopes are the same so we can use the existing scope to get the class info
107
108     // This method needs to be fleshed out.more it currently just returns enough
109     // space for the defined EEClass and the vtable and statics are not set.
110     //=============================================================================</TODO>
111
112     if (fHasLayout)
113     {
114         pEEClass = new (pAllocator->GetLowFrequencyHeap(), pamTracker) LayoutEEClass();
115     }
116     else if (fDelegate)
117     {
118         pEEClass = new (pAllocator->GetLowFrequencyHeap(), pamTracker) DelegateEEClass();
119     }
120     else
121     {
122         pEEClass = new (pAllocator->GetLowFrequencyHeap(), pamTracker) EEClass(sizeof(EEClass));
123     }
124
125     DWORD dwAttrClass = 0;
126     mdToken tkExtends = mdTokenNil;
127
128     // Set up variance info
129     if (bmtGenericsInfo->pVarianceInfo)
130     {
131         // Variance info is an optional field on EEClass, so ensure the optional field descriptor has been
132         // allocated.
133         EnsureOptionalFieldsAreAllocated(pEEClass, pamTracker, pAllocator->GetLowFrequencyHeap());
134         pEEClass->SetVarianceInfo((BYTE*) pamTracker->Track(
135             pAllocator->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(bmtGenericsInfo->GetNumGenericArgs()))));
136
137         memcpy(pEEClass->GetVarianceInfo(), bmtGenericsInfo->pVarianceInfo, bmtGenericsInfo->GetNumGenericArgs());
138     }
139
140     pInternalImport = pModule->GetMDImport();
141
142     if (pInternalImport == NULL)
143         COMPlusThrowHR(COR_E_TYPELOAD);
144     
145     IfFailThrow(pInternalImport->GetTypeDefProps(
146         cl, 
147         &dwAttrClass, 
148         &tkExtends));
149     
150     pEEClass->m_dwAttrClass = dwAttrClass;
151
152     // MDVal check: can't be both tdSequentialLayout and tdExplicitLayout
153     if((dwAttrClass & tdLayoutMask) == tdLayoutMask)
154         COMPlusThrowHR(COR_E_TYPELOAD);
155
156     if (IsTdInterface(dwAttrClass))
157     {
158         // MDVal check: must have nil tkExtends and must be tdAbstract
159         if((tkExtends & 0x00FFFFFF)||(!IsTdAbstract(dwAttrClass)))
160             COMPlusThrowHR(COR_E_TYPELOAD);
161     }
162
163     if (fHasLayout)
164         pEEClass->SetHasLayout();
165     
166 #ifdef FEATURE_COMINTEROP
167     if (IsTdWindowsRuntime(dwAttrClass))
168     {
169         Assembly *pAssembly = pModule->GetAssembly();
170
171         // On the desktop CLR, we do not allow non-FX assemblies to use/define WindowsRuntimeImport attribute.
172         //
173         // On CoreCLR, however, we do allow non-FX assemblies to have this attribute. This enables scenarios where we can
174         // activate 3rd-party WinRT components outside AppContainer - 1st party WinRT components are already allowed
175         // to be activated outside AppContainer (on both Desktop and CoreCLR).
176
177         pEEClass->SetProjectedFromWinRT();
178     }
179
180     if (pEEClass->IsProjectedFromWinRT())
181     {
182         if (IsTdInterface(dwAttrClass))
183         {
184             //
185             // Check for GuidAttribute
186             //
187             BOOL bHasGuid = FALSE;
188         
189             GUID guid;
190             HRESULT hr = pModule->GetMDImport()->GetItemGuid(cl, &guid);
191             IfFailThrow(hr);
192             
193             if (IsEqualGUID(guid, GUID_NULL))
194             {
195                 // A WinRT interface should have a GUID
196                 pModule->GetAssembly()->ThrowTypeLoadException(pModule->GetMDImport(), cl, IDS_EE_WINRT_INTERFACE_WITHOUT_GUID);            
197             }
198         }
199     }
200
201     WinMDAdapter::RedirectedTypeIndex redirectedTypeIndex;
202     redirectedTypeIndex = WinRTTypeNameConverter::GetRedirectedTypeIndexByName(pModule, cl);
203     if (redirectedTypeIndex != WinMDAdapter::RedirectedTypeIndex_Invalid)
204     {
205         EnsureOptionalFieldsAreAllocated(pEEClass, pamTracker, pAllocator->GetLowFrequencyHeap());
206         pEEClass->SetWinRTRedirectedTypeIndex(redirectedTypeIndex);
207     }
208 #endif // FEAUTRE_COMINTEROP
209
210 #ifdef _DEBUG 
211     pModule->GetClassLoader()->m_dwDebugClasses++;
212 #endif
213
214     return pEEClass;
215 }
216
217 //*******************************************************************************
218 //
219 // Create a hash of all methods in this class.  The hash is from method name to MethodDesc.
220 //
221 MethodTableBuilder::MethodNameHash *
222 MethodTableBuilder::CreateMethodChainHash(
223     MethodTable *pMT)
224 {
225     STANDARD_VM_CONTRACT;
226
227     MethodNameHash *pHash = new (GetStackingAllocator()) MethodNameHash();
228     pHash->Init(pMT->GetNumVirtuals(), GetStackingAllocator());
229
230     unsigned numVirtuals = GetParentMethodTable()->GetNumVirtuals();
231     for (unsigned i = 0; i < numVirtuals; ++i)
232     {
233         bmtMethodSlot &slot = (*bmtParent->pSlotTable)[i];
234         bmtRTMethod * pMethod = slot.Decl().AsRTMethod();
235         const MethodSignature &sig = pMethod->GetMethodSignature();
236         pHash->Insert(sig.GetName(), pMethod);
237     }
238
239     // Success
240     return pHash;
241 }
242
243 //*******************************************************************************
244 //
245 // Find a method in this class hierarchy - used ONLY by the loader during layout.  Do not use at runtime.
246 //
247 // *ppMemberSignature must be NULL on entry - it and *pcMemberSignature may or may not be filled out
248 //
249 // ppMethodDesc will be filled out with NULL if no matching method in the hierarchy is found.
250 //
251 // Returns FALSE if there was an error of some kind.
252 //
253 // pMethodConstraintsMatch receives the result of comparing the method constraints.
254 MethodTableBuilder::bmtRTMethod *
255 MethodTableBuilder::LoaderFindMethodInParentClass(
256     const MethodSignature & methodSig,
257     BOOL *                  pMethodConstraintsMatch)
258 {
259     CONTRACTL
260     {
261         STANDARD_VM_CHECK;
262         PRECONDITION(CheckPointer(this));
263         PRECONDITION(CheckPointer(bmtParent));
264         PRECONDITION(CheckPointer(methodSig.GetModule()));
265         PRECONDITION(CheckPointer(methodSig.GetSignature()));
266         PRECONDITION(HasParent());
267         PRECONDITION(methodSig.GetSignatureLength() != 0);
268     }
269     CONTRACTL_END;
270
271 //#if 0
272     MethodNameHash::HashEntry * pEntry;
273
274     // Have we created a hash of all the methods in the class chain?
275     if (bmtParent->pParentMethodHash == NULL)
276     {
277         // There may be such a method, so we will now create a hash table to reduce the pain for
278         // further lookups
279
280         // <TODO> Are we really sure that this is worth doing? </TODO>
281         bmtParent->pParentMethodHash = CreateMethodChainHash(GetParentMethodTable());
282     }
283
284     // We have a hash table, so use it
285     pEntry = bmtParent->pParentMethodHash->Lookup(methodSig.GetName());
286
287     // Traverse the chain of all methods with this name
288     while (pEntry != NULL)
289     {
290         bmtRTMethod * pEntryMethod = pEntry->m_data;
291         const MethodSignature & entrySig = pEntryMethod->GetMethodSignature();
292
293         // Note instantiation info
294         {
295             if (methodSig.Equivalent(entrySig))
296             {
297                 if (pMethodConstraintsMatch != NULL)
298                 {
299                     // Check the constraints are consistent,
300                     // and return the result to the caller.
301                     // We do this here to avoid recalculating pSubst.
302                     *pMethodConstraintsMatch = MetaSig::CompareMethodConstraints(
303                         &methodSig.GetSubstitution(), methodSig.GetModule(), methodSig.GetToken(),
304                         &entrySig.GetSubstitution(),  entrySig.GetModule(),  entrySig.GetToken());
305                 }
306
307                 return pEntryMethod;
308             }
309         }
310
311         // Advance to next item in the hash chain which has the same name
312         pEntry = bmtParent->pParentMethodHash->FindNext(pEntry);
313     }
314 //#endif
315
316 //@TODO: Move to this code, as the use of a HashTable is broken; overriding semantics
317 //@TODO: require matching against the most-derived slot of a given name and signature,
318 //@TODO: (which deals specifically with newslot methods with identical name and sig), but
319 //@TODO: HashTables are by definition unordered and so we've only been getting by with the
320 //@TODO: implementation being compatible with the order in which methods were added to
321 //@TODO: the HashTable in CreateMethodChainHash.
322 #if 0 
323     bmtParentInfo::Iterator it(bmtParent->IterateSlots());
324     it.MoveTo(static_cast<size_t>(GetParentMethodTable()->GetNumVirtuals()));
325     while (it.Prev())
326     {
327         bmtMethodHandle decl(it->Decl());
328         const MethodSignature &declSig(decl.GetMethodSignature());
329         if (declSig == methodSig)
330         {
331             if (pMethodConstraintsMatch != NULL)
332             {
333                 // Check the constraints are consistent,
334                 // and return the result to the caller.
335                 // We do this here to avoid recalculating pSubst.
336                 *pMethodConstraintsMatch = MetaSig::CompareMethodConstraints(
337                     &methodSig.GetSubstitution(), methodSig.GetModule(), methodSig.GetToken(),
338                     &declSig.GetSubstitution(),  declSig.GetModule(),  declSig.GetToken());
339             }
340
341             return decl.AsRTMethod();
342         }
343     }
344 #endif // 0
345
346     return NULL;
347 }
348
349 //*******************************************************************************
350 //
351 // Given an interface map to fill out, expand pNewInterface (and its sub-interfaces) into it, increasing
352 // pdwInterfaceListSize as appropriate, and avoiding duplicates.
353 //
354 void
355 MethodTableBuilder::ExpandApproxInterface(
356     bmtInterfaceInfo *          bmtInterface,  // out parameter, various parts cumulatively written to.
357     const Substitution *        pNewInterfaceSubstChain, 
358     MethodTable *               pNewInterface, 
359     InterfaceDeclarationScope   declScope 
360     COMMA_INDEBUG(MethodTable * dbg_pClassMT))
361 {
362     STANDARD_VM_CONTRACT;
363     
364     //#ExpandingInterfaces
365     // We expand the tree of inherited interfaces into a set by adding the
366     // current node BEFORE expanding the parents of the current node.
367     // ****** This must be consistent with code:ExpandExactInterface *******
368     // ****** This must be consistent with code:ClassCompat::MethodTableBuilder::BuildInteropVTable_ExpandInterface *******
369
370     // The interface list contains the fully expanded set of interfaces from the parent then
371     // we start adding all the interfaces we declare. We need to know which interfaces
372     // we declare but do not need duplicates of the ones we declare. This means we can
373     // duplicate our parent entries.
374
375     // Is it already present in the list?
376     for (DWORD i = 0; i < bmtInterface->dwInterfaceMapSize; i++)
377     {
378         bmtInterfaceEntry * pItfEntry = &bmtInterface->pInterfaceMap[i];
379         bmtRTType * pItfType = pItfEntry->GetInterfaceType();
380
381         // Type Equivalence is not respected for this comparision as you can have multiple type equivalent interfaces on a class
382         TokenPairList newVisited = TokenPairList::AdjustForTypeEquivalenceForbiddenScope(NULL);
383         if (MetaSig::CompareTypeDefsUnderSubstitutions(pItfType->GetMethodTable(),
384                                                        pNewInterface,
385                                                        &pItfType->GetSubstitution(),
386                                                        pNewInterfaceSubstChain,
387                                                        &newVisited))
388         {
389             if (declScope.fIsInterfaceDeclaredOnType)
390             {
391                 pItfEntry->IsDeclaredOnType() = true;
392             }
393 #ifdef _DEBUG
394             //#InjectInterfaceDuplicates_ApproxInterfaces
395             // We can inject duplicate interfaces in check builds.
396             // Has to be in sync with code:#InjectInterfaceDuplicates_Main
397             if (((dbg_pClassMT == NULL) && bmtInterface->dbg_fShouldInjectInterfaceDuplicates) || 
398                 ((dbg_pClassMT != NULL) && dbg_pClassMT->Debug_HasInjectedInterfaceDuplicates()))
399             {   
400                 // The injected duplicate interface should have the same status 'ImplementedByParent' as 
401                 // the original interface (can be false if the interface is implemented indirectly twice)
402                 declScope.fIsInterfaceDeclaredOnParent = pItfEntry->IsImplementedByParent();
403                 // Just pretend we didn't find this match, but mark all duplicates as 'DeclaredOnType' if 
404                 // needed
405                 continue;
406             }
407 #endif //_DEBUG
408             return; // found it, don't add it again
409         }
410     }
411
412     bmtRTType * pNewItfType =
413         new (GetStackingAllocator()) bmtRTType(*pNewInterfaceSubstChain, pNewInterface);
414
415     if (bmtInterface->dwInterfaceMapSize >= bmtInterface->dwInterfaceMapAllocated)
416     {
417         //
418         // Grow the array of interfaces
419         //
420         S_UINT32 dwNewAllocated = S_UINT32(2) * S_UINT32(bmtInterface->dwInterfaceMapAllocated) + S_UINT32(5);
421
422         if (dwNewAllocated.IsOverflow())
423         {
424             BuildMethodTableThrowException(COR_E_OVERFLOW);
425         }
426
427         S_SIZE_T safeSize = S_SIZE_T(sizeof(bmtInterfaceEntry)) *
428                             S_SIZE_T(dwNewAllocated.Value());
429
430         if (safeSize.IsOverflow())
431         {
432             BuildMethodTableThrowException(COR_E_OVERFLOW);
433         }
434
435         bmtInterfaceEntry * pNewMap = (bmtInterfaceEntry *)new (GetStackingAllocator()) BYTE[safeSize.Value()];
436         memcpy(pNewMap, bmtInterface->pInterfaceMap, sizeof(bmtInterfaceEntry) * bmtInterface->dwInterfaceMapAllocated);
437
438         bmtInterface->pInterfaceMap = pNewMap;
439         bmtInterface->dwInterfaceMapAllocated = dwNewAllocated.Value();
440     }
441
442     // The interface map memory was just allocated as an array of bytes, so we use
443     // in place new to init the new map entry. No need to do anything with the result,
444     // so just chuck it.
445     CONSISTENCY_CHECK(bmtInterface->dwInterfaceMapSize < bmtInterface->dwInterfaceMapAllocated);
446     new ((void *)&bmtInterface->pInterfaceMap[bmtInterface->dwInterfaceMapSize])
447         bmtInterfaceEntry(pNewItfType, declScope);
448
449     bmtInterface->dwInterfaceMapSize++;
450
451     // Make sure to pass in the substitution from the new itf type created above as
452     // these methods assume that substitutions are allocated in the stacking heap,
453     // not the stack.
454     InterfaceDeclarationScope declaredItfScope(declScope.fIsInterfaceDeclaredOnParent, false);
455     ExpandApproxDeclaredInterfaces(
456         bmtInterface,
457         bmtTypeHandle(pNewItfType),
458         declaredItfScope 
459         COMMA_INDEBUG(dbg_pClassMT));
460 } // MethodTableBuilder::ExpandApproxInterface
461
462 //*******************************************************************************
463 // Arguments:
464 //   dbg_pClassMT - Class on which the interfaces are declared (either explicitly or implicitly).
465 //                  It will never be an interface. It may be NULL (if it is the type being built).
466 void 
467 MethodTableBuilder::ExpandApproxDeclaredInterfaces(
468     bmtInterfaceInfo *          bmtInterface,  // out parameter, various parts cumulatively written to.
469     bmtTypeHandle               thType, 
470     InterfaceDeclarationScope   declScope 
471     COMMA_INDEBUG(MethodTable * dbg_pClassMT))
472 {
473     STANDARD_VM_CONTRACT;
474
475     _ASSERTE((dbg_pClassMT == NULL) || !dbg_pClassMT->IsInterface());
476
477     HRESULT hr;
478     // Iterate the list of interfaces declared by thType and add them to the map.
479     InterfaceImplEnum ie(thType.GetModule(), thType.GetTypeDefToken(), &thType.GetSubstitution());
480     while ((hr = ie.Next()) == S_OK)
481     {
482         MethodTable *pGenericIntf = ClassLoader::LoadApproxTypeThrowing(
483             thType.GetModule(), ie.CurrentToken(), NULL, NULL).GetMethodTable();
484         CONSISTENCY_CHECK(pGenericIntf->IsInterface());
485
486         ExpandApproxInterface(bmtInterface,
487                               ie.CurrentSubst(),
488                               pGenericIntf,
489                               declScope 
490                               COMMA_INDEBUG(dbg_pClassMT));
491     }
492     if (FAILED(hr))
493     {
494         BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
495     }
496 } // MethodTableBuilder::ExpandApproxDeclaredInterfaces
497
498 //*******************************************************************************
499 void
500 MethodTableBuilder::ExpandApproxInheritedInterfaces(
501     bmtInterfaceInfo *      bmtInterface,
502     bmtRTType *             pParentType)
503 {
504     STANDARD_VM_CONTRACT;
505
506     INTERIOR_STACK_PROBE(GetThread());
507
508     // Expand interfaces in superclasses first.  Interfaces inherited from parents
509     // must have identical indexes as in the parent.
510     bmtRTType * pParentOfParent = pParentType->GetParentType();
511     
512     //#InterfaceMap_SupersetOfParent
513     // We have to load parent's interface map the same way the parent did it (as open type).
514     // Further code depends on this:
515     //    code:#InterfaceMap_UseParentInterfaceImplementations
516     // We check that it is truth:
517     //    code:#ApproxInterfaceMap_SupersetOfParent
518     //    code:#ExactInterfaceMap_SupersetOfParent
519     // 
520     //#InterfaceMap_CanonicalSupersetOfParent
521     // Note that canonical instantiation of parent can have different interface instantiations in the 
522     // interface map than derived type:
523     //    class MyClass<T> : MyBase<string, T>, I<T>
524     //    class MyBase<U, V> : I<U>
525     // Type MyClass<_Canon> has MyBase<_Canon,_Canon> as parent. The interface maps are:
526     //    MyBase<_Canon,_Canon> ... I<_Canon>
527     //    MyClass<_Canon> ... I<string> (#1)
528     //                        I<_Canon> (#2)
529     // The I's instantiation I<string> (#1) in MyClass and I<_Canon> from MyBase are not the same 
530     // instantiations.
531     
532     // Backup parent substitution
533     Substitution parentSubstitution = pParentType->GetSubstitution();
534     // Make parent an open type
535     pParentType->SetSubstitution(Substitution());
536     
537     if (pParentOfParent != NULL)
538     {
539         ExpandApproxInheritedInterfaces(bmtInterface, pParentOfParent);
540     }
541
542     InterfaceDeclarationScope declScope(true, false);
543     ExpandApproxDeclaredInterfaces(
544         bmtInterface, 
545         bmtTypeHandle(pParentType), 
546         declScope 
547         COMMA_INDEBUG(pParentType->GetMethodTable()));
548     
549     // Make sure we loaded the same number of interfaces as the parent type itself
550     CONSISTENCY_CHECK(pParentType->GetMethodTable()->GetNumInterfaces() == bmtInterface->dwInterfaceMapSize);
551     
552     // Restore parent's substitution
553     pParentType->SetSubstitution(parentSubstitution);
554     
555     END_INTERIOR_STACK_PROBE;
556 } // MethodTableBuilder::ExpandApproxInheritedInterfaces
557
558 //*******************************************************************************
559 // Fill out a fully expanded interface map, such that if we are declared to
560 // implement I3, and I3 extends I1,I2, then I1,I2 are added to our list if
561 // they are not already present.
562 void
563 MethodTableBuilder::LoadApproxInterfaceMap()
564 {
565     STANDARD_VM_CONTRACT;
566
567     bmtInterface->dwInterfaceMapSize = 0;
568
569 #ifdef _DEBUG
570     //#InjectInterfaceDuplicates_Main
571     // We will inject duplicate interfaces in check builds if env. var. 
572     // COMPLUS_INTERNAL_TypeLoader_InjectInterfaceDuplicates is set to TRUE for all types (incl. non-generic 
573     // types).
574     // This should allow us better test coverage of duplicates in interface map.
575     // 
576     // The duplicates are legal for some types:
577     //     A<T> : I<T>
578     //     B<U,V> : A<U>, I<V>
579     //     C : B<int,int>
580     //   where the interface maps are:
581     //     A<T>             ... 1 item:  I<T>
582     //     A<int>           ... 1 item:  I<int>
583     //     B<U,V>           ... 2 items: I<U>, I<V>
584     //     B<int,int>       ... 2 items: I<int>, I<int>
585     //     B<_Canon,_Canon> ... 2 items: I<_Canon>, I<_Canon>
586     //     B<string,string> ... 2 items: I<string>, I<string>
587     //     C                ... 2 items: I<int>, I<int>
588     //     Note: C had only 1 item (I<int>) in CLR 2.0 RTM/SP1/SP2 and early in CLR 4.0.
589     // 
590     // We will create duplicate from every re-implemented interface (incl. non-generic):
591     //   code:#InjectInterfaceDuplicates_ApproxInterfaces
592     //   code:#InjectInterfaceDuplicates_LoadExactInterfaceMap
593     //   code:#InjectInterfaceDuplicates_ExactInterfaces
594     // 
595     // Note that we don't have to do anything for COM, because COM has its own interface map 
596     // (code:InteropMethodTableData)which is independent on type's interface map and is created only from 
597     // non-generic interfaces (see code:ClassCompat::MethodTableBuilder::BuildInteropVTable_InterfaceList)
598     
599     // We need to keep track which interface duplicates were injected. Right now its either all interfaces 
600     // (declared on the type being built, not inheritted) or none. In the future we could inject duplicates 
601     // just for some of them.
602     bmtInterface->dbg_fShouldInjectInterfaceDuplicates = 
603         (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_TypeLoader_InjectInterfaceDuplicates) != 0);
604     if (bmtGenerics->Debug_GetTypicalMethodTable() != NULL)
605     {   // It's safer to require that all instantiations have the same injected interface duplicates.
606         // In future we could inject different duplicates for various non-shared instantiations.
607         
608         // Use the same injection status as typical instantiation
609         bmtInterface->dbg_fShouldInjectInterfaceDuplicates = 
610             bmtGenerics->Debug_GetTypicalMethodTable()->Debug_HasInjectedInterfaceDuplicates();
611         
612         if (GetModule() == g_pObjectClass->GetModule())
613         {   // mscorlib has some weird hardcoded information about interfaces (e.g. 
614             // code:CEEPreloader::ApplyTypeDependencyForSZArrayHelper), so we don't inject duplicates into 
615             // mscorlib types
616             bmtInterface->dbg_fShouldInjectInterfaceDuplicates = FALSE;
617         }
618     }
619 #endif //_DEBUG
620
621     // First inherit all the parent's interfaces.  This is important, because our interface map must
622     // list the interfaces in identical order to our parent.
623     //
624     // <NICE> we should document the reasons why.  One reason is that DispatchMapTypeIDs can be indexes
625     // into the list </NICE>
626     if (HasParent())
627     {
628         ExpandApproxInheritedInterfaces(bmtInterface, GetParentType());
629 #ifdef _DEBUG
630         //#ApproxInterfaceMap_SupersetOfParent
631         // Check that parent's interface map is the same as what we just computed
632         // See code:#InterfaceMap_SupersetOfParent
633         {
634             MethodTable * pParentMT = GetParentMethodTable();
635             _ASSERTE(pParentMT->GetNumInterfaces() == bmtInterface->dwInterfaceMapSize);
636             
637             MethodTable::InterfaceMapIterator parentInterfacesIterator = pParentMT->IterateInterfaceMap();
638             UINT32 nInterfaceIndex = 0;
639             while (parentInterfacesIterator.Next())
640             {
641                 // Compare TypeDefs of the parent's interface and this interface (full MT comparison is in 
642                 // code:#ExactInterfaceMap_SupersetOfParent)
643                 OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOAD_APPROXPARENTS);
644                 _ASSERTE(parentInterfacesIterator.GetInterfaceInfo()->GetApproxMethodTable(pParentMT->GetLoaderModule())->HasSameTypeDefAs(
645                     bmtInterface->pInterfaceMap[nInterfaceIndex].GetInterfaceType()->GetMethodTable()));
646                 nInterfaceIndex++;
647             }
648             _ASSERTE(nInterfaceIndex == bmtInterface->dwInterfaceMapSize);
649         }
650 #endif //_DEBUG
651     }
652
653     // Now add in any freshly declared interfaces, possibly augmenting the flags
654     InterfaceDeclarationScope declScope(false, true);
655     ExpandApproxDeclaredInterfaces(
656         bmtInterface, 
657         bmtInternal->pType, 
658         declScope 
659         COMMA_INDEBUG(NULL));
660 } // MethodTableBuilder::LoadApproxInterfaceMap
661
662 //*******************************************************************************
663 // Fills array of TypeIDs with all duplicate occurences of pDeclIntfMT in the interface map.
664 // 
665 // Arguments:
666 //    rg/c DispatchMapTypeIDs - Array of TypeIDs and its count of elements.
667 //    pcIfaceDuplicates - Number of duplicate occurences of the interface in the interface map (ideally <= 
668 //         count of elements TypeIDs.
669 // 
670 // Note: If the passed rgDispatchMapTypeIDs array is smaller than the number of duplicates, fills it 
671 // with the duplicates that fit and returns number of all existing duplicates (not just those fileld in the 
672 // array) in pcIfaceDuplicates.
673 // 
674 void 
675 MethodTableBuilder::ComputeDispatchMapTypeIDs(
676     MethodTable *        pDeclInftMT, 
677     const Substitution * pDeclIntfSubst, 
678     DispatchMapTypeID *  rgDispatchMapTypeIDs, 
679     UINT32               cDispatchMapTypeIDs, 
680     UINT32 *             pcIfaceDuplicates)
681 {
682     STANDARD_VM_CONTRACT;
683     
684     _ASSERTE(pDeclInftMT->IsInterface());
685     
686     // Count of interface duplicates (also used as index into TypeIDs array)
687     *pcIfaceDuplicates = 0;
688     for (DWORD idx = 0; idx < bmtInterface->dwInterfaceMapSize; idx++)
689     {
690         bmtInterfaceEntry * pItfEntry = &bmtInterface->pInterfaceMap[idx];
691         bmtRTType * pItfType = pItfEntry->GetInterfaceType();
692         // Type Equivalence is forbidden in interface type ids.
693         TokenPairList newVisited = TokenPairList::AdjustForTypeEquivalenceForbiddenScope(NULL);
694         if (MetaSig::CompareTypeDefsUnderSubstitutions(pItfType->GetMethodTable(),
695                                                        pDeclInftMT,
696                                                        &pItfType->GetSubstitution(),
697                                                        pDeclIntfSubst,
698                                                        &newVisited))
699         {   // We found another occurence of this interface
700             // Can we fit it into the TypeID array?
701             if (*pcIfaceDuplicates < cDispatchMapTypeIDs)
702             {
703                 rgDispatchMapTypeIDs[*pcIfaceDuplicates] = DispatchMapTypeID::InterfaceClassID(idx);
704             }
705             // Increase number of duplicate interfaces
706             (*pcIfaceDuplicates)++;
707         }
708     }
709 } // MethodTableBuilder::ComputeDispatchMapTypeIDs
710
711 //*******************************************************************************
712 /*static*/
713 VOID DECLSPEC_NORETURN
714 MethodTableBuilder::BuildMethodTableThrowException(
715     HRESULT hr,
716     const bmtErrorInfo & bmtError)
717 {
718     CONTRACTL
719     {
720         THROWS;
721         GC_TRIGGERS;
722         INJECT_FAULT(COMPlusThrowOM(););
723     }
724     CONTRACTL_END
725
726     LPCUTF8 pszClassName, pszNameSpace;
727     if (FAILED(bmtError.pModule->GetMDImport()->GetNameOfTypeDef(bmtError.cl, &pszClassName, &pszNameSpace)))
728     {
729         pszClassName = pszNameSpace = "Invalid TypeDef record";
730     }
731     
732     if (IsNilToken(bmtError.dMethodDefInError) && (bmtError.szMethodNameForError == NULL))
733     {
734         if (hr == E_OUTOFMEMORY)
735         {
736             COMPlusThrowOM();
737         }
738         else
739             bmtError.pModule->GetAssembly()->ThrowTypeLoadException(
740                 pszNameSpace, pszClassName, bmtError.resIDWhy);
741     }
742     else
743     {
744         LPCUTF8 szMethodName;
745         if (bmtError.szMethodNameForError == NULL)
746         {
747             if (FAILED((bmtError.pModule->GetMDImport())->GetNameOfMethodDef(bmtError.dMethodDefInError, &szMethodName)))
748             {
749                 szMethodName = "Invalid MethodDef record";
750             }
751         }
752         else
753         {
754             szMethodName = bmtError.szMethodNameForError;
755         }
756
757         bmtError.pModule->GetAssembly()->ThrowTypeLoadException(
758             pszNameSpace, pszClassName, szMethodName, bmtError.resIDWhy);
759     }
760 } // MethodTableBuilder::BuildMethodTableThrowException
761
762 //*******************************************************************************
763 void MethodTableBuilder::SetBMTData(
764     LoaderAllocator *bmtAllocator,
765     bmtErrorInfo *bmtError,
766     bmtProperties *bmtProp,
767     bmtVtable *bmtVT,
768     bmtParentInfo *bmtParent,
769     bmtInterfaceInfo *bmtInterface,
770     bmtMetaDataInfo *bmtMetaData,
771     bmtMethodInfo *bmtMethod,
772     bmtMethAndFieldDescs *bmtMFDescs,
773     bmtFieldPlacement *bmtFP,
774     bmtInternalInfo *bmtInternal,
775     bmtGCSeriesInfo *bmtGCSeries,
776     bmtMethodImplInfo *bmtMethodImpl,
777     const bmtGenericsInfo *bmtGenerics,
778     bmtEnumFieldInfo *bmtEnumFields,
779     bmtContextStaticInfo *bmtCSInfo)
780 {
781     LIMITED_METHOD_CONTRACT;
782     this->bmtAllocator = bmtAllocator;
783     this->bmtError = bmtError;
784     this->bmtProp = bmtProp;
785     this->bmtVT = bmtVT;
786     this->bmtParent = bmtParent;
787     this->bmtInterface = bmtInterface;
788     this->bmtMetaData = bmtMetaData;
789     this->bmtMethod = bmtMethod;
790     this->bmtMFDescs = bmtMFDescs;
791     this->bmtFP = bmtFP;
792     this->bmtInternal = bmtInternal;
793     this->bmtGCSeries = bmtGCSeries;
794     this->bmtMethodImpl = bmtMethodImpl;
795     this->bmtGenerics = bmtGenerics;
796     this->bmtEnumFields = bmtEnumFields;
797     this->bmtCSInfo = bmtCSInfo;
798 }
799
800 //*******************************************************************************
801 // Used by MethodTableBuilder
802
803 MethodTableBuilder::bmtRTType *
804 MethodTableBuilder::CreateTypeChain(
805     MethodTable *        pMT,
806     const Substitution & subst)
807 {
808     CONTRACTL
809     {
810         STANDARD_VM_CHECK;
811         INSTANCE_CHECK;
812         PRECONDITION(CheckPointer(GetStackingAllocator()));
813         PRECONDITION(CheckPointer(pMT));
814     } CONTRACTL_END;
815
816     pMT = pMT->GetCanonicalMethodTable();
817
818     bmtRTType * pType = new (GetStackingAllocator())
819         bmtRTType(subst, pMT);
820
821     MethodTable * pMTParent = pMT->GetParentMethodTable();
822     if (pMTParent != NULL)
823     {
824         pType->SetParentType(
825             CreateTypeChain(
826                 pMTParent,
827                 pMT->GetSubstitutionForParent(&pType->GetSubstitution())));
828     }
829
830     return pType;
831 }
832
833 //*******************************************************************************
834 /* static */
835 MethodTableBuilder::bmtRTType *
836 MethodTableBuilder::bmtRTType::FindType(
837     bmtRTType *          pType,
838     MethodTable *        pTargetMT)
839 {
840     CONTRACTL {
841         STANDARD_VM_CHECK;
842         PRECONDITION(CheckPointer(pType));
843         PRECONDITION(CheckPointer(pTargetMT));
844     } CONTRACTL_END;
845
846     pTargetMT = pTargetMT->GetCanonicalMethodTable();
847     while (pType != NULL &&
848            pType->GetMethodTable()->GetCanonicalMethodTable() != pTargetMT)
849     {
850         pType = pType->GetParentType();
851     }
852
853     return pType;
854 }
855
856 //*******************************************************************************
857 mdTypeDef
858 MethodTableBuilder::bmtRTType::GetEnclosingTypeToken() const
859 {
860     STANDARD_VM_CONTRACT;
861
862     mdTypeDef tok = mdTypeDefNil;
863
864     if (IsNested())
865     {   // This is guaranteed to succeed because the EEClass would not have been
866         // set as nested unless a valid token was stored in metadata.
867         if (FAILED(GetModule()->GetMDImport()->GetNestedClassProps(
868             GetTypeDefToken(), &tok)))
869         {
870             return mdTypeDefNil;
871         }
872     }
873     
874     return tok;
875 }
876
877 //*******************************************************************************
878 /*static*/ bool
879 MethodTableBuilder::MethodSignature::NamesEqual(
880     const MethodSignature & sig1,
881     const MethodSignature & sig2)
882 {
883     STANDARD_VM_CONTRACT;
884
885     if (sig1.GetNameHash() != sig2.GetNameHash())
886     {
887         return false;
888     }
889
890     if (strcmp(sig1.GetName(), sig2.GetName()) != 0)
891     {
892         return false;
893     }
894
895     return true;
896 }
897
898 //*******************************************************************************
899 /*static*/ bool
900 MethodTableBuilder::MethodSignature::SignaturesEquivalent(
901     const MethodSignature & sig1, 
902     const MethodSignature & sig2)
903 {
904     STANDARD_VM_CONTRACT;
905
906     return !!MetaSig::CompareMethodSigs(
907         sig1.GetSignature(), static_cast<DWORD>(sig1.GetSignatureLength()), sig1.GetModule(), &sig1.GetSubstitution(), 
908         sig2.GetSignature(), static_cast<DWORD>(sig2.GetSignatureLength()), sig2.GetModule(), &sig2.GetSubstitution());
909 }
910
911 //*******************************************************************************
912 /*static*/ bool
913 MethodTableBuilder::MethodSignature::SignaturesExactlyEqual(
914     const MethodSignature & sig1, 
915     const MethodSignature & sig2)
916 {
917     STANDARD_VM_CONTRACT;
918
919     TokenPairList newVisited = TokenPairList::AdjustForTypeEquivalenceForbiddenScope(NULL);
920     return !!MetaSig::CompareMethodSigs(
921         sig1.GetSignature(), static_cast<DWORD>(sig1.GetSignatureLength()), sig1.GetModule(), &sig1.GetSubstitution(), 
922         sig2.GetSignature(), static_cast<DWORD>(sig2.GetSignatureLength()), sig2.GetModule(), &sig2.GetSubstitution(),
923         &newVisited);
924 }
925
926 //*******************************************************************************
927 bool
928 MethodTableBuilder::MethodSignature::Equivalent(
929     const MethodSignature &rhs) const
930 {
931     STANDARD_VM_CONTRACT;
932
933     return NamesEqual(*this, rhs) && SignaturesEquivalent(*this, rhs);
934 }
935
936 //*******************************************************************************
937 bool
938 MethodTableBuilder::MethodSignature::ExactlyEqual(
939     const MethodSignature &rhs) const
940 {
941     STANDARD_VM_CONTRACT;
942
943     return NamesEqual(*this, rhs) && SignaturesExactlyEqual(*this, rhs);
944 }
945
946 //*******************************************************************************
947 void
948 MethodTableBuilder::MethodSignature::GetMethodAttributes() const
949 {
950     STANDARD_VM_CONTRACT;
951
952     IMDInternalImport * pIMD = GetModule()->GetMDImport();
953     if (TypeFromToken(GetToken()) == mdtMethodDef)
954     {
955         DWORD cSig;
956         if (FAILED(pIMD->GetNameAndSigOfMethodDef(GetToken(), &m_pSig, &cSig, &m_szName)))
957         {   // We have empty name or signature on error, do nothing
958         }
959         m_cSig = static_cast<size_t>(cSig);
960     }
961     else
962     {
963         CONSISTENCY_CHECK(TypeFromToken(m_tok) == mdtMemberRef);
964         DWORD cSig;
965         if (FAILED(pIMD->GetNameAndSigOfMemberRef(GetToken(), &m_pSig, &cSig, &m_szName)))
966         {   // We have empty name or signature on error, do nothing
967         }
968         m_cSig = static_cast<size_t>(cSig);
969     }
970 }
971
972 //*******************************************************************************
973 UINT32
974 MethodTableBuilder::MethodSignature::GetNameHash() const
975 {
976     STANDARD_VM_CONTRACT;
977
978     CheckGetMethodAttributes();
979
980     if (m_nameHash == INVALID_NAME_HASH)
981     {
982         ULONG nameHash = HashStringA(GetName());
983         if (nameHash == INVALID_NAME_HASH)
984         {
985             nameHash /= 2;
986         }
987         m_nameHash = nameHash;
988     }
989
990     return m_nameHash;
991 }
992
993 //*******************************************************************************
994 MethodTableBuilder::bmtMDType::bmtMDType(
995     bmtRTType *             pParentType,
996     Module *                pModule,
997     mdTypeDef               tok,
998     const SigTypeContext &  sigContext)
999     : m_pParentType(pParentType),
1000       m_pModule(pModule),
1001       m_tok(tok),
1002       m_enclTok(mdTypeDefNil),
1003       m_sigContext(sigContext),
1004       m_subst(),
1005       m_dwAttrs(0),
1006       m_pMT(NULL)
1007 {
1008     STANDARD_VM_CONTRACT;
1009
1010     IfFailThrow(m_pModule->GetMDImport()->GetTypeDefProps(m_tok, &m_dwAttrs, NULL));
1011
1012     HRESULT hr = m_pModule->GetMDImport()->GetNestedClassProps(m_tok, &m_enclTok);
1013     if (FAILED(hr))
1014     {
1015         if (hr != CLDB_E_RECORD_NOTFOUND)
1016         {
1017             ThrowHR(hr);
1018         }
1019         // Just in case GetNestedClassProps sets the out param to some other value
1020         m_enclTok = mdTypeDefNil;
1021     }
1022 }
1023
1024 //*******************************************************************************
1025 MethodTableBuilder::bmtRTMethod::bmtRTMethod(
1026     bmtRTType *     pOwningType,
1027     MethodDesc *    pMD)
1028     : m_pOwningType(pOwningType),
1029       m_pMD(pMD),
1030       m_methodSig(pMD->GetModule(),
1031                   pMD->GetMemberDef(),
1032                   &pOwningType->GetSubstitution())
1033 {
1034     CONTRACTL
1035     {
1036         THROWS;
1037         GC_TRIGGERS;
1038         MODE_ANY;
1039     }
1040     CONTRACTL_END;
1041 }
1042
1043 //*******************************************************************************
1044 MethodTableBuilder::bmtMDMethod::bmtMDMethod(
1045     bmtMDType * pOwningType,
1046     mdMethodDef tok,
1047     DWORD dwDeclAttrs,
1048     DWORD dwImplAttrs,
1049     DWORD dwRVA,
1050     METHOD_TYPE type,
1051     METHOD_IMPL_TYPE implType)
1052     : m_pOwningType(pOwningType),
1053       m_dwDeclAttrs(dwDeclAttrs),
1054       m_dwImplAttrs(dwImplAttrs),
1055       m_dwRVA(dwRVA),
1056       m_type(type),
1057       m_implType(implType),
1058       m_methodSig(pOwningType->GetModule(),
1059                   tok,
1060                   &pOwningType->GetSubstitution()),
1061       m_pMD(NULL),
1062       m_pUnboxedMD(NULL),
1063       m_slotIndex(INVALID_SLOT_INDEX),
1064       m_unboxedSlotIndex(INVALID_SLOT_INDEX)
1065     {
1066         CONTRACTL
1067         {
1068             THROWS;
1069             GC_TRIGGERS;
1070             MODE_ANY;
1071         }
1072         CONTRACTL_END;
1073     }
1074 //*******************************************************************************
1075 void
1076 MethodTableBuilder::ImportParentMethods()
1077 {
1078     STANDARD_VM_CONTRACT;
1079
1080     if (!HasParent())
1081     {   // If there's no parent, there's no methods to import
1082         return;
1083     }
1084
1085     SLOT_INDEX numMethods = static_cast<SLOT_INDEX>
1086         (GetParentMethodTable()->GetNumMethods());
1087
1088     bmtParent->pSlotTable = new (GetStackingAllocator())
1089         bmtMethodSlotTable(numMethods, GetStackingAllocator());
1090
1091     MethodTable::MethodIterator it(GetParentMethodTable());
1092     for (;it.IsValid(); it.Next())
1093     {
1094         MethodDesc *  pDeclDesc = NULL;
1095         MethodTable * pDeclMT   = NULL;
1096         MethodDesc *  pImplDesc = NULL;
1097         MethodTable * pImplMT   = NULL;
1098
1099         if (it.IsVirtual())
1100         {
1101             pDeclDesc = it.GetDeclMethodDesc();
1102             pDeclMT = pDeclDesc->GetMethodTable();
1103             pImplDesc = it.GetMethodDesc();
1104             pImplMT = pImplDesc->GetMethodTable();
1105         }
1106         else
1107         {
1108             pDeclDesc = pImplDesc = it.GetMethodDesc();
1109             pDeclMT = pImplMT = it.GetMethodDesc()->GetMethodTable();
1110         }
1111
1112         CONSISTENCY_CHECK(CheckPointer(pDeclDesc));
1113         CONSISTENCY_CHECK(CheckPointer(pImplDesc));
1114
1115         // Create and assign to each slot
1116         bmtMethodSlot newSlot;
1117         newSlot.Decl() = new (GetStackingAllocator())
1118             bmtRTMethod(bmtRTType::FindType(GetParentType(), pDeclMT), pDeclDesc);
1119         if (pDeclDesc == pImplDesc)
1120         {
1121             newSlot.Impl() = newSlot.Decl();
1122         }
1123         else
1124         {
1125             newSlot.Impl() = new (GetStackingAllocator())
1126                 bmtRTMethod(bmtRTType::FindType(GetParentType(), pImplMT), pImplDesc);
1127         }
1128
1129         if (!bmtParent->pSlotTable->AddMethodSlot(newSlot))
1130             BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
1131     }
1132 }
1133
1134 //*******************************************************************************
1135 void
1136 MethodTableBuilder::CopyParentVtable()
1137 {
1138     STANDARD_VM_CONTRACT;
1139
1140     if (!HasParent())
1141     {
1142         return;
1143     }
1144
1145     for (bmtParentInfo::Iterator it = bmtParent->IterateSlots();
1146          !it.AtEnd() && it.CurrentIndex() < GetParentMethodTable()->GetNumVirtuals();
1147          ++it)
1148      {
1149         if (!bmtVT->pSlotTable->AddMethodSlot(*it))
1150             BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
1151         ++bmtVT->cVirtualSlots;
1152         ++bmtVT->cTotalSlots;
1153      }
1154 }
1155
1156 //*******************************************************************************
1157 // Determine if this is the special SIMD type System.Numerics.Vector<T>, whose
1158 // size is determined dynamically based on the hardware and the presence of JIT
1159 // support.
1160 // If so:
1161 //   - Update the NumInstanceFieldBytes on the bmtFieldPlacement.
1162 //   - Update the m_cbNativeSize and m_cbManagedSize if HasLayout() is true.
1163 // Return a BOOL result to indicate whether the size has been updated.
1164 //
1165 // Will throw IDS_EE_SIMD_NGEN_DISALLOWED if the type is System.Numerics.Vector`1
1166 // and this is an ngen compilation process.
1167 //
1168 BOOL MethodTableBuilder::CheckIfSIMDAndUpdateSize()
1169 {
1170     STANDARD_VM_CONTRACT;
1171
1172 #if defined(_TARGET_X86_) || defined(_TARGET_AMD64_)
1173     if (!GetAssembly()->IsSIMDVectorAssembly())
1174         return false;
1175
1176     if (bmtFP->NumInstanceFieldBytes != 16)
1177         return false;
1178
1179     LPCUTF8 className;
1180     LPCUTF8 nameSpace;
1181     if (FAILED(GetMDImport()->GetNameOfTypeDef(bmtInternal->pType->GetTypeDefToken(), &className, &nameSpace)))
1182         return false;
1183
1184     if (strcmp(className, "Vector`1") != 0 || strcmp(nameSpace, "System.Numerics") != 0)
1185         return false;
1186
1187     if (IsCompilationProcess())
1188     {
1189         COMPlusThrow(kTypeLoadException, IDS_EE_SIMD_NGEN_DISALLOWED);
1190     }
1191
1192 #ifndef CROSSGEN_COMPILE
1193     if (!TargetHasAVXSupport())
1194         return false;
1195
1196     EEJitManager *jitMgr = ExecutionManager::GetEEJitManager();
1197     if (jitMgr->LoadJIT())
1198     {
1199         CORJIT_FLAGS cpuCompileFlags = jitMgr->GetCPUCompileFlags();
1200         if (cpuCompileFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_FEATURE_SIMD))
1201         {
1202             unsigned intrinsicSIMDVectorLength = jitMgr->m_jit->getMaxIntrinsicSIMDVectorLength(cpuCompileFlags);
1203             if (intrinsicSIMDVectorLength != 0)
1204             {
1205                 bmtFP->NumInstanceFieldBytes     = intrinsicSIMDVectorLength;
1206                 if (HasLayout())
1207                 {
1208                     GetLayoutInfo()->m_cbNativeSize = intrinsicSIMDVectorLength;
1209                     GetLayoutInfo()->m_cbManagedSize = intrinsicSIMDVectorLength;
1210                 }
1211                 return true;
1212             }
1213         }
1214     }
1215 #endif // !CROSSGEN_COMPILE
1216 #endif // defined(_TARGET_X86_) || defined(_TARGET_AMD64_)
1217     return false;
1218 }
1219
1220 //*******************************************************************************
1221 void
1222 MethodTableBuilder::bmtInterfaceEntry::CreateSlotTable(
1223     StackingAllocator * pStackingAllocator)
1224 {
1225     STANDARD_VM_CONTRACT;
1226
1227     CONSISTENCY_CHECK(m_pImplTable == NULL);
1228
1229     SLOT_INDEX cSlots = (SLOT_INDEX)GetInterfaceType()->GetMethodTable()->GetNumVirtuals();
1230     bmtInterfaceSlotImpl * pST = new (pStackingAllocator) bmtInterfaceSlotImpl[cSlots];
1231
1232     MethodTable::MethodIterator it(GetInterfaceType()->GetMethodTable());
1233     for (; it.IsValid(); it.Next())
1234     {
1235         if (!it.IsVirtual())
1236         {
1237             break;
1238         }
1239
1240         bmtRTMethod * pCurMethod = new (pStackingAllocator)
1241             bmtRTMethod(GetInterfaceType(), it.GetDeclMethodDesc());
1242
1243         CONSISTENCY_CHECK(m_cImplTable == it.GetSlotNumber());
1244         pST[m_cImplTable++] = bmtInterfaceSlotImpl(pCurMethod, INVALID_SLOT_INDEX);
1245     }
1246
1247     m_pImplTable = pST;
1248 }
1249
1250 #ifdef _PREFAST_ 
1251 #pragma warning(push)
1252 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
1253 #endif // _PREFAST_
1254 //---------------------------------------------------------------------------------------
1255 // 
1256 // Builds the method table, allocates MethodDesc, handles overloaded members, attempts to compress
1257 // interface storage.  All dependent classes must already be resolved!
1258 // 
1259 MethodTable *
1260 MethodTableBuilder::BuildMethodTableThrowing(
1261     LoaderAllocator *          pAllocator, 
1262     Module *                   pLoaderModule, 
1263     Module *                   pModule, 
1264     mdToken                    cl, 
1265     BuildingInterfaceInfo_t *  pBuildingInterfaceList, 
1266     const LayoutRawFieldInfo * pLayoutRawFieldInfos, 
1267     MethodTable *              pParentMethodTable, 
1268     const bmtGenericsInfo *    bmtGenericsInfo, 
1269     SigPointer                 parentInst, 
1270     WORD                       cBuildingInterfaceList)
1271 {
1272     CONTRACTL
1273     {
1274         STANDARD_VM_CHECK;
1275         PRECONDITION(CheckPointer(GetHalfBakedClass()));
1276         PRECONDITION(CheckPointer(bmtGenericsInfo));
1277     }
1278     CONTRACTL_END;
1279
1280     pModule->EnsureLibraryLoaded();
1281
1282     // The following structs, defined as private members of MethodTableBuilder, contain the necessary local
1283     // parameters needed for BuildMethodTable Look at the struct definitions for a detailed list of all
1284     // parameters available to BuildMethodTableThrowing.
1285
1286     SetBMTData(
1287         pAllocator,
1288         new (GetStackingAllocator()) bmtErrorInfo(),
1289         new (GetStackingAllocator()) bmtProperties(),
1290         new (GetStackingAllocator()) bmtVtable(),
1291         new (GetStackingAllocator()) bmtParentInfo(),
1292         new (GetStackingAllocator()) bmtInterfaceInfo(),
1293         new (GetStackingAllocator()) bmtMetaDataInfo(),
1294         new (GetStackingAllocator()) bmtMethodInfo(),
1295         new (GetStackingAllocator()) bmtMethAndFieldDescs(),
1296         new (GetStackingAllocator()) bmtFieldPlacement(),
1297         new (GetStackingAllocator()) bmtInternalInfo(),
1298         new (GetStackingAllocator()) bmtGCSeriesInfo(),
1299         new (GetStackingAllocator()) bmtMethodImplInfo(),
1300         bmtGenericsInfo,
1301         new (GetStackingAllocator()) bmtEnumFieldInfo(pModule->GetMDImport()),
1302         new (GetStackingAllocator()) bmtContextStaticInfo());
1303
1304     //Initialize structs
1305
1306     bmtError->resIDWhy = IDS_CLASSLOAD_GENERAL;          // Set the reason and the offending method def. If the method information
1307     bmtError->pThrowable = NULL;
1308     bmtError->pModule  = pModule;
1309     bmtError->cl       = cl;
1310
1311     bmtInternal->pInternalImport = pModule->GetMDImport();
1312     bmtInternal->pModule = pModule;
1313
1314     bmtInternal->pParentMT = pParentMethodTable;
1315
1316     // Create the chain of bmtRTType for the parent types. This allows all imported
1317     // parent methods to be associated with their declaring types, and as such it is
1318     // easy to access the appropriate Substitution when comparing signatures.
1319     bmtRTType * pParent = NULL;
1320     if (pParentMethodTable != NULL)
1321     {
1322         Substitution * pParentSubst =
1323             new (GetStackingAllocator()) Substitution(pModule, parentInst, NULL);
1324         pParent = CreateTypeChain(pParentMethodTable, *pParentSubst);
1325     }
1326
1327     // Now create the bmtMDType for the type being built.
1328     bmtInternal->pType = new (GetStackingAllocator())
1329         bmtMDType(pParent, pModule, cl, bmtGenericsInfo->typeContext);
1330
1331     // put the interior stack probe after all the stack-allocted goop above.  We check compare our this pointer to the SP on
1332     // the dtor to determine if we are being called on an EH path or not.
1333     INTERIOR_STACK_PROBE_FOR(GetThread(), 8);
1334
1335     // If not NULL, it means there are some by-value fields, and this contains an entry for each inst
1336
1337 #ifdef _DEBUG 
1338     // Set debug class name string for easier debugging.
1339     LPCUTF8 className;
1340     LPCUTF8 nameSpace;
1341     if (FAILED(GetMDImport()->GetNameOfTypeDef(bmtInternal->pType->GetTypeDefToken(), &className, &nameSpace)))
1342     {
1343         className = nameSpace = "Invalid TypeDef record";
1344     }
1345     
1346     {
1347         S_SIZE_T safeLen = S_SIZE_T(sizeof(char))*(S_SIZE_T(strlen(className)) + S_SIZE_T(strlen(nameSpace)) + S_SIZE_T(2));
1348         if(safeLen.IsOverflow()) COMPlusThrowHR(COR_E_OVERFLOW);
1349
1350         size_t len = safeLen.Value();
1351         char *name = (char*) AllocateFromHighFrequencyHeap(safeLen);
1352         strcpy_s(name, len, nameSpace);
1353         if (strlen(nameSpace) > 0) {
1354             name[strlen(nameSpace)] = '.';
1355             name[strlen(nameSpace) + 1] = '\0';
1356         }
1357         strcat_s(name, len, className);
1358
1359         GetHalfBakedClass()->SetDebugClassName(name);
1360     }
1361
1362     if (g_pConfig->ShouldBreakOnClassBuild(className))
1363     {
1364         CONSISTENCY_CHECK_MSGF(false, ("BreakOnClassBuild: typename '%s' ", className));
1365         GetHalfBakedClass()->m_fDebuggingClass = TRUE;
1366     }
1367
1368     LPCUTF8 pszDebugName,pszDebugNamespace;
1369     if (FAILED(pModule->GetMDImport()->GetNameOfTypeDef(bmtInternal->pType->GetTypeDefToken(), &pszDebugName, &pszDebugNamespace)))
1370     {
1371         pszDebugName = pszDebugNamespace = "Invalid TypeDef record";
1372     }
1373
1374     StackSString debugName(SString::Utf8, pszDebugName);
1375
1376     // If there is an instantiation, update the debug name to include instantiation type names.
1377     if (bmtGenerics->HasInstantiation())
1378     {
1379         StackSString debugName(SString::Utf8, GetDebugClassName());
1380         TypeString::AppendInst(debugName, bmtGenerics->GetInstantiation(), TypeString::FormatBasic);
1381         StackScratchBuffer buff;
1382         const char* pDebugNameUTF8 = debugName.GetUTF8(buff);
1383         S_SIZE_T safeLen = S_SIZE_T(strlen(pDebugNameUTF8)) + S_SIZE_T(1);
1384         if(safeLen.IsOverflow())
1385             COMPlusThrowHR(COR_E_OVERFLOW);
1386
1387         size_t len = safeLen.Value();
1388         char *name = (char*) AllocateFromLowFrequencyHeap(safeLen);
1389         strcpy_s(name, len, pDebugNameUTF8);
1390         GetHalfBakedClass()->SetDebugClassName(name);
1391         pszDebugName = (LPCUTF8)name;
1392     }
1393
1394     LOG((LF_CLASSLOADER, LL_INFO1000, "Loading class \"%s%s%S\" from module \"%ws\" in domain 0x%p %s\n",
1395         *pszDebugNamespace ? pszDebugNamespace : "",
1396         *pszDebugNamespace ? NAMESPACE_SEPARATOR_STR : "",
1397         debugName.GetUnicode(),
1398         pModule->GetDebugName(),
1399         pModule->GetDomain(),
1400         (pModule->IsSystem()) ? "System Domain" : ""
1401     ));
1402 #endif // _DEBUG
1403
1404     // If this is mscorlib, then don't perform some sanity checks on the layout
1405     bmtProp->fNoSanityChecks = ((g_pObjectClass == NULL) || pModule == g_pObjectClass->GetModule()) ||
1406 #ifdef FEATURE_READYTORUN
1407         // No sanity checks for ready-to-run compiled images if possible
1408         (pModule->IsReadyToRun() && pModule->GetReadyToRunInfo()->SkipTypeValidation()) ||
1409 #endif
1410         // No sanity checks for real generic instantiations
1411         !bmtGenerics->IsTypicalTypeDefinition();
1412
1413     // Interfaces have a parent class of Object, but we don't really want to inherit all of
1414     // Object's virtual methods, so pretend we don't have a parent class - at the bottom of this
1415     // function we reset the parent class
1416     if (IsInterface())
1417     {
1418         bmtInternal->pType->SetParentType(NULL);
1419         bmtInternal->pParentMT = NULL;
1420     }
1421
1422     unsigned totalDeclaredFieldSize=0;
1423
1424     // Check to see if the class is a valuetype; but we don't want to mark System.Enum
1425     // as a ValueType. To accomplish this, the check takes advantage of the fact
1426     // that System.ValueType and System.Enum are loaded one immediately after the
1427     // other in that order, and so if the parent MethodTable is System.ValueType and
1428     // the System.Enum MethodTable is unset, then we must be building System.Enum and
1429     // so we don't mark it as a ValueType.
1430     if(HasParent() &&
1431        ((g_pEnumClass != NULL && GetParentMethodTable() == g_pValueTypeClass) ||
1432         GetParentMethodTable() == g_pEnumClass))
1433     {
1434         bmtProp->fIsValueClass = true;
1435
1436         HRESULT hr = GetMDImport()->GetCustomAttributeByName(bmtInternal->pType->GetTypeDefToken(),
1437                                                                 g_CompilerServicesUnsafeValueTypeAttribute,
1438                                                                 NULL, NULL);
1439         IfFailThrow(hr);
1440         if (hr == S_OK)
1441         {
1442             SetUnsafeValueClass();
1443         }
1444
1445         hr = GetMDImport()->GetCustomAttributeByName(bmtInternal->pType->GetTypeDefToken(),
1446             g_CompilerServicesIsByRefLikeAttribute,
1447             NULL, NULL);
1448         IfFailThrow(hr);
1449         if (hr == S_OK)
1450         {
1451             bmtFP->fIsByRefLikeType = true;
1452         }
1453     }
1454
1455     // Check to see if the class is an enumeration. No fancy checks like the one immediately
1456     // above for value types are necessary here.
1457     if(HasParent() && GetParentMethodTable() == g_pEnumClass)
1458     {
1459         bmtProp->fIsEnum = true;
1460
1461         // Ensure we don't have generic enums, or at least enums that have a
1462         // different number of type parameters from their enclosing class.
1463         // The goal is to ensure that the enum's values can't depend on the
1464         // type parameters in any way.  And we don't see any need for an
1465         // enum to have additional type parameters.
1466         if (bmtGenerics->GetNumGenericArgs() != 0)
1467         {
1468             // Nested enums can have generic type parameters from their enclosing class.
1469             // CLS rules require type parameters to be propogated to nested types.
1470             // Note that class G<T> { enum E { } } will produce "G`1+E<T>".
1471             // We want to disallow class G<T> { enum E<T, U> { } }
1472             // Perhaps the IL equivalent of class G<T> { enum E { } } should be legal.
1473             if (!IsNested())
1474             {
1475                 BuildMethodTableThrowException(IDS_CLASSLOAD_ENUM_EXTRA_GENERIC_TYPE_PARAM);
1476             }
1477
1478             mdTypeDef tdEnclosing = mdTypeDefNil;
1479             HRESULT hr = GetMDImport()->GetNestedClassProps(GetCl(), &tdEnclosing);
1480             if (FAILED(hr))
1481                 ThrowHR(hr, BFA_UNABLE_TO_GET_NESTED_PROPS);
1482
1483             HENUMInternalHolder   hEnumGenericPars(GetMDImport());
1484             if (FAILED(hEnumGenericPars.EnumInitNoThrow(mdtGenericParam, tdEnclosing)))
1485             {
1486                 GetAssembly()->ThrowTypeLoadException(GetMDImport(), tdEnclosing, IDS_CLASSLOAD_BADFORMAT);
1487             }
1488
1489             if (hEnumGenericPars.EnumGetCount() != bmtGenerics->GetNumGenericArgs())
1490             {
1491                 BuildMethodTableThrowException(IDS_CLASSLOAD_ENUM_EXTRA_GENERIC_TYPE_PARAM);
1492             }
1493         }
1494     }
1495
1496 #if defined(_TARGET_X86_) || defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_)
1497     if (GetModule()->IsSystem() && !bmtGenerics->HasInstantiation())
1498     {
1499         LPCUTF8 className;
1500         LPCUTF8 nameSpace;
1501         HRESULT hr = GetMDImport()->GetNameOfTypeDef(bmtInternal->pType->GetTypeDefToken(), &className, &nameSpace);
1502
1503         if (hr == S_OK && strcmp(nameSpace, "System.Runtime.Intrinsics") == 0)
1504         {
1505             if (IsCompilationProcess())
1506             {
1507                 // Disable AOT compiling for the SIMD hardware intrinsic types. These types require special
1508                 // ABI handling as they represent fundamental data types (__m64, __m128, and __m256) and not
1509                 // aggregate or union types. See https://github.com/dotnet/coreclr/issues/15943
1510                 //
1511                 // Once they are properly handled according to the ABI requirements, we can remove this check
1512                 // and allow them to be used in crossgen/AOT scenarios.
1513                 COMPlusThrow(kTypeLoadException, IDS_EE_HWINTRINSIC_NGEN_DISALLOWED);
1514             }
1515         }
1516
1517 #if defined(_TARGET_ARM64_)
1518         // All the funtions in System.Runtime.Intrinsics.Arm.Arm64 are hardware intrinsics.
1519         if (hr == S_OK && strcmp(nameSpace, "System.Runtime.Intrinsics.Arm.Arm64") == 0)
1520 #else
1521         // All the funtions in System.Runtime.Intrinsics.X86 are hardware intrinsics.
1522         if (hr == S_OK && strcmp(nameSpace, "System.Runtime.Intrinsics.X86") == 0)
1523 #endif
1524         {
1525             if (IsCompilationProcess())
1526             {
1527                 // Disable AOT compiling for managed implementation of hardware intrinsics in mscorlib.
1528                 // We specially treat them here to ensure correct ISA features are set during compilation
1529                 COMPlusThrow(kTypeLoadException, IDS_EE_HWINTRINSIC_NGEN_DISALLOWED);
1530             }
1531             bmtProp->fIsHardwareIntrinsic = true;
1532         }
1533     }
1534 #endif
1535
1536 #ifdef FEATURE_COMINTEROP 
1537
1538     // Com Import classes are special. These types must derive from System.Object,
1539     // and we then substitute the parent with System._ComObject.
1540     if (IsComImport() && !IsEnum() && !IsInterface() && !IsValueClass() && !IsDelegate())
1541     {
1542         // ComImport classes must either extend from Object or be a WinRT class
1543         // that extends from another WinRT class (and so form a chain of WinRT classes
1544         // that ultimately extend from object).
1545         MethodTable* pMTParent = GetParentMethodTable();
1546         if ((pMTParent == NULL) || !(
1547                 // is the parent valid?
1548                 (pMTParent == g_pObjectClass) ||
1549                 (GetHalfBakedClass()->IsProjectedFromWinRT() && pMTParent->IsProjectedFromWinRT())
1550                 ))
1551         {
1552             BuildMethodTableThrowException(IDS_CLASSLOAD_CANTEXTEND);
1553         }
1554
1555         if (HasLayout())
1556         {
1557             // ComImport classes cannot have layout information.
1558             BuildMethodTableThrowException(IDS_CLASSLOAD_COMIMPCANNOTHAVELAYOUT);
1559         }
1560
1561         if (pMTParent == g_pObjectClass)
1562         {                
1563             // ComImport classes ultimately extend from our __ComObject or RuntimeClass class
1564             MethodTable *pCOMMT = NULL;
1565             if (GetHalfBakedClass()->IsProjectedFromWinRT())
1566                 pCOMMT = g_pBaseRuntimeClass;
1567             else
1568                 pCOMMT = g_pBaseCOMObject;
1569             
1570             _ASSERTE(pCOMMT);
1571
1572             // We could have had COM interop classes derive from System._ComObject,
1573             // but instead we have them derive from System.Object, have them set the
1574             // ComImport bit in the type attributes, and then we swap out the parent
1575             // type under the covers.
1576             bmtInternal->pType->SetParentType(CreateTypeChain(pCOMMT, Substitution()));
1577             bmtInternal->pParentMT = pCOMMT;
1578         }
1579
1580         // if the current class is imported
1581         bmtProp->fIsComObjectType = true;
1582     }
1583
1584     if (GetHalfBakedClass()->IsProjectedFromWinRT() && IsValueClass() && !IsEnum())
1585     {
1586         // WinRT structures must have sequential layout
1587         if (!GetHalfBakedClass()->HasSequentialLayout())
1588         {
1589             BuildMethodTableThrowException(IDS_EE_STRUCTLAYOUT_WINRT);
1590         }
1591     }
1592
1593     // Check for special COM interop types.
1594     CheckForSpecialTypes();
1595
1596     CheckForTypeEquivalence(cBuildingInterfaceList, pBuildingInterfaceList);
1597
1598     if (HasParent())
1599     {   // Types that inherit from com object types are themselves com object types.
1600         if (GetParentMethodTable()->IsComObjectType())
1601         {
1602             // if the parent class is of ComObjectType
1603             // so is the child
1604             bmtProp->fIsComObjectType = true;
1605         }
1606
1607 #ifdef FEATURE_TYPEEQUIVALENCE
1608         // If your parent is type equivalent then so are you
1609         if (GetParentMethodTable()->HasTypeEquivalence())
1610         {
1611             bmtProp->fHasTypeEquivalence = true;
1612         }
1613 #endif
1614     }
1615
1616 #endif // FEATURE_COMINTEROP
1617
1618     if (!HasParent() && !IsInterface())
1619     {
1620         if(g_pObjectClass != NULL)
1621         {
1622             if(!IsGlobalClass())
1623             {
1624                 // Non object derived types that are not the global class are prohibited by spec
1625                 BuildMethodTableThrowException(IDS_CLASSLOAD_PARENTNULL);
1626             }
1627         }
1628     }
1629
1630     // NOTE: This appears to be the earliest point during class loading that other classes MUST be loaded
1631     // resolve unresolved interfaces, determine an upper bound on the size of the interface map,
1632     // and determine the size of the largest interface (in # slots)
1633     ResolveInterfaces(cBuildingInterfaceList, pBuildingInterfaceList);
1634
1635     // Enumerate this class's methodImpls
1636     EnumerateMethodImpls();
1637
1638     // Enumerate this class's methods and fields
1639     EnumerateClassMethods();
1640     ValidateMethods();
1641
1642     EnumerateClassFields();
1643
1644     // Import the slots of the parent for use in placing this type's methods.
1645     ImportParentMethods();
1646
1647     // This will allocate the working versions of the VTable and NonVTable in bmtVT
1648     AllocateWorkingSlotTables();
1649
1650     // Allocate a MethodDesc* for each method (needed later when doing interfaces), and a FieldDesc* for each field
1651     AllocateFieldDescs();
1652
1653     // Copy the parent's vtable into the current type's vtable
1654     CopyParentVtable();
1655
1656     bmtVT->pDispatchMapBuilder = new (GetStackingAllocator()) DispatchMapBuilder(GetStackingAllocator());
1657
1658     // Determine vtable placement for each member in this class
1659     PlaceVirtualMethods();
1660     PlaceNonVirtualMethods();
1661
1662     // Allocate MethodDescs (expects methods placed methods)
1663     AllocAndInitMethodDescs();
1664
1665     if (IsInterface())
1666     {
1667         //
1668         // We need to process/place method impls for default interface method overrides.
1669         // We won't build dispatch map for interfaces, though.
1670         //
1671         ProcessMethodImpls();
1672         PlaceMethodImpls();
1673     }
1674     else
1675     {
1676         //
1677         // If we are a class, then there may be some unplaced vtable methods (which are by definition
1678         // interface methods, otherwise they'd already have been placed).  Place as many unplaced methods
1679         // as possible, in the order preferred by interfaces.  However, do not allow any duplicates - once
1680         // a method has been placed, it cannot be placed again - if we are unable to neatly place an interface,
1681         // create duplicate slots for it starting at dwCurrentDuplicateVtableSlot.  Fill out the interface
1682         // map for all interfaces as they are placed.
1683         //
1684         // If we are an interface, then all methods are already placed.  Fill out the interface map for
1685         // interfaces as they are placed.
1686         //
1687         ComputeInterfaceMapEquivalenceSet();
1688
1689         PlaceInterfaceMethods();
1690
1691         ProcessMethodImpls();
1692         ProcessInexactMethodImpls();
1693         PlaceMethodImpls();
1694
1695         if (!bmtProp->fNoSanityChecks)
1696         {
1697             // Now that interface method implementation have been fully resolved,
1698             // we need to make sure that type constraints are also met.
1699             ValidateInterfaceMethodConstraints();
1700         }
1701     }
1702
1703     // Verify that we have not overflowed the number of slots.
1704     if (!FitsInU2((UINT64)bmtVT->pSlotTable->GetSlotCount()))
1705     {
1706         BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
1707     }
1708
1709     // ensure we didn't overflow the temporary vtable
1710     _ASSERTE(bmtVT->pSlotTable->GetSlotCount() <= bmtVT->dwMaxVtableSize);
1711
1712     // Allocate and initialize the dictionary for the type. This will be filled out later
1713     // with the final values.
1714     AllocAndInitDictionary();
1715
1716     ////////////////////////////////////////////////////////////////////////////////////////////////
1717     // Fields
1718     //
1719
1720     // We decide here if we need a dynamic entry for our statics. We need it here because
1721     // the offsets of our fields will depend on this. For the dynamic case (which requires
1722     // an extra indirection (indirect depending of methodtable) we'll allocate the slot
1723     // in setupmethodtable
1724     if (((pModule->IsReflection() || bmtGenerics->HasInstantiation() || !pModule->IsStaticStoragePrepared(cl)) &&
1725         (bmtVT->GetClassCtorSlotIndex() != INVALID_SLOT_INDEX || bmtEnumFields->dwNumStaticFields !=0))
1726 #ifdef EnC_SUPPORTED 
1727         // Classes in modules that have been edited (would do on class level if there were a
1728         // way to tell if the class had been edited) also have dynamic statics as the number
1729         // of statics might have changed, so can't use the static module-wide storage
1730         || (pModule->IsEditAndContinueEnabled() &&
1731                 ((EditAndContinueModule*)pModule)->GetApplyChangesCount() > CorDB_DEFAULT_ENC_FUNCTION_VERSION)
1732 #endif // EnC_SUPPORTED
1733         )
1734     {
1735         // We will need a dynamic id
1736         bmtProp->fDynamicStatics = true;
1737
1738         if (bmtGenerics->HasInstantiation())
1739         {
1740             bmtProp->fGenericsStatics = true;
1741         }
1742     }
1743
1744     // If not NULL, it means there are some by-value fields, and this contains an entry for each instance or static field,
1745     // which is NULL if not a by value field, and points to the EEClass of the field if a by value field.  Instance fields
1746     // come first, statics come second.
1747     MethodTable ** pByValueClassCache = NULL;
1748
1749     // Go thru all fields and initialize their FieldDescs.
1750     InitializeFieldDescs(GetApproxFieldDescListRaw(), pLayoutRawFieldInfos, bmtInternal, bmtGenerics,
1751         bmtMetaData, bmtEnumFields, bmtError,
1752         &pByValueClassCache, bmtMFDescs, bmtFP, bmtCSInfo,
1753         &totalDeclaredFieldSize);
1754
1755     // Place regular static fields
1756     PlaceRegularStaticFields();
1757
1758     // Place thread static fields
1759     PlaceThreadStaticFields();
1760
1761     LOG((LF_CODESHARING,
1762             LL_INFO10000,
1763             "Placing %d statics (%d handles) for class %s.\n",
1764             GetNumStaticFields(), GetNumHandleRegularStatics() + GetNumHandleThreadStatics(),
1765             pszDebugName));
1766
1767     if (IsBlittable() || IsManagedSequential())
1768     {
1769         bmtFP->NumGCPointerSeries = 0;
1770         bmtFP->NumInstanceGCPointerFields = 0;
1771
1772         _ASSERTE(HasLayout());
1773
1774         bmtFP->NumInstanceFieldBytes = IsBlittable() ? GetLayoutInfo()->m_cbNativeSize
1775                                                      : GetLayoutInfo()->m_cbManagedSize;
1776
1777         // For simple Blittable types we still need to check if they have any overlapping 
1778         // fields and call the method SetHasOverLayedFields() when they are detected.
1779         //
1780         if (HasExplicitFieldOffsetLayout())
1781         {
1782             _ASSERTE(!bmtGenerics->fContainsGenericVariables);   // A simple Blittable type can't ever be an open generic type.
1783             HandleExplicitLayout(pByValueClassCache);
1784         }
1785     }
1786     else
1787     {
1788         _ASSERTE(!IsBlittable());
1789         // HandleExplicitLayout fails for the GenericTypeDefinition when
1790         // it will succeed for some particular instantiations.
1791         // Thus we only do explicit layout for real instantiations, e.g. C<int>, not
1792         // the open types such as the GenericTypeDefinition C<!0> or any
1793         // of the "fake" types involving generic type variables which are
1794         // used for reflection and verification, e.g. C<List<!0>>.
1795         // 
1796         if (!bmtGenerics->fContainsGenericVariables && HasExplicitFieldOffsetLayout())
1797         {
1798             HandleExplicitLayout(pByValueClassCache);
1799         }
1800         else
1801         {
1802             // Place instance fields
1803             PlaceInstanceFields(pByValueClassCache);
1804         }
1805     }
1806
1807     if (CheckIfSIMDAndUpdateSize())
1808     {
1809         totalDeclaredFieldSize = bmtFP->NumInstanceFieldBytes;
1810     }
1811
1812     // We enforce that all value classes have non-zero size
1813     if (IsValueClass() && bmtFP->NumInstanceFieldBytes == 0)
1814     {
1815         BuildMethodTableThrowException(IDS_CLASSLOAD_ZEROSIZE);
1816     }
1817     
1818     if (bmtFP->fHasSelfReferencingStaticValueTypeField_WithRVA)
1819     {   // Verify self-referencing statics with RVA (now when the ValueType size is known)
1820         VerifySelfReferencingStaticValueTypeFields_WithRVA(pByValueClassCache);
1821     }
1822     
1823
1824     // Now setup the method table
1825
1826 #ifdef FEATURE_PREJIT
1827     Module *pComputedPZM = pLoaderModule;
1828
1829     if (bmtGenerics->GetNumGenericArgs() > 0)
1830     {
1831         pComputedPZM = Module::ComputePreferredZapModule(pModule, bmtGenerics->GetInstantiation());
1832     }
1833
1834     SetupMethodTable2(pLoaderModule, pComputedPZM);
1835 #else // FEATURE_PREJIT
1836     SetupMethodTable2(pLoaderModule);
1837 #endif // FEATURE_PREJIT
1838
1839     MethodTable * pMT = GetHalfBakedMethodTable();
1840
1841 #ifdef FEATURE_64BIT_ALIGNMENT
1842     if (GetHalfBakedClass()->IsAlign8Candidate())
1843         pMT->SetRequiresAlign8();
1844 #endif
1845
1846     if (bmtGenerics->pVarianceInfo != NULL)
1847     {
1848         pMT->SetHasVariance();
1849     }
1850
1851     if (bmtFP->NumRegularStaticGCBoxedFields != 0)
1852     {
1853         pMT->SetHasBoxedRegularStatics();
1854     }
1855
1856     if (bmtFP->fIsByRefLikeType)
1857     {
1858         pMT->SetIsByRefLike();
1859     }
1860
1861     if (IsValueClass())
1862     {
1863         if (bmtFP->NumInstanceFieldBytes != totalDeclaredFieldSize || HasOverLayedField())
1864             GetHalfBakedClass()->SetIsNotTightlyPacked();
1865
1866 #ifdef FEATURE_HFA
1867         GetHalfBakedClass()->CheckForHFA(pByValueClassCache);
1868 #endif
1869 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
1870 #ifdef FEATURE_HFA
1871 #error Can't have FEATURE_HFA and FEATURE_UNIX_AMD64_STRUCT_PASSING defined at the same time.
1872 #endif // FEATURE_HFA
1873         SystemVAmd64CheckForPassStructInRegister();
1874 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
1875     }
1876
1877 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
1878 #ifdef FEATURE_HFA
1879 #error Can't have FEATURE_HFA and FEATURE_UNIX_AMD64_STRUCT_PASSING defined at the same time.
1880 #endif // FEATURE_HFA
1881     if (HasLayout())
1882     {
1883         SystemVAmd64CheckForPassNativeStructInRegister();
1884     }
1885 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
1886 #ifdef FEATURE_HFA
1887     if (HasLayout())
1888     {
1889         GetHalfBakedClass()->CheckForNativeHFA();
1890     }
1891 #endif
1892
1893 #ifdef _DEBUG 
1894     pMT->SetDebugClassName(GetDebugClassName());
1895 #endif
1896
1897 #ifdef FEATURE_COMINTEROP 
1898     if (IsInterface())
1899     {
1900         GetCoClassAttribInfo();
1901     }
1902 #endif // FEATURE_COMINTEROP
1903
1904     if (HasExplicitFieldOffsetLayout())
1905         // Perform relevant GC calculations for tdexplicit
1906         HandleGCForExplicitLayout();
1907     else
1908         // Perform relevant GC calculations for value classes
1909         HandleGCForValueClasses(pByValueClassCache);
1910
1911         // GC reqires the series to be sorted.
1912         // TODO: fix it so that we emit them in the correct order in the first place.
1913     if (pMT->ContainsPointers())
1914     {
1915         CGCDesc* gcDesc = CGCDesc::GetCGCDescFromMT(pMT);
1916         qsort(gcDesc->GetLowestSeries(), (int)gcDesc->GetNumSeries(), sizeof(CGCDescSeries), compareCGCDescSeries);
1917     }
1918
1919     SetFinalizationSemantics();
1920
1921 #if defined(_DEBUG)
1922     // Figure out if we're domain agile..
1923     // Note that this checks a bunch of field directly on the class & method table,
1924     // so it needs to come late in the game.
1925     EEClass::SetAppDomainAgileAttribute(pMT);
1926 #endif
1927
1928     // Allocate dynamic slot if necessary
1929     if (bmtProp->fDynamicStatics)
1930     {
1931         if (bmtProp->fGenericsStatics)
1932         {
1933             FieldDesc* pStaticFieldDescs = NULL;
1934
1935             if (bmtEnumFields->dwNumStaticFields != 0)
1936             {
1937                 pStaticFieldDescs = pMT->GetApproxFieldDescListRaw() + bmtEnumFields->dwNumInstanceFields;
1938             }
1939
1940             pMT->SetupGenericsStaticsInfo(pStaticFieldDescs);
1941         }
1942         else
1943         {
1944             // Get an id for the dynamic class. We store it in the class because
1945             // no class that is persisted in ngen should have it (ie, if the class is ngened
1946             // The id is stored in an optional field so we need to ensure an optional field descriptor has
1947             // been allocated for this EEClass instance.
1948             EnsureOptionalFieldsAreAllocated(GetHalfBakedClass(), m_pAllocMemTracker, pAllocator->GetLowFrequencyHeap());
1949             SetModuleDynamicID(GetModule()->AllocateDynamicEntry(pMT));
1950         }
1951     }
1952
1953     //
1954     // if there are context or thread static set the info in the method table optional members
1955     //
1956
1957     // Check for the RemotingProxy Attribute
1958     // structs with GC pointers MUST be pointer sized aligned because the GC assumes it
1959     if (IsValueClass() && pMT->ContainsPointers() && (bmtFP->NumInstanceFieldBytes % sizeof(void*) != 0))
1960     {
1961         BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
1962     }
1963
1964     if (IsInterface())
1965     {
1966         // Reset parent class
1967         pMT->SetParentMethodTable (g_pObjectClass);
1968     }
1969
1970 #ifdef _DEBUG 
1971     // Reset the debug method names for BoxedEntryPointStubs
1972     // so they reflect the very best debug information for the methods
1973     {
1974         DeclaredMethodIterator methIt(*this);
1975         while (methIt.Next())
1976         {
1977             if (methIt->GetUnboxedMethodDesc() != NULL)
1978             {
1979                 {
1980                     MethodDesc *pMD = methIt->GetUnboxedMethodDesc();
1981                     StackSString name(SString::Utf8);
1982                     TypeString::AppendMethodDebug(name, pMD);
1983                     StackScratchBuffer buff;
1984                     const char* pDebugNameUTF8 = name.GetUTF8(buff);
1985                     S_SIZE_T safeLen = S_SIZE_T(strlen(pDebugNameUTF8)) + S_SIZE_T(1);
1986                     if(safeLen.IsOverflow()) COMPlusThrowHR(COR_E_OVERFLOW);
1987                     size_t len = safeLen.Value();
1988                     pMD->m_pszDebugMethodName = (char*) AllocateFromLowFrequencyHeap(safeLen);
1989                     _ASSERTE(pMD->m_pszDebugMethodName);
1990                     strcpy_s((char *) pMD->m_pszDebugMethodName, len, pDebugNameUTF8);
1991                 }
1992
1993                 {
1994                     MethodDesc *pMD = methIt->GetMethodDesc();
1995
1996                     StackSString name(SString::Utf8);
1997                     TypeString::AppendMethodDebug(name, pMD);
1998                     StackScratchBuffer buff;
1999                     const char* pDebugNameUTF8 = name.GetUTF8(buff);
2000                     S_SIZE_T safeLen = S_SIZE_T(strlen(pDebugNameUTF8))+S_SIZE_T(1);
2001                     if(safeLen.IsOverflow()) COMPlusThrowHR(COR_E_OVERFLOW);
2002                     size_t len = safeLen.Value();
2003                     pMD->m_pszDebugMethodName = (char*) AllocateFromLowFrequencyHeap(safeLen);
2004                     _ASSERTE(pMD->m_pszDebugMethodName);
2005                     strcpy_s((char *) pMD->m_pszDebugMethodName, len, pDebugNameUTF8);
2006                 }
2007             }
2008         }
2009     }
2010 #endif // _DEBUG
2011
2012
2013     //If this is a value type, then propagate the UnsafeValueTypeAttribute from
2014     //its instance members to this type.
2015     if (IsValueClass() && !IsUnsafeValueClass())
2016     {
2017         ApproxFieldDescIterator fields(GetHalfBakedMethodTable(),
2018                                        ApproxFieldDescIterator::INSTANCE_FIELDS );
2019         FieldDesc * current;
2020         while (NULL != (current = fields.Next()))
2021         {
2022             CONSISTENCY_CHECK(!current->IsStatic());
2023             if (current->GetFieldType() == ELEMENT_TYPE_VALUETYPE)
2024             {
2025                 TypeHandle th = current->LookupApproxFieldTypeHandle();
2026                 CONSISTENCY_CHECK(!th.IsNull());
2027                 if (th.AsMethodTable()->GetClass()->IsUnsafeValueClass())
2028                 {
2029                     SetUnsafeValueClass();
2030                     break;
2031                 }
2032             }
2033         }
2034     }
2035
2036 #ifdef FEATURE_ICASTABLE
2037     if (!IsValueClass() && g_pICastableInterface != NULL && pMT->CanCastToInterface(g_pICastableInterface))
2038     {
2039         pMT->SetICastable();
2040     }
2041 #endif // FEATURE_ICASTABLE       
2042
2043     // Grow the typedef ridmap in advance as we can't afford to
2044     // fail once we set the resolve bit
2045     pModule->EnsureTypeDefCanBeStored(bmtInternal->pType->GetTypeDefToken());
2046
2047     // Grow the tables in advance so that RID map filling cannot fail
2048     // once we're past the commit point.
2049     EnsureRIDMapsCanBeFilled();
2050
2051     {
2052         // NOTE. NOTE!! the EEclass can now be accessed by other threads.
2053         // Do NOT place any initialization after this point.
2054         // You may NOT fail the call after this point.
2055         FAULT_FORBID();
2056         CANNOTTHROWCOMPLUSEXCEPTION();
2057
2058         /*
2059         GetMemTracker()->SuppressRelease();
2060         */
2061     }
2062     
2063 #ifdef _DEBUG 
2064     if (g_pConfig->ShouldDumpOnClassLoad(pszDebugName))
2065     {
2066         LOG((LF_ALWAYS, LL_ALWAYS, "Method table summary for '%s':\n", pszDebugName));
2067         LOG((LF_ALWAYS, LL_ALWAYS, "Number of static fields: %d\n", bmtEnumFields->dwNumStaticFields));
2068         LOG((LF_ALWAYS, LL_ALWAYS, "Number of instance fields: %d\n", bmtEnumFields->dwNumInstanceFields));
2069         LOG((LF_ALWAYS, LL_ALWAYS, "Number of static obj ref fields: %d\n", bmtEnumFields->dwNumStaticObjRefFields));
2070         LOG((LF_ALWAYS, LL_ALWAYS, "Number of static boxed fields: %d\n", bmtEnumFields->dwNumStaticBoxedFields));
2071         LOG((LF_ALWAYS, LL_ALWAYS, "Number of declared fields: %d\n", NumDeclaredFields()));
2072         LOG((LF_ALWAYS, LL_ALWAYS, "Number of declared methods: %d\n", NumDeclaredMethods()));
2073         LOG((LF_ALWAYS, LL_ALWAYS, "Number of declared non-abstract methods: %d\n", bmtMethod->dwNumDeclaredNonAbstractMethods));
2074         pMT->Debug_DumpInterfaceMap("Approximate");
2075         pMT->DebugDumpVtable(pszDebugName, FALSE);
2076         pMT->DebugDumpFieldLayout(pszDebugName, FALSE);
2077         pMT->DebugDumpGCDesc(pszDebugName, FALSE);
2078         pMT->Debug_DumpDispatchMap();
2079     }
2080 #endif //_DEBUG
2081     
2082     STRESS_LOG3(LF_CLASSLOADER,  LL_INFO1000, "MethodTableBuilder: finished method table for module %p token %x = %pT \n",
2083         pModule,
2084         GetCl(),
2085         GetHalfBakedMethodTable());
2086
2087 #ifdef MDA_SUPPORTED
2088     MdaMarshaling* mda = MDA_GET_ASSISTANT(Marshaling);
2089     if (mda && HasLayout())
2090     {
2091         FieldMarshaler *pFieldMarshaler = (FieldMarshaler*)GetLayoutInfo()->GetFieldMarshalers();
2092         UINT  numReferenceFields        = GetLayoutInfo()->GetNumCTMFields();
2093
2094         while (numReferenceFields--)
2095         {
2096             mda->ReportFieldMarshal(pFieldMarshaler);
2097
2098             ((BYTE*&)pFieldMarshaler) += MAXFIELDMARSHALERSIZE;
2099         }
2100     }
2101 #endif // MDA_SUPPORTED
2102
2103 #ifdef FEATURE_PREJIT
2104     _ASSERTE(pComputedPZM == Module::GetPreferredZapModuleForMethodTable(pMT));
2105 #endif // FEATURE_PREJIT
2106
2107     END_INTERIOR_STACK_PROBE;
2108
2109     return GetHalfBakedMethodTable();
2110 } // MethodTableBuilder::BuildMethodTableThrowing
2111 #ifdef _PREFAST_ 
2112 #pragma warning(pop)
2113 #endif
2114
2115
2116 //---------------------------------------------------------------------------------------
2117 // 
2118 // Resolve unresolved interfaces, determine an upper bound on the size of the interface map.
2119 // 
2120 VOID 
2121 MethodTableBuilder::ResolveInterfaces(
2122     WORD                      cBuildingInterfaceList, 
2123     BuildingInterfaceInfo_t * pBuildingInterfaceList)
2124 {
2125     CONTRACTL
2126     {
2127         STANDARD_VM_CHECK;
2128         PRECONDITION(CheckPointer(this));
2129         PRECONDITION(CheckPointer(bmtAllocator));
2130         PRECONDITION(CheckPointer(bmtInterface));
2131         PRECONDITION(CheckPointer(bmtVT));
2132         PRECONDITION(CheckPointer(bmtParent));
2133     }
2134     CONTRACTL_END;
2135
2136     // resolve unresolved interfaces and determine the size of the largest interface (in # slots)
2137
2138
2139     LoadApproxInterfaceMap();
2140
2141     // Inherit parental slot counts
2142     //@TODO: This doesn't belong here.
2143     if (HasParent())
2144     {
2145         MethodTable * pParentClass = GetParentMethodTable();
2146         PREFIX_ASSUME(pParentClass != NULL);
2147
2148         bmtParent->NumParentPointerSeries  = pParentClass->ContainsPointers() ?
2149             (DWORD)CGCDesc::GetCGCDescFromMT(pParentClass)->GetNumSeries() : 0;
2150
2151         if (pParentClass->HasFieldsWhichMustBeInited())
2152         {
2153             SetHasFieldsWhichMustBeInited();
2154         }
2155 #ifdef FEATURE_READYTORUN
2156         if (!(IsValueClass() || (pParentClass == g_pObjectClass)))
2157         {
2158             CheckLayoutDependsOnOtherModules(pParentClass);
2159         }
2160 #endif
2161     }
2162     else
2163     {
2164         bmtParent->NumParentPointerSeries  = 0;
2165     }
2166 } // MethodTableBuilder::ResolveInterfaces
2167
2168 //*******************************************************************************
2169 /* static */
2170 int __cdecl MethodTableBuilder::bmtMetaDataInfo::MethodImplTokenPair::Compare(
2171         const void *elem1,
2172         const void *elem2)
2173 {
2174     STATIC_CONTRACT_LEAF;
2175     MethodImplTokenPair *e1 = (MethodImplTokenPair *)elem1;
2176     MethodImplTokenPair *e2 = (MethodImplTokenPair *)elem2;
2177     if (e1->methodBody < e2->methodBody) return -1;
2178     else if (e1->methodBody > e2->methodBody) return 1;
2179     else if (e1->methodDecl < e2->methodDecl) return -1;
2180     else if (e1->methodDecl > e2->methodDecl) return 1;
2181     else return 0;
2182 }
2183
2184 //*******************************************************************************
2185 /* static */
2186 BOOL MethodTableBuilder::bmtMetaDataInfo::MethodImplTokenPair::Equal(
2187         const MethodImplTokenPair *elem1,
2188         const MethodImplTokenPair *elem2)
2189 {
2190     STATIC_CONTRACT_LEAF;
2191     return ((elem1->methodBody == elem2->methodBody) &&
2192             (elem1->methodDecl == elem2->methodDecl));
2193 }
2194
2195 //*******************************************************************************
2196 VOID
2197 MethodTableBuilder::EnumerateMethodImpls()
2198 {
2199     STANDARD_VM_CONTRACT;
2200
2201     HRESULT hr = S_OK;
2202     IMDInternalImport * pMDInternalImport = GetMDImport();
2203     DWORD rid, maxRidMD, maxRidMR;
2204     HENUMInternalMethodImplHolder hEnumMethodImpl(pMDInternalImport);
2205     hr = hEnumMethodImpl.EnumMethodImplInitNoThrow(GetCl());
2206     
2207     if (FAILED(hr))
2208     {
2209         BuildMethodTableThrowException(hr, *bmtError);
2210     }
2211     
2212     // This gets the count out of the metadata interface.
2213     bmtMethod->dwNumberMethodImpls = hEnumMethodImpl.EnumMethodImplGetCount();
2214     bmtMethod->dwNumberInexactMethodImplCandidates = 0;
2215
2216     // This is the first pass. In this we will simply enumerate the token pairs and fill in
2217     // the data structures. In addition, we'll sort the list and eliminate duplicates.
2218     if (bmtMethod->dwNumberMethodImpls > 0)
2219     {
2220         //
2221         // Allocate the structures to keep track of the token pairs
2222         //
2223         bmtMetaData->rgMethodImplTokens = new (GetStackingAllocator())
2224             bmtMetaDataInfo::MethodImplTokenPair[bmtMethod->dwNumberMethodImpls];
2225
2226         // Iterate through each MethodImpl declared on this class
2227         for (DWORD i = 0; i < bmtMethod->dwNumberMethodImpls; i++)
2228         {
2229             hr = hEnumMethodImpl.EnumMethodImplNext(
2230                 &bmtMetaData->rgMethodImplTokens[i].methodBody,
2231                 &bmtMetaData->rgMethodImplTokens[i].methodDecl);
2232             bmtMetaData->rgMethodImplTokens[i].fConsiderDuringInexactMethodImplProcessing = false;
2233             bmtMetaData->rgMethodImplTokens[i].fThrowIfUnmatchedDuringInexactMethodImplProcessing = false;
2234             bmtMetaData->rgMethodImplTokens[i].interfaceEquivalenceSet = 0;
2235
2236             if (FAILED(hr))
2237             {
2238                 BuildMethodTableThrowException(hr, *bmtError);
2239             }
2240             // Grab the next set of body/decl tokens
2241             if (hr == S_FALSE)
2242             {
2243                 // In the odd case that the enumerator fails before we've reached the total reported
2244                 // entries, let's reset the count and just break out. (Should we throw?)
2245                 bmtMethod->dwNumberMethodImpls = i;
2246                 break;
2247             }
2248         }
2249
2250         // No need to do any sorting or duplicate elimination if there's not two or more methodImpls
2251         if (bmtMethod->dwNumberMethodImpls > 1)
2252         {
2253             // Now sort
2254             qsort(bmtMetaData->rgMethodImplTokens,
2255                   bmtMethod->dwNumberMethodImpls,
2256                   sizeof(bmtMetaDataInfo::MethodImplTokenPair),
2257                   &bmtMetaDataInfo::MethodImplTokenPair::Compare);
2258
2259             // Now eliminate duplicates
2260             for (DWORD i = 0; i < bmtMethod->dwNumberMethodImpls - 1; i++)
2261             {
2262                 CONSISTENCY_CHECK((i + 1) < bmtMethod->dwNumberMethodImpls);
2263
2264                 bmtMetaDataInfo::MethodImplTokenPair *e1 = &bmtMetaData->rgMethodImplTokens[i];
2265                 bmtMetaDataInfo::MethodImplTokenPair *e2 = &bmtMetaData->rgMethodImplTokens[i + 1];
2266
2267                 // If the pair are equal, eliminate the first one, and reduce the total count by one.
2268                 if (bmtMetaDataInfo::MethodImplTokenPair::Equal(e1, e2))
2269                 {
2270                     DWORD dwCopyNum = bmtMethod->dwNumberMethodImpls - (i + 1);
2271                     memcpy(e1, e2, dwCopyNum * sizeof(bmtMetaDataInfo::MethodImplTokenPair));
2272                     bmtMethod->dwNumberMethodImpls--;
2273                     CONSISTENCY_CHECK(bmtMethod->dwNumberMethodImpls > 0);
2274                 }
2275             }
2276         }
2277     }
2278
2279     if (bmtMethod->dwNumberMethodImpls != 0)
2280     {
2281         //
2282         // Allocate the structures to keep track of the impl matches
2283         //
2284         bmtMetaData->pMethodDeclSubsts = new (GetStackingAllocator())
2285             Substitution[bmtMethod->dwNumberMethodImpls];
2286
2287         // These are used for verification
2288         maxRidMD = pMDInternalImport->GetCountWithTokenKind(mdtMethodDef);
2289         maxRidMR = pMDInternalImport->GetCountWithTokenKind(mdtMemberRef);
2290
2291         // Iterate through each MethodImpl declared on this class
2292         for (DWORD i = 0; i < bmtMethod->dwNumberMethodImpls; i++)
2293         {
2294             PCCOR_SIGNATURE pSigDecl = NULL;
2295             PCCOR_SIGNATURE pSigBody = NULL;
2296             ULONG           cbSigDecl;
2297             ULONG           cbSigBody;
2298             mdToken tkParent;
2299
2300             mdToken theBody, theDecl;
2301             Substitution theDeclSubst(GetModule(), SigPointer(), NULL); // this can get updated later below.
2302
2303             theBody = bmtMetaData->rgMethodImplTokens[i].methodBody;
2304             theDecl = bmtMetaData->rgMethodImplTokens[i].methodDecl;
2305
2306             // IMPLEMENTATION LIMITATION: currently, we require that the body of a methodImpl
2307             // belong to the current type. This is because we need to allocate a different
2308             // type of MethodDesc for bodies that are part of methodImpls.
2309             if (TypeFromToken(theBody) != mdtMethodDef)
2310             {
2311                 hr = FindMethodDeclarationForMethodImpl(
2312                     theBody, 
2313                     &theBody, 
2314                     TRUE);
2315                 if (FAILED(hr))
2316                 {
2317                     BuildMethodTableThrowException(hr, IDS_CLASSLOAD_MI_ILLEGAL_BODY, mdMethodDefNil);
2318                 }
2319
2320                 // Make sure to update the stored token with the resolved token.
2321                 bmtMetaData->rgMethodImplTokens[i].methodBody = theBody;
2322             }
2323
2324             if (TypeFromToken(theBody) != mdtMethodDef)
2325             {
2326                 BuildMethodTableThrowException(BFA_METHODDECL_NOT_A_METHODDEF);
2327             }
2328             CONSISTENCY_CHECK(theBody == bmtMetaData->rgMethodImplTokens[i].methodBody);
2329
2330             //
2331             // Now that the tokens of Decl and Body are obtained, do the MD validation
2332             //
2333
2334             rid = RidFromToken(theDecl);
2335
2336             // Perform initial rudimentary validation of the token. Full token verification
2337             // will be done in TestMethodImpl when placing the methodImpls.
2338             if (TypeFromToken(theDecl) == mdtMethodDef)
2339             {
2340                 // Decl must be valid token
2341                 if ((rid == 0) || (rid > maxRidMD))
2342                 {
2343                     BuildMethodTableThrowException(IDS_CLASSLOAD_MI_ILLEGAL_TOKEN_DECL);
2344                 }
2345                 // Get signature and length
2346                 if (FAILED(pMDInternalImport->GetSigOfMethodDef(theDecl, &cbSigDecl, &pSigDecl)))
2347                 {
2348                     BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
2349                 }
2350             }
2351
2352             // The token is not a MethodDef (likely a MemberRef)
2353             else
2354             {
2355                 // Decl must be valid token
2356                 if ((TypeFromToken(theDecl) != mdtMemberRef) || (rid == 0) || (rid > maxRidMR))
2357                 {
2358                     bmtError->resIDWhy = IDS_CLASSLOAD_MI_ILLEGAL_TOKEN_DECL;
2359                     BuildMethodTableThrowException(IDS_CLASSLOAD_MI_ILLEGAL_TOKEN_DECL);
2360                 }
2361
2362                 // Get signature and length
2363                 LPCSTR szDeclName;
2364                 if (FAILED(pMDInternalImport->GetNameAndSigOfMemberRef(theDecl, &pSigDecl, &cbSigDecl, &szDeclName)))
2365                 {
2366                     BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
2367                 }
2368
2369                 // Get parent
2370                 hr = pMDInternalImport->GetParentToken(theDecl,&tkParent);
2371                 if (FAILED(hr))
2372                     BuildMethodTableThrowException(hr, *bmtError);
2373
2374                 theDeclSubst = Substitution(tkParent, GetModule(), NULL);
2375             }
2376
2377             // Perform initial rudimentary validation of the token. Full token verification
2378             // will be done in TestMethodImpl when placing the methodImpls.
2379             {
2380                 // Body must be valid token
2381                 rid = RidFromToken(theBody);
2382                 if ((rid == 0)||(rid > maxRidMD))
2383                 {
2384                     BuildMethodTableThrowException(IDS_CLASSLOAD_MI_ILLEGAL_TOKEN_BODY);
2385                 }
2386                 // Body's parent must be this class
2387                 hr = pMDInternalImport->GetParentToken(theBody,&tkParent);
2388                 if (FAILED(hr))
2389                     BuildMethodTableThrowException(hr, *bmtError);
2390                 if(tkParent != GetCl())
2391                 {
2392                     BuildMethodTableThrowException(IDS_CLASSLOAD_MI_ILLEGAL_BODY);
2393                 }
2394             }
2395             // Decl's and Body's signatures must match
2396             if(pSigDecl && cbSigDecl)
2397             {
2398                 if (FAILED(pMDInternalImport->GetSigOfMethodDef(theBody, &cbSigBody, &pSigBody)) || 
2399                     (pSigBody == NULL) || 
2400                     (cbSigBody == 0))
2401                 {
2402                     BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MISSING_SIG_BODY);
2403                 }
2404                 // Can't use memcmp because there may be two AssemblyRefs
2405                 // in this scope, pointing to the same assembly, etc.).
2406                 if (!MetaSig::CompareMethodSigs(
2407                         pSigDecl,
2408                         cbSigDecl,
2409                         GetModule(),
2410                         &theDeclSubst,
2411                         pSigBody,
2412                         cbSigBody,
2413                         GetModule(),
2414                         NULL))
2415                 {
2416                     BuildMethodTableThrowException(IDS_CLASSLOAD_MI_BODY_DECL_MISMATCH);
2417                 }
2418             }
2419             else
2420             {
2421                 BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MISSING_SIG_DECL);
2422             }
2423
2424             bmtMetaData->pMethodDeclSubsts[i] = theDeclSubst;
2425         }
2426     }
2427 } // MethodTableBuilder::EnumerateMethodImpls
2428
2429 //*******************************************************************************
2430 //
2431 // Find a method declaration that must reside in the scope passed in. This method cannot be called if
2432 // the reference travels to another scope.
2433 //
2434 // Protect against finding a declaration that lives within
2435 // us (the type being created)
2436 //
2437 HRESULT MethodTableBuilder::FindMethodDeclarationForMethodImpl(
2438             mdToken  pToken,       // Token that is being located (MemberRef or MemberDef)
2439             mdToken* pDeclaration, // [OUT] Method definition for Member
2440             BOOL fSameClass)       // Does the declaration need to be in this class
2441 {
2442     STANDARD_VM_CONTRACT;
2443
2444     HRESULT hr = S_OK;
2445
2446     IMDInternalImport *pMDInternalImport = GetMDImport();
2447
2448     PCCOR_SIGNATURE pSig;  // Signature of Member
2449     DWORD           cSig;
2450     LPCUTF8         szMember = NULL;
2451
2452     // The token should be a member ref or def. If it is a ref then we need to travel
2453     // back to us hopefully.
2454     if(TypeFromToken(pToken) == mdtMemberRef)
2455     {
2456         // Get the parent
2457         mdToken typeref;
2458         if (FAILED(pMDInternalImport->GetParentOfMemberRef(pToken, &typeref)))
2459         {
2460             BAD_FORMAT_NOTHROW_ASSERT(!"Invalid MemberRef record");
2461             IfFailRet(COR_E_TYPELOAD);
2462         }
2463         GOTPARENT:
2464         if (TypeFromToken(typeref) == mdtMethodDef)
2465         {   // If parent is a method def then this is a varags method
2466             mdTypeDef typeDef;
2467             hr = pMDInternalImport->GetParentToken(typeref, &typeDef);
2468
2469             if (TypeFromToken(typeDef) != mdtTypeDef)
2470             {   // A mdtMethodDef must be parented by a mdtTypeDef
2471                 BAD_FORMAT_NOTHROW_ASSERT(!"MethodDef without TypeDef as Parent");
2472                 IfFailRet(COR_E_TYPELOAD);
2473             }
2474
2475             BAD_FORMAT_NOTHROW_ASSERT(typeDef == GetCl());
2476
2477             // This is the real method we are overriding
2478             *pDeclaration = typeref;
2479         }
2480         else if (TypeFromToken(typeref) == mdtTypeSpec)
2481         {   // Added so that method impls can refer to instantiated interfaces or classes
2482             if (FAILED(pMDInternalImport->GetSigFromToken(typeref, &cSig, &pSig)))
2483             {
2484                 BAD_FORMAT_NOTHROW_ASSERT(!"Invalid TypeSpec record");
2485                 IfFailRet(COR_E_TYPELOAD);
2486             }
2487             CorElementType elemType = (CorElementType) *pSig++;
2488
2489             if (elemType == ELEMENT_TYPE_GENERICINST)
2490             {   // If this is a generic inst, we expect that the next elem is ELEMENT_TYPE_CLASS,
2491                 // which is handled in the case below.
2492                 elemType = (CorElementType) *pSig++;
2493                 BAD_FORMAT_NOTHROW_ASSERT(elemType == ELEMENT_TYPE_CLASS);
2494             }
2495
2496             if (elemType == ELEMENT_TYPE_CLASS)
2497             {   // This covers E_T_GENERICINST and E_T_CLASS typespec formats. We don't expect
2498                 // any other kinds to come through here.
2499                 CorSigUncompressToken(pSig, &typeref);
2500             }
2501             else
2502             {   // This is an unrecognized signature format.
2503                 BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT,
2504                                                IDS_CLASSLOAD_MI_BAD_SIG,
2505                                                mdMethodDefNil);
2506             }
2507             goto GOTPARENT;
2508         }
2509         else
2510         {   // Verify that the ref points back to us
2511             mdToken tkDef = mdTokenNil;
2512
2513             if (TypeFromToken(typeref) == mdtTypeRef)
2514             {   // We only get here when we know the token does not reference a type in a different scope.
2515                 LPCUTF8 pszNameSpace;
2516                 LPCUTF8 pszClassName;
2517
2518                 if (FAILED(pMDInternalImport->GetNameOfTypeRef(typeref, &pszNameSpace, &pszClassName)))
2519                 {
2520                     IfFailRet(COR_E_TYPELOAD);
2521                 }
2522                 mdToken tkRes;
2523                 if (FAILED(pMDInternalImport->GetResolutionScopeOfTypeRef(typeref, &tkRes)))
2524                 {
2525                     IfFailRet(COR_E_TYPELOAD);
2526                 }
2527                 hr = pMDInternalImport->FindTypeDef(pszNameSpace,
2528                                                     pszClassName,
2529                                                     (TypeFromToken(tkRes) == mdtTypeRef) ? tkRes : mdTokenNil,
2530                                                     &tkDef);
2531                 if (FAILED(hr))
2532                 {
2533                     IfFailRet(COR_E_TYPELOAD);
2534                 }
2535             }
2536             else if (TypeFromToken(typeref) == mdtTypeDef)
2537             {   // We get a typedef when the parent of the token is a typespec to the type.
2538                 tkDef = typeref;
2539             }
2540             else
2541             {
2542                 CONSISTENCY_CHECK_MSGF(FALSE, ("Invalid methodimpl signature in class %s.", GetDebugClassName()));
2543                 BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT,
2544                                                IDS_CLASSLOAD_MI_BAD_SIG,
2545                                                mdMethodDefNil);
2546             }
2547
2548             if (fSameClass && tkDef != GetCl())
2549             {   // If we required that the typedef be the same type as the current class,
2550                 // and it doesn't match, we need to return a failure result.
2551                 IfFailRet(COR_E_TYPELOAD);
2552             }
2553
2554             IfFailRet(pMDInternalImport->GetNameAndSigOfMemberRef(pToken, &pSig, &cSig, &szMember));
2555             
2556             if (isCallConv(
2557                 MetaSig::GetCallingConvention(GetModule(), Signature(pSig, cSig)),
2558                 IMAGE_CEE_CS_CALLCONV_FIELD))
2559             {
2560                 return VLDTR_E_MR_BADCALLINGCONV;
2561             }
2562             
2563             hr = pMDInternalImport->FindMethodDef(
2564                 tkDef, szMember, pSig, cSig, pDeclaration);
2565
2566             IfFailRet(hr);
2567         }
2568     }
2569     else if (TypeFromToken(pToken) == mdtMethodDef)
2570     {
2571         mdTypeDef typeDef;
2572
2573         // Verify that we are the parent
2574         hr = pMDInternalImport->GetParentToken(pToken, &typeDef);
2575         IfFailRet(hr);
2576
2577         if(typeDef != GetCl())
2578         {
2579             IfFailRet(COR_E_TYPELOAD);
2580         }
2581
2582         *pDeclaration = pToken;
2583     }
2584     else
2585     {
2586         IfFailRet(COR_E_TYPELOAD);
2587     }
2588     return hr;
2589 }
2590
2591 #ifdef _PREFAST_ 
2592 #pragma warning(push)
2593 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
2594 #endif // _PREFAST_
2595 //---------------------------------------------------------------------------------------
2596 //
2597 // Used by BuildMethodTable
2598 // 
2599 // Enumerate this class's members
2600 // 
2601 VOID
2602 MethodTableBuilder::EnumerateClassMethods()
2603 {
2604     CONTRACTL
2605     {
2606         STANDARD_VM_CHECK;
2607         PRECONDITION(CheckPointer(bmtInternal));
2608         PRECONDITION(CheckPointer(bmtEnumFields));
2609         PRECONDITION(CheckPointer(bmtMFDescs));
2610         PRECONDITION(CheckPointer(bmtProp));
2611         PRECONDITION(CheckPointer(bmtMetaData));
2612         PRECONDITION(CheckPointer(bmtVT));
2613         PRECONDITION(CheckPointer(bmtError));
2614     }
2615     CONTRACTL_END;
2616
2617     HRESULT hr = S_OK;
2618     DWORD i;
2619     IMDInternalImport *pMDInternalImport = GetMDImport();
2620     mdToken tok;
2621     DWORD dwMemberAttrs;
2622     BOOL fIsClassEnum = IsEnum();
2623     BOOL fIsClassInterface = IsInterface();
2624     BOOL fIsClassValueType = IsValueClass();
2625     BOOL fIsClassComImport = IsComImport();
2626     BOOL fIsClassNotAbstract = (IsTdAbstract(GetAttrClass()) == 0);
2627     PCCOR_SIGNATURE pMemberSignature;
2628     ULONG           cMemberSignature;
2629
2630     //
2631     // Run through the method list and calculate the following:
2632     // # methods.
2633     // # "other" methods (i.e. static or private)
2634     // # non-other methods
2635     //
2636
2637     HENUMInternalHolder hEnumMethod(pMDInternalImport);
2638     hr = hEnumMethod.EnumInitNoThrow(mdtMethodDef, GetCl());
2639     if (FAILED(hr))
2640     {
2641         BuildMethodTableThrowException(hr, *bmtError);
2642     }
2643
2644     // Allocate an array to contain the method tokens as well as information about the methods.
2645     DWORD cMethAndGaps = hEnumMethod.EnumGetCount();
2646
2647     if ((DWORD)MAX_SLOT_INDEX <= cMethAndGaps)
2648         BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
2649
2650     bmtMethod->m_cMaxDeclaredMethods = (SLOT_INDEX)cMethAndGaps;
2651     bmtMethod->m_cDeclaredMethods = 0;
2652     bmtMethod->m_rgDeclaredMethods = new (GetStackingAllocator())
2653         bmtMDMethod *[bmtMethod->m_cMaxDeclaredMethods];
2654
2655     enum { SeenCtor = 1, SeenInvoke = 2, SeenBeginInvoke = 4, SeenEndInvoke = 8};
2656     unsigned delegateMethodsSeen = 0;
2657
2658     for (i = 0; i < cMethAndGaps; i++)
2659     {
2660         ULONG dwMethodRVA;
2661         DWORD dwImplFlags;
2662         METHOD_TYPE type;
2663         METHOD_IMPL_TYPE implType;
2664         LPSTR strMethodName;
2665
2666 #ifdef FEATURE_TYPEEQUIVALENCE
2667         // TypeEquivalent structs must not have methods
2668         if (bmtProp->fIsTypeEquivalent && fIsClassValueType)
2669         {
2670             BuildMethodTableThrowException(IDS_CLASSLOAD_EQUIVALENTSTRUCTMETHODS);
2671         }
2672 #endif
2673
2674         //
2675         // Go to the next method and retrieve its attributes.
2676         //
2677
2678         hEnumMethod.EnumNext(&tok);
2679         DWORD   rid = RidFromToken(tok);
2680         if ((rid == 0)||(rid > pMDInternalImport->GetCountWithTokenKind(mdtMethodDef)))
2681         {
2682             BuildMethodTableThrowException(BFA_METHOD_TOKEN_OUT_OF_RANGE);
2683         }
2684
2685         if (FAILED(pMDInternalImport->GetMethodDefProps(tok, &dwMemberAttrs)))
2686         {
2687             BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
2688         }
2689         if (IsMdRTSpecialName(dwMemberAttrs) || IsMdVirtual(dwMemberAttrs) || IsDelegate())
2690         {
2691             if (FAILED(pMDInternalImport->GetNameOfMethodDef(tok, (LPCSTR *)&strMethodName)))
2692             {
2693                 BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
2694             }
2695             if(IsStrLongerThan(strMethodName,MAX_CLASS_NAME))
2696             {
2697                 BuildMethodTableThrowException(BFA_METHOD_NAME_TOO_LONG);
2698             }
2699         }
2700         else
2701         {
2702             strMethodName = NULL;
2703         }
2704
2705         DWORD numGenericMethodArgs = 0;
2706
2707         {
2708             HENUMInternalHolder hEnumTyPars(pMDInternalImport);
2709             hr = hEnumTyPars.EnumInitNoThrow(mdtGenericParam, tok);
2710             if (FAILED(hr))
2711             {
2712                 BuildMethodTableThrowException(hr, *bmtError);
2713             }
2714
2715             numGenericMethodArgs = hEnumTyPars.EnumGetCount();
2716
2717             // We do not want to support context-bound objects with generic methods.
2718
2719             if (numGenericMethodArgs != 0)
2720             {
2721                 HENUMInternalHolder hEnumGenericPars(pMDInternalImport);
2722
2723                 hEnumGenericPars.EnumInit(mdtGenericParam, tok);
2724
2725                 for (unsigned methIdx = 0; methIdx < numGenericMethodArgs; methIdx++)
2726                 {
2727                     mdGenericParam tkTyPar;
2728                     pMDInternalImport->EnumNext(&hEnumGenericPars, &tkTyPar);
2729                     DWORD flags;
2730                     if (FAILED(pMDInternalImport->GetGenericParamProps(tkTyPar, NULL, &flags, NULL, NULL, NULL)))
2731                     {
2732                         BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
2733                     }
2734                     
2735                     if (0 != (flags & ~(gpVarianceMask | gpSpecialConstraintMask)))
2736                     {
2737                         BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
2738                     }
2739                     switch (flags & gpVarianceMask)
2740                     {
2741                         case gpNonVariant:
2742                             break;
2743
2744                         case gpCovariant: // intentional fallthru
2745                         case gpContravariant:
2746                             BuildMethodTableThrowException(VLDTR_E_GP_ILLEGAL_VARIANT_MVAR);
2747                             break;
2748
2749                         default:
2750                             BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
2751                     }
2752
2753                 }
2754             }
2755         }
2756
2757         //
2758         // We need to check if there are any gaps in the vtable. These are
2759         // represented by methods with the mdSpecial flag and a name of the form
2760         // _VTblGap_nnn (to represent nnn empty slots) or _VTblGap (to represent a
2761         // single empty slot).
2762         //
2763
2764         if (IsMdRTSpecialName(dwMemberAttrs))
2765         {
2766             PREFIX_ASSUME(strMethodName != NULL); // if we've gotten here we've called GetNameOfMethodDef
2767
2768             // The slot is special, but it might not be a vtable spacer. To
2769             // determine that we must look at the name.
2770             if (strncmp(strMethodName, "_VtblGap", 8) == 0)
2771             {
2772                                 //
2773                 // This slot doesn't really exist, don't add it to the method
2774                 // table. Instead it represents one or more empty slots, encoded
2775                 // in the method name. Locate the beginning of the count in the
2776                 // name. There are these points to consider:
2777                 //   There may be no count present at all (in which case the
2778                 //   count is taken as one).
2779                 //   There may be an additional count just after Gap but before
2780                 //   the '_'. We ignore this.
2781                                 //
2782
2783                 LPCSTR pos = strMethodName + 8;
2784
2785                 // Skip optional number.
2786                 while (IS_DIGIT(*pos))
2787                     pos++;
2788
2789                 WORD n = 0;
2790
2791                 // Check for presence of count.
2792                 if (*pos == '\0')
2793                     n = 1;
2794                 else
2795                 {
2796                     if (*pos != '_')
2797                     {
2798                         BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT,
2799                                                        IDS_CLASSLOAD_BADSPECIALMETHOD,
2800                                                        tok);
2801                     }
2802
2803                     // Skip '_'.
2804                     pos++;
2805
2806                     // Read count.
2807                     bool fReadAtLeastOneDigit = false;
2808                     while (IS_DIGIT(*pos))
2809                     {
2810                         _ASSERTE(n < 6552);
2811                         n *= 10;
2812                         n += DIGIT_TO_INT(*pos);
2813                         pos++;
2814                         fReadAtLeastOneDigit = true;
2815                     }
2816
2817                     // Check for end of name.
2818                     if (*pos != '\0' || !fReadAtLeastOneDigit)
2819                     {
2820                         BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT,
2821                                                        IDS_CLASSLOAD_BADSPECIALMETHOD,
2822                                                        tok);
2823                     }
2824                 }
2825
2826 #ifdef FEATURE_COMINTEROP 
2827                 // Record vtable gap in mapping list. The map is an optional field, so ensure we've allocated
2828                 // these fields first.
2829                 EnsureOptionalFieldsAreAllocated(GetHalfBakedClass(), m_pAllocMemTracker, GetLoaderAllocator()->GetLowFrequencyHeap());
2830                 if (GetHalfBakedClass()->GetSparseCOMInteropVTableMap() == NULL)
2831                     GetHalfBakedClass()->SetSparseCOMInteropVTableMap(new SparseVTableMap());
2832
2833                 GetHalfBakedClass()->GetSparseCOMInteropVTableMap()->RecordGap((WORD)NumDeclaredMethods(), n);
2834
2835                 bmtProp->fSparse = true;
2836 #endif // FEATURE_COMINTEROP
2837                 continue;
2838             }
2839
2840         }
2841
2842
2843         //
2844         // This is a real method so add it to the enumeration of methods. We now need to retrieve
2845         // information on the method and store it for later use.
2846         //
2847         if (FAILED(pMDInternalImport->GetMethodImplProps(tok, &dwMethodRVA, &dwImplFlags)))
2848         {
2849             BuildMethodTableThrowException(
2850                 COR_E_BADIMAGEFORMAT, 
2851                 IDS_CLASSLOAD_BADSPECIALMETHOD, 
2852                 tok);
2853         }
2854         //
2855         // But first - minimal flags validity checks
2856         //
2857         // No methods in Enums!
2858         if (fIsClassEnum)
2859         {
2860             BuildMethodTableThrowException(BFA_METHOD_IN_A_ENUM);
2861         }
2862         // RVA : 0
2863         if (dwMethodRVA != 0)
2864         {
2865 #ifdef FEATURE_COMINTEROP 
2866             if(fIsClassComImport)
2867             {
2868                 BuildMethodTableThrowException(BFA_METHOD_WITH_NONZERO_RVA);
2869             }
2870 #endif // FEATURE_COMINTEROP
2871             if(IsMdAbstract(dwMemberAttrs))
2872             {
2873                 BuildMethodTableThrowException(BFA_ABSTRACT_METHOD_WITH_RVA);
2874             }
2875             if(IsMiRuntime(dwImplFlags))
2876             {
2877                 BuildMethodTableThrowException(BFA_RUNTIME_METHOD_WITH_RVA);
2878             }
2879             if(IsMiInternalCall(dwImplFlags))
2880             {
2881                 BuildMethodTableThrowException(BFA_INTERNAL_METHOD_WITH_RVA);
2882             }
2883         }
2884
2885         // Abstract / not abstract
2886         if(IsMdAbstract(dwMemberAttrs))
2887         {
2888             if(fIsClassNotAbstract)
2889             {
2890                 BuildMethodTableThrowException(BFA_AB_METHOD_IN_AB_CLASS);
2891             }
2892             if(!IsMdVirtual(dwMemberAttrs))
2893             {
2894                 BuildMethodTableThrowException(BFA_NONVIRT_AB_METHOD);
2895             }
2896         }
2897         else if(fIsClassInterface)
2898         {
2899             if (IsMdRTSpecialName(dwMemberAttrs))
2900             {
2901                 CONSISTENCY_CHECK(CheckPointer(strMethodName));
2902                 if (strcmp(strMethodName, COR_CCTOR_METHOD_NAME))
2903                 {
2904                     BuildMethodTableThrowException(BFA_NONAB_NONCCTOR_METHOD_ON_INT);
2905                 }
2906             }
2907         }
2908
2909         // Virtual / not virtual
2910         if(IsMdVirtual(dwMemberAttrs))
2911         {
2912             if(IsMdPinvokeImpl(dwMemberAttrs))
2913             {
2914                 BuildMethodTableThrowException(BFA_VIRTUAL_PINVOKE_METHOD);
2915             }
2916             if(IsMdStatic(dwMemberAttrs))
2917             {
2918                 BuildMethodTableThrowException(BFA_VIRTUAL_STATIC_METHOD);
2919             }
2920             if(strMethodName && (0==strcmp(strMethodName, COR_CTOR_METHOD_NAME)))
2921             {
2922                 BuildMethodTableThrowException(BFA_VIRTUAL_INSTANCE_CTOR);
2923             }
2924         }
2925
2926 #ifndef FEATURE_DEFAULT_INTERFACES
2927         // Some interface checks.
2928         if (fIsClassInterface)
2929         {
2930             if (IsMdVirtual(dwMemberAttrs))
2931             {
2932                 if (!IsMdAbstract(dwMemberAttrs))
2933                 {
2934                     BuildMethodTableThrowException(BFA_VIRTUAL_NONAB_INT_METHOD);
2935                 }
2936             }
2937             else
2938             {
2939                 // Instance field/method
2940                 if (!IsMdStatic(dwMemberAttrs))
2941                 {
2942                     BuildMethodTableThrowException(BFA_NONVIRT_INST_INT_METHOD);
2943                 }
2944             }
2945         }
2946 #endif
2947
2948         // No synchronized methods in ValueTypes
2949         if(fIsClassValueType && IsMiSynchronized(dwImplFlags))
2950         {
2951             BuildMethodTableThrowException(BFA_SYNC_METHOD_IN_VT);
2952         }
2953
2954         // Global methods:
2955         if(IsGlobalClass())
2956         {
2957             if(!IsMdStatic(dwMemberAttrs))
2958             {
2959                 BuildMethodTableThrowException(BFA_NONSTATIC_GLOBAL_METHOD);
2960             }
2961             if (strMethodName)  //<TODO>@todo: investigate mc++ generating null name</TODO>
2962             {
2963                 if(0==strcmp(strMethodName, COR_CTOR_METHOD_NAME))
2964                 {
2965                     BuildMethodTableThrowException(BFA_GLOBAL_INST_CTOR);
2966                 }
2967             }
2968         }
2969         //@GENERICS:
2970         // Generic methods or methods in generic classes
2971         // may not be part of a COM Import class (except for WinRT), PInvoke, internal call outside mscorlib.
2972         if ((bmtGenerics->GetNumGenericArgs() != 0 || numGenericMethodArgs != 0) &&
2973             (
2974 #ifdef FEATURE_COMINTEROP 
2975              fIsClassComImport ||
2976              bmtProp->fComEventItfType ||
2977 #endif // FEATURE_COMINTEROP
2978              IsMdPinvokeImpl(dwMemberAttrs) ||
2979              (IsMiInternalCall(dwImplFlags) && !GetModule()->IsSystem())))
2980         {
2981 #ifdef FEATURE_COMINTEROP
2982             if (!GetHalfBakedClass()->IsProjectedFromWinRT())
2983 #endif // FEATURE_COMINTEROP
2984             {
2985                 BuildMethodTableThrowException(BFA_BAD_PLACE_FOR_GENERIC_METHOD);
2986             }
2987         }
2988
2989         // Generic methods may not be marked "runtime".  However note that
2990         // methods in generic delegate classes are, hence we don't apply this to
2991         // methods in generic classes in general.
2992         if (numGenericMethodArgs != 0 && IsMiRuntime(dwImplFlags))
2993         {
2994             BuildMethodTableThrowException(BFA_GENERIC_METHOD_RUNTIME_IMPL);
2995         }
2996
2997
2998         // Signature validation
2999         if (FAILED(pMDInternalImport->GetSigOfMethodDef(tok, &cMemberSignature, &pMemberSignature)))
3000         {
3001             BuildMethodTableThrowException(hr, BFA_BAD_SIGNATURE, mdMethodDefNil);
3002         }
3003         hr = validateTokenSig(tok,pMemberSignature,cMemberSignature,dwMemberAttrs,pMDInternalImport);
3004         if (FAILED(hr))
3005         {
3006             BuildMethodTableThrowException(hr, BFA_BAD_SIGNATURE, mdMethodDefNil);
3007         }
3008
3009         // Check the appearance of covariant and contravariant in the method signature
3010         // Note that variance is only supported for interfaces
3011         if (bmtGenerics->pVarianceInfo != NULL)
3012         {
3013             SigPointer sp(pMemberSignature, cMemberSignature);
3014             ULONG callConv;
3015             IfFailThrow(sp.GetCallingConvInfo(&callConv));
3016
3017             if (callConv & IMAGE_CEE_CS_CALLCONV_GENERIC)
3018                 IfFailThrow(sp.GetData(NULL));
3019
3020             DWORD numArgs;
3021             IfFailThrow(sp.GetData(&numArgs));
3022
3023             // Return type behaves covariantly
3024             if (!EEClass::CheckVarianceInSig(
3025                     bmtGenerics->GetNumGenericArgs(), 
3026                     bmtGenerics->pVarianceInfo, 
3027                     GetModule(), 
3028                     sp, 
3029                     gpCovariant))
3030             {
3031                 BuildMethodTableThrowException(IDS_CLASSLOAD_VARIANCE_IN_METHOD_RESULT, tok);
3032             }
3033             IfFailThrow(sp.SkipExactlyOne());
3034             for (DWORD j = 0; j < numArgs; j++)
3035             {
3036                 // Argument types behave contravariantly
3037                 if (!EEClass::CheckVarianceInSig(bmtGenerics->GetNumGenericArgs(),
3038                                                  bmtGenerics->pVarianceInfo,
3039                                                  GetModule(),
3040                                                  sp,
3041                                                  gpContravariant))
3042                 {
3043                     BuildMethodTableThrowException(IDS_CLASSLOAD_VARIANCE_IN_METHOD_ARG, tok);
3044                 }
3045                 IfFailThrow(sp.SkipExactlyOne());
3046             }
3047         }
3048
3049         //
3050         // Determine the method's type
3051         //
3052
3053         if (IsReallyMdPinvokeImpl(dwMemberAttrs) || IsMiInternalCall(dwImplFlags))
3054         {
3055             hr = NDirect::HasNAT_LAttribute(pMDInternalImport, tok, dwMemberAttrs);
3056
3057             // There was a problem querying for the attribute
3058             if (FAILED(hr))
3059             {
3060                 BuildMethodTableThrowException(hr, IDS_CLASSLOAD_BADPINVOKE, tok);
3061             }
3062
3063             // The attribute is not present
3064             if (hr == S_FALSE)
3065             {
3066                 if (fIsClassComImport
3067 #ifdef FEATURE_COMINTEROP 
3068                     || GetHalfBakedClass()->IsProjectedFromWinRT()
3069                     || bmtProp->fComEventItfType
3070 #endif //FEATURE_COMINTEROP
3071                     )
3072                 {
3073 #ifdef FEATURE_COMINTEROP
3074                     // ComImport classes have methods which are just used
3075                     // for implementing all interfaces the class supports
3076                     type = METHOD_TYPE_COMINTEROP;
3077
3078                     // constructor is special
3079                     if (IsMdRTSpecialName(dwMemberAttrs))
3080                     {
3081                         // Note: Method name (.ctor) will be checked in code:ValidateMethods
3082                         
3083                         // WinRT ctors are interop calls via stubs
3084                         if (!GetHalfBakedClass()->IsProjectedFromWinRT())
3085                         {
3086                             // Ctor on a non-WinRT class
3087                             type = METHOD_TYPE_FCALL;
3088                         }
3089                     }
3090 #else
3091                     //If we don't support com interop, refuse to load interop methods.  Otherwise we fail to
3092                     //jit calls to them since the constuctor has no intrinsic ID.
3093                     BuildMethodTableThrowException(hr, IDS_CLASSLOAD_GENERAL, tok);
3094 #endif // FEATURE_COMINTEROP
3095                 }
3096                 else if (dwMethodRVA == 0)
3097                 {
3098                     type = METHOD_TYPE_FCALL;
3099                 }
3100                 else
3101                 {
3102                     type = METHOD_TYPE_NDIRECT;
3103                 }
3104             }
3105             // The NAT_L attribute is present, marking this method as NDirect
3106             else
3107             {
3108                 CONSISTENCY_CHECK(hr == S_OK);
3109                 type = METHOD_TYPE_NDIRECT;
3110             }
3111         }
3112         else if (IsMiRuntime(dwImplFlags))
3113         {
3114                 // currently the only runtime implemented functions are delegate instance methods
3115             if (!IsDelegate() || IsMdStatic(dwMemberAttrs) || IsMdAbstract(dwMemberAttrs))
3116             {
3117                 BuildMethodTableThrowException(BFA_BAD_RUNTIME_IMPL);
3118             }
3119
3120             unsigned newDelegateMethodSeen = 0;
3121
3122             if (IsMdRTSpecialName(dwMemberAttrs))   // .ctor
3123             {
3124                 if (strcmp(strMethodName, COR_CTOR_METHOD_NAME) != 0 || IsMdVirtual(dwMemberAttrs))
3125                 {
3126                     BuildMethodTableThrowException(BFA_BAD_FLAGS_ON_DELEGATE);
3127                 }
3128                 newDelegateMethodSeen = SeenCtor;
3129                 type = METHOD_TYPE_FCALL;
3130             }
3131             else
3132             {
3133                 if (strcmp(strMethodName, "Invoke") == 0)
3134                     newDelegateMethodSeen = SeenInvoke;
3135                 else if (strcmp(strMethodName, "BeginInvoke") == 0)
3136                     newDelegateMethodSeen = SeenBeginInvoke;
3137                 else if (strcmp(strMethodName, "EndInvoke") == 0)
3138                     newDelegateMethodSeen = SeenEndInvoke;
3139                 else
3140                 {
3141                     BuildMethodTableThrowException(BFA_UNKNOWN_DELEGATE_METHOD);
3142                 }
3143                 type = METHOD_TYPE_EEIMPL;
3144             }
3145
3146             // If we get here we have either set newDelegateMethodSeen or we have thrown a BMT exception
3147             _ASSERTE(newDelegateMethodSeen != 0);
3148
3149             if ((delegateMethodsSeen & newDelegateMethodSeen) != 0)
3150             {
3151                 BuildMethodTableThrowException(BFA_DUPLICATE_DELEGATE_METHOD);
3152             }
3153
3154             delegateMethodsSeen |= newDelegateMethodSeen;
3155         }
3156         else if (numGenericMethodArgs != 0)
3157         {
3158             //We use an instantiated method desc to represent a generic method
3159             type = METHOD_TYPE_INSTANTIATED;
3160         }
3161         else if (fIsClassInterface)
3162         {
3163 #ifdef FEATURE_COMINTEROP 
3164             if (IsMdStatic(dwMemberAttrs))
3165             {
3166                 // Static methods in interfaces need nothing special.
3167                 type = METHOD_TYPE_NORMAL;
3168             }
3169             else if (bmtGenerics->GetNumGenericArgs() != 0 &&
3170                 (bmtGenerics->fSharedByGenericInstantiations || (!bmtProp->fIsRedirectedInterface && !GetHalfBakedClass()->IsProjectedFromWinRT())))
3171             {
3172                 // Methods in instantiated interfaces need nothing special - they are not visible from COM etc.
3173                 // mcComInterop is only useful for unshared instantiated WinRT interfaces. If the interface is
3174                 // shared by multiple instantiations, the MD would be useless for interop anyway.
3175                 type = METHOD_TYPE_NORMAL;
3176             }
3177             else if (bmtProp->fIsMngStandardItf)
3178             {
3179                 // If the interface is a standard managed interface then allocate space for an FCall method desc.
3180                 type = METHOD_TYPE_FCALL;
3181             }
3182             else if (IsMdAbstract(dwMemberAttrs))
3183             {
3184                 // If COM interop is supported then all other interface MDs may be
3185                 // accessed via COM interop. mcComInterop MDs have an additional
3186                 // pointer-sized field pointing to COM interop data which are
3187                 // allocated lazily when/if the MD actually gets used for interop.
3188                 type = METHOD_TYPE_COMINTEROP;
3189             }
3190             else
3191 #endif // !FEATURE_COMINTEROP
3192             {
3193                 // This codepath is used by remoting
3194                 type = METHOD_TYPE_NORMAL;
3195             }
3196         }
3197         else
3198         {
3199             type = METHOD_TYPE_NORMAL;
3200         }
3201
3202         // PInvoke methods are not permitted on collectible types
3203         if ((type == METHOD_TYPE_NDIRECT) && GetAssembly()->IsCollectible())
3204         {
3205             BuildMethodTableThrowException(IDS_CLASSLOAD_COLLECTIBLEPINVOKE);
3206         }
3207
3208         // Generic methods should always be METHOD_TYPE_INSTANTIATED
3209         if ((numGenericMethodArgs != 0) && (type != METHOD_TYPE_INSTANTIATED))
3210         {
3211             BuildMethodTableThrowException(BFA_GENERIC_METHODS_INST);
3212         }
3213
3214         // count how many overrides this method does All methods bodies are defined
3215         // on this type so we can just compare the tok with the body token found
3216         // from the overrides.
3217         implType = METHOD_IMPL_NOT;
3218         for (DWORD impls = 0; impls < bmtMethod->dwNumberMethodImpls; impls++)
3219         {
3220             if (bmtMetaData->rgMethodImplTokens[impls].methodBody == tok)
3221             {
3222                 implType = METHOD_IMPL;
3223                 break;
3224             }
3225         }
3226
3227         // For delegates we don't allow any non-runtime implemented bodies
3228         // for any of the four special methods
3229         if (IsDelegate() && !IsMiRuntime(dwImplFlags))
3230         {
3231             if ((strcmp(strMethodName, COR_CTOR_METHOD_NAME) == 0) ||
3232                 (strcmp(strMethodName, "Invoke")             == 0) ||
3233                 (strcmp(strMethodName, "BeginInvoke")        == 0) ||
3234                 (strcmp(strMethodName, "EndInvoke")          == 0)   )
3235             {
3236                 BuildMethodTableThrowException(BFA_ILLEGAL_DELEGATE_METHOD);
3237             }
3238         }
3239
3240         //
3241         // Create a new bmtMDMethod representing this method and add it to the
3242         // declared method list.
3243         //
3244
3245         bmtMDMethod * pNewMethod = new (GetStackingAllocator()) bmtMDMethod(
3246             bmtInternal->pType,
3247             tok,
3248             dwMemberAttrs,
3249             dwImplFlags,
3250             dwMethodRVA,
3251             type,
3252             implType);
3253
3254         bmtMethod->AddDeclaredMethod(pNewMethod);
3255
3256         //
3257         // Update the count of the various types of methods.
3258         //
3259
3260         bmtVT->dwMaxVtableSize++;
3261
3262         // Increment the number of non-abstract declared methods
3263         if (!IsMdAbstract(dwMemberAttrs))
3264         {
3265             bmtMethod->dwNumDeclaredNonAbstractMethods++;
3266         }
3267     }
3268
3269     // Check to see that we have all of the required delegate methods (ECMA 13.6 Delegates)
3270     if (IsDelegate())
3271     {
3272         // Do we have all four special delegate methods
3273         // or just the two special delegate methods
3274         if ((delegateMethodsSeen != (SeenCtor | SeenInvoke | SeenBeginInvoke | SeenEndInvoke)) &&
3275             (delegateMethodsSeen != (SeenCtor | SeenInvoke)) )
3276         {
3277             BuildMethodTableThrowException(BFA_MISSING_DELEGATE_METHOD);
3278         }
3279     }
3280
3281     if (i != cMethAndGaps)
3282     {
3283         BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_METHOD_COUNT, mdTokenNil);
3284     }
3285
3286 #ifdef FEATURE_COMINTEROP 
3287     //
3288     // If the interface is sparse, we need to finalize the mapping list by
3289     // telling it how many real methods we found.
3290     //
3291
3292     if (bmtProp->fSparse)
3293     {
3294         GetHalfBakedClass()->GetSparseCOMInteropVTableMap()->FinalizeMapping(NumDeclaredMethods());
3295     }
3296 #endif // FEATURE_COMINTEROP
3297 } // MethodTableBuilder::EnumerateClassMethods
3298 #ifdef _PREFAST_ 
3299 #pragma warning(pop)
3300 #endif
3301
3302 //*******************************************************************************
3303 //
3304 // Run through the field list and calculate the following:
3305 // # static fields
3306 // # static fields that contain object refs.
3307 // # instance fields
3308 //
3309 VOID
3310 MethodTableBuilder::EnumerateClassFields()
3311 {
3312     STANDARD_VM_CONTRACT;
3313
3314     HRESULT hr = S_OK;
3315     DWORD i;
3316     IMDInternalImport *pMDInternalImport = GetMDImport();
3317     mdToken tok;
3318     DWORD dwMemberAttrs;
3319
3320     bmtEnumFields->dwNumStaticFields        = 0;
3321     bmtEnumFields->dwNumStaticObjRefFields  = 0;
3322     bmtEnumFields->dwNumStaticBoxedFields   = 0;
3323
3324     bmtEnumFields->dwNumThreadStaticFields  = 0;
3325     bmtEnumFields->dwNumThreadStaticObjRefFields  = 0;
3326     bmtEnumFields->dwNumThreadStaticBoxedFields   = 0;
3327
3328     bmtEnumFields->dwNumInstanceFields      = 0;
3329
3330     HENUMInternalHolder hEnumField(pMDInternalImport);
3331     hr = hEnumField.EnumInitNoThrow(mdtFieldDef, GetCl());
3332     if (FAILED(hr))
3333     {
3334         BuildMethodTableThrowException(hr, *bmtError);
3335     }
3336
3337     bmtMetaData->cFields = hEnumField.EnumGetCount();
3338
3339     // Retrieve the fields and store them in a temp array.
3340     bmtMetaData->pFields = new (GetStackingAllocator()) mdToken[bmtMetaData->cFields];
3341     bmtMetaData->pFieldAttrs = new (GetStackingAllocator()) DWORD[bmtMetaData->cFields];
3342
3343     DWORD   dwFieldLiteralInitOnly = fdLiteral | fdInitOnly;
3344     DWORD   dwMaxFieldDefRid = pMDInternalImport->GetCountWithTokenKind(mdtFieldDef);
3345
3346     for (i = 0; hEnumField.EnumNext(&tok); i++)
3347     {
3348         //
3349         // Retrieve the attributes of the field.
3350         //
3351         DWORD rid = RidFromToken(tok);
3352         if ((rid == 0)||(rid > dwMaxFieldDefRid))
3353         {
3354             BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, BFA_BAD_FIELD_TOKEN, mdTokenNil);
3355         }
3356         
3357         if (FAILED(pMDInternalImport->GetFieldDefProps(tok, &dwMemberAttrs)))
3358         {
3359             BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, BFA_BAD_FIELD_TOKEN, tok);
3360         }
3361         
3362         //
3363         // Store the field and its attributes in the bmtMetaData structure for later use.
3364         //
3365
3366         bmtMetaData->pFields[i] = tok;
3367         bmtMetaData->pFieldAttrs[i] = dwMemberAttrs;
3368
3369         if((dwMemberAttrs & fdFieldAccessMask)==fdFieldAccessMask)
3370         {
3371             BuildMethodTableThrowException(BFA_INVALID_FIELD_ACC_FLAGS);
3372         }
3373         if((dwMemberAttrs & dwFieldLiteralInitOnly)==dwFieldLiteralInitOnly)
3374         {
3375             BuildMethodTableThrowException(BFA_FIELD_LITERAL_AND_INIT);
3376         }
3377
3378         // can only have static global fields
3379         if(IsGlobalClass())
3380         {
3381             if(!IsFdStatic(dwMemberAttrs))
3382             {
3383                 BuildMethodTableThrowException(BFA_NONSTATIC_GLOBAL_FIELD);
3384             }
3385         }
3386
3387         //
3388         // Update the count of the various types of fields.
3389         //
3390
3391         if (IsFdStatic(dwMemberAttrs))
3392         {
3393             if (!IsFdLiteral(dwMemberAttrs))
3394             {
3395 #ifdef FEATURE_TYPEEQUIVALENCE
3396                 if (bmtProp->fIsTypeEquivalent)
3397                 {
3398                     BuildMethodTableThrowException(IDS_CLASSLOAD_EQUIVALENTSTRUCTFIELDS);
3399                 }
3400 #endif
3401
3402                 bmtEnumFields->dwNumStaticFields++;
3403
3404                 // If this static field is thread static, then we need
3405                 // to increment bmtEnumFields->dwNumThreadStaticFields
3406                 hr = pMDInternalImport->GetCustomAttributeByName(tok,
3407                                                                  g_ThreadStaticAttributeClassName,
3408                                                                  NULL, NULL);
3409                 IfFailThrow(hr);
3410                 if (hr == S_OK)
3411                 {
3412                     // It's a thread static, so increment the count
3413                     bmtEnumFields->dwNumThreadStaticFields++;
3414                 }
3415             }
3416         }
3417         else
3418         {
3419 #ifdef FEATURE_TYPEEQUIVALENCE
3420             if (!IsFdPublic(dwMemberAttrs) && bmtProp->fIsTypeEquivalent)
3421             {
3422                 BuildMethodTableThrowException(IDS_CLASSLOAD_EQUIVALENTSTRUCTFIELDS);
3423             }
3424 #endif
3425
3426             if (!IsFdLiteral(dwMemberAttrs))
3427             {
3428                 bmtEnumFields->dwNumInstanceFields++;
3429             }
3430             if(IsInterface())
3431             {
3432                 BuildMethodTableThrowException(BFA_INSTANCE_FIELD_IN_INT);
3433             }
3434         }
3435     }
3436
3437     if (i != bmtMetaData->cFields)
3438     {
3439         BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD_COUNT, mdTokenNil);
3440     }
3441
3442     if(IsEnum() && (bmtEnumFields->dwNumInstanceFields==0))
3443     {
3444         BuildMethodTableThrowException(BFA_INSTANCE_FIELD_IN_ENUM);
3445     }
3446
3447     bmtEnumFields->dwNumDeclaredFields = bmtEnumFields->dwNumStaticFields + bmtEnumFields->dwNumInstanceFields;
3448 }
3449
3450 //*******************************************************************************
3451 //
3452 // Used by BuildMethodTable
3453 //
3454 // Determines the maximum size of the vtable and allocates the temporary storage arrays
3455 // Also copies the parent's vtable into the working vtable.
3456 //
3457 VOID    MethodTableBuilder::AllocateWorkingSlotTables()
3458 {
3459     CONTRACTL
3460     {
3461         STANDARD_VM_CHECK;
3462         PRECONDITION(CheckPointer(this));
3463         PRECONDITION(CheckPointer(bmtAllocator));
3464         PRECONDITION(CheckPointer(bmtMFDescs));
3465         PRECONDITION(CheckPointer(bmtMetaData));
3466         PRECONDITION(CheckPointer(bmtVT));
3467         PRECONDITION(CheckPointer(bmtEnumFields));
3468         PRECONDITION(CheckPointer(bmtInterface));
3469         PRECONDITION(CheckPointer(bmtFP));
3470         PRECONDITION(CheckPointer(bmtParent));
3471
3472     }
3473     CONTRACTL_END;
3474
3475     // Allocate a FieldDesc* for each field
3476     bmtMFDescs->ppFieldDescList = new (GetStackingAllocator()) FieldDesc*[bmtMetaData->cFields];
3477     ZeroMemory(bmtMFDescs->ppFieldDescList, bmtMetaData->cFields * sizeof(FieldDesc *));
3478
3479     // Create a temporary function table (we don't know how large the vtable will be until the very end,
3480     // since we don't yet know how many declared methods are overrides vs. newslots).
3481
3482     if (IsValueClass())
3483     {   // ValueClass virtuals are converted into non-virtual methods and the virtual slots
3484         // become unboxing stubs that forward to these new non-virtual methods. This has the
3485         // side effect of doubling the number of slots introduced by newslot virtuals.
3486         bmtVT->dwMaxVtableSize += NumDeclaredMethods();
3487     }
3488
3489     _ASSERTE(!HasParent() || (bmtInterface->dwInterfaceMapSize - GetParentMethodTable()->GetNumInterfaces()) >= 0);
3490
3491     if (HasParent())
3492     {   // Add parent vtable size. <TODO> This should actually be the parent's virtual method count. </TODO>
3493         bmtVT->dwMaxVtableSize += bmtParent->pSlotTable->GetSlotCount();
3494     }
3495
3496     S_SLOT_INDEX cMaxSlots = AsClrSafeInt(bmtVT->dwMaxVtableSize) + AsClrSafeInt(NumDeclaredMethods());
3497
3498     if (cMaxSlots.IsOverflow() || MAX_SLOT_INDEX < cMaxSlots.Value())
3499         cMaxSlots = S_SLOT_INDEX(MAX_SLOT_INDEX);
3500
3501     // Allocate the temporary vtable
3502     bmtVT->pSlotTable = new (GetStackingAllocator())
3503         bmtMethodSlotTable(cMaxSlots.Value(), GetStackingAllocator());
3504
3505     if (HasParent())
3506     {
3507 #if 0 
3508         // @<TODO>todo: Figure out the right way to override Equals for value
3509         // types only.
3510         //
3511         // This is broken because
3512         // (a) g_pObjectClass->FindMethod("Equals", &gsig_IM_Obj_RetBool); will return
3513         //      the EqualsValue method
3514         // (b) When mscorlib has been preloaded (and thus the munge already done
3515         //      ahead of time), we cannot easily find both methods
3516         //      to compute EqualsAddr & EqualsSlot
3517         //
3518         // For now, the Equals method has a runtime check to see if it's
3519         // comparing value types.
3520         //</TODO>
3521
3522         // If it is a value type, over ride a few of the base class methods.
3523         if (IsValueClass())
3524         {
3525             static WORD EqualsSlot;
3526
3527             // If we haven't been through here yet, get some stuff from the Object class definition.
3528             if (EqualsSlot == NULL)
3529             {
3530                 // Get the slot of the Equals method.
3531                 MethodDesc *pEqualsMD = g_pObjectClass->FindMethod("Equals", &gsig_IM_Obj_RetBool);
3532                 THROW_BAD_FORMAT_MAYBE(pEqualsMD != NULL, 0, this);
3533                 EqualsSlot = pEqualsMD->GetSlot();
3534
3535                 // Get the address of the EqualsValue method.
3536                 MethodDesc *pEqualsValueMD = g_pObjectClass->FindMethod("EqualsValue", &gsig_IM_Obj_RetBool);
3537                 THROW_BAD_FORMAT_MAYBE(pEqualsValueMD != NULL, 0, this);
3538
3539                 // Patch the EqualsValue method desc in a dangerous way to
3540                 // look like the Equals method desc.
3541                 pEqualsValueMD->SetSlot(EqualsSlot);
3542                 pEqualsValueMD->SetMemberDef(pEqualsMD->GetMemberDef());
3543             }
3544
3545             // Override the valuetype "Equals" with "EqualsValue".
3546             bmtVT->SetMethodDescForSlot(EqualsSlot, EqualsSlot);
3547         }
3548 #endif // 0
3549     }
3550
3551     S_UINT32 cEntries = S_UINT32(2) * S_UINT32(NumDeclaredMethods());
3552     if (cEntries.IsOverflow())
3553     {
3554         ThrowHR(COR_E_OVERFLOW);
3555     }
3556 }
3557
3558 //*******************************************************************************
3559 //
3560 // Used by BuildMethodTable
3561 //
3562 // Allocate a MethodDesc* for each method (needed later when doing interfaces), and a FieldDesc* for each field
3563 //
3564 VOID MethodTableBuilder::AllocateFieldDescs()
3565 {
3566     CONTRACTL
3567     {
3568         STANDARD_VM_CHECK;
3569         PRECONDITION(CheckPointer(this));
3570         PRECONDITION(CheckPointer(bmtAllocator));
3571         PRECONDITION(CheckPointer(bmtMFDescs));
3572         PRECONDITION(CheckPointer(bmtMetaData));
3573         PRECONDITION(CheckPointer(bmtVT));
3574         PRECONDITION(CheckPointer(bmtEnumFields));
3575         PRECONDITION(CheckPointer(bmtFP));
3576         PRECONDITION(CheckPointer(bmtParent));
3577
3578     }
3579     CONTRACTL_END;
3580
3581     // We'll be counting the # fields of each size as we go along
3582     for (DWORD i = 0; i <= MAX_LOG2_PRIMITIVE_FIELD_SIZE; i++)
3583     {
3584         bmtFP->NumRegularStaticFieldsOfSize[i]    = 0;
3585         bmtFP->NumThreadStaticFieldsOfSize[i]    = 0;
3586         bmtFP->NumInstanceFieldsOfSize[i]  = 0;
3587     }
3588
3589     //
3590     // Allocate blocks of MethodDescs and FieldDescs for all declared methods and fields
3591     //
3592     // In order to avoid allocating a field pointing back to the method
3593     // table in every single method desc, we allocate memory in the
3594     // following manner:
3595     //   o  Field descs get a single contiguous block.
3596     //   o  Method descs of different sizes (normal vs NDirect) are
3597     //      allocated in different MethodDescChunks.
3598     //   o  Each method desc chunk starts with a header, and has
3599     //      at most MAX_ method descs (if there are more
3600     //      method descs of a given size, multiple chunks are allocated).
3601     // This way method descs can use an 8-bit offset field to locate the
3602     // pointer to their method table.
3603     //
3604
3605     /////////////////////////////////////////////////////////////////
3606     // Allocate fields
3607     if (NumDeclaredFields() > 0)
3608     {
3609         GetHalfBakedClass()->SetFieldDescList((FieldDesc *)
3610             AllocateFromHighFrequencyHeap(S_SIZE_T(NumDeclaredFields()) * S_SIZE_T(sizeof(FieldDesc))));
3611         INDEBUG(GetClassLoader()->m_dwDebugFieldDescs += NumDeclaredFields();)
3612         INDEBUG(GetClassLoader()->m_dwFieldDescData += (NumDeclaredFields() * sizeof(FieldDesc));)
3613     }
3614 }
3615
3616 #ifdef FEATURE_DOUBLE_ALIGNMENT_HINT
3617 //*******************************************************************************
3618 //
3619 // Heuristic to determine if we should have instances of this class 8 byte aligned
3620 //
3621 BOOL MethodTableBuilder::ShouldAlign8(DWORD dwR8Fields, DWORD dwTotalFields)
3622 {
3623     LIMITED_METHOD_CONTRACT;
3624
3625     return dwR8Fields*2>dwTotalFields && dwR8Fields>=2;
3626 }
3627 #endif
3628
3629 //*******************************************************************************
3630 BOOL MethodTableBuilder::IsSelfReferencingStaticValueTypeField(mdToken     dwByValueClassToken,
3631                                                                bmtInternalInfo* bmtInternal,
3632                                                                const bmtGenericsInfo *bmtGenerics,
3633                                                                PCCOR_SIGNATURE pMemberSignature,
3634                                                                DWORD       cMemberSignature)
3635 {
3636     STANDARD_VM_CONTRACT;
3637
3638     if (dwByValueClassToken != this->GetCl())
3639     {
3640         return FALSE;
3641     }
3642
3643     if (!bmtGenerics->HasInstantiation())
3644     {
3645         return TRUE;
3646     }
3647
3648     // The value class is generic.  Check that the signature of the field
3649     // is _exactly_ equivalent to VC<!0, !1, !2, ...>.  Do this by consing up a fake
3650     // signature.
3651     DWORD nGenericArgs = bmtGenerics->GetNumGenericArgs();
3652     CONSISTENCY_CHECK(nGenericArgs != 0);
3653
3654     SigBuilder sigBuilder;
3655
3656     sigBuilder.AppendElementType(ELEMENT_TYPE_GENERICINST);
3657     sigBuilder.AppendElementType(ELEMENT_TYPE_VALUETYPE);
3658     sigBuilder.AppendToken(dwByValueClassToken);
3659     sigBuilder.AppendData(nGenericArgs);
3660     for (unsigned int typearg = 0; typearg < nGenericArgs; typearg++)
3661     {
3662         sigBuilder.AppendElementType(ELEMENT_TYPE_VAR);
3663         sigBuilder.AppendData(typearg);
3664     }
3665
3666     DWORD cFakeSig;
3667     PCCOR_SIGNATURE pFakeSig = (PCCOR_SIGNATURE)sigBuilder.GetSignature(&cFakeSig);
3668
3669     PCCOR_SIGNATURE pFieldSig = pMemberSignature + 1; // skip the CALLCONV_FIELD
3670
3671     return MetaSig::CompareElementType(pFakeSig,             pFieldSig,
3672                                        pFakeSig + cFakeSig,  pMemberSignature + cMemberSignature,
3673                                        GetModule(), GetModule(),
3674                                        NULL,                 NULL);
3675
3676 }
3677
3678 //*******************************************************************************
3679 //
3680 // Used pByValueClass cache to mark self-references
3681 //
3682 static BOOL IsSelfRef(MethodTable * pMT)
3683 {
3684     return pMT == (MethodTable *)-1;
3685 }
3686
3687 //*******************************************************************************
3688 //
3689 // Used by BuildMethodTable
3690 //
3691 // Go thru all fields and initialize their FieldDescs.
3692 //
3693 #ifdef _PREFAST_ 
3694 #pragma warning(push)
3695 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
3696 #endif // _PREFAST_
3697
3698 VOID    MethodTableBuilder::InitializeFieldDescs(FieldDesc *pFieldDescList,
3699                                                  const LayoutRawFieldInfo* pLayoutRawFieldInfos,
3700                                                  bmtInternalInfo* bmtInternal,
3701                                                  const bmtGenericsInfo* bmtGenerics,
3702                                                  bmtMetaDataInfo* bmtMetaData,
3703                                                  bmtEnumFieldInfo* bmtEnumFields,
3704                                                  bmtErrorInfo* bmtError,
3705                                                  MethodTable *** pByValueClassCache,
3706                                                  bmtMethAndFieldDescs* bmtMFDescs,
3707                                                  bmtFieldPlacement* bmtFP,
3708                                                  bmtContextStaticInfo* pbmtCSInfo,
3709                                                  unsigned* totalDeclaredSize)
3710 {
3711     CONTRACTL
3712     {
3713         STANDARD_VM_CHECK;
3714         PRECONDITION(CheckPointer(this));
3715         PRECONDITION(CheckPointer(bmtInternal));
3716         PRECONDITION(CheckPointer(bmtGenerics));
3717         PRECONDITION(CheckPointer(bmtMetaData));
3718         PRECONDITION(CheckPointer(bmtEnumFields));
3719         PRECONDITION(CheckPointer(bmtError));
3720         PRECONDITION(CheckPointer(pByValueClassCache));
3721         PRECONDITION(CheckPointer(bmtMFDescs));
3722         PRECONDITION(CheckPointer(bmtFP));
3723         PRECONDITION(CheckPointer(totalDeclaredSize));
3724     }
3725     CONTRACTL_END;
3726
3727     DWORD i;
3728     IMDInternalImport * pInternalImport = GetMDImport(); // to avoid multiple dereferencings
3729
3730     FieldMarshaler * pNextFieldMarshaler = NULL;
3731     if (HasLayout())
3732     {
3733         pNextFieldMarshaler = (FieldMarshaler*)(GetLayoutInfo()->GetFieldMarshalers());
3734     }
3735
3736
3737 //========================================================================
3738 // BEGIN:
3739 //    Go thru all fields and initialize their FieldDescs.
3740 //========================================================================
3741
3742     DWORD   dwCurrentDeclaredField = 0;
3743     DWORD   dwCurrentStaticField   = 0;
3744     DWORD   dwCurrentThreadStaticField = 0;
3745
3746
3747     DWORD   dwR8Fields              = 0;        // Number of R8's the class has
3748
3749 #ifdef FEATURE_64BIT_ALIGNMENT
3750     // Track whether any field in this type requires 8-byte alignment
3751     BOOL    fFieldRequiresAlign8 = HasParent() ? GetParentMethodTable()->RequiresAlign8() : FALSE;
3752 #endif
3753
3754     for (i = 0; i < bmtMetaData->cFields; i++)
3755     {
3756         PCCOR_SIGNATURE pMemberSignature;
3757         DWORD       cMemberSignature;
3758         DWORD       dwMemberAttrs;
3759
3760         dwMemberAttrs = bmtMetaData->pFieldAttrs[i];
3761
3762         BOOL fIsStatic = IsFdStatic(dwMemberAttrs);
3763
3764         // We don't store static final primitive fields in the class layout
3765         if (IsFdLiteral(dwMemberAttrs))
3766             continue;
3767
3768         if (!IsFdPublic(dwMemberAttrs))
3769             SetHasNonPublicFields();
3770
3771         if (IsFdNotSerialized(dwMemberAttrs))
3772             SetCannotBeBlittedByObjectCloner();
3773
3774         IfFailThrow(pInternalImport->GetSigOfFieldDef(bmtMetaData->pFields[i], &cMemberSignature, &pMemberSignature));
3775         // Signature validation
3776         IfFailThrow(validateTokenSig(bmtMetaData->pFields[i],pMemberSignature,cMemberSignature,dwMemberAttrs,pInternalImport));
3777
3778         FieldDesc * pFD;
3779         DWORD       dwLog2FieldSize = 0;
3780         BOOL        bCurrentFieldIsGCPointer = FALSE;
3781         mdToken     dwByValueClassToken = 0;
3782         MethodTable * pByValueClass = NULL;
3783         BOOL        fIsByValue = FALSE;
3784         BOOL        fIsThreadStatic = FALSE;
3785         static const BOOL fIsContextStatic = FALSE;
3786         BOOL        fHasRVA = FALSE;
3787
3788         MetaSig fsig(pMemberSignature,
3789                      cMemberSignature,
3790                      GetModule(),
3791                      &bmtGenerics->typeContext,
3792                      MetaSig::sigField);
3793         CorElementType ElementType = fsig.NextArg();
3794
3795
3796         // Get type
3797         if (!isCallConv(fsig.GetCallingConvention(), IMAGE_CEE_CS_CALLCONV_FIELD))
3798         {
3799             IfFailThrow(COR_E_TYPELOAD);
3800         }
3801
3802         // Determine if a static field is special i.e. RVA based, local to
3803         // a thread or a context
3804         if (fIsStatic)
3805         {
3806             if (IsFdHasFieldRVA(dwMemberAttrs))
3807             {
3808                 fHasRVA = TRUE;
3809             }
3810
3811             HRESULT hr;
3812  
3813             hr = pInternalImport->GetCustomAttributeByName(bmtMetaData->pFields[i],
3814                                                            g_ThreadStaticAttributeClassName,
3815                                                            NULL, NULL);
3816             IfFailThrow(hr);
3817             if (hr == S_OK)
3818             {
3819                 fIsThreadStatic = TRUE;
3820             }
3821
3822
3823             if (ElementType == ELEMENT_TYPE_VALUETYPE)
3824             {
3825                 hr = pInternalImport->GetCustomAttributeByName(bmtMetaData->pFields[i],
3826                                                                g_CompilerServicesFixedAddressValueTypeAttribute,
3827                                                                NULL, NULL);
3828                 IfFailThrow(hr);
3829                 if (hr == S_OK)
3830                 {
3831                     bmtFP->fHasFixedAddressValueTypes = true;
3832                 }
3833             }
3834
3835
3836             // Do some sanity checks that we are not mixing context and thread
3837             // relative statics.
3838             if (fHasRVA && (fIsThreadStatic || fIsContextStatic))
3839             {
3840                 IfFailThrow(COR_E_TYPELOAD);
3841             }
3842
3843             if ((fIsThreadStatic || fIsContextStatic || bmtFP->fHasFixedAddressValueTypes) && GetAssembly()->IsCollectible())
3844             {
3845                 if (bmtFP->fHasFixedAddressValueTypes)
3846                 {
3847                     BuildMethodTableThrowException(IDS_CLASSLOAD_COLLECTIBLEFIXEDVTATTR);
3848                 }
3849                 BuildMethodTableThrowException(IDS_CLASSLOAD_COLLECTIBLESPECIALSTATICS);
3850             }
3851         }
3852
3853
3854     GOT_ELEMENT_TYPE:
3855         // Type to store in FieldDesc - we don't want to have extra case statements for
3856         // ELEMENT_TYPE_STRING, SDARRAY etc., so we convert all object types to CLASS.
3857         // Also, BOOLEAN, CHAR are converted to U1, I2.
3858         CorElementType FieldDescElementType = ElementType;
3859
3860         switch (ElementType)
3861         {
3862         case ELEMENT_TYPE_I1:
3863         case ELEMENT_TYPE_U1:
3864             {
3865                 dwLog2FieldSize = 0;
3866                 break;
3867             }
3868
3869         case ELEMENT_TYPE_I2:
3870         case ELEMENT_TYPE_U2:
3871             {
3872                 dwLog2FieldSize = 1;
3873                 break;
3874             }
3875
3876         case ELEMENT_TYPE_I4:
3877         case ELEMENT_TYPE_U4:
3878         IN_WIN32(case ELEMENT_TYPE_I:)
3879         IN_WIN32(case ELEMENT_TYPE_U:)
3880         case ELEMENT_TYPE_R4:
3881             {
3882                 dwLog2FieldSize = 2;
3883                 break;
3884             }
3885
3886         case ELEMENT_TYPE_BOOLEAN:
3887             {
3888                 //                FieldDescElementType = ELEMENT_TYPE_U1;
3889                 dwLog2FieldSize = 0;
3890                 break;
3891             }
3892
3893         case ELEMENT_TYPE_CHAR:
3894             {
3895                 //                FieldDescElementType = ELEMENT_TYPE_U2;
3896                 dwLog2FieldSize = 1;
3897                 break;
3898             }
3899
3900         case ELEMENT_TYPE_R8:
3901             {
3902                 dwR8Fields++;
3903
3904                 // Deliberate fall through...
3905             }
3906        
3907         case ELEMENT_TYPE_I8:
3908         case ELEMENT_TYPE_U8:
3909         IN_WIN64(case ELEMENT_TYPE_I:)
3910         IN_WIN64(case ELEMENT_TYPE_U:)
3911             {
3912 #ifdef FEATURE_64BIT_ALIGNMENT
3913                 // Record that this field requires alignment for Int64/UInt64.
3914                 if(!fIsStatic)
3915                     fFieldRequiresAlign8 = true;
3916 #endif                
3917                 dwLog2FieldSize = 3;
3918                 break;
3919             }
3920
3921         case ELEMENT_TYPE_FNPTR:
3922         case ELEMENT_TYPE_PTR:   // ptrs are unmanaged scalars, for layout
3923             {
3924                 dwLog2FieldSize = LOG2_PTRSIZE;
3925                 break;
3926             }
3927
3928         // Class type variable (method type variables aren't allowed in fields)
3929         // These only occur in open types used for verification/reflection.
3930         case ELEMENT_TYPE_VAR:
3931         case ELEMENT_TYPE_MVAR:
3932            // deliberate drop through - do fake field layout
3933         case ELEMENT_TYPE_STRING:
3934         case ELEMENT_TYPE_SZARRAY:      // single dim, zero
3935         case ELEMENT_TYPE_ARRAY:        // all other arrays
3936         case ELEMENT_TYPE_CLASS: // objectrefs
3937         case ELEMENT_TYPE_OBJECT:
3938             {
3939                 dwLog2FieldSize = LOG2_PTRSIZE;
3940                 bCurrentFieldIsGCPointer = TRUE;
3941                 FieldDescElementType = ELEMENT_TYPE_CLASS;
3942
3943                 if (!fIsStatic)
3944                 {
3945                     SetHasFieldsWhichMustBeInited();
3946                     if (ElementType != ELEMENT_TYPE_STRING)
3947                         SetCannotBeBlittedByObjectCloner();
3948                 }
3949                 else
3950                 {   // EnumerateFieldDescs already counted the total number of static vs. instance
3951                     // fields, now we're further subdividing the static field count by GC and non-GC.
3952                     bmtEnumFields->dwNumStaticObjRefFields++;
3953                     if (fIsThreadStatic)
3954                         bmtEnumFields->dwNumThreadStaticObjRefFields++;
3955                 }
3956                 break;
3957             }
3958
3959         case ELEMENT_TYPE_VALUETYPE: // a byvalue class field
3960             {
3961                 Module * pTokenModule;
3962                 dwByValueClassToken = fsig.GetArgProps().PeekValueTypeTokenClosed(GetModule(), &bmtGenerics->typeContext, &pTokenModule);
3963                 fIsByValue = TRUE;
3964
3965                 // By-value class
3966                 BAD_FORMAT_NOTHROW_ASSERT(dwByValueClassToken != 0);
3967                 
3968                 if (this->IsValueClass() && (pTokenModule == GetModule()))
3969                 {
3970                     if (TypeFromToken(dwByValueClassToken) == mdtTypeRef)
3971                     {
3972                         // It's a typeref - check if it's a class that has a static field of itself
3973                         LPCUTF8 pszNameSpace;
3974                         LPCUTF8 pszClassName;
3975                         if (FAILED(pInternalImport->GetNameOfTypeRef(dwByValueClassToken, &pszNameSpace, &pszClassName)))
3976                         {
3977                             BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
3978                         }
3979                         
3980                         if (IsStrLongerThan((char *)pszClassName, MAX_CLASS_NAME)
3981                             || IsStrLongerThan((char *)pszNameSpace, MAX_CLASS_NAME)
3982                             || (strlen(pszClassName) + strlen(pszNameSpace) + 1 >= MAX_CLASS_NAME))
3983                         {
3984                             BuildMethodTableThrowException(BFA_TYPEREG_NAME_TOO_LONG, mdMethodDefNil);
3985                         }
3986
3987                         mdToken tkRes;
3988                         if (FAILED(pInternalImport->GetResolutionScopeOfTypeRef(dwByValueClassToken, &tkRes)))
3989                         {
3990                             BuildMethodTableThrowException(BFA_BAD_TYPEREF_TOKEN, dwByValueClassToken);
3991                         }
3992                         
3993                         if (TypeFromToken(tkRes) == mdtTypeRef)
3994                         {
3995                             if (!pInternalImport->IsValidToken(tkRes))
3996                             {
3997                                 BuildMethodTableThrowException(BFA_BAD_TYPEREF_TOKEN, mdMethodDefNil);
3998                             }
3999                         }
4000                         else
4001                         {
4002                             tkRes = mdTokenNil;
4003                         }
4004                         
4005                         if (FAILED(pInternalImport->FindTypeDef(pszNameSpace,
4006                                                                 pszClassName,
4007                                                                 tkRes,
4008                                                                 &dwByValueClassToken)))
4009                         {
4010                             dwByValueClassToken = mdTokenNil;
4011                         }
4012                     } // If field is static typeref
4013
4014                     BOOL selfref = IsSelfReferencingStaticValueTypeField(dwByValueClassToken,
4015                                                                     bmtInternal,
4016                                                                     bmtGenerics,
4017                                                                     pMemberSignature,
4018                                                                     cMemberSignature);
4019
4020                     if (selfref)
4021                     {   // immediately self-referential fields must be static.
4022                         if (!fIsStatic)
4023                         {
4024                             BuildMethodTableThrowException(IDS_CLASSLOAD_VALUEINSTANCEFIELD, mdMethodDefNil);
4025                         }
4026
4027                         if (!IsValueClass())
4028                         {
4029                             BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_MUST_BE_BYVAL, mdTokenNil);
4030                         }
4031
4032                         pByValueClass = (MethodTable *)-1;
4033                     }
4034                 } // If 'this' is a value class
4035
4036                 // It's not self-referential so try to load it
4037                 if (pByValueClass == NULL)
4038                 {
4039                     // Loading a non-self-ref valuetype field.
4040                     OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOAD_APPROXPARENTS);
4041                     // We load the approximate type of the field to avoid recursion problems.
4042                     // MethodTable::DoFullyLoad() will later load it fully
4043                     pByValueClass = fsig.GetArgProps().GetTypeHandleThrowing(GetModule(),
4044                                                                             &bmtGenerics->typeContext,
4045                                                                              ClassLoader::LoadTypes,
4046                                                                              CLASS_LOAD_APPROXPARENTS,
4047                                                                              TRUE
4048                                                                              ).GetMethodTable();
4049                 }
4050                 
4051                 // #FieldDescTypeMorph  IF it is an enum, strip it down to its underlying type
4052                 if (IsSelfRef(pByValueClass) ? IsEnum() : pByValueClass->IsEnum())
4053                 {
4054                     if (IsSelfRef(pByValueClass))
4055                     {   // It is self-referencing enum (ValueType) static field - it is forbidden in the ECMA spec, but supported by CLR since v1
4056                         // Note: literal static fields are skipped early in this loop
4057                         if (bmtMFDescs->ppFieldDescList[0] == NULL)
4058                         {   // The field is defined before (the only) instance field
4059                             // AppCompat with 3.5 SP1 and 4.0 RTM behavior
4060                             BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil);
4061                         }
4062                         // 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 
4063                         // later in this method)
4064                         // Therefore we do not have to run code:VerifySelfReferencingStaticValueTypeFields_WithRVA or code:#SelfReferencingStaticValueTypeField_Checks
4065                     }
4066                     BAD_FORMAT_NOTHROW_ASSERT((IsSelfRef(pByValueClass) ? 
4067                             bmtEnumFields->dwNumInstanceFields : pByValueClass->GetNumInstanceFields())
4068                                 == 1); // enums must have exactly one field
4069                     FieldDesc * enumField = IsSelfRef(pByValueClass) ?
4070                             bmtMFDescs->ppFieldDescList[0] : pByValueClass->GetApproxFieldDescListRaw();
4071                     BAD_FORMAT_NOTHROW_ASSERT(!enumField->IsStatic());   // no real static fields on enums
4072                     ElementType = enumField->GetFieldType();
4073                     BAD_FORMAT_NOTHROW_ASSERT(ElementType != ELEMENT_TYPE_VALUETYPE);
4074                     fIsByValue = FALSE; // we're going to treat it as the underlying type now
4075                     goto GOT_ELEMENT_TYPE;
4076                 }
4077                 
4078                 // Check ByRefLike fields
4079                 if (!IsSelfRef(pByValueClass) && pByValueClass->IsByRefLike())
4080                 {
4081                     if (fIsStatic)
4082                     {
4083                         // By-ref-like types cannot be used for static fields
4084                         BuildMethodTableThrowException(IDS_CLASSLOAD_BYREFLIKE_STATICFIELD);
4085                     }
4086                     if (!IsValueClass())
4087                     {
4088                         // Non-value-classes cannot contain by-ref-like instance fields
4089                         BuildMethodTableThrowException(IDS_CLASSLOAD_BYREFLIKE_NOTVALUECLASSFIELD);
4090                     }
4091                     if (!bmtFP->fIsByRefLikeType)
4092                     {
4093                         BuildMethodTableThrowException(IDS_CLASSLOAD_NOTBYREFLIKE);
4094                     }
4095                 }
4096
4097                 if (!IsSelfRef(pByValueClass) && pByValueClass->GetClass()->HasNonPublicFields())
4098                 {   // If a class has a field of type ValueType with non-public fields in it,
4099                     // the class must "inherit" this characteristic
4100                     SetHasNonPublicFields();
4101                 }
4102
4103                 if (!fHasRVA)
4104                 {
4105                     if (!fIsStatic)
4106                     {
4107                         // Inherit instance attributes
4108                         EEClass * pFieldClass = pByValueClass->GetClass();
4109
4110 #ifdef FEATURE_64BIT_ALIGNMENT
4111                         // If a value type requires 8-byte alignment this requirement must be inherited by any
4112                         // class/struct that embeds it as a field.
4113                         if (pFieldClass->IsAlign8Candidate())
4114                             fFieldRequiresAlign8 = true;
4115 #endif
4116                         if (pFieldClass->HasNonPublicFields())
4117                             SetHasNonPublicFields();
4118                         if (pFieldClass->HasFieldsWhichMustBeInited())
4119                             SetHasFieldsWhichMustBeInited();
4120
4121 #ifdef FEATURE_READYTORUN
4122                         if (!(pByValueClass->IsTruePrimitive() || pByValueClass->IsEnum()))
4123                         {
4124                             CheckLayoutDependsOnOtherModules(pByValueClass);
4125                         }
4126 #endif
4127                     }
4128                     else
4129                     {   // Increment the number of static fields that contain object references.
4130                         bmtEnumFields->dwNumStaticBoxedFields++;
4131                         if (fIsThreadStatic)
4132                             bmtEnumFields->dwNumThreadStaticBoxedFields++;
4133                     }
4134                 }
4135                 
4136                 if (*pByValueClassCache == NULL)
4137                 {
4138                     DWORD dwNumFields = bmtEnumFields->dwNumInstanceFields + bmtEnumFields->dwNumStaticFields;
4139                     
4140                     *pByValueClassCache = new (GetStackingAllocator()) MethodTable * [dwNumFields];
4141                     memset (*pByValueClassCache, 0, dwNumFields * sizeof(MethodTable **));
4142                 }
4143                 
4144                 // Thread static fields come after instance fields and regular static fields in this list
4145                 if (fIsThreadStatic)
4146                 {
4147                     (*pByValueClassCache)[bmtEnumFields->dwNumInstanceFields + bmtEnumFields->dwNumStaticFields - bmtEnumFields->dwNumThreadStaticFields + dwCurrentThreadStaticField] = pByValueClass;
4148                     // make sure to record the correct size for static field
4149                     // layout
4150                     dwLog2FieldSize = LOG2_PTRSIZE; // handle
4151                 }
4152                 // Regular static fields come after instance fields in this list
4153                 else if (fIsStatic)
4154                 {
4155                     (*pByValueClassCache)[bmtEnumFields->dwNumInstanceFields + dwCurrentStaticField] = pByValueClass;
4156                     // make sure to record the correct size for static field
4157                     // layout
4158                     dwLog2FieldSize = LOG2_PTRSIZE; // handle
4159                 }
4160                 else
4161                 {
4162                     (*pByValueClassCache)[dwCurrentDeclaredField] = pByValueClass;
4163                     dwLog2FieldSize = 0; // unused
4164                 }
4165                 
4166                 break;
4167             }
4168         default:
4169             {
4170                 BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil);
4171             }
4172         }
4173
4174         if (!fIsStatic)
4175         {
4176             pFD = &pFieldDescList[dwCurrentDeclaredField];
4177             *totalDeclaredSize += (1 << dwLog2FieldSize);
4178         }
4179         else /* (dwMemberAttrs & mdStatic) */
4180         {
4181             if (fIsThreadStatic)
4182             {
4183                 pFD = &pFieldDescList[bmtEnumFields->dwNumInstanceFields + bmtEnumFields->dwNumStaticFields - bmtEnumFields->dwNumThreadStaticFields + dwCurrentThreadStaticField];
4184             }
4185             else
4186             {
4187                 pFD = &pFieldDescList[bmtEnumFields->dwNumInstanceFields + dwCurrentStaticField];
4188             }
4189         }
4190
4191         bmtMFDescs->ppFieldDescList[i] = pFD;
4192
4193         const LayoutRawFieldInfo *pLayoutFieldInfo = NULL;
4194
4195         if (HasLayout())
4196         {
4197             const LayoutRawFieldInfo *pwalk = pLayoutRawFieldInfos;
4198             while (pwalk->m_MD != mdFieldDefNil)
4199             {
4200                 if (pwalk->m_MD == bmtMetaData->pFields[i])
4201                 {
4202                     pLayoutFieldInfo = pwalk;
4203
4204                     const FieldMarshaler *pSrcFieldMarshaler = (const FieldMarshaler *) &pwalk->m_FieldMarshaler;
4205
4206                     pSrcFieldMarshaler->CopyTo(pNextFieldMarshaler, MAXFIELDMARSHALERSIZE);
4207
4208                     pNextFieldMarshaler->SetFieldDesc(pFD);
4209                     pNextFieldMarshaler->SetExternalOffset(pwalk->m_offset);
4210
4211                     ((BYTE*&)pNextFieldMarshaler) += MAXFIELDMARSHALERSIZE;
4212                     break;
4213                 }
4214                 pwalk++;
4215             }
4216         }
4217
4218         LPCSTR pszFieldName = NULL;
4219 #ifdef _DEBUG 
4220         if (FAILED(pInternalImport->GetNameOfFieldDef(bmtMetaData->pFields[i], &pszFieldName)))
4221         {
4222             pszFieldName = "Invalid FieldDef record";
4223         }
4224 #endif
4225         // #InitCall Initialize contents of the field descriptor called from 
4226         pFD->Init(
4227                   bmtMetaData->pFields[i],
4228                   FieldDescElementType,
4229                   dwMemberAttrs,
4230                   fIsStatic,
4231                   fHasRVA,
4232                   fIsThreadStatic,
4233                   fIsContextStatic,
4234                   pszFieldName
4235                   );
4236
4237         // We're using FieldDesc::m_pMTOfEnclosingClass to temporarily store the field's size.
4238         // 
4239         if (fIsByValue)
4240         {
4241             if (!fIsStatic &&
4242                 (IsBlittable() || HasExplicitFieldOffsetLayout()))
4243             {
4244                 (DWORD_PTR &)pFD->m_pMTOfEnclosingClass =
4245                     (*pByValueClassCache)[dwCurrentDeclaredField]->GetNumInstanceFieldBytes();
4246
4247                 if (pLayoutFieldInfo)
4248                     IfFailThrow(pFD->SetOffset(pLayoutFieldInfo->m_offset));
4249                 else
4250                     pFD->SetOffset(FIELD_OFFSET_VALUE_CLASS);
4251             }
4252             else if (!fIsStatic && IsManagedSequential())
4253             {
4254                 (DWORD_PTR &)pFD->m_pMTOfEnclosingClass =
4255                     (*pByValueClassCache)[dwCurrentDeclaredField]->GetNumInstanceFieldBytes();
4256
4257                 IfFailThrow(pFD->SetOffset(pLayoutFieldInfo->m_managedOffset));
4258             }
4259             else
4260             {
4261                 // static value class fields hold a handle, which is ptr sized
4262                 // (instance field layout ignores this value)
4263                 (DWORD_PTR&)(pFD->m_pMTOfEnclosingClass) = LOG2_PTRSIZE;
4264                 pFD->SetOffset(FIELD_OFFSET_VALUE_CLASS);
4265             }
4266         }
4267         else
4268         {
4269             (DWORD_PTR &)(pFD->m_pMTOfEnclosingClass) = (size_t)dwLog2FieldSize;
4270
4271             // -1 (FIELD_OFFSET_UNPLACED) means that this is a non-GC field that has not yet been placed
4272             // -2 (FIELD_OFFSET_UNPLACED_GC_PTR) means that this is a GC pointer field that has not yet been placed
4273
4274             // If there is any kind of explicit layout information for this field, use it. If not, then
4275             // mark it as either GC or non-GC and as unplaced; it will get placed later on in an optimized way.
4276
4277             if ((IsBlittable() || HasExplicitFieldOffsetLayout()) && !fIsStatic)
4278                 IfFailThrow(pFD->SetOffset(pLayoutFieldInfo->m_offset));
4279             else if (IsManagedSequential() && !fIsStatic)
4280                 IfFailThrow(pFD->SetOffset(pLayoutFieldInfo->m_managedOffset));
4281             else if (bCurrentFieldIsGCPointer)
4282                 pFD->SetOffset(FIELD_OFFSET_UNPLACED_GC_PTR);
4283             else
4284                 pFD->SetOffset(FIELD_OFFSET_UNPLACED);
4285         }
4286
4287         if (!fIsStatic)
4288         {
4289             if (!fIsByValue)
4290             {
4291                 if (++bmtFP->NumInstanceFieldsOfSize[dwLog2FieldSize] == 1)
4292                     bmtFP->FirstInstanceFieldOfSize[dwLog2FieldSize] = dwCurrentDeclaredField;
4293             }
4294
4295             dwCurrentDeclaredField++;
4296
4297             if (bCurrentFieldIsGCPointer)
4298             {
4299                 bmtFP->NumInstanceGCPointerFields++;
4300             }
4301         }
4302         else /* static fields */
4303         {
4304             // Static fields are stored in the vtable after the vtable and interface slots.  We don't
4305             // know how large the vtable will be, so we will have to fixup the slot number by
4306             // <vtable + interface size> later.
4307
4308             if (fIsThreadStatic)
4309             {
4310                 dwCurrentThreadStaticField++;
4311             }
4312             else
4313             {
4314                 dwCurrentStaticField++;
4315             }
4316
4317             if (fHasRVA)
4318             {
4319                 if (FieldDescElementType == ELEMENT_TYPE_CLASS)
4320                 {   // RVA fields are not allowed to have GC pointers.
4321                     BAD_FORMAT_NOTHROW_ASSERT(!"ObjectRef in an RVA field");
4322                     BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil);
4323                 }
4324                 if (FieldDescElementType == ELEMENT_TYPE_VALUETYPE)
4325                 {
4326                     if (IsSelfRef(pByValueClass))
4327                     {   // We will verify self-referencing statics after the loop through all fields - see code:#SelfReferencingStaticValueTypeField_Checks
4328                         bmtFP->fHasSelfReferencingStaticValueTypeField_WithRVA = TRUE;
4329                     }
4330                     else
4331                     {
4332                         if (pByValueClass->GetClass()->HasFieldsWhichMustBeInited())
4333                         {   // RVA fields are not allowed to have GC pointers.
4334                             BAD_FORMAT_NOTHROW_ASSERT(!"ObjectRef in an RVA field");
4335                             BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil);
4336                         }
4337                     }
4338                 }
4339                 
4340                 // Set the field offset
4341                 DWORD rva;
4342                 IfFailThrow(pInternalImport->GetFieldRVA(pFD->GetMemberDef(), &rva));
4343                 
4344                 // Ensure that the IL image is loaded. Note that this assembly may
4345                 // have an ngen image, but this type may have failed to load during ngen.
4346                 GetModule()->GetFile()->LoadLibrary(FALSE);
4347                 
4348                 DWORD fldSize;
4349                 if (FieldDescElementType == ELEMENT_TYPE_VALUETYPE)
4350                 {
4351                     if (IsSelfRef(pByValueClass))
4352                     {
4353                         _ASSERTE(bmtFP->fHasSelfReferencingStaticValueTypeField_WithRVA);
4354                         
4355                         // We do not known the size yet
4356                         _ASSERTE(bmtFP->NumInstanceFieldBytes == 0);
4357                         // We will check just the RVA with size 0 now, the full size verification will happen in code:VerifySelfReferencingStaticValueTypeFields_WithRVA
4358                         fldSize = 0;
4359                     }
4360                     else
4361                     {
4362                         fldSize = pByValueClass->GetNumInstanceFieldBytes();
4363                     }
4364                 }
4365                 else
4366                 {
4367                     fldSize = GetSizeForCorElementType(FieldDescElementType);
4368                 }
4369                 
4370                 pFD->SetOffsetRVA(rva);
4371             }
4372             else if (fIsThreadStatic)
4373             {
4374                 bmtFP->NumThreadStaticFieldsOfSize[dwLog2FieldSize]++;
4375
4376                 if (bCurrentFieldIsGCPointer)
4377                     bmtFP->NumThreadStaticGCPointerFields++;
4378
4379                 if (fIsByValue)
4380                     bmtFP->NumThreadStaticGCBoxedFields++;
4381             }
4382             else
4383             {
4384                 bmtFP->NumRegularStaticFieldsOfSize[dwLog2FieldSize]++;
4385
4386                 if (bCurrentFieldIsGCPointer)
4387                     bmtFP->NumRegularStaticGCPointerFields++;
4388
4389                 if (fIsByValue)
4390                     bmtFP->NumRegularStaticGCBoxedFields++;
4391             }
4392         }
4393     }
4394     // We processed all fields
4395     
4396     //#SelfReferencingStaticValueTypeField_Checks
4397     if (bmtFP->fHasSelfReferencingStaticValueTypeField_WithRVA)
4398     {   // The type has self-referencing static ValueType field with RVA, do more checks now that depend on all fields being processed
4399         
4400         // For enums we already checked its underlying type, we should not get here
4401         _ASSERTE(!IsEnum());
4402         
4403         if (HasFieldsWhichMustBeInited())
4404         {   // RVA fields are not allowed to have GC pointers.
4405             BAD_FORMAT_NOTHROW_ASSERT(!"ObjectRef in an RVA self-referencing static field");
4406             BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil);
4407         }
4408     }
4409     
4410     DWORD dwNumInstanceFields = dwCurrentDeclaredField + (HasParent() ? GetParentMethodTable()->GetNumInstanceFields() : 0);
4411     DWORD dwNumStaticFields = bmtEnumFields->dwNumStaticFields;
4412     DWORD dwNumThreadStaticFields = bmtEnumFields->dwNumThreadStaticFields;
4413
4414     if (!FitsIn<WORD>(dwNumInstanceFields) ||
4415         !FitsIn<WORD>(dwNumStaticFields))
4416     {   // An implementation limitation means that it's an error if there are greater that MAX_WORD fields.
4417         BuildMethodTableThrowException(IDS_EE_TOOMANYFIELDS);
4418     }
4419
4420     GetHalfBakedClass()->SetNumInstanceFields((WORD)dwNumInstanceFields);
4421     GetHalfBakedClass()->SetNumStaticFields((WORD)dwNumStaticFields);
4422     GetHalfBakedClass()->SetNumThreadStaticFields((WORD)dwNumThreadStaticFields);
4423
4424     if (bmtFP->fHasFixedAddressValueTypes)
4425     {
4426         // To make things simpler, if the class has any field with this requirement, we'll set
4427         // all the statics to have this property. This allows us to only need to persist one bit
4428         // for the ngen case.
4429         GetHalfBakedClass()->SetHasFixedAddressVTStatics();
4430     }
4431
4432 #ifdef FEATURE_64BIT_ALIGNMENT
4433     // For types with layout we drop any 64-bit alignment requirement if the packing size was less than 8
4434     // bytes (this mimics what the native compiler does and ensures we match up calling conventions during
4435     // interop).
4436     if (HasLayout() && GetLayoutInfo()->GetPackingSize() < 8)
4437     {
4438         fFieldRequiresAlign8 = false;
4439     }
4440
4441     if (fFieldRequiresAlign8)
4442     {
4443         SetAlign8Candidate();
4444     }
4445 #endif // FEATURE_64BIT_ALIGNMENT
4446
4447 #ifdef FEATURE_DOUBLE_ALIGNMENT_HINT
4448     if (ShouldAlign8(dwR8Fields, dwNumInstanceFields))
4449     {
4450         SetAlign8Candidate();
4451     }
4452 #endif // FEATURE_DOUBLE_ALIGNMENT_HINT
4453
4454
4455     //========================================================================
4456     // END:
4457     //    Go thru all fields and initialize their FieldDescs.
4458     //========================================================================
4459
4460     return;
4461 } // MethodTableBuilder::InitializeFieldDescs
4462
4463 #ifdef _PREFAST_ 
4464 #pragma warning(pop)
4465 #endif
4466
4467 //*******************************************************************************
4468 // Verify self-referencing static ValueType fields with RVA (when the size of the ValueType is known).
4469 void 
4470 MethodTableBuilder::VerifySelfReferencingStaticValueTypeFields_WithRVA(
4471     MethodTable ** pByValueClassCache)
4472 {
4473     STANDARD_VM_CONTRACT;
4474     
4475     _ASSERTE(bmtFP->fHasSelfReferencingStaticValueTypeField_WithRVA);
4476     // Enum's static self-referencing fields have been verified as the underlying type of the enum, we should not get here for them
4477     _ASSERTE(!IsEnum());
4478     // The size of the ValueType should be known at this point (the caller throws if it is 0)
4479     _ASSERTE(bmtFP->NumInstanceFieldBytes != 0);
4480     
4481     FieldDesc * pFieldDescList = GetApproxFieldDescListRaw();
4482     DWORD nFirstThreadStaticFieldIndex = bmtEnumFields->dwNumInstanceFields + bmtEnumFields->dwNumStaticFields - bmtEnumFields->dwNumThreadStaticFields;
4483     for (DWORD i = bmtEnumFields->dwNumInstanceFields; i < nFirstThreadStaticFieldIndex; i++)
4484     {
4485         FieldDesc * pFD = &pFieldDescList[i];
4486         _ASSERTE(pFD->IsStatic());
4487         
4488         if (pFD->IsRVA() && pFD->IsByValue())
4489         {
4490             _ASSERTE(pByValueClassCache[i] != NULL);
4491             
4492             if (IsSelfRef(pByValueClassCache[i]))
4493             {
4494                 DWORD rva;
4495                 IfFailThrow(GetMDImport()->GetFieldRVA(pFD->GetMemberDef(), &rva));
4496             }
4497         }
4498     }
4499 } // MethodTableBuilder::VerifySelfReferencingStaticValueTypeFields_WithRVA
4500
4501 //*******************************************************************************
4502 // Returns true if hEnclosingTypeCandidate encloses, at any arbitrary depth,
4503 // hNestedTypeCandidate; returns false otherwise.
4504
4505 bool MethodTableBuilder::IsEnclosingNestedTypePair(
4506     bmtTypeHandle hEnclosingTypeCandidate,
4507     bmtTypeHandle hNestedTypeCandidate)
4508 {
4509     STANDARD_VM_CONTRACT;
4510
4511     CONSISTENCY_CHECK(!hEnclosingTypeCandidate.IsNull());
4512     CONSISTENCY_CHECK(!hNestedTypeCandidate.IsNull());
4513     CONSISTENCY_CHECK(!bmtTypeHandle::Equal(hEnclosingTypeCandidate, hNestedTypeCandidate));
4514
4515     Module * pModule = hEnclosingTypeCandidate.GetModule();
4516
4517     if (pModule != hNestedTypeCandidate.GetModule())
4518     {   // If the modules aren't the same, then there's no way
4519         // hBase could be an enclosing type of hChild. We make
4520         // this check early so that the code can deal with only
4521         // one Module and IMDInternalImport instance and can avoid
4522         // extra checks.
4523         return false;
4524     }
4525
4526     IMDInternalImport * pMDImport = pModule->GetMDImport();
4527
4528     mdTypeDef tkEncl = hEnclosingTypeCandidate.GetTypeDefToken();
4529     mdTypeDef tkNest = hNestedTypeCandidate.GetTypeDefToken();
4530
4531     while (tkEncl != tkNest)
4532     {   // Do this using the metadata APIs because MethodTableBuilder does
4533         // not construct type representations for enclosing type chains.
4534         if (FAILED(pMDImport->GetNestedClassProps(tkNest, &tkNest)))
4535         {   // tokNest is not a nested type.
4536             return false;
4537         }
4538     }
4539
4540     // tkNest's enclosing type is tkEncl, so we've shown that
4541     // hEnclosingTypeCandidate encloses hNestedTypeCandidate
4542     return true;
4543 }
4544
4545 //*******************************************************************************
4546 // Given an arbitrary nesting+subclassing pattern like this:
4547 //
4548 // class C1 {
4549 //     private virtual void Foo() { ... }
4550 //     class C2 : C1 {
4551 //       ...
4552 //         class CN : CN-1 {
4553 //             private override void Foo() { ... }
4554 //         }
4555 //       ...
4556 //     }
4557 // }
4558 //
4559 // this method will return true, where hChild == N and hBase == C1
4560 //
4561 // Note that there is no requirement that a type derive from its immediately
4562 // enclosing type, but can skip a level, such as this example:
4563 //
4564 // class A
4565 // {
4566 //     private virtual void Foo() { }
4567 //     public class B
4568 //     {
4569 //         public class C : A
4570 //         {
4571 //             private override void Foo() { }
4572 //         }
4573 //     }
4574 // }
4575 //
4576 // NOTE: IMPORTANT: This code assumes that hBase is indeed a base type of hChild,
4577 //                  and behaviour is undefined if this is not the case.
4578
4579 bool MethodTableBuilder::IsBaseTypeAlsoEnclosingType(
4580     bmtTypeHandle hBase,
4581     bmtTypeHandle hChild)
4582 {
4583     STANDARD_VM_CONTRACT;
4584
4585     CONSISTENCY_CHECK(!hBase.IsNull());
4586     CONSISTENCY_CHECK(!hChild.IsNull());
4587     CONSISTENCY_CHECK(!bmtTypeHandle::Equal(hBase, hChild));
4588
4589     // The idea of this algorithm is that if we climb the inheritance chain
4590     // starting at hChild then we'll eventually hit hBase. If we check that
4591     // for every (hParent, hChild) pair in the chain that hParent encloses
4592     // hChild, then we've shown that hBase encloses hChild.
4593
4594     while (!bmtTypeHandle::Equal(hBase, hChild))
4595     {
4596         CONSISTENCY_CHECK(!hChild.GetParentType().IsNull());
4597         bmtTypeHandle hParent(hChild.GetParentType());
4598
4599         if (!IsEnclosingNestedTypePair(hParent, hChild))
4600         {   // First, the parent type must enclose the child type.
4601             // If this is not the case we fail immediately.
4602             return false;
4603         }
4604
4605         // Move up one in the inheritance chain, and try again.
4606         hChild = hParent;
4607     }
4608
4609     // If the loop worked itself from the original hChild all the way
4610     // up to hBase, then we know that for every (hParent, hChild)
4611     // pair in the chain that hParent enclosed hChild, and so we know
4612     // that hBase encloses the original hChild
4613     return true;
4614 }
4615
4616 //*******************************************************************************
4617 BOOL MethodTableBuilder::TestOverrideForAccessibility(
4618     bmtMethodHandle hParentMethod,
4619     bmtTypeHandle   hChildType)
4620 {
4621     STANDARD_VM_CONTRACT;
4622
4623     bmtTypeHandle hParentType(hParentMethod.GetOwningType());
4624
4625     Module * pParentModule = hParentType.GetModule();
4626     Module * pChildModule = hChildType.GetModule();
4627
4628     Assembly * pParentAssembly = pParentModule->GetAssembly();
4629     Assembly * pChildAssembly = pChildModule->GetAssembly();
4630
4631     BOOL isSameAssembly = (pChildAssembly == pParentAssembly);
4632
4633     DWORD dwParentAttrs = hParentMethod.GetDeclAttrs();
4634
4635     // AKA "strict bit". This means that overridability is tightly bound to accessibility.
4636     if (IsMdCheckAccessOnOverride(dwParentAttrs))
4637     {
4638         // Same Assembly
4639         if (isSameAssembly || pParentAssembly->GrantsFriendAccessTo(pChildAssembly, hParentMethod.GetMethodDesc())
4640             || pChildAssembly->IgnoresAccessChecksTo(pParentAssembly))
4641         {
4642             // Can always override any method that has accessibility greater than mdPrivate
4643             if ((dwParentAttrs & mdMemberAccessMask) > mdPrivate)
4644             {   // Fall through
4645             }
4646             // Generally, types cannot override inherited mdPrivate methods, except:
4647             // Types can access enclosing type's private members, so it can
4648             // override them if the nested type extends its enclosing type.
4649             else if ((dwParentAttrs & mdMemberAccessMask) == mdPrivate &&
4650                      IsBaseTypeAlsoEnclosingType(hParentType, hChildType))
4651             {   // Fall through
4652             }
4653             else
4654             {
4655                 return FALSE;
4656             }
4657         }
4658         // Cross-Assembly
4659         else
4660         {
4661             // If the method marks itself as check visibility the the method must be
4662             // public, FamORAssem, or family
4663             if((dwParentAttrs & mdMemberAccessMask) <= mdAssem)
4664             {
4665                 return FALSE;
4666             }
4667         }
4668     }
4669     return TRUE;
4670 }
4671
4672 //*******************************************************************************
4673 VOID MethodTableBuilder::TestOverRide(bmtMethodHandle hParentMethod,
4674                                       bmtMethodHandle hChildMethod)
4675 {
4676     CONTRACTL {
4677         STANDARD_VM_CHECK;
4678         PRECONDITION(IsMdVirtual(hParentMethod.GetDeclAttrs()));
4679         PRECONDITION(IsMdVirtual(hChildMethod.GetDeclAttrs()));
4680     } CONTRACTL_END;
4681
4682     DWORD dwAttrs = hChildMethod.GetDeclAttrs();
4683     DWORD dwParentAttrs = hParentMethod.GetDeclAttrs();
4684
4685     Module *pModule = hChildMethod.GetOwningType().GetModule();
4686     Module *pParentModule = hParentMethod.GetOwningType().GetModule();
4687
4688     Assembly *pAssembly = pModule->GetAssembly();
4689     Assembly *pParentAssembly = pParentModule->GetAssembly();
4690
4691     BOOL isSameModule = (pModule == pParentModule);
4692     BOOL isSameAssembly = (pAssembly == pParentAssembly);
4693
4694     if (!TestOverrideForAccessibility(hParentMethod, hChildMethod.GetOwningType()))
4695     {
4696         BuildMethodTableThrowException(IDS_CLASSLOAD_MI_ACCESS_FAILURE, hChildMethod.GetMethodSignature().GetToken());
4697     }
4698
4699     //
4700     // Refer to Partition II, 9.3.3 for more information on what is permitted.
4701     //
4702
4703     enum WIDENING_STATUS
4704     {
4705         e_NO,       // NO
4706         e_YES,      // YES
4707         e_SA,       // YES, but only when same assembly
4708         e_NSA,      // YES, but only when NOT same assembly
4709         e_SM,       // YES, but only when same module
4710     };
4711
4712     static_assert_no_msg(mdPrivateScope == 0x00);
4713     static_assert_no_msg(mdPrivate      == 0x01);
4714     static_assert_no_msg(mdFamANDAssem  == 0x02);
4715     static_assert_no_msg(mdAssem        == 0x03);
4716     static_assert_no_msg(mdFamily       == 0x04);
4717     static_assert_no_msg(mdFamORAssem   == 0x05);
4718     static_assert_no_msg(mdPublic       == 0x06);
4719
4720     static const DWORD dwCount = mdPublic - mdPrivateScope + 1;
4721     static const WIDENING_STATUS rgWideningTable[dwCount][dwCount] =
4722
4723     //               |        Base type
4724     // Subtype       |        mdPrivateScope  mdPrivate   mdFamANDAssem   mdAssem     mdFamily    mdFamORAssem    mdPublic
4725     // --------------+-------------------------------------------------------------------------------------------------------
4726     /*mdPrivateScope | */ { { e_SM,           e_NO,       e_NO,           e_NO,       e_NO,       e_NO,           e_NO    },
4727     /*mdPrivate      | */   { e_SM,           e_YES,      e_NO,           e_NO,       e_NO,       e_NO,           e_NO    },
4728     /*mdFamANDAssem  | */   { e_SM,           e_YES,      e_SA,           e_NO,       e_NO,       e_NO,           e_NO    },
4729     /*mdAssem        | */   { e_SM,           e_YES,      e_SA,           e_SA,       e_NO,       e_NO,           e_NO    },
4730     /*mdFamily       | */   { e_SM,           e_YES,      e_YES,          e_NO,       e_YES,      e_NSA,          e_NO    },
4731     /*mdFamORAssem   | */   { e_SM,           e_YES,      e_YES,          e_SA,       e_YES,      e_YES,          e_NO    },
4732     /*mdPublic       | */   { e_SM,           e_YES,      e_YES,          e_YES,      e_YES,      e_YES,          e_YES   } };
4733
4734     DWORD idxParent = (dwParentAttrs & mdMemberAccessMask) - mdPrivateScope;
4735     DWORD idxMember = (dwAttrs & mdMemberAccessMask) - mdPrivateScope;
4736     CONSISTENCY_CHECK(idxParent < dwCount);
4737     CONSISTENCY_CHECK(idxMember < dwCount);
4738
4739     WIDENING_STATUS entry = rgWideningTable[idxMember][idxParent];
4740
4741     if (entry == e_NO ||
4742         (entry == e_SA && !isSameAssembly && !pParentAssembly->GrantsFriendAccessTo(pAssembly, hParentMethod.GetMethodDesc())
4743          && !pAssembly->IgnoresAccessChecksTo(pParentAssembly)) ||
4744         (entry == e_NSA && isSameAssembly) ||
4745         (entry == e_SM && !isSameModule)
4746        )
4747     {
4748         BuildMethodTableThrowException(IDS_CLASSLOAD_REDUCEACCESS, hChildMethod.GetMethodSignature().GetToken());
4749     }
4750
4751     return;
4752 }
4753
4754 //*******************************************************************************
4755 VOID MethodTableBuilder::TestMethodImpl(
4756     bmtMethodHandle hDeclMethod,
4757     bmtMethodHandle hImplMethod)
4758 {
4759     CONTRACTL
4760     {
4761         STANDARD_VM_CHECK;
4762         PRECONDITION(!hDeclMethod.IsNull());
4763         PRECONDITION(!hImplMethod.IsNull());
4764     }
4765     CONTRACTL_END
4766
4767     Module * pDeclModule = hDeclMethod.GetOwningType().GetModule();
4768     Module * pImplModule = hImplMethod.GetOwningType().GetModule();
4769
4770     mdTypeDef tokDecl = hDeclMethod.GetMethodSignature().GetToken();
4771     mdTypeDef tokImpl = hImplMethod.GetMethodSignature().GetToken();
4772
4773     BOOL isSameModule = pDeclModule->Equals(pImplModule);
4774
4775     IMDInternalImport *pIMDDecl = pDeclModule->GetMDImport();
4776     IMDInternalImport *pIMDImpl = pImplModule->GetMDImport();
4777
4778     DWORD dwDeclAttrs;
4779     if (FAILED(pIMDDecl->GetMethodDefProps(tokDecl, &dwDeclAttrs)))
4780     {
4781         BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
4782     }
4783     DWORD dwImplAttrs;
4784     if (FAILED(pIMDImpl->GetMethodDefProps(tokImpl, &dwImplAttrs)))
4785     {
4786         BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
4787     }
4788     
4789     HRESULT hr = COR_E_TYPELOAD;
4790
4791     if (!IsMdVirtual(dwDeclAttrs))
4792     {
4793         BuildMethodTableThrowException(IDS_CLASSLOAD_MI_NONVIRTUAL_DECL);
4794     }
4795     if (!IsMdVirtual(dwImplAttrs))
4796     {
4797         BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MUSTBEVIRTUAL);
4798     }
4799     // Virtual methods cannot be static
4800     if (IsMdStatic(dwDeclAttrs))
4801     {
4802         BuildMethodTableThrowException(IDS_CLASSLOAD_STATICVIRTUAL);
4803     }
4804     if (IsMdStatic(dwImplAttrs))
4805     {
4806         BuildMethodTableThrowException(IDS_CLASSLOAD_STATICVIRTUAL);
4807     }
4808     if (IsMdFinal(dwDeclAttrs))
4809     {
4810         BuildMethodTableThrowException(IDS_CLASSLOAD_MI_FINAL_DECL);
4811     }
4812
4813     // Interface method body that has methodimpl should always be final
4814     if (IsInterface() && !IsMdFinal(dwImplAttrs))
4815     {
4816         BuildMethodTableThrowException(IDS_CLASSLOAD_MI_FINAL_IMPL);
4817     }
4818
4819     // Since MethodImpl's do not affect the visibility of the Decl method, there's
4820     // no need to check.
4821
4822     // If Decl's parent is other than this class, Decl must not be private
4823     mdTypeDef tkImplParent = mdTypeDefNil;
4824     mdTypeDef tkDeclParent = mdTypeDefNil;
4825
4826     if (FAILED(hr = pIMDDecl->GetParentToken(tokDecl, &tkDeclParent)))
4827     {
4828         BuildMethodTableThrowException(hr, *bmtError);
4829     }
4830     if (FAILED(hr = pIMDImpl->GetParentToken(tokImpl, &tkImplParent)))
4831     {
4832         BuildMethodTableThrowException(hr, *bmtError);
4833     }
4834
4835     // Make sure that we test for accessibility restrictions only if the decl is
4836     // not within our own type, as we are allowed to methodImpl a private with the
4837     // strict bit set if it is in our own type.
4838     if (!isSameModule || tkDeclParent != tkImplParent)
4839     {
4840         if (!TestOverrideForAccessibility(hDeclMethod, hImplMethod.GetOwningType()))
4841         {
4842             BuildMethodTableThrowException(IDS_CLASSLOAD_MI_ACCESS_FAILURE, tokImpl);
4843         }
4844
4845         // Decl's parent must not be tdSealed
4846         mdToken tkGrandParentDummyVar;
4847         DWORD dwDeclTypeAttrs;
4848         if (FAILED(hr = pIMDDecl->GetTypeDefProps(tkDeclParent, &dwDeclTypeAttrs, &tkGrandParentDummyVar)))
4849         {
4850             BuildMethodTableThrowException(hr, *bmtError);
4851         }
4852         if (IsTdSealed(dwDeclTypeAttrs))
4853         {
4854             BuildMethodTableThrowException(IDS_CLASSLOAD_MI_SEALED_DECL);
4855         }
4856     }
4857     
4858     return;
4859 }
4860
4861
4862 //*******************************************************************************
4863 //
4864 // Used by BuildMethodTable
4865 //
4866 VOID
4867 MethodTableBuilder::ValidateMethods()
4868 {
4869     CONTRACTL
4870     {
4871         STANDARD_VM_CHECK;
4872
4873         PRECONDITION(CheckPointer(this));
4874         PRECONDITION(CheckPointer(bmtInternal));
4875         PRECONDITION(CheckPointer(bmtMetaData));
4876         PRECONDITION(CheckPointer(bmtError));
4877         PRECONDITION(CheckPointer(bmtProp));
4878         PRECONDITION(CheckPointer(bmtInterface));
4879         PRECONDITION(CheckPointer(bmtParent));
4880         PRECONDITION(CheckPointer(bmtMFDescs));
4881         PRECONDITION(CheckPointer(bmtEnumFields));
4882         PRECONDITION(CheckPointer(bmtMethodImpl));
4883         PRECONDITION(CheckPointer(bmtVT));
4884     }
4885     CONTRACTL_END;
4886
4887     // Used to keep track of located default and type constructors.
4888     CONSISTENCY_CHECK(bmtVT->pCCtor == NULL);
4889     CONSISTENCY_CHECK(bmtVT->pDefaultCtor == NULL);
4890
4891     // Fetch the hard-coded signatures for the type constructor and the
4892     // default constructor and create MethodSignature objects for both at
4893     // the method level so this does not happen for every specialname
4894     // method.
4895
4896     Signature sig;
4897     
4898     sig = MscorlibBinder::GetSignature(&gsig_SM_RetVoid);
4899
4900     MethodSignature cctorSig(MscorlibBinder::GetModule(),
4901                              COR_CCTOR_METHOD_NAME,
4902                              sig.GetRawSig(), sig.GetRawSigLen());
4903
4904     sig = MscorlibBinder::GetSignature(&gsig_IM_RetVoid);
4905
4906     MethodSignature defaultCtorSig(MscorlibBinder::GetModule(),
4907                                    COR_CTOR_METHOD_NAME,
4908                                    sig.GetRawSig(), sig.GetRawSigLen());
4909
4910     Module * pModule = GetModule();
4911     DeclaredMethodIterator it(*this);
4912     while (it.Next())
4913     {
4914         // The RVA is only valid/testable if it has not been overwritten
4915         // for something like edit-and-continue
4916         // Complete validation of non-zero RVAs is done later inside MethodDesc::GetILHeader.
4917         if ((it.RVA() == 0) && (pModule->GetDynamicIL(it.Token(), FALSE) == NULL))
4918         {
4919             // for IL code that is implemented here must have a valid code RVA
4920             // this came up due to a linker bug where the ImplFlags/DescrOffset were
4921             // being set to null and we weren't coping with it
4922             if((IsMiIL(it.ImplFlags()) || IsMiOPTIL(it.ImplFlags())) &&
4923                    !IsMdAbstract(it.Attrs()) &&
4924                    !IsReallyMdPinvokeImpl(it.Attrs()) &&
4925                 !IsMiInternalCall(it.ImplFlags()))
4926             {
4927                 BuildMethodTableThrowException(IDS_CLASSLOAD_MISSINGMETHODRVA, it.Token());
4928             }
4929         }
4930
4931         if (IsMdRTSpecialName(it.Attrs()))
4932         {
4933             if (IsMdVirtual(it.Attrs()))
4934             {   // Virtual specialname methods are illegal
4935                 BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
4936             }
4937
4938             // Constructors (.ctor) and class initialisers (.cctor) are special
4939             const MethodSignature &curSig(it->GetMethodSignature());
4940
4941             if (IsMdStatic(it.Attrs()))
4942             {   // The only rtSpecialName static method allowed is the .cctor
4943                 if (!curSig.ExactlyEqual(cctorSig))
4944                 {   // Bad method
4945                     BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
4946                 }
4947
4948                 // Remember it for later
4949                 bmtVT->pCCtor = *it;
4950             }
4951             else
4952             {
4953                 if(!MethodSignature::NamesEqual(curSig, defaultCtorSig))
4954                 {   // The only rtSpecialName instance methods allowed are .ctors
4955                     BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
4956                 }
4957
4958                 // .ctor must return void
4959                 MetaSig methodMetaSig(curSig.GetSignature(),
4960                                         static_cast<DWORD>(curSig.GetSignatureLength()),
4961                                         curSig.GetModule(),
4962                                         NULL);
4963
4964                 if (methodMetaSig.GetReturnType() != ELEMENT_TYPE_VOID)
4965                 {   // All constructors must have a void return type
4966                     BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
4967                 }
4968
4969                 // See if this is a default constructor.  If so, remember it for later.
4970                 if (curSig.ExactlyEqual(defaultCtorSig))
4971                 {
4972                     bmtVT->pDefaultCtor = *it;
4973                 }
4974             }
4975         }
4976
4977         // Make sure that fcalls have a 0 rva.  This is assumed by the prejit fixup logic
4978         if (it.MethodType() == METHOD_TYPE_FCALL && it.RVA() != 0)
4979         {
4980             BuildMethodTableThrowException(BFA_ECALLS_MUST_HAVE_ZERO_RVA, it.Token());
4981         }
4982
4983         // check for proper use of the Managed and native flags
4984         if (IsMiManaged(it.ImplFlags()))
4985         {
4986             if (IsMiIL(it.ImplFlags()) || IsMiRuntime(it.ImplFlags())) // IsMiOPTIL(it.ImplFlags()) no longer supported
4987             {
4988                 // No need to set code address, pre stub used automatically.
4989             }
4990             else
4991             {
4992                 if (IsMiNative(it.ImplFlags()))
4993                 {
4994                     // For now simply disallow managed native code if you turn this on you have to at least
4995                     // insure that we have SkipVerificationPermission or equivalent
4996                     BuildMethodTableThrowException(BFA_MANAGED_NATIVE_NYI, it.Token());
4997                 }
4998                 else
4999                 {
5000                     BuildMethodTableThrowException(BFA_BAD_IMPL_FLAGS, it.Token());
5001                 }
5002             }
5003         }
5004         else
5005         {
5006             if (IsMiNative(it.ImplFlags()) && IsGlobalClass())
5007             {
5008                 // global function unmanaged entrypoint via IJW thunk was handled
5009                 // above.
5010             }
5011             else
5012             {
5013                 BuildMethodTableThrowException(IDS_CLASSLOAD_BAD_UNMANAGED_RVA, it.Token());
5014             }
5015             if (it.MethodType() != METHOD_TYPE_NDIRECT)
5016             {
5017                 BuildMethodTableThrowException(BFA_BAD_UNMANAGED_ENTRY_POINT);
5018             }
5019         }
5020
5021         // Vararg methods are not allowed inside generic classes
5022         // and nor can they be generic methods.
5023         if (bmtGenerics->GetNumGenericArgs() > 0 || (it.MethodType() == METHOD_TYPE_INSTANTIATED) )
5024         {
5025             DWORD cMemberSignature;
5026             PCCOR_SIGNATURE pMemberSignature = it.GetSig(&cMemberSignature);
5027             // We've been trying to avoid asking for the signature - now we need it
5028             if (pMemberSignature == NULL)
5029             {
5030                 pMemberSignature = it.GetSig(&cMemberSignature);
5031             }
5032
5033             if (MetaSig::IsVarArg(pModule, Signature(pMemberSignature, cMemberSignature)))
5034             {
5035                 BuildMethodTableThrowException(BFA_GENCODE_NOT_BE_VARARG);
5036             }
5037         }
5038
5039         if (IsMdVirtual(it.Attrs()) && IsMdPublic(it.Attrs()) && it.Name() == NULL)
5040         {
5041             BuildMethodTableThrowException(IDS_CLASSLOAD_NOMETHOD_NAME);
5042         }
5043
5044         if (it.IsMethodImpl())
5045         {
5046             if (!IsMdVirtual(it.Attrs()))
5047             {   // Non-virtual methods cannot participate in a methodImpl pair.
5048                 BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MUSTBEVIRTUAL, it.Token());
5049             }
5050         }
5051
5052         // Virtual static methods are not allowed.
5053         if (IsMdStatic(it.Attrs()) && IsMdVirtual(it.Attrs()))
5054         {
5055             BuildMethodTableThrowException(IDS_CLASSLOAD_STATICVIRTUAL, it.Token());
5056         }
5057     }
5058 }
5059
5060 //*******************************************************************************
5061 // Essentially, this is a helper method that combines calls to InitMethodDesc and 
5062 // SetSecurityFlagsOnMethod. It then assigns the newly initialized MethodDesc to 
5063 // the bmtMDMethod.
5064 VOID
5065 MethodTableBuilder::InitNewMethodDesc(
5066     bmtMDMethod * pMethod,
5067     MethodDesc * pNewMD)
5068 {
5069     STANDARD_VM_CONTRACT;
5070
5071     //
5072     // First, set all flags that control layout of optional slots
5073     //
5074     pNewMD->SetClassification(GetMethodClassification(pMethod->GetMethodType()));
5075
5076     if (pMethod->GetMethodImplType() == METHOD_IMPL)
5077         pNewMD->SetHasMethodImplSlot();
5078
5079     if (pMethod->GetSlotIndex() >= bmtVT->cVtableSlots)
5080         pNewMD->SetHasNonVtableSlot();
5081
5082     if (NeedsNativeCodeSlot(pMethod))
5083         pNewMD->SetHasNativeCodeSlot();
5084
5085     // Now we know the classification we can allocate the correct type of
5086     // method desc and perform any classification specific initialization.
5087
5088     LPCSTR pName = pMethod->GetMethodSignature().GetName();
5089     if (pName == NULL)
5090     {
5091         if (FAILED(GetMDImport()->GetNameOfMethodDef(pMethod->GetMethodSignature().GetToken(), &pName)))
5092         {
5093             BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
5094         }
5095     }
5096     
5097 #ifdef _DEBUG 
5098     LPCUTF8 pszDebugMethodName;
5099     if (FAILED(GetMDImport()->GetNameOfMethodDef(pMethod->GetMethodSignature().GetToken(), &pszDebugMethodName)))
5100     {
5101         pszDebugMethodName = "Invalid MethodDef record";
5102     }
5103     S_SIZE_T safeLen = S_SIZE_T(strlen(pszDebugMethodName)) + S_SIZE_T(1);
5104     if(safeLen.IsOverflow())
5105         COMPlusThrowHR(COR_E_OVERFLOW);
5106
5107     size_t len = safeLen.Value();
5108     LPCUTF8 pszDebugMethodNameCopy = (char*) AllocateFromLowFrequencyHeap(safeLen);
5109     strcpy_s((char *) pszDebugMethodNameCopy, len, pszDebugMethodName);
5110 #endif // _DEBUG
5111
5112     // Do the init specific to each classification of MethodDesc & assign some common fields
5113     InitMethodDesc(pNewMD,
5114                    GetMethodClassification(pMethod->GetMethodType()),
5115                    pMethod->GetMethodSignature().GetToken(),
5116                    pMethod->GetImplAttrs(),
5117                    pMethod->GetDeclAttrs(),
5118                    FALSE,
5119                    pMethod->GetRVA(),
5120                    GetMDImport(),
5121                    pName
5122                    COMMA_INDEBUG(pszDebugMethodNameCopy)
5123                    COMMA_INDEBUG(GetDebugClassName())
5124                    COMMA_INDEBUG("") // FIX this happens on global methods, give better info
5125                   );
5126
5127     pMethod->SetMethodDesc(pNewMD);
5128
5129     bmtRTMethod * pParentMethod = NULL;
5130
5131     if (HasParent())
5132     {
5133         SLOT_INDEX idx = pMethod->GetSlotIndex();
5134         CONSISTENCY_CHECK(idx != INVALID_SLOT_INDEX);
5135
5136         if (idx < GetParentMethodTable()->GetNumVirtuals())
5137         {
5138             pParentMethod = (*bmtParent->pSlotTable)[idx].Decl().AsRTMethod();
5139         }
5140     }
5141
5142     // Turn off inlining for any calls
5143     // that are marked in the metadata as not being inlineable.
5144     if(IsMiNoInlining(pMethod->GetImplAttrs()))
5145     {
5146         pNewMD->SetNotInline(true);
5147     }
5148
5149     // Check for methods marked as [Intrinsic]
5150     if (GetModule()->IsSystem())
5151     {
5152         HRESULT hr = GetMDImport()->GetCustomAttributeByName(pMethod->GetMethodSignature().GetToken(),
5153             g_CompilerServicesIntrinsicAttribute,
5154             NULL,
5155             NULL);
5156
5157         if (hr == S_OK || bmtProp->fIsHardwareIntrinsic)
5158         {
5159             pNewMD->SetIsJitIntrinsic();
5160         }
5161
5162     }
5163
5164     pNewMD->SetSlot(pMethod->GetSlotIndex());
5165 }
5166
5167 //*******************************************************************************
5168 // Determine vtable placement for each non-virtual in the class, while also
5169 // looking for default and type constructors.
5170 VOID
5171 MethodTableBuilder::PlaceNonVirtualMethods()
5172 {
5173     CONTRACTL
5174     {
5175         STANDARD_VM_CHECK;
5176
5177         PRECONDITION(CheckPointer(this));
5178         PRECONDITION(CheckPointer(bmtInternal));
5179         PRECONDITION(CheckPointer(bmtMetaData));
5180         PRECONDITION(CheckPointer(bmtError));
5181         PRECONDITION(CheckPointer(bmtProp));
5182         PRECONDITION(CheckPointer(bmtInterface));
5183         PRECONDITION(CheckPointer(bmtParent));
5184         PRECONDITION(CheckPointer(bmtMFDescs));
5185         PRECONDITION(CheckPointer(bmtEnumFields));
5186         PRECONDITION(CheckPointer(bmtMethodImpl));
5187         PRECONDITION(CheckPointer(bmtVT));
5188     }
5189     CONTRACTL_END;
5190
5191     INDEBUG(bmtVT->SealVirtualSlotSection();)
5192
5193     //
5194     // For each non-virtual method, place the method in the next available non-virtual method slot.
5195     //
5196
5197     // Place the cctor and default ctor first. code::MethodTableGetCCtorSlot and code:MethodTable::GetDefaultCtorSlot 
5198     // depends on this.
5199     if (bmtVT->pCCtor != NULL)
5200     {
5201         if (!bmtVT->AddNonVirtualMethod(bmtVT->pCCtor))
5202             BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
5203     }
5204
5205     if (bmtVT->pDefaultCtor != NULL)
5206     {
5207         if (!bmtVT->AddNonVirtualMethod(bmtVT->pDefaultCtor))
5208             BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
5209     }
5210
5211     // We use slot during remoting and to map methods between generic instantiations
5212     // (see MethodTable::GetParallelMethodDesc). The current implementation
5213     // of this mechanism requires real slots.
5214     BOOL fCanHaveNonVtableSlots = (bmtGenerics->GetNumGenericArgs() == 0) && !IsInterface();
5215
5216     // Flag to avoid second pass when possible
5217     BOOL fHasNonVtableSlots = FALSE;
5218
5219     //
5220     // Place all methods that require real vtable slot first. This is necessary so
5221     // that they get consequitive slot numbers right after virtual slots.
5222     //
5223
5224     DeclaredMethodIterator it(*this);
5225     while (it.Next())
5226     {
5227         // Skip methods that are placed already
5228         if (it->GetSlotIndex() != INVALID_SLOT_INDEX)
5229             continue;
5230
5231 #ifdef _DEBUG 
5232         if(GetHalfBakedClass()->m_fDebuggingClass && g_pConfig->ShouldBreakOnMethod(it.Name()))
5233             CONSISTENCY_CHECK_MSGF(false, ("BreakOnMethodName: '%s' ", it.Name()));
5234 #endif // _DEBUG
5235
5236         if (!fCanHaveNonVtableSlots ||
5237             it->GetMethodType() == METHOD_TYPE_INSTANTIATED ||
5238             MayBeRemotingIntercepted(*it))
5239         {
5240             // We use slot during remoting and to map methods between generic instantiations
5241             // (see MethodTable::GetParallelMethodDesc). The current implementation
5242             // of this mechanism requires real slots.
5243         }
5244         else
5245         {
5246             // This method does not need real vtable slot
5247             fHasNonVtableSlots = TRUE;
5248             continue;
5249         }
5250
5251         // This will update slot index in bmtMDMethod
5252         if (!bmtVT->AddNonVirtualMethod(*it))
5253             BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
5254     }
5255
5256     // Remeber last real vtable slot
5257     bmtVT->cVtableSlots = bmtVT->cTotalSlots;
5258
5259     // Are there any Non-vtable slots to place?
5260     if (!fHasNonVtableSlots)
5261         return;
5262
5263     //
5264     // Now, place the remaining methods. They will get non-vtable slot.
5265     //
5266
5267     DeclaredMethodIterator it2(*this);
5268     while (it2.Next())
5269     {
5270         // Skip methods that are placed already
5271         if (it2->GetSlotIndex() != INVALID_SLOT_INDEX)
5272             continue;
5273
5274         if (!bmtVT->AddNonVirtualMethod(*it2))
5275             BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
5276     }
5277
5278 }
5279
5280 //*******************************************************************************
5281 // Determine vtable placement for each virtual member in this class.
5282 VOID
5283 MethodTableBuilder::PlaceVirtualMethods()
5284 {
5285     CONTRACTL
5286     {
5287         STANDARD_VM_CHECK;
5288
5289         PRECONDITION(CheckPointer(this));
5290         PRECONDITION(CheckPointer(bmtInternal));
5291         PRECONDITION(CheckPointer(bmtMetaData));
5292         PRECONDITION(CheckPointer(bmtError));
5293         PRECONDITION(CheckPointer(bmtProp));
5294         PRECONDITION(CheckPointer(bmtInterface));
5295         PRECONDITION(CheckPointer(bmtParent));
5296         PRECONDITION(CheckPointer(bmtMFDescs));
5297         PRECONDITION(CheckPointer(bmtEnumFields));
5298         PRECONDITION(CheckPointer(bmtMethodImpl));
5299         PRECONDITION(CheckPointer(bmtVT));
5300     }
5301     CONTRACTL_END;
5302
5303 #ifdef _DEBUG 
5304     LPCUTF8 pszDebugName, pszDebugNamespace;
5305     if (FAILED(GetMDImport()->GetNameOfTypeDef(GetCl(), &pszDebugName, &pszDebugNamespace)))
5306     {
5307         pszDebugName = pszDebugNamespace = "Invalid TypeDef record";
5308     }
5309 #endif // _DEBUG
5310
5311     //
5312     // For each virtual method
5313     //  - If the method is not declared as newslot, search all virtual methods in the parent
5314     //    type for an override candidate.
5315     //      - If such a candidate is found, test to see if the override is valid. If
5316     //        the override is not valid, throw TypeLoadException
5317     //  - If a candidate is found above, place the method in the inherited slot as both
5318     //    the Decl and the Impl.
5319     //  - Else, place the method in the next available empty vtable slot.
5320     //
5321
5322     DeclaredMethodIterator it(*this);
5323     while (it.Next())
5324     {
5325         if (!IsMdVirtual(it.Attrs()))
5326         {   // Only processing declared virtual methods
5327             continue;
5328         }
5329
5330 #ifdef _DEBUG 
5331         if(GetHalfBakedClass()->m_fDebuggingClass && g_pConfig->ShouldBreakOnMethod(it.Name()))
5332             CONSISTENCY_CHECK_MSGF(false, ("BreakOnMethodName: '%s' ", it.Name()));
5333 #endif // _DEBUG
5334
5335         // If this member is a method which overrides a parent method, it will be set to non-NULL
5336         bmtRTMethod * pParentMethod = NULL;
5337
5338         // Hash that a method with this name exists in this class
5339         // Note that ctors and static ctors are not added to the table
5340         BOOL fMethodConstraintsMatch = FALSE;
5341
5342         // If the member is marked with a new slot we do not need to find it in the parent
5343         if (HasParent() && !IsMdNewSlot(it.Attrs()))
5344         {
5345             // Attempt to find the method with this name and signature in the parent class.
5346             // This method may or may not create pParentMethodHash (if it does not already exist).
5347             // It also may or may not fill in pMemberSignature/cMemberSignature.
5348             // An error is only returned when we can not create the hash.
5349             // NOTE: This operation touches metadata
5350             pParentMethod = LoaderFindMethodInParentClass(
5351                 it->GetMethodSignature(), bmtProp->fNoSanityChecks ? NULL : &fMethodConstraintsMatch);
5352
5353             if (pParentMethod != NULL)
5354             {   // Found an override candidate
5355                 DWORD dwParentAttrs = pParentMethod->GetDeclAttrs();
5356
5357                 if (!IsMdVirtual(dwParentAttrs))
5358                 {   // Can't override a non-virtual methods
5359                     BuildMethodTableThrowException(BFA_NONVIRT_NO_SEARCH, it.Token());
5360                 }
5361
5362                 if(IsMdFinal(dwParentAttrs))
5363                 {   // Can't override a final methods
5364                     BuildMethodTableThrowException(IDS_CLASSLOAD_MI_FINAL_DECL, it.Token());
5365                 }
5366
5367                 if(!bmtProp->fNoSanityChecks)
5368                 {
5369                     TestOverRide(bmtMethodHandle(pParentMethod),
5370                                  bmtMethodHandle(*it));
5371
5372                     if (!fMethodConstraintsMatch)
5373                     {
5374                         BuildMethodTableThrowException(
5375                                 IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_IMPLICIT_OVERRIDE,
5376                                 it.Token());
5377                     }
5378                 }
5379             }
5380         }
5381
5382         // vtable method
5383         if (IsInterface())
5384         {
5385             CONSISTENCY_CHECK(pParentMethod == NULL);
5386             // Also sets new slot number on bmtRTMethod and MethodDesc
5387             if (!bmtVT->AddVirtualMethod(*it))
5388                 BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
5389         }
5390         else if (pParentMethod != NULL)
5391         {
5392             bmtVT->SetVirtualMethodOverride(pParentMethod->GetSlotIndex(), *it);
5393         }
5394         else
5395         {
5396             if (!bmtVT->AddVirtualMethod(*it))
5397                 BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
5398         }
5399     }
5400 }
5401
5402 // Given an interface map entry, and a name+signature, compute the method on the interface
5403 // that the name+signature corresponds to. Used by ProcessMethodImpls and ProcessInexactMethodImpls
5404 // Always returns the first match that it finds. Affects the ambiguities in code:#ProcessInexactMethodImpls_Ambiguities
5405 MethodTableBuilder::bmtMethodHandle 
5406 MethodTableBuilder::FindDeclMethodOnInterfaceEntry(bmtInterfaceEntry *pItfEntry, MethodSignature &declSig)
5407 {
5408     STANDARD_VM_CONTRACT;
5409
5410     bmtMethodHandle declMethod;
5411
5412     bmtInterfaceEntry::InterfaceSlotIterator slotIt =
5413         pItfEntry->IterateInterfaceSlots(GetStackingAllocator());
5414     // Check for exact match
5415     for (; !slotIt.AtEnd(); slotIt.Next())
5416     {
5417         bmtRTMethod * pCurDeclMethod = slotIt->Decl().AsRTMethod();
5418
5419         if (declSig.ExactlyEqual(pCurDeclMethod->GetMethodSignature()))
5420         {
5421             declMethod = slotIt->Decl();
5422             break;
5423         }
5424     }
5425     slotIt.ResetToStart();
5426
5427     // Check for equivalent match if exact match wasn't found
5428     if (declMethod.IsNull())
5429     {
5430         for (; !slotIt.AtEnd(); slotIt.Next())
5431         {
5432             bmtRTMethod * pCurDeclMethod = slotIt->Decl().AsRTMethod();
5433
5434             // Type Equivalence is forbidden in MethodImpl MemberRefs
5435             if (declSig.Equivalent(pCurDeclMethod->GetMethodSignature()))
5436             {
5437                 declMethod = slotIt->Decl();
5438                 break;
5439             }
5440         }
5441     }
5442
5443     return declMethod;
5444 }
5445
5446 //*******************************************************************************
5447 //
5448 // Used by BuildMethodTable
5449 // Process the list of inexact method impls generated during ProcessMethodImpls.
5450 // This list is used to cause a methodImpl to an interface to override
5451 // methods on several equivalent interfaces in the interface map. This logic is necessary
5452 // so that in the presence of an embedded interface the behavior appears to mimic
5453 // the behavior if the interface was not embedded.
5454 //
5455 // In particular, the logic here is to handle cases such as
5456 //
5457 //  Assembly A
5458 // [TypeIdentifier("x","y")]
5459 // interface I'
5460 // {  void Method(); }
5461 // interface IOther : I' {}
5462 //
5463 //  Assembly B
5464 // [TypeIdentifier("x","y")]
5465 // interface I
5466 // {  void Method(); }
5467 // class Test : I, IOther
5468 // {
5469 //     void I.Method()
5470 //     {}
5471 // }
5472 // 
5473 // In this case, there is one method, and one methodimpl, but there are 2 interfaces on the class that both
5474 // require an implementation of their method. The correct semantic for type equivalence, is that any
5475 // methodimpl directly targeting a method on an interface must be respected, and if it also applies to a type
5476 // equivalent interface method, then if that method was not methodimpl'd directly, then the methodimpl should apply
5477 // there as well. The ProcessInexactMethodImpls function does this secondary MethodImpl mapping.
5478 //
5479 //#ProcessInexactMethodImpls_Ambiguities
5480 // In the presence of ambiguities, such as there are 3 equivalent interfaces implemented on a class and 2 methodimpls,
5481 // we will apply the 2 method impls exactly to appropriate interface methods, and arbitrarily pick one to apply to the
5482 // other interface. This is clearly ambiguous, but tricky to detect in the type loader efficiently, and should hopefully
5483 // not cause too many problems.
5484 //
5485 VOID
5486 MethodTableBuilder::ProcessInexactMethodImpls()
5487 {
5488     STANDARD_VM_CONTRACT;
5489
5490     if (bmtMethod->dwNumberInexactMethodImplCandidates == 0)
5491         return;
5492
5493     DeclaredMethodIterator it(*this);
5494     while (it.Next())
5495     {
5496         // Non-virtual methods cannot be classified as methodImpl - we should have thrown an
5497         // error before reaching this point.
5498         CONSISTENCY_CHECK(!(!IsMdVirtual(it.Attrs()) && it.IsMethodImpl()));
5499
5500         if (!IsMdVirtual(it.Attrs()))
5501         {   // Only virtual methods can participate in methodImpls
5502             continue;
5503         }
5504
5505         if(!it.IsMethodImpl())
5506         {
5507             // Skip methods which are not the bodies of MethodImpl specifications
5508             continue;
5509         }
5510
5511         // If this method serves as the BODY of a MethodImpl specification, then
5512         // we should iterate all the MethodImpl's for this class and see just how many
5513         // of them this method participates in as the BODY.
5514         for(DWORD m = 0; m < bmtMethod->dwNumberMethodImpls; m++)
5515         {
5516             // Inexact matching logic only works on MethodImpls that have been opted into inexactness by ProcessMethodImpls.
5517             if (!bmtMetaData->rgMethodImplTokens[m].fConsiderDuringInexactMethodImplProcessing)
5518             {
5519                 continue;
5520             }
5521
5522             // If the methodimpl we are working with does not match this method, continue to next methodimpl
5523             if(it.Token() != bmtMetaData->rgMethodImplTokens[m].methodBody)
5524             {
5525                 continue;
5526             }
5527
5528             bool fMatchFound = false;
5529
5530             LPCUTF8 szName = NULL;
5531             PCCOR_SIGNATURE pSig = NULL;
5532             ULONG cbSig;
5533
5534             mdToken mdDecl = bmtMetaData->rgMethodImplTokens[m].methodDecl;
5535             
5536             if (TypeFromToken(mdDecl) == mdtMethodDef)
5537             {   // Different methods are aused to access MethodDef and MemberRef
5538                 // names and signatures.
5539                 if (FAILED(GetMDImport()->GetNameOfMethodDef(mdDecl, &szName)) || 
5540                     FAILED(GetMDImport()->GetSigOfMethodDef(mdDecl, &cbSig, &pSig)))
5541                 {
5542                     BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
5543                 }
5544             }
5545             else
5546             {
5547                 if (FAILED(GetMDImport()->GetNameAndSigOfMemberRef(mdDecl, &pSig, &cbSig, &szName)))
5548                 {
5549                     BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
5550                 }
5551             }
5552
5553             Substitution *pDeclSubst = &bmtMetaData->pMethodDeclSubsts[m];
5554             MethodSignature declSig(GetModule(), szName, pSig, cbSig, pDeclSubst);
5555             bmtInterfaceEntry * pItfEntry = NULL;
5556
5557             for (DWORD i = 0; i < bmtInterface->dwInterfaceMapSize; i++)
5558             {
5559                 if (bmtInterface->pInterfaceMap[i].GetInterfaceEquivalenceSet() != bmtMetaData->rgMethodImplTokens[m].interfaceEquivalenceSet)
5560                     continue;
5561
5562                 bmtMethodHandle declMethod;
5563                 pItfEntry = &bmtInterface->pInterfaceMap[i];
5564
5565                 // Search for declmethod on this interface
5566                 declMethod = FindDeclMethodOnInterfaceEntry(pItfEntry, declSig);
5567
5568                 // If we didn't find a match, continue on to next interface in the equivalence set
5569                 if (declMethod.IsNull())
5570                     continue;
5571
5572                 if (!IsMdVirtual(declMethod.GetDeclAttrs()))
5573                 {   // Make sure the decl is virtual
5574                     BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MUSTBEVIRTUAL, it.Token());
5575                 }
5576
5577                 fMatchFound = true;
5578
5579                 bool fPreexistingImplFound = false;
5580
5581                 // Check to ensure there isn't already a matching declMethod in the method impl list
5582                 for (DWORD iMethodImpl = 0; iMethodImpl < bmtMethodImpl->pIndex; iMethodImpl++)
5583                 {
5584                     if (bmtMethodImpl->GetDeclarationMethod(iMethodImpl) == declMethod)
5585                     {
5586                         fPreexistingImplFound = true;
5587                         break;
5588                     }
5589                 }
5590
5591                 // Search for other matches
5592                 if (fPreexistingImplFound)
5593                     continue;
5594
5595                 // Otherwise, record the method impl discovery if the match is 
5596                 bmtMethodImpl->AddMethodImpl(*it, declMethod, GetStackingAllocator());
5597             }
5598
5599             if (!fMatchFound && bmtMetaData->rgMethodImplTokens[m].fThrowIfUnmatchedDuringInexactMethodImplProcessing)
5600             {
5601                 BuildMethodTableThrowException(IDS_CLASSLOAD_MI_DECLARATIONNOTFOUND, it.Token());
5602             }
5603         }
5604     }
5605 }
5606
5607 //*******************************************************************************
5608 //
5609 // Used by BuildMethodTable
5610 //
5611 VOID
5612 MethodTableBuilder::ProcessMethodImpls()
5613 {
5614     STANDARD_VM_CONTRACT;
5615
5616     if (bmtMethod->dwNumberMethodImpls == 0)
5617         return;
5618
5619     HRESULT hr = S_OK;
5620
5621     DeclaredMethodIterator it(*this);
5622     while (it.Next())
5623     {
5624         // Non-virtual methods cannot be classified as methodImpl - we should have thrown an
5625         // error before reaching this point.
5626         CONSISTENCY_CHECK(!(!IsMdVirtual(it.Attrs()) && it.IsMethodImpl()));
5627
5628         if (!IsMdVirtual(it.Attrs()))
5629         {   // Only virtual methods can participate in methodImpls
5630             continue;
5631         }
5632
5633         // If this method serves as the BODY of a MethodImpl specification, then
5634         // we should iterate all the MethodImpl's for this class and see just how many
5635         // of them this method participates in as the BODY.
5636         if(it.IsMethodImpl())
5637         {
5638             for(DWORD m = 0; m < bmtMethod->dwNumberMethodImpls; m++)
5639             {
5640                 if(it.Token() == bmtMetaData->rgMethodImplTokens[m].methodBody)
5641                 {
5642                     mdToken mdDecl = bmtMetaData->rgMethodImplTokens[m].methodDecl;
5643                     bmtMethodHandle declMethod;
5644
5645                     // Get the parent token for the decl method token
5646                     mdToken tkParent = mdTypeDefNil;
5647                     if (TypeFromToken(mdDecl) == mdtMethodDef || TypeFromToken(mdDecl) == mdtMemberRef)
5648                     {
5649                         if (FAILED(hr = GetMDImport()->GetParentToken(mdDecl,&tkParent)))
5650                         {
5651                             BuildMethodTableThrowException(hr, *bmtError);
5652                         }
5653                     }
5654
5655                     if (GetCl() == tkParent)
5656                     {   // The DECL has been declared within the class that we're currently building.
5657                         hr = S_OK;
5658
5659                         if(bmtError->pThrowable != NULL)
5660                         {
5661                             *(bmtError->pThrowable) = NULL;
5662                         }
5663
5664                         if(TypeFromToken(mdDecl) != mdtMethodDef)
5665                         {
5666                             if (FAILED(hr = FindMethodDeclarationForMethodImpl(
5667                                                 mdDecl, &mdDecl, TRUE)))
5668                             {
5669                                 BuildMethodTableThrowException(hr, *bmtError);
5670                             }
5671                         }
5672
5673                         CONSISTENCY_CHECK(TypeFromToken(mdDecl) == mdtMethodDef);
5674                         declMethod = bmtMethod->FindDeclaredMethodByToken(mdDecl);
5675                     }
5676                     else
5677                     {   // We can't call GetDescFromMemberDefOrRef here because this
5678                         // method depends on a fully-loaded type, including parent types,
5679                         // which is not always guaranteed. In particular, it requires that
5680                         // the instantiation dictionary be filled. The solution is the following:
5681                         //   1. Load the approximate type that the method belongs to.
5682                         //   2. Get or create the correct substitution for the type involved
5683                         //   3. Iterate the introduced methods on that type looking for a matching
5684                         //      method.
5685
5686                         LPCUTF8 szName = NULL;
5687                         PCCOR_SIGNATURE pSig = NULL;
5688                         ULONG cbSig;
5689                         if (TypeFromToken(mdDecl) == mdtMethodDef)
5690                         {   // Different methods are aused to access MethodDef and MemberRef
5691                             // names and signatures.
5692                             if (FAILED(GetMDImport()->GetNameOfMethodDef(mdDecl, &szName)) || 
5693                                 FAILED(GetMDImport()->GetSigOfMethodDef(mdDecl, &cbSig, &pSig)))
5694                             {
5695                                 BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
5696                             }
5697                         }
5698                         else
5699                         {
5700                             if (FAILED(GetMDImport()->GetNameAndSigOfMemberRef(mdDecl, &pSig, &cbSig, &szName)))
5701                             {
5702                                 BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
5703                             }
5704                         }
5705                         
5706                         Substitution *pDeclSubst = &bmtMetaData->pMethodDeclSubsts[m];
5707                         MethodTable * pDeclMT = NULL;
5708                         MethodSignature declSig(GetModule(), szName, pSig, cbSig, pDeclSubst);
5709
5710                         {   // 1. Load the approximate type.
5711                             // Block for the LoadsTypeViolation.
5712                             CONTRACT_VIOLATION(LoadsTypeViolation);
5713                             pDeclMT = ClassLoader::LoadTypeDefOrRefOrSpecThrowing(
5714                                 GetModule(),
5715                                 tkParent,
5716                                 &bmtGenerics->typeContext,
5717                                 ClassLoader::ThrowIfNotFound,
5718                                 ClassLoader::PermitUninstDefOrRef,
5719                                 ClassLoader::LoadTypes,
5720                                 CLASS_LOAD_APPROXPARENTS,
5721                                 TRUE).GetMethodTable()->GetCanonicalMethodTable();
5722                         }
5723
5724                         {   // 2. Get or create the correct substitution
5725                             bmtRTType * pDeclType = NULL;
5726
5727                             if (pDeclMT->IsInterface())
5728                             {   // If the declaration method is a part of an interface, search through
5729                                 // the interface map to find the matching interface so we can provide
5730                                 // the correct substitution chain.
5731                                 pDeclType = NULL;
5732
5733                                 bmtInterfaceEntry * pItfEntry = NULL;
5734                                 for (DWORD i = 0; i < bmtInterface->dwInterfaceMapSize; i++)
5735                                 {
5736                                     bmtRTType * pCurItf = bmtInterface->pInterfaceMap[i].GetInterfaceType();
5737                                     // Type Equivalence is not respected for this comparision as you can have multiple type equivalent interfaces on a class
5738                                     TokenPairList newVisited = TokenPairList::AdjustForTypeEquivalenceForbiddenScope(NULL);
5739                                     if (MetaSig::CompareTypeDefsUnderSubstitutions(
5740                                         pCurItf->GetMethodTable(),      pDeclMT,
5741                                         &pCurItf->GetSubstitution(),    pDeclSubst,
5742                                         &newVisited))
5743                                     {
5744                                         pItfEntry = &bmtInterface->pInterfaceMap[i];
5745                                         pDeclType = pCurItf;
5746                                         break;
5747                                     }
5748                                 }
5749
5750                                 if (IsInterface())
5751                                 {
5752                                     if (pDeclType == NULL)
5753                                     {
5754                                         // Interface is not implemented by this type.
5755                                         BuildMethodTableThrowException(IDS_CLASSLOAD_MI_NOTIMPLEMENTED, it.Token());
5756                                     }
5757                                 }
5758                                 else
5759                                 {
5760                                     if (pDeclType == NULL)
5761                                     {
5762                                         DWORD equivalenceSet = 0;
5763
5764                                         for (DWORD i = 0; i < bmtInterface->dwInterfaceMapSize; i++)
5765                                         {
5766                                             bmtRTType * pCurItf = bmtInterface->pInterfaceMap[i].GetInterfaceType();
5767                                             // Type Equivalence is respected for this comparision as we just need to find an 
5768                                             // equivalent interface, the particular interface is unimportant
5769                                             if (MetaSig::CompareTypeDefsUnderSubstitutions(
5770                                                 pCurItf->GetMethodTable(), pDeclMT,
5771                                                 &pCurItf->GetSubstitution(), pDeclSubst,
5772                                                 NULL))
5773                                             {
5774                                                 equivalenceSet = bmtInterface->pInterfaceMap[i].GetInterfaceEquivalenceSet();
5775                                                 pItfEntry = &bmtInterface->pInterfaceMap[i];
5776                                                 break;
5777                                             }
5778                                         }
5779
5780                                         if (equivalenceSet == 0)
5781                                         {
5782                                             // Interface is not implemented by this type.
5783                                             BuildMethodTableThrowException(IDS_CLASSLOAD_MI_NOTIMPLEMENTED, it.Token());
5784                                         }
5785
5786                                         // Interface is not implemented by this type exactly. We need to consider this MethodImpl on non exact interface matches,
5787                                         // as the only match may be one of the non-exact matches
5788                                         bmtMetaData->rgMethodImplTokens[m].fConsiderDuringInexactMethodImplProcessing = true;
5789                                         bmtMetaData->rgMethodImplTokens[m].fThrowIfUnmatchedDuringInexactMethodImplProcessing = true;
5790                                         bmtMetaData->rgMethodImplTokens[m].interfaceEquivalenceSet = equivalenceSet;
5791                                         bmtMethod->dwNumberInexactMethodImplCandidates++;
5792                                         continue; // Move on to other MethodImpls
5793                                     }
5794                                     else
5795                                     {
5796                                         // This method impl may need to match other methods during inexact processing
5797                                         if (pItfEntry->InEquivalenceSetWithMultipleEntries())
5798                                         {
5799                                             bmtMetaData->rgMethodImplTokens[m].fConsiderDuringInexactMethodImplProcessing = true;
5800                                             bmtMetaData->rgMethodImplTokens[m].fThrowIfUnmatchedDuringInexactMethodImplProcessing = false;
5801                                             bmtMetaData->rgMethodImplTokens[m].interfaceEquivalenceSet = pItfEntry->GetInterfaceEquivalenceSet();
5802                                             bmtMethod->dwNumberInexactMethodImplCandidates++;
5803                                         }
5804                                     }
5805                                 }
5806
5807                                 // 3. Find the matching method.
5808                                 declMethod = FindDeclMethodOnInterfaceEntry(pItfEntry, declSig);
5809                             }
5810                             else
5811                             {   // Assume the MethodTable is a parent of the current type,
5812                                 // and create the substitution chain to match it.
5813
5814                                 pDeclType = NULL;
5815
5816                                 for (bmtRTType *pCur = GetParentType();
5817                                      pCur != NULL;
5818                                      pCur = pCur->GetParentType())
5819                                 {
5820                                     if (pCur->GetMethodTable() == pDeclMT)
5821                                     {
5822                                         pDeclType = pCur;
5823                                         break;
5824                                     }
5825                                 }
5826
5827                                 if (pDeclType == NULL)
5828                                 {   // Method's type is not a parent.
5829                                     BuildMethodTableThrowException(IDS_CLASSLOAD_MI_DECLARATIONNOTFOUND, it.Token());
5830                                 }
5831
5832                                 // 3. Find the matching method.
5833                                 bmtRTType *pCurDeclType = pDeclType;
5834                                 do
5835                                 {
5836                                     // two pass algorithm. search for exact matches followed
5837                                     // by equivalent matches.
5838                                     for (int iPass = 0; (iPass < 2) && (declMethod.IsNull()); iPass++)
5839                                     {
5840                                         MethodTable *pCurDeclMT = pCurDeclType->GetMethodTable();
5841     
5842                                         MethodTable::IntroducedMethodIterator methIt(pCurDeclMT);
5843                                         for(; methIt.IsValid(); methIt.Next())
5844                                         {
5845                                             MethodDesc * pCurMD = methIt.GetMethodDesc();
5846     
5847                                             if (pCurDeclMT != pDeclMT)
5848                                             {
5849                                                 // If the method isn't on the declaring type, then it must be virtual.
5850                                                 if (!pCurMD->IsVirtual())
5851                                                     continue;
5852                                             }
5853                                             if (strcmp(szName, pCurMD->GetName()) == 0)
5854                                             {
5855                                                 PCCOR_SIGNATURE pCurMDSig;
5856                                                 DWORD cbCurMDSig;
5857                                                 pCurMD->GetSig(&pCurMDSig, &cbCurMDSig);
5858
5859                                                 // First pass searches for declaration methods should not use type equivalence
5860                                                 TokenPairList newVisited = TokenPairList::AdjustForTypeEquivalenceForbiddenScope(NULL);
5861
5862                                                 if (MetaSig::CompareMethodSigs(
5863                                                     declSig.GetSignature(),
5864                                                     static_cast<DWORD>(declSig.GetSignatureLength()),
5865                                                     declSig.GetModule(),
5866                                                     &declSig.GetSubstitution(),
5867                                                     pCurMDSig,
5868                                                     cbCurMDSig,
5869                                                     pCurMD->GetModule(),
5870                                                     &pCurDeclType->GetSubstitution(),
5871                                                     iPass == 0 ? &newVisited : NULL))
5872                                                 {
5873                                                     declMethod = (*bmtParent->pSlotTable)[pCurMD->GetSlot()].Decl();
5874                                                     break;
5875                                                 }
5876                                             }
5877                                         }
5878                                     }
5879
5880                                     pCurDeclType = pCurDeclType->GetParentType();
5881                                 } while ((pCurDeclType != NULL) && (declMethod.IsNull()));
5882                             }
5883
5884                             if (declMethod.IsNull())
5885                             {   // Would prefer to let this fall out to the BuildMethodTableThrowException
5886                                 // below, but due to v2.0 and earlier behaviour throwing a MissingMethodException,
5887                                 // primarily because this code used to be a simple call to
5888                                 // MemberLoader::GetDescFromMemberDefOrRef (see above for reason why),
5889                                 // we must continue to do the same.
5890                                 MemberLoader::ThrowMissingMethodException(
5891                                     pDeclMT,
5892                                     declSig.GetName(),
5893                                     declSig.GetModule(),
5894                                     declSig.GetSignature(),
5895                                     static_cast<DWORD>(declSig.GetSignatureLength()),
5896                                     &bmtGenerics->typeContext);
5897                             }
5898                         }
5899                     }
5900
5901                     if (declMethod.IsNull())
5902                     {   // Method not found, throw.
5903                         BuildMethodTableThrowException(IDS_CLASSLOAD_MI_DECLARATIONNOTFOUND, it.Token());
5904                     }
5905                     
5906                     if (!IsMdVirtual(declMethod.GetDeclAttrs()))
5907                     {   // Make sure the decl is virtual
5908                         BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MUSTBEVIRTUAL, it.Token());
5909                     }
5910
5911                     bmtMethodImpl->AddMethodImpl(*it, declMethod, GetStackingAllocator());
5912                 }
5913             }
5914         }
5915     } /* end ... for each member */
5916 }
5917
5918 //*******************************************************************************
5919 // InitMethodDesc takes a pointer to space that's already allocated for the
5920 // particular type of MethodDesc, and initializes based on the other info.
5921 // This factors logic between PlaceMembers (the regular code path) & AddMethod
5922 // (Edit & Continue (EnC) code path) so we don't have to maintain separate copies.
5923 VOID 
5924 MethodTableBuilder::InitMethodDesc(
5925     MethodDesc *        pNewMD, // This is should actually be of the correct sub-type, based on Classification
5926     DWORD               Classification,
5927     mdToken             tok,
5928     DWORD               dwImplFlags,
5929     DWORD               dwMemberAttrs,
5930     BOOL                fEnC,
5931     DWORD               RVA,        // Only needed for NDirect case
5932     IMDInternalImport * pIMDII,     // Needed for NDirect, EEImpl(Delegate) cases
5933     LPCSTR              pMethodName // Only needed for mcEEImpl (Delegate) case
5934     COMMA_INDEBUG(LPCUTF8 pszDebugMethodName)
5935     COMMA_INDEBUG(LPCUTF8 pszDebugClassName)
5936     COMMA_INDEBUG(LPCUTF8 pszDebugMethodSignature)
5937     )
5938 {
5939     CONTRACTL
5940     {
5941         THROWS;
5942         if (fEnC) { GC_NOTRIGGER; } else { GC_TRIGGERS; }
5943         MODE_ANY;
5944     }
5945     CONTRACTL_END;
5946
5947     LOG((LF_CORDB, LL_EVERYTHING, "EEC::IMD: pNewMD:0x%x for tok:0x%x (%s::%s)\n",
5948         pNewMD, tok, pszDebugClassName, pszDebugMethodName));
5949
5950     // Now we know the classification we can perform any classification specific initialization.
5951
5952     // The method desc is zero inited by the caller.
5953
5954     switch (Classification)
5955     {
5956     case mcNDirect:
5957         {
5958             // NDirect specific initialization.
5959             NDirectMethodDesc *pNewNMD = (NDirectMethodDesc*)pNewMD;
5960
5961             // Allocate writeable data
5962             pNewNMD->ndirect.m_pWriteableData.SetValue((NDirectWriteableData*)
5963                 AllocateFromHighFrequencyHeap(S_SIZE_T(sizeof(NDirectWriteableData))));
5964
5965 #ifdef HAS_NDIRECT_IMPORT_PRECODE 
5966             pNewNMD->ndirect.m_pImportThunkGlue.SetValue(Precode::Allocate(PRECODE_NDIRECT_IMPORT, pNewMD,
5967                 GetLoaderAllocator(), GetMemTracker())->AsNDirectImportPrecode());
5968 #else // !HAS_NDIRECT_IMPORT_PRECODE
5969             pNewNMD->GetNDirectImportThunkGlue()->Init(pNewNMD);
5970 #endif // !HAS_NDIRECT_IMPORT_PRECODE
5971
5972 #if defined(_TARGET_X86_)
5973             pNewNMD->ndirect.m_cbStackArgumentSize = 0xFFFF;
5974 #endif // defined(_TARGET_X86_)
5975
5976
5977             pNewNMD->GetWriteableData()->m_pNDirectTarget = pNewNMD->GetNDirectImportThunkGlue()->GetEntrypoint();
5978         }
5979         break;
5980
5981     case mcFCall:
5982         break;
5983
5984     case mcEEImpl:
5985         // For the Invoke method we will set a standard invoke method.
5986         BAD_FORMAT_NOTHROW_ASSERT(IsDelegate());
5987
5988         // For the asserts, either the pointer is NULL (since the class hasn't
5989         // been constructed yet), or we're in EnC mode, meaning that the class
5990         // does exist, but we may be re-assigning the field to point to an
5991         // updated MethodDesc
5992
5993         // It is not allowed for EnC to replace one of the runtime builtin methods
5994
5995         if (strcmp(pMethodName, "Invoke") == 0)
5996         {
5997             BAD_FORMAT_NOTHROW_ASSERT(((DelegateEEClass*)GetHalfBakedClass())->m_pInvokeMethod.IsNull());
5998             ((DelegateEEClass*)GetHalfBakedClass())->m_pInvokeMethod.SetValue(pNewMD);
5999         }
6000         else if (strcmp(pMethodName, "BeginInvoke") == 0)
6001         {
6002             BAD_FORMAT_NOTHROW_ASSERT(((DelegateEEClass*)GetHalfBakedClass())->m_pBeginInvokeMethod.IsNull());
6003             ((DelegateEEClass*)GetHalfBakedClass())->m_pBeginInvokeMethod.SetValue(pNewMD);
6004         }
6005         else if (strcmp(pMethodName, "EndInvoke") == 0)
6006         {
6007             BAD_FORMAT_NOTHROW_ASSERT(((DelegateEEClass*)GetHalfBakedClass())->m_pEndInvokeMethod.IsNull());
6008             ((DelegateEEClass*)GetHalfBakedClass())->m_pEndInvokeMethod.SetValue(pNewMD);
6009         }
6010         else
6011         {
6012             BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
6013         }
6014
6015         // StoredSig specific intialization
6016         {
6017             StoredSigMethodDesc *pNewSMD = (StoredSigMethodDesc*) pNewMD;;
6018             DWORD cSig;
6019             PCCOR_SIGNATURE pSig;
6020             if (FAILED(pIMDII->GetSigOfMethodDef(tok, &cSig, &pSig)))
6021             {
6022                 BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
6023             }
6024             pNewSMD->SetStoredMethodSig(pSig, cSig);
6025         }
6026         break;
6027
6028 #ifdef FEATURE_COMINTEROP
6029     case mcComInterop:
6030 #endif // FEATURE_COMINTEROP
6031     case mcIL:
6032         break;
6033
6034     case mcInstantiated:
6035 #ifdef EnC_SUPPORTED 
6036         if (fEnC)
6037         {
6038             // We reuse the instantiated methoddescs to get the slot
6039             InstantiatedMethodDesc* pNewIMD = (InstantiatedMethodDesc*) pNewMD;
6040             pNewIMD->SetupEnCAddedMethod();
6041         }
6042         else
6043 #endif // EnC_SUPPORTED
6044         {
6045             // Initialize the typical instantiation.
6046             InstantiatedMethodDesc* pNewIMD = (InstantiatedMethodDesc*) pNewMD;
6047             //data has the same lifetime as method table, use our allocator
6048             pNewIMD->SetupGenericMethodDefinition(pIMDII, GetLoaderAllocator(), GetMemTracker(), GetModule(),
6049                                                   tok);
6050         }
6051         break;
6052
6053     default:
6054         BAD_FORMAT_NOTHROW_ASSERT(!"Failed to set a method desc classification");
6055     }
6056
6057     // Check the method desc's classification.
6058     _ASSERTE(pNewMD->GetClassification() == Classification);
6059
6060     pNewMD->SetMemberDef(tok);
6061
6062     if (IsMdStatic(dwMemberAttrs))
6063         pNewMD->SetStatic();
6064
6065     // Set suppress unmanaged code access permission attribute
6066
6067     if (pNewMD->IsNDirect())
6068         pNewMD->ComputeSuppressUnmanagedCodeAccessAttr(pIMDII);
6069
6070 #ifdef _DEBUG 
6071     // Mark as many methods as synchronized as possible.
6072     //
6073     // Note that this can easily cause programs to deadlock, and that
6074     // should not be treated as a bug in the program.
6075
6076     static ConfigDWORD stressSynchronized;
6077     DWORD stressSynchronizedVal = stressSynchronized.val(CLRConfig::INTERNAL_stressSynchronized);
6078
6079     bool isStressSynchronized =  stressSynchronizedVal &&
6080         pNewMD->IsIL() && // Synchronized is not supported on Ecalls, NDirect method, etc
6081         // IsValueClass() and IsEnum() do not work for System.ValueType and System.Enum themselves
6082         ((g_pValueTypeClass != NULL && g_pEnumClass != NULL &&
6083           !IsValueClass()) || // Can not synchronize on byref "this"
6084           IsMdStatic(dwMemberAttrs)) && // IsStatic() blows up in _DEBUG as pNewMD is not fully inited
6085         g_pObjectClass != NULL; // Ignore Object:* since "this" could be a boxed object
6086
6087     // stressSynchronized=1 turns off the stress in the system domain to reduce
6088     // the chances of spurious deadlocks. Deadlocks in user code can still occur.
6089     // stressSynchronized=2 will probably cause more deadlocks, and is not recommended
6090     if (stressSynchronizedVal == 1 && GetAssembly()->IsSystem())
6091         isStressSynchronized = false;
6092
6093     if (IsMiSynchronized(dwImplFlags) || isStressSynchronized)
6094 #else // !_DEBUG
6095     if (IsMiSynchronized(dwImplFlags))
6096 #endif // !_DEBUG
6097         pNewMD->SetSynchronized();
6098
6099 #ifdef _DEBUG 
6100     pNewMD->m_pszDebugMethodName = (LPUTF8)pszDebugMethodName;
6101     pNewMD->m_pszDebugClassName  = (LPUTF8)pszDebugClassName;
6102     pNewMD->m_pDebugMethodTable.SetValue(GetHalfBakedMethodTable());
6103
6104     if (pszDebugMethodSignature == NULL)
6105         pNewMD->m_pszDebugMethodSignature = FormatSig(pNewMD,pNewMD->GetLoaderAllocator()->GetLowFrequencyHeap(),GetMemTracker());
6106     else
6107         pNewMD->m_pszDebugMethodSignature = pszDebugMethodSignature;
6108 #endif // _DEBUG
6109 } // MethodTableBuilder::InitMethodDesc
6110
6111 //*******************************************************************************
6112 //
6113 // Used by BuildMethodTable
6114 //
6115 VOID 
6116 MethodTableBuilder::AddMethodImplDispatchMapping(
6117     DispatchMapTypeID typeID,
6118     SLOT_INDEX        slotNumber,
6119     bmtMDMethod *     pImplMethod)
6120 {
6121     STANDARD_VM_CONTRACT;
6122
6123     MethodDesc * pMDImpl = pImplMethod->GetMethodDesc();
6124
6125     // Look for an existing entry in the map.
6126     DispatchMapBuilder::Iterator it(bmtVT->pDispatchMapBuilder);
6127     if (bmtVT->pDispatchMapBuilder->Find(typeID, slotNumber, it))
6128     {
6129         // Throw if this entry has already previously been MethodImpl'd.
6130         if (it.IsMethodImpl())
6131         {
6132             // NOTE: This is where we check for duplicate overrides. This is the easiest place to check
6133             //       because duplicate overrides could in fact have separate MemberRefs to the same
6134             //       member and so just comparing tokens at the very start would not be enough.
6135             if (it.GetTargetMD() != pMDImpl)
6136             {
6137                 BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MULTIPLEOVERRIDES, pMDImpl->GetMemberDef());
6138             }
6139         }
6140         // This is the first MethodImpl. That's ok.
6141         else
6142         {
6143             it.SetTarget(pMDImpl);
6144             it.SetIsMethodImpl();
6145         }
6146     }
6147     // A mapping for this interface method does not exist, so insert it.
6148     else
6149     {
6150         bmtVT->pDispatchMapBuilder->InsertMDMapping(
6151             typeID, 
6152             slotNumber, 
6153             pMDImpl, 
6154             TRUE);
6155     }
6156
6157     // Save the entry into the vtable as well, if it isn't an interface methodImpl
6158     if (typeID == DispatchMapTypeID::ThisClassID())
6159     {
6160         bmtVT->SetVirtualMethodImpl(slotNumber, pImplMethod);
6161     }
6162 } // MethodTableBuilder::AddMethodImplDispatchMapping
6163
6164 //*******************************************************************************
6165 VOID
6166 MethodTableBuilder::MethodImplCompareSignatures(
6167     bmtMethodHandle     hDecl,
6168     bmtMethodHandle     hImpl,
6169     DWORD               dwConstraintErrorCode)
6170 {
6171     CONTRACTL {
6172         STANDARD_VM_CHECK;
6173         PRECONDITION(!hDecl.IsNull());
6174         PRECONDITION(!hImpl.IsNull());
6175         PRECONDITION(TypeFromToken(hDecl.GetMethodSignature().GetToken()) == mdtMethodDef);
6176         PRECONDITION(TypeFromToken(hImpl.GetMethodSignature().GetToken()) == mdtMethodDef);
6177     } CONTRACTL_END;
6178
6179     const MethodSignature &declSig(hDecl.GetMethodSignature());
6180     const MethodSignature &implSig(hImpl.GetMethodSignature());
6181
6182     if (!MethodSignature::SignaturesEquivalent(declSig, implSig))
6183     {
6184         LOG((LF_CLASSLOADER, LL_INFO1000, "BADSIG placing MethodImpl: %x\n", declSig.GetToken()));
6185         BuildMethodTableThrowException(COR_E_TYPELOAD, IDS_CLASSLOAD_MI_BADSIGNATURE, declSig.GetToken());
6186     }
6187
6188     //now compare the method constraints
6189     if (!MetaSig::CompareMethodConstraints(&implSig.GetSubstitution(), implSig.GetModule(), implSig.GetToken(),
6190                                            &declSig.GetSubstitution(), declSig.GetModule(), declSig.GetToken()))
6191     {
6192         BuildMethodTableThrowException(dwConstraintErrorCode, implSig.GetToken());
6193     }
6194 }
6195
6196 //*******************************************************************************
6197 // We should have collected all the method impls. Cycle through them creating the method impl
6198 // structure that holds the information about which slots are overridden.
6199 VOID
6200 MethodTableBuilder::PlaceMethodImpls()
6201 {
6202     STANDARD_VM_CONTRACT;
6203
6204     if(bmtMethodImpl->pIndex == 0)
6205     {
6206         return;
6207     }
6208
6209     // Allocate some temporary storage. The number of overrides for a single method impl
6210     // cannot be greater then the number of vtable slots for classes. But for interfaces
6211     // it might contain overrides for other interface methods.
6212     DWORD dwMaxSlotSize = IsInterface() ? bmtMethod->dwNumberMethodImpls : bmtVT->cVirtualSlots;
6213
6214     DWORD * slots = new (&GetThread()->m_MarshalAlloc) DWORD[dwMaxSlotSize];
6215     RelativePointer<MethodDesc *> * replaced = new (&GetThread()->m_MarshalAlloc) RelativePointer<MethodDesc*>[dwMaxSlotSize];
6216
6217     DWORD iEntry = 0;
6218     bmtMDMethod * pCurImplMethod = bmtMethodImpl->GetImplementationMethod(iEntry);
6219
6220     DWORD slotIndex = 0;
6221
6222     // The impls are sorted according to the method descs for the body of the method impl.
6223     // Loop through the impls until the next body is found. When a single body
6224     // has been done move the slots implemented and method descs replaced into the storage
6225     // found on the body method desc.
6226     while (true)
6227     {   // collect information until we reach the next body
6228
6229         // Get the declaration part of the method impl. It will either be a token
6230         // (declaration is on this type) or a method desc.
6231         bmtMethodHandle hDeclMethod = bmtMethodImpl->GetDeclarationMethod(iEntry);
6232         if(hDeclMethod.IsMDMethod())
6233         {   
6234             // The declaration is on the type being built
6235             bmtMDMethod * pCurDeclMethod = hDeclMethod.AsMDMethod();
6236
6237             mdToken mdef = pCurDeclMethod->GetMethodSignature().GetToken();
6238             if (bmtMethodImpl->IsBody(mdef))
6239             {   // A method declared on this class cannot be both a decl and an impl
6240                 BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MULTIPLEOVERRIDES, mdef);
6241             }
6242
6243             if (IsInterface())
6244             {
6245                 // Throws
6246                 PlaceInterfaceDeclarationOnInterface(
6247                     hDeclMethod,
6248                     pCurImplMethod,
6249                     slots,              // Adds override to the slot and replaced arrays.
6250                     replaced,
6251                     &slotIndex,
6252                     dwMaxSlotSize);     // Increments count                
6253             }
6254             else
6255             {
6256                 // Throws
6257                 PlaceLocalDeclarationOnClass(
6258                     pCurDeclMethod,
6259                     pCurImplMethod,
6260                     slots,              // Adds override to the slot and replaced arrays.
6261                     replaced,
6262                     &slotIndex,
6263                     dwMaxSlotSize);     // Increments count
6264             }
6265         }
6266         else
6267         {
6268             bmtRTMethod * pCurDeclMethod = hDeclMethod.AsRTMethod();
6269
6270             if (IsInterface())
6271             {
6272                 // Throws
6273                 PlaceInterfaceDeclarationOnInterface(
6274                     hDeclMethod,
6275                     pCurImplMethod,
6276                     slots,              // Adds override to the slot and replaced arrays.
6277                     replaced,
6278                     &slotIndex,
6279                     dwMaxSlotSize);     // Increments count     
6280             }
6281             else
6282             {
6283                 // Do not use pDecl->IsInterface here as that asks the method table and the MT may not yet be set up.
6284                 if (pCurDeclMethod->GetOwningType()->IsInterface())
6285                 {
6286                     // Throws
6287                     PlaceInterfaceDeclarationOnClass(
6288                         pCurDeclMethod,
6289                         pCurImplMethod);
6290                 }
6291                 else
6292                 {
6293                     // Throws
6294                     PlaceParentDeclarationOnClass(
6295                         pCurDeclMethod,
6296                         pCurImplMethod,
6297                         slots,
6298                         replaced,
6299                         &slotIndex,
6300                         dwMaxSlotSize);        // Increments count
6301                 }
6302             }
6303         }
6304
6305         iEntry++;
6306
6307         if(iEntry == bmtMethodImpl->pIndex)
6308         {
6309             // We hit the end of the list so dump the current data and leave
6310             WriteMethodImplData(pCurImplMethod, slotIndex, slots, replaced);
6311             break;
6312         }
6313         else
6314         {
6315             bmtMDMethod * pNextImplMethod = bmtMethodImpl->GetImplementationMethod(iEntry);
6316
6317             if (pNextImplMethod != pCurImplMethod)
6318             {
6319                 // If we're moving on to a new body, dump the current data and reset the counter
6320                 WriteMethodImplData(pCurImplMethod, slotIndex, slots, replaced);
6321                 slotIndex = 0;
6322             }
6323
6324             pCurImplMethod = pNextImplMethod;
6325         }
6326     }  // while(next != NULL)
6327 } // MethodTableBuilder::PlaceMethodImpls
6328
6329 //*******************************************************************************
6330 VOID
6331 MethodTableBuilder::WriteMethodImplData(
6332     bmtMDMethod * pImplMethod, 
6333     DWORD         cSlots, 
6334     DWORD *       rgSlots, 
6335     RelativePointer<MethodDesc *> * rgDeclMD)
6336 {
6337     STANDARD_VM_CONTRACT;
6338     
6339     // Use the number of overrides to
6340     // push information on to the method desc. We store the slots that
6341     // are overridden and the method desc that is replaced. That way
6342     // when derived classes need to determine if the method is to be
6343     // overridden then it can check the name against the replaced
6344     // method desc not the bodies name.
6345     if (cSlots == 0)
6346     {
6347         //@TODO:NEWVTWORK: Determine methodImpl status so that we don't need this workaround.
6348         //@TODO:NEWVTWORK: This occurs when only interface decls are involved, since
6349         //@TODO:NEWVTWORK: these are stored in the dispatch map and not on the methoddesc.
6350     }
6351     else
6352     {
6353         MethodImpl * pImpl = pImplMethod->GetMethodDesc()->GetMethodImpl();
6354
6355         // Set the size of the info the MethodImpl needs to keep track of.
6356         pImpl->SetSize(GetLoaderAllocator()->GetHighFrequencyHeap(), GetMemTracker(), cSlots);
6357
6358         if (!IsInterface())
6359         {
6360             // If we are currently builting an interface, the slots here has no meaning and we can skip it
6361             // Sort the two arrays in slot index order
6362             // This is required in MethodImpl::FindSlotIndex and MethodImpl::Iterator as we'll be using 
6363             // binary search later
6364             for (DWORD i = 0; i < cSlots; i++)
6365             {
6366                 int min = i;
6367                 for (DWORD j = i + 1; j < cSlots; j++)
6368                 {
6369                     if (rgSlots[j] < rgSlots[min])
6370                     {
6371                         min = j;
6372                     }
6373                 }
6374
6375                 if (min != i)
6376                 {
6377                     MethodDesc * mTmp = rgDeclMD[i].GetValue();
6378                     rgDeclMD[i].SetValue(rgDeclMD[min].GetValue());
6379                     rgDeclMD[min].SetValue(mTmp);
6380
6381                     DWORD sTmp = rgSlots[i];
6382                     rgSlots[i] = rgSlots[min];
6383                     rgSlots[min] = sTmp;
6384                 }
6385             }
6386         }
6387
6388         // Go and set the method impl
6389         pImpl->SetData(rgSlots, rgDeclMD);
6390
6391         GetHalfBakedClass()->SetContainsMethodImpls();
6392     }
6393 } // MethodTableBuilder::WriteMethodImplData
6394
6395 //*******************************************************************************
6396 VOID
6397 MethodTableBuilder::PlaceLocalDeclarationOnClass(
6398     bmtMDMethod * pDecl, 
6399     bmtMDMethod * pImpl, 
6400     DWORD *       slots, 
6401     RelativePointer<MethodDesc *> * replaced,
6402     DWORD *       pSlotIndex,
6403     DWORD         dwMaxSlotSize)
6404 {
6405     CONTRACTL
6406     {
6407         STANDARD_VM_CHECK;
6408         PRECONDITION(CheckPointer(bmtVT->pDispatchMapBuilder));
6409         PRECONDITION(CheckPointer(pDecl));
6410         PRECONDITION(CheckPointer(pImpl));
6411     }
6412     CONTRACTL_END
6413
6414     if (!bmtProp->fNoSanityChecks)
6415     {
6416         ///////////////////////////////
6417         // Verify the signatures match
6418
6419         MethodImplCompareSignatures(
6420             pDecl,
6421             pImpl,
6422             IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_LOCAL_METHOD_IMPL);
6423
6424         ///////////////////////////////
6425         // Validate the method impl.
6426
6427         TestMethodImpl(
6428             bmtMethodHandle(pDecl),
6429             bmtMethodHandle(pImpl));
6430     }
6431
6432     // Don't allow overrides for any of the four special runtime implemented delegate methods
6433     if (IsDelegate())
6434     {
6435         LPCUTF8 strMethodName = pDecl->GetMethodSignature().GetName();
6436         if ((strcmp(strMethodName, COR_CTOR_METHOD_NAME) == 0) || 
6437             (strcmp(strMethodName, "Invoke")             == 0) || 
6438             (strcmp(strMethodName, "BeginInvoke")        == 0) || 
6439             (strcmp(strMethodName, "EndInvoke")          == 0))
6440         {
6441             BuildMethodTableThrowException(
6442                 IDS_CLASSLOAD_MI_CANNOT_OVERRIDE, 
6443                 pDecl->GetMethodSignature().GetToken());
6444         }
6445     }
6446
6447     ///////////////////
6448     // Add the mapping
6449
6450     // Call helper to add it. Will throw if decl is already MethodImpl'd
6451     CONSISTENCY_CHECK(pDecl->GetSlotIndex() == static_cast<SLOT_INDEX>(pDecl->GetMethodDesc()->GetSlot()));
6452     AddMethodImplDispatchMapping(
6453         DispatchMapTypeID::ThisClassID(), 
6454         pDecl->GetSlotIndex(), 
6455         pImpl);
6456
6457     // We implement this slot, record it
6458     ASSERT(*pSlotIndex < dwMaxSlotSize);
6459     slots[*pSlotIndex] = pDecl->GetSlotIndex();
6460     replaced[*pSlotIndex].SetValue(pDecl->GetMethodDesc());
6461
6462     // increment the counter
6463     (*pSlotIndex)++;
6464 } // MethodTableBuilder::PlaceLocalDeclarationOnClass
6465
6466 //*******************************************************************************
6467 VOID MethodTableBuilder::PlaceInterfaceDeclarationOnClass(
6468     bmtRTMethod *     pDecl,
6469     bmtMDMethod *     pImpl)
6470 {
6471     CONTRACTL {
6472         STANDARD_VM_CHECK;
6473         PRECONDITION(CheckPointer(pDecl));
6474         PRECONDITION(CheckPointer(pImpl));
6475         PRECONDITION(pDecl->GetMethodDesc()->IsInterface());
6476         PRECONDITION(CheckPointer(bmtVT->pDispatchMapBuilder));
6477     } CONTRACTL_END;
6478
6479     MethodDesc *  pDeclMD = pDecl->GetMethodDesc();
6480     MethodTable * pDeclMT = pDeclMD->GetMethodTable();
6481
6482     // Note that the fact that pDecl is non-NULL means that we found the
6483     // declaration token to be owned by a declared interface for this type.
6484
6485     if (!bmtProp->fNoSanityChecks)
6486     {
6487         ///////////////////////////////
6488         // Verify the signatures match
6489
6490         MethodImplCompareSignatures(
6491             pDecl,
6492             pImpl,
6493             IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_INTERFACE_METHOD_IMPL);
6494
6495         ///////////////////////////////
6496         // Validate the method impl.
6497
6498         TestMethodImpl(
6499             bmtMethodHandle(pDecl),
6500             bmtMethodHandle(pImpl));
6501     }
6502
6503     ///////////////////
6504     // Add the mapping
6505
6506     // Note that we need only one DispatchMapTypeID for this interface (though there might be more if there 
6507     // are duplicates). The first one is easy to get, but we could (in theory) use the last one or a random 
6508     // one.
6509     // Q: Why don't we have to place this method for all duplicate interfaces? Because VSD knows about 
6510     // duplicates and finds the right (latest) implementation for us - see 
6511     // code:MethodTable::MethodDataInterfaceImpl::PopulateNextLevel#ProcessAllDuplicates.
6512     UINT32 cInterfaceDuplicates;
6513     DispatchMapTypeID firstDispatchMapTypeID;
6514     ComputeDispatchMapTypeIDs(
6515         pDeclMT, 
6516         &pDecl->GetMethodSignature().GetSubstitution(), 
6517         &firstDispatchMapTypeID, 
6518         1, 
6519         &cInterfaceDuplicates);
6520     CONSISTENCY_CHECK(cInterfaceDuplicates >= 1);
6521     CONSISTENCY_CHECK(firstDispatchMapTypeID.IsImplementedInterface());
6522
6523     // Call helper to add it. Will throw if decl is already MethodImpl'd
6524     CONSISTENCY_CHECK(pDecl->GetSlotIndex() == static_cast<SLOT_INDEX>(pDecl->GetMethodDesc()->GetSlot()));
6525     AddMethodImplDispatchMapping(
6526         firstDispatchMapTypeID, 
6527         pDecl->GetSlotIndex(), 
6528         pImpl);
6529
6530     if (IsCompilationProcess())
6531     {
6532         //
6533         // Mark this interface as overridable. It is used to skip generation of
6534         // CCWs stubs during NGen (see code:MethodNeedsReverseComStub)
6535         //
6536         if (!IsMdFinal(pImpl->GetDeclAttrs()))
6537         {
6538             pDeclMT->GetWriteableDataForWrite()->SetIsOverridingInterface();
6539         }
6540     }
6541     
6542 #ifdef _DEBUG
6543     if (bmtInterface->dbg_fShouldInjectInterfaceDuplicates)
6544     {   // We injected interface duplicates
6545         
6546         // We have to MethodImpl all interface duplicates as all duplicates are 'declared on type' (see 
6547         // code:#InjectInterfaceDuplicates_ApproxInterfaces)
6548         DispatchMapTypeID * rgDispatchMapTypeIDs = (DispatchMapTypeID *)_alloca(sizeof(DispatchMapTypeID) * cInterfaceDuplicates);
6549         ComputeDispatchMapTypeIDs(
6550             pDeclMT, 
6551             &pDecl->GetMethodSignature().GetSubstitution(), 
6552             rgDispatchMapTypeIDs, 
6553             cInterfaceDuplicates, 
6554             &cInterfaceDuplicates);
6555         for (UINT32 nInterfaceDuplicate = 1; nInterfaceDuplicate < cInterfaceDuplicates; nInterfaceDuplicate++)
6556         {
6557             // Add MethodImpl record for each injected interface duplicate
6558             AddMethodImplDispatchMapping(
6559                 rgDispatchMapTypeIDs[nInterfaceDuplicate], 
6560                 pDecl->GetSlotIndex(), 
6561                 pImpl);
6562         }
6563     }
6564 #endif //_DEBUG
6565 } // MethodTableBuilder::PlaceInterfaceDeclarationOnClass
6566
6567 //*******************************************************************************
6568 VOID MethodTableBuilder::PlaceInterfaceDeclarationOnInterface(
6569     bmtMethodHandle hDecl, 
6570     bmtMDMethod   *pImpl, 
6571     DWORD *       slots, 
6572     RelativePointer<MethodDesc *> * replaced,
6573     DWORD *       pSlotIndex,
6574     DWORD         dwMaxSlotSize)
6575 {
6576     CONTRACTL {
6577         STANDARD_VM_CHECK;
6578         PRECONDITION(CheckPointer(pImpl));
6579         PRECONDITION(IsInterface());
6580         PRECONDITION(hDecl.GetMethodDesc()->IsInterface());
6581     } CONTRACTL_END;
6582
6583     MethodDesc *  pDeclMD = hDecl.GetMethodDesc();
6584
6585     if (!bmtProp->fNoSanityChecks)
6586     {
6587         ///////////////////////////////
6588         // Verify the signatures match
6589
6590         MethodImplCompareSignatures(
6591             hDecl,
6592             bmtMethodHandle(pImpl),
6593             IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_INTERFACE_METHOD_IMPL);
6594
6595         ///////////////////////////////
6596         // Validate the method impl.
6597
6598         TestMethodImpl(hDecl, bmtMethodHandle(pImpl));
6599     }
6600
6601     // We implement this slot, record it
6602     ASSERT(*pSlotIndex < dwMaxSlotSize);
6603     slots[*pSlotIndex] = hDecl.GetSlotIndex();
6604     replaced[*pSlotIndex].SetValue(pDeclMD);
6605
6606     // increment the counter
6607     (*pSlotIndex)++;
6608 } // MethodTableBuilder::PlaceInterfaceDeclarationOnInterface
6609
6610 //*******************************************************************************
6611 VOID
6612 MethodTableBuilder::PlaceParentDeclarationOnClass(
6613     bmtRTMethod * pDecl, 
6614     bmtMDMethod * pImpl, 
6615     DWORD *       slots, 
6616     RelativePointer<MethodDesc *> * replaced,
6617     DWORD *       pSlotIndex,
6618     DWORD         dwMaxSlotSize)
6619 {
6620     CONTRACTL {
6621         STANDARD_VM_CHECK;
6622         PRECONDITION(CheckPointer(pDecl));
6623         PRECONDITION(CheckPointer(pImpl));
6624         PRECONDITION(CheckPointer(bmtVT->pDispatchMapBuilder));
6625         PRECONDITION(CheckPointer(GetParentMethodTable()));
6626     } CONTRACTL_END;
6627
6628     MethodDesc * pDeclMD = pDecl->GetMethodDesc();
6629
6630     // Note that the fact that pDecl is non-NULL means that we found the
6631     // declaration token to be owned by a parent type.
6632
6633     if (!bmtProp->fNoSanityChecks)
6634     {
6635         /////////////////////////////////////////
6636         // Verify that the signatures match
6637
6638         MethodImplCompareSignatures(
6639             pDecl,
6640             pImpl,
6641             IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_PARENT_METHOD_IMPL);
6642
6643         ////////////////////////////////
6644         // Verify rules of method impls
6645
6646         TestMethodImpl(
6647             bmtMethodHandle(pDecl),
6648             bmtMethodHandle(pImpl));
6649     }
6650
6651     ///////////////////
6652     // Add the mapping
6653
6654     // Call helper to add it. Will throw if DECL is already MethodImpl'd
6655     AddMethodImplDispatchMapping(
6656         DispatchMapTypeID::ThisClassID(), 
6657         pDeclMD->GetSlot(), 
6658         pImpl);
6659
6660     // We implement this slot, record it
6661     ASSERT(*pSlotIndex < dwMaxSlotSize);
6662     slots[*pSlotIndex] = pDeclMD->GetSlot();
6663     replaced[*pSlotIndex].SetValue(pDeclMD);
6664
6665     // increment the counter
6666     (*pSlotIndex)++;
6667 } // MethodTableBuilder::PlaceParentDeclarationOnClass
6668
6669 //*******************************************************************************
6670 // This will validate that all interface methods that were matched during
6671 // layout also validate against type constraints.
6672
6673 VOID MethodTableBuilder::ValidateInterfaceMethodConstraints()
6674 {
6675     STANDARD_VM_CONTRACT;
6676
6677     DispatchMapBuilder::Iterator it(bmtVT->pDispatchMapBuilder);
6678     for (; it.IsValid(); it.Next())
6679     {
6680         if (it.GetTypeID() != DispatchMapTypeID::ThisClassID())
6681         {
6682             bmtRTType * pItf = bmtInterface->pInterfaceMap[it.GetTypeID().GetInterfaceNum()].GetInterfaceType();
6683
6684             // Grab the method token
6685             MethodTable * pMTItf = pItf->GetMethodTable();
6686             CONSISTENCY_CHECK(CheckPointer(pMTItf->GetMethodDescForSlot(it.GetSlotNumber())));
6687             mdMethodDef mdTok = pItf->GetMethodTable()->GetMethodDescForSlot(it.GetSlotNumber())->GetMemberDef();
6688
6689             // Default to the current module. The code immediately below determines if this
6690             // assumption is incorrect.
6691             Module *          pTargetModule          = GetModule();
6692
6693             // Get the module of the target method. Get it through the chunk to
6694             // avoid triggering the assert that MethodTable is non-NULL. It may
6695             // be null since it may belong to the type we're building right now.
6696             MethodDesc *      pTargetMD              = it.GetTargetMD();
6697
6698             // If pTargetMT is null, this indicates that the target MethodDesc belongs
6699             // to the current type. Otherwise, the MethodDesc MUST be owned by a parent
6700             // of the type we're building.
6701             BOOL              fTargetIsOwnedByParent = !pTargetMD->GetMethodTablePtr()->IsNull();        
6702             
6703             // If the method is owned by a parent, we need to use the parent's module,
6704             // and we must construct the substitution chain all the way up to the parent.
6705             const Substitution *pSubstTgt = NULL;
6706             if (fTargetIsOwnedByParent)
6707             {
6708                 CONSISTENCY_CHECK(CheckPointer(GetParentType()));
6709                 bmtRTType *pTargetType = bmtRTType::FindType(GetParentType(), pTargetMD->GetMethodTable());
6710                 pSubstTgt = &pTargetType->GetSubstitution();
6711                 pTargetModule = pTargetType->GetModule();
6712             }
6713
6714             // Now compare the method constraints.
6715             if (!MetaSig::CompareMethodConstraints(pSubstTgt,
6716                                                    pTargetModule,
6717                                                    pTargetMD->GetMemberDef(),
6718                                                    &pItf->GetSubstitution(),
6719                                                    pMTItf->GetModule(),
6720                                                    mdTok))
6721             {
6722                 LOG((LF_CLASSLOADER, LL_INFO1000,
6723                      "BADCONSTRAINTS on interface method implementation: %x\n", pTargetMD));
6724                 // This exception will be due to an implicit implementation, since explicit errors
6725                 // will be detected in MethodImplCompareSignatures (for now, anyway).
6726                 CONSISTENCY_CHECK(!it.IsMethodImpl());
6727                 DWORD idsError = it.IsMethodImpl() ?
6728                                  IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_INTERFACE_METHOD_IMPL :
6729                                  IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_IMPLICIT_IMPLEMENTATION;
6730                 if (fTargetIsOwnedByParent)
6731                 {
6732                     DefineFullyQualifiedNameForClass();
6733                     LPCUTF8 szClassName = GetFullyQualifiedNameForClassNestedAware(pTargetMD->GetMethodTable());
6734                     LPCUTF8 szMethodName = pTargetMD->GetName();
6735
6736                     CQuickBytes qb;
6737                     // allocate enough room for "<class>.<method>\0"
6738                     size_t cchFullName = strlen(szClassName) + 1 + strlen(szMethodName) + 1;
6739                     LPUTF8 szFullName = (LPUTF8) qb.AllocThrows(cchFullName);
6740                     strcpy_s(szFullName, cchFullName, szClassName);
6741                     strcat_s(szFullName, cchFullName, ".");
6742                     strcat_s(szFullName, cchFullName, szMethodName);
6743
6744                     BuildMethodTableThrowException(idsError, szFullName);
6745                 }
6746                 else
6747                 {
6748                     BuildMethodTableThrowException(idsError, pTargetMD->GetMemberDef());
6749                 }
6750             }
6751         }
6752     }
6753 } // MethodTableBuilder::ValidateInterfaceMethodConstraints
6754
6755 //*******************************************************************************
6756 // Used to allocate and initialize MethodDescs (both the boxed and unboxed entrypoints)
6757 VOID MethodTableBuilder::AllocAndInitMethodDescs()
6758 {
6759     STANDARD_VM_CONTRACT;
6760
6761     //
6762     // Go over all MethodDescs and create smallest number of MethodDescChunks possible.
6763     //
6764     // Iterate over all methods and start a new chunk only if:
6765     //  - Token range (upper 24 bits of the method token) has changed.
6766     //  - The maximum size of the chunk has been reached.
6767     //
6768
6769     int currentTokenRange = -1; // current token range
6770     SIZE_T sizeOfMethodDescs = 0; // current running size of methodDesc chunk
6771     int startIndex = 0; // start of the current chunk (index into bmtMethod array)
6772
6773     DeclaredMethodIterator it(*this);
6774     while (it.Next())
6775     {
6776         int tokenRange = GetTokenRange(it.Token());
6777
6778         // This code assumes that iterator returns tokens in ascending order. If this assumption does not hold, 
6779         // the code will still work with small performance penalty (method desc chunk layout will be less efficient).
6780         _ASSERTE(tokenRange >= currentTokenRange);
6781
6782         SIZE_T size = MethodDesc::GetBaseSize(GetMethodClassification(it->GetMethodType()));
6783
6784         // Add size of optional slots
6785
6786         if (it->GetMethodImplType() == METHOD_IMPL)
6787             size += sizeof(MethodImpl);
6788
6789         if (it->GetSlotIndex() >= bmtVT->cVtableSlots)
6790             size += sizeof(MethodDesc::NonVtableSlot); // slot
6791
6792         if (NeedsNativeCodeSlot(*it))
6793             size += sizeof(MethodDesc::NativeCodeSlot);
6794
6795         // See comment in AllocAndInitMethodDescChunk
6796         if (NeedsTightlyBoundUnboxingStub(*it))
6797         {
6798             size *= 2;
6799
6800             if (bmtGenerics->GetNumGenericArgs() == 0) {
6801                 size += sizeof(MethodDesc::NonVtableSlot);
6802             }
6803             else {
6804                 bmtVT->cVtableSlots++;
6805             }
6806         }
6807
6808         if (tokenRange != currentTokenRange ||
6809             sizeOfMethodDescs + size > MethodDescChunk::MaxSizeOfMethodDescs)
6810         {
6811             if (sizeOfMethodDescs != 0)
6812             {
6813                 AllocAndInitMethodDescChunk(startIndex, it.CurrentIndex() - startIndex, sizeOfMethodDescs);
6814                 startIndex = it.CurrentIndex();
6815             }
6816
6817             currentTokenRange = tokenRange;
6818             sizeOfMethodDescs = 0;
6819         }
6820
6821         sizeOfMethodDescs += size;
6822     }
6823
6824     if (sizeOfMethodDescs != 0)
6825     {
6826         AllocAndInitMethodDescChunk(startIndex, NumDeclaredMethods() - startIndex, sizeOfMethodDescs);
6827     }
6828 }
6829
6830 //*******************************************************************************
6831 // Allocates and initializes one method desc chunk.
6832 //
6833 // Arguments:
6834 //    startIndex - index of first method in bmtMethod array.
6835 //    count - number of methods in this chunk (contiguous region from startIndex)
6836 //    sizeOfMethodDescs - total expected size of MethodDescs in this chunk
6837 //
6838 // Used by AllocAndInitMethodDescs.
6839 //
6840 VOID MethodTableBuilder::AllocAndInitMethodDescChunk(COUNT_T startIndex, COUNT_T count, SIZE_T sizeOfMethodDescs)
6841 {
6842     CONTRACTL {
6843         STANDARD_VM_CHECK;
6844         PRECONDITION(sizeOfMethodDescs <= MethodDescChunk::MaxSizeOfMethodDescs);
6845     } CONTRACTL_END;
6846
6847     void * pMem = GetMemTracker()->Track(
6848         GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(TADDR) + sizeof(MethodDescChunk) + sizeOfMethodDescs)));
6849
6850     // Skip pointer to temporary entrypoints
6851     MethodDescChunk * pChunk = (MethodDescChunk *)((BYTE*)pMem + sizeof(TADDR));
6852
6853     COUNT_T methodDescCount = 0;
6854
6855     SIZE_T offset = sizeof(MethodDescChunk);
6856
6857 #ifdef _PREFAST_ 
6858 #pragma warning(push)
6859 #pragma warning(disable:22019) // Suppress PREFast warning about integer underflow
6860 #endif // _PREFAST_
6861     for (COUNT_T i = 0; i < count; i++)
6862 #ifdef _PREFAST_ 
6863 #pragma warning(pop)
6864 #endif // _PREFAST_
6865
6866     {
6867         bmtMDMethod * pMDMethod = (*bmtMethod)[static_cast<SLOT_INDEX>(startIndex + i)];
6868
6869         MethodDesc * pMD = (MethodDesc *)((BYTE *)pChunk + offset); 
6870
6871         pMD->SetChunkIndex(pChunk);
6872
6873         InitNewMethodDesc(pMDMethod, pMD);
6874
6875 #ifdef _PREFAST_ 
6876 #pragma warning(push)
6877 #pragma warning(disable:22018) // Suppress PREFast warning about integer underflow
6878 #endif // _PREFAST_
6879         offset += pMD->SizeOf();
6880 #ifdef _PREFAST_ 
6881 #pragma warning(pop)
6882 #endif // _PREFAST_
6883
6884         methodDescCount++;
6885
6886         // If we're a value class, we want to create duplicate slots
6887         // and MethodDescs for all methods in the vtable
6888         // section (i.e. not non-virtual instance methods or statics).
6889         // In the name of uniformity it would be much nicer
6890         // if we created _all_ value class BoxedEntryPointStubs at this point.
6891         // However, non-virtual instance methods only require unboxing
6892         // stubs in the rare case that we create a delegate to such a
6893         // method, and thus it would be inefficient to create them on
6894         // loading: after all typical structs will have many non-virtual
6895         // instance methods.
6896         //
6897         // Unboxing stubs for non-virtual instance methods are created
6898         // in code:MethodDesc::FindOrCreateAssociatedMethodDesc.
6899
6900         if (NeedsTightlyBoundUnboxingStub(pMDMethod))
6901         {
6902             MethodDesc * pUnboxedMD = (MethodDesc *)((BYTE *)pChunk + offset); 
6903
6904             //////////////////////////////////
6905             // Initialize the new MethodDesc
6906
6907             // <NICE> memcpy operations on data structures like MethodDescs are extremely fragile
6908             // and should not be used.  We should go to the effort of having proper constructors
6909             // in the MethodDesc class. </NICE>
6910
6911             memcpy(pUnboxedMD, pMD, pMD->SizeOf());
6912
6913             // Reset the chunk index
6914             pUnboxedMD->SetChunkIndex(pChunk);
6915
6916             if (bmtGenerics->GetNumGenericArgs() == 0) {
6917                 pUnboxedMD->SetHasNonVtableSlot();
6918             }
6919
6920             //////////////////////////////////////////////////////////
6921             // Modify the original MethodDesc to be an unboxing stub
6922
6923             pMD->SetIsUnboxingStub();
6924
6925             ////////////////////////////////////////////////////////////////////
6926             // Add the new MethodDesc to the non-virtual portion of the vtable
6927
6928             if (!bmtVT->AddUnboxedMethod(pMDMethod))
6929                 BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
6930
6931             pUnboxedMD->SetSlot(pMDMethod->GetUnboxedSlotIndex());
6932             pMDMethod->SetUnboxedMethodDesc(pUnboxedMD);
6933
6934             offset += pUnboxedMD->SizeOf();
6935             methodDescCount++;
6936         }
6937     }
6938     _ASSERTE(offset == sizeof(MethodDescChunk) + sizeOfMethodDescs);
6939
6940     pChunk->SetSizeAndCount((ULONG)sizeOfMethodDescs, methodDescCount);
6941
6942     GetHalfBakedClass()->AddChunk(pChunk);
6943 }
6944
6945 //*******************************************************************************
6946 BOOL
6947 MethodTableBuilder::NeedsTightlyBoundUnboxingStub(bmtMDMethod * pMDMethod)
6948 {
6949     STANDARD_VM_CONTRACT;
6950
6951     return IsValueClass() &&
6952            !IsMdStatic(pMDMethod->GetDeclAttrs()) &&
6953            IsMdVirtual(pMDMethod->GetDeclAttrs()) &&
6954            (pMDMethod->GetMethodType() != METHOD_TYPE_INSTANTIATED) &&
6955            !IsMdRTSpecialName(pMDMethod->GetDeclAttrs());
6956 }
6957
6958 //*******************************************************************************
6959 BOOL
6960 MethodTableBuilder::NeedsNativeCodeSlot(bmtMDMethod * pMDMethod)
6961 {
6962     LIMITED_METHOD_CONTRACT;
6963
6964
6965 #ifdef FEATURE_TIERED_COMPILATION
6966     // Keep in-sync with MethodDesc::IsEligibleForTieredCompilation()
6967     if (g_pConfig->TieredCompilation() &&
6968         (pMDMethod->GetMethodType() == METHOD_TYPE_NORMAL || pMDMethod->GetMethodType() == METHOD_TYPE_INSTANTIATED))
6969     {
6970         return TRUE;
6971     }
6972 #endif
6973
6974 #if defined(FEATURE_JIT_PITCHING)
6975     if ((CLRConfig::GetConfigValue(CLRConfig::INTERNAL_JitPitchEnabled) != 0) &&
6976         (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_JitPitchMemThreshold) != 0))
6977         return TRUE;
6978 #endif
6979
6980     return GetModule()->IsEditAndContinueEnabled();
6981 }
6982
6983 //*******************************************************************************
6984 BOOL
6985 MethodTableBuilder::MayBeRemotingIntercepted(bmtMDMethod * pMDMethod)
6986 {
6987     LIMITED_METHOD_CONTRACT;
6988
6989     return FALSE;
6990 }
6991
6992 //*******************************************************************************
6993 VOID
6994 MethodTableBuilder::AllocAndInitDictionary()
6995 {
6996     STANDARD_VM_CONTRACT;
6997
6998     // Allocate dictionary layout used by all compatible instantiations
6999
7000     if (bmtGenerics->fSharedByGenericInstantiations && !bmtGenerics->fContainsGenericVariables)
7001     {
7002         // We use the number of methods as a heuristic for the number of slots in the dictionary
7003         // attached to shared class method tables.
7004         // If there are no declared methods then we have no slots, and we will never do any token lookups
7005         //
7006         // Heuristics
7007         //  - Classes with a small number of methods (2-3) tend to be more likely to use new slots,
7008         //    i.e. further methods tend to reuse slots from previous methods.
7009         //      = treat all classes with only 2-3 methods as if they have an extra method.
7010         //  - Classes with more generic parameters tend to use more slots.
7011         //      = multiply by 1.5 for 2 params or more
7012
7013         DWORD numMethodsAdjusted =
7014             (bmtMethod->dwNumDeclaredNonAbstractMethods == 0)
7015             ? 0
7016             : (bmtMethod->dwNumDeclaredNonAbstractMethods < 3)
7017             ? 3
7018             : bmtMethod->dwNumDeclaredNonAbstractMethods;
7019
7020         _ASSERTE(bmtGenerics->GetNumGenericArgs() != 0);
7021         DWORD nTypeFactorBy2 = (bmtGenerics->GetNumGenericArgs() == 1)
7022                                ? 2
7023                                : 3;
7024
7025         DWORD estNumTypeSlots = (numMethodsAdjusted * nTypeFactorBy2 + 2) / 3;
7026         // estNumTypeSlots should fit in a WORD as long as we maintain the current
7027         // limit on the number of methods in a type (approx 2^16).
7028         _ASSERTE(FitsIn<WORD>(estNumTypeSlots));
7029         WORD numTypeSlots = static_cast<WORD>(estNumTypeSlots);
7030
7031         if (numTypeSlots > 0)
7032         {
7033             // Dictionary layout is an optional field on EEClass, so ensure the optional field descriptor has
7034             // been allocated.
7035             EnsureOptionalFieldsAreAllocated(GetHalfBakedClass(), m_pAllocMemTracker, GetLoaderAllocator()->GetLowFrequencyHeap());
7036             GetHalfBakedClass()->SetDictionaryLayout(DictionaryLayout::Allocate(numTypeSlots, bmtAllocator, m_pAllocMemTracker));
7037         }
7038     }
7039
7040 }
7041
7042 //*******************************************************************************
7043 //
7044 // Used by BuildMethodTable
7045 //
7046 // Compute the set of interfaces which are equivalent. Duplicates in the interface map
7047 // will be placed into different equivalence sets unless they participate in type equivalence.
7048 // This is a bit odd, but it turns out we only need to know about equivalence classes if
7049 // there is type equivalence involved in the interface, and not detecting, or detecting equivalence
7050 // in other cases does not result in differing behavior.
7051 // 
7052 // By restricting the reasons for having equivalence matches, we reduce the algorithm from one which
7053 // is O(n*n) best case to an algorithm which will typically execute something more like O(m*n) best case time 
7054 // where m is the number of generic interface (although still n*n in worst case). The assumption is that equivalent
7055 // and generic interfaces are relatively rare.
7056 VOID
7057 MethodTableBuilder::ComputeInterfaceMapEquivalenceSet()
7058 {
7059     STANDARD_VM_CONTRACT;
7060
7061     UINT32 nextEquivalenceSet = 1;
7062
7063     for (DWORD dwCurInterface = 0;
7064          dwCurInterface < bmtInterface->dwInterfaceMapSize;
7065          dwCurInterface++)
7066     {
7067         // Keep track of the current interface we are trying to calculate the equivalence set of
7068         bmtInterfaceEntry *     pCurItfEntry = &bmtInterface->pInterfaceMap[dwCurInterface];
7069         bmtRTType *             pCurItf      = pCurItfEntry->GetInterfaceType();
7070         MethodTable *           pCurItfMT    = pCurItf->GetMethodTable();
7071         const Substitution *    pCurItfSubst = &pCurItf->GetSubstitution();
7072
7073         UINT32 currentEquivalenceSet = 0;
7074
7075         // Only interfaces with type equivalence, or that are generic need to be compared for equivalence
7076         if (pCurItfMT->HasTypeEquivalence() || pCurItfMT->HasInstantiation())
7077         {
7078             for (DWORD dwCurInterfaceCompare = 0;
7079                  dwCurInterfaceCompare < dwCurInterface;
7080                  dwCurInterfaceCompare++)
7081             {
7082                 // Keep track of the current interface we are trying to calculate the equivalence set of
7083                 bmtInterfaceEntry *     pCompareItfEntry = &bmtInterface->pInterfaceMap[dwCurInterfaceCompare];
7084                 bmtRTType *             pCompareItf      = pCompareItfEntry->GetInterfaceType();
7085                 MethodTable *           pCompareItfMT    = pCompareItf->GetMethodTable();
7086                 const Substitution *    pCompareItfSubst = &pCompareItf->GetSubstitution();
7087
7088                 // Only interfaces with type equivalence, or that are generic need to be compared for equivalence
7089                 if (pCompareItfMT->HasTypeEquivalence() || pCompareItfMT->HasInstantiation())
7090                 {
7091                     if (MetaSig::CompareTypeDefsUnderSubstitutions(pCurItfMT,
7092                                                                    pCompareItfMT,
7093                                                                    pCurItfSubst,
7094                                                                    pCompareItfSubst,
7095                                                                    NULL))
7096                     {
7097                         currentEquivalenceSet = pCompareItfEntry->GetInterfaceEquivalenceSet();
7098                         // Use the equivalence set of the interface map entry we just found
7099                         pCurItfEntry->SetInterfaceEquivalenceSet(currentEquivalenceSet, true);
7100                         // Update the interface map entry we just found to indicate that it is part of an equivalence
7101                         // set with multiple entries.
7102                         pCompareItfEntry->SetInterfaceEquivalenceSet(currentEquivalenceSet, true);
7103                         break;
7104                     }
7105                 }
7106             }
7107         }
7108
7109         // If we did not find an equivalent interface above, use the next available equivalence set indicator
7110         if (currentEquivalenceSet == 0)
7111         {
7112             pCurItfEntry->SetInterfaceEquivalenceSet(nextEquivalenceSet, false);
7113             nextEquivalenceSet++;
7114         }
7115     }
7116 }
7117
7118 //*******************************************************************************
7119 //
7120 // Used by PlaceInterfaceMethods
7121 //
7122 // Given an interface in our interface map, and a particular method on that interface, place
7123 // a method from the parent types implementation of an equivalent interface into that method 
7124 // slot. Used by PlaceInterfaceMethods to make equivalent interface implementations have the 
7125 // same behavior as if the parent interface was implemented on this type instead of an equivalent interface.
7126 //
7127 // This logic is used in situations such as below. I and I' are equivalent interfaces
7128 //
7129 //#
7130 // class Base : I
7131 // {void I.Method() { } }
7132 // interface IOther : I' {}
7133 // class Derived : IOther
7134 // { virtual void Method() {}}
7135 //
7136 // We should Map I'.Method to Base.Method, not Derived.Method
7137 // 
7138 // Another example
7139 // class Base : I
7140 // { virtual void Method() }
7141 // interface IOther : I' {}
7142 // class Derived : IOther
7143 // { virtual void Method() {}}
7144 //
7145 // We should map I'.Method to Base.Method, not Derived.Method
7146 //
7147 // class Base : I
7148 // {void I.Method() { } }
7149 // class Derived : I'
7150 // {}
7151 //
7152 // We should Map I'.Method to Base.Method, and not throw TypeLoadException
7153 //
7154 #ifdef FEATURE_COMINTEROP
7155 VOID 
7156 MethodTableBuilder::PlaceMethodFromParentEquivalentInterfaceIntoInterfaceSlot(
7157     bmtInterfaceEntry::InterfaceSlotIterator & itfSlotIt, 
7158     bmtInterfaceEntry *                        pCurItfEntry, 
7159     DispatchMapTypeID **                       prgInterfaceDispatchMapTypeIDs, 
7160     DWORD                                      dwCurInterface)
7161 {
7162     STANDARD_VM_CONTRACT;
7163
7164     bmtRTMethod * pCurItfMethod = itfSlotIt->Decl().AsRTMethod();
7165
7166     if (itfSlotIt->Impl() != INVALID_SLOT_INDEX)
7167     {
7168         return;
7169     }
7170
7171     // For every equivalent interface entry that was actually implemented by parent, then look at equivalent method slot on that entry
7172     // and if it matches and has a slot implementation, then record and continue
7173     for (DWORD dwEquivalentInterface = 0;
7174          (dwEquivalentInterface < bmtInterface->dwInterfaceMapSize) && (itfSlotIt->Impl() == INVALID_SLOT_INDEX);
7175          dwEquivalentInterface++)
7176     {
7177         bmtInterfaceEntry *  pEquivItfEntry = &bmtInterface->pInterfaceMap[dwEquivalentInterface];
7178         bmtRTType *          pEquivItf      = pEquivItfEntry->GetInterfaceType();
7179         MethodTable *        pEquivItfMT    = pEquivItf->GetMethodTable();
7180         const Substitution * pEquivItfSubst = &pEquivItf->GetSubstitution();
7181         if (pEquivItfEntry->GetInterfaceEquivalenceSet() != pCurItfEntry->GetInterfaceEquivalenceSet())
7182         {
7183             // Not equivalent
7184             continue;
7185         }
7186         if (!pEquivItfEntry->IsImplementedByParent())
7187         {
7188             // Not implemented by parent
7189             continue;
7190         }
7191         
7192         WORD slot = static_cast<WORD>(itfSlotIt.CurrentIndex());
7193         BOOL fFound = FALSE;
7194
7195         // Determine which slot on the equivalent interface would map to the slot we are attempting to fill
7196         // in with an implementation.
7197         WORD otherMTSlot = GetEquivalentMethodSlot(pCurItfEntry->GetInterfaceType()->GetMethodTable(), 
7198                                                    pEquivItfEntry->GetInterfaceType()->GetMethodTable(), 
7199                                                    slot, 
7200                                                    &fFound);
7201
7202         if (fFound)
7203         {
7204             UINT32 cInterfaceDuplicates;
7205             if (*prgInterfaceDispatchMapTypeIDs == NULL)
7206             {
7207                 *prgInterfaceDispatchMapTypeIDs = 
7208                     new (GetStackingAllocator()) DispatchMapTypeID[bmtInterface->dwInterfaceMapSize];
7209             }
7210
7211             // Compute all TypeIDs for this interface (all duplicates in the interface map)
7212             ComputeDispatchMapTypeIDs(
7213                 pEquivItfMT, 
7214                 pEquivItfSubst, 
7215                 *prgInterfaceDispatchMapTypeIDs, 
7216                 bmtInterface->dwInterfaceMapSize, 
7217                 &cInterfaceDuplicates);
7218             // There cannot be more duplicates than number of interfaces
7219             _ASSERTE(cInterfaceDuplicates <= bmtInterface->dwInterfaceMapSize);
7220             _ASSERTE(cInterfaceDuplicates > 0);
7221             
7222             // NOTE: This override does not cache the resulting MethodData object
7223             MethodTable::MethodDataWrapper hParentData;
7224             hParentData = MethodTable::GetMethodData(
7225                     *prgInterfaceDispatchMapTypeIDs, 
7226                     cInterfaceDuplicates, 
7227                     pEquivItfMT, 
7228                     GetParentMethodTable());
7229
7230             SLOT_INDEX slotIndex = static_cast<SLOT_INDEX>
7231                 (hParentData->GetImplSlotNumber(static_cast<UINT32>(otherMTSlot)));
7232
7233             // Interface is implemented on parent abstract type and this particular slot was not implemented
7234             if (slotIndex == INVALID_SLOT_INDEX)
7235             {
7236                 continue;
7237             }
7238
7239             bmtMethodSlot & parentSlotImplementation = (*bmtParent->pSlotTable)[slotIndex];
7240             bmtMethodHandle & parentImplementation = parentSlotImplementation.Impl();
7241
7242             // Check to verify that the equivalent slot on the equivalent interface actually matches the method
7243             // on the current interface. If not, then the slot is not a match, and we should search other interfaces
7244             // for an implementation of the method.
7245             if (!MethodSignature::SignaturesEquivalent(pCurItfMethod->GetMethodSignature(), parentImplementation.GetMethodSignature()))
7246             {
7247                 continue;
7248             }
7249
7250             itfSlotIt->Impl() = slotIndex;
7251
7252             MethodDesc * pMD = hParentData->GetImplMethodDesc(static_cast<UINT32>(otherMTSlot));
7253
7254             DispatchMapTypeID dispatchMapTypeID =
7255                 DispatchMapTypeID::InterfaceClassID(dwCurInterface);
7256             bmtVT->pDispatchMapBuilder->InsertMDMapping(
7257                 dispatchMapTypeID, 
7258                 static_cast<UINT32>(itfSlotIt.CurrentIndex()), 
7259                 pMD, 
7260                 FALSE);
7261         }
7262     }
7263 } // MethodTableBuilder::PlaceMethodFromParentEquivalentInterfaceIntoInterfaceSlot
7264 #endif // FEATURE_COMINTEROP
7265
7266 //*******************************************************************************
7267 //
7268 // Used by BuildMethodTable
7269 //
7270 //
7271 // If we are a class, then there may be some unplaced vtable methods (which are by definition
7272 // interface methods, otherwise they'd already have been placed).  Place as many unplaced methods
7273 // as possible, in the order preferred by interfaces.  However, do not allow any duplicates - once
7274 // a method has been placed, it cannot be placed again - if we are unable to neatly place an interface,
7275 // create duplicate slots for it starting at dwCurrentDuplicateVtableSlot.  Fill out the interface
7276 // map for all interfaces as they are placed.
7277 //
7278 // If we are an interface, then all methods are already placed.  Fill out the interface map for
7279 // interfaces as they are placed.
7280 //
7281 // BEHAVIOUR (based on Partition II: 11.2, not including MethodImpls)
7282 //   C is current class, P is a parent class, I is the interface being implemented
7283 //
7284 //   FOREACH interface I implemented by this class C
7285 //     FOREACH method I::M
7286 //       IF I is EXPLICITLY implemented by C
7287 //         IF some method C::M matches I::M
7288 //           USE C::M as implementation for I::M
7289 //         ELIF we inherit a method P::M that matches I::M
7290 //           USE P::M as implementation for I::M
7291 //         ENDIF
7292 //       ELSE
7293 //         IF I::M lacks implementation
7294 //           IF some method C::M matches I::M
7295 //             USE C::M as implementation for I::M
7296 //           ELIF we inherit a method P::M that matches I::M
7297 //             USE P::M as implementation for I::M
7298 //           ELIF I::M was implemented by the parent type with method Parent::M
7299 //             USE Parent::M for the implementation of I::M // VSD does this by default if we really 
7300 //                                                           // implemented I on the parent type, but 
7301 //                                                           // equivalent interfaces need to make this 
7302 //                                                           // explicit
7303 //           ENDIF
7304 //         ENDIF
7305 //       ENDIF
7306 //     ENDFOR
7307 //   ENDFOR
7308 //
7309
7310 VOID
7311 MethodTableBuilder::PlaceInterfaceMethods()
7312 {
7313     STANDARD_VM_CONTRACT;
7314
7315     BOOL fParentInterface;
7316     DispatchMapTypeID * rgInterfaceDispatchMapTypeIDs = NULL;
7317
7318     for (DWORD dwCurInterface = 0;
7319          dwCurInterface < bmtInterface->dwInterfaceMapSize;
7320          dwCurInterface++)
7321     {
7322         // Default to being implemented by the current class
7323         fParentInterface = FALSE;
7324
7325         // Keep track of the current interface we are trying to place
7326         bmtInterfaceEntry *     pCurItfEntry = &bmtInterface->pInterfaceMap[dwCurInterface];
7327         bmtRTType *             pCurItf      = pCurItfEntry->GetInterfaceType();
7328         MethodTable *           pCurItfMT    = pCurItf->GetMethodTable();
7329         const Substitution *    pCurItfSubst = &pCurItf->GetSubstitution();
7330
7331         //
7332         // There are three reasons why an interface could be in the implementation list
7333         // 1. Inherited from parent
7334         // 2. Explicitly declared in the implements list
7335         // 3. Implicitly declared through the implements list of an explicitly declared interface
7336         //
7337         // The reason these cases need to be distinguished is that an inherited interface that is
7338         // also explicitly redeclared in the implements list must be fully reimplemented using the
7339         // virtual methods of this type (thereby using matching methods in this type that may have
7340         // a different slot than an inherited method, but hidden it by name & sig); however all
7341         // implicitly redeclared interfaces should not be fully reimplemented if they were also
7342         // inherited from the parent.
7343         //
7344         // Example:
7345         //   interface I1 : I2
7346         //   class A : I1
7347         //   class B : A, I1
7348         //
7349         // In this example I1 must be fully reimplemented on B, but B can inherit the implementation
7350         // of I2.
7351         //
7352
7353         if (pCurItfEntry->IsImplementedByParent())
7354         {
7355             if (!pCurItfEntry->IsDeclaredOnType())
7356             {
7357                 fParentInterface = TRUE;
7358             }
7359         }
7360
7361         bool fEquivalentInterfaceImplementedByParent = pCurItfEntry->IsImplementedByParent();
7362         bool fEquivalentInterfaceDeclaredOnType = pCurItfEntry->IsDeclaredOnType();
7363
7364         if (pCurItfEntry->InEquivalenceSetWithMultipleEntries())
7365         {
7366             for (DWORD dwEquivalentInterface = 0;
7367                  dwEquivalentInterface < bmtInterface->dwInterfaceMapSize;
7368                  dwEquivalentInterface++)
7369             {
7370                 bmtInterfaceEntry *     pEquivItfEntry = &bmtInterface->pInterfaceMap[dwEquivalentInterface];
7371                 if (pEquivItfEntry->GetInterfaceEquivalenceSet() != pCurItfEntry->GetInterfaceEquivalenceSet())
7372                 {
7373                     // Not equivalent
7374                     continue;
7375                 }
7376                 if (pEquivItfEntry->IsImplementedByParent())
7377                 {
7378                     fEquivalentInterfaceImplementedByParent = true;
7379                 }
7380                 if (pEquivItfEntry->IsDeclaredOnType())
7381                 {
7382                     fEquivalentInterfaceDeclaredOnType = true;
7383                 }
7384
7385                 if (fEquivalentInterfaceDeclaredOnType && fEquivalentInterfaceImplementedByParent)
7386                     break;
7387             }
7388         }
7389
7390         bool fParentInterfaceEquivalent = fEquivalentInterfaceImplementedByParent && !fEquivalentInterfaceDeclaredOnType;
7391
7392         CONSISTENCY_CHECK(!fParentInterfaceEquivalent || HasParent());
7393
7394         if (fParentInterfaceEquivalent)
7395         {
7396             // In the case the fParentInterface is TRUE, virtual overrides are enough and the interface
7397             // does not have to be explicitly (re)implemented. The only exception is if the parent is
7398             // abstract, in which case an inherited interface may not be fully implemented yet.
7399             // This is an optimization that allows us to skip the more expensive slot filling in below.
7400             // Note that the check here is for fParentInterface and not for fParentInterfaceEquivalent.
7401             // This is necessary as if the interface is not actually implemented on the parent type we will
7402             // need to fill in the slot table below.
7403             if (fParentInterface && !GetParentMethodTable()->IsAbstract())
7404             {
7405                 continue;
7406             }
7407
7408             {
7409                 // We will reach here in two cases.
7410                 // 1 .The parent is abstract and the interface has been declared on the parent,
7411                 // and possibly partially implemented, so we need to populate the
7412                 // bmtInterfaceSlotImpl table for this interface with the implementation slot
7413                 // information.
7414                 // 2 .The the interface has not been declared on the parent,
7415                 // but an equivalent interface has been. So we need to populate the
7416                 // bmtInterfaceSlotImpl table for this interface with the implementation slot
7417                 // information from one of the parent equivalent interfaces. We may or may not
7418                 // find implementations for all of the methods on the interface on the parent type.
7419                 // The parent type may or may not be abstract.
7420
7421                 MethodTable::MethodDataWrapper hParentData;
7422                 CONSISTENCY_CHECK(CheckPointer(GetParentMethodTable()));
7423                 
7424                 if (rgInterfaceDispatchMapTypeIDs == NULL)
7425                 {
7426                     rgInterfaceDispatchMapTypeIDs = 
7427                         new (GetStackingAllocator()) DispatchMapTypeID[bmtInterface->dwInterfaceMapSize];
7428                 }
7429                 
7430                 if (pCurItfEntry->IsImplementedByParent())
7431                 {
7432                     UINT32 cInterfaceDuplicates;
7433                     // Compute all TypeIDs for this interface (all duplicates in the interface map)
7434                     ComputeDispatchMapTypeIDs(
7435                         pCurItfMT, 
7436                         pCurItfSubst, 
7437                         rgInterfaceDispatchMapTypeIDs, 
7438                         bmtInterface->dwInterfaceMapSize, 
7439                         &cInterfaceDuplicates);
7440                     // There cannot be more duplicates than number of interfaces
7441                     _ASSERTE(cInterfaceDuplicates <= bmtInterface->dwInterfaceMapSize);
7442                     _ASSERTE(cInterfaceDuplicates > 0);
7443                     
7444                     //#InterfaceMap_UseParentInterfaceImplementations
7445                     // We rely on the fact that interface map of parent type is subset of this type (incl. 
7446                     // duplicates), see code:#InterfaceMap_SupersetOfParent
7447                     // NOTE: This override does not cache the resulting MethodData object
7448                     hParentData = MethodTable::GetMethodData(
7449                             rgInterfaceDispatchMapTypeIDs, 
7450                             cInterfaceDuplicates, 
7451                             pCurItfMT, 
7452                             GetParentMethodTable());
7453
7454                     bmtInterfaceEntry::InterfaceSlotIterator itfSlotIt =
7455                         pCurItfEntry->IterateInterfaceSlots(GetStackingAllocator());
7456                     for (; !itfSlotIt.AtEnd(); itfSlotIt.Next())
7457                     {
7458                         itfSlotIt->Impl() = static_cast<SLOT_INDEX>
7459                             (hParentData->GetImplSlotNumber(static_cast<UINT32>(itfSlotIt.CurrentIndex())));
7460                     }
7461                 }
7462 #ifdef FEATURE_COMINTEROP
7463                 else
7464                 {
7465                     // Iterate through the methods on the interface, and if they have a slot which was filled in
7466                     // on an equivalent interface inherited from the parent fill in the approrpriate slot.
7467                     // This code path is only used when there is an implicit implementation of an interface
7468                     // that was not implemented on a parent type, but there was an equivalent interface implemented
7469                     // on a parent type.
7470                     bmtInterfaceEntry::InterfaceSlotIterator itfSlotIt =
7471                         pCurItfEntry->IterateInterfaceSlots(GetStackingAllocator());
7472                     for (; !itfSlotIt.AtEnd(); itfSlotIt.Next())
7473                     {
7474                         PlaceMethodFromParentEquivalentInterfaceIntoInterfaceSlot(itfSlotIt, pCurItfEntry, &rgInterfaceDispatchMapTypeIDs, dwCurInterface);
7475                     }
7476                 }
7477 #endif // FEATURE_COMINTEROP
7478             }
7479         }
7480
7481 #ifdef FEATURE_COMINTEROP
7482         // WinRT types always use methodimpls to line up methods with interface implementations, so we do not want to allow implicit
7483         // interface implementations to kick in.   This can especially cause problems with redirected interfaces, where the underlying
7484         // runtimeclass doesn't actually implement the interfaces we claim it does.   For example, a WinRT class which implements both
7485         // IVector<int> and ICalculator will be projected as implementing IList<int> and ICalculator.  In this case, we do not want the
7486         // ICalculator Add(int) method to get lined up with the ICollection<int> Add method, since that will cause us to dispatch to the
7487         // wrong underlying COM interface.
7488         //
7489         // There are a special WinRT types in mscorlib (notably DisposableRuntimeClass) which do implement interfaces in the normal way
7490         // so we skip this check for them.  (Note that we can't use a methodimpl directly in mscorlib, since ComImport classes are
7491         // forbidden from having implementation code by the C# compiler).
7492         if (GetHalfBakedClass()->IsProjectedFromWinRT() && !GetModule()->IsSystem())
7493         {
7494             continue;
7495         }
7496 #endif // FEATURE_COMINTEROP
7497
7498         // For each method declared in this interface
7499         bmtInterfaceEntry::InterfaceSlotIterator itfSlotIt =
7500             pCurItfEntry->IterateInterfaceSlots(GetStackingAllocator());
7501         for (; !itfSlotIt.AtEnd(); ++itfSlotIt)
7502         {
7503             if (fParentInterfaceEquivalent)
7504             {
7505                 if (itfSlotIt->Impl() != INVALID_SLOT_INDEX)
7506                 {   // If this interface is not explicitly declared on this class, and the interface slot has already been
7507                     // given an implementation, then the only way to provide a new implementation is through an override
7508                     // or through a MethodImpl. This is necessary in addition to the continue statement before this for
7509                     // loop because an abstract interface can still have a partial implementation and it is necessary to
7510                     // skip those interface slots that have already been satisfied.
7511                     continue;
7512                 }
7513             }
7514
7515             BOOL                    fFoundMatchInBuildingClass = FALSE;
7516             bmtInterfaceSlotImpl &  curItfSlot = *itfSlotIt;
7517             bmtRTMethod *           pCurItfMethod = curItfSlot.Decl().AsRTMethod();
7518             const MethodSignature & curItfMethodSig = pCurItfMethod->GetMethodSignature();
7519
7520             //
7521             // First, try to find the method explicitly declared in our class
7522             //
7523
7524             DeclaredMethodIterator methIt(*this);
7525             while (methIt.Next())
7526             {
7527                 // Note that non-publics can legally be exposed via an interface, but only
7528                 // through methodImpls.
7529                 if (IsMdVirtual(methIt.Attrs()) && IsMdPublic(methIt.Attrs()))
7530                 {
7531 #ifdef _DEBUG 
7532                     if(GetHalfBakedClass()->m_fDebuggingClass && g_pConfig->ShouldBreakOnMethod(methIt.Name()))
7533                         CONSISTENCY_CHECK_MSGF(false, ("BreakOnMethodName: '%s' ", methIt.Name()));
7534 #endif // _DEBUG
7535
7536                     if (pCurItfMethod->GetMethodSignature().Equivalent(methIt->GetMethodSignature()))
7537                     {
7538                         fFoundMatchInBuildingClass = TRUE;
7539                         curItfSlot.Impl() = methIt->GetSlotIndex();
7540
7541                         DispatchMapTypeID dispatchMapTypeID =
7542                             DispatchMapTypeID::InterfaceClassID(dwCurInterface);
7543                         bmtVT->pDispatchMapBuilder->InsertMDMapping(
7544                             dispatchMapTypeID, 
7545                             static_cast<UINT32>(itfSlotIt.CurrentIndex()), 
7546                             methIt->GetMethodDesc(),
7547                             FALSE);
7548
7549                         break;
7550                     }
7551                 }
7552             } // end ... try to find method
7553
7554             //
7555             // The ECMA CLR spec states that a type will inherit interface implementations
7556             // and that explicit re-declaration of an inherited interface will try to match
7557             // only newslot methods with methods in the re-declared interface (note that
7558             // this also takes care of matching against unsatisfied interface methods in
7559             // the abstract parent type scenario).
7560             //
7561             // So, if the interface was not declared on a parent and we haven't found a
7562             // newslot method declared on this type as a match, search all remaining
7563             // public virtual methods (including overrides declared on this type) for a
7564             // match.
7565             //
7566             // Please see bug VSW577403 and VSW593884 for details of this breaking change.
7567             //
7568             if (!fFoundMatchInBuildingClass &&
7569                 !fEquivalentInterfaceImplementedByParent)
7570             {
7571                 if (HasParent())
7572                 {
7573                     // Iterate backward through the parent's method table. This is important to 
7574                     // find the most derived method.
7575                     bmtParentInfo::Iterator parentMethodIt = bmtParent->IterateSlots();
7576                     parentMethodIt.ResetToEnd();
7577                     while (parentMethodIt.Prev())
7578                     {
7579                         bmtRTMethod * pCurParentMethod = parentMethodIt->Decl().AsRTMethod();
7580                         DWORD dwAttrs = pCurParentMethod->GetDeclAttrs();
7581                         if (!IsMdVirtual(dwAttrs) || !IsMdPublic(dwAttrs))
7582                         {   // Only match mdPublic mdVirtual methods for interface implementation
7583                             continue;
7584                         }
7585
7586                         if (curItfMethodSig.Equivalent(pCurParentMethod->GetMethodSignature()))
7587                         {
7588                             fFoundMatchInBuildingClass = TRUE;
7589                             curItfSlot.Impl() = pCurParentMethod->GetSlotIndex();
7590
7591                             DispatchMapTypeID dispatchMapTypeID =
7592                                 DispatchMapTypeID::InterfaceClassID(dwCurInterface);
7593                             bmtVT->pDispatchMapBuilder->InsertMDMapping(
7594                                 dispatchMapTypeID, 
7595                                 static_cast<UINT32>(itfSlotIt.CurrentIndex()), 
7596                                 pCurParentMethod->GetMethodDesc(), 
7597                                 FALSE);
7598
7599                             break;
7600                         }
7601                     } // end ... try to find parent method
7602                 }
7603             }
7604
7605             // For type equivalent interfaces that had an equivalent interface implemented by their parent
7606             // and where the previous logic to fill in the method based on the virtual mappings on the type have
7607             // failed, we should attempt to get the mappings from the equivalent interfaces declared on parent types
7608             // of the type we are currently building.
7609 #ifdef FEATURE_COMINTEROP
7610             if (!fFoundMatchInBuildingClass && fEquivalentInterfaceImplementedByParent && !pCurItfEntry->IsImplementedByParent())
7611             {
7612                 PlaceMethodFromParentEquivalentInterfaceIntoInterfaceSlot(itfSlotIt, pCurItfEntry, &rgInterfaceDispatchMapTypeIDs, dwCurInterface);
7613             }
7614 #endif
7615         }
7616     }
7617 } // MethodTableBuilder::PlaceInterfaceMethods
7618
7619
7620 //*******************************************************************************
7621 //
7622 // Used by BuildMethodTable
7623 //
7624 // Place static fields
7625 //
7626 VOID MethodTableBuilder::PlaceRegularStaticFields()
7627 {
7628     STANDARD_VM_CONTRACT;
7629
7630     DWORD i;
7631
7632     LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Placing statics for %s\n", this->GetDebugClassName()));
7633
7634     //
7635     // Place gc refs and value types first, as they need to have handles created for them.
7636     // (Placing them together allows us to easily create the handles when Restoring the class,
7637     // and when initializing new DLS for the class.)
7638     //
7639
7640     DWORD   dwCumulativeStaticFieldPos = 0 ;
7641     DWORD   dwCumulativeStaticGCFieldPos = 0;
7642     DWORD   dwCumulativeStaticBoxFieldPos = 0;
7643
7644     // We don't need to do any calculations for the gc refs or valuetypes, as they're
7645     // guaranteed to be aligned in ModuleStaticsInfo
7646     bmtFP->NumRegularStaticFieldsOfSize[LOG2_PTRSIZE] -=
7647         bmtFP->NumRegularStaticGCBoxedFields + bmtFP->NumRegularStaticGCPointerFields;
7648
7649     // Place fields, largest first, padding so that each group is aligned to its natural size
7650     for (i = MAX_LOG2_PRIMITIVE_FIELD_SIZE; (signed int) i >= 0; i--)
7651     {
7652         // Fields of this size start at the next available location
7653         bmtFP->RegularStaticFieldStart[i] = dwCumulativeStaticFieldPos;
7654         dwCumulativeStaticFieldPos += (bmtFP->NumRegularStaticFieldsOfSize[i] << i);
7655
7656         // Reset counters for the loop after this one
7657         bmtFP->NumRegularStaticFieldsOfSize[i]    = 0;
7658     }
7659
7660
7661     if (dwCumulativeStaticFieldPos > FIELD_OFFSET_LAST_REAL_OFFSET)
7662         BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
7663
7664     DWORD dwNumHandleStatics = bmtFP->NumRegularStaticGCBoxedFields + bmtFP->NumRegularStaticGCPointerFields;
7665     if (!FitsIn<WORD>(dwNumHandleStatics))
7666     {   // Overflow.
7667         BuildMethodTableThrowException(IDS_EE_TOOMANYFIELDS);
7668     }
7669     SetNumHandleRegularStatics(static_cast<WORD>(dwNumHandleStatics));
7670
7671     if (!FitsIn<WORD>(bmtFP->NumRegularStaticGCBoxedFields))
7672     {   // Overflow.
7673         BuildMethodTableThrowException(IDS_EE_TOOMANYFIELDS);
7674     }
7675     SetNumBoxedRegularStatics(static_cast<WORD>(bmtFP->NumRegularStaticGCBoxedFields));
7676
7677     // Tell the module to give us the offsets we'll be using and commit space for us
7678     // if necessary
7679     DWORD dwNonGCOffset, dwGCOffset;
7680     GetModule()->GetOffsetsForRegularStaticData(bmtInternal->pType->GetTypeDefToken(),
7681                                                 bmtProp->fDynamicStatics,
7682                                                 GetNumHandleRegularStatics(), dwCumulativeStaticFieldPos,
7683                                                 &dwGCOffset, &dwNonGCOffset);
7684
7685     // Allocate boxed statics first ("x << LOG2_PTRSIZE" is equivalent to "x * sizeof(void *)")
7686     dwCumulativeStaticGCFieldPos = bmtFP->NumRegularStaticGCBoxedFields<<LOG2_PTRSIZE;
7687
7688     FieldDesc *pFieldDescList = GetApproxFieldDescListRaw();
7689     // Place static fields
7690     for (i = 0; i < bmtEnumFields->dwNumStaticFields - bmtEnumFields->dwNumThreadStaticFields; i++)
7691     {
7692         FieldDesc * pCurField   = &pFieldDescList[bmtEnumFields->dwNumInstanceFields+i];
7693         DWORD dwLog2FieldSize   = (DWORD)(DWORD_PTR&)pCurField->m_pMTOfEnclosingClass; // log2(field size)
7694         DWORD dwOffset          = (DWORD) pCurField->m_dwOffset; // offset or type of field
7695
7696         switch (dwOffset)
7697         {
7698         case FIELD_OFFSET_UNPLACED_GC_PTR:
7699             // Place GC reference static field
7700             pCurField->SetOffset(dwCumulativeStaticGCFieldPos + dwGCOffset);
7701             dwCumulativeStaticGCFieldPos += 1<<LOG2_PTRSIZE;
7702             LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Field placed at GC offset 0x%x\n", pCurField->GetOffset_NoLogging()));
7703
7704             break;
7705
7706         case FIELD_OFFSET_VALUE_CLASS:
7707             // Place boxed GC reference static field
7708             pCurField->SetOffset(dwCumulativeStaticBoxFieldPos + dwGCOffset);
7709             dwCumulativeStaticBoxFieldPos += 1<<LOG2_PTRSIZE;
7710             LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Field placed at GC offset 0x%x\n", pCurField->GetOffset_NoLogging()));
7711
7712             break;
7713
7714         case FIELD_OFFSET_UNPLACED:
7715             // Place non-GC static field
7716             pCurField->SetOffset(bmtFP->RegularStaticFieldStart[dwLog2FieldSize] +
7717                                  (bmtFP->NumRegularStaticFieldsOfSize[dwLog2FieldSize] << dwLog2FieldSize) +
7718                                  dwNonGCOffset);
7719             bmtFP->NumRegularStaticFieldsOfSize[dwLog2FieldSize]++;
7720             LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Field placed at non GC offset 0x%x\n", pCurField->GetOffset_NoLogging()));
7721             break;
7722
7723         default:
7724             // RVA field
7725             break;
7726         }
7727
7728         LOG((LF_CLASSLOADER, LL_INFO1000000, "Offset of %s: %i\n", pCurField->m_debugName, pCurField->GetOffset_NoLogging()));
7729     }
7730
7731     if (bmtProp->fDynamicStatics)
7732     {
7733         _ASSERTE(dwNonGCOffset == 0 ||  // no statics at all
7734                  dwNonGCOffset == DomainLocalModule::DynamicEntry::GetOffsetOfDataBlob()); // We need space to point to the GC statics
7735         bmtProp->dwNonGCRegularStaticFieldBytes = dwCumulativeStaticFieldPos;
7736     }
7737     else
7738     {
7739         bmtProp->dwNonGCRegularStaticFieldBytes = 0; // Non dynamics shouldnt be using this
7740     }
7741     LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Static field bytes needed (0 is normal for non dynamic case)%i\n", bmtProp->dwNonGCRegularStaticFieldBytes));
7742 }
7743
7744
7745 VOID MethodTableBuilder::PlaceThreadStaticFields()
7746 {
7747     STANDARD_VM_CONTRACT;
7748
7749     DWORD i;
7750
7751     LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Placing ThreadStatics for %s\n", this->GetDebugClassName()));
7752
7753     //
7754     // Place gc refs and value types first, as they need to have handles created for them.
7755     // (Placing them together allows us to easily create the handles when Restoring the class,
7756     // and when initializing new DLS for the class.)
7757     //
7758
7759     DWORD   dwCumulativeStaticFieldPos = 0 ;
7760     DWORD   dwCumulativeStaticGCFieldPos = 0;
7761     DWORD   dwCumulativeStaticBoxFieldPos = 0;
7762
7763     // We don't need to do any calculations for the gc refs or valuetypes, as they're
7764     // guaranteed to be aligned in ModuleStaticsInfo
7765     bmtFP->NumThreadStaticFieldsOfSize[LOG2_PTRSIZE] -=
7766         bmtFP->NumThreadStaticGCBoxedFields + bmtFP->NumThreadStaticGCPointerFields;
7767
7768     // Place fields, largest first, padding so that each group is aligned to its natural size
7769     for (i = MAX_LOG2_PRIMITIVE_FIELD_SIZE; (signed int) i >= 0; i--)
7770     {
7771         // Fields of this size start at the next available location
7772         bmtFP->ThreadStaticFieldStart[i] = dwCumulativeStaticFieldPos;
7773         dwCumulativeStaticFieldPos += (bmtFP->NumThreadStaticFieldsOfSize[i] << i);
7774
7775         // Reset counters for the loop after this one
7776         bmtFP->NumThreadStaticFieldsOfSize[i]    = 0;
7777     }
7778
7779
7780     if (dwCumulativeStaticFieldPos > FIELD_OFFSET_LAST_REAL_OFFSET)
7781         BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
7782
7783     DWORD dwNumHandleStatics = bmtFP->NumThreadStaticGCBoxedFields + bmtFP->NumThreadStaticGCPointerFields;
7784     if (!FitsIn<WORD>(dwNumHandleStatics))
7785     {   // Overflow.
7786         BuildMethodTableThrowException(IDS_EE_TOOMANYFIELDS);
7787     }
7788
7789     SetNumHandleThreadStatics(static_cast<WORD>(dwNumHandleStatics));
7790
7791     if (!FitsIn<WORD>(bmtFP->NumThreadStaticGCBoxedFields))
7792     {   // Overflow.
7793         BuildMethodTableThrowException(IDS_EE_TOOMANYFIELDS);
7794     }
7795
7796     SetNumBoxedThreadStatics(static_cast<WORD>(bmtFP->NumThreadStaticGCBoxedFields));
7797
7798     // Tell the module to give us the offsets we'll be using and commit space for us
7799     // if necessary
7800     DWORD dwNonGCOffset, dwGCOffset;
7801
7802     GetModule()->GetOffsetsForThreadStaticData(bmtInternal->pType->GetTypeDefToken(),
7803                                                bmtProp->fDynamicStatics,
7804                                                GetNumHandleThreadStatics(), dwCumulativeStaticFieldPos,
7805                                                &dwGCOffset, &dwNonGCOffset);
7806
7807     // Allocate boxed statics first ("x << LOG2_PTRSIZE" is equivalent to "x * sizeof(void *)")
7808     dwCumulativeStaticGCFieldPos = bmtFP->NumThreadStaticGCBoxedFields<<LOG2_PTRSIZE;
7809
7810     FieldDesc *pFieldDescList = GetHalfBakedClass()->GetFieldDescList();
7811     // Place static fields
7812     for (i = 0; i < bmtEnumFields->dwNumThreadStaticFields; i++)
7813     {
7814         FieldDesc * pCurField   = &pFieldDescList[bmtEnumFields->dwNumInstanceFields + bmtEnumFields->dwNumStaticFields - bmtEnumFields->dwNumThreadStaticFields + i];
7815         DWORD dwLog2FieldSize   = (DWORD)(DWORD_PTR&)pCurField->m_pMTOfEnclosingClass; // log2(field size)
7816         DWORD dwOffset          = (DWORD) pCurField->m_dwOffset; // offset or type of field
7817
7818         switch (dwOffset)
7819         {
7820         case FIELD_OFFSET_UNPLACED_GC_PTR:
7821             // Place GC reference static field
7822             pCurField->SetOffset(dwCumulativeStaticGCFieldPos + dwGCOffset);
7823             dwCumulativeStaticGCFieldPos += 1<<LOG2_PTRSIZE;
7824             LOG((LF_CLASSLOADER, LL_INFO10000, "THREAD STATICS: Field placed at GC offset 0x%x\n", pCurField->GetOffset_NoLogging()));
7825
7826             break;
7827
7828         case FIELD_OFFSET_VALUE_CLASS:
7829             // Place boxed GC reference static field
7830             pCurField->SetOffset(dwCumulativeStaticBoxFieldPos + dwGCOffset);
7831             dwCumulativeStaticBoxFieldPos += 1<<LOG2_PTRSIZE;
7832             LOG((LF_CLASSLOADER, LL_INFO10000, "THREAD STATICS: Field placed at GC offset 0x%x\n", pCurField->GetOffset_NoLogging()));
7833
7834             break;
7835
7836         case FIELD_OFFSET_UNPLACED:
7837             // Place non-GC static field
7838             pCurField->SetOffset(bmtFP->ThreadStaticFieldStart[dwLog2FieldSize] +
7839                                  (bmtFP->NumThreadStaticFieldsOfSize[dwLog2FieldSize] << dwLog2FieldSize) +
7840                                  dwNonGCOffset);
7841             bmtFP->NumThreadStaticFieldsOfSize[dwLog2FieldSize]++;
7842             LOG((LF_CLASSLOADER, LL_INFO10000, "THREAD STATICS: Field placed at non GC offset 0x%x\n", pCurField->GetOffset_NoLogging()));
7843             break;
7844
7845         default:
7846             // RVA field
7847             break;
7848         }
7849
7850         LOG((LF_CLASSLOADER, LL_INFO1000000, "Offset of %s: %i\n", pCurField->m_debugName, pCurField->GetOffset_NoLogging()));
7851     }
7852
7853     if (bmtProp->fDynamicStatics)
7854     {
7855         _ASSERTE(dwNonGCOffset == 0 ||  // no thread statics at all
7856                  dwNonGCOffset == ThreadLocalModule::DynamicEntry::GetOffsetOfDataBlob()); // We need space to point to the GC statics
7857         bmtProp->dwNonGCThreadStaticFieldBytes = dwCumulativeStaticFieldPos;
7858     }
7859     else
7860     {
7861         bmtProp->dwNonGCThreadStaticFieldBytes = 0; // Non dynamics shouldnt be using this
7862     }
7863     LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: ThreadStatic field bytes needed (0 is normal for non dynamic case)%i\n", bmtProp->dwNonGCThreadStaticFieldBytes));
7864 }
7865
7866 //*******************************************************************************
7867 //
7868 // Used by BuildMethodTable
7869 //
7870 // Place instance fields
7871 //
7872 VOID    MethodTableBuilder::PlaceInstanceFields(MethodTable ** pByValueClassCache)
7873 {
7874     STANDARD_VM_CONTRACT;
7875
7876
7877     DWORD i;
7878
7879         //===============================================================
7880         // BEGIN: Place instance fields
7881         //===============================================================
7882
7883         FieldDesc *pFieldDescList = GetHalfBakedClass()->GetFieldDescList();
7884         DWORD   dwCumulativeInstanceFieldPos;
7885
7886         // Instance fields start right after the parent
7887         dwCumulativeInstanceFieldPos    = HasParent() ? GetParentMethodTable()->GetNumInstanceFieldBytes() : 0;
7888
7889         DWORD dwOffsetBias = 0;
7890 #ifdef FEATURE_64BIT_ALIGNMENT
7891         // On platforms where the alignment of 64-bit primitives is a requirement (but we're not guaranteed
7892         // this implicitly by the GC) field offset 0 is actually not 8-byte aligned in reference classes.
7893         // That's because all such platforms are currently 32-bit and the 4-byte MethodTable pointer pushes us
7894         // out of alignment. Ideally we'd solve this by arranging to have the object header allocated at a
7895         // 4-byte offset from an 8-byte boundary, but this is difficult to achieve for objects allocated on
7896         // the large object heap (which actually requires headers to be 8-byte aligned).
7897         //
7898         // So we adjust dwCumulativeInstanceFieldPos to account for the MethodTable* and our alignment
7899         // calculations will automatically adjust and add padding as necessary. We need to remove this
7900         // adjustment when setting the field offset in the field desc, however, since the rest of the system
7901         // expects that value to not include the MethodTable*.
7902         //
7903         // This happens only for reference classes: value type field 0 really does lie at offset 0 for unboxed
7904         // value types. We deal with boxed value types by allocating their headers mis-aligned (luckily for us
7905         // value types can never get large enough to allocate on the LOH). 
7906         if (!IsValueClass())
7907         {
7908             dwOffsetBias = sizeof(MethodTable*);
7909             dwCumulativeInstanceFieldPos += dwOffsetBias;
7910         }
7911 #endif // FEATURE_64BIT_ALIGNMENT
7912
7913 #ifdef FEATURE_READYTORUN
7914         if (NeedsAlignedBaseOffset())
7915         {
7916             // READYTORUN: FUTURE: Use the minimum possible alignment, reduce padding when inheriting within same bubble
7917             DWORD dwAlignment = DATA_ALIGNMENT;
7918 #ifdef FEATURE_64BIT_ALIGNMENT
7919             if (GetHalfBakedClass()->IsAlign8Candidate())
7920                 dwAlignment = 8;
7921 #endif
7922             dwCumulativeInstanceFieldPos = (DWORD)ALIGN_UP(dwCumulativeInstanceFieldPos, dwAlignment);
7923         }
7924 #endif // FEATURE_READYTORUN
7925
7926         // place small fields first if the parent have a number of field bytes that is not aligned
7927         if (!IS_ALIGNED(dwCumulativeInstanceFieldPos, DATA_ALIGNMENT))
7928         {
7929             for (i = 0; i < MAX_LOG2_PRIMITIVE_FIELD_SIZE; i++) {
7930                 DWORD j;
7931
7932                 if (IS_ALIGNED(dwCumulativeInstanceFieldPos, 1<<(i+1)))
7933                     continue;
7934
7935                 // check whether there are any bigger fields
7936                 for (j = i + 1; j <= MAX_LOG2_PRIMITIVE_FIELD_SIZE; j++) {
7937                     if (bmtFP->NumInstanceFieldsOfSize[j] != 0)
7938                         break;
7939                 }
7940                 // nothing to gain if there are no bigger fields
7941                 // (the subsequent loop will place fields from large to small fields)
7942                 if (j > MAX_LOG2_PRIMITIVE_FIELD_SIZE)
7943                     break;
7944
7945                 // check whether there are any small enough fields
7946                 for (j = i; (signed int) j >= 0; j--) {
7947                     if (bmtFP->NumInstanceFieldsOfSize[j] != 0)
7948                         break;
7949                     // TODO: since we will refuse to place GC references we should filter them out here.
7950                     // otherwise the "back-filling" process stops completely.
7951                     // (PlaceInstanceFields)
7952                     // the following code would fix the issue (a replacement for the code above this comment):
7953                     // if (bmtFP->NumInstanceFieldsOfSize[j] != 0 &&
7954                     //     (j != LOG2SLOT || bmtFP->NumInstanceFieldsOfSize[j] > bmtFP->NumInstanceGCPointerFields))
7955                     // {
7956                     //     break;
7957                     // }
7958
7959                 }
7960                 // nothing to play with if there are no smaller fields
7961                 if ((signed int) j < 0)
7962                     break;
7963                 // eventually go back and use the smaller field as filling
7964                 i = j;
7965
7966                 CONSISTENCY_CHECK(bmtFP->NumInstanceFieldsOfSize[i] != 0);
7967
7968                 j = bmtFP->FirstInstanceFieldOfSize[i];
7969
7970                 // Avoid reordering of gcfields
7971                 if (i == LOG2SLOT) {
7972                     for ( ; j < bmtEnumFields->dwNumInstanceFields; j++) {
7973                         if ((pFieldDescList[j].GetOffset_NoLogging() == FIELD_OFFSET_UNPLACED) &&
7974                             ((DWORD_PTR&)pFieldDescList[j].m_pMTOfEnclosingClass == (size_t)i))
7975                             break;
7976                     }
7977
7978                     // out of luck - can't reorder gc fields
7979                     if (j >= bmtEnumFields->dwNumInstanceFields)
7980                         break;
7981                 }
7982
7983                 // Place the field
7984                 dwCumulativeInstanceFieldPos = (DWORD)ALIGN_UP(dwCumulativeInstanceFieldPos, 1 << i);
7985
7986                 pFieldDescList[j].SetOffset(dwCumulativeInstanceFieldPos - dwOffsetBias);
7987                 dwCumulativeInstanceFieldPos += (1 << i);
7988
7989                 // We've placed this field now, so there is now one less of this size field to place
7990                 if (--bmtFP->NumInstanceFieldsOfSize[i] == 0)
7991                     continue;
7992
7993                 // We are done in this round if we haven't picked the first field
7994                 if (bmtFP->FirstInstanceFieldOfSize[i] != j)
7995                     continue;
7996
7997                 // Update FirstInstanceFieldOfSize[i] to point to the next such field
7998                 for (j = j+1; j < bmtEnumFields->dwNumInstanceFields; j++)
7999                 {
8000                     // The log of the field size is stored in the method table
8001                     if ((DWORD_PTR&)pFieldDescList[j].m_pMTOfEnclosingClass == (size_t)i)
8002                     {
8003                         bmtFP->FirstInstanceFieldOfSize[i] = j;
8004                         break;
8005                     }
8006                 }
8007                 _ASSERTE(j < bmtEnumFields->dwNumInstanceFields);
8008             }
8009         }
8010
8011         // Place fields, largest first
8012         for (i = MAX_LOG2_PRIMITIVE_FIELD_SIZE; (signed int) i >= 0; i--)
8013         {
8014             if (bmtFP->NumInstanceFieldsOfSize[i] == 0)
8015                 continue;
8016
8017             // Align instance fields if we aren't already
8018 #ifdef FEATURE_64BIT_ALIGNMENT
8019             DWORD dwDataAlignment = 1 << i;
8020 #else
8021             DWORD dwDataAlignment = min(1 << i, DATA_ALIGNMENT);
8022 #endif
8023             dwCumulativeInstanceFieldPos = (DWORD)ALIGN_UP(dwCumulativeInstanceFieldPos, dwDataAlignment);
8024
8025             // Fields of this size start at the next available location
8026             bmtFP->InstanceFieldStart[i] = dwCumulativeInstanceFieldPos;
8027             dwCumulativeInstanceFieldPos += (bmtFP->NumInstanceFieldsOfSize[i] << i);
8028
8029             // Reset counters for the loop after this one
8030             bmtFP->NumInstanceFieldsOfSize[i]  = 0;
8031         }
8032
8033
8034         // Make corrections to reserve space for GC Pointer Fields
8035         //
8036         // The GC Pointers simply take up the top part of the region associated
8037         // with fields of that size (GC pointers can be 64 bit on certain systems)
8038         if (bmtFP->NumInstanceGCPointerFields)
8039         {
8040             bmtFP->GCPointerFieldStart = bmtFP->InstanceFieldStart[LOG2SLOT] - dwOffsetBias;
8041             bmtFP->InstanceFieldStart[LOG2SLOT] = bmtFP->InstanceFieldStart[LOG2SLOT] + (bmtFP->NumInstanceGCPointerFields << LOG2SLOT);
8042             bmtFP->NumInstanceGCPointerFields = 0;     // reset to zero here, counts up as pointer slots are assigned below
8043         }
8044
8045         // Place instance fields - be careful not to place any already-placed fields
8046         for (i = 0; i < bmtEnumFields->dwNumInstanceFields; i++)
8047         {
8048             DWORD dwFieldSize   = (DWORD)(DWORD_PTR&)pFieldDescList[i].m_pMTOfEnclosingClass;
8049             DWORD dwOffset;
8050
8051             dwOffset = pFieldDescList[i].GetOffset_NoLogging();
8052
8053             // Don't place already-placed fields
8054             if ((dwOffset == FIELD_OFFSET_UNPLACED || dwOffset == FIELD_OFFSET_UNPLACED_GC_PTR || dwOffset == FIELD_OFFSET_VALUE_CLASS))
8055             {
8056                 if (dwOffset == FIELD_OFFSET_UNPLACED_GC_PTR)
8057                 {
8058                     pFieldDescList[i].SetOffset(bmtFP->GCPointerFieldStart + (bmtFP->NumInstanceGCPointerFields << LOG2SLOT));
8059                     bmtFP->NumInstanceGCPointerFields++;
8060                 }
8061                 else if (pFieldDescList[i].IsByValue() == FALSE) // it's a regular field
8062                 {
8063                     pFieldDescList[i].SetOffset(bmtFP->InstanceFieldStart[dwFieldSize] + (bmtFP->NumInstanceFieldsOfSize[dwFieldSize] << dwFieldSize) - dwOffsetBias);
8064                     bmtFP->NumInstanceFieldsOfSize[dwFieldSize]++;
8065                 }
8066             }
8067         }
8068
8069         DWORD dwNumGCPointerSeries;
8070         // Save Number of pointer series
8071         if (bmtFP->NumInstanceGCPointerFields)
8072             dwNumGCPointerSeries = bmtParent->NumParentPointerSeries + 1;
8073         else
8074             dwNumGCPointerSeries = bmtParent->NumParentPointerSeries;
8075
8076         // Place by value class fields last
8077         // Update the number of GC pointer series
8078         for (i = 0; i < bmtEnumFields->dwNumInstanceFields; i++)
8079         {
8080             if (pFieldDescList[i].IsByValue())
8081             {
8082                 MethodTable * pByValueMT = pByValueClassCache[i];
8083
8084                     // value classes could have GC pointers in them, which need to be pointer-size aligned
8085                     // so do this if it has not been done already
8086
8087 #if !defined(_WIN64) && (DATA_ALIGNMENT > 4) 
8088                 dwCumulativeInstanceFieldPos = (DWORD)ALIGN_UP(dwCumulativeInstanceFieldPos,
8089                     (pByValueMT->GetNumInstanceFieldBytes() >= DATA_ALIGNMENT) ? DATA_ALIGNMENT : sizeof(void*));
8090 #else // !(!defined(_WIN64) && (DATA_ALIGNMENT > 4))
8091 #ifdef FEATURE_64BIT_ALIGNMENT
8092                 if (pByValueMT->RequiresAlign8())
8093                     dwCumulativeInstanceFieldPos = (DWORD)ALIGN_UP(dwCumulativeInstanceFieldPos, 8);
8094                 else
8095 #endif // FEATURE_64BIT_ALIGNMENT
8096                     dwCumulativeInstanceFieldPos = (DWORD)ALIGN_UP(dwCumulativeInstanceFieldPos, sizeof(void*));
8097 #endif // !(!defined(_WIN64) && (DATA_ALIGNMENT > 4))
8098
8099                 pFieldDescList[i].SetOffset(dwCumulativeInstanceFieldPos - dwOffsetBias);
8100                 dwCumulativeInstanceFieldPos += pByValueMT->GetAlignedNumInstanceFieldBytes();
8101
8102                 // Add pointer series for by-value classes
8103                 dwNumGCPointerSeries += pByValueMT->ContainsPointers() ?
8104                     (DWORD)CGCDesc::GetCGCDescFromMT(pByValueMT)->GetNumSeries() : 0;
8105             }
8106         }
8107
8108             // Can be unaligned
8109         DWORD dwNumInstanceFieldBytes = dwCumulativeInstanceFieldPos - dwOffsetBias;
8110
8111         if (IsValueClass())
8112         {
8113                  // Like C++ we enforce that there can be no 0 length structures.
8114                 // Thus for a value class with no fields, we 'pad' the length to be 1
8115             if (dwNumInstanceFieldBytes == 0)
8116                 dwNumInstanceFieldBytes = 1;
8117
8118                 // The JITs like to copy full machine words,
8119                 //  so if the size is bigger than a void* round it up to minAlign
8120                 // and if the size is smaller than void* round it up to next power of two
8121             unsigned minAlign;
8122
8123 #ifdef FEATURE_64BIT_ALIGNMENT
8124             if (GetHalfBakedClass()->IsAlign8Candidate()) {
8125                 minAlign = 8;
8126             }
8127             else
8128 #endif // FEATURE_64BIT_ALIGNMENT
8129             if (dwNumInstanceFieldBytes > sizeof(void*)) {
8130                 minAlign = sizeof(void*);
8131             }
8132             else {
8133                 minAlign = 1;
8134                 while (minAlign < dwNumInstanceFieldBytes)
8135                     minAlign *= 2;
8136             }
8137
8138             dwNumInstanceFieldBytes = (dwNumInstanceFieldBytes + minAlign-1) & ~(minAlign-1);
8139         }
8140
8141         if (dwNumInstanceFieldBytes > FIELD_OFFSET_LAST_REAL_OFFSET) {
8142             BuildMethodTableThrowException(IDS_CLASSLOAD_FIELDTOOLARGE);
8143         }
8144
8145         bmtFP->NumInstanceFieldBytes = dwNumInstanceFieldBytes;
8146
8147         bmtFP->NumGCPointerSeries = dwNumGCPointerSeries;
8148
8149         //===============================================================
8150         // END: Place instance fields
8151         //===============================================================
8152 }
8153
8154 //*******************************************************************************
8155 // this accesses the field size which is temporarily stored in m_pMTOfEnclosingClass
8156 // during class loading. Don't use any other time
8157 DWORD MethodTableBuilder::GetFieldSize(FieldDesc *pFD)
8158 {
8159     STATIC_CONTRACT_NOTHROW;
8160     STATIC_CONTRACT_GC_NOTRIGGER;
8161     STATIC_CONTRACT_FORBID_FAULT;
8162
8163         // We should only be calling this while this class is being built.
8164     _ASSERTE(GetHalfBakedMethodTable() == 0);
8165     BAD_FORMAT_NOTHROW_ASSERT(! pFD->IsByValue() || HasExplicitFieldOffsetLayout());
8166
8167     if (pFD->IsByValue())
8168         return (DWORD)(DWORD_PTR&)(pFD->m_pMTOfEnclosingClass);
8169     return (1 << (DWORD)(DWORD_PTR&)(pFD->m_pMTOfEnclosingClass));
8170 }
8171
8172 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
8173 // checks whether the struct is enregisterable.
8174 void MethodTableBuilder::SystemVAmd64CheckForPassStructInRegister()
8175 {
8176     STANDARD_VM_CONTRACT;
8177
8178     // This method should be called for valuetypes only
8179     _ASSERTE(IsValueClass());
8180
8181     TypeHandle th(GetHalfBakedMethodTable());
8182
8183     if (th.IsTypeDesc())
8184     {
8185         // Not an enregisterable managed structure.
8186         return;
8187     }
8188
8189     DWORD totalStructSize = bmtFP->NumInstanceFieldBytes;
8190
8191     // If num of bytes for the fields is bigger than CLR_SYSTEMV_MAX_STRUCT_BYTES_TO_PASS_IN_REGISTERS
8192     // pass through stack
8193     if (totalStructSize > CLR_SYSTEMV_MAX_STRUCT_BYTES_TO_PASS_IN_REGISTERS)
8194     {
8195         LOG((LF_JIT, LL_EVERYTHING, "**** SystemVAmd64CheckForPassStructInRegister: struct %s is too big to pass in registers (%d bytes)\n",
8196                this->GetDebugClassName(), totalStructSize));
8197         return;
8198     }
8199
8200     const bool useNativeLayout = false;
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         // All the above tests passed. It's registers passed struct!
8206         GetHalfBakedMethodTable()->SetRegPassedStruct();
8207
8208         StoreEightByteClassification(&helper);
8209     }
8210 }
8211
8212 // checks whether the struct is enregisterable.
8213 void MethodTableBuilder::SystemVAmd64CheckForPassNativeStructInRegister()
8214 {
8215     STANDARD_VM_CONTRACT;
8216     DWORD totalStructSize = 0;
8217
8218     // If not a native value type, return.
8219     if (!IsValueClass())
8220     {
8221         return;
8222     }
8223
8224     totalStructSize = GetLayoutInfo()->GetNativeSize();
8225
8226     // If num of bytes for the fields is bigger than CLR_SYSTEMV_MAX_STRUCT_BYTES_TO_PASS_IN_REGISTERS
8227     // pass through stack
8228     if (totalStructSize > CLR_SYSTEMV_MAX_STRUCT_BYTES_TO_PASS_IN_REGISTERS)
8229     {
8230         LOG((LF_JIT, LL_EVERYTHING, "**** SystemVAmd64CheckForPassNativeStructInRegister: struct %s is too big to pass in registers (%d bytes)\n",
8231             this->GetDebugClassName(), totalStructSize));
8232         return;
8233     }
8234
8235     _ASSERTE(HasLayout());
8236
8237     // Classify the native layout for this struct.
8238     const bool useNativeLayout = true;
8239     // Iterate through the fields and make sure they meet requirements to pass in registers
8240     SystemVStructRegisterPassingHelper helper((unsigned int)totalStructSize);
8241     if (GetHalfBakedMethodTable()->ClassifyEightBytes(&helper, 0, 0, useNativeLayout))
8242     {
8243         GetLayoutInfo()->SetNativeStructPassedInRegisters();
8244     }
8245 }
8246
8247 // Store the eightbyte classification into the EEClass
8248 void MethodTableBuilder::StoreEightByteClassification(SystemVStructRegisterPassingHelper* helper)
8249 {
8250     EEClass* eeClass = GetHalfBakedMethodTable()->GetClass();
8251     LoaderAllocator* pAllocator = MethodTableBuilder::GetLoaderAllocator();
8252     AllocMemTracker* pamTracker = MethodTableBuilder::GetMemTracker();
8253     EnsureOptionalFieldsAreAllocated(eeClass, pamTracker, pAllocator->GetLowFrequencyHeap());
8254     eeClass->SetEightByteClassification(helper->eightByteCount, helper->eightByteClassifications, helper->eightByteSizes);
8255 }
8256
8257 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
8258
8259 //---------------------------------------------------------------------------------------
8260 //
8261 // make sure that no object fields are overlapped incorrectly and define the
8262 // GC pointer series for the class. We are assuming that this class will always be laid out within
8263 // its enclosing class by the compiler in such a way that offset 0 will be the correct alignment
8264 // for object ref fields so we don't need to try to align it
8265 // 
8266 VOID 
8267 MethodTableBuilder::HandleExplicitLayout(
8268     MethodTable ** pByValueClassCache)
8269 {
8270     STANDARD_VM_CONTRACT;
8271
8272
8273     // Instance slice size is the total size of an instance, and is calculated as
8274     // the field whose offset and size add to the greatest number.
8275     UINT instanceSliceSize = 0;
8276     DWORD firstObjectOverlapOffset = ((DWORD)(-1));
8277
8278
8279     UINT i;
8280     for (i = 0; i < bmtMetaData->cFields; i++)
8281     {
8282         FieldDesc *pFD = bmtMFDescs->ppFieldDescList[i];
8283         if (pFD == NULL || pFD->IsStatic())
8284         {
8285             continue;
8286         }
8287
8288         UINT fieldExtent = 0;
8289         if (!ClrSafeInt<UINT>::addition(pFD->GetOffset_NoLogging(), GetFieldSize(pFD), fieldExtent))
8290         {
8291             BuildMethodTableThrowException(COR_E_OVERFLOW);
8292         }
8293
8294         if (fieldExtent > instanceSliceSize)
8295         {
8296             instanceSliceSize = fieldExtent;
8297         }
8298     }
8299
8300     CQuickBytes qb;
8301     PREFIX_ASSUME(sizeof(BYTE) == 1);
8302     BYTE *pFieldLayout = (BYTE*) qb.AllocThrows(instanceSliceSize * sizeof(BYTE));
8303     for (i=0; i < instanceSliceSize; i++)
8304     {
8305         pFieldLayout[i] = empty;
8306     }
8307
8308     // go through each field and look for invalid layout
8309     // (note that we are more permissive than what Ecma allows. We only disallow the minimum set necessary to
8310     // close security holes.)
8311     //
8312     // This is what we implment:
8313     //
8314     // 1. Verify that every OREF is on a valid alignment
8315     // 2. Verify that OREFs only overlap with other OREFs.
8316     // 3. If an OREF does overlap with another OREF, the class is marked unverifiable.
8317     // 4. If an overlap of any kind occurs, the class will be marked NotTightlyPacked (affects ValueType.Equals()).
8318     //
8319     char emptyObject[sizeof(void*)];
8320     char isObject[sizeof(void*)];
8321     for (i = 0; i < sizeof(void*); i++)
8322     {
8323         emptyObject[i] = empty;
8324         isObject[i]    = oref;
8325     }
8326
8327
8328     ExplicitClassTrust explicitClassTrust;
8329
8330     UINT valueClassCacheIndex = ((UINT)(-1));
8331     UINT badOffset = 0;
8332     FieldDesc * pFD = NULL;
8333     for (i = 0; i < bmtMetaData->cFields; i++)
8334     {
8335         // Note about this loop body:
8336         //
8337         // This loop is coded to make it as hard as possible to allow a field to be trusted when it shouldn't.
8338         //
8339         // Every path in this loop body must lead to an explicit decision as to whether the field nonoverlaps,
8340         // overlaps in a verifiable fashion, overlaps in a nonverifiable fashion or overlaps in a completely illegal fashion.
8341         //
8342         // It must call fieldTrust.SetTrust() with the appropriate result. If you don't call it, fieldTrust's destructor
8343         // will intentionally default to kNone and mark the entire class illegal.
8344         //
8345         // If your result is anything but kNone (class is illegal), you must also explicitly "continue" the loop.
8346         // There is a "break" at end of this loop body that will abort the loop if you don't do this. And
8347         // if you don't finish iterating through all the fields, this function will automatically mark the entire
8348         // class illegal. This rule is a vestige of an earlier version of this function.
8349
8350         // This object's dtor will aggregate the trust decision for this field into the trust level for the class as a whole.
8351         ExplicitFieldTrustHolder fieldTrust(&explicitClassTrust);
8352
8353         pFD = bmtMFDescs->ppFieldDescList[i];
8354         if (pFD == NULL || pFD->IsStatic())
8355         {
8356             fieldTrust.SetTrust(ExplicitFieldTrust::kNonOverLayed);
8357             continue;
8358         }
8359
8360         // "i" indexes all fields, valueClassCacheIndex indexes non-static fields only. Don't get them confused!
8361         valueClassCacheIndex++;
8362
8363         if (CorTypeInfo::IsObjRef(pFD->GetFieldType()))
8364         {
8365             // Check that the ref offset is pointer aligned
8366             if ((pFD->GetOffset_NoLogging() & ((ULONG)sizeof(OBJECTREF) - 1)) != 0)
8367             {
8368                 badOffset = pFD->GetOffset_NoLogging();
8369                 fieldTrust.SetTrust(ExplicitFieldTrust::kNone);
8370
8371                 // If we got here, OREF field was not pointer aligned. THROW.
8372                 break;
8373             }
8374             // check if overlaps another object
8375             if (memcmp((void *)&pFieldLayout[pFD->GetOffset_NoLogging()], (void *)isObject, sizeof(isObject)) == 0)
8376             {
8377                 // If we got here, an OREF overlapped another OREF. We permit this but mark the class unverifiable.
8378                 fieldTrust.SetTrust(ExplicitFieldTrust::kLegal);
8379
8380                 if (firstObjectOverlapOffset == ((DWORD)(-1)))
8381                 {
8382                     firstObjectOverlapOffset = pFD->GetOffset_NoLogging();
8383                 }
8384
8385                 continue;
8386             }
8387             // check if is empty at this point
8388             if (memcmp((void *)&pFieldLayout[pFD->GetOffset_NoLogging()], (void *)emptyObject, sizeof(emptyObject)) == 0)
8389             {
8390                 // If we got here, this OREF is overlapping no other fields (yet). Record that these bytes now contain an OREF.
8391                 memset((void *)&pFieldLayout[pFD->GetOffset_NoLogging()], oref, sizeof(isObject));
8392                 fieldTrust.SetTrust(ExplicitFieldTrust::kNonOverLayed);
8393                 continue;
8394             }
8395
8396             // If we got here, the OREF overlaps a non-OREF. THROW.
8397             badOffset = pFD->GetOffset_NoLogging();
8398             fieldTrust.SetTrust(ExplicitFieldTrust::kNone);
8399             break;
8400         }
8401         else
8402         {
8403             UINT fieldSize;
8404             if (pFD->IsByValue())
8405             {
8406                 MethodTable *pByValueMT = pByValueClassCache[valueClassCacheIndex];
8407                 if (pByValueMT->ContainsPointers())
8408                 {
8409                     if ((pFD->GetOffset_NoLogging() & ((ULONG)sizeof(void*) - 1)) == 0)
8410                     {
8411                         ExplicitFieldTrust::TrustLevel trust;
8412                         DWORD firstObjectOverlapOffsetInsideValueClass = ((DWORD)(-1));
8413                         trust = CheckValueClassLayout(pByValueMT, &pFieldLayout[pFD->GetOffset_NoLogging()], &firstObjectOverlapOffsetInsideValueClass);
8414                         fieldTrust.SetTrust(trust);
8415                         if (firstObjectOverlapOffsetInsideValueClass != ((DWORD)(-1)))
8416                         {
8417                             if (firstObjectOverlapOffset == ((DWORD)(-1)))
8418                             {
8419                                 firstObjectOverlapOffset = pFD->GetOffset_NoLogging() + firstObjectOverlapOffsetInsideValueClass;
8420                             }
8421                         }
8422
8423                         if (trust != ExplicitFieldTrust::kNone)
8424                         {
8425                             continue;
8426                         }
8427                         else
8428                         {
8429                             // If we got here, then an OREF inside the valuetype illegally overlapped a non-OREF field. THROW.
8430                             badOffset = pFD->GetOffset_NoLogging();
8431                             break;
8432                         }
8433                     }
8434                     // If we got here, then a valuetype containing an OREF was misaligned.
8435                     badOffset = pFD->GetOffset_NoLogging();
8436                     fieldTrust.SetTrust(ExplicitFieldTrust::kNone);
8437                     break;
8438                 }
8439                 // no pointers so fall through to do standard checking
8440                 fieldSize = pByValueMT->GetNumInstanceFieldBytes();
8441             }
8442             else
8443             {
8444                 // field size temporarily stored in pInterface field
8445                 fieldSize = GetFieldSize(pFD);
8446             }
8447
8448             // If we got here, we are trying to place a non-OREF (or a valuetype composed of non-OREFs.)
8449             // Look for any orefs under this field
8450             BYTE *loc;
8451             if ((loc = (BYTE*)memchr((void*)&pFieldLayout[pFD->GetOffset_NoLogging()], oref, fieldSize)) == NULL)
8452             {
8453                 // If we have a nonoref in the range then we are doing an overlay
8454                 if(memchr((void*)&pFieldLayout[pFD->GetOffset_NoLogging()], nonoref, fieldSize))
8455                 {
8456                     fieldTrust.SetTrust(ExplicitFieldTrust::kVerifiable);
8457                 }
8458                 else
8459                 {
8460                     fieldTrust.SetTrust(ExplicitFieldTrust::kNonOverLayed);
8461                 }
8462                 memset((void*)&pFieldLayout[pFD->GetOffset_NoLogging()], nonoref, fieldSize);
8463                 continue;
8464             }
8465
8466             // If we got here, we tried to place a non-OREF (or a valuetype composed of non-OREFs)
8467             // on top of an OREF. THROW.
8468             badOffset = (UINT)(loc - pFieldLayout);
8469             fieldTrust.SetTrust(ExplicitFieldTrust::kNone);
8470             break;
8471             // anything else is an error
8472         }
8473
8474         // We have to comment out this assert because otherwise, the compiler refuses to build because the _ASSERT is unreachable
8475         // (Thanks for nothing, compiler, that's what the assert is trying to enforce!) But the intent of the assert is correct.
8476         //_ASSERTE(!"You aren't supposed to be here. Some path inside the loop body did not execute an explicit break or continue.");
8477
8478
8479         // If we got here, some code above failed to execute an explicit "break" or "continue." This is a bug! To be safe,
8480         // we will put a catchall "break" here which will cause the typeload to abort (albeit with a probably misleading
8481         // error message.)
8482         break;
8483     } // for(;;)
8484
8485     // We only break out of the loop above if we detected an error.
8486     if (i < bmtMetaData->cFields || !explicitClassTrust.IsLegal())
8487     {
8488         ThrowFieldLayoutError(GetCl(),
8489                               GetModule(),
8490                               badOffset,
8491                               IDS_CLASSLOAD_EXPLICIT_LAYOUT);
8492     }
8493
8494     if (!explicitClassTrust.IsNonOverLayed())
8495     {
8496         SetHasOverLayedFields();
8497     }
8498
8499     if (IsBlittable() || IsManagedSequential())
8500     {
8501         // Bug 849333: We shouldn't update "bmtFP->NumInstanceFieldBytes" 
8502         // for Blittable/ManagedSequential types.  As this will break backward compatiblity
8503         // for the size of types that return true for HasExplicitFieldOffsetLayout()
8504         // 
8505         return;
8506     }
8507
8508     FindPointerSeriesExplicit(instanceSliceSize, pFieldLayout);
8509
8510     // Fixup the offset to include parent as current offsets are relative to instance slice
8511     // Could do this earlier, but it's just easier to assume instance relative for most
8512     // of the earlier calculations
8513
8514     // Instance fields start right after the parent
8515     S_UINT32 dwInstanceSliceOffset = S_UINT32(HasParent() ? GetParentMethodTable()->GetNumInstanceFieldBytes() : 0);
8516     if (bmtGCSeries->numSeries != 0)
8517     {
8518         dwInstanceSliceOffset.AlignUp(sizeof(void*));
8519     }
8520     if (dwInstanceSliceOffset.IsOverflow())
8521     {
8522         // addition overflow or cast truncation
8523         BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
8524     }
8525
8526     S_UINT32 numInstanceFieldBytes = dwInstanceSliceOffset + S_UINT32(instanceSliceSize);
8527
8528     if (IsValueClass())
8529     {
8530         ULONG clstotalsize;
8531         if (FAILED(GetMDImport()->GetClassTotalSize(GetCl(), &clstotalsize)))
8532         {
8533             clstotalsize = 0;
8534         }
8535         
8536         if (clstotalsize != 0)
8537         {
8538             // size must be large enough to accomodate layout. If not, we use the layout size instead.
8539             if (!numInstanceFieldBytes.IsOverflow() && clstotalsize >= numInstanceFieldBytes.Value())
8540             {
8541                 numInstanceFieldBytes = S_UINT32(clstotalsize);
8542             }
8543         }
8544     }
8545     
8546     // The GC requires that all valuetypes containing orefs be sized to a multiple of sizeof(void*).
8547     if (bmtGCSeries->numSeries != 0)
8548     {
8549         numInstanceFieldBytes.AlignUp(sizeof(void*));
8550     }
8551     if (numInstanceFieldBytes.IsOverflow())
8552     {
8553         // addition overflow or cast truncation
8554         BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
8555     }
8556
8557     // Set the total size
8558     bmtFP->NumInstanceFieldBytes = numInstanceFieldBytes.Value();
8559
8560     for (i = 0; i < bmtMetaData->cFields; i++)
8561     {
8562         FieldDesc * pTempFD = bmtMFDescs->ppFieldDescList[i];
8563         if ((pTempFD == NULL) || pTempFD->IsStatic())
8564         {
8565             continue;
8566         }
8567         HRESULT hr = pTempFD->SetOffset(pTempFD->GetOffset_NoLogging() + dwInstanceSliceOffset.Value());
8568         if (FAILED(hr))
8569         {
8570             BuildMethodTableThrowException(hr, *bmtError);
8571         }
8572     }
8573 } // MethodTableBuilder::HandleExplicitLayout
8574
8575 //*******************************************************************************
8576 // make sure that no object fields are overlapped incorrectly, returns S_FALSE if
8577 // there overlap but nothing illegal, S_OK if there is no overlap
8578 /*static*/ ExplicitFieldTrust::TrustLevel MethodTableBuilder::CheckValueClassLayout(MethodTable * pMT, BYTE *pFieldLayout, DWORD *pFirstObjectOverlapOffset)
8579 {
8580     STANDARD_VM_CONTRACT;
8581
8582
8583     *pFirstObjectOverlapOffset = (DWORD)(-1);
8584
8585     // Build a layout of the value class. Don't know the sizes of all the fields easily, but
8586     // do know a) vc is already consistent so don't need to check it's overlaps and
8587     // b) size and location of all objectrefs. So build it by setting all non-oref
8588     // then fill in the orefs later
8589     UINT fieldSize = pMT->GetNumInstanceFieldBytes();
8590     CQuickBytes qb;
8591     BYTE *vcLayout = (BYTE*) qb.AllocThrows(fieldSize * sizeof(BYTE));
8592
8593     memset((void*)vcLayout, nonoref, fieldSize);
8594
8595     // use pointer series to locate the orefs
8596
8597     CGCDesc* map = CGCDesc::GetCGCDescFromMT(pMT);
8598     CGCDescSeries *pSeries = map->GetLowestSeries();
8599
8600     for (SIZE_T j = 0; j < map->GetNumSeries(); j++)
8601     {
8602         CONSISTENCY_CHECK(pSeries <= map->GetHighestSeries());
8603
8604         memset((void*)&vcLayout[pSeries->GetSeriesOffset()-sizeof(Object)], oref, pSeries->GetSeriesSize() + pMT->GetBaseSize());
8605         pSeries++;
8606     }
8607
8608
8609     ExplicitClassTrust explicitClassTrust;
8610
8611     for (UINT i=0; i < fieldSize; i++) {
8612
8613         ExplicitFieldTrustHolder fieldTrust(&explicitClassTrust);
8614
8615         if (vcLayout[i] == oref) {
8616             switch (pFieldLayout[i]) {
8617                 // oref <--> empty
8618                 case empty:
8619                     pFieldLayout[i] = oref;
8620                     fieldTrust.SetTrust(ExplicitFieldTrust::kNonOverLayed);
8621                     break;
8622
8623                 // oref <--> nonoref
8624                 case nonoref:
8625                     fieldTrust.SetTrust(ExplicitFieldTrust::kNone);
8626                     break;
8627
8628                 // oref <--> oref
8629                 case oref:
8630                     fieldTrust.SetTrust(ExplicitFieldTrust::kLegal);
8631                     if ((*pFirstObjectOverlapOffset) == ((DWORD)(-1)))
8632                     {
8633                         *pFirstObjectOverlapOffset = (DWORD)i;
8634                     }
8635                     break;
8636
8637                 default:
8638                     _ASSERTE(!"Can't get here.");
8639                 }
8640         } else if (vcLayout[i] == nonoref) {
8641             switch (pFieldLayout[i]) {
8642                 // nonoref <--> empty
8643                 case empty:
8644                     pFieldLayout[i] = nonoref;
8645                     fieldTrust.SetTrust(ExplicitFieldTrust::kNonOverLayed);
8646                     break;
8647
8648                 // nonoref <--> nonoref
8649                 case nonoref:
8650                     fieldTrust.SetTrust(ExplicitFieldTrust::kVerifiable);
8651                     break;
8652
8653                 // nonoref <--> oref
8654                 case oref:
8655                     fieldTrust.SetTrust(ExplicitFieldTrust::kNone);
8656                     break;
8657
8658                 default:
8659                     _ASSERTE(!"Can't get here.");
8660             }
8661         } else {
8662             _ASSERTE(!"Can't get here.");
8663         }
8664     }
8665
8666     return explicitClassTrust.GetTrustLevel();
8667 }
8668
8669
8670
8671
8672
8673
8674
8675 //*******************************************************************************
8676 void MethodTableBuilder::FindPointerSeriesExplicit(UINT instanceSliceSize,
8677                                                    BYTE *pFieldLayout)
8678 {
8679     STANDARD_VM_CONTRACT;
8680
8681
8682     // Allocate a structure to track the series. We know that the worst case is a
8683     // ref-non-ref-non, and since only ref series are recorded and non-ref series
8684     // are skipped, the max number of series is total instance size / 2 / sizeof(ref).
8685     // But watch out for the case where we have e.g. an instanceSlizeSize of 4.
8686     DWORD sz = (instanceSliceSize + (2 * sizeof(OBJECTREF)) - 1);
8687     bmtGCSeries->pSeries = new bmtGCSeriesInfo::Series[sz/2/sizeof(OBJECTREF)];
8688
8689     BYTE *loc = pFieldLayout;
8690     BYTE *layoutEnd = pFieldLayout + instanceSliceSize;
8691     while (loc < layoutEnd)
8692     {
8693         // Find the next OREF entry.
8694         loc = (BYTE*)memchr((void*)loc, oref, layoutEnd-loc);
8695         if (loc == NULL)
8696         {
8697             break;
8698         }
8699
8700         // Find the next non-OREF entry
8701         BYTE *cur = loc;
8702         while(cur < layoutEnd && *cur == oref)
8703         {
8704             cur++;
8705         }
8706
8707         // so we have a GC series at loc for cur-loc bytes
8708         bmtGCSeries->pSeries[bmtGCSeries->numSeries].offset = (DWORD)(loc - pFieldLayout);
8709         bmtGCSeries->pSeries[bmtGCSeries->numSeries].len = (DWORD)(cur - loc);
8710
8711         CONSISTENCY_CHECK(IS_ALIGNED(cur - loc, sizeof(size_t)));
8712
8713         bmtGCSeries->numSeries++;
8714         loc = cur;
8715     }
8716
8717     // Calculate the total series count including the parent, if a parent exists.
8718
8719     bmtFP->NumGCPointerSeries = bmtParent->NumParentPointerSeries + bmtGCSeries->numSeries;
8720
8721 }
8722
8723 //*******************************************************************************
8724 VOID 
8725 MethodTableBuilder::HandleGCForExplicitLayout()
8726 {
8727     STANDARD_VM_CONTRACT;
8728
8729     MethodTable *pMT = GetHalfBakedMethodTable();
8730
8731 #ifdef FEATURE_COLLECTIBLE_TYPES
8732     if (bmtFP->NumGCPointerSeries == 0 && pMT->Collectible())
8733     {
8734         // For collectible types, insert empty gc series
8735         CGCDescSeries *pSeries;
8736
8737         CGCDesc::Init( (PVOID) pMT, 1);
8738         pSeries = ((CGCDesc*)pMT)->GetLowestSeries();
8739         pSeries->SetSeriesSize( (size_t) (0) - (size_t) pMT->GetBaseSize());
8740         pSeries->SetSeriesOffset(sizeof(Object));
8741     }
8742     else
8743 #endif // FEATURE_COLLECTIBLE_TYPES
8744     if (bmtFP->NumGCPointerSeries != 0)
8745     {
8746         pMT->SetContainsPointers();
8747
8748         // Copy the pointer series map from the parent
8749         CGCDesc::Init( (PVOID) pMT, bmtFP->NumGCPointerSeries );
8750         if (bmtParent->NumParentPointerSeries != 0)
8751         {
8752             size_t ParentGCSize = CGCDesc::ComputeSize(bmtParent->NumParentPointerSeries);
8753             memcpy( (PVOID) (((BYTE*) pMT) - ParentGCSize),  (PVOID) (((BYTE*) GetParentMethodTable()) - ParentGCSize), ParentGCSize - sizeof(UINT) );
8754
8755         }
8756
8757         UINT32 dwInstanceSliceOffset = AlignUp(HasParent() ? GetParentMethodTable()->GetNumInstanceFieldBytes() : 0, sizeof(void*));
8758
8759         // Build the pointer series map for this pointers in this instance
8760         CGCDescSeries *pSeries = ((CGCDesc*)pMT)->GetLowestSeries();
8761         for (UINT i=0; i < bmtGCSeries->numSeries; i++) {
8762             // See gcdesc.h for an explanation of why we adjust by subtracting BaseSize
8763             BAD_FORMAT_NOTHROW_ASSERT(pSeries <= CGCDesc::GetCGCDescFromMT(pMT)->GetHighestSeries());
8764
8765             pSeries->SetSeriesSize( (size_t) bmtGCSeries->pSeries[i].len - (size_t) pMT->GetBaseSize() );
8766             pSeries->SetSeriesOffset(bmtGCSeries->pSeries[i].offset + sizeof(Object) + dwInstanceSliceOffset);
8767             pSeries++;
8768         }
8769     }
8770
8771     delete [] bmtGCSeries->pSeries;
8772     bmtGCSeries->pSeries = NULL;
8773 } // MethodTableBuilder::HandleGCForExplicitLayout
8774
8775 static 
8776 BOOL 
8777 InsertMethodTable(
8778     MethodTable  *pNew, 
8779     MethodTable **pArray, 
8780     DWORD         nArraySizeMax, 
8781     DWORD        *pNumAssigned)
8782 {
8783     LIMITED_METHOD_CONTRACT;
8784
8785     for (DWORD j = 0; j < (*pNumAssigned); j++)
8786     {
8787         if (pNew == pArray[j])
8788         {
8789 #ifdef _DEBUG
8790             LOG((LF_CLASSLOADER, LL_INFO1000, "GENERICS: Found duplicate interface %s (%p) at position %d out of %d\n", pNew->GetDebugClassName(), pNew, j, *pNumAssigned));
8791 #endif
8792             return pNew->HasInstantiation(); // bail out - we found a duplicate instantiated interface
8793         }
8794         else
8795         {
8796 #ifdef _DEBUG 
8797             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));
8798 #endif
8799         }
8800     }
8801     if (*pNumAssigned >= nArraySizeMax)
8802     {
8803         LOG((LF_CLASSLOADER, LL_INFO1000, "GENERICS: Found interface %s (%p) exceeding size %d of interface array\n", pNew->GetDebugClassName(), pNew, nArraySizeMax));
8804         return TRUE;
8805     }
8806     LOG((LF_CLASSLOADER, LL_INFO1000, "GENERICS: Inserting interface %s (%p) at position %d\n", pNew->GetDebugClassName(), pNew, *pNumAssigned));
8807     pArray[(*pNumAssigned)++] = pNew;
8808     return FALSE;
8809 } // InsertMethodTable
8810
8811
8812 //*******************************************************************************
8813 // --------------------------------------------------------------------------------------------
8814 // Copy virtual slots inherited from parent:
8815 //
8816 // In types created at runtime, inherited virtual slots are initialized using approximate parent 
8817 // during method table building. This method will update them based on the exact parent.
8818 // In types loaded from NGen image, inherited virtual slots from cross-module parents are not 
8819 // initialized. This method will initialize them based on the actually loaded exact parent
8820 // if necessary.
8821 /* static */
8822 void MethodTableBuilder::CopyExactParentSlots(MethodTable *pMT, MethodTable *pApproxParentMT)
8823 {
8824     CONTRACTL
8825     {
8826         STANDARD_VM_CHECK;
8827         PRECONDITION(CheckPointer(pMT));
8828     }
8829     CONTRACTL_END;
8830
8831     if (pMT->IsZapped())
8832         return;
8833
8834     DWORD nParentVirtuals = pMT->GetNumParentVirtuals();
8835     if (nParentVirtuals == 0)
8836         return;
8837
8838     _ASSERTE(nParentVirtuals == pApproxParentMT->GetNumVirtuals());
8839
8840     //
8841     // Update all inherited virtual slots to match exact parent
8842     //
8843
8844     if (!pMT->IsCanonicalMethodTable())
8845     {
8846         //
8847         // Copy all slots for non-canonical methodtables to avoid touching methoddescs.
8848         //
8849         MethodTable * pCanonMT = pMT->GetCanonicalMethodTable();
8850
8851         // Do not write into vtable chunks shared with parent. It would introduce race 
8852         // with code:MethodDesc::SetStableEntryPointInterlocked.
8853         //
8854         // Non-canonical method tables either share everything or nothing so it is sufficient to check
8855         // just the first indirection to detect sharing.
8856         if (pMT->GetVtableIndirections()[0].GetValueMaybeNull() != pCanonMT->GetVtableIndirections()[0].GetValueMaybeNull())
8857         {
8858             for (DWORD i = 0; i < nParentVirtuals; i++)
8859             {
8860                 PCODE target = pCanonMT->GetRestoredSlot(i);
8861                 pMT->SetSlot(i, target);
8862             }
8863         }
8864     }
8865     else
8866     {
8867         MethodTable::MethodDataWrapper hMTData(MethodTable::GetMethodData(pMT, FALSE));
8868
8869         MethodTable * pParentMT = pMT->GetParentMethodTable();
8870
8871         for (DWORD i = 0; i < nParentVirtuals; i++)
8872         {
8873             // fix up wrongly-inherited method descriptors
8874             MethodDesc* pMD = hMTData->GetImplMethodDesc(i);
8875             CONSISTENCY_CHECK(pMD == pMT->GetMethodDescForSlot(i));
8876
8877             if (pMD->GetMethodTable() == pMT)
8878                 continue;
8879
8880             // We need to re-inherit this slot from the exact parent.
8881
8882             DWORD indirectionIndex = MethodTable::GetIndexOfVtableIndirection(i);
8883             if (pMT->GetVtableIndirections()[indirectionIndex].GetValueMaybeNull() == pApproxParentMT->GetVtableIndirections()[indirectionIndex].GetValueMaybeNull())
8884             {
8885                 // The slot lives in a chunk shared from the approximate parent MT
8886                 // If so, we need to change to share the chunk from the exact parent MT
8887
8888 #ifdef FEATURE_PREJIT
8889                 _ASSERTE(MethodTable::CanShareVtableChunksFrom(pParentMT, pMT->GetLoaderModule(), Module::GetPreferredZapModuleForMethodTable(pMT)));
8890 #else
8891                 _ASSERTE(MethodTable::CanShareVtableChunksFrom(pParentMT, pMT->GetLoaderModule()));
8892 #endif
8893
8894                 pMT->GetVtableIndirections()[indirectionIndex].SetValueMaybeNull(pParentMT->GetVtableIndirections()[indirectionIndex].GetValueMaybeNull());
8895
8896                 i = MethodTable::GetEndSlotForVtableIndirection(indirectionIndex, nParentVirtuals) - 1;
8897                 continue;
8898             }
8899
8900             // The slot lives in an unshared chunk. We need to update the slot contents
8901             PCODE target = pParentMT->GetRestoredSlot(i);
8902             pMT->SetSlot(i, target);
8903         }
8904     }
8905 } // MethodTableBuilder::CopyExactParentSlots
8906
8907 //*******************************************************************************
8908 /* static */
8909 void 
8910 MethodTableBuilder::LoadExactInterfaceMap(MethodTable *pMT)
8911 {
8912     CONTRACTL
8913     {
8914         STANDARD_VM_CHECK;
8915         PRECONDITION(CheckPointer(pMT));
8916     }
8917     CONTRACTL_END;
8918
8919     BOOL hasInstantiatedInterfaces = FALSE;
8920     MethodTable::InterfaceMapIterator it = pMT->IterateInterfaceMap();
8921     while (it.Next())
8922     {
8923         if (it.GetInterface()->HasInstantiation())
8924         {
8925             hasInstantiatedInterfaces = TRUE;
8926             break;
8927         }
8928     }
8929
8930     // If we have some instantiated interfaces, then we have lots more work to do...
8931
8932     // In the worst case we have to use the metadata to
8933     //  (a) load the exact interfaces and determine the order in which they
8934     //      go.  We do those by re-running the interface layout algorithm
8935     //      and using metadata-comparisons to place interfaces in the list.
8936     //  (b) do a check to see if any ambiguity in the interface dispatch map is introduced
8937     //      by the instantiation
8938     // See code:#LoadExactInterfaceMap_Algorithm2
8939     //
8940     // However, we can do something simpler: we just use
8941     // the loaded interface method tables to determine ordering.  This can be done
8942     // if there are no duplicate instantiated interfaces in the interface
8943     // set.
8944     // See code:#LoadExactInterfaceMap_Algorithm1.
8945
8946     if (!hasInstantiatedInterfaces)
8947     {
8948         return;
8949     }
8950
8951     HRESULT hr;
8952     TypeHandle thisTH(pMT);
8953     SigTypeContext typeContext(thisTH);
8954     MethodTable *pParentMT = pMT->GetParentMethodTable();
8955
8956     //#LoadExactInterfaceMap_Algorithm1
8957     // Exact interface instantiation loading TECHNIQUE 1.
8958     // (a) For interfaces inherited from an instantiated parent class, just copy down from exact parent
8959     // (b) Grab newly declared interfaces by loading and then copying down all their inherited parents
8960     // (c) But check for any exact duplicates along the way
8961     // (d) If no duplicates then we can use the computed interface map we've created
8962     // (e) If duplicates found then use the slow metadata-based technique code:#LoadExactInterfaceMap_Algorithm2
8963     DWORD nInterfacesCount = pMT->GetNumInterfaces();
8964     MethodTable **pExactMTs = (MethodTable**) _alloca(sizeof(MethodTable *) * nInterfacesCount);
8965     DWORD nAssigned = 0;
8966     BOOL duplicates = false;
8967     if (pParentMT != NULL)
8968     {
8969         MethodTable::InterfaceMapIterator parentIt = pParentMT->IterateInterfaceMap();
8970         while (parentIt.Next())
8971         {
8972             duplicates |= InsertMethodTable(parentIt.GetInterface(), pExactMTs, nInterfacesCount, &nAssigned);
8973         }
8974     }
8975     InterfaceImplEnum ie(pMT->GetModule(), pMT->GetCl(), NULL);
8976     while ((hr = ie.Next()) == S_OK)
8977     {
8978         MethodTable *pNewIntfMT = ClassLoader::LoadTypeDefOrRefOrSpecThrowing(pMT->GetModule(),
8979                                                                               ie.CurrentToken(),
8980                                                                               &typeContext,
8981                                                                               ClassLoader::ThrowIfNotFound,
8982                                                                               ClassLoader::FailIfUninstDefOrRef,
8983                                                                               ClassLoader::LoadTypes,
8984                                                                               CLASS_LOAD_EXACTPARENTS,
8985                                                                               TRUE).GetMethodTable();
8986
8987         duplicates |= InsertMethodTable(pNewIntfMT, pExactMTs, nInterfacesCount, &nAssigned);
8988         MethodTable::InterfaceMapIterator intIt = pNewIntfMT->IterateInterfaceMap();
8989         while (intIt.Next())
8990         {
8991             duplicates |= InsertMethodTable(intIt.GetInterface(), pExactMTs, nInterfacesCount, &nAssigned);
8992         }
8993     }
8994     if (FAILED(hr))
8995     {
8996         pMT->GetAssembly()->ThrowTypeLoadException(pMT->GetMDImport(), pMT->GetCl(), IDS_CLASSLOAD_BADFORMAT);
8997     }
8998 #ifdef _DEBUG 
8999     duplicates |= EEConfig::GetConfigDWORD_DontUse_(CLRConfig::INTERNAL_AlwaysUseMetadataInterfaceMapLayout, FALSE);
9000     
9001     //#InjectInterfaceDuplicates_LoadExactInterfaceMap
9002     // If we are injecting duplicates also for non-generic interfaces in check builds, we have to use 
9003     // algorithm code:#LoadExactInterfaceMap_Algorithm2.
9004     // Has to be in sync with code:#InjectInterfaceDuplicates_Main.
9005     duplicates |= pMT->Debug_HasInjectedInterfaceDuplicates();
9006 #endif
9007     CONSISTENCY_CHECK(duplicates || (nAssigned == pMT->GetNumInterfaces()));
9008     if (duplicates)
9009     {
9010         //#LoadExactInterfaceMap_Algorithm2
9011         // Exact interface instantiation loading TECHNIQUE 2 - The exact instantiation has caused some duplicates to
9012         // appear in the interface map!  This may not be an error: if the duplicates
9013         // were ones that arose because because of inheritance from
9014         // a parent type then we accept that.  For example
9015         //     class C<T> : I<T>
9016         //     class D<T> : C<T>, I<string>
9017         // is acceptable even when loading D<string>.  Note that in such a case
9018         // there will be two entries for I<string> in the final interface map for D<string>.
9019         // For dispatch the mappings in D take precedence.
9020         //
9021         // However we consider it an error if there is real ambiguity within
9022         // the interface definitions within the one class, e.g.
9023         //     class E<T> : I<T>, I<string>
9024         // In this situation it is not defined how to dispatch calls to I<string>: would
9025         // we use the bindings for I<T> or I<string>?
9026         //
9027         // Because we may had duplicates the interface map we created above may not
9028         // be the correct one: for example for D<string> above we would have computed
9029         // a map with only one entry.  This is incorrect: an exact instantiation's interface
9030         // map must have entries that match the ordering of the interface map in the generic case
9031         // (this is because code:#InterfaceMap_SupersetOfParent).
9032         //
9033         // So, in order to determine how to place the interfaces we need go back to
9034         // the metadata. We also do this to check if the presence of duplicates
9035         // has caused any potential ambiguity, i.e. the E<string> case above.
9036
9037         // First we do a GetCheckpoint for the thread-based allocator.  ExpandExactInheritedInterfaces allocates substitution chains
9038         // on the thread allocator rather than on the stack.
9039         Thread * pThread = GetThread();
9040         CheckPointHolder cph(pThread->m_MarshalAlloc.GetCheckpoint()); //hold checkpoint for autorelease
9041
9042         // ***********************************************************
9043         // ****** This must be consistent with code:ExpandApproxInterface etc. *******
9044         //
9045         // The correlation to ExpandApproxInterfaces etc. simply drops out by how we
9046         // traverse interfaces.
9047         // ***********************************************************
9048
9049         bmtExactInterfaceInfo bmtExactInterface;
9050         bmtExactInterface.pInterfaceSubstitution = new (&pThread->m_MarshalAlloc) Substitution[pMT->GetNumInterfaces()];
9051         bmtExactInterface.pExactMTs = pExactMTs;
9052         bmtExactInterface.nAssigned = 0;
9053         bmtExactInterface.typeContext = typeContext;
9054
9055         // Do the interfaces inherited from a parent class
9056         if ((pParentMT != NULL) && (pParentMT->GetNumInterfaces() > 0))
9057         {
9058             Substitution * pParentSubstForTypeLoad = new (&pThread->m_MarshalAlloc) Substitution(
9059                 pMT->GetSubstitutionForParent(NULL));
9060             Substitution * pParentSubstForComparing = new (&pThread->m_MarshalAlloc) Substitution(
9061                 pMT->GetSubstitutionForParent(NULL));
9062             ExpandExactInheritedInterfaces(
9063                 &bmtExactInterface, 
9064                 pParentMT, 
9065                 pParentSubstForTypeLoad, 
9066                 pParentSubstForComparing);
9067         }
9068 #ifdef _DEBUG
9069         //#ExactInterfaceMap_SupersetOfParent
9070         // Check that parent's interface map is subset of this interface map
9071         // See code:#InterfaceMap_SupersetOfParent
9072         {
9073             _ASSERTE(pParentMT->GetNumInterfaces() == bmtExactInterface.nAssigned);
9074             
9075             MethodTable::InterfaceMapIterator parentInterfacesIterator = pParentMT->IterateInterfaceMap();
9076             UINT32 nInterfaceIndex = 0;
9077             while (parentInterfacesIterator.Next())
9078             {
9079                 if (pMT->IsSharedByGenericInstantiations())
9080                 {   // The type is a canonical instantiation (contains _Canon)
9081                     // The interface instantiations of parent can be different (see 
9082                     // code:#InterfaceMap_CanonicalSupersetOfParent), therefore we cannot compare 
9083                     // MethodTables
9084                     _ASSERTE(parentInterfacesIterator.GetInterfaceInfo()->GetApproxMethodTable(pParentMT->GetLoaderModule())->HasSameTypeDefAs(
9085                         bmtExactInterface.pExactMTs[nInterfaceIndex]));
9086                 }
9087                 else
9088                 {   // It is not canonical instantiation, we can compare MethodTables
9089                     _ASSERTE(parentInterfacesIterator.GetInterface() == bmtExactInterface.pExactMTs[nInterfaceIndex]);
9090                 }
9091                 nInterfaceIndex++;
9092             }
9093             _ASSERTE(nInterfaceIndex == bmtExactInterface.nAssigned);
9094         }
9095 #endif //_DEBUG
9096
9097         // If there are any __Canon instances in the type argument list, then we defer the
9098         // ambiguity checking until an exact instantiation.
9099         if (!pMT->IsSharedByGenericInstantiations())
9100         {
9101             // There are no __Canon types in the instantiation, so do ambiguity check.
9102             bmtInterfaceAmbiguityCheckInfo bmtCheckInfo;
9103             bmtCheckInfo.pMT = pMT;
9104             bmtCheckInfo.ppInterfaceSubstitutionChains = new (&pThread->m_MarshalAlloc) Substitution *[pMT->GetNumInterfaces()];
9105             bmtCheckInfo.ppExactDeclaredInterfaces = new (&pThread->m_MarshalAlloc) MethodTable *[pMT->GetNumInterfaces()];
9106             bmtCheckInfo.nAssigned = 0;
9107             bmtCheckInfo.typeContext = typeContext;
9108             MethodTableBuilder::InterfacesAmbiguityCheck(&bmtCheckInfo, pMT->GetModule(), pMT->GetCl(), NULL);
9109         }
9110
9111         // OK, there is no ambiguity amongst the instantiated interfaces declared on this class.
9112         MethodTableBuilder::ExpandExactDeclaredInterfaces(
9113             &bmtExactInterface, 
9114             pMT->GetModule(), 
9115             pMT->GetCl(), 
9116             NULL, 
9117             NULL 
9118             COMMA_INDEBUG(pMT));
9119         CONSISTENCY_CHECK(bmtExactInterface.nAssigned == pMT->GetNumInterfaces());
9120         
9121         // We cannot process interface duplicates on types with __Canon. The duplicates are processed on 
9122         // exact types only
9123         if (!pMT->IsSharedByGenericInstantiations())
9124         {
9125             // Process all pairs of duplicates in the interface map:
9126             //     i.e. If there are 3 duplicates of the same interface at indexes: i1, i2 and i3, then 
9127             //     process pairs of indexes [i1,i2], [i1,i3] and [i2,i3].
9128             //  - Update 'declared on type' flag for those interfaces which duplicate is 'declared on type'
9129             //  - Check interface method implementation ambiguity code:#DuplicateInterface_MethodAmbiguity
9130             for (DWORD nOriginalIndex = 0; nOriginalIndex < nInterfacesCount; nOriginalIndex++)
9131             {
9132                 // Search for duplicates further in the interface map
9133                 for (DWORD nDuplicateIndex = nOriginalIndex + 1; nDuplicateIndex < nInterfacesCount; nDuplicateIndex++)
9134                 {
9135                     if (pExactMTs[nOriginalIndex] != pExactMTs[nDuplicateIndex])
9136                     {   // It's not a duplicate of original interface, skip it
9137                         continue;
9138                     }
9139                     // We found a duplicate
9140                     
9141                     // Set 'declared on type' flag if either original or duplicate interface is 
9142                     // 'declared on type'
9143                     if (pMT->IsInterfaceDeclaredOnClass(nOriginalIndex) || 
9144                         pMT->IsInterfaceDeclaredOnClass(nDuplicateIndex))
9145                     {
9146                         // 
9147                         // Note that both checks are needed:
9148                         //     A<T> : I<T>
9149                         //     B<T,U> : A<T>, I<U>
9150                         //     C<T,U> : B<T,U>, I<T>   // Reimplements interface from A<T>
9151                         // After code:BuildMethodTableThrowing algorithm, this will happen:
9152                         // B<int,int> will have interface map similar to B<T,U>:
9153                         //     I<int> ... not 'declared on type'
9154                         //     I<int> ... 'declared on type'
9155                         // C<int,int> will have interface map similar to C<T,U>:
9156                         //     I<int> ... 'declared on type'
9157                         //     I<int> ... not 'declared on type'
9158                         // 
9159                         
9160                         pMT->SetInterfaceDeclaredOnClass(nOriginalIndex);
9161                         pMT->SetInterfaceDeclaredOnClass(nDuplicateIndex);
9162                     }
9163                     
9164                     //#DuplicateInterface_MethodAmbiguity
9165                     // 
9166                     // In the ideal world we would now check for interface method implementation 
9167                     // ambiguity in the instantiation, but that would be a technical breaking change 
9168                     // (against 2.0 RTM/SP1).
9169                     // Therefore we ALLOW when interface method is implemented twice through this 
9170                     // original and duplicate interface.
9171                     // 
9172                     // This ambiguity pattern is therefore ALLOWED (can be expressed only in IL, not in C#):
9173                     //     I<T>
9174                     //         void Print(T t);
9175                     //     A<T> : I<T>    // abstract class
9176                     //     B<T,U> : A<T>, I<U>
9177                     //         void Print(T t) { ... }
9178                     //         void Print(U u) { ... }
9179                     //     Now B<int,int> has 2 implementations of I<int>.Print(int), while B<int,char> is 
9180                     //     fine. Therefore an instantiation can introduce ambiguity.
9181                     
9182 #if 0 // Removing this code for now as it is a technical breaking change (against CLR 2.0 RTM/SP1).
9183       // We might decide later that we want to take this breaking change.
9184                     // 
9185                     // Note that dispatch map entries are sorted by interface index and then interface 
9186                     // method slot index.
9187                     // 
9188                     DispatchMapTypeID originalTypeID = DispatchMapTypeID::InterfaceClassID(nOriginalIndex);
9189                     DispatchMap::EncodedMapIterator originalIt(pMT);
9190                     // Find first entry for original interface
9191                     while (originalIt.IsValid())
9192                     {
9193                         DispatchMapEntry *pEntry = originalIt.Entry();
9194                         if (pEntry->GetTypeID().ToUINT32() >= originalTypeID.ToUINT32())
9195                         {   // Found the place where original interface entries should be (dispatch map is 
9196                             // sorted)
9197                             break;
9198                         }
9199                         originalIt.Next();
9200                     }
9201                     
9202                     DispatchMapTypeID duplicateTypeID = DispatchMapTypeID::InterfaceClassID(nDuplicateIndex);
9203                     DispatchMap::EncodedMapIterator duplicateIt(pMT);
9204                     // Find first entry for duplicate interface
9205                     while (duplicateIt.IsValid())
9206                     {
9207                         DispatchMapEntry *pEntry = duplicateIt.Entry();
9208                         if (pEntry->GetTypeID().ToUINT32() >= duplicateTypeID.ToUINT32())
9209                         {   // Found the place where original interface entries should be (dispatch map is 
9210                             // sorted)
9211                             break;
9212                         }
9213                         duplicateIt.Next();
9214                     }
9215                     
9216                     // Compare original and duplicate interface entries in the dispatch map if they contain 
9217                     // different implementation for the same interface method
9218                     for (;;)
9219                     {
9220                         if (!originalIt.IsValid() || !duplicateIt.IsValid())
9221                         {   // We reached end of one dispatch map iterator
9222                             break;
9223                         }
9224                         DispatchMapEntry *pOriginalEntry = originalIt.Entry();
9225                         if (pOriginalEntry->GetTypeID().ToUINT32() != originalTypeID.ToUINT32())
9226                         {   // We reached behind original interface entries
9227                             break;
9228                         }
9229                         DispatchMapEntry *pDuplicateEntry = duplicateIt.Entry();
9230                         if (pDuplicateEntry->GetTypeID().ToUINT32() != duplicateTypeID.ToUINT32())
9231                         {   // We reached behind duplicate interface entries
9232                             break;
9233                         }
9234                         
9235                         if (pOriginalEntry->GetSlotNumber() == pDuplicateEntry->GetSlotNumber())
9236                         {   // Found duplicate implementation of interface method
9237                             if (pOriginalEntry->GetTargetSlotNumber() != pDuplicateEntry->GetTargetSlotNumber())
9238                             {   // Implementation of the slots is different
9239                                 bmtErrorInfo bmtError;
9240                                 
9241                                 bmtError.pModule = pMT->GetModule();
9242                                 bmtError.cl = pMT->GetCl();
9243                                 bmtError.resIDWhy = IDS_CLASSLOAD_MI_MULTIPLEOVERRIDES;
9244                                 bmtError.szMethodNameForError = NULL;
9245                                 bmtError.pThrowable = NULL;
9246                                 
9247                                 MethodDesc *pMD = pMT->GetMethodDescForSlot(pDuplicateEntry->GetTargetSlotNumber());
9248                                 bmtError.dMethodDefInError = pMD->GetMemberDef();
9249                                 
9250                                 BuildMethodTableThrowException(COR_E_TYPELOAD, bmtError);
9251                             }
9252                             // The method is implemented by the same slot on both interfaces (original and 
9253                             // duplicate)
9254                             
9255                             // Process next dispatch map entry
9256                             originalIt.Next();
9257                             duplicateIt.Next();
9258                             continue;
9259                         }
9260                         // Move iterator representing smaller interface method slot index (the dispatch map 
9261                         // is sorted by slot indexes)
9262                         if (pOriginalEntry->GetSlotNumber() < pDuplicateEntry->GetSlotNumber())
9263                         {
9264                             originalIt.Next();
9265                             continue;
9266                         }
9267                         _ASSERTE(pOriginalEntry->GetSlotNumber() > pDuplicateEntry->GetSlotNumber());
9268                         duplicateIt.Next();
9269                     }
9270 #endif //0
9271                 }
9272                 // All duplicates of this original interface were processed
9273             }
9274             // All pairs of duplicates in the interface map are processed
9275         }
9276     }
9277     // Duplicates in the interface map are resolved
9278     
9279     // OK, if we've got this far then pExactMTs should now hold the array of exact instantiated interfaces.
9280     MethodTable::InterfaceMapIterator thisIt = pMT->IterateInterfaceMap();
9281     DWORD i = 0;
9282     while (thisIt.Next())
9283     {
9284 #ifdef _DEBUG 
9285         MethodTable*pOldMT = thisIt.GetInterface();
9286         MethodTable *pNewMT = pExactMTs[i];
9287         CONSISTENCY_CHECK(pOldMT->HasSameTypeDefAs(pNewMT));
9288 #endif // _DEBUG
9289         thisIt.SetInterface(pExactMTs[i]);
9290         i++;
9291     }
9292
9293 } // MethodTableBuilder::LoadExactInterfaceMap
9294
9295 //*******************************************************************************
9296 void 
9297 MethodTableBuilder::ExpandExactInheritedInterfaces(
9298     bmtExactInterfaceInfo * bmtInfo, 
9299     MethodTable *           pMT, 
9300     const Substitution *    pSubstForTypeLoad, 
9301     Substitution *          pSubstForComparing)
9302 {
9303     STANDARD_VM_CONTRACT;
9304
9305     MethodTable *pParentMT = pMT->GetParentMethodTable();
9306     
9307     // Backup type's substitution chain for comparing interfaces
9308     Substitution substForComparingBackup = *pSubstForComparing;
9309     // Make type an open type for comparing interfaces
9310     *pSubstForComparing = Substitution();
9311     
9312     if (pParentMT)
9313     {
9314         // Chain parent's substitution for exact type load
9315         Substitution * pParentSubstForTypeLoad = new (&GetThread()->m_MarshalAlloc) Substitution(
9316             pMT->GetSubstitutionForParent(pSubstForTypeLoad));
9317         
9318         // Chain parent's substitution for comparing interfaces (note that this type is temporarily 
9319         // considered as open type)
9320         Substitution * pParentSubstForComparing = new (&GetThread()->m_MarshalAlloc) Substitution(
9321             pMT->GetSubstitutionForParent(pSubstForComparing));
9322         
9323         ExpandExactInheritedInterfaces(
9324             bmtInfo, 
9325             pParentMT, 
9326             pParentSubstForTypeLoad, 
9327             pParentSubstForComparing);
9328     }
9329     ExpandExactDeclaredInterfaces(
9330         bmtInfo, 
9331         pMT->GetModule(), 
9332         pMT->GetCl(), 
9333         pSubstForTypeLoad, 
9334         pSubstForComparing 
9335         COMMA_INDEBUG(pMT));
9336     
9337     // Restore type's subsitution chain for comparing interfaces
9338     *pSubstForComparing = substForComparingBackup;
9339 } // MethodTableBuilder::ExpandExactInheritedInterfaces
9340
9341 //*******************************************************************************
9342 /* static */
9343 void 
9344 MethodTableBuilder::ExpandExactDeclaredInterfaces(
9345     bmtExactInterfaceInfo *     bmtInfo, 
9346     Module *                    pModule, 
9347     mdToken                     typeDef, 
9348     const Substitution *        pSubstForTypeLoad, 
9349     Substitution *              pSubstForComparing 
9350     COMMA_INDEBUG(MethodTable * dbg_pClassMT))
9351 {
9352     STANDARD_VM_CONTRACT;
9353
9354     HRESULT hr;
9355     InterfaceImplEnum ie(pModule, typeDef, NULL);
9356     while ((hr = ie.Next()) == S_OK)
9357     {
9358         MethodTable * pInterface = ClassLoader::LoadTypeDefOrRefOrSpecThrowing(
9359             pModule, 
9360             ie.CurrentToken(), 
9361             &bmtInfo->typeContext,
9362             ClassLoader::ThrowIfNotFound,
9363             ClassLoader::FailIfUninstDefOrRef,
9364             ClassLoader::LoadTypes,
9365             CLASS_LOAD_EXACTPARENTS,
9366             TRUE,
9367             pSubstForTypeLoad).GetMethodTable();
9368         
9369         Substitution ifaceSubstForTypeLoad(ie.CurrentToken(), pModule, pSubstForTypeLoad);
9370         Substitution ifaceSubstForComparing(ie.CurrentToken(), pModule, pSubstForComparing);
9371         ExpandExactInterface(
9372             bmtInfo, 
9373             pInterface, 
9374             &ifaceSubstForTypeLoad, 
9375             &ifaceSubstForComparing 
9376             COMMA_INDEBUG(dbg_pClassMT));
9377     }
9378     if (FAILED(hr))
9379     {
9380         pModule->GetAssembly()->ThrowTypeLoadException(pModule->GetMDImport(), typeDef, IDS_CLASSLOAD_BADFORMAT);
9381     }
9382 } // MethodTableBuilder::ExpandExactDeclaredInterfaces
9383
9384 //*******************************************************************************
9385 void 
9386 MethodTableBuilder::ExpandExactInterface(
9387     bmtExactInterfaceInfo *     bmtInfo, 
9388     MethodTable *               pIntf, 
9389     const Substitution *        pSubstForTypeLoad_OnStack,   // Allocated on stack!
9390     const Substitution *        pSubstForComparing_OnStack   // Allocated on stack!
9391     COMMA_INDEBUG(MethodTable * dbg_pClassMT))
9392 {
9393     STANDARD_VM_CONTRACT;
9394
9395     // ****** This must be consistent with code:MethodTableBuilder::ExpandApproxInterface ******
9396
9397     // Is it already present according to the "generic" layout of the interfaces.
9398     // Note we use exactly the same algorithm as when we
9399     // determined the layout of the interface map for the "generic" version of the class.
9400     for (DWORD i = 0; i < bmtInfo->nAssigned; i++)
9401     {
9402         // Type Equivalence is not respected for this comparision as you can have multiple type equivalent interfaces on a class
9403         TokenPairList newVisited = TokenPairList::AdjustForTypeEquivalenceForbiddenScope(NULL);
9404         if (MetaSig::CompareTypeDefsUnderSubstitutions(bmtInfo->pExactMTs[i],
9405                                                        pIntf,
9406                                                        &bmtInfo->pInterfaceSubstitution[i],
9407                                                        pSubstForComparing_OnStack,
9408                                                        &newVisited))
9409         {
9410 #ifdef _DEBUG
9411             //#InjectInterfaceDuplicates_ExactInterfaces
9412             // We will inject duplicate interfaces in check builds.
9413             // Has to be in sync with code:#InjectInterfaceDuplicates_Main.
9414             if (dbg_pClassMT->Debug_HasInjectedInterfaceDuplicates())
9415             {   // Just pretend we didn't find this match
9416                 break;
9417             }
9418 #endif //_DEBUG
9419             return; // found it, don't add it again
9420         }
9421     }
9422
9423     // Add the interface and its sub-interfaces
9424     DWORD n = bmtInfo->nAssigned;
9425     bmtInfo->pExactMTs[n] = pIntf;
9426     bmtInfo->pInterfaceSubstitution[n] = *pSubstForComparing_OnStack;
9427     bmtInfo->nAssigned++;
9428     
9429     Substitution * pSubstForTypeLoad = new (&GetThread()->m_MarshalAlloc) Substitution(*pSubstForTypeLoad_OnStack);
9430     
9431     ExpandExactDeclaredInterfaces(
9432         bmtInfo, 
9433         pIntf->GetModule(), 
9434         pIntf->GetCl(), 
9435         pSubstForTypeLoad, 
9436         &bmtInfo->pInterfaceSubstitution[n] 
9437         COMMA_INDEBUG(dbg_pClassMT));
9438 } // MethodTableBuilder::ExpandExactInterface
9439
9440 //*******************************************************************************
9441 /* static */
9442 void MethodTableBuilder::InterfacesAmbiguityCheck(bmtInterfaceAmbiguityCheckInfo *bmtCheckInfo,
9443                                                   Module *pModule,
9444                                                   mdToken typeDef,
9445                                                   const Substitution *pSubstChain)
9446 {
9447     STANDARD_VM_CONTRACT;
9448
9449     HRESULT hr;
9450     InterfaceImplEnum ie(pModule, typeDef, pSubstChain);
9451     while ((hr = ie.Next()) == S_OK)
9452     {
9453         MethodTable *pInterface =
9454             ClassLoader::LoadTypeDefOrRefOrSpecThrowing(pModule, ie.CurrentToken(),
9455                                                         &bmtCheckInfo->typeContext,
9456                                                         ClassLoader::ThrowIfNotFound,
9457                                                         ClassLoader::FailIfUninstDefOrRef,
9458                                                         ClassLoader::LoadTypes,
9459                                                         CLASS_LOAD_EXACTPARENTS,
9460                                                         TRUE,
9461                                                         pSubstChain).GetMethodTable();
9462         InterfaceAmbiguityCheck(bmtCheckInfo, ie.CurrentSubst(), pInterface);
9463     }
9464     if (FAILED(hr))
9465     {
9466         pModule->GetAssembly()->ThrowTypeLoadException(pModule->GetMDImport(), typeDef, IDS_CLASSLOAD_BADFORMAT);
9467     }
9468 }
9469
9470 //*******************************************************************************
9471 void MethodTableBuilder::InterfaceAmbiguityCheck(bmtInterfaceAmbiguityCheckInfo *bmtCheckInfo,
9472                                                  const Substitution *pItfSubstChain,
9473                                                  MethodTable *pIntf)
9474 {
9475     STANDARD_VM_CONTRACT;
9476
9477     // Is it already in the generic version of the freshly declared interfaces. We
9478     // do this based on metadata, i.e. via the substitution chains.
9479     // Note we use exactly the same algorithm as when we
9480     // determined the layout of the interface map for the "generic" version of the class.
9481     for (DWORD i = 0; i < bmtCheckInfo->nAssigned; i++)
9482     {
9483         // Type Equivalence is not respected for this comparision as you can have multiple type equivalent interfaces on a class
9484         TokenPairList newVisited = TokenPairList::AdjustForTypeEquivalenceForbiddenScope(NULL);
9485         if (MetaSig::CompareTypeDefsUnderSubstitutions(bmtCheckInfo->ppExactDeclaredInterfaces[i],
9486                                                        pIntf,
9487                                                        bmtCheckInfo->ppInterfaceSubstitutionChains[i],
9488                                                        pItfSubstChain,
9489                                                        &newVisited))
9490             return; // found it, don't add it again
9491     }
9492
9493     // OK, so it isn't a duplicate based on the generic IL, now check if the instantiation
9494     // makes it a duplicate.
9495     for (DWORD i = 0; i < bmtCheckInfo->nAssigned; i++)
9496     {
9497         if (bmtCheckInfo->ppExactDeclaredInterfaces[i] == pIntf)
9498         {
9499                 bmtCheckInfo->pMT->GetModule()->GetAssembly()->ThrowTypeLoadException(bmtCheckInfo->pMT->GetMDImport(),
9500                                                                                       bmtCheckInfo->pMT->GetCl(),
9501                                                                                       IDS_CLASSLOAD_OVERLAPPING_INTERFACES);
9502         }
9503     }
9504
9505     DWORD n = bmtCheckInfo->nAssigned;
9506     bmtCheckInfo->ppExactDeclaredInterfaces[n] = pIntf;
9507     bmtCheckInfo->ppInterfaceSubstitutionChains[n] = new (&GetThread()->m_MarshalAlloc) Substitution[pItfSubstChain->GetLength()];
9508     pItfSubstChain->CopyToArray(bmtCheckInfo->ppInterfaceSubstitutionChains[n]);
9509
9510     bmtCheckInfo->nAssigned++;
9511     InterfacesAmbiguityCheck(bmtCheckInfo,pIntf->GetModule(),pIntf->GetCl(),pItfSubstChain);
9512 }
9513
9514
9515 //*******************************************************************************
9516 void MethodTableBuilder::CheckForSystemTypes()
9517 {
9518     STANDARD_VM_CONTRACT;
9519
9520     LPCUTF8 name, nameSpace;
9521
9522     MethodTable * pMT = GetHalfBakedMethodTable();
9523     EEClass * pClass = GetHalfBakedClass();
9524
9525     // We can exit early for generic types - there are just a few cases to check for.
9526     if (bmtGenerics->HasInstantiation())
9527     {
9528         if (pMT->IsIntrinsicType() && pClass->HasLayout())
9529         {
9530             if (FAILED(GetMDImport()->GetNameOfTypeDef(GetCl(), &name, &nameSpace)))
9531             {
9532                 BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
9533             }
9534
9535             if (strcmp(nameSpace, g_IntrinsicsNS) == 0)
9536             {
9537                 EEClassLayoutInfo * pLayout = pClass->GetLayoutInfo();
9538
9539                 // The SIMD Hardware Intrinsic types correspond to fundamental data types in the underlying ABIs:
9540                 // * Vector64<T>:  __m64
9541                 // * Vector128<T>: __m128
9542                 // * Vector256<T>: __m256
9543
9544                 // These __m128 and __m256 types, among other requirements, are special in that they must always
9545                 // be aligned properly.
9546
9547                 if (strcmp(name, g_Vector64Name) == 0)
9548                 {
9549                     // The System V ABI for i386 defaults to 8-byte alignment for __m64, except for parameter passing,
9550                     // where it has an alignment of 4.
9551
9552                     pLayout->m_LargestAlignmentRequirementOfAllMembers        = 8; // sizeof(__m64)
9553                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 8; // sizeof(__m64)
9554                 }
9555                 else if (strcmp(name, g_Vector128Name) == 0)
9556                 {
9557     #ifdef _TARGET_ARM_
9558                     // The Procedure Call Standard for ARM defaults to 8-byte alignment for __m128
9559
9560                     pLayout->m_LargestAlignmentRequirementOfAllMembers        = 8;
9561                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 8;
9562     #else
9563                     pLayout->m_LargestAlignmentRequirementOfAllMembers        = 16; // sizeof(__m128)
9564                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 16; // sizeof(__m128)
9565     #endif // _TARGET_ARM_
9566                 }
9567                 else if (strcmp(name, g_Vector256Name) == 0)
9568                 {
9569     #ifdef _TARGET_ARM_
9570                     // No such type exists for the Procedure Call Standard for ARM. We will default
9571                     // to the same alignment as __m128, which is supported by the ABI.
9572
9573                     pLayout->m_LargestAlignmentRequirementOfAllMembers        = 8;
9574                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 8;
9575     #elif defined(_TARGET_ARM64_)
9576                     // The Procedure Call Standard for ARM 64-bit (with SVE support) defaults to
9577                     // 16-byte alignment for __m256.
9578
9579                     pLayout->m_LargestAlignmentRequirementOfAllMembers        = 16;
9580                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 16;
9581     #else
9582                     pLayout->m_LargestAlignmentRequirementOfAllMembers        = 32; // sizeof(__m256)
9583                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 32; // sizeof(__m256)
9584     #endif // _TARGET_ARM_ elif _TARGET_ARM64_
9585                 }
9586                 else
9587                 {
9588                     // These types should be handled or explicitly skipped below to ensure that we don't
9589                     // miss adding required ABI support for future types.
9590
9591                     _ASSERTE_MSG(FALSE, "Unhandled Hardware Intrinsic Type.");
9592                 }
9593
9594                 return;
9595             }
9596         }
9597
9598         if (g_pNullableClass != NULL)
9599         {
9600             _ASSERTE(g_pByReferenceClass != NULL);
9601             _ASSERTE(g_pByReferenceClass->IsByRefLike());
9602
9603 #ifdef _TARGET_X86_
9604             if (GetCl() == g_pByReferenceClass->GetCl())
9605             {
9606                 // x86 by default treats the type of ByReference<T> as the actual type of its IntPtr field, see calls to
9607                 // ComputeInternalCorElementTypeForValueType in this file. This is a special case where the struct needs to be
9608                 // treated as a value type so that its field can be considered as a by-ref pointer.
9609                 _ASSERTE(pMT->GetFlag(MethodTable::enum_flag_Category_Mask) == MethodTable::enum_flag_Category_PrimitiveValueType);
9610                 pMT->ClearFlag(MethodTable::enum_flag_Category_Mask);
9611                 pMT->SetInternalCorElementType(ELEMENT_TYPE_VALUETYPE);
9612                 return;
9613             }
9614 #endif
9615
9616             _ASSERTE(g_pNullableClass->IsNullable());
9617
9618             // Pre-compute whether the class is a Nullable<T> so that code:Nullable::IsNullableType is efficient
9619             // This is useful to the performance of boxing/unboxing a Nullable
9620             if (GetCl() == g_pNullableClass->GetCl())
9621                 pMT->SetIsNullable();
9622
9623             return;
9624         }
9625     }
9626
9627     if (IsNested() || IsEnum())
9628         return;
9629
9630     if (FAILED(GetMDImport()->GetNameOfTypeDef(GetCl(), &name, &nameSpace)))
9631     {
9632         BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
9633     }
9634
9635     if (IsValueClass())
9636     {
9637         //
9638         // Value types 
9639         // 
9640
9641         // All special value types are in the system namespace
9642         if (strcmp(nameSpace, g_SystemNS) != 0)
9643             return;
9644
9645         // Check if it is a primitive type 
9646         CorElementType type = CorTypeInfo::FindPrimitiveType(name);
9647         if (type != ELEMENT_TYPE_END)
9648         {
9649             pMT->SetInternalCorElementType(type);
9650             pMT->SetIsTruePrimitive();
9651
9652 #if defined(_TARGET_X86_) && defined(UNIX_X86_ABI)
9653             switch (type)
9654             {
9655                 // The System V ABI for i386 defines different packing for these types.
9656
9657                 case ELEMENT_TYPE_I8:
9658                 case ELEMENT_TYPE_U8:
9659                 case ELEMENT_TYPE_R8:
9660                 {
9661                     EEClassLayoutInfo * pLayout = pClass->GetLayoutInfo();
9662                     pLayout->m_LargestAlignmentRequirementOfAllMembers        = 4;
9663                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 4;
9664                     break;
9665                 }
9666
9667                 default:
9668                     break;
9669             }
9670 #endif // _TARGET_X86_ && UNIX_X86_ABI
9671
9672 #ifdef _DEBUG 
9673             if (FAILED(GetMDImport()->GetNameOfTypeDef(GetCl(), &name, &nameSpace)))
9674             {
9675                 name = nameSpace = "Invalid TypeDef record";
9676             }
9677             LOG((LF_CLASSLOADER, LL_INFO10000, "%s::%s marked as primitive type %i\n", nameSpace, name, type));
9678 #endif // _DEBUG
9679         }
9680         else if (strcmp(name, g_NullableName) == 0)
9681         {
9682             pMT->SetIsNullable();
9683         }
9684 #ifdef _TARGET_X86_
9685         else if (strcmp(name, g_ByReferenceName) == 0)
9686         {
9687             // x86 by default treats the type of ByReference<T> as the actual type of its IntPtr field, see calls to
9688             // ComputeInternalCorElementTypeForValueType in this file. This is a special case where the struct needs to be
9689             // treated as a value type so that its field can be considered as a by-ref pointer.
9690             _ASSERTE(pMT->GetFlag(MethodTable::enum_flag_Category_Mask) == MethodTable::enum_flag_Category_PrimitiveValueType);
9691             pMT->ClearFlag(MethodTable::enum_flag_Category_Mask);
9692             pMT->SetInternalCorElementType(ELEMENT_TYPE_VALUETYPE);
9693         }
9694 #endif
9695 #ifndef _TARGET_X86_ 
9696         else if (strcmp(name, g_RuntimeArgumentHandleName) == 0)
9697         {
9698             pMT->SetInternalCorElementType (ELEMENT_TYPE_I);
9699         }
9700         else if (strcmp(name, g_RuntimeMethodHandleInternalName) == 0)
9701         {
9702             pMT->SetInternalCorElementType (ELEMENT_TYPE_I);
9703         }
9704 #endif
9705 #if defined(ALIGN_ACCESS) || defined(FEATURE_64BIT_ALIGNMENT)
9706         else if (strcmp(name, g_DecimalName) == 0)
9707         {
9708             // This is required because native layout of System.Decimal causes it to be aligned
9709             // differently to the layout of the native DECIMAL structure, which will cause
9710             // data misalignent exceptions if Decimal is embedded in another type.
9711
9712             EEClassLayoutInfo* pLayout = pClass->GetLayoutInfo();
9713             pLayout->m_LargestAlignmentRequirementOfAllMembers        = sizeof(ULONGLONG);
9714             pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = sizeof(ULONGLONG);
9715
9716 #ifdef FEATURE_64BIT_ALIGNMENT
9717             // Also need to mark the type so it will be allocated on a 64-bit boundary for
9718             // platforms that won't do this naturally.
9719             SetAlign8Candidate();
9720 #endif
9721         }
9722 #endif // ALIGN_ACCESS || FEATURE_64BIT_ALIGNMENT
9723     }
9724     else
9725     {
9726         //
9727         // Reference types
9728         // 
9729         if (strcmp(name, g_StringName) == 0 && strcmp(nameSpace, g_SystemNS) == 0)
9730         {
9731             // Strings are not "normal" objects, so we need to mess with their method table a bit
9732             // so that the GC can figure out how big each string is...
9733             DWORD baseSize = ObjSizeOf(StringObject) + sizeof(WCHAR);
9734             pMT->SetBaseSize(baseSize); // NULL character included
9735
9736             GetHalfBakedClass()->SetBaseSizePadding(baseSize - bmtFP->NumInstanceFieldBytes);
9737
9738             pMT->SetComponentSize(2);
9739         }
9740         else if (strcmp(name, g_CriticalFinalizerObjectName) == 0 && strcmp(nameSpace, g_ConstrainedExecutionNS) == 0)
9741         {
9742             // To introduce a class with a critical finalizer,
9743             // we'll set the bit here.
9744             pMT->SetHasCriticalFinalizer();
9745         }
9746 #ifdef FEATURE_COMINTEROP 
9747         else
9748         {
9749             bool bIsComObject = false;
9750             bool bIsRuntimeClass = false;
9751
9752             if (strcmp(name, g_ComObjectName) == 0 && strcmp(nameSpace, g_SystemNS) == 0)
9753                 bIsComObject = true;
9754             
9755             if (strcmp(name, g_RuntimeClassName) == 0 && strcmp(nameSpace, g_WinRTNS) == 0)
9756                 bIsRuntimeClass = true;
9757
9758             if (bIsComObject || bIsRuntimeClass)
9759             {
9760                 // Make System.__ComObject/System.Runtime.InteropServices.WindowsRuntime.RuntimeClass a ComImport type
9761                 // We can't do it using attribute as C# won't allow putting code in ComImport types
9762                 pMT->SetComObjectType();
9763
9764                 // COM objects need an optional field on the EEClass, so ensure this class instance has allocated
9765                 // the optional field descriptor.
9766                 EnsureOptionalFieldsAreAllocated(pClass, m_pAllocMemTracker, GetLoaderAllocator()->GetLowFrequencyHeap());            
9767             }            
9768             
9769             if (bIsRuntimeClass)            
9770             {
9771                 // Note that we set it here to avoid type loader considering RuntimeClass as a normal WindowsImportType 
9772                 // as functions in RuntimeClass doesn't go through COM interop
9773                 GetHalfBakedClass()->SetProjectedFromWinRT();
9774             }
9775         }
9776 #endif // FEATURE_COMINTEROP
9777     }
9778 }
9779
9780 //==========================================================================================
9781 // Helper to create a new method table. This is the only
9782 // way to allocate a new MT. Don't try calling new / ctor.
9783 // Called from SetupMethodTable
9784 // This needs to be kept consistent with MethodTable::GetSavedExtent()
9785 MethodTable * MethodTableBuilder::AllocateNewMT(Module *pLoaderModule,
9786                                          DWORD dwVtableSlots,
9787                                          DWORD dwVirtuals,
9788                                          DWORD dwGCSize,
9789                                          DWORD dwNumInterfaces,
9790                                          DWORD dwNumDicts,
9791                                          DWORD cbInstAndDict,
9792                                          MethodTable *pMTParent,
9793                                          ClassLoader *pClassLoader,
9794                                          LoaderAllocator *pAllocator,
9795                                          BOOL isInterface,
9796                                          BOOL fDynamicStatics,
9797                                          BOOL fHasGenericsStaticsInfo,
9798                                          BOOL fNeedsRCWPerTypeData,
9799                                          BOOL fNeedsRemotableMethodInfo,
9800                                          BOOL fNeedsRemotingVtsInfo,
9801                                          BOOL fHasContextStatics
9802 #ifdef FEATURE_COMINTEROP
9803         , BOOL fHasDynamicInterfaceMap
9804 #endif
9805 #ifdef FEATURE_PREJIT
9806         , Module *pComputedPZM
9807 #endif // FEATURE_PREJIT
9808         , AllocMemTracker *pamTracker
9809     )
9810 {
9811     CONTRACT (MethodTable*)
9812     {
9813         THROWS;
9814         GC_TRIGGERS;
9815         MODE_ANY;
9816         POSTCONDITION(CheckPointer(RETVAL));
9817     }
9818     CONTRACT_END;
9819
9820     DWORD dwNonVirtualSlots = dwVtableSlots - dwVirtuals;
9821
9822     // GCSize must be aligned
9823     _ASSERTE(IS_ALIGNED(dwGCSize, sizeof(void*)));
9824
9825     // size without the interface map
9826     S_SIZE_T cbTotalSize = S_SIZE_T(dwGCSize) + S_SIZE_T(sizeof(MethodTable));
9827
9828     // vtable
9829     cbTotalSize += MethodTable::GetNumVtableIndirections(dwVirtuals) * sizeof(MethodTable::VTableIndir_t);
9830
9831
9832     DWORD dwMultipurposeSlotsMask = 0;
9833     if (dwNumInterfaces != 0)
9834         dwMultipurposeSlotsMask |= MethodTable::enum_flag_HasInterfaceMap;
9835     if (dwNumDicts != 0)
9836         dwMultipurposeSlotsMask |= MethodTable::enum_flag_HasPerInstInfo;
9837     if (bmtVT->pDispatchMapBuilder->Count() > 0)
9838         dwMultipurposeSlotsMask |= MethodTable::enum_flag_HasDispatchMapSlot;
9839     if (dwNonVirtualSlots != 0)
9840         dwMultipurposeSlotsMask |= MethodTable::enum_flag_HasNonVirtualSlots;
9841     if (pLoaderModule != GetModule())
9842         dwMultipurposeSlotsMask |= MethodTable::enum_flag_HasModuleOverride;
9843
9844     // Add space for optional members here. Same as GetOptionalMembersSize()
9845     cbTotalSize += MethodTable::GetOptionalMembersAllocationSize(dwMultipurposeSlotsMask,
9846                                                       fNeedsRemotableMethodInfo,
9847                                                       fHasGenericsStaticsInfo,
9848                                                       FALSE, // no GuidInfo needed for canonical instantiations
9849                                                       FALSE, // no CCW template needed for canonical instantiations
9850                                                       fNeedsRCWPerTypeData,
9851                                                       fNeedsRemotingVtsInfo,
9852                                                       fHasContextStatics,
9853                                                       RidFromToken(GetCl()) >= METHODTABLE_TOKEN_OVERFLOW);
9854
9855     // Interface map starts here
9856     S_SIZE_T offsetOfInterfaceMap = cbTotalSize;
9857
9858     cbTotalSize += S_SIZE_T(dwNumInterfaces) * S_SIZE_T(sizeof(InterfaceInfo_t));
9859
9860 #ifdef FEATURE_COMINTEROP
9861     // DynamicInterfaceMap have an extra DWORD added to the end of the normal interface
9862     // map. This will be used to store the count of dynamically added interfaces
9863     // (the ones that are not in  the metadata but are QI'ed for at runtime).
9864     cbTotalSize += S_SIZE_T(fHasDynamicInterfaceMap ? sizeof(DWORD_PTR) : 0);
9865 #endif
9866
9867     // Dictionary pointers start here
9868     S_SIZE_T offsetOfInstAndDict = cbTotalSize;
9869
9870     if (dwNumDicts != 0)
9871     {
9872         cbTotalSize += sizeof(GenericsDictInfo);
9873         cbTotalSize += S_SIZE_T(dwNumDicts) * S_SIZE_T(sizeof(MethodTable::PerInstInfoElem_t));
9874         cbTotalSize += cbInstAndDict;
9875     }
9876
9877     S_SIZE_T offsetOfUnsharedVtableChunks = cbTotalSize;
9878
9879     BOOL canShareVtableChunks = pMTParent && MethodTable::CanShareVtableChunksFrom(pMTParent, pLoaderModule
9880 #ifdef FEATURE_PREJIT
9881         , pComputedPZM
9882 #endif //FEATURE_PREJIT
9883         );
9884
9885     // If pMTParent has a generic instantiation, we cannot share its vtable chunks
9886     // This is because pMTParent is only approximate at this point, and MethodTableBuilder::CopyExactParentSlots
9887     // may swap in an exact parent that does not satisfy CanShareVtableChunksFrom
9888     if (pMTParent && pMTParent->HasInstantiation())
9889     {
9890         canShareVtableChunks = FALSE;
9891     }
9892
9893     // We will share any parent vtable chunk that does not contain a method we overrode (or introduced)
9894     // For the rest, we need to allocate space
9895     for (DWORD i = 0; i < dwVirtuals; i++)
9896     {
9897         if (!canShareVtableChunks || ChangesImplementationOfVirtualSlot(static_cast<SLOT_INDEX>(i)))
9898         {
9899             DWORD chunkStart = MethodTable::GetStartSlotForVtableIndirection(MethodTable::GetIndexOfVtableIndirection(i), dwVirtuals);
9900             DWORD chunkEnd = MethodTable::GetEndSlotForVtableIndirection(MethodTable::GetIndexOfVtableIndirection(i), dwVirtuals);
9901
9902             cbTotalSize += S_SIZE_T(chunkEnd - chunkStart) * S_SIZE_T(sizeof(PCODE));
9903
9904             i = chunkEnd - 1;
9905         }
9906     }
9907
9908     // Add space for the non-virtual slots array (pointed to by an optional member) if required
9909     // If there is only one non-virtual slot, we store it directly in the optional member and need no array
9910     S_SIZE_T offsetOfNonVirtualSlots = cbTotalSize;
9911     if (dwNonVirtualSlots > 1)
9912     {
9913         cbTotalSize += S_SIZE_T(dwNonVirtualSlots) * S_SIZE_T(sizeof(PCODE));
9914     }
9915
9916     BYTE *pData = (BYTE *)pamTracker->Track(pAllocator->GetHighFrequencyHeap()->AllocMem(cbTotalSize));
9917
9918     _ASSERTE(IS_ALIGNED(pData, sizeof(size_t)));
9919     
9920     // There should be no overflows if we have allocated the memory succesfully
9921     _ASSERTE(!cbTotalSize.IsOverflow());
9922
9923     MethodTable* pMT = (MethodTable*)(pData + dwGCSize);
9924
9925     pMT->SetMultipurposeSlotsMask(dwMultipurposeSlotsMask);
9926
9927     MethodTableWriteableData * pMTWriteableData = (MethodTableWriteableData *) (BYTE *)
9928         pamTracker->Track(pAllocator->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(MethodTableWriteableData))));
9929     // Note: Memory allocated on loader heap is zero filled
9930     pMT->SetWriteableData(pMTWriteableData);
9931
9932     // This also disables IBC logging until the type is sufficiently intitialized so
9933     // it needs to be done early
9934     pMTWriteableData->SetIsNotFullyLoadedForBuildMethodTable();
9935
9936 #ifdef _DEBUG
9937     pClassLoader->m_dwGCSize += dwGCSize;
9938     pClassLoader->m_dwInterfaceMapSize += (dwNumInterfaces * sizeof(InterfaceInfo_t));
9939     pClassLoader->m_dwMethodTableSize += (DWORD)cbTotalSize.Value();
9940     pClassLoader->m_dwVtableData += (dwVtableSlots * sizeof(PCODE));
9941 #endif // _DEBUG
9942
9943     // There should be no overflows if we have allocated the memory succesfully
9944     _ASSERTE(!offsetOfUnsharedVtableChunks.IsOverflow());
9945     _ASSERTE(!offsetOfNonVirtualSlots.IsOverflow());
9946     _ASSERTE(!offsetOfInterfaceMap.IsOverflow());
9947     _ASSERTE(!offsetOfInstAndDict.IsOverflow());
9948
9949     // initialize the total number of slots
9950     pMT->SetNumVirtuals(static_cast<WORD>(dwVirtuals));
9951
9952     pMT->SetParentMethodTable(pMTParent);
9953
9954     // Fill out the vtable indirection slots
9955     SIZE_T dwCurrentUnsharedSlotOffset = offsetOfUnsharedVtableChunks.Value();
9956     MethodTable::VtableIndirectionSlotIterator it = pMT->IterateVtableIndirectionSlots();
9957     while (it.Next())
9958     {
9959         BOOL shared = canShareVtableChunks;
9960
9961         // Recalculate whether we will share this chunk
9962         if (canShareVtableChunks)
9963         {
9964             for (DWORD i = it.GetStartSlot(); i < it.GetEndSlot(); i++)
9965             {
9966                 if (ChangesImplementationOfVirtualSlot(static_cast<SLOT_INDEX>(i)))
9967                 {
9968                     shared = FALSE;
9969                     break;
9970                 }
9971             }
9972         }
9973
9974         if (shared)
9975         {
9976             // Share the parent chunk
9977             _ASSERTE(it.GetEndSlot() <= pMTParent->GetNumVirtuals());
9978             it.SetIndirectionSlot(pMTParent->GetVtableIndirections()[it.GetIndex()].GetValueMaybeNull());
9979         }
9980         else
9981         {
9982             // Use the locally allocated chunk
9983             it.SetIndirectionSlot((PTR_PCODE)(pData+dwCurrentUnsharedSlotOffset));
9984             dwCurrentUnsharedSlotOffset += it.GetSize();
9985         }
9986     }
9987
9988 #ifdef FEATURE_COMINTEROP
9989     // Extensible RCW's are prefixed with the count of dynamic interfaces.
9990     if (fHasDynamicInterfaceMap)
9991     {
9992         _ASSERTE (dwNumInterfaces > 0);
9993         pMT->SetInterfaceMap ((WORD) (dwNumInterfaces), (InterfaceInfo_t*)(pData+offsetOfInterfaceMap.Value()+sizeof(DWORD_PTR)));
9994
9995         *(((DWORD_PTR *)pMT->GetInterfaceMap()) - 1) = 0;
9996     }
9997     else
9998 #endif // FEATURE_COMINTEROP
9999     {
10000         // interface map is at the end of the vtable
10001         pMT->SetInterfaceMap ((WORD) dwNumInterfaces, (InterfaceInfo_t *)(pData+offsetOfInterfaceMap.Value()));
10002     }
10003
10004     _ASSERTE(((WORD) dwNumInterfaces) == dwNumInterfaces);
10005
10006     if (fDynamicStatics)
10007     {
10008         pMT->SetDynamicStatics(fHasGenericsStaticsInfo);
10009     }
10010
10011     if (dwNonVirtualSlots > 0)
10012     {
10013         if (dwNonVirtualSlots > 1)
10014         {
10015             pMT->SetNonVirtualSlotsArray((PTR_PCODE)(pData+offsetOfNonVirtualSlots.Value()));
10016         }
10017         else
10018         {
10019             pMT->SetHasSingleNonVirtualSlot();
10020         }
10021     }
10022
10023     // the dictionary pointers follow the interface map
10024     if (dwNumDicts)
10025     {
10026         MethodTable::PerInstInfoElem_t *pPerInstInfo = (MethodTable::PerInstInfoElem_t *)(pData + offsetOfInstAndDict.Value() + sizeof(GenericsDictInfo));
10027
10028         pMT->SetPerInstInfo ( pPerInstInfo);
10029
10030         // Fill in the dictionary for this type, if it's instantiated
10031         if (cbInstAndDict)
10032         {
10033             MethodTable::PerInstInfoElem_t *pPInstInfo = (MethodTable::PerInstInfoElem_t *)(pPerInstInfo + (dwNumDicts-1));
10034             pPInstInfo->SetValueMaybeNull((Dictionary*) (pPerInstInfo + dwNumDicts));
10035         }
10036     }
10037
10038 #ifdef _DEBUG
10039     pMT->m_pWriteableData.GetValue()->m_dwLastVerifedGCCnt = (DWORD)-1;
10040 #endif // _DEBUG
10041
10042     RETURN(pMT);
10043 }
10044
10045     
10046 //*******************************************************************************
10047 //
10048 // Used by BuildMethodTable
10049 //
10050 // Setup the method table
10051 //
10052 #ifdef _PREFAST_ 
10053 #pragma warning(push)
10054 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
10055 #endif // _PREFAST_
10056
10057 VOID
10058 MethodTableBuilder::SetupMethodTable2(
10059         Module * pLoaderModule 
10060 #ifdef FEATURE_PREJIT
10061         , Module * pComputedPZM 
10062 #endif // FEATURE_PREJIT
10063     )
10064 {
10065     CONTRACTL
10066     {
10067         STANDARD_VM_CHECK;
10068         PRECONDITION(CheckPointer(this));
10069         PRECONDITION(CheckPointer(bmtVT));
10070         PRECONDITION(CheckPointer(bmtInterface));
10071         PRECONDITION(CheckPointer(bmtInternal));
10072         PRECONDITION(CheckPointer(bmtProp));
10073         PRECONDITION(CheckPointer(bmtMFDescs));
10074         PRECONDITION(CheckPointer(bmtEnumFields));
10075         PRECONDITION(CheckPointer(bmtError));
10076         PRECONDITION(CheckPointer(bmtMetaData));
10077         PRECONDITION(CheckPointer(bmtParent));
10078         PRECONDITION(CheckPointer(bmtGenerics));
10079     }
10080     CONTRACTL_END;
10081
10082     DWORD i;
10083
10084 #ifdef FEATURE_COMINTEROP 
10085     BOOL fHasDynamicInterfaceMap = bmtInterface->dwInterfaceMapSize > 0 &&
10086                                    bmtProp->fIsComObjectType &&
10087                                    (GetParentMethodTable() != g_pObjectClass);
10088     BOOL fNeedsRCWPerTypeData = bmtProp->fNeedsRCWPerTypeData;
10089 #else // FEATURE_COMINTEROP
10090     BOOL fNeedsRCWPerTypeData = FALSE;
10091 #endif // FEATURE_COMINTEROP
10092
10093     EEClass *pClass = GetHalfBakedClass();
10094
10095     DWORD cbDict = bmtGenerics->HasInstantiation()
10096                    ?  DictionaryLayout::GetFirstDictionaryBucketSize(
10097                           bmtGenerics->GetNumGenericArgs(), pClass->GetDictionaryLayout())
10098                    : 0;
10099
10100
10101     BOOL fHasContextStatics = FALSE;
10102     BOOL fNeedsRemotableMethodInfo=FALSE;
10103     BOOL fNeedsRemotingVtsInfo = FALSE;
10104
10105 #ifdef FEATURE_COLLECTIBLE_TYPES
10106     BOOL fCollectible = pLoaderModule->IsCollectible();
10107 #endif // FEATURE_COLLECTIBLE_TYPES
10108
10109     DWORD dwGCSize;
10110     
10111     if (bmtFP->NumGCPointerSeries > 0)
10112     {
10113         dwGCSize = (DWORD)CGCDesc::ComputeSize(bmtFP->NumGCPointerSeries);
10114     }
10115     else
10116     {
10117 #ifdef FEATURE_COLLECTIBLE_TYPES
10118         if (fCollectible)
10119             dwGCSize = (DWORD)CGCDesc::ComputeSize(1);
10120         else
10121 #endif // FEATURE_COLLECTIBLE_TYPES
10122             dwGCSize = 0;
10123     }
10124
10125     pClass->SetNumMethods(bmtVT->cTotalSlots);
10126     pClass->SetNumNonVirtualSlots(bmtVT->cVtableSlots - bmtVT->cVirtualSlots);
10127
10128     // Now setup the method table
10129     // interface map is allocated along with the method table
10130     MethodTable *pMT = AllocateNewMT(pLoaderModule,
10131                                    bmtVT->cVtableSlots,
10132                                    bmtVT->cVirtualSlots,
10133                                    dwGCSize,
10134                                    bmtInterface->dwInterfaceMapSize,
10135                                    bmtGenerics->numDicts,
10136                                    cbDict,
10137                                    GetParentMethodTable(),
10138                                    GetClassLoader(),
10139                                    bmtAllocator,
10140                                    IsInterface(),
10141                                    bmtProp->fDynamicStatics,
10142                                    bmtProp->fGenericsStatics,
10143                                    fNeedsRCWPerTypeData,
10144                                    fNeedsRemotableMethodInfo,
10145                                    fNeedsRemotingVtsInfo,
10146                                    fHasContextStatics,
10147 #ifdef FEATURE_COMINTEROP 
10148                                    fHasDynamicInterfaceMap,
10149 #endif
10150 #ifdef FEATURE_PREJIT
10151                                    pComputedPZM,
10152 #endif //FEATURE_PREJIT
10153                                    GetMemTracker());
10154
10155     pMT->SetClass(pClass);
10156     pClass->m_pMethodTable.SetValue(pMT);
10157     m_pHalfBakedMT = pMT;
10158
10159 #ifdef _DEBUG 
10160     pMT->SetDebugClassName(GetDebugClassName());
10161 #endif
10162
10163 #ifdef FEATURE_COMINTEROP
10164     if (fNeedsRCWPerTypeData)
10165         pMT->SetHasRCWPerTypeData();
10166 #endif // FEATURE_COMINTEROP
10167
10168
10169     if (IsInterface())
10170         pMT->SetIsInterface();
10171
10172     if (GetParentMethodTable() != NULL)
10173     {
10174         if (GetParentMethodTable()->HasModuleDependencies())
10175         {
10176             pMT->SetHasModuleDependencies();
10177         }
10178         else
10179         {
10180             Module * pModule = GetModule();
10181             Module * pParentModule = GetParentMethodTable()->GetModule();
10182             if (pModule != pParentModule && !pModule->HasUnconditionalActiveDependency(pParentModule))
10183             {
10184                 pMT->SetHasModuleDependencies();
10185             }
10186         }
10187
10188         if (GetParentMethodTable()->HasPreciseInitCctors() || !pClass->IsBeforeFieldInit())
10189         {
10190             pMT->SetHasPreciseInitCctors();
10191         }
10192     }
10193
10194     // Must be done early because various methods test HasInstantiation() and ContainsGenericVariables()
10195     if (bmtGenerics->GetNumGenericArgs() != 0)
10196     {
10197         pMT->SetHasInstantiation(bmtGenerics->fTypicalInstantiation, bmtGenerics->fSharedByGenericInstantiations);
10198
10199         if (bmtGenerics->fContainsGenericVariables)
10200             pMT->SetContainsGenericVariables();
10201     }
10202
10203     if (bmtGenerics->numDicts != 0)
10204     {
10205         if (!FitsIn<WORD>(bmtGenerics->GetNumGenericArgs()))
10206         {
10207             BuildMethodTableThrowException(IDS_CLASSLOAD_TOOMANYGENERICARGS);
10208         }
10209
10210         pMT->SetDictInfo(bmtGenerics->numDicts,
10211             static_cast<WORD>(bmtGenerics->GetNumGenericArgs()));
10212     }
10213
10214     CONSISTENCY_CHECK(pMT->GetNumGenericArgs() == bmtGenerics->GetNumGenericArgs());
10215     CONSISTENCY_CHECK(pMT->GetNumDicts() == bmtGenerics->numDicts);
10216     CONSISTENCY_CHECK(pMT->HasInstantiation() == bmtGenerics->HasInstantiation());
10217     CONSISTENCY_CHECK(pMT->HasInstantiation() == !pMT->GetInstantiation().IsEmpty());
10218
10219     pMT->SetLoaderModule(pLoaderModule);
10220     pMT->SetLoaderAllocator(bmtAllocator);
10221
10222     pMT->SetModule(GetModule());
10223
10224     pMT->SetInternalCorElementType (ELEMENT_TYPE_CLASS);
10225
10226     SetNonGCRegularStaticFieldBytes (bmtProp->dwNonGCRegularStaticFieldBytes);
10227     SetNonGCThreadStaticFieldBytes (bmtProp->dwNonGCThreadStaticFieldBytes);
10228
10229 #ifdef FEATURE_TYPEEQUIVALENCE
10230     if (bmtProp->fHasTypeEquivalence)
10231     {
10232         pMT->SetHasTypeEquivalence();
10233     }
10234 #endif //FEATURE_TYPEEQUIVALENCE
10235
10236 #ifdef FEATURE_COMINTEROP 
10237     if (bmtProp->fSparse)
10238         pClass->SetSparseForCOMInterop();
10239
10240     if (IsInterface() && IsComImport())
10241     {
10242         // Determine if we are creating an interface methodtable that may be used to dispatch through VSD
10243         // on an object that has the methodtable of __ComObject.
10244
10245         // This is done to allow COM tearoff interfaces, but as a side-effect of this feature,
10246         // we end up using a domain-shared type (__ComObject) with a domain-specific dispatch token.
10247         // This is a problem because the same domain-specific dispatch token value can appear in
10248         // multiple unshared domains (VSD takes advantage of the fact that in general a shared type
10249         // cannot implement an unshared interface). This means that the same <token, __ComObject> pair
10250         // value can mean different things in different domains (since the token could represent
10251         // IFoo in one domain and IBar in another). This is a problem because the
10252         // VSD polymorphic lookup mechanism relies on a process-wide cache table, and as a result
10253         // these duplicate values would collide if we didn't use fat dispatch token to ensure uniqueness
10254         // and the interface methodtable is not in the shared domain.
10255
10256         pMT->SetRequiresFatDispatchTokens();
10257     }
10258 #endif // FEATURE_COMINTEROP
10259
10260     if (bmtVT->pCCtor != NULL)
10261     {
10262         pMT->SetHasClassConstructor();
10263         CONSISTENCY_CHECK(pMT->GetClassConstructorSlot() == bmtVT->pCCtor->GetSlotIndex());
10264     }
10265     if (bmtVT->pDefaultCtor != NULL)
10266     {
10267         pMT->SetHasDefaultConstructor();
10268         CONSISTENCY_CHECK(pMT->GetDefaultConstructorSlot() == bmtVT->pDefaultCtor->GetSlotIndex());
10269     }
10270
10271     for (MethodDescChunk *pChunk = GetHalfBakedClass()->GetChunks(); pChunk != NULL; pChunk = pChunk->GetNextChunk())
10272     {
10273         pChunk->SetMethodTable(pMT);
10274     }
10275
10276 #ifdef _DEBUG 
10277     {
10278         // disable ibc logging because we can assert in ComputerPreferredZapModule for partially constructed
10279         // generic types 
10280         IBCLoggingDisabler disableLogging;
10281
10282         DeclaredMethodIterator it(*this);
10283         while (it.Next())
10284         {
10285             MethodDesc *pMD = it->GetMethodDesc();
10286             if (pMD != NULL)
10287             {
10288                 pMD->m_pDebugMethodTable.SetValue(pMT);
10289                 pMD->m_pszDebugMethodSignature = FormatSig(pMD, GetLoaderAllocator()->GetLowFrequencyHeap(), GetMemTracker());
10290             }
10291             MethodDesc *pUnboxedMD = it->GetUnboxedMethodDesc();
10292             if (pUnboxedMD != NULL)
10293             {
10294                 pUnboxedMD->m_pDebugMethodTable.SetValue(pMT);
10295                 pUnboxedMD->m_pszDebugMethodSignature = FormatSig(pUnboxedMD, GetLoaderAllocator()->GetLowFrequencyHeap(), GetMemTracker());
10296             }
10297         }
10298     }
10299 #endif // _DEBUG
10300
10301     // Note that for value classes, the following calculation is only appropriate
10302     // when the instance is in its "boxed" state.
10303     if (!IsInterface())
10304     {
10305         DWORD baseSize = Max<DWORD>(bmtFP->NumInstanceFieldBytes + ObjSizeOf(Object), MIN_OBJECT_SIZE);
10306         baseSize = (baseSize + ALLOC_ALIGN_CONSTANT) & ~ALLOC_ALIGN_CONSTANT;  // m_BaseSize must be aligned
10307         pMT->SetBaseSize(baseSize);
10308
10309         GetHalfBakedClass()->SetBaseSizePadding(baseSize - bmtFP->NumInstanceFieldBytes);
10310
10311 #ifdef FEATURE_COMINTEROP 
10312         if (bmtProp->fIsComObjectType)
10313         {   // Propagate the com specific info
10314             pMT->SetComObjectType();
10315
10316             // COM objects need an optional field on the EEClass, so ensure this class instance has allocated
10317             // the optional field descriptor.
10318             EnsureOptionalFieldsAreAllocated(pClass, m_pAllocMemTracker, GetLoaderAllocator()->GetLowFrequencyHeap());
10319         }
10320
10321         if (pMT->GetAssembly()->IsManagedWinMD())
10322         {
10323             // We need to mark classes that are implementations of managed WinRT runtime classes with
10324             // the "exported to WinRT" flag. It's not quite possible to tell which ones these are by
10325             // reading metadata so we ask the adapter.
10326
10327             IWinMDImport *pWinMDImport = pMT->GetAssembly()->GetManifestWinMDImport();
10328             _ASSERTE(pWinMDImport != NULL);
10329
10330             BOOL bResult;
10331             IfFailThrow(pWinMDImport->IsRuntimeClassImplementation(GetCl(), &bResult));
10332                 
10333             if (bResult)
10334             {
10335                 pClass->SetExportedToWinRT();
10336
10337                 // We need optional fields for activation from WinRT.
10338                 EnsureOptionalFieldsAreAllocated(pClass, m_pAllocMemTracker, GetLoaderAllocator()->GetLowFrequencyHeap());
10339             }
10340         }
10341
10342         if (pClass->IsProjectedFromWinRT() || pClass->IsExportedToWinRT())
10343         {
10344             const BYTE *        pVal;                 
10345             ULONG               cbVal;        
10346             HRESULT hr = GetMDImport()->GetCustomAttributeByName(GetCl(), g_WindowsFoundationMarshalingBehaviorAttributeClassName, (const void **) &pVal, &cbVal);
10347             if (hr == S_OK)
10348             {
10349                 CustomAttributeParser cap(pVal, cbVal);
10350                 IfFailThrow(cap.SkipProlog());
10351                 UINT32 u = 0;
10352                 IfFailThrow(cap.GetU4(&u));
10353                 if(u > 0)
10354                     pClass->SetMarshalingType(u);
10355             }
10356         }
10357 #endif // FEATURE_COMINTEROP
10358     }
10359     else
10360     {
10361 #ifdef FEATURE_COMINTEROP 
10362         // If this is an interface then we need to set the ComInterfaceType to
10363         // -1 to indicate we have not yet determined the interface type.
10364         pClass->SetComInterfaceType((CorIfaceAttr)-1);
10365
10366         // If this is a special COM event interface, then mark the MT as such.
10367         if (bmtProp->fComEventItfType)
10368         {
10369             pClass->SetComEventItfType();
10370         }
10371 #endif // FEATURE_COMINTEROP
10372     }
10373     _ASSERTE((pMT->IsInterface() == 0) == (IsInterface() == 0));
10374
10375     if (HasLayout())
10376     {
10377         pClass->SetNativeSize(GetLayoutInfo()->GetNativeSize());
10378     }
10379
10380     FieldDesc *pFieldDescList = pClass->GetFieldDescList();
10381     // Set all field slots to point to the newly created MethodTable
10382     for (i = 0; i < (bmtEnumFields->dwNumStaticFields + bmtEnumFields->dwNumInstanceFields); i++)
10383     {
10384         pFieldDescList[i].m_pMTOfEnclosingClass.SetValue(pMT);
10385     }
10386
10387     // Fill in type parameters before looking up exact parent or fetching the types of any field descriptors!
10388     // This must come before the use of GetFieldType in the value class representation optimization below.
10389     if (bmtGenerics->GetNumGenericArgs() != 0)
10390     {
10391         // Space has already been allocated for the instantiation but the parameters haven't been filled in
10392         Instantiation destInst = pMT->GetInstantiation();
10393         Instantiation inst = bmtGenerics->GetInstantiation();
10394
10395         // So fill them in...
10396         TypeHandle * pInstDest = (TypeHandle *)destInst.GetRawArgs();
10397         for (DWORD j = 0; j < bmtGenerics->GetNumGenericArgs(); j++)
10398         {
10399             pInstDest[j] = inst[j];
10400         }
10401     }
10402
10403     CorElementType normalizedType = ELEMENT_TYPE_CLASS;
10404     if (IsValueClass())
10405     {
10406         if (IsEnum())
10407         {
10408             if (GetNumInstanceFields() != 1 ||
10409                 !CorTypeInfo::IsPrimitiveType(pFieldDescList[0].GetFieldType()))
10410             {
10411                 BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil);
10412             }
10413             CONSISTENCY_CHECK(!pFieldDescList[0].IsStatic());
10414             normalizedType = pFieldDescList->GetFieldType();
10415         }
10416         else
10417         {
10418 #ifdef _TARGET_X86_ 
10419             // JIT64 is not aware of normalized value types and this
10420             // optimization (return small value types by value in registers)
10421             // is already done in JIT64.
10422             OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOADED);
10423             normalizedType = EEClass::ComputeInternalCorElementTypeForValueType(pMT);
10424 #else
10425             normalizedType = ELEMENT_TYPE_VALUETYPE;
10426 #endif
10427         }
10428     }
10429     pMT->SetInternalCorElementType(normalizedType);
10430
10431     // If this type is marked by [Intrinsic] attribute, it may be specially treated by the runtime/compiler
10432     // Currently, only SIMD types have [Intrinsic] attribute
10433     //
10434     // We check this here fairly early to ensure other downstream checks on these types can be slightly more efficient.
10435     if ((GetModule()->IsSystem() || GetAssembly()->IsSIMDVectorAssembly()) && IsValueClass() && bmtGenerics->HasInstantiation())
10436     {
10437         HRESULT hr = GetMDImport()->GetCustomAttributeByName(bmtInternal->pType->GetTypeDefToken(), 
10438             g_CompilerServicesIntrinsicAttribute, 
10439             NULL, 
10440             NULL);
10441
10442         if (hr == S_OK)
10443         {
10444             pMT->SetIsIntrinsicType();
10445         }
10446     }
10447
10448     if (GetModule()->IsSystem())
10449     {
10450         // we are in mscorlib
10451         CheckForSystemTypes();
10452     }
10453
10454     // Now fill in the real interface map with the approximate interfaces
10455     if (bmtInterface->dwInterfaceMapSize > 0)
10456     {
10457         // First ensure we have enough space to record extra flag information for each interface (we don't
10458         // record this directly into each interface map entry since these flags don't pack well due to
10459         // alignment).
10460         PVOID pExtraInterfaceInfo = NULL;
10461         SIZE_T cbExtraInterfaceInfo = MethodTable::GetExtraInterfaceInfoSize(bmtInterface->dwInterfaceMapSize);
10462         if (cbExtraInterfaceInfo)
10463             pExtraInterfaceInfo = GetMemTracker()->Track(GetLoaderAllocator()->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(cbExtraInterfaceInfo)));
10464
10465         // Call this even in the case where pExtraInterfaceInfo == NULL (certain cases are optimized and don't
10466         // require extra buffer space).
10467         pMT->InitializeExtraInterfaceInfo(pExtraInterfaceInfo);
10468
10469         InterfaceInfo_t *pInterfaces = pMT->GetInterfaceMap();
10470
10471         CONSISTENCY_CHECK(CheckPointer(pInterfaces));
10472
10473         // Copy the interface map member by member so there is no junk in the padding.
10474         for (i = 0; i < bmtInterface->dwInterfaceMapSize; i++)
10475         {
10476             bmtInterfaceEntry * pEntry = &bmtInterface->pInterfaceMap[i];
10477
10478             if (pEntry->IsDeclaredOnType())
10479                 pMT->SetInterfaceDeclaredOnClass(i);
10480             _ASSERTE(!!pEntry->IsDeclaredOnType() == !!pMT->IsInterfaceDeclaredOnClass(i));
10481
10482             pInterfaces[i].SetMethodTable(pEntry->GetInterfaceType()->GetMethodTable());
10483         }
10484     }
10485
10486     pMT->SetCl(GetCl());
10487
10488     // The type is sufficiently initialized for most general purpose accessor methods to work.
10489     // Mark the type as restored to avoid avoid asserts. Note that this also enables IBC logging.
10490     pMT->GetWriteableDataForWrite_NoLogging()->SetIsRestoredForBuildMethodTable();
10491
10492 #ifdef _DEBUG
10493     // Store status if we tried to inject duplicate interfaces
10494     if (bmtInterface->dbg_fShouldInjectInterfaceDuplicates)
10495         pMT->Debug_SetHasInjectedInterfaceDuplicates();
10496 #endif //_DEBUG
10497
10498     // Keep bmtInterface data around since we no longer write the flags (IsDeclaredOnType and
10499     // IsImplementedByParent) into the interface map (these flags are only required during type loading).
10500
10501     {
10502         for (MethodDescChunk *pChunk = GetHalfBakedClass()->GetChunks(); pChunk != NULL; pChunk = pChunk->GetNextChunk())
10503         {
10504             // Make sure that temporary entrypoints are create for methods. NGEN uses temporary
10505             // entrypoints as surrogate keys for precodes.
10506             pChunk->EnsureTemporaryEntryPointsCreated(GetLoaderAllocator(), GetMemTracker());
10507         }
10508     }
10509
10510     {   // copy onto the real vtable (methods only)
10511         //@GENERICS: Because we sometimes load an inexact parent (see ClassLoader::GetParent) the inherited slots might
10512         // come from the wrong place and need fixing up once we know the exact parent
10513
10514         for (bmtVtable::Iterator slotIt = bmtVT->IterateSlots(); !slotIt.AtEnd(); ++slotIt)
10515         {
10516             SLOT_INDEX iCurSlot = static_cast<SLOT_INDEX>(slotIt.CurrentIndex());
10517
10518             // We want the unboxed MethodDesc if we're out of the virtual method range
10519             // and the method we're dealing with has an unboxing method. If so, then
10520             // the unboxing method was placed in the virtual section of the vtable and
10521             // we now need to place the unboxed version.
10522             MethodDesc * pMD = NULL;
10523             if (iCurSlot < bmtVT->cVirtualSlots || !slotIt->Impl().AsMDMethod()->IsUnboxing())
10524             {
10525                 pMD = slotIt->Impl().GetMethodDesc();
10526                 CONSISTENCY_CHECK(slotIt->Decl().GetSlotIndex() == iCurSlot);
10527             }
10528             else
10529             {
10530                 pMD = slotIt->Impl().AsMDMethod()->GetUnboxedMethodDesc();
10531                 CONSISTENCY_CHECK(pMD->GetSlot() == iCurSlot);
10532             }
10533
10534             CONSISTENCY_CHECK(CheckPointer(pMD));
10535
10536             if (pMD->GetMethodTable() != pMT)
10537             {
10538                 //
10539                 // Inherited slots
10540                 //
10541                 // Do not write into vtable chunks shared with parent. It would introduce race 
10542                 // with code:MethodDesc::SetStableEntryPointInterlocked.
10543                 //
10544                 DWORD indirectionIndex = MethodTable::GetIndexOfVtableIndirection(iCurSlot);
10545                 if (GetParentMethodTable()->GetVtableIndirections()[indirectionIndex].GetValueMaybeNull() != pMT->GetVtableIndirections()[indirectionIndex].GetValueMaybeNull())
10546                     pMT->SetSlot(iCurSlot, pMD->GetMethodEntryPoint());
10547             }
10548             else
10549             {
10550                 //
10551                 // Owned slots
10552                 //
10553                 _ASSERTE(iCurSlot >= bmtVT->cVirtualSlots || ChangesImplementationOfVirtualSlot(iCurSlot));
10554
10555                 PCODE addr = pMD->GetTemporaryEntryPoint();
10556                 _ASSERTE(addr != NULL);
10557
10558                 if (pMD->HasNonVtableSlot())
10559                 {
10560                     *pMD->GetAddrOfSlot() = addr;
10561                 }
10562                 else
10563                 {
10564                     pMT->SetSlot(iCurSlot, addr);
10565                 }
10566
10567                 if (pMD->GetSlot() == iCurSlot && pMD->RequiresStableEntryPoint())
10568                 {
10569                     // The rest of the system assumes that certain methods always have stable entrypoints.
10570                     // Create them now.
10571                     pMD->GetOrCreatePrecode();
10572                 }
10573             }
10574         }
10575     }
10576
10577     // If we have any entries, then finalize them and allocate the object in class loader heap
10578     DispatchMap                 *pDispatchMap        = NULL;
10579     DispatchMapBuilder          *pDispatchMapBuilder = bmtVT->pDispatchMapBuilder;
10580     CONSISTENCY_CHECK(CheckPointer(pDispatchMapBuilder));
10581
10582     if (pDispatchMapBuilder->Count() > 0)
10583     {
10584         // Create a map in stacking memory.
10585         BYTE * pbMap;
10586         UINT32 cbMap;
10587         DispatchMap::CreateEncodedMapping(
10588             pMT, 
10589             pDispatchMapBuilder, 
10590             pDispatchMapBuilder->GetAllocator(), 
10591             &pbMap, 
10592             &cbMap);
10593
10594         // Now finalize the impltable and allocate the block in the low frequency loader heap
10595         size_t objSize = (size_t) DispatchMap::GetObjectSize(cbMap);
10596         void * pv = AllocateFromLowFrequencyHeap(S_SIZE_T(objSize));
10597         _ASSERTE(pv != NULL);
10598
10599         // Use placement new
10600         pDispatchMap = new (pv) DispatchMap(pbMap, cbMap);
10601         pMT->SetDispatchMap(pDispatchMap);
10602
10603 #ifdef LOGGING 
10604         g_sdStats.m_cDispatchMap++;
10605         g_sdStats.m_cbDispatchMap += (UINT32) objSize;
10606         LOG((LF_LOADER, LL_INFO1000, "SD: Dispatch map for %s: %d bytes for map, %d bytes total for object.\n",
10607             pMT->GetDebugClassName(), cbMap, objSize));
10608 #endif // LOGGING
10609
10610     }
10611
10612     // GetMethodData by default will cache its result. However, in the case that we're
10613     // building a MethodTable, we aren't guaranteed that this type is going to successfully
10614     // load and so caching it would result in errors down the road since the memory and
10615     // type occupying the same memory location would very likely be incorrect. The second
10616     // argument specifies that GetMethodData should not cache the returned object.
10617     MethodTable::MethodDataWrapper hMTData(MethodTable::GetMethodData(pMT, FALSE));
10618
10619     if (!IsInterface())
10620     {
10621         // Propagate inheritance.
10622
10623         // NOTE: In the world of unfolded interface this was used to propagate overrides into
10624         //       the unfolded interface vtables to make sure that overrides of virtual methods
10625         //       also overrode the interface methods that they contributed to. This had the
10626         //       unfortunate side-effect of also overwriting regular vtable slots that had been
10627         //       methodimpl'd and as a result changed the meaning of methodimpl from "substitute
10628         //       the body of method A with the body of method B" to "unify the slots of methods
10629         //       A and B". But now compilers have come to rely on this side-effect and it can
10630         //       not be brought back to its originally intended behaviour.
10631
10632         // For every slot whose body comes from another slot (determined by getting the MethodDesc
10633         // for a slot and seeing if MethodDesc::GetSlot returns a different value than the slot
10634         // from which the MethodDesc was recovered), copy the value of the slot stated by the
10635         // MethodDesc over top of the current slot.
10636
10637         // Because of the way slot unification works, we need to iterate the enture vtable until
10638         // no slots need updated. To understand this, imagine the following:
10639         //      C1::M1 is overridden by C2::M2
10640         //      C1::M2 is methodImpled by C1::M3
10641         //      C1::M3 is overridden by C2::M3
10642         // This should mean that C1::M1 is implemented by C2::M3, but if we didn't run the below
10643         // for loop a second time, this would not be propagated properly - it would only be placed
10644         // into the slot for C1::M2 and never make its way up to C1::M1.
10645         
10646         BOOL fChangeMade;
10647         do
10648         {
10649             fChangeMade = FALSE;
10650             for (i = 0; i < pMT->GetNumVirtuals(); i++)
10651             {
10652                 MethodDesc* pMD = hMTData->GetImplMethodDesc(i);
10653
10654                 CONSISTENCY_CHECK(CheckPointer(pMD));
10655                 CONSISTENCY_CHECK(pMD == pMT->GetMethodDescForSlot(i));
10656
10657                 // This indicates that the method body in this slot was copied here through a methodImpl.
10658                 // Thus, copy the value of the slot from which the body originally came, in case it was
10659                 // overridden, to make sure the two slots stay in sync.
10660                 INDEBUG(MethodDesc * pMDOld; pMDOld = pMD;)
10661                 if(pMD->GetSlot() != i &&
10662                    pMT->GetSlot(i) != pMT->GetSlot(pMD->GetSlot()))
10663                 {
10664                     // Copy the slot value in the method's original slot.
10665                     pMT->SetSlot(i,pMT->GetSlot(pMD->GetSlot()));
10666                     hMTData->InvalidateCachedVirtualSlot(i);
10667
10668                     // Update the pMD to the new method desc we just copied over ourselves with. This will
10669                     // be used in the check for missing method block below.
10670                     pMD = pMT->GetMethodDescForSlot(pMD->GetSlot());
10671
10672                     // This method is now duplicate
10673                     pMD->SetDuplicate();
10674                     INDEBUG(g_dupMethods++;)
10675                     fChangeMade = TRUE;
10676                 }
10677             }
10678         }
10679         while (fChangeMade);
10680     }
10681
10682     if (!bmtProp->fNoSanityChecks)
10683         VerifyVirtualMethodsImplemented(hMTData);
10684
10685 #ifdef _DEBUG 
10686     {
10687         for (bmtVtable::Iterator i = bmtVT->IterateSlots();
10688              !i.AtEnd(); ++i)
10689         {
10690             _ASSERTE(i->Impl().GetMethodDesc() != NULL);
10691         }
10692     }
10693 #endif // _DEBUG
10694
10695
10696 #ifdef FEATURE_COMINTEROP 
10697     // for ComObject types, i.e. if the class extends from a COM Imported
10698     // class
10699     // make sure any interface implementated by the COM Imported class
10700     // is overridden fully, (OR) not overridden at all..
10701     // We relax this for WinRT where we want to be able to override individual methods.
10702     if (bmtProp->fIsComObjectType && !pMT->IsWinRTObjectType())
10703     {
10704         MethodTable::InterfaceMapIterator intIt = pMT->IterateInterfaceMap();
10705         while (intIt.Next())
10706         {
10707             MethodTable* pIntfMT = intIt.GetInterface();
10708             if (pIntfMT->GetNumVirtuals() != 0)
10709             {
10710                 BOOL hasComImportMethod = FALSE;
10711                 BOOL hasManagedMethod = FALSE;
10712
10713                 // NOTE: Avoid caching the MethodData object for the type being built.
10714                 MethodTable::MethodDataWrapper hItfImplData(MethodTable::GetMethodData(pIntfMT, pMT, FALSE));
10715                 MethodTable::MethodIterator it(hItfImplData);
10716                 for (;it.IsValid(); it.Next())
10717                 {
10718                     MethodDesc *pClsMD = NULL;
10719                     // If we fail to find an _IMPLEMENTATION_ for the interface MD, then
10720                     // we are a ComImportMethod, otherwise we still be a ComImportMethod or
10721                     // we can be a ManagedMethod.
10722                     DispatchSlot impl(it.GetTarget());
10723                     if (!impl.IsNull())
10724                     {
10725                         pClsMD = it.GetMethodDesc();
10726
10727                         CONSISTENCY_CHECK(!pClsMD->IsInterface());
10728                         if (pClsMD->GetClass()->IsComImport())
10729                         {
10730                             hasComImportMethod = TRUE;
10731                         }
10732                         else
10733                         {
10734                             hasManagedMethod = TRUE;
10735                         }
10736                     }
10737                     else
10738                     {
10739                         // Need to set the pClsMD for the error reporting below.
10740                         pClsMD = it.GetDeclMethodDesc();
10741                         CONSISTENCY_CHECK(CheckPointer(pClsMD));
10742                         hasComImportMethod = TRUE;
10743                     }
10744
10745                     // One and only one of the two must be set.
10746                     if ((hasComImportMethod && hasManagedMethod) ||
10747                         (!hasComImportMethod && !hasManagedMethod))
10748                     {
10749                         BuildMethodTableThrowException(IDS_EE_BAD_COMEXTENDS_CLASS, pClsMD->GetNameOnNonArrayClass());
10750                     }
10751                 }
10752             }
10753         }
10754     }
10755
10756     // For COM event interfaces, we need to make sure that all the methods are
10757     // methods to add or remove events. This means that they all need to take
10758     // a delegate derived class and have a void return type.
10759     if (bmtProp->fComEventItfType)
10760     {
10761         // COM event interfaces had better be interfaces.
10762         CONSISTENCY_CHECK(IsInterface());
10763
10764         // Go through all the methods and check the validity of the signature.
10765         // NOTE: Uses hMTData to avoid caching a MethodData object for the type being built.
10766         MethodTable::MethodIterator it(hMTData);
10767         for (;it.IsValid(); it.Next())
10768         {
10769             MethodDesc* pMD = it.GetMethodDesc();
10770             _ASSERTE(pMD);
10771
10772             MetaSig Sig(pMD);
10773
10774             {
10775                 CONTRACT_VIOLATION(LoadsTypeViolation);
10776                 if (Sig.GetReturnType() != ELEMENT_TYPE_VOID ||
10777                     Sig.NumFixedArgs() != 1 ||
10778                     Sig.NextArg() != ELEMENT_TYPE_CLASS ||
10779                     !Sig.GetLastTypeHandleThrowing().CanCastTo(TypeHandle(g_pDelegateClass)))
10780                 {
10781                     BuildMethodTableThrowException(IDS_EE_BAD_COMEVENTITF_CLASS, pMD->GetNameOnNonArrayClass());
10782                 }
10783             }
10784         }
10785     }
10786 #endif // FEATURE_COMINTEROP
10787
10788     // If this class uses any VTS (Version Tolerant Serialization) features
10789     // (event callbacks or OptionalField attributes) we've previously cached the
10790     // additional information in the bmtMFDescs structure. Now it's time to add
10791     // this information as an optional extension to the MethodTable.
10792 }
10793 #ifdef _PREFAST_ 
10794 #pragma warning(pop)
10795 #endif
10796
10797 // Returns true if there is at least one default implementation for this interface method
10798 // We don't care about conflicts at this stage in order to avoid impact type load performance
10799 BOOL MethodTableBuilder::HasDefaultInterfaceImplementation(MethodDesc *pDeclMD)
10800 {
10801     STANDARD_VM_CONTRACT;
10802
10803 #ifdef FEATURE_DEFAULT_INTERFACES
10804     // If the interface method is already non-abstract, we are done
10805     if (pDeclMD->IsDefaultInterfaceMethod())
10806         return TRUE;
10807
10808     MethodTable *pDeclMT = pDeclMD->GetMethodTable();
10809
10810     // Otherwise, traverse the list of interfaces and see if there is at least one override 
10811     bmtInterfaceInfo::MapIterator intIt = bmtInterface->IterateInterfaceMap();
10812     for (; !intIt.AtEnd(); intIt.Next())
10813     {
10814         MethodTable *pIntfMT = intIt->GetInterfaceType()->GetMethodTable();
10815         if (pIntfMT->GetClass()->ContainsMethodImpls() && pIntfMT->CanCastToInterface(pDeclMT))
10816         {
10817             MethodTable::MethodIterator methodIt(pIntfMT);
10818             for (; methodIt.IsValid(); methodIt.Next())
10819             {
10820                 MethodDesc *pMD = methodIt.GetMethodDesc();
10821                 if (pMD->IsMethodImpl())
10822                 {
10823                     MethodImpl::Iterator it(pMD);
10824                     while (it.IsValid())
10825                     {
10826                         if (it.GetMethodDesc() == pDeclMD)
10827                             return TRUE;
10828                     }
10829                 }
10830             }
10831         }
10832     }
10833 #endif // FEATURE_DEFAULT_INTERFACES
10834
10835     return FALSE;
10836 }
10837
10838 void MethodTableBuilder::VerifyVirtualMethodsImplemented(MethodTable::MethodData * hMTData)
10839 {
10840     STANDARD_VM_CONTRACT;
10841
10842     //
10843     // This verification is not applicable or required in many cases
10844     //
10845
10846     if (IsAbstract() || IsInterface())
10847         return;
10848
10849 #ifdef FEATURE_COMINTEROP
10850     // Note that this is important for WinRT where redirected .NET interfaces appear on the interface
10851     // impl list but their methods are not implemented (the adapter only hides the WinRT methods, it
10852     // does not make up the .NET ones).
10853     if (bmtProp->fIsComObjectType)
10854         return;
10855 #endif // FEATURE_COMINTEROP
10856
10857     // Since interfaces aren't laid out in the vtable for stub dispatch, what we need to do
10858     // is try to find an implementation for every interface contract by iterating through
10859     // the interfaces not declared on a parent.
10860     BOOL fParentIsAbstract = FALSE;
10861     if (HasParent())
10862     {
10863         fParentIsAbstract = GetParentMethodTable()->IsAbstract();
10864     }
10865
10866     // If the parent is abstract, we need to check that each virtual method is implemented
10867     if (fParentIsAbstract)
10868     {
10869         // NOTE: Uses hMTData to avoid caching a MethodData object for the type being built.
10870         MethodTable::MethodIterator it(hMTData);
10871         for (; it.IsValid() && it.IsVirtual(); it.Next())
10872         {
10873             MethodDesc *pMD = it.GetMethodDesc();
10874             if (pMD->IsAbstract())
10875             {
10876                 MethodDesc *pDeclMD = it.GetDeclMethodDesc();
10877                 BuildMethodTableThrowException(IDS_CLASSLOAD_NOTIMPLEMENTED, pDeclMD->GetNameOnNonArrayClass());
10878             }
10879         }
10880     }
10881         
10882     DispatchMapTypeID * rgInterfaceDispatchMapTypeIDs = 
10883         new (GetStackingAllocator()) DispatchMapTypeID[bmtInterface->dwInterfaceMapSize];
10884         
10885     bmtInterfaceInfo::MapIterator intIt = bmtInterface->IterateInterfaceMap();
10886     for (; !intIt.AtEnd(); intIt.Next())
10887     {
10888         if (fParentIsAbstract || !intIt->IsImplementedByParent())
10889         {
10890             // Compute all TypeIDs for this interface (all duplicates in the interface map)
10891             UINT32 cInterfaceDuplicates;
10892             ComputeDispatchMapTypeIDs(
10893                 intIt->GetInterfaceType()->GetMethodTable(), 
10894                 &intIt->GetInterfaceType()->GetSubstitution(), 
10895                 rgInterfaceDispatchMapTypeIDs, 
10896                 bmtInterface->dwInterfaceMapSize, 
10897                 &cInterfaceDuplicates);
10898             _ASSERTE(cInterfaceDuplicates <= bmtInterface->dwInterfaceMapSize);
10899             _ASSERTE(cInterfaceDuplicates > 0);
10900                 
10901             // NOTE: This override does not cache the resulting MethodData object.
10902             MethodTable::MethodDataWrapper hData(MethodTable::GetMethodData(
10903                 rgInterfaceDispatchMapTypeIDs, 
10904                 cInterfaceDuplicates, 
10905                 intIt->GetInterfaceType()->GetMethodTable(), 
10906                 GetHalfBakedMethodTable()));
10907             MethodTable::MethodIterator it(hData);
10908             for (; it.IsValid() && it.IsVirtual(); it.Next())
10909             {
10910                 if (it.GetTarget().IsNull())
10911                 {
10912                     MethodDesc *pMD = it.GetDeclMethodDesc();
10913
10914                     if (!HasDefaultInterfaceImplementation(pMD))
10915                         BuildMethodTableThrowException(IDS_CLASSLOAD_NOTIMPLEMENTED, pMD->GetNameOnNonArrayClass());
10916                 }
10917             }
10918         }
10919     }
10920 }
10921
10922 INT32 __stdcall IsDefined(Module *pModule, mdToken token, TypeHandle attributeClass)
10923 {
10924     CONTRACTL
10925     {
10926         THROWS;
10927         GC_TRIGGERS;
10928     }
10929     CONTRACTL_END;
10930
10931     BOOL isDefined = FALSE;
10932
10933     IMDInternalImport *pInternalImport = pModule->GetMDImport();
10934     BOOL isSealed = FALSE;
10935
10936     HENUMInternalHolder hEnum(pInternalImport);
10937     TypeHandle caTH;
10938
10939     // Get the enum first but don't get any values
10940     hEnum.EnumInit(mdtCustomAttribute, token);
10941
10942     ULONG cMax = pInternalImport->EnumGetCount(&hEnum);
10943     if (cMax)
10944     {
10945         // we have something to look at
10946
10947
10948         if (!attributeClass.IsNull())
10949             isSealed = attributeClass.GetMethodTable()->IsSealed();
10950
10951         // Loop through the Attributes and look for the requested one
10952         mdCustomAttribute cv;
10953         while (pInternalImport->EnumNext(&hEnum, &cv))
10954         {
10955             //
10956             // fetch the ctor
10957             mdToken     tkCtor;
10958             IfFailThrow(pInternalImport->GetCustomAttributeProps(cv, &tkCtor));
10959             
10960             mdToken tkType = TypeFromToken(tkCtor);
10961             if(tkType != mdtMemberRef && tkType != mdtMethodDef)
10962                 continue; // we only deal with the ctor case
10963
10964             //
10965             // get the info to load the type, so we can check whether the current
10966             // attribute is a subtype of the requested attribute
10967             IfFailThrow(pInternalImport->GetParentToken(tkCtor, &tkType));
10968             
10969             _ASSERTE(TypeFromToken(tkType) == mdtTypeRef || TypeFromToken(tkType) == mdtTypeDef);
10970             // load the type
10971             if (isSealed)
10972             {
10973                 caTH=ClassLoader::LoadTypeDefOrRefThrowing(pModule, tkType,
10974                                                            ClassLoader::ReturnNullIfNotFound,
10975                                                            ClassLoader::FailIfUninstDefOrRef,
10976                                                            TypeFromToken(tkType) == mdtTypeDef ? tdAllTypes : tdNoTypes);
10977             }
10978             else
10979             {
10980                 caTH = ClassLoader::LoadTypeDefOrRefThrowing(pModule, tkType,
10981                                                              ClassLoader::ReturnNullIfNotFound,
10982                                                              ClassLoader::FailIfUninstDefOrRef);
10983             }
10984             if (caTH.IsNull())
10985                 continue;
10986
10987             // a null class implies all custom attribute
10988             if (!attributeClass.IsNull())
10989             {
10990                 if (isSealed)
10991                 {
10992                     if (attributeClass != caTH)
10993                         continue;
10994                 }
10995                 else
10996                 {
10997                     if (!caTH.CanCastTo(attributeClass))
10998                         continue;
10999                 }
11000             }
11001
11002             //
11003             // if we are here we got one
11004             isDefined = TRUE;
11005             break;
11006         }
11007     }
11008
11009     return isDefined;
11010 }
11011
11012 //*******************************************************************************
11013 VOID MethodTableBuilder::CheckForRemotingProxyAttrib()
11014 {
11015     STANDARD_VM_CONTRACT;
11016
11017 }
11018
11019
11020 //*******************************************************************************
11021 // Checks for a bunch of special interface names and if it matches then it sets
11022 // bmtProp->fIsMngStandardItf to TRUE. Additionally, it checks to see if the
11023 // type is an interface and if it has ComEventInterfaceAttribute custom attribute
11024 // set, then it sets bmtProp->fComEventItfType to true.
11025 //
11026 // NOTE: This only does anything when COM interop is enabled.
11027
11028 VOID MethodTableBuilder::CheckForSpecialTypes()
11029 {
11030 #ifdef FEATURE_COMINTEROP
11031     STANDARD_VM_CONTRACT;
11032
11033
11034     Module *pModule = GetModule();
11035     IMDInternalImport *pMDImport = pModule->GetMDImport();
11036
11037     // Check to see if this type is a managed standard interface. All the managed
11038     // standard interfaces live in mscorlib.dll so checking for that first
11039     // makes the strcmp that comes afterwards acceptable.
11040     if (pModule->IsSystem())
11041     {
11042         if (IsInterface())
11043         {
11044             LPCUTF8 pszClassName;
11045             LPCUTF8 pszClassNamespace;
11046             if (FAILED(pMDImport->GetNameOfTypeDef(GetCl(), &pszClassName, &pszClassNamespace)))
11047             {
11048                 pszClassName = pszClassNamespace = NULL;
11049             }
11050             if ((pszClassName != NULL) && (pszClassNamespace != NULL))
11051             {
11052                 LPUTF8 pszFullyQualifiedName = NULL;
11053                 MAKE_FULLY_QUALIFIED_NAME(pszFullyQualifiedName, pszClassNamespace, pszClassName);
11054
11055                 // This is just to give us a scope to break out of.
11056                 do
11057                 {
11058
11059 #define MNGSTDITF_BEGIN_INTERFACE(FriendlyName, strMngItfName, strUCOMMngItfName, strCustomMarshalerName, strCustomMarshalerCookie, strManagedViewName, NativeItfIID, bCanCastOnNativeItfQI) \
11060                     if (strcmp(strMngItfName, pszFullyQualifiedName) == 0) \
11061                     { \
11062                         bmtProp->fIsMngStandardItf = true; \
11063                         break; \
11064                     }
11065
11066 #define MNGSTDITF_DEFINE_METH_IMPL(FriendlyName, ECallMethName, MethName, MethSig, FcallDecl)
11067
11068 #define MNGSTDITF_END_INTERFACE(FriendlyName)
11069
11070 #include "mngstditflist.h"
11071
11072 #undef MNGSTDITF_BEGIN_INTERFACE
11073 #undef MNGSTDITF_DEFINE_METH_IMPL
11074 #undef MNGSTDITF_END_INTERFACE
11075
11076                 } while (FALSE);
11077
11078                 if (strcmp(pszFullyQualifiedName, g_CollectionsGenericCollectionItfName) == 0 ||
11079                     strcmp(pszFullyQualifiedName, g_CollectionsGenericReadOnlyCollectionItfName) == 0 ||
11080                     strcmp(pszFullyQualifiedName, g_CollectionsCollectionItfName) == 0)
11081                 {
11082                     // ICollection`1, ICollection and IReadOnlyCollection`1 are special cases the adapter is unaware of
11083                     bmtProp->fIsRedirectedInterface = true;
11084                 }
11085                 else
11086                 {
11087                     if (strcmp(pszFullyQualifiedName, WinMDAdapter::GetRedirectedTypeFullCLRName(WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_IEnumerable)) == 0 ||
11088                         strcmp(pszFullyQualifiedName, WinMDAdapter::GetRedirectedTypeFullCLRName(WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_IList)) == 0 ||
11089                         strcmp(pszFullyQualifiedName, WinMDAdapter::GetRedirectedTypeFullCLRName(WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_IDictionary)) == 0 ||
11090                         strcmp(pszFullyQualifiedName, WinMDAdapter::GetRedirectedTypeFullCLRName(WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_IReadOnlyList)) == 0 ||
11091                         strcmp(pszFullyQualifiedName, WinMDAdapter::GetRedirectedTypeFullCLRName(WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_IReadOnlyDictionary)) == 0 ||
11092                         strcmp(pszFullyQualifiedName, WinMDAdapter::GetRedirectedTypeFullCLRName(WinMDAdapter::RedirectedTypeIndex_System_Collections_IEnumerable)) == 0 ||
11093                         strcmp(pszFullyQualifiedName, WinMDAdapter::GetRedirectedTypeFullCLRName(WinMDAdapter::RedirectedTypeIndex_System_Collections_IList)) == 0 ||
11094                         strcmp(pszFullyQualifiedName, WinMDAdapter::GetRedirectedTypeFullCLRName(WinMDAdapter::RedirectedTypeIndex_System_IDisposable)) == 0)
11095                     {
11096                         bmtProp->fIsRedirectedInterface = true;
11097                     }
11098                 }
11099
11100                 // We want to allocate the per-type RCW data optional MethodTable field for
11101                 // 1. Redirected interfaces
11102                 // 2. Mscorlib-declared [WindowsRuntimeImport] interfaces
11103                 bmtProp->fNeedsRCWPerTypeData = (bmtProp->fIsRedirectedInterface || GetHalfBakedClass()->IsProjectedFromWinRT());
11104
11105                 if (!bmtProp->fNeedsRCWPerTypeData)
11106                 {
11107                     // 3. Non-generic IEnumerable
11108                     if (strcmp(pszFullyQualifiedName, g_CollectionsEnumerableItfName) == 0)
11109                     {
11110                         bmtProp->fNeedsRCWPerTypeData = true;
11111                     }
11112                 }
11113             }
11114         }
11115         else if (IsDelegate() && bmtGenerics->HasInstantiation())
11116         {
11117             // 4. Redirected delegates
11118             if (GetHalfBakedClass()->GetWinRTRedirectedTypeIndex()
11119                 != WinMDAdapter::RedirectedTypeIndex_Invalid)
11120             {
11121                 bmtProp->fNeedsRCWPerTypeData = true;
11122             }
11123         }
11124     }
11125     else if (bmtGenerics->HasInstantiation() && pModule->GetAssembly()->IsWinMD())
11126     {
11127         // 5. WinRT types with variance
11128         if (bmtGenerics->pVarianceInfo != NULL)
11129         {
11130             bmtProp->fNeedsRCWPerTypeData = true;
11131         }
11132         else if (IsInterface())
11133         {
11134             // 6. Windows.Foundation.Collections.IIterator`1
11135             LPCUTF8 pszClassName;
11136             LPCUTF8 pszClassNamespace;
11137             if (SUCCEEDED(pMDImport->GetNameOfTypeDef(GetCl(), &pszClassName, &pszClassNamespace)))
11138             {
11139                 LPUTF8 pszFullyQualifiedName = NULL;
11140                 MAKE_FULLY_QUALIFIED_NAME(pszFullyQualifiedName, pszClassNamespace, pszClassName);
11141
11142                 if (strcmp(pszFullyQualifiedName, g_WinRTIIteratorClassName) == 0)
11143                 {
11144                     bmtProp->fNeedsRCWPerTypeData = true;
11145                 }
11146             }
11147         }
11148     }
11149     else if ((IsInterface() || IsDelegate()) && 
11150         IsTdPublic(GetHalfBakedClass()->GetAttrClass()) && 
11151         GetHalfBakedClass()->GetWinRTRedirectedTypeIndex() != WinMDAdapter::RedirectedTypeIndex_Invalid)
11152     {
11153         // 7. System.Collections.Specialized.INotifyCollectionChanged
11154         // 8. System.Collections.Specialized.NotifyCollectionChangedEventHandler
11155         // 9. System.ComponentModel.INotifyPropertyChanged
11156         // 10. System.ComponentModel.PropertyChangedEventHandler
11157         // 11. System.Windows.Input.ICommand
11158         LPCUTF8 pszClassName;
11159         LPCUTF8 pszClassNamespace;
11160         if (SUCCEEDED(pMDImport->GetNameOfTypeDef(GetCl(), &pszClassName, &pszClassNamespace)))
11161         {
11162             LPUTF8 pszFullyQualifiedName = NULL;
11163             MAKE_FULLY_QUALIFIED_NAME(pszFullyQualifiedName, pszClassNamespace, pszClassName);
11164
11165             if (strcmp(pszFullyQualifiedName, g_INotifyCollectionChangedName) == 0 ||
11166                 strcmp(pszFullyQualifiedName, g_NotifyCollectionChangedEventHandlerName) == 0 ||
11167                 strcmp(pszFullyQualifiedName, g_INotifyPropertyChangedName) == 0 ||
11168                 strcmp(pszFullyQualifiedName, g_PropertyChangedEventHandlerName) == 0 ||
11169                 strcmp(pszFullyQualifiedName, g_ICommandName) == 0)
11170             {
11171                 bmtProp->fNeedsRCWPerTypeData = true;
11172             }
11173         }
11174     }
11175
11176     // Check to see if the type is a COM event interface (classic COM interop only).
11177     if (IsInterface() && !GetHalfBakedClass()->IsProjectedFromWinRT())
11178     {
11179         HRESULT hr = pMDImport->GetCustomAttributeByName(GetCl(), INTEROP_COMEVENTINTERFACE_TYPE, NULL, NULL);
11180         if (hr == S_OK)
11181         {
11182             bmtProp->fComEventItfType = true;
11183         }
11184     }
11185 #endif // FEATURE_COMINTEROP
11186 }
11187
11188 #ifdef FEATURE_READYTORUN
11189 //*******************************************************************************
11190 VOID MethodTableBuilder::CheckLayoutDependsOnOtherModules(MethodTable * pDependencyMT)
11191 {
11192     STANDARD_VM_CONTRACT;
11193
11194     // These cases are expected to be handled by the caller
11195     _ASSERTE(!(pDependencyMT == g_pObjectClass || pDependencyMT->IsTruePrimitive() || ((g_pEnumClass != NULL) && pDependencyMT->IsEnum())));
11196
11197     //
11198     // WARNING: Changes in this algorithm are potential ReadyToRun breaking changes !!!
11199     //
11200     // Track whether field layout of this type depend on information outside its containing module
11201     //
11202     // It is a stronger condition than MethodTable::IsInheritanceChainLayoutFixedInCurrentVersionBubble(). 
11203     // It has to remain fixed accross versioning changes in the module dependencies. In particular, it does 
11204     // not take into account NonVersionable attribute. Otherwise, adding NonVersionable attribute to existing
11205     // type would be ReadyToRun incompatible change.
11206     //
11207     if (pDependencyMT->GetModule() == GetModule())
11208     {
11209         if (!pDependencyMT->GetClass()->HasLayoutDependsOnOtherModules())
11210             return;
11211     }
11212
11213     GetHalfBakedClass()->SetHasLayoutDependsOnOtherModules();
11214 }
11215
11216 BOOL MethodTableBuilder::NeedsAlignedBaseOffset()
11217 {
11218     STANDARD_VM_CONTRACT;
11219
11220     //
11221     // WARNING: Changes in this algorithm are potential ReadyToRun breaking changes !!!
11222     //
11223     // This method returns whether the type needs aligned base offset in order to have layout resilient to 
11224     // base class layout changes.
11225     //
11226     if (IsValueClass())
11227         return FALSE;
11228
11229     // Always use the ReadyToRun field layout algorithm if the source IL image was ReadyToRun, independent on
11230     // whether ReadyToRun is actually enabled for the module. It is required to allow mixing and matching 
11231     // ReadyToRun images with NGen.
11232     if (!GetModule()->GetFile()->IsILImageReadyToRun())
11233     {
11234         // Always use ReadyToRun field layout algorithm to produce ReadyToRun images
11235         if (!IsReadyToRunCompilation())
11236             return FALSE;
11237     }
11238
11239     MethodTable * pParentMT = GetParentMethodTable();
11240
11241     // Trivial parents
11242     if (pParentMT == NULL || pParentMT == g_pObjectClass)
11243         return FALSE;
11244
11245     if (pParentMT->GetModule() == GetModule())
11246     {
11247         if (!pParentMT->GetClass()->HasLayoutDependsOnOtherModules())
11248             return FALSE;
11249     }
11250
11251     return TRUE;
11252 }
11253 #endif // FEATURE_READYTORUN
11254
11255 //*******************************************************************************
11256 //
11257 // Used by BuildMethodTable
11258 //
11259 // Set the HasFinalizer and HasCriticalFinalizer flags
11260 //
11261 VOID MethodTableBuilder::SetFinalizationSemantics()
11262 {
11263     STANDARD_VM_CONTRACT;
11264
11265     if (g_pObjectFinalizerMD && !IsInterface() && !IsValueClass())
11266     {
11267         WORD slot = g_pObjectFinalizerMD->GetSlot();
11268
11269         // Objects not derived from Object will get marked as having a finalizer, if they have 
11270         // sufficient virtual methods.  This will only be an issue if they can be allocated 
11271         // in the GC heap (which will cause all sorts of other problems).
11272         if (slot < bmtVT->cVirtualSlots && (*bmtVT)[slot].Impl().GetMethodDesc() != g_pObjectFinalizerMD)
11273         {
11274             GetHalfBakedMethodTable()->SetHasFinalizer();
11275
11276             // The need for a critical finalizer can be inherited from a parent.
11277             // Since we set this automatically for CriticalFinalizerObject
11278             // elsewhere, the code below is the means by which any derived class
11279             // picks up the attribute.
11280             if (HasParent() && GetParentMethodTable()->HasCriticalFinalizer())
11281             {
11282                 GetHalfBakedMethodTable()->SetHasCriticalFinalizer();
11283             }
11284         }
11285     }
11286 }
11287
11288 //*******************************************************************************
11289 //
11290 // Used by BuildMethodTable
11291 //
11292 // Perform relevant GC calculations for value classes
11293 //
11294 VOID MethodTableBuilder::HandleGCForValueClasses(MethodTable ** pByValueClassCache)
11295 {
11296     STANDARD_VM_CONTRACT;
11297
11298     DWORD i;
11299
11300     EEClass *pClass = GetHalfBakedClass();
11301     MethodTable *pMT = GetHalfBakedMethodTable();
11302
11303     FieldDesc *pFieldDescList = pClass->GetFieldDescList();
11304
11305     // Note that for value classes, the following calculation is only appropriate
11306     // when the instance is in its "boxed" state.
11307 #ifdef FEATURE_COLLECTIBLE_TYPES
11308     if (bmtFP->NumGCPointerSeries == 0 && pMT->Collectible())
11309     {
11310         // For collectible types, insert empty gc series
11311         CGCDescSeries *pSeries;
11312
11313         CGCDesc::Init( (PVOID) pMT, 1);
11314         pSeries = ((CGCDesc*)pMT)->GetLowestSeries();
11315         pSeries->SetSeriesSize( (size_t) (0) - (size_t) pMT->GetBaseSize());
11316         pSeries->SetSeriesOffset(sizeof(Object));
11317     }
11318     else
11319 #endif // FEATURE_COLLECTIBLE_TYPES
11320     if (bmtFP->NumGCPointerSeries != 0)
11321     {
11322         CGCDescSeries *pSeries;
11323         CGCDescSeries *pHighest;
11324
11325         pMT->SetContainsPointers();
11326
11327         // Copy the pointer series map from the parent
11328         CGCDesc::Init( (PVOID) pMT, bmtFP->NumGCPointerSeries );
11329         if (bmtParent->NumParentPointerSeries != 0)
11330         {
11331             size_t ParentGCSize = CGCDesc::ComputeSize(bmtParent->NumParentPointerSeries);
11332             memcpy( (PVOID) (((BYTE*) pMT) - ParentGCSize),
11333                     (PVOID) (((BYTE*) GetParentMethodTable()) - ParentGCSize),
11334                     ParentGCSize - sizeof(size_t)   // sizeof(size_t) is the NumSeries count
11335                   );
11336
11337         }
11338
11339         // Build the pointer series map for this pointers in this instance
11340         pSeries = ((CGCDesc*)pMT)->GetLowestSeries();
11341         if (bmtFP->NumInstanceGCPointerFields)
11342         {
11343             // See gcdesc.h for an explanation of why we adjust by subtracting BaseSize
11344             pSeries->SetSeriesSize( (size_t) (bmtFP->NumInstanceGCPointerFields * sizeof(OBJECTREF)) - (size_t) pMT->GetBaseSize());
11345             pSeries->SetSeriesOffset(bmtFP->GCPointerFieldStart+sizeof(Object));
11346             pSeries++;
11347         }
11348
11349         // Insert GC info for fields which are by-value classes
11350         for (i = 0; i < bmtEnumFields->dwNumInstanceFields; i++)
11351         {
11352             if (pFieldDescList[i].IsByValue())
11353             {
11354                 MethodTable *pByValueMT = pByValueClassCache[i];
11355
11356                 if (pByValueMT->ContainsPointers())
11357                 {
11358                     // Offset of the by value class in the class we are building, does NOT include Object
11359                     DWORD       dwCurrentOffset = pFieldDescList[i].GetOffset_NoLogging();
11360
11361                     // The by value class may have more than one pointer series
11362                     CGCDescSeries * pByValueSeries = CGCDesc::GetCGCDescFromMT(pByValueMT)->GetLowestSeries();
11363                     SIZE_T dwNumByValueSeries = CGCDesc::GetCGCDescFromMT(pByValueMT)->GetNumSeries();
11364
11365                     for (SIZE_T j = 0; j < dwNumByValueSeries; j++)
11366                     {
11367                         size_t cbSeriesSize;
11368                         size_t cbSeriesOffset;
11369
11370                         _ASSERTE(pSeries <= CGCDesc::GetCGCDescFromMT(pMT)->GetHighestSeries());
11371
11372                         cbSeriesSize = pByValueSeries->GetSeriesSize();
11373
11374                         // Add back the base size of the by value class, since it's being transplanted to this class
11375                         cbSeriesSize += pByValueMT->GetBaseSize();
11376
11377                         // Subtract the base size of the class we're building
11378                         cbSeriesSize -= pMT->GetBaseSize();
11379
11380                         // Set current series we're building
11381                         pSeries->SetSeriesSize(cbSeriesSize);
11382
11383                         // Get offset into the value class of the first pointer field (includes a +Object)
11384                         cbSeriesOffset = pByValueSeries->GetSeriesOffset();
11385
11386                         // Add it to the offset of the by value class in our class
11387                         cbSeriesOffset += dwCurrentOffset;
11388
11389                         pSeries->SetSeriesOffset(cbSeriesOffset); // Offset of field
11390                         pSeries++;
11391                         pByValueSeries++;
11392                     }
11393                 }
11394             }
11395         }
11396
11397         // Adjust the inherited series - since the base size has increased by "# new field instance bytes", we need to
11398         // subtract that from all the series (since the series always has BaseSize subtracted for it - see gcdesc.h)
11399         pHighest = CGCDesc::GetCGCDescFromMT(pMT)->GetHighestSeries();
11400         while (pSeries <= pHighest)
11401         {
11402             CONSISTENCY_CHECK(CheckPointer(GetParentMethodTable()));
11403             pSeries->SetSeriesSize( pSeries->GetSeriesSize() - ((size_t) pMT->GetBaseSize() - (size_t) GetParentMethodTable()->GetBaseSize()) );
11404             pSeries++;
11405         }
11406
11407         _ASSERTE(pSeries-1 <= CGCDesc::GetCGCDescFromMT(pMT)->GetHighestSeries());
11408     }
11409
11410 }
11411
11412 //*******************************************************************************
11413 //
11414 // Used by BuildMethodTable
11415 //
11416 // Check for the presence of type equivalence. If present, make sure
11417 // it is permitted to be on this type.
11418 //
11419
11420 void MethodTableBuilder::CheckForTypeEquivalence(
11421     WORD                     cBuildingInterfaceList,
11422     BuildingInterfaceInfo_t *pBuildingInterfaceList)
11423 {
11424     STANDARD_VM_CONTRACT;
11425
11426 #ifdef FEATURE_TYPEEQUIVALENCE
11427     bmtProp->fIsTypeEquivalent = !!IsTypeDefEquivalent(GetCl(), GetModule());
11428
11429     if (bmtProp->fIsTypeEquivalent)
11430     {
11431         BOOL fTypeEquivalentNotPermittedDueToType = !(((IsComImport() || bmtProp->fComEventItfType) && IsInterface()) || IsValueClass() || IsDelegate());
11432         BOOL fTypeEquivalentNotPermittedDueToGenerics = bmtGenerics->HasInstantiation();
11433
11434         if (fTypeEquivalentNotPermittedDueToType || fTypeEquivalentNotPermittedDueToGenerics)
11435         {
11436             BuildMethodTableThrowException(IDS_CLASSLOAD_EQUIVALENTBADTYPE);
11437         }
11438
11439         GetHalfBakedClass()->SetIsEquivalentType();
11440     }
11441
11442     bmtProp->fHasTypeEquivalence = bmtProp->fIsTypeEquivalent;
11443
11444     if (!bmtProp->fHasTypeEquivalence)
11445     {
11446         // fHasTypeEquivalence flag is inherited from interfaces so we can quickly detect
11447         // types that implement type equivalent interfaces
11448         for (WORD i = 0; i < cBuildingInterfaceList; i++)
11449         {
11450             MethodTable *pItfMT = pBuildingInterfaceList[i].m_pMethodTable;
11451             if (pItfMT->HasTypeEquivalence())
11452             {
11453                 bmtProp->fHasTypeEquivalence = true;
11454                 break;
11455             }
11456         }
11457     }
11458
11459     if (!bmtProp->fHasTypeEquivalence)
11460     {
11461         // fHasTypeEquivalence flag is "inherited" from generic arguments so we can quickly detect
11462         // types like List<Str> where Str is a structure with the TypeIdentifierAttribute.
11463         if (bmtGenerics->HasInstantiation() && !bmtGenerics->IsTypicalTypeDefinition())
11464         {
11465             Instantiation inst = bmtGenerics->GetInstantiation();
11466             for (DWORD i = 0; i < inst.GetNumArgs(); i++) 
11467             {
11468                 if (inst[i].HasTypeEquivalence())
11469                 {
11470                     bmtProp->fHasTypeEquivalence = true;
11471                     break;
11472                 }
11473             }
11474         }
11475     }
11476 #endif //FEATURE_TYPEEQUIVALENCE
11477 }
11478
11479 //*******************************************************************************
11480 //
11481 // Used by BuildMethodTable
11482 //
11483 // Before we make the final leap, make sure we've allocated all memory needed to
11484 // fill out the RID maps.
11485 //
11486 VOID MethodTableBuilder::EnsureRIDMapsCanBeFilled()
11487 {
11488     STANDARD_VM_CONTRACT;
11489
11490
11491     DWORD i;
11492
11493
11494     // Rather than call Ensure***CanBeStored() hundreds of times, we
11495     // will call it once on the largest token we find. This relies
11496     // on an invariant that RidMaps don't use some kind of sparse
11497     // allocation.
11498
11499     {
11500         mdMethodDef largest = mdMethodDefNil;
11501
11502         DeclaredMethodIterator it(*this);
11503         while (it.Next())
11504         {
11505             if (it.Token() > largest)
11506             {
11507                 largest = it.Token();
11508             }
11509         }
11510         if ( largest != mdMethodDefNil )
11511         {
11512             GetModule()->EnsureMethodDefCanBeStored(largest);
11513         }
11514     }
11515
11516     {
11517         mdFieldDef largest = mdFieldDefNil;
11518
11519         for (i = 0; i < bmtMetaData->cFields; i++)
11520         {
11521             if (bmtMetaData->pFields[i] > largest)
11522             {
11523                 largest = bmtMetaData->pFields[i];
11524             }
11525         }
11526         if ( largest != mdFieldDefNil )
11527         {
11528             GetModule()->EnsureFieldDefCanBeStored(largest);
11529         }
11530     }
11531 }
11532
11533 #ifdef FEATURE_COMINTEROP
11534 //*******************************************************************************
11535 void MethodTableBuilder::GetCoClassAttribInfo()
11536 {
11537     STANDARD_VM_CONTRACT;
11538
11539     if (!GetHalfBakedClass()->IsProjectedFromWinRT()) // ignore classic COM interop CA on WinRT interfaces
11540     {
11541         // Retrieve the CoClassAttribute CA.
11542         HRESULT hr = GetMDImport()->GetCustomAttributeByName(GetCl(), INTEROP_COCLASS_TYPE, NULL, NULL);
11543         if (hr == S_OK)
11544         {
11545             // COM class interfaces may lazily populate the m_pCoClassForIntf field of EEClass. This field is
11546             // optional so we must ensure the optional field descriptor has been allocated.
11547             EnsureOptionalFieldsAreAllocated(GetHalfBakedClass(), m_pAllocMemTracker, GetLoaderAllocator()->GetLowFrequencyHeap());
11548             SetIsComClassInterface();
11549         }
11550     }
11551 }
11552 #endif // FEATURE_COMINTEROP
11553
11554 //*******************************************************************************
11555 void MethodTableBuilder::bmtMethodImplInfo::AddMethodImpl(
11556     bmtMDMethod * pImplMethod, bmtMethodHandle declMethod,
11557     StackingAllocator * pStackingAllocator)
11558 {
11559     STANDARD_VM_CONTRACT;
11560
11561     CONSISTENCY_CHECK(CheckPointer(pImplMethod));
11562     CONSISTENCY_CHECK(!declMethod.IsNull());
11563     if (pIndex >= cMaxIndex)
11564     {
11565         DWORD newEntriesCount = 0;
11566
11567         if (!ClrSafeInt<DWORD>::multiply(cMaxIndex, 2, newEntriesCount))
11568             ThrowHR(COR_E_OVERFLOW);
11569
11570         if (newEntriesCount == 0)
11571             newEntriesCount = 10;
11572
11573         // If we have to grow this array, we will not free the old array before we clean up the BuildMethodTable operation
11574         // because this is a stacking allocator. However, the old array will get freed when all the stack allocator is freed.
11575         Entry *rgEntriesNew = new (pStackingAllocator) Entry[newEntriesCount];
11576         memcpy(rgEntriesNew, rgEntries, sizeof(Entry) * cMaxIndex);
11577
11578         // Start using newly allocated array.
11579         rgEntries = rgEntriesNew;
11580         cMaxIndex = newEntriesCount;
11581     }
11582     rgEntries[pIndex++] = Entry(pImplMethod, declMethod);
11583 }
11584
11585 //*******************************************************************************
11586 // Returns TRUE if tok acts as a body for any methodImpl entry. FALSE, otherwise.
11587 BOOL MethodTableBuilder::bmtMethodImplInfo::IsBody(mdToken tok)
11588 {
11589     LIMITED_METHOD_CONTRACT;
11590     CONSISTENCY_CHECK(TypeFromToken(tok) == mdtMethodDef);
11591     for (DWORD i = 0; i < pIndex; i++)
11592     {
11593         if (GetBodyMethodDesc(i)->GetMemberDef() == tok)
11594         {
11595             return TRUE;
11596         }
11597     }
11598     return FALSE;
11599 }
11600
11601 //*******************************************************************************
11602 BYTE *
11603 MethodTableBuilder::AllocateFromHighFrequencyHeap(S_SIZE_T cbMem)
11604 {
11605     CONTRACTL
11606     {
11607         THROWS;
11608         GC_NOTRIGGER;
11609         MODE_ANY;
11610     }
11611     CONTRACTL_END;
11612     return (BYTE *)GetMemTracker()->Track(
11613         GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem(cbMem));
11614 }
11615
11616 //*******************************************************************************
11617 BYTE *
11618 MethodTableBuilder::AllocateFromLowFrequencyHeap(S_SIZE_T cbMem)
11619 {
11620     CONTRACTL
11621     {
11622         THROWS;
11623         GC_NOTRIGGER;
11624         MODE_ANY;
11625     }
11626     CONTRACTL_END;
11627     return (BYTE *)GetMemTracker()->Track(
11628         GetLoaderAllocator()->GetLowFrequencyHeap()->AllocMem(cbMem));
11629 }
11630
11631 //-------------------------------------------------------------------------------
11632 // Make best-case effort to obtain an image name for use in an error message.
11633 //
11634 // This routine must expect to be called before the this object is fully loaded.
11635 // It can return an empty if the name isn't available or the object isn't initialized
11636 // enough to get a name, but it mustn't crash.
11637 //-------------------------------------------------------------------------------
11638 LPCWSTR MethodTableBuilder::GetPathForErrorMessages()
11639 {
11640     STANDARD_VM_CONTRACT;
11641
11642     return GetModule()->GetPathForErrorMessages();
11643 }
11644
11645 BOOL MethodTableBuilder::ChangesImplementationOfVirtualSlot(SLOT_INDEX idx)
11646 {
11647     STANDARD_VM_CONTRACT;
11648
11649     BOOL fChangesImplementation = TRUE;
11650
11651     _ASSERTE(idx < bmtVT->cVirtualSlots);
11652
11653     if (HasParent() && idx < GetParentMethodTable()->GetNumVirtuals())
11654     {
11655         _ASSERTE(idx < bmtParent->pSlotTable->GetSlotCount());
11656         bmtMethodHandle VTImpl = (*bmtVT)[idx].Impl();
11657         bmtMethodHandle ParentImpl = (*bmtParent)[idx].Impl();
11658
11659         fChangesImplementation = VTImpl != ParentImpl;
11660
11661         // See code:MethodTableBuilder::SetupMethodTable2 and its logic
11662         // for handling MethodImpl's on parent classes which affect non interface
11663         // methods.
11664         if (!fChangesImplementation && (ParentImpl.GetSlotIndex() != idx))
11665             fChangesImplementation = TRUE;
11666     }
11667
11668     return fChangesImplementation;
11669 }
11670
11671 // Must be called prior to setting the value of any optional field on EEClass (on a debug build an assert will
11672 // fire if this invariant is violated).
11673 void MethodTableBuilder::EnsureOptionalFieldsAreAllocated(EEClass *pClass, AllocMemTracker *pamTracker, LoaderHeap *pHeap)
11674 {
11675     STANDARD_VM_CONTRACT;
11676
11677     if (pClass->HasOptionalFields())
11678         return;
11679
11680     EEClassOptionalFields *pOptFields = (EEClassOptionalFields*)
11681         pamTracker->Track(pHeap->AllocMem(S_SIZE_T(sizeof(EEClassOptionalFields))));
11682
11683     // Initialize default values for all optional fields.
11684     pOptFields->Init();
11685
11686     // Attach optional fields to the class.
11687     pClass->AttachOptionalFields(pOptFields);
11688 }
11689
11690 //---------------------------------------------------------------------------------------
11691 // 
11692 // Gather information about a generic type
11693 // - number of parameters
11694 // - variance annotations
11695 // - dictionaries
11696 // - sharability
11697 // 
11698 //static
11699 void 
11700 MethodTableBuilder::GatherGenericsInfo(
11701     Module *          pModule, 
11702     mdTypeDef         cl, 
11703     Instantiation     inst, 
11704     bmtGenericsInfo * bmtGenericsInfo)
11705 {
11706     CONTRACTL
11707     {
11708         STANDARD_VM_CHECK;
11709         PRECONDITION(GetThread() != NULL);
11710         PRECONDITION(CheckPointer(pModule));
11711         PRECONDITION(CheckPointer(bmtGenericsInfo));
11712     }
11713     CONTRACTL_END;
11714
11715     IMDInternalImport * pInternalImport = pModule->GetMDImport();
11716
11717     // Enumerate the formal type parameters
11718     HENUMInternal   hEnumGenericPars;
11719     HRESULT hr = pInternalImport->EnumInit(mdtGenericParam, cl, &hEnumGenericPars);
11720     if (FAILED(hr))
11721         pModule->GetAssembly()->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
11722
11723     DWORD numGenericArgs = pInternalImport->EnumGetCount(&hEnumGenericPars);
11724
11725     // Work out what kind of EEClass we're creating w.r.t. generics.  If there
11726     // are no generics involved this will be a VMFLAG_NONGENERIC.
11727     BOOL fHasVariance = FALSE;
11728     if (numGenericArgs > 0)
11729     {
11730         // Generic type verification
11731         {
11732             DWORD   dwAttr;
11733             mdToken tkParent;
11734             if (FAILED(pInternalImport->GetTypeDefProps(cl, &dwAttr, &tkParent)))
11735             {
11736                 pModule->GetAssembly()->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
11737             }
11738             // A generic with explicit layout is not allowed.
11739             if (IsTdExplicitLayout(dwAttr))
11740             {
11741                 pModule->GetAssembly()->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_EXPLICIT_GENERIC);
11742             }
11743         }
11744         
11745         bmtGenericsInfo->numDicts = 1;
11746         
11747         mdGenericParam tkTyPar;
11748         bmtGenericsInfo->pVarianceInfo = new (&GetThread()->m_MarshalAlloc) BYTE[numGenericArgs];
11749
11750         // If it has generic arguments but none have been specified, then load the instantiation at the formals
11751         if (inst.IsEmpty())
11752         {
11753             bmtGenericsInfo->fTypicalInstantiation = TRUE;
11754             S_UINT32 scbAllocSize = S_UINT32(numGenericArgs) * S_UINT32(sizeof(TypeHandle));
11755             TypeHandle * genericArgs = (TypeHandle *) GetThread()->m_MarshalAlloc.Alloc(scbAllocSize);
11756
11757             inst = Instantiation(genericArgs, numGenericArgs);
11758
11759             bmtGenericsInfo->fSharedByGenericInstantiations = FALSE;
11760         }
11761         else
11762         {
11763             bmtGenericsInfo->fTypicalInstantiation = FALSE;
11764
11765             bmtGenericsInfo->fSharedByGenericInstantiations = TypeHandle::IsCanonicalSubtypeInstantiation(inst);
11766             _ASSERTE(bmtGenericsInfo->fSharedByGenericInstantiations == ClassLoader::IsSharableInstantiation(inst));
11767
11768 #ifdef _DEBUG
11769             // Set typical instantiation MethodTable
11770             {
11771                 MethodTable * pTypicalInstantiationMT = pModule->LookupTypeDef(cl).AsMethodTable();
11772                 // Typical instantiation was already loaded by code:ClassLoader::LoadApproxTypeThrowing
11773                 _ASSERTE(pTypicalInstantiationMT != NULL);
11774                 bmtGenericsInfo->dbg_pTypicalInstantiationMT = pTypicalInstantiationMT;
11775             }
11776 #endif //_DEBUG
11777         }
11778         
11779         TypeHandle * pDestInst = (TypeHandle *)inst.GetRawArgs();
11780         for (unsigned int i = 0; i < numGenericArgs; i++)
11781         {
11782             pInternalImport->EnumNext(&hEnumGenericPars, &tkTyPar);
11783             DWORD flags;
11784             if (FAILED(pInternalImport->GetGenericParamProps(tkTyPar, NULL, &flags, NULL, NULL, NULL)))
11785             {
11786                 pModule->GetAssembly()->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
11787             }
11788             
11789             if (bmtGenericsInfo->fTypicalInstantiation)
11790             {
11791                 // code:Module.m_GenericParamToDescMap maps generic parameter RIDs to TypeVarTypeDesc
11792                 // instances so that we do not leak by allocating them all over again, if the type
11793                 // repeatedly fails to load.
11794                 TypeVarTypeDesc *pTypeVarTypeDesc = pModule->LookupGenericParam(tkTyPar);
11795                 if (pTypeVarTypeDesc == NULL)
11796                 {
11797                     // Do NOT use the alloc tracker for this memory as we need it stay allocated even if the load fails.
11798                     void *mem = (void *)pModule->GetLoaderAllocator()->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(TypeVarTypeDesc)));
11799                     pTypeVarTypeDesc = new (mem) TypeVarTypeDesc(pModule, cl, i, tkTyPar);
11800
11801                     // No race here - the row in GenericParam table is owned exclusively by this type and we
11802                     // are holding a lock preventing other threads from concurrently loading it.
11803                     pModule->StoreGenericParamThrowing(tkTyPar, pTypeVarTypeDesc);
11804                 }
11805                 pDestInst[i] = TypeHandle(pTypeVarTypeDesc);
11806             }
11807
11808             DWORD varianceAnnotation = flags & gpVarianceMask;
11809             bmtGenericsInfo->pVarianceInfo[i] = static_cast<BYTE>(varianceAnnotation);
11810             if (varianceAnnotation != gpNonVariant)               
11811             {
11812                 if (varianceAnnotation != gpContravariant && varianceAnnotation != gpCovariant)
11813                 {
11814                     pModule->GetAssembly()->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADVARIANCE);
11815                 }
11816                 else
11817                 {
11818                     fHasVariance = TRUE;
11819                 }
11820             }
11821         }
11822
11823         if (!fHasVariance)
11824             bmtGenericsInfo->pVarianceInfo = NULL;
11825     }
11826     else
11827     {
11828         bmtGenericsInfo->fTypicalInstantiation = FALSE;
11829         bmtGenericsInfo->fSharedByGenericInstantiations = FALSE;
11830         bmtGenericsInfo->numDicts = 0;
11831     }
11832
11833     bmtGenericsInfo->fContainsGenericVariables = MethodTable::ComputeContainsGenericVariables(inst);
11834
11835     SigTypeContext typeContext(inst, Instantiation());
11836     bmtGenericsInfo->typeContext = typeContext;
11837 } // MethodTableBuilder::GatherGenericsInfo
11838
11839 //---------------------------------------------------------------------------------------
11840 // 
11841 // This service is called for normal classes -- and for the pseudo class we invent to
11842 // hold the module's public members.
11843 // 
11844 //static
11845 TypeHandle 
11846 ClassLoader::CreateTypeHandleForTypeDefThrowing(
11847     Module *          pModule, 
11848     mdTypeDef         cl, 
11849     Instantiation     inst, 
11850     AllocMemTracker * pamTracker)
11851 {
11852     CONTRACT(TypeHandle)
11853     {
11854         STANDARD_VM_CHECK;
11855         PRECONDITION(GetThread() != NULL);
11856         PRECONDITION(CheckPointer(pModule));
11857         POSTCONDITION(!RETVAL.IsNull());
11858         POSTCONDITION(CheckPointer(RETVAL.GetMethodTable()));
11859     }
11860     CONTRACT_END;
11861
11862     MethodTable * pMT = NULL;
11863
11864     Thread * pThread = GetThread();
11865     BEGIN_SO_INTOLERANT_CODE_FOR(pThread, DefaultEntryProbeAmount() * 2)
11866
11867     MethodTable * pParentMethodTable = NULL;
11868     SigPointer    parentInst;
11869     mdTypeDef     tdEnclosing = mdTypeDefNil;
11870     DWORD         cInterfaces;
11871     BuildingInterfaceInfo_t * pInterfaceBuildInfo = NULL;
11872     IMDInternalImport *       pInternalImport = NULL;
11873     LayoutRawFieldInfo *      pLayoutRawFieldInfos = NULL;
11874     MethodTableBuilder::bmtGenericsInfo genericsInfo;
11875     
11876     Assembly * pAssembly = pModule->GetAssembly();
11877     pInternalImport = pModule->GetMDImport();
11878
11879     if (TypeFromToken(cl) != mdtTypeDef || !pInternalImport->IsValidToken(cl))
11880     {
11881         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
11882     }
11883
11884     // GetCheckpoint for the thread-based allocator
11885     // This checkpoint provides a scope for all transient allocations of data structures
11886     // used during class loading.
11887     // <NICE> Ideally a debug/checked build should pass around tokens indicating the Checkpoint
11888     // being used and check these dynamically </NICE>
11889     CheckPointHolder cph(pThread->m_MarshalAlloc.GetCheckpoint()); //hold checkpoint for autorelease
11890     
11891     // Gather up generics info
11892     MethodTableBuilder::GatherGenericsInfo(pModule, cl, inst, &genericsInfo);
11893
11894     Module * pLoaderModule = pModule;
11895     if (!inst.IsEmpty())
11896     {
11897         pLoaderModule = ClassLoader::ComputeLoaderModuleWorker(
11898             pModule, 
11899             cl, 
11900             inst, 
11901             Instantiation());
11902         pLoaderModule->GetLoaderAllocator()->EnsureInstantiation(pModule, inst);
11903     }
11904
11905     LoaderAllocator * pAllocator = pLoaderModule->GetLoaderAllocator();
11906
11907     {
11908         // As this is loading a parent type, we are allowed to override the load type limit.
11909         OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOAD_APPROXPARENTS);
11910         pParentMethodTable = LoadApproxParentThrowing(pModule, cl, &parentInst, &genericsInfo.typeContext);
11911     }
11912
11913     if (pParentMethodTable != NULL)
11914     {
11915         // Since methods on System.Array assume the layout of arrays, we can not allow
11916         // subclassing of arrays, it is sealed from the users point of view.
11917         // Value types and enums should be sealed - disable inheritting from them (we cannot require sealed 
11918         // flag because of AppCompat)
11919         if (pParentMethodTable->IsSealed() || 
11920             (pParentMethodTable == g_pArrayClass) || 
11921             pParentMethodTable->IsValueType())
11922         {
11923             pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_SEALEDPARENT);
11924         }
11925
11926         DWORD dwTotalDicts = genericsInfo.numDicts + pParentMethodTable->GetNumDicts();
11927         if (!FitsIn<WORD>(dwTotalDicts))
11928         {
11929             pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_TOOMANYGENERICARGS);
11930         }
11931         genericsInfo.numDicts = static_cast<WORD>(dwTotalDicts);
11932     }
11933
11934     GetEnclosingClassThrowing(pInternalImport, pModule, cl, &tdEnclosing);
11935
11936     BYTE nstructPackingSize = 0, nstructNLT = 0;
11937     BOOL fExplicitOffsets = FALSE;
11938     // NOTE: HasLayoutMetadata does not load classes
11939     BOOL fHasLayout = 
11940         !genericsInfo.fContainsGenericVariables && 
11941         HasLayoutMetadata(
11942             pModule->GetAssembly(), 
11943             pInternalImport, 
11944             cl, 
11945             pParentMethodTable, 
11946             &nstructPackingSize, 
11947             &nstructNLT, 
11948             &fExplicitOffsets);
11949
11950     BOOL fIsEnum = ((g_pEnumClass != NULL) && (pParentMethodTable == g_pEnumClass));
11951
11952     // enums may not have layout because they derive from g_pEnumClass and that has no layout
11953     // this is enforced by HasLayoutMetadata above
11954     _ASSERTE(!(fIsEnum && fHasLayout));
11955
11956     // This is a delegate class if it derives from MulticastDelegate (we do not allow single cast delegates)
11957     BOOL fIsDelegate = pParentMethodTable && pParentMethodTable == g_pMulticastDelegateClass;
11958
11959     // Create a EEClass entry for it, filling out a few fields, such as the parent class token
11960     // (and the generic type should we be creating an instantiation)
11961     EEClass * pClass = MethodTableBuilder::CreateClass(
11962         pModule, 
11963         cl, 
11964         fHasLayout, 
11965         fIsDelegate, 
11966         fIsEnum, 
11967         &genericsInfo, 
11968         pAllocator, 
11969         pamTracker);
11970
11971     if ((pParentMethodTable != NULL) && (pParentMethodTable == g_pDelegateClass))
11972     {
11973         // Note we do not allow single cast delegates
11974         if (pModule->GetAssembly() != SystemDomain::SystemAssembly())
11975         {
11976             pAssembly->ThrowTypeLoadException(pInternalImport, cl, BFA_CANNOT_INHERIT_FROM_DELEGATE);
11977         }
11978
11979 #ifdef _DEBUG
11980         // Only MultiCastDelegate should inherit from Delegate
11981         LPCUTF8 className;
11982         LPCUTF8 nameSpace;
11983         if (FAILED(pInternalImport->GetNameOfTypeDef(cl, &className, &nameSpace)))
11984         {
11985             className = nameSpace = "Invalid TypeDef record";
11986         }
11987         BAD_FORMAT_NOTHROW_ASSERT(strcmp(className, "MulticastDelegate") == 0);
11988 #endif
11989     }
11990
11991     if (fIsDelegate)
11992     {
11993         if (!pClass->IsSealed())
11994         {
11995             pAssembly->ThrowTypeLoadException(pInternalImport, cl, BFA_DELEGATE_CLASS_NOTSEALED);
11996         }
11997
11998         pClass->SetIsDelegate();
11999     }
12000
12001     if (tdEnclosing != mdTypeDefNil)
12002     {
12003         pClass->SetIsNested();
12004         THROW_BAD_FORMAT_MAYBE(IsTdNested(pClass->GetProtection()), VLDTR_E_TD_ENCLNOTNESTED, pModule);
12005     }
12006     else if (IsTdNested(pClass->GetProtection()))
12007     {
12008         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12009     }
12010     
12011     // We only permit generic interfaces and delegates to have variant type parameters
12012     if (genericsInfo.pVarianceInfo != NULL && !pClass->IsInterface() && !fIsDelegate)
12013     {
12014         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_VARIANCE_CLASS);
12015     }
12016     
12017     // Now load all the interfaces
12018     HENUMInternalHolder hEnumInterfaceImpl(pInternalImport);
12019     hEnumInterfaceImpl.EnumInit(mdtInterfaceImpl, cl);
12020     
12021     cInterfaces = pInternalImport->EnumGetCount(&hEnumInterfaceImpl);
12022     
12023     if (cInterfaces != 0)
12024     {
12025         DWORD i;
12026         
12027         // Allocate the BuildingInterfaceList table
12028         pInterfaceBuildInfo = new (&GetThread()->m_MarshalAlloc) BuildingInterfaceInfo_t[cInterfaces];
12029         
12030         mdInterfaceImpl ii;
12031         for (i = 0; pInternalImport->EnumNext(&hEnumInterfaceImpl, &ii); i++)
12032         {
12033             // Get properties on this interface
12034             mdTypeRef crInterface;
12035             if (FAILED(pInternalImport->GetTypeOfInterfaceImpl(ii, &crInterface)))
12036             {
12037                 pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12038             }
12039             // validate the token
12040             mdToken crIntType = 
12041                 (RidFromToken(crInterface) && pInternalImport->IsValidToken(crInterface)) ? 
12042                 TypeFromToken(crInterface) : 
12043                 0;
12044             switch (crIntType)
12045             {
12046                 case mdtTypeDef:
12047                 case mdtTypeRef:
12048                 case mdtTypeSpec:
12049                     break;
12050                 default:
12051                     pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_INTERFACENULL);
12052             }
12053             
12054             TypeHandle intType;
12055             
12056             {
12057                 OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOAD_APPROXPARENTS);
12058                 intType = LoadApproxTypeThrowing(pModule, crInterface, NULL, &genericsInfo.typeContext);
12059             }
12060             
12061             pInterfaceBuildInfo[i].m_pMethodTable = intType.AsMethodTable();
12062             if (pInterfaceBuildInfo[i].m_pMethodTable == NULL)
12063             {
12064                 pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_INTERFACENULL);
12065             }
12066             
12067             // Ensure this is an interface
12068             if (!pInterfaceBuildInfo[i].m_pMethodTable->IsInterface())
12069             {
12070                  pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_NOTINTERFACE);
12071             }
12072             
12073             // Check interface for use of variant type parameters
12074             if ((genericsInfo.pVarianceInfo != NULL) && (TypeFromToken(crInterface) == mdtTypeSpec))
12075             {
12076                 ULONG cSig;
12077                 PCCOR_SIGNATURE pSig;
12078                 if (FAILED(pInternalImport->GetTypeSpecFromToken(crInterface, &pSig, &cSig)))
12079                 {
12080                     pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12081                 }
12082                 // Interfaces behave covariantly
12083                 if (!EEClass::CheckVarianceInSig(
12084                         genericsInfo.GetNumGenericArgs(), 
12085                         genericsInfo.pVarianceInfo, 
12086                         pModule, 
12087                         SigPointer(pSig, cSig), 
12088                         gpCovariant))
12089                 {
12090                     pAssembly->ThrowTypeLoadException(
12091                         pInternalImport, 
12092                         cl, 
12093                         IDS_CLASSLOAD_VARIANCE_IN_INTERFACE);
12094                 }
12095             }
12096         }
12097         _ASSERTE(i == cInterfaces);
12098     }
12099     
12100     if (fHasLayout ||
12101         /* Variant delegates should not have any instance fields of the variant.
12102            type parameter. For now, we just completely disallow all fields even
12103            if they are non-variant or static, as it is not a useful scenario.
12104            @TODO: A more logical place for this check would be in 
12105            MethodTableBuilder::EnumerateClassMembers() */
12106         (fIsDelegate && genericsInfo.pVarianceInfo))
12107     {
12108         // check for fields and variance
12109         ULONG               cFields;
12110         HENUMInternalHolder hEnumField(pInternalImport);
12111         hEnumField.EnumInit(mdtFieldDef, cl);
12112
12113         cFields = pInternalImport->EnumGetCount(&hEnumField);
12114
12115         if ((cFields != 0) && fIsDelegate && (genericsInfo.pVarianceInfo != NULL))
12116         {
12117             pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_VARIANCE_IN_DELEGATE);
12118         }
12119
12120         if (fHasLayout)
12121         {
12122             // Though we fail on this condition, we should never run into it.
12123             CONSISTENCY_CHECK(nstructPackingSize != 0);
12124             // MD Val check: PackingSize
12125             if((nstructPackingSize == 0)  || 
12126                (nstructPackingSize > 128) || 
12127                (nstructPackingSize & (nstructPackingSize-1)))
12128             {
12129                 THROW_BAD_FORMAT_MAYBE(!"ClassLayout:Invalid PackingSize", BFA_BAD_PACKING_SIZE, pModule);
12130                 pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12131             }
12132
12133             pLayoutRawFieldInfos = (LayoutRawFieldInfo *)GetThread()->m_MarshalAlloc.Alloc(
12134                 (S_UINT32(1) + S_UINT32(cFields)) * S_UINT32(sizeof(LayoutRawFieldInfo)));
12135             
12136             {
12137                 // Warning: this can load classes
12138                 CONTRACT_VIOLATION(LoadsTypeViolation);
12139
12140                 // Set a flag that allows us to break dead-locks that are result of the LoadsTypeViolation
12141                 ThreadStateNCStackHolder tsNC(TRUE, Thread::TSNC_LoadsTypeViolation);
12142
12143                 EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing(
12144                     cl, 
12145                     nstructPackingSize, 
12146                     nstructNLT, 
12147 #ifdef FEATURE_COMINTEROP
12148                     pClass->IsProjectedFromWinRT(),
12149 #endif // FEATURE_COMINTEROP
12150                     fExplicitOffsets, 
12151                     pParentMethodTable, 
12152                     cFields, 
12153                     &hEnumField, 
12154                     pModule, 
12155                     &genericsInfo.typeContext, 
12156                     &(((LayoutEEClass *)pClass)->m_LayoutInfo), 
12157                     pLayoutRawFieldInfos, 
12158                     pAllocator, 
12159                     pamTracker);
12160             }
12161         }
12162     }
12163
12164     // Resolve this class, given that we know now that all of its dependencies are loaded and resolved.
12165     // !!! This must be the last thing in this TRY block: if MethodTableBuilder succeeds, it has published the class
12166     // and there is no going back.
12167     MethodTableBuilder builder(
12168         NULL,
12169         pClass,
12170         &GetThread()->m_MarshalAlloc, 
12171         pamTracker);
12172
12173     pMT = builder.BuildMethodTableThrowing(
12174         pAllocator, 
12175         pLoaderModule, 
12176         pModule, 
12177         cl, 
12178         pInterfaceBuildInfo, 
12179         pLayoutRawFieldInfos, 
12180         pParentMethodTable, 
12181         &genericsInfo, 
12182         parentInst, 
12183         (WORD)cInterfaces);
12184
12185     END_SO_INTOLERANT_CODE;
12186     RETURN(TypeHandle(pMT));
12187 } // ClassLoader::CreateTypeHandleForTypeDefThrowing