Sync may31 release/8.0-tizen (#510)
[platform/upstream/dotnet/runtime.git] / src / coreclr / 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 //
4 // File: METHODTABLEBUILDER.CPP
5 //
6
7
8 //
9
10 //
11 // ============================================================================
12
13 #include "common.h"
14
15 #include "methodtablebuilder.h"
16
17 #include "sigbuilder.h"
18 #include "dllimport.h"
19 #include "fieldmarshaler.h"
20 #include "encee.h"
21 #include "ecmakey.h"
22 #include "customattribute.h"
23 #include "typestring.h"
24
25 //*******************************************************************************
26 // Helper functions to sort GCdescs by offset (decending order)
27 int __cdecl compareCGCDescSeries(const void *arg1, const void *arg2)
28 {
29     STATIC_CONTRACT_NOTHROW;
30     STATIC_CONTRACT_GC_NOTRIGGER;
31     STATIC_CONTRACT_FORBID_FAULT;
32
33     CGCDescSeries* gcInfo1 = (CGCDescSeries*) arg1;
34     CGCDescSeries* gcInfo2 = (CGCDescSeries*) arg2;
35
36     return (int)(gcInfo2->GetSeriesOffset() - gcInfo1->GetSeriesOffset());
37 }
38
39 //*******************************************************************************
40
41 const char* FormatSig(MethodDesc* pMD, LoaderHeap *pHeap, AllocMemTracker *pamTracker);
42
43 #ifdef _DEBUG
44 unsigned g_dupMethods = 0;
45 #endif // _DEBUG
46
47 //==========================================================================
48 // This function is very specific about how it constructs a EEClass.  It first
49 // determines the necessary size of the vtable and the number of statics that
50 // this class requires.  The necessary memory is then allocated for a EEClass
51 // and its vtable and statics.  The class members are then initialized and
52 // the memory is then returned to the caller
53 //
54 // LPEEClass CreateClass()
55 //
56 // Parameters :
57 //      [in] scope - scope of the current class not the one requested to be opened
58 //      [in] cl - class token of the class to be created.
59 //      [out] ppEEClass - pointer to pointer to hold the address of the EEClass
60 //                        allocated in this function.
61 // Return : returns an HRESULT indicating the success of this function.
62 //
63 // This parameter has been removed but might need to be reinstated if the
64 // global for the metadata loader is removed.
65 //      [in] pIMLoad - MetaDataLoader class/object for the current scope.
66
67
68 //==========================================================================
69 /*static*/ EEClass *
70 MethodTableBuilder::CreateClass( Module *pModule,
71                                 mdTypeDef cl,
72                                 BOOL fHasLayout,
73                                 BOOL fDelegate,
74                                 BOOL fIsEnum,
75                                 const MethodTableBuilder::bmtGenericsInfo *bmtGenericsInfo,
76                                 LoaderAllocator * pAllocator,
77                                 AllocMemTracker *pamTracker)
78 {
79     CONTRACTL
80     {
81         STANDARD_VM_CHECK;
82         PRECONDITION(!(fHasLayout && fDelegate));
83         PRECONDITION(!(fHasLayout && fIsEnum));
84         PRECONDITION(CheckPointer(bmtGenericsInfo));
85     }
86     CONTRACTL_END;
87
88     EEClass *pEEClass = NULL;
89     IMDInternalImport *pInternalImport;
90
91     //<TODO>============================================================================
92     // vtabsize and static size need to be converted from pointer sizes to #'s
93     // of bytes this will be very important for 64 bit NT!
94     // We will need to call on IMetaDataLoad to get these sizes and fill out the
95     // tables
96
97     // From the classref call on metadata to resolve the classref and check scope
98     // to make sure that this class is in the same scope otherwise we need to open
99     // a new scope and possibly file.
100
101     // if the scopes are different call the code to load a new file and get the new scope
102
103     // scopes are the same so we can use the existing scope to get the class info
104
105     // This method needs to be fleshed out.more it currently just returns enough
106     // space for the defined EEClass and the vtable and statics are not set.
107     //=============================================================================</TODO>
108
109     if (fHasLayout)
110     {
111         pEEClass = new (pAllocator->GetLowFrequencyHeap(), pamTracker) LayoutEEClass();
112     }
113     else if (fDelegate)
114     {
115         pEEClass = new (pAllocator->GetLowFrequencyHeap(), pamTracker) DelegateEEClass();
116     }
117     else
118     {
119         pEEClass = new (pAllocator->GetLowFrequencyHeap(), pamTracker) EEClass(sizeof(EEClass));
120     }
121
122     DWORD dwAttrClass = 0;
123     mdToken tkExtends = mdTokenNil;
124
125     // Set up variance info
126     if (bmtGenericsInfo->pVarianceInfo)
127     {
128         // Variance info is an optional field on EEClass, so ensure the optional field descriptor has been
129         // allocated.
130         EnsureOptionalFieldsAreAllocated(pEEClass, pamTracker, pAllocator->GetLowFrequencyHeap());
131         pEEClass->SetVarianceInfo((BYTE*) pamTracker->Track(
132             pAllocator->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(bmtGenericsInfo->GetNumGenericArgs()))));
133
134         memcpy(pEEClass->GetVarianceInfo(), bmtGenericsInfo->pVarianceInfo, bmtGenericsInfo->GetNumGenericArgs());
135     }
136
137     pInternalImport = pModule->GetMDImport();
138
139     if (pInternalImport == NULL)
140         COMPlusThrowHR(COR_E_TYPELOAD);
141
142     IfFailThrow(pInternalImport->GetTypeDefProps(
143         cl,
144         &dwAttrClass,
145         &tkExtends));
146
147     pEEClass->m_dwAttrClass = dwAttrClass;
148
149     // MDVal check: can't be both tdSequentialLayout and tdExplicitLayout
150     if((dwAttrClass & tdLayoutMask) == tdLayoutMask)
151         COMPlusThrowHR(COR_E_TYPELOAD);
152
153     if (IsTdInterface(dwAttrClass))
154     {
155         // MDVal check: must have nil tkExtends and must be tdAbstract
156         if((tkExtends & 0x00FFFFFF)||(!IsTdAbstract(dwAttrClass)))
157             COMPlusThrowHR(COR_E_TYPELOAD);
158     }
159
160     if (fHasLayout)
161         pEEClass->SetHasLayout();
162
163     if (IsTdWindowsRuntime(dwAttrClass))
164     {
165         COMPlusThrowHR(COR_E_TYPELOAD);
166     }
167
168 #ifdef _DEBUG
169     pModule->GetClassLoader()->m_dwDebugClasses++;
170 #endif
171
172     return pEEClass;
173 }
174
175 //*******************************************************************************
176 //
177 // Create a hash of all methods in this class.  The hash is from method name to MethodDesc.
178 //
179 MethodTableBuilder::MethodNameHash *
180 MethodTableBuilder::CreateMethodChainHash(
181     MethodTable *pMT)
182 {
183     STANDARD_VM_CONTRACT;
184
185     MethodNameHash *pHash = new (GetStackingAllocator()) MethodNameHash();
186     pHash->Init(pMT->GetNumVirtuals(), GetStackingAllocator());
187
188     unsigned numVirtuals = GetParentMethodTable()->GetNumVirtuals();
189     for (unsigned i = 0; i < numVirtuals; ++i)
190     {
191         bmtMethodSlot &slot = (*bmtParent->pSlotTable)[i];
192         bmtRTMethod * pMethod = slot.Decl().AsRTMethod();
193         const MethodSignature &sig = pMethod->GetMethodSignature();
194         pHash->Insert(sig.GetName(), pMethod);
195     }
196
197     // Success
198     return pHash;
199 }
200
201 //*******************************************************************************
202 //
203 // Find a method in this class hierarchy - used ONLY by the loader during layout.  Do not use at runtime.
204 //
205 // *ppMemberSignature must be NULL on entry - it and *pcMemberSignature may or may not be filled out
206 //
207 // ppMethodDesc will be filled out with NULL if no matching method in the hierarchy is found.
208 //
209 // Returns FALSE if there was an error of some kind.
210 //
211 // pMethodConstraintsMatch receives the result of comparing the method constraints.
212 MethodTableBuilder::bmtRTMethod *
213 MethodTableBuilder::LoaderFindMethodInParentClass(
214     const MethodSignature & methodSig,
215     BOOL *                  pMethodConstraintsMatch)
216 {
217     CONTRACTL
218     {
219         STANDARD_VM_CHECK;
220         PRECONDITION(CheckPointer(this));
221         PRECONDITION(CheckPointer(bmtParent));
222         PRECONDITION(CheckPointer(methodSig.GetModule()));
223         PRECONDITION(CheckPointer(methodSig.GetSignature()));
224         PRECONDITION(HasParent());
225         PRECONDITION(methodSig.GetSignatureLength() != 0);
226     }
227     CONTRACTL_END;
228
229 //#if 0
230     MethodNameHash::HashEntry * pEntry;
231
232     // Have we created a hash of all the methods in the class chain?
233     if (bmtParent->pParentMethodHash == NULL)
234     {
235         // There may be such a method, so we will now create a hash table to reduce the pain for
236         // further lookups
237
238         // <TODO> Are we really sure that this is worth doing? </TODO>
239         bmtParent->pParentMethodHash = CreateMethodChainHash(GetParentMethodTable());
240     }
241
242     // We have a hash table, so use it
243     pEntry = bmtParent->pParentMethodHash->Lookup(methodSig.GetName());
244
245     // Traverse the chain of all methods with this name
246     while (pEntry != NULL)
247     {
248         bmtRTMethod * pEntryMethod = pEntry->m_data;
249         const MethodSignature & entrySig = pEntryMethod->GetMethodSignature();
250
251         // Note instantiation info
252         {
253             if (methodSig.Equivalent(entrySig))
254             {
255                 if (pMethodConstraintsMatch != NULL)
256                 {
257                     if ((*methodSig.GetSignature()) & IMAGE_CEE_CS_CALLCONV_GENERIC)
258                     {
259                         // Check the constraints are consistent,
260                         // and return the result to the caller.
261                         // We do this here to avoid recalculating pSubst.
262                         *pMethodConstraintsMatch = MetaSig::CompareMethodConstraints(
263                             methodSig.GetSubstitution(), methodSig.GetModule(), methodSig.GetToken(),
264                             entrySig.GetSubstitution(),  entrySig.GetModule(),  entrySig.GetToken());
265                     }
266                     else
267                     {
268                         *pMethodConstraintsMatch = TRUE; // If the method isn't generic, just mark that constraints match
269                     }
270                 }
271
272                 return pEntryMethod;
273             }
274         }
275
276         // Advance to next item in the hash chain which has the same name
277         pEntry = bmtParent->pParentMethodHash->FindNext(pEntry);
278     }
279 //#endif
280
281 //@TODO: Move to this code, as the use of a HashTable is broken; overriding semantics
282 //@TODO: require matching against the most-derived slot of a given name and signature,
283 //@TODO: (which deals specifically with newslot methods with identical name and sig), but
284 //@TODO: HashTables are by definition unordered and so we've only been getting by with the
285 //@TODO: implementation being compatible with the order in which methods were added to
286 //@TODO: the HashTable in CreateMethodChainHash.
287 #if 0
288     bmtParentInfo::Iterator it(bmtParent->IterateSlots());
289     it.MoveTo(static_cast<size_t>(GetParentMethodTable()->GetNumVirtuals()));
290     while (it.Prev())
291     {
292         bmtMethodHandle decl(it->Decl());
293         const MethodSignature &declSig(decl.GetMethodSignature());
294         if (declSig == methodSig)
295         {
296             if (pMethodConstraintsMatch != NULL)
297             {
298                 // Check the constraints are consistent,
299                 // and return the result to the caller.
300                 // We do this here to avoid recalculating pSubst.
301                 *pMethodConstraintsMatch = MetaSig::CompareMethodConstraints(
302                     &methodSig.GetSubstitution(), methodSig.GetModule(), methodSig.GetToken(),
303                     &declSig.GetSubstitution(),  declSig.GetModule(),  declSig.GetToken());
304             }
305
306             return decl.AsRTMethod();
307         }
308     }
309 #endif // 0
310
311     return NULL;
312 }
313
314 //*******************************************************************************
315 //
316 // Given an interface map to fill out, expand pNewInterface (and its sub-interfaces) into it, increasing
317 // pdwInterfaceListSize as appropriate, and avoiding duplicates.
318 //
319 void
320 MethodTableBuilder::ExpandApproxInterface(
321     bmtInterfaceInfo *          bmtInterface,  // out parameter, various parts cumulatively written to.
322     const Substitution *        pNewInterfaceSubstChain,
323     MethodTable *               pNewInterface,
324     InterfaceDeclarationScope   declScope
325     COMMA_INDEBUG(MethodTable * dbg_pClassMT))
326 {
327     STANDARD_VM_CONTRACT;
328
329     if (pNewInterface->HasVirtualStaticMethods())
330     {
331         bmtProp->fHasVirtualStaticMethods = TRUE;
332     }
333
334     //#ExpandingInterfaces
335     // We expand the tree of inherited interfaces into a set by adding the
336     // current node BEFORE expanding the parents of the current node.
337     // ****** This must be consistent with code:ExpandExactInterface *******
338     // ****** This must be consistent with code:ClassCompat::MethodTableBuilder::BuildInteropVTable_ExpandInterface *******
339
340     // The interface list contains the fully expanded set of interfaces from the parent then
341     // we start adding all the interfaces we declare. We need to know which interfaces
342     // we declare but do not need duplicates of the ones we declare. This means we can
343     // duplicate our parent entries.
344
345     // Is it already present in the list?
346     for (DWORD i = 0; i < bmtInterface->dwInterfaceMapSize; i++)
347     {
348         bmtInterfaceEntry * pItfEntry = &bmtInterface->pInterfaceMap[i];
349         bmtRTType * pItfType = pItfEntry->GetInterfaceType();
350
351         // Type Equivalence is not respected for this comparison as you can have multiple type equivalent interfaces on a class
352         TokenPairList newVisited = TokenPairList::AdjustForTypeEquivalenceForbiddenScope(NULL);
353         if (MetaSig::CompareTypeDefsUnderSubstitutions(pItfType->GetMethodTable(),
354                                                        pNewInterface,
355                                                        &pItfType->GetSubstitution(),
356                                                        pNewInterfaceSubstChain,
357                                                        &newVisited))
358         {
359             if (declScope.fIsInterfaceDeclaredOnType)
360             {
361                 pItfEntry->IsDeclaredOnType() = true;
362             }
363 #ifdef _DEBUG
364             //#InjectInterfaceDuplicates_ApproxInterfaces
365             // We can inject duplicate interfaces in check builds.
366             // Has to be in sync with code:#InjectInterfaceDuplicates_Main
367             if (((dbg_pClassMT == NULL) && bmtInterface->dbg_fShouldInjectInterfaceDuplicates) ||
368                 ((dbg_pClassMT != NULL) && dbg_pClassMT->Debug_HasInjectedInterfaceDuplicates()))
369             {
370                 // The injected duplicate interface should have the same status 'ImplementedByParent' as
371                 // the original interface (can be false if the interface is implemented indirectly twice)
372                 declScope.fIsInterfaceDeclaredOnParent = pItfEntry->IsImplementedByParent();
373                 // Just pretend we didn't find this match, but mark all duplicates as 'DeclaredOnType' if
374                 // needed
375                 continue;
376             }
377 #endif //_DEBUG
378             return; // found it, don't add it again
379         }
380     }
381
382     bmtRTType * pNewItfType =
383         new (GetStackingAllocator()) bmtRTType(*pNewInterfaceSubstChain, pNewInterface);
384
385     if (bmtInterface->dwInterfaceMapSize >= bmtInterface->dwInterfaceMapAllocated)
386     {
387         //
388         // Grow the array of interfaces
389         //
390         S_UINT32 dwNewAllocated = S_UINT32(2) * S_UINT32(bmtInterface->dwInterfaceMapAllocated) + S_UINT32(5);
391
392         if (dwNewAllocated.IsOverflow())
393         {
394             BuildMethodTableThrowException(COR_E_OVERFLOW);
395         }
396
397         S_SIZE_T safeSize = S_SIZE_T(sizeof(bmtInterfaceEntry)) *
398                             S_SIZE_T(dwNewAllocated.Value());
399
400         if (safeSize.IsOverflow())
401         {
402             BuildMethodTableThrowException(COR_E_OVERFLOW);
403         }
404
405         bmtInterfaceEntry * pNewMap = (bmtInterfaceEntry *)new (GetStackingAllocator()) BYTE[safeSize.Value()];
406         if (bmtInterface->dwInterfaceMapAllocated > 0)
407             memcpy(pNewMap, bmtInterface->pInterfaceMap, sizeof(bmtInterfaceEntry) * bmtInterface->dwInterfaceMapAllocated);
408
409         bmtInterface->pInterfaceMap = pNewMap;
410         bmtInterface->dwInterfaceMapAllocated = dwNewAllocated.Value();
411     }
412
413     // The interface map memory was just allocated as an array of bytes, so we use
414     // in place new to init the new map entry. No need to do anything with the result,
415     // so just chuck it.
416     CONSISTENCY_CHECK(bmtInterface->dwInterfaceMapSize < bmtInterface->dwInterfaceMapAllocated);
417     new ((void *)&bmtInterface->pInterfaceMap[bmtInterface->dwInterfaceMapSize])
418         bmtInterfaceEntry(pNewItfType, declScope);
419
420     bmtInterface->dwInterfaceMapSize++;
421
422     // Checking for further expanded interfaces isn't necessary for the system module, as we can rely on the C# compiler
423     // to have found all of the interfaces that the type implements, and to place them in the interface list itself. Also
424     // we can assume no ambiguous interfaces
425     // Code related to this is marked with #SpecialCorelibInterfaceExpansionAlgorithm
426     if (!(GetModule()->IsSystem() && IsValueClass()))
427     {
428         // Make sure to pass in the substitution from the new itf type created above as
429         // these methods assume that substitutions are allocated in the stacking heap,
430         // not the stack.
431         InterfaceDeclarationScope declaredItfScope(declScope.fIsInterfaceDeclaredOnParent, false);
432         ExpandApproxDeclaredInterfaces(
433             bmtInterface,
434             bmtTypeHandle(pNewItfType),
435             declaredItfScope
436             COMMA_INDEBUG(dbg_pClassMT));
437     }
438 } // MethodTableBuilder::ExpandApproxInterface
439
440 //*******************************************************************************
441 // Arguments:
442 //   dbg_pClassMT - Class on which the interfaces are declared (either explicitly or implicitly).
443 //                  It will never be an interface. It may be NULL (if it is the type being built).
444 void
445 MethodTableBuilder::ExpandApproxDeclaredInterfaces(
446     bmtInterfaceInfo *          bmtInterface,  // out parameter, various parts cumulatively written to.
447     bmtTypeHandle               thType,
448     InterfaceDeclarationScope   declScope
449     COMMA_INDEBUG(MethodTable * dbg_pClassMT))
450 {
451     STANDARD_VM_CONTRACT;
452
453     _ASSERTE((dbg_pClassMT == NULL) || !dbg_pClassMT->IsInterface());
454
455     HRESULT hr;
456     // Iterate the list of interfaces declared by thType and add them to the map.
457     InterfaceImplEnum ie(thType.GetModule(), thType.GetTypeDefToken(), &thType.GetSubstitution());
458     while ((hr = ie.Next()) == S_OK)
459     {
460         MethodTable *pGenericIntf = ClassLoader::LoadApproxTypeThrowing(
461             thType.GetModule(), ie.CurrentToken(), NULL, NULL).GetMethodTable();
462         CONSISTENCY_CHECK(pGenericIntf->IsInterface());
463
464         ExpandApproxInterface(bmtInterface,
465                               ie.CurrentSubst(),
466                               pGenericIntf,
467                               declScope
468                               COMMA_INDEBUG(dbg_pClassMT));
469     }
470     if (FAILED(hr))
471     {
472         BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
473     }
474 } // MethodTableBuilder::ExpandApproxDeclaredInterfaces
475
476 //*******************************************************************************
477 void
478 MethodTableBuilder::ExpandApproxInheritedInterfaces(
479     bmtInterfaceInfo *      bmtInterface,
480     bmtRTType *             pParentType)
481 {
482     STANDARD_VM_CONTRACT;
483
484     // Expand interfaces in superclasses first.  Interfaces inherited from parents
485     // must have identical indexes as in the parent.
486     bmtRTType * pParentOfParent = pParentType->GetParentType();
487
488     //#InterfaceMap_SupersetOfParent
489     // We have to load parent's interface map the same way the parent did it (as open type).
490     // Further code depends on this:
491     //    code:#InterfaceMap_UseParentInterfaceImplementations
492     // We check that it is truth:
493     //    code:#ApproxInterfaceMap_SupersetOfParent
494     //    code:#ExactInterfaceMap_SupersetOfParent
495     //
496     //#InterfaceMap_CanonicalSupersetOfParent
497     // Note that canonical instantiation of parent can have different interface instantiations in the
498     // interface map than derived type:
499     //    class MyClass<T> : MyBase<string, T>, I<T>
500     //    class MyBase<U, V> : I<U>
501     // Type MyClass<_Canon> has MyBase<_Canon,_Canon> as parent. The interface maps are:
502     //    MyBase<_Canon,_Canon> ... I<_Canon>
503     //    MyClass<_Canon> ... I<string> (#1)
504     //                        I<_Canon> (#2)
505     // The I's instantiation I<string> (#1) in MyClass and I<_Canon> from MyBase are not the same
506     // instantiations.
507
508     // Backup parent substitution
509     Substitution parentSubstitution = pParentType->GetSubstitution();
510     // Make parent an open type
511     pParentType->SetSubstitution(Substitution());
512
513     if (pParentOfParent != NULL)
514     {
515         ExpandApproxInheritedInterfaces(bmtInterface, pParentOfParent);
516     }
517
518     InterfaceDeclarationScope declScope(true, false);
519     ExpandApproxDeclaredInterfaces(
520         bmtInterface,
521         bmtTypeHandle(pParentType),
522         declScope
523         COMMA_INDEBUG(pParentType->GetMethodTable()));
524
525     // Make sure we loaded the same number of interfaces as the parent type itself
526     CONSISTENCY_CHECK(pParentType->GetMethodTable()->GetNumInterfaces() == bmtInterface->dwInterfaceMapSize);
527
528     // Restore parent's substitution
529     pParentType->SetSubstitution(parentSubstitution);
530 } // MethodTableBuilder::ExpandApproxInheritedInterfaces
531
532 //*******************************************************************************
533 // Fill out a fully expanded interface map, such that if we are declared to
534 // implement I3, and I3 extends I1,I2, then I1,I2 are added to our list if
535 // they are not already present.
536 void
537 MethodTableBuilder::LoadApproxInterfaceMap()
538 {
539     STANDARD_VM_CONTRACT;
540
541     bmtInterface->dwInterfaceMapSize = 0;
542
543 #ifdef _DEBUG
544     //#InjectInterfaceDuplicates_Main
545     // We will inject duplicate interfaces in check builds if env. var.
546     // COMPLUS_INTERNAL_TypeLoader_InjectInterfaceDuplicates is set to TRUE for all types (incl. non-generic
547     // types).
548     // This should allow us better test coverage of duplicates in interface map.
549     //
550     // The duplicates are legal for some types:
551     //     A<T> : I<T>
552     //     B<U,V> : A<U>, I<V>
553     //     C : B<int,int>
554     //   where the interface maps are:
555     //     A<T>             ... 1 item:  I<T>
556     //     A<int>           ... 1 item:  I<int>
557     //     B<U,V>           ... 2 items: I<U>, I<V>
558     //     B<int,int>       ... 2 items: I<int>, I<int>
559     //     B<_Canon,_Canon> ... 2 items: I<_Canon>, I<_Canon>
560     //     B<string,string> ... 2 items: I<string>, I<string>
561     //     C                ... 2 items: I<int>, I<int>
562     //     Note: C had only 1 item (I<int>) in CLR 2.0 RTM/SP1/SP2 and early in CLR 4.0.
563     //
564     // We will create duplicate from every re-implemented interface (incl. non-generic):
565     //   code:#InjectInterfaceDuplicates_ApproxInterfaces
566     //   code:#InjectInterfaceDuplicates_LoadExactInterfaceMap
567     //   code:#InjectInterfaceDuplicates_ExactInterfaces
568     //
569     // Note that we don't have to do anything for COM, because COM has its own interface map
570     // (code:InteropMethodTableData)which is independent on type's interface map and is created only from
571     // non-generic interfaces (see code:ClassCompat::MethodTableBuilder::BuildInteropVTable_InterfaceList)
572
573     // We need to keep track which interface duplicates were injected. Right now its either all interfaces
574     // (declared on the type being built, not inheritted) or none. In the future we could inject duplicates
575     // just for some of them.
576     bmtInterface->dbg_fShouldInjectInterfaceDuplicates =
577         (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_TypeLoader_InjectInterfaceDuplicates) != 0);
578     if (bmtGenerics->Debug_GetTypicalMethodTable() != NULL)
579     {   // It's safer to require that all instantiations have the same injected interface duplicates.
580         // In future we could inject different duplicates for various non-shared instantiations.
581
582         // Use the same injection status as typical instantiation
583         bmtInterface->dbg_fShouldInjectInterfaceDuplicates =
584             bmtGenerics->Debug_GetTypicalMethodTable()->Debug_HasInjectedInterfaceDuplicates();
585     }
586 #endif //_DEBUG
587
588     // First inherit all the parent's interfaces.  This is important, because our interface map must
589     // list the interfaces in identical order to our parent.
590     //
591     // <NICE> we should document the reasons why.  One reason is that DispatchMapTypeIDs can be indexes
592     // into the list </NICE>
593     if (HasParent())
594     {
595         ExpandApproxInheritedInterfaces(bmtInterface, GetParentType());
596 #ifdef _DEBUG
597         //#ApproxInterfaceMap_SupersetOfParent
598         // Check that parent's interface map is the same as what we just computed
599         // See code:#InterfaceMap_SupersetOfParent
600         {
601             MethodTable * pParentMT = GetParentMethodTable();
602             _ASSERTE(pParentMT->GetNumInterfaces() == bmtInterface->dwInterfaceMapSize);
603
604             MethodTable::InterfaceMapIterator parentInterfacesIterator = pParentMT->IterateInterfaceMap();
605             UINT32 nInterfaceIndex = 0;
606             while (parentInterfacesIterator.Next())
607             {
608                 // Compare TypeDefs of the parent's interface and this interface (full MT comparison is in
609                 // code:#ExactInterfaceMap_SupersetOfParent)
610                 OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOAD_APPROXPARENTS);
611                 _ASSERTE(parentInterfacesIterator.GetInterfaceInfo()->GetApproxMethodTable(pParentMT->GetLoaderModule())->HasSameTypeDefAs(
612                     bmtInterface->pInterfaceMap[nInterfaceIndex].GetInterfaceType()->GetMethodTable()));
613                 nInterfaceIndex++;
614             }
615             _ASSERTE(nInterfaceIndex == bmtInterface->dwInterfaceMapSize);
616         }
617 #endif //_DEBUG
618     }
619
620     // Now add in any freshly declared interfaces, possibly augmenting the flags
621     InterfaceDeclarationScope declScope(false, true);
622     ExpandApproxDeclaredInterfaces(
623         bmtInterface,
624         bmtInternal->pType,
625         declScope
626         COMMA_INDEBUG(NULL));
627 } // MethodTableBuilder::LoadApproxInterfaceMap
628
629 //*******************************************************************************
630 // Fills array of TypeIDs with all duplicate occurrences of pDeclIntfMT in the interface map.
631 //
632 // Arguments:
633 //    rg/c DispatchMapTypeIDs - Array of TypeIDs and its count of elements.
634 //    pcIfaceDuplicates - Number of duplicate occurrences of the interface in the interface map (ideally <=
635 //         count of elements TypeIDs.
636 //
637 // Note: If the passed rgDispatchMapTypeIDs array is smaller than the number of duplicates, fills it
638 // with the duplicates that fit and returns number of all existing duplicates (not just those fileld in the
639 // array) in pcIfaceDuplicates.
640 //
641 void
642 MethodTableBuilder::ComputeDispatchMapTypeIDs(
643     MethodTable *        pDeclInftMT,
644     const Substitution * pDeclIntfSubst,
645     DispatchMapTypeID *  rgDispatchMapTypeIDs,
646     UINT32               cDispatchMapTypeIDs,
647     UINT32 *             pcIfaceDuplicates)
648 {
649     STANDARD_VM_CONTRACT;
650
651     _ASSERTE(pDeclInftMT->IsInterface());
652
653     // Count of interface duplicates (also used as index into TypeIDs array)
654     *pcIfaceDuplicates = 0;
655     for (DWORD idx = 0; idx < bmtInterface->dwInterfaceMapSize; idx++)
656     {
657         bmtInterfaceEntry * pItfEntry = &bmtInterface->pInterfaceMap[idx];
658         bmtRTType * pItfType = pItfEntry->GetInterfaceType();
659         // Type Equivalence is forbidden in interface type ids.
660         TokenPairList newVisited = TokenPairList::AdjustForTypeEquivalenceForbiddenScope(NULL);
661         if (MetaSig::CompareTypeDefsUnderSubstitutions(pItfType->GetMethodTable(),
662                                                        pDeclInftMT,
663                                                        &pItfType->GetSubstitution(),
664                                                        pDeclIntfSubst,
665                                                        &newVisited))
666         {   // We found another occurrence of this interface
667             // Can we fit it into the TypeID array?
668             if (*pcIfaceDuplicates < cDispatchMapTypeIDs)
669             {
670                 rgDispatchMapTypeIDs[*pcIfaceDuplicates] = DispatchMapTypeID::InterfaceClassID(idx);
671             }
672             // Increase number of duplicate interfaces
673             (*pcIfaceDuplicates)++;
674         }
675     }
676 } // MethodTableBuilder::ComputeDispatchMapTypeIDs
677
678 //*******************************************************************************
679 /*static*/
680 VOID DECLSPEC_NORETURN
681 MethodTableBuilder::BuildMethodTableThrowException(
682     HRESULT hr,
683     const bmtErrorInfo & bmtError)
684 {
685     CONTRACTL
686     {
687         THROWS;
688         GC_TRIGGERS;
689         INJECT_FAULT(COMPlusThrowOM(););
690     }
691     CONTRACTL_END
692
693     LPCUTF8 pszClassName, pszNameSpace;
694     if (FAILED(bmtError.pModule->GetMDImport()->GetNameOfTypeDef(bmtError.cl, &pszClassName, &pszNameSpace)))
695     {
696         pszClassName = pszNameSpace = "Invalid TypeDef record";
697     }
698
699     if (IsNilToken(bmtError.dMethodDefInError) && (bmtError.szMethodNameForError == NULL))
700     {
701         if (hr == E_OUTOFMEMORY)
702         {
703             COMPlusThrowOM();
704         }
705         else
706             bmtError.pModule->GetAssembly()->ThrowTypeLoadException(
707                 pszNameSpace, pszClassName, bmtError.resIDWhy);
708     }
709     else
710     {
711         LPCUTF8 szMethodName;
712         if (bmtError.szMethodNameForError == NULL)
713         {
714             if (FAILED((bmtError.pModule->GetMDImport())->GetNameOfMethodDef(bmtError.dMethodDefInError, &szMethodName)))
715             {
716                 szMethodName = "Invalid MethodDef record";
717             }
718         }
719         else
720         {
721             szMethodName = bmtError.szMethodNameForError;
722         }
723
724         bmtError.pModule->GetAssembly()->ThrowTypeLoadException(
725             pszNameSpace, pszClassName, szMethodName, bmtError.resIDWhy);
726     }
727 } // MethodTableBuilder::BuildMethodTableThrowException
728
729 //*******************************************************************************
730 void MethodTableBuilder::SetBMTData(
731     LoaderAllocator *bmtAllocator,
732     bmtErrorInfo *bmtError,
733     bmtProperties *bmtProp,
734     bmtVtable *bmtVT,
735     bmtParentInfo *bmtParent,
736     bmtInterfaceInfo *bmtInterface,
737     bmtMetaDataInfo *bmtMetaData,
738     bmtMethodInfo *bmtMethod,
739     bmtMethAndFieldDescs *bmtMFDescs,
740     bmtFieldPlacement *bmtFP,
741     bmtInternalInfo *bmtInternal,
742     bmtGCSeriesInfo *bmtGCSeries,
743     bmtMethodImplInfo *bmtMethodImpl,
744     const bmtGenericsInfo *bmtGenerics,
745     bmtEnumFieldInfo *bmtEnumFields)
746 {
747     LIMITED_METHOD_CONTRACT;
748     this->bmtAllocator = bmtAllocator;
749     this->bmtError = bmtError;
750     this->bmtProp = bmtProp;
751     this->bmtVT = bmtVT;
752     this->bmtParent = bmtParent;
753     this->bmtInterface = bmtInterface;
754     this->bmtMetaData = bmtMetaData;
755     this->bmtMethod = bmtMethod;
756     this->bmtMFDescs = bmtMFDescs;
757     this->bmtFP = bmtFP;
758     this->bmtInternal = bmtInternal;
759     this->bmtGCSeries = bmtGCSeries;
760     this->bmtMethodImpl = bmtMethodImpl;
761     this->bmtGenerics = bmtGenerics;
762     this->bmtEnumFields = bmtEnumFields;
763 }
764
765 //*******************************************************************************
766 // Used by MethodTableBuilder
767
768 MethodTableBuilder::bmtRTType *
769 MethodTableBuilder::CreateTypeChain(
770     MethodTable *        pMT,
771     const Substitution & subst)
772 {
773     CONTRACTL
774     {
775         STANDARD_VM_CHECK;
776         INSTANCE_CHECK;
777         PRECONDITION(CheckPointer(GetStackingAllocator()));
778         PRECONDITION(CheckPointer(pMT));
779     } CONTRACTL_END;
780
781     pMT = pMT->GetCanonicalMethodTable();
782
783     bmtRTType * pType = new (GetStackingAllocator())
784         bmtRTType(subst, pMT);
785
786     MethodTable * pMTParent = pMT->GetParentMethodTable();
787     if (pMTParent != NULL)
788     {
789         pType->SetParentType(
790             CreateTypeChain(
791                 pMTParent,
792                 pMT->GetSubstitutionForParent(&pType->GetSubstitution())));
793     }
794
795     return pType;
796 }
797
798 //*******************************************************************************
799 /* static */
800 MethodTableBuilder::bmtRTType *
801 MethodTableBuilder::bmtRTType::FindType(
802     bmtRTType *          pType,
803     MethodTable *        pTargetMT)
804 {
805     CONTRACTL {
806         STANDARD_VM_CHECK;
807         PRECONDITION(CheckPointer(pType));
808         PRECONDITION(CheckPointer(pTargetMT));
809     } CONTRACTL_END;
810
811     pTargetMT = pTargetMT->GetCanonicalMethodTable();
812     while (pType != NULL &&
813            pType->GetMethodTable()->GetCanonicalMethodTable() != pTargetMT)
814     {
815         pType = pType->GetParentType();
816     }
817
818     return pType;
819 }
820
821 //*******************************************************************************
822 mdTypeDef
823 MethodTableBuilder::bmtRTType::GetEnclosingTypeToken() const
824 {
825     STANDARD_VM_CONTRACT;
826
827     mdTypeDef tok = mdTypeDefNil;
828
829     if (IsNested())
830     {   // This is guaranteed to succeed because the EEClass would not have been
831         // set as nested unless a valid token was stored in metadata.
832         if (FAILED(GetModule()->m_pEnclosingTypeMap->GetEnclosingTypeNoThrow(GetTypeDefToken(), &tok, GetModule()->GetMDImport())))
833         {
834             return mdTypeDefNil;
835         }
836     }
837
838     return tok;
839 }
840
841 //*******************************************************************************
842 /*static*/ bool
843 MethodTableBuilder::MethodSignature::NamesEqual(
844     const MethodSignature & sig1,
845     const MethodSignature & sig2)
846 {
847     STANDARD_VM_CONTRACT;
848
849     if (sig1.GetNameHash() != sig2.GetNameHash())
850     {
851         return false;
852     }
853
854     if (strcmp(sig1.GetName(), sig2.GetName()) != 0)
855     {
856         return false;
857     }
858
859     return true;
860 }
861
862 //*******************************************************************************
863 /*static*/ bool
864 MethodTableBuilder::MethodSignature::SignaturesEquivalent(
865     const MethodSignature & sig1,
866     const MethodSignature & sig2,
867     BOOL allowCovariantReturn)
868 {
869     STANDARD_VM_CONTRACT;
870
871     return !!MetaSig::CompareMethodSigs(
872         sig1.GetSignature(), static_cast<DWORD>(sig1.GetSignatureLength()), sig1.GetModule(), sig1.GetSubstitution(),
873         sig2.GetSignature(), static_cast<DWORD>(sig2.GetSignatureLength()), sig2.GetModule(), sig2.GetSubstitution(),
874         allowCovariantReturn);
875 }
876
877 //*******************************************************************************
878 /*static*/ bool
879 MethodTableBuilder::MethodSignature::SignaturesExactlyEqual(
880     const MethodSignature & sig1,
881     const MethodSignature & sig2)
882 {
883     STANDARD_VM_CONTRACT;
884
885     TokenPairList newVisited = TokenPairList::AdjustForTypeEquivalenceForbiddenScope(NULL);
886     return !!MetaSig::CompareMethodSigs(
887         sig1.GetSignature(), static_cast<DWORD>(sig1.GetSignatureLength()), sig1.GetModule(), sig1.GetSubstitution(),
888         sig2.GetSignature(), static_cast<DWORD>(sig2.GetSignatureLength()), sig2.GetModule(), sig2.GetSubstitution(),
889         FALSE, &newVisited);
890 }
891
892 //*******************************************************************************
893 bool
894 MethodTableBuilder::MethodSignature::Equivalent(
895     const MethodSignature &rhs) const
896 {
897     STANDARD_VM_CONTRACT;
898
899     return NamesEqual(*this, rhs) && SignaturesEquivalent(*this, rhs, FALSE);
900 }
901
902 //*******************************************************************************
903 bool
904 MethodTableBuilder::MethodSignature::ExactlyEqual(
905     const MethodSignature &rhs) const
906 {
907     STANDARD_VM_CONTRACT;
908
909     return NamesEqual(*this, rhs) && SignaturesExactlyEqual(*this, rhs);
910 }
911
912 //*******************************************************************************
913 void
914 MethodTableBuilder::MethodSignature::GetMethodAttributes() const
915 {
916     STANDARD_VM_CONTRACT;
917
918     IMDInternalImport * pIMD = GetModule()->GetMDImport();
919     if (TypeFromToken(GetToken()) == mdtMethodDef)
920     {
921         DWORD cSig;
922         if (FAILED(pIMD->GetNameAndSigOfMethodDef(GetToken(), &m_pSig, &cSig, &m_szName)))
923         {   // We have empty name or signature on error, do nothing
924         }
925         m_cSig = static_cast<size_t>(cSig);
926     }
927     else
928     {
929         CONSISTENCY_CHECK(TypeFromToken(m_tok) == mdtMemberRef);
930         DWORD cSig;
931         if (FAILED(pIMD->GetNameAndSigOfMemberRef(GetToken(), &m_pSig, &cSig, &m_szName)))
932         {   // We have empty name or signature on error, do nothing
933         }
934         m_cSig = static_cast<size_t>(cSig);
935     }
936 }
937
938 //*******************************************************************************
939 UINT32
940 MethodTableBuilder::MethodSignature::GetNameHash() const
941 {
942     STANDARD_VM_CONTRACT;
943
944     CheckGetMethodAttributes();
945
946     if (m_nameHash == INVALID_NAME_HASH)
947     {
948         ULONG nameHash = HashStringA(GetName());
949         if (nameHash == INVALID_NAME_HASH)
950         {
951             nameHash /= 2;
952         }
953         m_nameHash = nameHash;
954     }
955
956     return m_nameHash;
957 }
958
959 //*******************************************************************************
960 MethodTableBuilder::bmtMDType::bmtMDType(
961     bmtRTType *             pParentType,
962     Module *                pModule,
963     mdTypeDef               tok,
964     const SigTypeContext &  sigContext)
965     : m_pParentType(pParentType),
966       m_pModule(pModule),
967       m_tok(tok),
968       m_enclTok(mdTypeDefNil),
969       m_sigContext(sigContext),
970       m_subst(),
971       m_dwAttrs(0),
972       m_pMT(NULL)
973 {
974     STANDARD_VM_CONTRACT;
975
976     IfFailThrow(m_pModule->GetMDImport()->GetTypeDefProps(m_tok, &m_dwAttrs, NULL));
977
978     HRESULT hr = m_pModule->m_pEnclosingTypeMap->GetEnclosingTypeNoThrow(m_tok, &m_enclTok, m_pModule->GetMDImport());
979
980     if (FAILED(hr))
981     {
982         if (hr != CLDB_E_RECORD_NOTFOUND)
983         {
984             ThrowHR(hr);
985         }
986         // Just in case GetNestedClassProps sets the out param to some other value
987         m_enclTok = mdTypeDefNil;
988     }
989 }
990
991 //*******************************************************************************
992 MethodTableBuilder::bmtRTMethod::bmtRTMethod(
993     bmtRTType *     pOwningType,
994     MethodDesc *    pMD)
995     : m_pOwningType(pOwningType),
996       m_pMD(pMD),
997       m_methodSig(pMD->GetModule(),
998                   pMD->GetMemberDef(),
999                   &pOwningType->GetSubstitution())
1000 {
1001     CONTRACTL
1002     {
1003         THROWS;
1004         GC_TRIGGERS;
1005         MODE_ANY;
1006     }
1007     CONTRACTL_END;
1008 }
1009
1010 //*******************************************************************************
1011 MethodTableBuilder::bmtMDMethod::bmtMDMethod(
1012     bmtMDType * pOwningType,
1013     mdMethodDef tok,
1014     DWORD dwDeclAttrs,
1015     DWORD dwImplAttrs,
1016     DWORD dwRVA,
1017     MethodClassification type,
1018     METHOD_IMPL_TYPE implType)
1019     : m_pOwningType(pOwningType),
1020       m_dwDeclAttrs(dwDeclAttrs),
1021       m_dwImplAttrs(dwImplAttrs),
1022       m_dwRVA(dwRVA),
1023       m_type(type),
1024       m_implType(implType),
1025       m_methodSig(pOwningType->GetModule(),
1026                   tok,
1027                   &pOwningType->GetSubstitution()),
1028       m_pMD(NULL),
1029       m_pUnboxedMD(NULL),
1030       m_slotIndex(INVALID_SLOT_INDEX),
1031       m_unboxedSlotIndex(INVALID_SLOT_INDEX)
1032     {
1033         CONTRACTL
1034         {
1035             THROWS;
1036             GC_TRIGGERS;
1037             MODE_ANY;
1038         }
1039         CONTRACTL_END;
1040     }
1041 //*******************************************************************************
1042 void
1043 MethodTableBuilder::ImportParentMethods()
1044 {
1045     STANDARD_VM_CONTRACT;
1046
1047     if (!HasParent())
1048     {   // If there's no parent, there's no methods to import
1049         return;
1050     }
1051
1052     SLOT_INDEX numMethods = static_cast<SLOT_INDEX>
1053         (GetParentMethodTable()->GetNumMethods());
1054
1055     bmtParent->pSlotTable = new (GetStackingAllocator())
1056         bmtMethodSlotTable(numMethods, GetStackingAllocator());
1057
1058     MethodTable::MethodIterator it(GetParentMethodTable());
1059     for (;it.IsValid(); it.Next())
1060     {
1061         MethodDesc *  pDeclDesc = NULL;
1062         MethodTable * pDeclMT   = NULL;
1063         MethodDesc *  pImplDesc = NULL;
1064         MethodTable * pImplMT   = NULL;
1065
1066         if (it.IsVirtual())
1067         {
1068             pDeclDesc = it.GetDeclMethodDesc();
1069             pDeclMT = pDeclDesc->GetMethodTable();
1070             pImplDesc = it.GetMethodDesc();
1071             pImplMT = pImplDesc->GetMethodTable();
1072         }
1073         else
1074         {
1075             pDeclDesc = pImplDesc = it.GetMethodDesc();
1076             pDeclMT = pImplMT = it.GetMethodDesc()->GetMethodTable();
1077         }
1078
1079         CONSISTENCY_CHECK(CheckPointer(pDeclDesc));
1080         CONSISTENCY_CHECK(CheckPointer(pImplDesc));
1081
1082         // Create and assign to each slot
1083         bmtMethodSlot newSlot;
1084         newSlot.Decl() = new (GetStackingAllocator())
1085             bmtRTMethod(bmtRTType::FindType(GetParentType(), pDeclMT), pDeclDesc);
1086         if (pDeclDesc == pImplDesc)
1087         {
1088             newSlot.Impl() = newSlot.Decl();
1089         }
1090         else
1091         {
1092             newSlot.Impl() = new (GetStackingAllocator())
1093                 bmtRTMethod(bmtRTType::FindType(GetParentType(), pImplMT), pImplDesc);
1094         }
1095
1096         if (!bmtParent->pSlotTable->AddMethodSlot(newSlot))
1097             BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
1098     }
1099 }
1100
1101 //*******************************************************************************
1102 void
1103 MethodTableBuilder::CopyParentVtable()
1104 {
1105     STANDARD_VM_CONTRACT;
1106
1107     if (!HasParent())
1108     {
1109         return;
1110     }
1111
1112     for (bmtParentInfo::Iterator it = bmtParent->IterateSlots();
1113          !it.AtEnd() && it.CurrentIndex() < GetParentMethodTable()->GetNumVirtuals();
1114          ++it)
1115      {
1116         if (!bmtVT->pSlotTable->AddMethodSlot(*it))
1117             BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
1118         ++bmtVT->cVirtualSlots;
1119         ++bmtVT->cTotalSlots;
1120      }
1121 }
1122
1123 //*******************************************************************************
1124 // Determine if this is the special SIMD type System.Numerics.Vector<T>, whose
1125 // size is determined dynamically based on the hardware and the presence of JIT
1126 // support.
1127 // If so:
1128 //   - Update the NumInstanceFieldBytes on the bmtFieldPlacement.
1129 //   - Update the m_cbNativeSize and m_cbManagedSize if HasLayout() is true.
1130 // Return a BOOL result to indicate whether the size has been updated.
1131 //
1132 BOOL MethodTableBuilder::CheckIfSIMDAndUpdateSize()
1133 {
1134     STANDARD_VM_CONTRACT;
1135
1136 #if defined(TARGET_X86) || defined(TARGET_AMD64)
1137     if (!bmtProp->fIsIntrinsicType)
1138         return false;
1139
1140     if (bmtFP->NumInstanceFieldBytes != 16)
1141         return false;
1142
1143     LPCUTF8 className;
1144     LPCUTF8 nameSpace;
1145
1146     if (FAILED(GetMDImport()->GetNameOfTypeDef(bmtInternal->pType->GetTypeDefToken(), &className, &nameSpace)))
1147         return false;
1148
1149     if (strcmp(className, "Vector`1") != 0 || strcmp(nameSpace, "System.Numerics") != 0)
1150         return false;
1151
1152     CORJIT_FLAGS CPUCompileFlags       = ExecutionManager::GetEEJitManager()->GetCPUCompileFlags();
1153     uint32_t     numInstanceFieldBytes = 16;
1154
1155     if (CPUCompileFlags.IsSet(InstructionSet_VectorT512))
1156     {
1157         // TODO-XARCH: The JIT needs to be updated to support 64-byte Vector<T>
1158         numInstanceFieldBytes = 32;
1159     }
1160     else if (CPUCompileFlags.IsSet(InstructionSet_VectorT256))
1161     {
1162         numInstanceFieldBytes = 32;
1163     }
1164
1165     if (numInstanceFieldBytes != 16)
1166     {
1167         bmtFP->NumInstanceFieldBytes = numInstanceFieldBytes;
1168
1169         if (HasLayout())
1170         {
1171             GetLayoutInfo()->m_cbManagedSize = numInstanceFieldBytes;
1172         }
1173
1174         return true;
1175     }
1176 #endif // TARGET_X86 || TARGET_AMD64
1177
1178     return false;
1179 }
1180
1181 //*******************************************************************************
1182 void
1183 MethodTableBuilder::bmtInterfaceEntry::CreateSlotTable(
1184     StackingAllocator * pStackingAllocator)
1185 {
1186     STANDARD_VM_CONTRACT;
1187
1188     CONSISTENCY_CHECK(m_pImplTable == NULL);
1189
1190     SLOT_INDEX cSlots = (SLOT_INDEX)GetInterfaceType()->GetMethodTable()->GetNumVirtuals();
1191     SLOT_INDEX cSlotsTotal = cSlots;
1192
1193     if (GetInterfaceType()->GetMethodTable()->HasVirtualStaticMethods())
1194     {
1195         MethodTable::MethodIterator it(GetInterfaceType()->GetMethodTable());
1196         for (; it.IsValid(); it.Next())
1197         {
1198             MethodDesc *pDeclMD = it.GetDeclMethodDesc();
1199             if (pDeclMD->IsStatic() && pDeclMD->IsVirtual())
1200             {
1201                 cSlotsTotal++;
1202             }
1203         }
1204     }
1205
1206     bmtInterfaceSlotImpl * pST = new (pStackingAllocator) bmtInterfaceSlotImpl[cSlotsTotal];
1207
1208
1209     MethodTable::MethodIterator it(GetInterfaceType()->GetMethodTable());
1210     for (; it.IsValid(); it.Next())
1211     {
1212         MethodDesc *pDeclMD = it.GetDeclMethodDesc();
1213         if (!pDeclMD->IsVirtual())
1214         {
1215             continue;
1216         }
1217
1218         bmtRTMethod * pCurMethod = new (pStackingAllocator)
1219             bmtRTMethod(GetInterfaceType(), it.GetDeclMethodDesc());
1220
1221         if (pDeclMD->IsStatic())
1222         {
1223             pST[cSlots + m_cImplTableStatics++] = bmtInterfaceSlotImpl(pCurMethod, INVALID_SLOT_INDEX);
1224         }
1225         else
1226         {
1227             CONSISTENCY_CHECK(m_cImplTable == it.GetSlotNumber());
1228             pST[m_cImplTable++] = bmtInterfaceSlotImpl(pCurMethod, INVALID_SLOT_INDEX);
1229         }
1230     }
1231
1232     m_pImplTable = pST;
1233 }
1234
1235 #ifdef _PREFAST_
1236 #pragma warning(push)
1237 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
1238 #endif // _PREFAST_
1239 //---------------------------------------------------------------------------------------
1240 //
1241 // Builds the method table, allocates MethodDesc, handles overloaded members, attempts to compress
1242 // interface storage.  All dependent classes must already be resolved!
1243 //
1244 MethodTable *
1245 MethodTableBuilder::BuildMethodTableThrowing(
1246     LoaderAllocator *          pAllocator,
1247     Module *                   pLoaderModule,
1248     Module *                   pModule,
1249     mdToken                    cl,
1250     BuildingInterfaceInfo_t *  pBuildingInterfaceList,
1251     const LayoutRawFieldInfo * pLayoutRawFieldInfos,
1252     MethodTable *              pParentMethodTable,
1253     const bmtGenericsInfo *    bmtGenericsInfo,
1254     SigPointer                 parentInst,
1255     WORD                       cBuildingInterfaceList)
1256 {
1257     CONTRACTL
1258     {
1259         STANDARD_VM_CHECK;
1260         PRECONDITION(CheckPointer(GetHalfBakedClass()));
1261         PRECONDITION(CheckPointer(bmtGenericsInfo));
1262     }
1263     CONTRACTL_END;
1264
1265     pModule->EnsureLibraryLoaded();
1266
1267     // The following structs, defined as private members of MethodTableBuilder, contain the necessary local
1268     // parameters needed for BuildMethodTable Look at the struct definitions for a detailed list of all
1269     // parameters available to BuildMethodTableThrowing.
1270
1271     SetBMTData(
1272         pAllocator,
1273         new (GetStackingAllocator()) bmtErrorInfo(),
1274         new (GetStackingAllocator()) bmtProperties(),
1275         new (GetStackingAllocator()) bmtVtable(),
1276         new (GetStackingAllocator()) bmtParentInfo(),
1277         new (GetStackingAllocator()) bmtInterfaceInfo(),
1278         new (GetStackingAllocator()) bmtMetaDataInfo(),
1279         new (GetStackingAllocator()) bmtMethodInfo(),
1280         new (GetStackingAllocator()) bmtMethAndFieldDescs(),
1281         new (GetStackingAllocator()) bmtFieldPlacement(),
1282         new (GetStackingAllocator()) bmtInternalInfo(),
1283         new (GetStackingAllocator()) bmtGCSeriesInfo(),
1284         new (GetStackingAllocator()) bmtMethodImplInfo(),
1285         bmtGenericsInfo,
1286         new (GetStackingAllocator()) bmtEnumFieldInfo(pModule->GetMDImport()));
1287
1288     //Initialize structs
1289
1290     bmtError->resIDWhy = IDS_CLASSLOAD_GENERAL;          // Set the reason and the offending method def. If the method information
1291     bmtError->pThrowable = NULL;
1292     bmtError->pModule  = pModule;
1293     bmtError->cl       = cl;
1294
1295     bmtInternal->pInternalImport = pModule->GetMDImport();
1296     bmtInternal->pModule = pModule;
1297
1298     bmtInternal->pParentMT = pParentMethodTable;
1299
1300     // Create the chain of bmtRTType for the parent types. This allows all imported
1301     // parent methods to be associated with their declaring types, and as such it is
1302     // easy to access the appropriate Substitution when comparing signatures.
1303     bmtRTType * pParent = NULL;
1304     if (pParentMethodTable != NULL)
1305     {
1306         Substitution * pParentSubst =
1307             new (GetStackingAllocator()) Substitution(pModule, parentInst, NULL);
1308         pParent = CreateTypeChain(pParentMethodTable, *pParentSubst);
1309     }
1310
1311     // Now create the bmtMDType for the type being built.
1312     bmtInternal->pType = new (GetStackingAllocator())
1313         bmtMDType(pParent, pModule, cl, bmtGenericsInfo->typeContext);
1314
1315     // If not NULL, it means there are some by-value fields, and this contains an entry for each inst
1316
1317 #ifdef _DEBUG
1318     // Set debug class name string for easier debugging.
1319     LPCUTF8 className;
1320     LPCUTF8 nameSpace;
1321     if (FAILED(GetMDImport()->GetNameOfTypeDef(bmtInternal->pType->GetTypeDefToken(), &className, &nameSpace)))
1322     {
1323         className = nameSpace = "Invalid TypeDef record";
1324     }
1325
1326     {
1327         S_SIZE_T safeLen = S_SIZE_T(sizeof(char))*(S_SIZE_T(strlen(className)) + S_SIZE_T(strlen(nameSpace)) + S_SIZE_T(2));
1328         if(safeLen.IsOverflow()) COMPlusThrowHR(COR_E_OVERFLOW);
1329
1330         size_t len = safeLen.Value();
1331         char *name = (char*) AllocateFromHighFrequencyHeap(safeLen);
1332         strcpy_s(name, len, nameSpace);
1333         if (strlen(nameSpace) > 0) {
1334             name[strlen(nameSpace)] = '.';
1335             name[strlen(nameSpace) + 1] = '\0';
1336         }
1337         strcat_s(name, len, className);
1338
1339         GetHalfBakedClass()->SetDebugClassName(name);
1340     }
1341
1342     if (g_pConfig->ShouldBreakOnClassBuild(className))
1343     {
1344         CONSISTENCY_CHECK_MSGF(false, ("BreakOnClassBuild: typename '%s' ", className));
1345         GetHalfBakedClass()->m_fDebuggingClass = TRUE;
1346     }
1347
1348     LPCUTF8 pszDebugName,pszDebugNamespace;
1349     if (FAILED(pModule->GetMDImport()->GetNameOfTypeDef(bmtInternal->pType->GetTypeDefToken(), &pszDebugName, &pszDebugNamespace)))
1350     {
1351         pszDebugName = pszDebugNamespace = "Invalid TypeDef record";
1352     }
1353
1354     StackSString debugName(SString::Utf8, pszDebugName);
1355
1356     // If there is an instantiation, update the debug name to include instantiation type names.
1357     if (bmtGenerics->HasInstantiation())
1358     {
1359         StackSString debugName(SString::Utf8, GetDebugClassName());
1360         TypeString::AppendInst(debugName, bmtGenerics->GetInstantiation(), TypeString::FormatBasic);
1361         const char* pDebugNameUTF8 = debugName.GetUTF8();
1362         S_SIZE_T safeLen = S_SIZE_T(strlen(pDebugNameUTF8)) + S_SIZE_T(1);
1363         if(safeLen.IsOverflow())
1364             COMPlusThrowHR(COR_E_OVERFLOW);
1365
1366         size_t len = safeLen.Value();
1367         char *name = (char*) AllocateFromLowFrequencyHeap(safeLen);
1368         strcpy_s(name, len, pDebugNameUTF8);
1369         GetHalfBakedClass()->SetDebugClassName(name);
1370         pszDebugName = (LPCUTF8)name;
1371     }
1372
1373     LOG((LF_CLASSLOADER, LL_INFO1000, "Loading class \"%s%s%s\" from module \"%s\" in domain 0x%p %s\n",
1374         *pszDebugNamespace ? pszDebugNamespace : "",
1375         *pszDebugNamespace ? NAMESPACE_SEPARATOR_STR : "",
1376         debugName.GetUTF8(),
1377         pModule->GetDebugName(),
1378         pModule->GetDomain(),
1379         (pModule->IsSystem()) ? "System Domain" : ""
1380     ));
1381 #endif // _DEBUG
1382
1383     // If this is CoreLib, then don't perform some sanity checks on the layout
1384     bmtProp->fNoSanityChecks = pModule->IsSystem() ||
1385 #ifdef FEATURE_READYTORUN
1386         // No sanity checks for ready-to-run compiled images if possible
1387         (pModule->IsReadyToRun() && pModule->GetReadyToRunInfo()->SkipTypeValidation()) ||
1388 #endif
1389         // No sanity checks for real generic instantiations
1390         !bmtGenerics->IsTypicalTypeDefinition();
1391
1392     // Interfaces have a parent class of Object, but we don't really want to inherit all of
1393     // Object's virtual methods, so pretend we don't have a parent class - at the bottom of this
1394     // function we reset the parent class
1395     if (IsInterface())
1396     {
1397         bmtInternal->pType->SetParentType(NULL);
1398         bmtInternal->pParentMT = NULL;
1399     }
1400
1401     unsigned totalDeclaredFieldSize=0;
1402
1403     // Check to see if the class is a valuetype; but we don't want to mark System.Enum
1404     // as a ValueType. To accomplish this, the check takes advantage of the fact
1405     // that System.ValueType and System.Enum are loaded one immediately after the
1406     // other in that order, and so if the parent MethodTable is System.ValueType and
1407     // the System.Enum MethodTable is unset, then we must be building System.Enum and
1408     // so we don't mark it as a ValueType.
1409     if(HasParent() &&
1410        ((g_pEnumClass != NULL && GetParentMethodTable() == g_pValueTypeClass) ||
1411         GetParentMethodTable() == g_pEnumClass))
1412     {
1413         bmtProp->fIsValueClass = true;
1414
1415         HRESULT hr = GetCustomAttribute(bmtInternal->pType->GetTypeDefToken(),
1416                                         WellKnownAttribute::UnsafeValueType,
1417                                         NULL, NULL);
1418         IfFailThrow(hr);
1419         if (hr == S_OK)
1420         {
1421             SetUnsafeValueClass();
1422         }
1423
1424         hr = GetCustomAttribute(bmtInternal->pType->GetTypeDefToken(),
1425             WellKnownAttribute::IsByRefLike,
1426             NULL, NULL);
1427         IfFailThrow(hr);
1428         if (hr == S_OK)
1429         {
1430             bmtFP->fIsByRefLikeType = true;
1431         }
1432     }
1433
1434     // Check to see if the class is an enumeration. No fancy checks like the one immediately
1435     // above for value types are necessary here.
1436     if(HasParent() && GetParentMethodTable() == g_pEnumClass)
1437     {
1438         bmtProp->fIsEnum = true;
1439
1440         // Ensure we don't have generic enums, or at least enums that have a
1441         // different number of type parameters from their enclosing class.
1442         // The goal is to ensure that the enum's values can't depend on the
1443         // type parameters in any way.  And we don't see any need for an
1444         // enum to have additional type parameters.
1445         if (bmtGenerics->GetNumGenericArgs() != 0)
1446         {
1447             // Nested enums can have generic type parameters from their enclosing class.
1448             // CLS rules require type parameters to be propagated to nested types.
1449             // Note that class G<T> { enum E { } } will produce "G`1+E<T>".
1450             // We want to disallow class G<T> { enum E<T, U> { } }
1451             // Perhaps the IL equivalent of class G<T> { enum E { } } should be legal.
1452             if (!IsNested())
1453             {
1454                 BuildMethodTableThrowException(IDS_CLASSLOAD_ENUM_EXTRA_GENERIC_TYPE_PARAM);
1455             }
1456
1457             mdTypeDef tdEnclosing = mdTypeDefNil;
1458             HRESULT hr = GetModule()->m_pEnclosingTypeMap->GetEnclosingTypeNoThrow(GetCl(), &tdEnclosing, GetModule()->GetMDImport());
1459             if (FAILED(hr))
1460                 ThrowHR(hr, BFA_UNABLE_TO_GET_NESTED_PROPS);
1461
1462             uint32_t genericArgCount;
1463             if (FAILED(GetModule()->m_pTypeGenericInfoMap->GetGenericArgumentCountNoThrow(tdEnclosing, &genericArgCount, GetMDImport())))
1464             {
1465                 GetAssembly()->ThrowTypeLoadException(GetMDImport(), tdEnclosing, IDS_CLASSLOAD_BADFORMAT);
1466             }
1467
1468             if (genericArgCount != bmtGenerics->GetNumGenericArgs())
1469             {
1470                 BuildMethodTableThrowException(IDS_CLASSLOAD_ENUM_EXTRA_GENERIC_TYPE_PARAM);
1471             }
1472         }
1473     }
1474
1475     // If this type is marked by [Intrinsic] attribute, it may be specially treated by the runtime/compiler
1476     // SIMD types have [Intrinsic] attribute, for example
1477     //
1478     // We check this here fairly early to ensure other downstream checks on these types can be slightly more efficient.
1479     if (GetModule()->IsSystem())
1480     {
1481         HRESULT hr = GetCustomAttribute(bmtInternal->pType->GetTypeDefToken(),
1482             WellKnownAttribute::Intrinsic,
1483             NULL,
1484             NULL);
1485
1486         if (hr == S_OK)
1487         {
1488             bmtProp->fIsIntrinsicType = true;
1489         }
1490     }
1491
1492 #if defined(TARGET_X86) || defined(TARGET_AMD64) || defined(TARGET_ARM64)
1493     if (bmtProp->fIsIntrinsicType && !bmtGenerics->HasInstantiation())
1494     {
1495         LPCUTF8 className;
1496         LPCUTF8 nameSpace;
1497         HRESULT hr = GetMDImport()->GetNameOfTypeDef(bmtInternal->pType->GetTypeDefToken(), &className, &nameSpace);
1498
1499         if (bmtInternal->pType->IsNested())
1500         {
1501             IfFailThrow(GetMDImport()->GetNameOfTypeDef(bmtInternal->pType->GetEnclosingTypeToken(), NULL, &nameSpace));
1502         }
1503
1504 #if defined(TARGET_ARM64)
1505         // All the funtions in System.Runtime.Intrinsics.Arm are hardware intrinsics.
1506         if (hr == S_OK && strcmp(nameSpace, "System.Runtime.Intrinsics.Arm") == 0)
1507 #else
1508         // All the funtions in System.Runtime.Intrinsics.X86 are hardware intrinsics.
1509         if (hr == S_OK && (strcmp(nameSpace, "System.Runtime.Intrinsics.X86") == 0))
1510 #endif
1511         {
1512             bmtProp->fIsHardwareIntrinsic = true;
1513         }
1514     }
1515 #endif
1516
1517     // Com Import classes are special. These types must derive from System.Object,
1518     // and we then substitute the parent with System._ComObject.
1519     if (IsComImport() && !IsEnum() && !IsInterface() && !IsValueClass() && !IsDelegate())
1520     {
1521 #ifdef FEATURE_COMINTEROP
1522         // ComImport classes must extend from Object
1523         MethodTable* pMTParent = GetParentMethodTable();
1524         if ((pMTParent == NULL) || (pMTParent != g_pObjectClass))
1525         {
1526             BuildMethodTableThrowException(IDS_CLASSLOAD_CANTEXTEND);
1527         }
1528
1529         if (HasLayout())
1530         {
1531             // ComImport classes cannot have layout information.
1532             BuildMethodTableThrowException(IDS_CLASSLOAD_COMIMPCANNOTHAVELAYOUT);
1533         }
1534
1535         if (g_pBaseCOMObject != NULL)
1536         {
1537             // We could have had COM interop classes derive from System._ComObject,
1538             // but instead we have them derive from System.Object, have them set the
1539             // ComImport bit in the type attributes, and then we swap out the parent
1540             // type under the covers.
1541             bmtInternal->pType->SetParentType(CreateTypeChain(g_pBaseCOMObject, Substitution()));
1542             bmtInternal->pParentMT = g_pBaseCOMObject;
1543         }
1544 #endif
1545         // if the current class is imported
1546         bmtProp->fIsComObjectType = true;
1547     }
1548
1549 #ifdef FEATURE_COMINTEROP
1550     // Check for special COM interop types.
1551     CheckForSpecialTypes();
1552
1553     CheckForTypeEquivalence(cBuildingInterfaceList, pBuildingInterfaceList);
1554
1555     if (HasParent())
1556     {   // Types that inherit from com object types are themselves com object types.
1557         if (GetParentMethodTable()->IsComObjectType())
1558         {
1559             // if the parent class is of ComObjectType
1560             // so is the child
1561             bmtProp->fIsComObjectType = true;
1562         }
1563
1564 #ifdef FEATURE_TYPEEQUIVALENCE
1565         // If your parent is type equivalent then so are you
1566         if (GetParentMethodTable()->HasTypeEquivalence())
1567         {
1568             bmtProp->fHasTypeEquivalence = true;
1569         }
1570 #endif
1571     }
1572
1573 #endif // FEATURE_COMINTEROP
1574
1575     if (!HasParent() && !IsInterface())
1576     {
1577         if(g_pObjectClass != NULL)
1578         {
1579             if(!IsGlobalClass())
1580             {
1581                 // Non object derived types that are not the global class are prohibited by spec
1582                 BuildMethodTableThrowException(IDS_CLASSLOAD_PARENTNULL);
1583             }
1584         }
1585     }
1586
1587     // NOTE: This appears to be the earliest point during class loading that other classes MUST be loaded
1588     // resolve unresolved interfaces, determine an upper bound on the size of the interface map,
1589     // and determine the size of the largest interface (in # slots)
1590     ResolveInterfaces(cBuildingInterfaceList, pBuildingInterfaceList);
1591
1592     // Enumerate this class's methodImpls
1593     EnumerateMethodImpls();
1594
1595     // Enumerate this class's methods and fields
1596     EnumerateClassMethods();
1597     ValidateMethods();
1598
1599     EnumerateClassFields();
1600
1601     // Import the slots of the parent for use in placing this type's methods.
1602     ImportParentMethods();
1603
1604     // This will allocate the working versions of the VTable and NonVTable in bmtVT
1605     AllocateWorkingSlotTables();
1606
1607     // Allocate a MethodDesc* for each method (needed later when doing interfaces), and a FieldDesc* for each field
1608     AllocateFieldDescs();
1609
1610     // Copy the parent's vtable into the current type's vtable
1611     CopyParentVtable();
1612
1613     bmtVT->pDispatchMapBuilder = new (GetStackingAllocator()) DispatchMapBuilder(GetStackingAllocator());
1614
1615     // Determine vtable placement for each member in this class
1616     PlaceVirtualMethods();
1617     PlaceNonVirtualMethods();
1618
1619     // Allocate MethodDescs (expects methods placed methods)
1620     AllocAndInitMethodDescs();
1621
1622     if (IsInterface())
1623     {
1624         //
1625         // We need to process/place method impls for default interface method overrides.
1626         // We won't build dispatch map for interfaces, though.
1627         //
1628         ProcessMethodImpls();
1629         PlaceMethodImpls();
1630     }
1631     else
1632     {
1633         //
1634         // If we are a class, then there may be some unplaced vtable methods (which are by definition
1635         // interface methods, otherwise they'd already have been placed).  Place as many unplaced methods
1636         // as possible, in the order preferred by interfaces.  However, do not allow any duplicates - once
1637         // a method has been placed, it cannot be placed again - if we are unable to neatly place an interface,
1638         // create duplicate slots for it starting at dwCurrentDuplicateVtableSlot.  Fill out the interface
1639         // map for all interfaces as they are placed.
1640         //
1641         // If we are an interface, then all methods are already placed.  Fill out the interface map for
1642         // interfaces as they are placed.
1643         //
1644         ComputeInterfaceMapEquivalenceSet();
1645
1646         PlaceInterfaceMethods();
1647
1648         ProcessMethodImpls();
1649         ProcessInexactMethodImpls();
1650         PlaceMethodImpls();
1651
1652         if (!bmtProp->fNoSanityChecks)
1653         {
1654             // Now that interface method implementation have been fully resolved,
1655             // we need to make sure that type constraints are also met.
1656             ValidateInterfaceMethodConstraints();
1657         }
1658     }
1659
1660     // Verify that we have not overflowed the number of slots.
1661     if (!FitsInU2((UINT64)bmtVT->pSlotTable->GetSlotCount()))
1662     {
1663         BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
1664     }
1665
1666     // ensure we didn't overflow the temporary vtable
1667     _ASSERTE(bmtVT->pSlotTable->GetSlotCount() <= bmtVT->dwMaxVtableSize);
1668
1669     // Allocate and initialize the dictionary for the type. This will be filled out later
1670     // with the final values.
1671     AllocAndInitDictionary();
1672
1673     ////////////////////////////////////////////////////////////////////////////////////////////////
1674     // Fields
1675     //
1676
1677     // We decide here if we need a dynamic entry for our statics. We need it here because
1678     // the offsets of our fields will depend on this. For the dynamic case (which requires
1679     // an extra indirection (indirect depending of methodtable) we'll allocate the slot
1680     // in setupmethodtable
1681     if (((pAllocator->IsCollectible() ||  pModule->IsReflection() || bmtGenerics->HasInstantiation() || !pModule->IsStaticStoragePrepared(cl)) &&
1682         (bmtVT->GetClassCtorSlotIndex() != INVALID_SLOT_INDEX || bmtEnumFields->dwNumStaticFields !=0))
1683 #ifdef EnC_SUPPORTED
1684         // Classes in modules that have been edited (would do on class level if there were a
1685         // way to tell if the class had been edited) also have dynamic statics as the number
1686         // of statics might have changed, so can't use the static module-wide storage
1687         || (pModule->IsEditAndContinueEnabled() &&
1688                 ((EditAndContinueModule*)pModule)->GetApplyChangesCount() > CorDB_DEFAULT_ENC_FUNCTION_VERSION)
1689 #endif // EnC_SUPPORTED
1690         )
1691     {
1692         // We will need a dynamic id
1693         bmtProp->fDynamicStatics = true;
1694
1695         if (bmtGenerics->HasInstantiation())
1696         {
1697             bmtProp->fGenericsStatics = true;
1698         }
1699     }
1700
1701     // If not NULL, it means there are some by-value fields, and this contains an entry for each instance or static field,
1702     // which is NULL if not a by value field, and points to the EEClass of the field if a by value field.  Instance fields
1703     // come first, statics come second.
1704     MethodTable ** pByValueClassCache = NULL;
1705
1706     // Go thru all fields and initialize their FieldDescs.
1707     InitializeFieldDescs(GetApproxFieldDescListRaw(), pLayoutRawFieldInfos, bmtInternal, bmtGenerics,
1708         bmtMetaData, bmtEnumFields, bmtError,
1709         &pByValueClassCache, bmtMFDescs, bmtFP,
1710         &totalDeclaredFieldSize);
1711
1712     if (IsValueClass())
1713     {
1714         const void* pVal;                  // The custom value.
1715         ULONG       cbVal;                 // Size of the custom value.
1716         HRESULT hr = GetCustomAttribute(bmtInternal->pType->GetTypeDefToken(),
1717             WellKnownAttribute::InlineArrayAttribute,
1718             &pVal, &cbVal);
1719
1720         if (hr != S_FALSE)
1721         {
1722             if (bmtEnumFields->dwNumInstanceFields != 1)
1723             {
1724                 BuildMethodTableThrowException(IDS_CLASSLOAD_INLINE_ARRAY_FIELD_COUNT);
1725             }
1726
1727             if (cbVal >= (sizeof(INT32) + 2))
1728             {
1729                 INT32 repeat = GET_UNALIGNED_VAL32((byte*)pVal + 2);
1730                 if (repeat > 0)
1731                 {
1732                     bmtFP->NumInlineArrayElements = repeat;
1733                     GetHalfBakedClass()->SetIsInlineArray();
1734                 }
1735                 else
1736                 {
1737                     BuildMethodTableThrowException(IDS_CLASSLOAD_INLINE_ARRAY_LENGTH);
1738                 }
1739
1740                 if (HasExplicitFieldOffsetLayout())
1741                 {
1742                     BuildMethodTableThrowException(IDS_CLASSLOAD_INLINE_ARRAY_EXPLICIT);
1743                 }
1744             }
1745         }
1746     }
1747
1748     // Place regular static fields
1749     PlaceRegularStaticFields();
1750
1751     // Place thread static fields
1752     PlaceThreadStaticFields();
1753
1754     LOG((LF_CODESHARING,
1755             LL_INFO10000,
1756             "Placing %d statics (%d handles) for class %s.\n",
1757             GetNumStaticFields(), GetNumHandleRegularStatics() + GetNumHandleThreadStatics(),
1758             pszDebugName));
1759
1760     if (IsBlittable() || IsManagedSequential())
1761     {
1762         bmtFP->NumGCPointerSeries = 0;
1763         bmtFP->NumInstanceGCPointerFields = 0;
1764
1765         _ASSERTE(HasLayout());
1766
1767         if (bmtFP->NumInlineArrayElements != 0)
1768         {
1769             GetLayoutInfo()->m_cbManagedSize *= bmtFP->NumInlineArrayElements;
1770         }
1771
1772         bmtFP->NumInstanceFieldBytes = GetLayoutInfo()->m_cbManagedSize;
1773
1774         // For simple Blittable types we still need to check if they have any overlapping
1775         // fields and call the method SetHasOverlaidFields() when they are detected.
1776         //
1777         if (HasExplicitFieldOffsetLayout())
1778         {
1779             _ASSERTE(!bmtGenerics->fContainsGenericVariables);   // A simple Blittable type can't ever be an open generic type.
1780             HandleExplicitLayout(pByValueClassCache);
1781         }
1782     }
1783     else
1784     {
1785         _ASSERTE(!IsBlittable());
1786         // HandleExplicitLayout fails for the GenericTypeDefinition when
1787         // it will succeed for some particular instantiations.
1788         // Thus we only do explicit layout for real instantiations, e.g. C<int>, not
1789         // the open types such as the GenericTypeDefinition C<!0> or any
1790         // of the "fake" types involving generic type variables which are
1791         // used for reflection and verification, e.g. C<List<!0>>.
1792         //
1793         if (!bmtGenerics->fContainsGenericVariables && HasExplicitFieldOffsetLayout())
1794         {
1795             HandleExplicitLayout(pByValueClassCache);
1796         }
1797         else
1798         {
1799             // Place instance fields
1800             PlaceInstanceFields(pByValueClassCache);
1801         }
1802     }
1803
1804     if (CheckIfSIMDAndUpdateSize())
1805     {
1806         totalDeclaredFieldSize = bmtFP->NumInstanceFieldBytes;
1807     }
1808
1809     // We enforce that all value classes have non-zero size
1810     if (IsValueClass() && bmtFP->NumInstanceFieldBytes == 0)
1811     {
1812         BuildMethodTableThrowException(IDS_CLASSLOAD_ZEROSIZE);
1813     }
1814
1815     if (bmtFP->fHasSelfReferencingStaticValueTypeField_WithRVA)
1816     {   // Verify self-referencing statics with RVA (now when the ValueType size is known)
1817         VerifySelfReferencingStaticValueTypeFields_WithRVA(pByValueClassCache);
1818     }
1819
1820
1821     // Now setup the method table
1822
1823     SetupMethodTable2(pLoaderModule);
1824
1825     MethodTable * pMT = GetHalfBakedMethodTable();
1826
1827 #ifdef FEATURE_64BIT_ALIGNMENT
1828     if (GetHalfBakedClass()->IsAlign8Candidate())
1829         pMT->SetRequiresAlign8();
1830 #endif
1831
1832     if (bmtGenerics->pVarianceInfo != NULL)
1833     {
1834         pMT->SetHasVariance();
1835     }
1836
1837     if (bmtFP->NumRegularStaticGCBoxedFields != 0)
1838     {
1839         pMT->SetHasBoxedRegularStatics();
1840     }
1841
1842     if (bmtFP->fIsByRefLikeType)
1843     {
1844         pMT->SetIsByRefLike();
1845     }
1846
1847     if (IsValueClass())
1848     {
1849         if (bmtFP->NumInstanceFieldBytes != totalDeclaredFieldSize || HasOverlaidField())
1850             GetHalfBakedClass()->SetIsNotTightlyPacked();
1851
1852 #ifdef FEATURE_HFA
1853         GetHalfBakedClass()->CheckForHFA(pByValueClassCache);
1854 #endif
1855 #ifdef UNIX_AMD64_ABI
1856 #ifdef FEATURE_HFA
1857 #error "Can't have FEATURE_HFA and UNIX_AMD64_ABI defined at the same time."
1858 #endif // FEATURE_HFA
1859         SystemVAmd64CheckForPassStructInRegister(pByValueClassCache);
1860 #endif // UNIX_AMD64_ABI
1861     }
1862
1863 #ifdef _DEBUG
1864     pMT->SetDebugClassName(GetDebugClassName());
1865 #endif
1866
1867 #ifdef FEATURE_COMINTEROP
1868     if (IsInterface())
1869     {
1870         GetCoClassAttribInfo();
1871     }
1872 #endif // FEATURE_COMINTEROP
1873
1874     if (HasExplicitFieldOffsetLayout())
1875         // Perform relevant GC calculations for tdexplicit
1876         HandleGCForExplicitLayout();
1877     else
1878         // Perform relevant GC calculations for value classes
1879         HandleGCForValueClasses(pByValueClassCache);
1880
1881     // GC reqires the series to be sorted.
1882     // TODO: fix it so that we emit them in the correct order in the first place.
1883     if (pMT->ContainsPointers())
1884     {
1885         CGCDesc* gcDesc = CGCDesc::GetCGCDescFromMT(pMT);
1886         qsort(gcDesc->GetLowestSeries(), (int)gcDesc->GetNumSeries(), sizeof(CGCDescSeries), compareCGCDescSeries);
1887     }
1888
1889     SetFinalizationSemantics();
1890
1891     // Allocate dynamic slot if necessary
1892     if (bmtProp->fDynamicStatics)
1893     {
1894         if (bmtProp->fGenericsStatics)
1895         {
1896             FieldDesc* pStaticFieldDescs = NULL;
1897
1898             if (bmtEnumFields->dwNumStaticFields != 0)
1899             {
1900                 pStaticFieldDescs = pMT->GetApproxFieldDescListRaw() + bmtEnumFields->dwNumInstanceFields;
1901             }
1902
1903             pMT->SetupGenericsStaticsInfo(pStaticFieldDescs);
1904         }
1905         else
1906         {
1907             // Get an id for the dynamic class. We store it in the class because
1908             // no class that is persisted in ngen should have it (ie, if the class is ngened
1909             // The id is stored in an optional field so we need to ensure an optional field descriptor has
1910             // been allocated for this EEClass instance.
1911             EnsureOptionalFieldsAreAllocated(GetHalfBakedClass(), m_pAllocMemTracker, pAllocator->GetLowFrequencyHeap());
1912             SetModuleDynamicID(GetModule()->AllocateDynamicEntry(pMT));
1913         }
1914     }
1915
1916     //
1917     // if there are context or thread static set the info in the method table optional members
1918     //
1919
1920     // structs with GC pointers MUST be pointer sized aligned because the GC assumes it
1921     if (IsValueClass() && pMT->ContainsPointers() && (bmtFP->NumInstanceFieldBytes % TARGET_POINTER_SIZE != 0))
1922     {
1923         BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
1924     }
1925
1926     if (IsInterface())
1927     {
1928         // Reset parent class
1929         pMT->SetParentMethodTable (g_pObjectClass);
1930     }
1931
1932 #ifdef _DEBUG
1933     // Reset the debug method names for BoxedEntryPointStubs
1934     // so they reflect the very best debug information for the methods
1935     {
1936         DeclaredMethodIterator methIt(*this);
1937         while (methIt.Next())
1938         {
1939             if (methIt->GetUnboxedMethodDesc() != NULL)
1940             {
1941                 {
1942                     MethodDesc *pMD = methIt->GetUnboxedMethodDesc();
1943                     StackSString name;
1944                     TypeString::AppendMethodDebug(name, pMD);
1945                     const char* pDebugNameUTF8 = name.GetUTF8();
1946                     S_SIZE_T safeLen = S_SIZE_T(strlen(pDebugNameUTF8)) + S_SIZE_T(1);
1947                     if(safeLen.IsOverflow()) COMPlusThrowHR(COR_E_OVERFLOW);
1948                     size_t len = safeLen.Value();
1949                     pMD->m_pszDebugMethodName = (char*) AllocateFromLowFrequencyHeap(safeLen);
1950                     _ASSERTE(pMD->m_pszDebugMethodName);
1951                     strcpy_s((char *) pMD->m_pszDebugMethodName, len, pDebugNameUTF8);
1952                 }
1953
1954                 {
1955                     MethodDesc *pMD = methIt->GetMethodDesc();
1956
1957                     StackSString name;
1958                     TypeString::AppendMethodDebug(name, pMD);
1959                     const char* pDebugNameUTF8 = name.GetUTF8();
1960                     S_SIZE_T safeLen = S_SIZE_T(strlen(pDebugNameUTF8))+S_SIZE_T(1);
1961                     if(safeLen.IsOverflow()) COMPlusThrowHR(COR_E_OVERFLOW);
1962                     size_t len = safeLen.Value();
1963                     pMD->m_pszDebugMethodName = (char*) AllocateFromLowFrequencyHeap(safeLen);
1964                     _ASSERTE(pMD->m_pszDebugMethodName);
1965                     strcpy_s((char *) pMD->m_pszDebugMethodName, len, pDebugNameUTF8);
1966                 }
1967             }
1968         }
1969     }
1970 #endif // _DEBUG
1971
1972
1973     //If this is a value type, then propagate the UnsafeValueTypeAttribute from
1974     //its instance members to this type.
1975     if (IsValueClass() && !IsUnsafeValueClass())
1976     {
1977         ApproxFieldDescIterator fields(GetHalfBakedMethodTable(),
1978                                        ApproxFieldDescIterator::INSTANCE_FIELDS );
1979         FieldDesc * current;
1980         while (NULL != (current = fields.Next()))
1981         {
1982             CONSISTENCY_CHECK(!current->IsStatic());
1983             if (current->GetFieldType() == ELEMENT_TYPE_VALUETYPE)
1984             {
1985                 _ASSERTE((size_t)fields.GetValueClassCacheIndex() < bmtEnumFields->dwNumInstanceFields);
1986                 TypeHandle th = TypeHandle(pByValueClassCache[fields.GetValueClassCacheIndex()]);
1987                 CONSISTENCY_CHECK(!th.IsNull());
1988                 if (th.AsMethodTable()->GetClass()->IsUnsafeValueClass())
1989                 {
1990                     SetUnsafeValueClass();
1991                     break;
1992                 }
1993             }
1994         }
1995     }
1996
1997     if (!IsValueClass())
1998     {
1999 #ifdef FEATURE_ICASTABLE
2000         if (g_pICastableInterface != NULL && pMT->CanCastToInterface(g_pICastableInterface))
2001         {
2002             pMT->SetICastable();
2003         }
2004 #endif // FEATURE_ICASTABLE
2005
2006         if (g_pIDynamicInterfaceCastableInterface != NULL && pMT->CanCastToInterface(g_pIDynamicInterfaceCastableInterface))
2007         {
2008             pMT->SetIDynamicInterfaceCastable();
2009         }
2010     }
2011
2012 #ifdef FEATURE_OBJCMARSHAL
2013     // Check if this type has a finalizer and then if it is a referenced tracked type.
2014     if (pMT->HasFinalizer() && !IsValueClass() && !IsInterface() && !IsDelegate())
2015     {
2016         BOOL isTrackedReference = FALSE;
2017         if (HasParent())
2018         {
2019             MethodTable * pParentClass = GetParentMethodTable();
2020             PREFIX_ASSUME(pParentClass != NULL);
2021             isTrackedReference = pParentClass->IsTrackedReferenceWithFinalizer();
2022         }
2023
2024         if (!isTrackedReference)
2025         {
2026             HRESULT hr = GetCustomAttribute(bmtInternal->pType->GetTypeDefToken(),
2027                 WellKnownAttribute::ObjectiveCTrackedTypeAttribute,
2028                 NULL,
2029                 NULL);
2030
2031             isTrackedReference = hr == S_OK ? TRUE : FALSE;
2032         }
2033
2034         if (isTrackedReference)
2035             pMT->SetIsTrackedReferenceWithFinalizer();
2036     }
2037 #endif // FEATURE_OBJCMARSHAL
2038
2039     // Grow the typedef ridmap in advance as we can't afford to
2040     // fail once we set the resolve bit
2041     pModule->EnsureTypeDefCanBeStored(bmtInternal->pType->GetTypeDefToken());
2042
2043     // Grow the tables in advance so that RID map filling cannot fail
2044     // once we're past the commit point.
2045     EnsureRIDMapsCanBeFilled();
2046
2047 #ifdef _DEBUG
2048     if (g_pConfig->ShouldDumpOnClassLoad(pszDebugName))
2049     {
2050         LOG((LF_ALWAYS, LL_ALWAYS, "Method table summary for '%s':\n", pszDebugName));
2051         LOG((LF_ALWAYS, LL_ALWAYS, "Number of static fields: %d\n", bmtEnumFields->dwNumStaticFields));
2052         LOG((LF_ALWAYS, LL_ALWAYS, "Number of instance fields: %d\n", bmtEnumFields->dwNumInstanceFields));
2053         LOG((LF_ALWAYS, LL_ALWAYS, "Number of static obj ref fields: %d\n", bmtEnumFields->dwNumStaticObjRefFields));
2054         LOG((LF_ALWAYS, LL_ALWAYS, "Number of static boxed fields: %d\n", bmtEnumFields->dwNumStaticBoxedFields));
2055         LOG((LF_ALWAYS, LL_ALWAYS, "Number of declared fields: %d\n", NumDeclaredFields()));
2056         LOG((LF_ALWAYS, LL_ALWAYS, "Number of declared methods: %d\n", NumDeclaredMethods()));
2057         LOG((LF_ALWAYS, LL_ALWAYS, "Number of declared non-abstract methods: %d\n", bmtMethod->dwNumDeclaredNonAbstractMethods));
2058
2059         BOOL debugging = IsDebuggerPresent();
2060         pMT->Debug_DumpInterfaceMap("Approximate");
2061         pMT->DebugDumpVtable(pszDebugName, debugging);
2062         pMT->DebugDumpFieldLayout(pszDebugName, debugging);
2063         pMT->DebugDumpGCDesc(pszDebugName, debugging);
2064         pMT->Debug_DumpDispatchMap();
2065     }
2066 #endif //_DEBUG
2067
2068     STRESS_LOG3(LF_CLASSLOADER,  LL_INFO1000, "MTB:BMTT finished method table for module %p token %x = %p\n",
2069         pModule,
2070         GetCl(),
2071         GetHalfBakedMethodTable());
2072
2073     return GetHalfBakedMethodTable();
2074 } // MethodTableBuilder::BuildMethodTableThrowing
2075 #ifdef _PREFAST_
2076 #pragma warning(pop)
2077 #endif
2078
2079
2080 //---------------------------------------------------------------------------------------
2081 //
2082 // Resolve unresolved interfaces, determine an upper bound on the size of the interface map.
2083 //
2084 VOID
2085 MethodTableBuilder::ResolveInterfaces(
2086     WORD                      cBuildingInterfaceList,
2087     BuildingInterfaceInfo_t * pBuildingInterfaceList)
2088 {
2089     CONTRACTL
2090     {
2091         STANDARD_VM_CHECK;
2092         PRECONDITION(CheckPointer(this));
2093         PRECONDITION(CheckPointer(bmtAllocator));
2094         PRECONDITION(CheckPointer(bmtInterface));
2095         PRECONDITION(CheckPointer(bmtVT));
2096         PRECONDITION(CheckPointer(bmtParent));
2097     }
2098     CONTRACTL_END;
2099
2100     // resolve unresolved interfaces and determine the size of the largest interface (in # slots)
2101
2102
2103     LoadApproxInterfaceMap();
2104
2105     // Inherit parental slot counts
2106     //@TODO: This doesn't belong here.
2107     if (HasParent())
2108     {
2109         MethodTable * pParentClass = GetParentMethodTable();
2110         PREFIX_ASSUME(pParentClass != NULL);
2111
2112         bmtParent->NumParentPointerSeries  = pParentClass->ContainsPointers() ?
2113             (DWORD)CGCDesc::GetCGCDescFromMT(pParentClass)->GetNumSeries() : 0;
2114
2115         if (pParentClass->HasFieldsWhichMustBeInited())
2116         {
2117             SetHasFieldsWhichMustBeInited();
2118         }
2119 #ifdef FEATURE_READYTORUN
2120         if (!(IsValueClass() || (pParentClass == g_pObjectClass)))
2121         {
2122             CheckLayoutDependsOnOtherModules(pParentClass);
2123         }
2124 #endif
2125     }
2126     else
2127     {
2128         bmtParent->NumParentPointerSeries  = 0;
2129     }
2130 } // MethodTableBuilder::ResolveInterfaces
2131
2132 //*******************************************************************************
2133 /* static */
2134 int __cdecl MethodTableBuilder::bmtMetaDataInfo::MethodImplTokenPair::Compare(
2135         const void *elem1,
2136         const void *elem2)
2137 {
2138     STATIC_CONTRACT_LEAF;
2139     MethodImplTokenPair *e1 = (MethodImplTokenPair *)elem1;
2140     MethodImplTokenPair *e2 = (MethodImplTokenPair *)elem2;
2141     if (e1->methodBody < e2->methodBody) return -1;
2142     else if (e1->methodBody > e2->methodBody) return 1;
2143     else if (e1->methodDecl < e2->methodDecl) return -1;
2144     else if (e1->methodDecl > e2->methodDecl) return 1;
2145     else return 0;
2146 }
2147
2148 //*******************************************************************************
2149 /* static */
2150 BOOL MethodTableBuilder::bmtMetaDataInfo::MethodImplTokenPair::Equal(
2151         const MethodImplTokenPair *elem1,
2152         const MethodImplTokenPair *elem2)
2153 {
2154     STATIC_CONTRACT_LEAF;
2155     return ((elem1->methodBody == elem2->methodBody) &&
2156             (elem1->methodDecl == elem2->methodDecl));
2157 }
2158
2159 //*******************************************************************************
2160 BOOL MethodTableBuilder::IsEligibleForCovariantReturns(mdToken methodDeclToken)
2161 {
2162     STANDARD_VM_CONTRACT;
2163
2164     //
2165     // Note on covariant return types: right now we only support covariant returns for MethodImpls on
2166     // classes, where the MethodDecl is also on a class. Interface methods are not supported.
2167     // We will also allow covariant return types if both the MethodImpl and MethodDecl are not on the same type.
2168     //
2169
2170     HRESULT hr = S_OK;
2171     IMDInternalImport* pMDInternalImport = GetMDImport();
2172
2173     // First, check if the type with the MethodImpl is a class.
2174     if (IsValueClass() || IsInterface())
2175         return FALSE;
2176
2177     mdToken tkParent;
2178     hr = pMDInternalImport->GetParentToken(methodDeclToken, &tkParent);
2179     if (FAILED(hr))
2180         BuildMethodTableThrowException(hr, *bmtError);
2181
2182     // Second, check that the type with the MethodImpl is not the same as the type with the MethodDecl
2183     if (GetCl() == tkParent)
2184         return FALSE;
2185
2186     // Finally, check that the type with the MethodDecl is not an interface. To do so, we need to compute the TypeDef
2187     // token of the type with the MethodDecl, as well as its module, in order to use the metadata to check if the type
2188     // is an interface.
2189     mdToken declTypeDefToken = mdTokenNil;
2190     Module* pDeclModule = GetModule();
2191     if (TypeFromToken(tkParent) == mdtTypeRef || TypeFromToken(tkParent) == mdtTypeDef)
2192     {
2193         if (!ClassLoader::ResolveTokenToTypeDefThrowing(GetModule(), tkParent, &pDeclModule, &declTypeDefToken))
2194             return FALSE;
2195     }
2196     else if (TypeFromToken(tkParent) == mdtTypeSpec)
2197     {
2198         ULONG cbTypeSig;
2199         PCCOR_SIGNATURE pTypeSig;
2200         hr = pMDInternalImport->GetSigFromToken(tkParent, &cbTypeSig, &pTypeSig);
2201         if (FAILED(hr))
2202             BuildMethodTableThrowException(hr, *bmtError);
2203
2204         SigParser parser(pTypeSig, cbTypeSig);
2205
2206         CorElementType elementType;
2207         IfFailThrow(parser.GetElemType(&elementType));
2208
2209         if (elementType == ELEMENT_TYPE_GENERICINST)
2210         {
2211             IfFailThrow(parser.GetElemType(&elementType));
2212         }
2213
2214         if (elementType == ELEMENT_TYPE_CLASS)
2215         {
2216             mdToken declTypeDefOrRefToken;
2217             IfFailThrow(parser.GetToken(&declTypeDefOrRefToken));
2218             if (!ClassLoader::ResolveTokenToTypeDefThrowing(GetModule(), declTypeDefOrRefToken, &pDeclModule, &declTypeDefToken))
2219                 return FALSE;
2220         }
2221     }
2222
2223     if (declTypeDefToken == mdTokenNil)
2224         return FALSE;
2225
2226     // Now that we have computed the TypeDef token and the module, check its attributes to verify it is not an interface.
2227
2228     DWORD attr;
2229     hr = pDeclModule->GetMDImport()->GetTypeDefProps(declTypeDefToken, &attr, NULL);
2230     if (FAILED(hr))
2231         BuildMethodTableThrowException(hr, *bmtError);
2232
2233     return !IsTdInterface(attr);
2234 }
2235
2236 //*******************************************************************************
2237 VOID
2238 MethodTableBuilder::EnumerateMethodImpls()
2239 {
2240     STANDARD_VM_CONTRACT;
2241
2242     HRESULT hr = S_OK;
2243     IMDInternalImport * pMDInternalImport = GetMDImport();
2244     DWORD rid, maxRidMD, maxRidMR;
2245     HENUMInternalMethodImplHolder hEnumMethodImpl(pMDInternalImport);
2246     hr = hEnumMethodImpl.EnumMethodImplInitNoThrow(GetCl());
2247
2248     if (FAILED(hr))
2249     {
2250         BuildMethodTableThrowException(hr, *bmtError);
2251     }
2252
2253     // This gets the count out of the metadata interface.
2254     bmtMethod->dwNumberMethodImpls = hEnumMethodImpl.EnumMethodImplGetCount();
2255     bmtMethod->dwNumberInexactMethodImplCandidates = 0;
2256
2257     // This is the first pass. In this we will simply enumerate the token pairs and fill in
2258     // the data structures. In addition, we'll sort the list and eliminate duplicates.
2259     if (bmtMethod->dwNumberMethodImpls > 0)
2260     {
2261         //
2262         // Allocate the structures to keep track of the token pairs
2263         //
2264         bmtMetaData->rgMethodImplTokens = new (GetStackingAllocator())
2265             bmtMetaDataInfo::MethodImplTokenPair[bmtMethod->dwNumberMethodImpls];
2266
2267         // Iterate through each MethodImpl declared on this class
2268         for (DWORD i = 0; i < bmtMethod->dwNumberMethodImpls; i++)
2269         {
2270             hr = hEnumMethodImpl.EnumMethodImplNext(
2271                 &bmtMetaData->rgMethodImplTokens[i].methodBody,
2272                 &bmtMetaData->rgMethodImplTokens[i].methodDecl);
2273             bmtMetaData->rgMethodImplTokens[i].fConsiderDuringInexactMethodImplProcessing = false;
2274             bmtMetaData->rgMethodImplTokens[i].fThrowIfUnmatchedDuringInexactMethodImplProcessing = false;
2275             bmtMetaData->rgMethodImplTokens[i].interfaceEquivalenceSet = 0;
2276             bmtMetaData->rgMethodImplTokens[i].fRequiresCovariantReturnTypeChecking = false;
2277
2278             if (FAILED(hr))
2279             {
2280                 BuildMethodTableThrowException(hr, *bmtError);
2281             }
2282             // Grab the next set of body/decl tokens
2283             if (hr == S_FALSE)
2284             {
2285                 // In the odd case that the enumerator fails before we've reached the total reported
2286                 // entries, let's reset the count and just break out. (Should we throw?)
2287                 bmtMethod->dwNumberMethodImpls = i;
2288                 break;
2289             }
2290         }
2291
2292         // No need to do any sorting or duplicate elimination if there's not two or more methodImpls
2293         if (bmtMethod->dwNumberMethodImpls > 1)
2294         {
2295             // Now sort
2296             qsort(bmtMetaData->rgMethodImplTokens,
2297                   bmtMethod->dwNumberMethodImpls,
2298                   sizeof(bmtMetaDataInfo::MethodImplTokenPair),
2299                   &bmtMetaDataInfo::MethodImplTokenPair::Compare);
2300
2301             // Now eliminate duplicates
2302             for (DWORD i = 0; i < bmtMethod->dwNumberMethodImpls - 1; i++)
2303             {
2304                 CONSISTENCY_CHECK((i + 1) < bmtMethod->dwNumberMethodImpls);
2305
2306                 bmtMetaDataInfo::MethodImplTokenPair *e1 = &bmtMetaData->rgMethodImplTokens[i];
2307                 bmtMetaDataInfo::MethodImplTokenPair *e2 = &bmtMetaData->rgMethodImplTokens[i + 1];
2308
2309                 // If the pair are equal, eliminate the first one, and reduce the total count by one.
2310                 if (bmtMetaDataInfo::MethodImplTokenPair::Equal(e1, e2))
2311                 {
2312                     DWORD dwCopyNum = bmtMethod->dwNumberMethodImpls - (i + 1);
2313                     memcpy(e1, e2, dwCopyNum * sizeof(bmtMetaDataInfo::MethodImplTokenPair));
2314                     bmtMethod->dwNumberMethodImpls--;
2315                     CONSISTENCY_CHECK(bmtMethod->dwNumberMethodImpls > 0);
2316                 }
2317             }
2318         }
2319     }
2320
2321     if (bmtMethod->dwNumberMethodImpls != 0)
2322     {
2323         //
2324         // Allocate the structures to keep track of the impl matches
2325         //
2326         bmtMetaData->pMethodDeclSubsts = new (GetStackingAllocator())
2327             Substitution[bmtMethod->dwNumberMethodImpls];
2328
2329         // These are used for verification
2330         maxRidMD = pMDInternalImport->GetCountWithTokenKind(mdtMethodDef);
2331         maxRidMR = pMDInternalImport->GetCountWithTokenKind(mdtMemberRef);
2332
2333         // Iterate through each MethodImpl declared on this class
2334         for (DWORD i = 0; i < bmtMethod->dwNumberMethodImpls; i++)
2335         {
2336             PCCOR_SIGNATURE pSigDecl = NULL;
2337             PCCOR_SIGNATURE pSigBody = NULL;
2338             ULONG           cbSigDecl;
2339             ULONG           cbSigBody;
2340             mdToken tkParent;
2341
2342             mdToken theBody, theDecl;
2343             Substitution theDeclSubst(GetModule(), SigPointer(), NULL); // this can get updated later below.
2344
2345             theBody = bmtMetaData->rgMethodImplTokens[i].methodBody;
2346             theDecl = bmtMetaData->rgMethodImplTokens[i].methodDecl;
2347
2348             // IMPLEMENTATION LIMITATION: currently, we require that the body of a methodImpl
2349             // belong to the current type. This is because we need to allocate a different
2350             // type of MethodDesc for bodies that are part of methodImpls.
2351             if (TypeFromToken(theBody) != mdtMethodDef)
2352             {
2353                 hr = FindMethodDeclarationForMethodImpl(
2354                     theBody,
2355                     &theBody,
2356                     TRUE);
2357                 if (FAILED(hr))
2358                 {
2359                     BuildMethodTableThrowException(hr, IDS_CLASSLOAD_MI_ILLEGAL_BODY, mdMethodDefNil);
2360                 }
2361
2362                 // Make sure to update the stored token with the resolved token.
2363                 bmtMetaData->rgMethodImplTokens[i].methodBody = theBody;
2364             }
2365
2366             if (TypeFromToken(theBody) != mdtMethodDef)
2367             {
2368                 BuildMethodTableThrowException(BFA_METHODDECL_NOT_A_METHODDEF);
2369             }
2370             CONSISTENCY_CHECK(theBody == bmtMetaData->rgMethodImplTokens[i].methodBody);
2371
2372             //
2373             // Now that the tokens of Decl and Body are obtained, do the MD validation
2374             //
2375
2376             rid = RidFromToken(theDecl);
2377
2378             // Perform initial rudimentary validation of the token. Full token verification
2379             // will be done in TestMethodImpl when placing the methodImpls.
2380             if (TypeFromToken(theDecl) == mdtMethodDef)
2381             {
2382                 // Decl must be valid token
2383                 if ((rid == 0) || (rid > maxRidMD))
2384                 {
2385                     BuildMethodTableThrowException(IDS_CLASSLOAD_MI_ILLEGAL_TOKEN_DECL);
2386                 }
2387                 // Get signature and length
2388                 if (FAILED(pMDInternalImport->GetSigOfMethodDef(theDecl, &cbSigDecl, &pSigDecl)))
2389                 {
2390                     BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
2391                 }
2392             }
2393
2394             // The token is not a MethodDef (likely a MemberRef)
2395             else
2396             {
2397                 // Decl must be valid token
2398                 if ((TypeFromToken(theDecl) != mdtMemberRef) || (rid == 0) || (rid > maxRidMR))
2399                 {
2400                     bmtError->resIDWhy = IDS_CLASSLOAD_MI_ILLEGAL_TOKEN_DECL;
2401                     BuildMethodTableThrowException(IDS_CLASSLOAD_MI_ILLEGAL_TOKEN_DECL);
2402                 }
2403
2404                 // Get signature and length
2405                 LPCSTR szDeclName;
2406                 if (FAILED(pMDInternalImport->GetNameAndSigOfMemberRef(theDecl, &pSigDecl, &cbSigDecl, &szDeclName)))
2407                 {
2408                     BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
2409                 }
2410
2411                 // Get parent
2412                 hr = pMDInternalImport->GetParentToken(theDecl,&tkParent);
2413                 if (FAILED(hr))
2414                     BuildMethodTableThrowException(hr, *bmtError);
2415
2416                 theDeclSubst = Substitution(tkParent, GetModule(), NULL);
2417             }
2418
2419             // Perform initial rudimentary validation of the token. Full token verification
2420             // will be done in TestMethodImpl when placing the methodImpls.
2421             {
2422                 // Body must be valid token
2423                 rid = RidFromToken(theBody);
2424                 if ((rid == 0)||(rid > maxRidMD))
2425                 {
2426                     BuildMethodTableThrowException(IDS_CLASSLOAD_MI_ILLEGAL_TOKEN_BODY);
2427                 }
2428                 // Body's parent must be this class
2429                 hr = pMDInternalImport->GetParentToken(theBody,&tkParent);
2430                 if (FAILED(hr))
2431                     BuildMethodTableThrowException(hr, *bmtError);
2432                 if(tkParent != GetCl())
2433                 {
2434                     BuildMethodTableThrowException(IDS_CLASSLOAD_MI_ILLEGAL_BODY);
2435                 }
2436             }
2437             // Decl's and Body's signatures must match
2438             if(pSigDecl && cbSigDecl)
2439             {
2440                 if (FAILED(pMDInternalImport->GetSigOfMethodDef(theBody, &cbSigBody, &pSigBody)) ||
2441                     (pSigBody == NULL) ||
2442                     (cbSigBody == 0))
2443                 {
2444                     BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MISSING_SIG_BODY);
2445                 }
2446
2447                 // Can't use memcmp because there may be two AssemblyRefs
2448                 // in this scope, pointing to the same assembly, etc.).
2449                 BOOL compatibleSignatures = MetaSig::CompareMethodSigs(pSigDecl, cbSigDecl, GetModule(), &theDeclSubst, pSigBody, cbSigBody, GetModule(), NULL, FALSE);
2450
2451                 if (!compatibleSignatures && IsEligibleForCovariantReturns(theDecl))
2452                 {
2453                     if (MetaSig::CompareMethodSigs(pSigDecl, cbSigDecl, GetModule(), &theDeclSubst, pSigBody, cbSigBody, GetModule(), NULL, TRUE))
2454                     {
2455                         // Signatures matched, except for the return type. Flag that MethodImpl to check the return type at a later
2456                         // stage for compatibility, and treat it as compatible for now.
2457                         // For compatibility rules, see ECMA I.8.7.1. We will use the MethodTable::CanCastTo() at a later stage to validate
2458                         // compatibilities of the return types according to these rules.
2459
2460                         compatibleSignatures = TRUE;
2461                         bmtMetaData->rgMethodImplTokens[i].fRequiresCovariantReturnTypeChecking = true;
2462                         bmtMetaData->fHasCovariantOverride = true;
2463                     }
2464                 }
2465
2466                 if (!compatibleSignatures)
2467                 {
2468                     BuildMethodTableThrowException(IDS_CLASSLOAD_MI_BODY_DECL_MISMATCH);
2469                 }
2470             }
2471             else
2472             {
2473                 BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MISSING_SIG_DECL);
2474             }
2475
2476             bmtMetaData->pMethodDeclSubsts[i] = theDeclSubst;
2477         }
2478     }
2479 } // MethodTableBuilder::EnumerateMethodImpls
2480
2481 //*******************************************************************************
2482 //
2483 // Find a method declaration that must reside in the scope passed in. This method cannot be called if
2484 // the reference travels to another scope.
2485 //
2486 // Protect against finding a declaration that lives within
2487 // us (the type being created)
2488 //
2489 HRESULT MethodTableBuilder::FindMethodDeclarationForMethodImpl(
2490             mdToken  pToken,       // Token that is being located (MemberRef or MemberDef)
2491             mdToken* pDeclaration, // [OUT] Method definition for Member
2492             BOOL fSameClass)       // Does the declaration need to be in this class
2493 {
2494     STANDARD_VM_CONTRACT;
2495
2496     HRESULT hr = S_OK;
2497
2498     IMDInternalImport *pMDInternalImport = GetMDImport();
2499
2500     PCCOR_SIGNATURE pSig;  // Signature of Member
2501     DWORD           cSig;
2502     LPCUTF8         szMember = NULL;
2503
2504     // The token should be a member ref or def. If it is a ref then we need to travel
2505     // back to us hopefully.
2506     if(TypeFromToken(pToken) == mdtMemberRef)
2507     {
2508         // Get the parent
2509         mdToken typeref;
2510         if (FAILED(pMDInternalImport->GetParentOfMemberRef(pToken, &typeref)))
2511         {
2512             BAD_FORMAT_NOTHROW_ASSERT(!"Invalid MemberRef record");
2513             IfFailRet(COR_E_TYPELOAD);
2514         }
2515         GOTPARENT:
2516         if (TypeFromToken(typeref) == mdtMethodDef)
2517         {   // If parent is a method def then this is a varags method
2518             mdTypeDef typeDef;
2519             IfFailRet(pMDInternalImport->GetParentToken(typeref, &typeDef));
2520
2521             if (TypeFromToken(typeDef) != mdtTypeDef)
2522             {   // A mdtMethodDef must be parented by a mdtTypeDef
2523                 BAD_FORMAT_NOTHROW_ASSERT(!"MethodDef without TypeDef as Parent");
2524                 IfFailRet(COR_E_TYPELOAD);
2525             }
2526
2527             BAD_FORMAT_NOTHROW_ASSERT(typeDef == GetCl());
2528
2529             // This is the real method we are overriding
2530             *pDeclaration = typeref;
2531         }
2532         else if (TypeFromToken(typeref) == mdtTypeSpec)
2533         {   // Added so that method impls can refer to instantiated interfaces or classes
2534             if (FAILED(pMDInternalImport->GetSigFromToken(typeref, &cSig, &pSig)))
2535             {
2536                 BAD_FORMAT_NOTHROW_ASSERT(!"Invalid TypeSpec record");
2537                 IfFailRet(COR_E_TYPELOAD);
2538             }
2539             CorElementType elemType = (CorElementType) *pSig++;
2540
2541             if (elemType == ELEMENT_TYPE_GENERICINST)
2542             {   // If this is a generic inst, we expect that the next elem is ELEMENT_TYPE_CLASS,
2543                 // which is handled in the case below.
2544                 elemType = (CorElementType) *pSig++;
2545                 BAD_FORMAT_NOTHROW_ASSERT(elemType == ELEMENT_TYPE_CLASS);
2546             }
2547
2548             if (elemType == ELEMENT_TYPE_CLASS)
2549             {   // This covers E_T_GENERICINST and E_T_CLASS typespec formats. We don't expect
2550                 // any other kinds to come through here.
2551                 CorSigUncompressToken(pSig, &typeref);
2552             }
2553             else
2554             {   // This is an unrecognized signature format.
2555                 BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT,
2556                                                IDS_CLASSLOAD_MI_BAD_SIG,
2557                                                mdMethodDefNil);
2558             }
2559             goto GOTPARENT;
2560         }
2561         else
2562         {   // Verify that the ref points back to us
2563             mdToken tkDef = mdTokenNil;
2564
2565             if (TypeFromToken(typeref) == mdtTypeRef)
2566             {   // We only get here when we know the token does not reference a type in a different scope.
2567                 LPCUTF8 pszNameSpace;
2568                 LPCUTF8 pszClassName;
2569
2570                 if (FAILED(pMDInternalImport->GetNameOfTypeRef(typeref, &pszNameSpace, &pszClassName)))
2571                 {
2572                     IfFailRet(COR_E_TYPELOAD);
2573                 }
2574                 mdToken tkRes;
2575                 if (FAILED(pMDInternalImport->GetResolutionScopeOfTypeRef(typeref, &tkRes)))
2576                 {
2577                     IfFailRet(COR_E_TYPELOAD);
2578                 }
2579                 hr = pMDInternalImport->FindTypeDef(pszNameSpace,
2580                                                     pszClassName,
2581                                                     (TypeFromToken(tkRes) == mdtTypeRef) ? tkRes : mdTokenNil,
2582                                                     &tkDef);
2583                 if (FAILED(hr))
2584                 {
2585                     IfFailRet(COR_E_TYPELOAD);
2586                 }
2587             }
2588             else if (TypeFromToken(typeref) == mdtTypeDef)
2589             {   // We get a typedef when the parent of the token is a typespec to the type.
2590                 tkDef = typeref;
2591             }
2592             else
2593             {
2594                 CONSISTENCY_CHECK_MSGF(FALSE, ("Invalid methodimpl signature in class %s.", GetDebugClassName()));
2595                 BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT,
2596                                                IDS_CLASSLOAD_MI_BAD_SIG,
2597                                                mdMethodDefNil);
2598             }
2599
2600             if (fSameClass && tkDef != GetCl())
2601             {   // If we required that the typedef be the same type as the current class,
2602                 // and it doesn't match, we need to return a failure result.
2603                 IfFailRet(COR_E_TYPELOAD);
2604             }
2605
2606             IfFailRet(pMDInternalImport->GetNameAndSigOfMemberRef(pToken, &pSig, &cSig, &szMember));
2607
2608             if (isCallConv(
2609                 MetaSig::GetCallingConvention(Signature(pSig, cSig)),
2610                 IMAGE_CEE_CS_CALLCONV_FIELD))
2611             {
2612                 return VLDTR_E_MR_BADCALLINGCONV;
2613             }
2614
2615             hr = pMDInternalImport->FindMethodDef(
2616                 tkDef, szMember, pSig, cSig, pDeclaration);
2617
2618             IfFailRet(hr);
2619         }
2620     }
2621     else if (TypeFromToken(pToken) == mdtMethodDef)
2622     {
2623         mdTypeDef typeDef;
2624
2625         // Verify that we are the parent
2626         hr = pMDInternalImport->GetParentToken(pToken, &typeDef);
2627         IfFailRet(hr);
2628
2629         if(typeDef != GetCl())
2630         {
2631             IfFailRet(COR_E_TYPELOAD);
2632         }
2633
2634         *pDeclaration = pToken;
2635     }
2636     else
2637     {
2638         IfFailRet(COR_E_TYPELOAD);
2639     }
2640     return hr;
2641 }
2642
2643 #ifdef _PREFAST_
2644 #pragma warning(push)
2645 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
2646 #endif // _PREFAST_
2647 //---------------------------------------------------------------------------------------
2648 //
2649 // Used by BuildMethodTable
2650 //
2651 // Enumerate this class's members
2652 //
2653 VOID
2654 MethodTableBuilder::EnumerateClassMethods()
2655 {
2656     CONTRACTL
2657     {
2658         STANDARD_VM_CHECK;
2659         PRECONDITION(CheckPointer(bmtInternal));
2660         PRECONDITION(CheckPointer(bmtEnumFields));
2661         PRECONDITION(CheckPointer(bmtMFDescs));
2662         PRECONDITION(CheckPointer(bmtProp));
2663         PRECONDITION(CheckPointer(bmtMetaData));
2664         PRECONDITION(CheckPointer(bmtVT));
2665         PRECONDITION(CheckPointer(bmtError));
2666     }
2667     CONTRACTL_END;
2668
2669     HRESULT hr = S_OK;
2670     DWORD i;
2671     IMDInternalImport *pMDInternalImport = GetMDImport();
2672     mdToken tok;
2673     DWORD dwMemberAttrs;
2674     BOOL fIsClassEnum = IsEnum();
2675     BOOL fIsClassInterface = IsInterface();
2676     BOOL fIsClassValueType = IsValueClass();
2677     BOOL fIsClassComImport = IsComImport();
2678     BOOL fIsClassNotAbstract = (IsTdAbstract(GetAttrClass()) == 0);
2679     PCCOR_SIGNATURE pMemberSignature = NULL;
2680     ULONG           cMemberSignature = 0;
2681
2682     //
2683     // Run through the method list and calculate the following:
2684     // # methods.
2685     // # "other" methods (i.e. static or private)
2686     // # non-other methods
2687     //
2688
2689     HENUMInternalHolder hEnumMethod(pMDInternalImport);
2690     hr = hEnumMethod.EnumInitNoThrow(mdtMethodDef, GetCl());
2691     if (FAILED(hr))
2692     {
2693         BuildMethodTableThrowException(hr, *bmtError);
2694     }
2695
2696     // Allocate an array to contain the method tokens as well as information about the methods.
2697     DWORD cMethAndGaps = hEnumMethod.EnumGetCount();
2698
2699     if ((DWORD)MAX_SLOT_INDEX <= cMethAndGaps)
2700         BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
2701
2702     bmtMethod->m_cMaxDeclaredMethods = (SLOT_INDEX)cMethAndGaps;
2703     bmtMethod->m_cDeclaredMethods = 0;
2704     bmtMethod->m_rgDeclaredMethods = new (GetStackingAllocator())
2705         bmtMDMethod *[bmtMethod->m_cMaxDeclaredMethods];
2706
2707     enum { SeenCtor = 1, SeenInvoke = 2, SeenBeginInvoke = 4, SeenEndInvoke = 8};
2708     unsigned delegateMethodsSeen = 0;
2709
2710     for (i = 0; i < cMethAndGaps; i++)
2711     {
2712         ULONG dwMethodRVA;
2713         DWORD dwImplFlags;
2714         MethodClassification type;
2715         METHOD_IMPL_TYPE implType;
2716         LPSTR strMethodName;
2717
2718         pMemberSignature = NULL;
2719         cMemberSignature = 0;
2720
2721         //
2722         // Go to the next method and retrieve its attributes.
2723         //
2724
2725         hEnumMethod.EnumNext(&tok);
2726         DWORD   rid = RidFromToken(tok);
2727         if ((rid == 0)||(rid > pMDInternalImport->GetCountWithTokenKind(mdtMethodDef)))
2728         {
2729             BuildMethodTableThrowException(BFA_METHOD_TOKEN_OUT_OF_RANGE);
2730         }
2731         if (!bmtProp->fNoSanityChecks && FAILED(pMDInternalImport->GetSigOfMethodDef(tok, &cMemberSignature, &pMemberSignature)))
2732         {
2733             BuildMethodTableThrowException(hr, BFA_BAD_SIGNATURE, mdMethodDefNil);
2734         }
2735         if (FAILED(pMDInternalImport->GetMethodDefProps(tok, &dwMemberAttrs)))
2736         {
2737             BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
2738         }
2739
2740 #ifdef FEATURE_TYPEEQUIVALENCE
2741         // TypeEquivalent structs must not have non-static methods
2742         if (!IsMdStatic(dwMemberAttrs) && bmtProp->fIsTypeEquivalent && fIsClassValueType)
2743         {
2744             BuildMethodTableThrowException(IDS_CLASSLOAD_EQUIVALENTSTRUCTMETHODS);
2745         }
2746 #endif
2747
2748         bool isVtblGap = false;
2749         if (IsMdRTSpecialName(dwMemberAttrs) || IsMdVirtual(dwMemberAttrs) || IsDelegate())
2750         {
2751             if (FAILED(pMDInternalImport->GetNameOfMethodDef(tok, (LPCSTR *)&strMethodName)))
2752             {
2753                 BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
2754             }
2755             if(IsStrLongerThan(strMethodName,MAX_CLASS_NAME))
2756             {
2757                 BuildMethodTableThrowException(BFA_METHOD_NAME_TOO_LONG);
2758             }
2759
2760             isVtblGap = IsMdRTSpecialName(dwMemberAttrs) && IsVtblGapName(strMethodName);
2761         }
2762         else
2763         {
2764             strMethodName = NULL;
2765         }
2766
2767         // Signature validation
2768         if (!bmtProp->fNoSanityChecks && !isVtblGap)
2769         {
2770             hr = validateTokenSig(tok,pMemberSignature,cMemberSignature,dwMemberAttrs,pMDInternalImport);
2771             if (FAILED(hr))
2772             {
2773                 BuildMethodTableThrowException(hr, BFA_BAD_SIGNATURE, mdMethodDefNil);
2774             }
2775         }
2776
2777         bool hasGenericMethodArgsComputed;
2778         bool hasGenericMethodArgs = this->GetModule()->m_pMethodIsGenericMap->IsGeneric(tok, &hasGenericMethodArgsComputed);
2779         if (!hasGenericMethodArgsComputed)
2780         {
2781             if (pMemberSignature == NULL)
2782             {
2783                 if (FAILED(pMDInternalImport->GetSigOfMethodDef(tok, &cMemberSignature, &pMemberSignature)))
2784                 {
2785                     BuildMethodTableThrowException(hr, BFA_BAD_SIGNATURE, mdMethodDefNil);
2786                 }
2787             }
2788             SigParser genericArgParser(pMemberSignature, cMemberSignature);
2789             uint32_t ulCallConv;
2790             hr = genericArgParser.GetCallingConvInfo(&ulCallConv);
2791             if (FAILED(hr))
2792             {
2793                 BuildMethodTableThrowException(hr, *bmtError);
2794             }
2795
2796             // Only read the generic parameter table if the method signature is generic
2797             hasGenericMethodArgs = !!(ulCallConv & IMAGE_CEE_CS_CALLCONV_GENERIC);
2798             hasGenericMethodArgsComputed = true;
2799         }
2800
2801         if (hasGenericMethodArgs && !bmtProp->fNoSanityChecks)
2802         {
2803             HENUMInternalHolder hEnumTyPars(pMDInternalImport);
2804             hr = hEnumTyPars.EnumInitNoThrow(mdtGenericParam, tok);
2805             if (FAILED(hr))
2806             {
2807                 BuildMethodTableThrowException(hr, *bmtError);
2808             }
2809
2810             uint32_t numGenericMethodArgs = hEnumTyPars.EnumGetCount();
2811             if (numGenericMethodArgs != 0)
2812             {
2813                 HENUMInternalHolder hEnumGenericPars(pMDInternalImport);
2814
2815                 hEnumGenericPars.EnumInit(mdtGenericParam, tok);
2816
2817                 for (unsigned methIdx = 0; methIdx < numGenericMethodArgs; methIdx++)
2818                 {
2819                     mdGenericParam tkTyPar;
2820                     pMDInternalImport->EnumNext(&hEnumGenericPars, &tkTyPar);
2821                     DWORD flags;
2822                     if (FAILED(pMDInternalImport->GetGenericParamProps(tkTyPar, NULL, &flags, NULL, NULL, NULL)))
2823                     {
2824                         BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
2825                     }
2826
2827                     if (0 != (flags & ~(gpVarianceMask | gpSpecialConstraintMask)))
2828                     {
2829                         BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
2830                     }
2831                     switch (flags & gpVarianceMask)
2832                     {
2833                         case gpNonVariant:
2834                             break;
2835
2836                         case gpCovariant: // intentional fallthru
2837                         case gpContravariant:
2838                             BuildMethodTableThrowException(VLDTR_E_GP_ILLEGAL_VARIANT_MVAR);
2839                             break;
2840
2841                         default:
2842                             BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
2843                     }
2844                 }
2845             }
2846         }
2847
2848         //
2849         // We need to check if there are any gaps in the vtable. These are
2850         // represented by methods with the mdSpecial flag and a name of the form
2851         // _VTblGap_nnn (to represent nnn empty slots) or _VTblGap (to represent a
2852         // single empty slot).
2853         //
2854
2855         if (isVtblGap)
2856         {
2857             //
2858             // This slot doesn't really exist, don't add it to the method
2859             // table. Instead it represents one or more empty slots, encoded
2860             // in the method name. Locate the beginning of the count in the
2861             // name. There are these points to consider:
2862             //   There may be no count present at all (in which case the
2863             //   count is taken as one).
2864             //   There may be an additional count just after Gap but before
2865             //   the '_'. We ignore this.
2866             //
2867
2868             LPCSTR pos = strMethodName + COR_VTABLEGAP_NAME_LENGTH;
2869
2870             // Skip optional number.
2871             while (IS_DIGIT(*pos))
2872                 pos++;
2873
2874             WORD n = 0;
2875
2876             // Check for presence of count.
2877             if (*pos == '\0')
2878             {
2879                 n = 1;
2880             }
2881             else
2882             {
2883                 if (*pos != '_')
2884                 {
2885                     BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT,
2886                                                     IDS_CLASSLOAD_BADSPECIALMETHOD,
2887                                                     tok);
2888                 }
2889
2890                 // Skip '_'.
2891                 pos++;
2892
2893                 // Read count.
2894                 bool fReadAtLeastOneDigit = false;
2895                 while (IS_DIGIT(*pos))
2896                 {
2897                     _ASSERTE(n < 6552);
2898                     n *= 10;
2899                     n += DIGIT_TO_INT(*pos);
2900                     pos++;
2901                     fReadAtLeastOneDigit = true;
2902                 }
2903
2904                 // Check for end of name.
2905                 if (*pos != '\0' || !fReadAtLeastOneDigit)
2906                 {
2907                     BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT,
2908                                                     IDS_CLASSLOAD_BADSPECIALMETHOD,
2909                                                     tok);
2910                 }
2911             }
2912
2913 #ifdef FEATURE_COMINTEROP
2914             // Record vtable gap in mapping list. The map is an optional field, so ensure we've allocated
2915             // these fields first.
2916             EnsureOptionalFieldsAreAllocated(GetHalfBakedClass(), m_pAllocMemTracker, GetLoaderAllocator()->GetLowFrequencyHeap());
2917             if (GetHalfBakedClass()->GetSparseCOMInteropVTableMap() == NULL)
2918                 GetHalfBakedClass()->SetSparseCOMInteropVTableMap(new SparseVTableMap());
2919
2920             GetHalfBakedClass()->GetSparseCOMInteropVTableMap()->RecordGap((WORD)NumDeclaredMethods(), n);
2921
2922             bmtProp->fSparse = true;
2923 #endif // FEATURE_COMINTEROP
2924             continue;
2925         }
2926
2927         //
2928         // This is a real method so add it to the enumeration of methods. We now need to retrieve
2929         // information on the method and store it for later use.
2930         //
2931         if (FAILED(pMDInternalImport->GetMethodImplProps(tok, &dwMethodRVA, &dwImplFlags)))
2932         {
2933             BuildMethodTableThrowException(
2934                 COR_E_BADIMAGEFORMAT,
2935                 IDS_CLASSLOAD_BADSPECIALMETHOD,
2936                 tok);
2937         }
2938
2939         // Check for the presence of virtual static methods
2940         bool isStaticVirtual = (IsMdVirtual(dwMemberAttrs) && IsMdStatic(dwMemberAttrs));
2941         if (isStaticVirtual)
2942         {
2943             bmtProp->fHasVirtualStaticMethods = TRUE;
2944         }
2945
2946         //
2947         // But first - minimal flags validity checks
2948         //
2949         // No methods in Enums!
2950 #ifndef _DEBUG // Don't run the minimal validity checks for the system dll/r2r dlls (except in debug builds so we don't build a bad system dll)
2951         if (!bmtProp->fNoSanityChecks)
2952 #endif
2953         {
2954             if (fIsClassEnum)
2955             {
2956                 BuildMethodTableThrowException(BFA_METHOD_IN_A_ENUM);
2957             }
2958             // RVA : 0
2959             if (dwMethodRVA != 0)
2960             {
2961                 if(fIsClassComImport)
2962                 {
2963                     BuildMethodTableThrowException(BFA_METHOD_WITH_NONZERO_RVA);
2964                 }
2965                 if(IsMdAbstract(dwMemberAttrs))
2966                 {
2967                     BuildMethodTableThrowException(BFA_ABSTRACT_METHOD_WITH_RVA);
2968                 }
2969                 if(IsMiRuntime(dwImplFlags))
2970                 {
2971                     BuildMethodTableThrowException(BFA_RUNTIME_METHOD_WITH_RVA);
2972                 }
2973                 if(IsMiInternalCall(dwImplFlags))
2974                 {
2975                     BuildMethodTableThrowException(BFA_INTERNAL_METHOD_WITH_RVA);
2976                 }
2977             }
2978
2979             // Abstract / not abstract
2980             if(IsMdAbstract(dwMemberAttrs))
2981             {
2982                 if(fIsClassNotAbstract)
2983                 {
2984                     BuildMethodTableThrowException(BFA_AB_METHOD_IN_AB_CLASS);
2985                 }
2986                 if(!IsMdVirtual(dwMemberAttrs) && !IsMdStatic(dwMemberAttrs))
2987                 {
2988                     BuildMethodTableThrowException(BFA_NONVIRT_AB_METHOD);
2989                 }
2990             }
2991             else if(fIsClassInterface)
2992             {
2993                 if (IsMdRTSpecialName(dwMemberAttrs))
2994                 {
2995                     CONSISTENCY_CHECK(CheckPointer(strMethodName));
2996                     if (strcmp(strMethodName, COR_CCTOR_METHOD_NAME))
2997                     {
2998                         BuildMethodTableThrowException(BFA_NONAB_NONCCTOR_METHOD_ON_INT);
2999                     }
3000                 }
3001             }
3002
3003             // Virtual / not virtual
3004             if(IsMdVirtual(dwMemberAttrs))
3005             {
3006                 if(IsMdPinvokeImpl(dwMemberAttrs))
3007                 {
3008                     BuildMethodTableThrowException(BFA_VIRTUAL_PINVOKE_METHOD);
3009                 }
3010                 if(IsMdStatic(dwMemberAttrs))
3011                 {
3012                     if (!fIsClassInterface)
3013                     {
3014                         // Static virtual methods are only allowed to exist in interfaces
3015                         BuildMethodTableThrowException(BFA_VIRTUAL_STATIC_METHOD);
3016                     }
3017                 }
3018                 if(strMethodName && (0==strcmp(strMethodName, COR_CTOR_METHOD_NAME)))
3019                 {
3020                     BuildMethodTableThrowException(BFA_VIRTUAL_INSTANCE_CTOR);
3021                 }
3022             }
3023
3024             // Some interface checks.
3025             // We only need them if default interface method support is disabled or if this is fragile crossgen
3026 #if !defined(FEATURE_DEFAULT_INTERFACES)
3027             if (fIsClassInterface)
3028             {
3029                 if (IsMdVirtual(dwMemberAttrs))
3030                 {
3031                     if (!IsMdAbstract(dwMemberAttrs))
3032                     {
3033                         BuildMethodTableThrowException(BFA_VIRTUAL_NONAB_INT_METHOD);
3034                     }
3035                 }
3036                 else
3037                 {
3038                     // Instance method
3039                     if (!IsMdStatic(dwMemberAttrs))
3040                     {
3041                         BuildMethodTableThrowException(BFA_NONVIRT_INST_INT_METHOD);
3042                     }
3043                 }
3044             }
3045 #endif // !defined(FEATURE_DEFAULT_INTERFACES)
3046
3047             // No synchronized methods in ValueTypes
3048             if(fIsClassValueType && IsMiSynchronized(dwImplFlags))
3049             {
3050                 BuildMethodTableThrowException(BFA_SYNC_METHOD_IN_VT);
3051             }
3052
3053             // Global methods:
3054             if(IsGlobalClass())
3055             {
3056                 if(!IsMdStatic(dwMemberAttrs))
3057                 {
3058                     BuildMethodTableThrowException(BFA_NONSTATIC_GLOBAL_METHOD);
3059                 }
3060                 if (strMethodName)  //<TODO>@todo: investigate mc++ generating null name</TODO>
3061                 {
3062                     if(0==strcmp(strMethodName, COR_CTOR_METHOD_NAME))
3063                     {
3064                         BuildMethodTableThrowException(BFA_GLOBAL_INST_CTOR);
3065                     }
3066                 }
3067             }
3068             //@GENERICS:
3069             // Generic methods or methods in generic classes
3070             // may not be part of a COM Import class, PInvoke, internal call outside CoreLib.
3071             if ((bmtGenerics->GetNumGenericArgs() != 0 || hasGenericMethodArgs) &&
3072                 (
3073 #ifdef FEATURE_COMINTEROP
3074                 fIsClassComImport ||
3075                 bmtProp->fComEventItfType ||
3076 #endif // FEATURE_COMINTEROP
3077                 IsMdPinvokeImpl(dwMemberAttrs) ||
3078                 (IsMiInternalCall(dwImplFlags) && !GetModule()->IsSystem())))
3079             {
3080                 BuildMethodTableThrowException(BFA_BAD_PLACE_FOR_GENERIC_METHOD);
3081             }
3082
3083             // Generic methods may not be marked "runtime".  However note that
3084             // methods in generic delegate classes are, hence we don't apply this to
3085             // methods in generic classes in general.
3086             if (hasGenericMethodArgs && IsMiRuntime(dwImplFlags))
3087             {
3088                 BuildMethodTableThrowException(BFA_GENERIC_METHOD_RUNTIME_IMPL);
3089             }
3090
3091             // Check the appearance of covariant and contravariant in the method signature
3092             // Note that variance is only supported for interfaces, and these rules are not
3093             // checked for non-virtual static methods as they cannot be called variantly.
3094             if ((bmtGenerics->pVarianceInfo != NULL) && (IsMdVirtual(dwMemberAttrs) || !IsMdStatic(dwMemberAttrs)))
3095             {
3096                 if (pMemberSignature == NULL)
3097                 {
3098                     if (FAILED(pMDInternalImport->GetSigOfMethodDef(tok, &cMemberSignature, &pMemberSignature)))
3099                     {
3100                         BuildMethodTableThrowException(hr, BFA_BAD_SIGNATURE, mdMethodDefNil);
3101                     }
3102                 }
3103
3104                 SigPointer sp(pMemberSignature, cMemberSignature);
3105                 uint32_t callConv;
3106                 IfFailThrow(sp.GetCallingConvInfo(&callConv));
3107
3108                 if (callConv & IMAGE_CEE_CS_CALLCONV_GENERIC)
3109                     IfFailThrow(sp.GetData(NULL));
3110
3111                 uint32_t numArgs;
3112                 IfFailThrow(sp.GetData(&numArgs));
3113
3114                 // Return type behaves covariantly
3115                 if (!EEClass::CheckVarianceInSig(
3116                         bmtGenerics->GetNumGenericArgs(),
3117                         bmtGenerics->pVarianceInfo,
3118                         GetModule(),
3119                         sp,
3120                         gpCovariant))
3121                 {
3122                     BuildMethodTableThrowException(IDS_CLASSLOAD_VARIANCE_IN_METHOD_RESULT, tok);
3123                 }
3124                 IfFailThrow(sp.SkipExactlyOne());
3125                 for (uint32_t j = 0; j < numArgs; j++)
3126                 {
3127                     // Argument types behave contravariantly
3128                     if (!EEClass::CheckVarianceInSig(bmtGenerics->GetNumGenericArgs(),
3129                                                     bmtGenerics->pVarianceInfo,
3130                                                     GetModule(),
3131                                                     sp,
3132                                                     gpContravariant))
3133                     {
3134                         BuildMethodTableThrowException(IDS_CLASSLOAD_VARIANCE_IN_METHOD_ARG, tok);
3135                     }
3136                     IfFailThrow(sp.SkipExactlyOne());
3137                 }
3138             }
3139         }
3140
3141         //
3142         // Determine the method's type
3143         //
3144
3145         if (IsReallyMdPinvokeImpl(dwMemberAttrs) || IsMiInternalCall(dwImplFlags))
3146         {
3147             hr = NDirect::HasNAT_LAttribute(pMDInternalImport, tok, dwMemberAttrs);
3148
3149             // There was a problem querying for the attribute
3150             if (FAILED(hr))
3151             {
3152                 BuildMethodTableThrowException(hr, IDS_CLASSLOAD_BADPINVOKE, tok);
3153             }
3154
3155             // The attribute is not present
3156             if (hr == S_FALSE)
3157             {
3158 #ifdef FEATURE_COMINTEROP
3159                 if (fIsClassComImport || bmtProp->fComEventItfType)
3160                 {
3161                     // ComImport classes have methods which are just used
3162                     // for implementing all interfaces the class supports
3163                     type = mcComInterop;
3164
3165                     // constructor is special
3166                     if (IsMdRTSpecialName(dwMemberAttrs))
3167                     {
3168                         // Note: Method name (.ctor) will be checked in code:ValidateMethods
3169                         type = mcFCall;
3170                     }
3171                 }
3172                 else
3173 #endif //FEATURE_COMINTEROP
3174                 if (dwMethodRVA == 0)
3175                 {
3176                     type = mcFCall;
3177                 }
3178                 else
3179                 {
3180                     type = mcNDirect;
3181                 }
3182             }
3183             // The NAT_L attribute is present, marking this method as NDirect
3184             else
3185             {
3186                 CONSISTENCY_CHECK(hr == S_OK);
3187                 type = mcNDirect;
3188             }
3189         }
3190         else if (IsMiRuntime(dwImplFlags))
3191         {
3192                 // currently the only runtime implemented functions are delegate instance methods
3193             if (!IsDelegate() || IsMdStatic(dwMemberAttrs) || IsMdAbstract(dwMemberAttrs))
3194             {
3195                 BuildMethodTableThrowException(BFA_BAD_RUNTIME_IMPL);
3196             }
3197
3198             unsigned newDelegateMethodSeen = 0;
3199
3200             if (IsMdRTSpecialName(dwMemberAttrs))   // .ctor
3201             {
3202                 if (strcmp(strMethodName, COR_CTOR_METHOD_NAME) != 0 || IsMdVirtual(dwMemberAttrs))
3203                 {
3204                     BuildMethodTableThrowException(BFA_BAD_FLAGS_ON_DELEGATE);
3205                 }
3206                 newDelegateMethodSeen = SeenCtor;
3207                 type = mcFCall;
3208             }
3209             else
3210             {
3211                 if (strcmp(strMethodName, "Invoke") == 0)
3212                     newDelegateMethodSeen = SeenInvoke;
3213                 else if (strcmp(strMethodName, "BeginInvoke") == 0)
3214                     newDelegateMethodSeen = SeenBeginInvoke;
3215                 else if (strcmp(strMethodName, "EndInvoke") == 0)
3216                     newDelegateMethodSeen = SeenEndInvoke;
3217                 else
3218                 {
3219                     BuildMethodTableThrowException(BFA_UNKNOWN_DELEGATE_METHOD);
3220                 }
3221                 type = mcEEImpl;
3222             }
3223
3224             // If we get here we have either set newDelegateMethodSeen or we have thrown a BMT exception
3225             _ASSERTE(newDelegateMethodSeen != 0);
3226
3227             if ((delegateMethodsSeen & newDelegateMethodSeen) != 0)
3228             {
3229                 BuildMethodTableThrowException(BFA_DUPLICATE_DELEGATE_METHOD);
3230             }
3231
3232             delegateMethodsSeen |= newDelegateMethodSeen;
3233         }
3234         else if (hasGenericMethodArgs)
3235         {
3236             //We use an instantiated method desc to represent a generic method
3237             type = mcInstantiated;
3238         }
3239         else if (fIsClassInterface)
3240         {
3241 #ifdef FEATURE_COMINTEROP
3242             if (IsMdStatic(dwMemberAttrs))
3243             {
3244                 // Static methods in interfaces need nothing special.
3245                 type = mcIL;
3246             }
3247             else if (bmtGenerics->GetNumGenericArgs() != 0 &&
3248                 (bmtGenerics->fSharedByGenericInstantiations))
3249             {
3250                 // Methods in instantiated interfaces need nothing special - they are not visible from COM etc.
3251                 type = mcIL;
3252             }
3253             else if (bmtProp->fIsMngStandardItf)
3254             {
3255                 // If the interface is a standard managed interface then allocate space for an FCall method desc.
3256                 type = mcFCall;
3257             }
3258             else if (IsMdAbstract(dwMemberAttrs))
3259             {
3260                 // If COM interop is supported then all other interface MDs may be
3261                 // accessed via COM interop. mcComInterop MDs have an additional
3262                 // pointer-sized field pointing to COM interop data which are
3263                 // allocated lazily when/if the MD actually gets used for interop.
3264                 type = mcComInterop;
3265             }
3266             else
3267 #endif // !FEATURE_COMINTEROP
3268             {
3269                 type = mcIL;
3270             }
3271         }
3272         else
3273         {
3274             type = mcIL;
3275         }
3276
3277         // Generic methods should always be mcInstantiated
3278         if (hasGenericMethodArgs && (type != mcInstantiated))
3279         {
3280             BuildMethodTableThrowException(BFA_GENERIC_METHODS_INST);
3281         }
3282
3283         // Check if the method is a MethodImpl body. All method bodies are defined
3284         // on this type so we can just compare the tok with the body token found
3285         // from the overrides.
3286         implType = METHOD_IMPL_NOT;
3287         for (DWORD impls = 0; impls < bmtMethod->dwNumberMethodImpls; impls++)
3288         {
3289             if (bmtMetaData->rgMethodImplTokens[impls].methodBody == tok)
3290             {
3291                 implType = METHOD_IMPL;
3292                 break;
3293             }
3294         }
3295
3296         // For delegates we don't allow any non-runtime implemented bodies
3297         // for any of the four special methods
3298         if (IsDelegate() && !IsMiRuntime(dwImplFlags))
3299         {
3300             if ((strcmp(strMethodName, COR_CTOR_METHOD_NAME) == 0) ||
3301                 (strcmp(strMethodName, "Invoke")             == 0) ||
3302                 (strcmp(strMethodName, "BeginInvoke")        == 0) ||
3303                 (strcmp(strMethodName, "EndInvoke")          == 0)   )
3304             {
3305                 BuildMethodTableThrowException(BFA_ILLEGAL_DELEGATE_METHOD);
3306             }
3307         }
3308
3309         //
3310         // Create a new bmtMDMethod representing this method and add it to the
3311         // declared method list.
3312         //
3313
3314         bmtMDMethod * pNewMethod = new (GetStackingAllocator()) bmtMDMethod(
3315             bmtInternal->pType,
3316             tok,
3317             dwMemberAttrs,
3318             dwImplFlags,
3319             dwMethodRVA,
3320             type,
3321             implType);
3322
3323         bmtMethod->AddDeclaredMethod(pNewMethod);
3324
3325         //
3326         // Update the count of the various types of methods.
3327         //
3328
3329         bmtVT->dwMaxVtableSize++;
3330
3331         // Increment the number of non-abstract declared methods
3332         if (!IsMdAbstract(dwMemberAttrs))
3333         {
3334             bmtMethod->dwNumDeclaredNonAbstractMethods++;
3335         }
3336     }
3337
3338     if (bmtMethod->dwNumDeclaredNonAbstractMethods == 0)
3339     {
3340         GetHalfBakedClass()->SetHasOnlyAbstractMethods();
3341     }
3342
3343     // Check to see that we have all of the required delegate methods (ECMA 13.6 Delegates)
3344     if (IsDelegate())
3345     {
3346         // Do we have all four special delegate methods
3347         // or just the two special delegate methods
3348         if ((delegateMethodsSeen != (SeenCtor | SeenInvoke | SeenBeginInvoke | SeenEndInvoke)) &&
3349             (delegateMethodsSeen != (SeenCtor | SeenInvoke)) )
3350         {
3351             BuildMethodTableThrowException(BFA_MISSING_DELEGATE_METHOD);
3352         }
3353     }
3354
3355     if (i != cMethAndGaps)
3356     {
3357         BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_METHOD_COUNT, mdTokenNil);
3358     }
3359
3360 #ifdef FEATURE_COMINTEROP
3361     //
3362     // If the interface is sparse, we need to finalize the mapping list by
3363     // telling it how many real methods we found.
3364     //
3365
3366     if (bmtProp->fSparse)
3367     {
3368         GetHalfBakedClass()->GetSparseCOMInteropVTableMap()->FinalizeMapping(NumDeclaredMethods());
3369     }
3370 #endif // FEATURE_COMINTEROP
3371 } // MethodTableBuilder::EnumerateClassMethods
3372 #ifdef _PREFAST_
3373 #pragma warning(pop)
3374 #endif
3375
3376 //*******************************************************************************
3377 //
3378 // Run through the field list and calculate the following:
3379 // # static fields
3380 // # static fields that contain object refs.
3381 // # instance fields
3382 //
3383 VOID
3384 MethodTableBuilder::EnumerateClassFields()
3385 {
3386     STANDARD_VM_CONTRACT;
3387
3388     HRESULT hr = S_OK;
3389     DWORD i;
3390     IMDInternalImport *pMDInternalImport = GetMDImport();
3391     mdToken tok;
3392     DWORD dwMemberAttrs;
3393
3394     bmtEnumFields->dwNumStaticFields        = 0;
3395     bmtEnumFields->dwNumStaticObjRefFields  = 0;
3396     bmtEnumFields->dwNumStaticBoxedFields   = 0;
3397
3398     bmtEnumFields->dwNumThreadStaticFields  = 0;
3399     bmtEnumFields->dwNumThreadStaticObjRefFields  = 0;
3400     bmtEnumFields->dwNumThreadStaticBoxedFields   = 0;
3401
3402     bmtEnumFields->dwNumInstanceFields      = 0;
3403
3404     HENUMInternalHolder hEnumField(pMDInternalImport);
3405     hr = hEnumField.EnumInitNoThrow(mdtFieldDef, GetCl());
3406     if (FAILED(hr))
3407     {
3408         BuildMethodTableThrowException(hr, *bmtError);
3409     }
3410
3411     bmtMetaData->cFields = hEnumField.EnumGetCount();
3412
3413     // Retrieve the fields and store them in a temp array.
3414     bmtMetaData->pFields = new (GetStackingAllocator()) mdToken[bmtMetaData->cFields];
3415     bmtMetaData->pFieldAttrs = new (GetStackingAllocator()) DWORD[bmtMetaData->cFields];
3416
3417     DWORD   dwFieldLiteralInitOnly = fdLiteral | fdInitOnly;
3418     DWORD   dwMaxFieldDefRid = pMDInternalImport->GetCountWithTokenKind(mdtFieldDef);
3419
3420     for (i = 0; hEnumField.EnumNext(&tok); i++)
3421     {
3422         //
3423         // Retrieve the attributes of the field.
3424         //
3425         DWORD rid = RidFromToken(tok);
3426         if ((rid == 0)||(rid > dwMaxFieldDefRid))
3427         {
3428             BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, BFA_BAD_FIELD_TOKEN, mdTokenNil);
3429         }
3430
3431         if (FAILED(pMDInternalImport->GetFieldDefProps(tok, &dwMemberAttrs)))
3432         {
3433             BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, BFA_BAD_FIELD_TOKEN, tok);
3434         }
3435
3436         //
3437         // Store the field and its attributes in the bmtMetaData structure for later use.
3438         //
3439
3440         bmtMetaData->pFields[i] = tok;
3441         bmtMetaData->pFieldAttrs[i] = dwMemberAttrs;
3442
3443         if((dwMemberAttrs & fdFieldAccessMask)==fdFieldAccessMask)
3444         {
3445             BuildMethodTableThrowException(BFA_INVALID_FIELD_ACC_FLAGS);
3446         }
3447         if((dwMemberAttrs & dwFieldLiteralInitOnly)==dwFieldLiteralInitOnly)
3448         {
3449             BuildMethodTableThrowException(BFA_FIELD_LITERAL_AND_INIT);
3450         }
3451
3452         // can only have static global fields
3453         if(IsGlobalClass())
3454         {
3455             if(!IsFdStatic(dwMemberAttrs))
3456             {
3457                 BuildMethodTableThrowException(BFA_NONSTATIC_GLOBAL_FIELD);
3458             }
3459         }
3460
3461         //
3462         // Update the count of the various types of fields.
3463         //
3464
3465         if (IsFdStatic(dwMemberAttrs))
3466         {
3467             if (!IsFdLiteral(dwMemberAttrs))
3468             {
3469 #ifdef FEATURE_TYPEEQUIVALENCE
3470                 if (bmtProp->fIsTypeEquivalent)
3471                 {
3472                     BuildMethodTableThrowException(IDS_CLASSLOAD_EQUIVALENTSTRUCTFIELDS);
3473                 }
3474 #endif
3475
3476                 bmtEnumFields->dwNumStaticFields++;
3477
3478                 // If this static field is thread static, then we need
3479                 // to increment bmtEnumFields->dwNumThreadStaticFields
3480                 hr = GetCustomAttribute(tok,
3481                                         WellKnownAttribute::ThreadStatic,
3482                                         NULL, NULL);
3483                 IfFailThrow(hr);
3484                 if (hr == S_OK)
3485                 {
3486                     // It's a thread static, so increment the count
3487                     bmtEnumFields->dwNumThreadStaticFields++;
3488                 }
3489             }
3490         }
3491         else
3492         {
3493 #ifdef FEATURE_TYPEEQUIVALENCE
3494             if (!IsFdPublic(dwMemberAttrs) && bmtProp->fIsTypeEquivalent)
3495             {
3496                 BuildMethodTableThrowException(IDS_CLASSLOAD_EQUIVALENTSTRUCTFIELDS);
3497             }
3498 #endif
3499
3500             if (!IsFdLiteral(dwMemberAttrs))
3501             {
3502                 bmtEnumFields->dwNumInstanceFields++;
3503             }
3504             if(IsInterface())
3505             {
3506                 BuildMethodTableThrowException(BFA_INSTANCE_FIELD_IN_INT);
3507             }
3508         }
3509     }
3510
3511     if (i != bmtMetaData->cFields)
3512     {
3513         BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD_COUNT, mdTokenNil);
3514     }
3515
3516     if(IsEnum() && (bmtEnumFields->dwNumInstanceFields==0))
3517     {
3518         BuildMethodTableThrowException(BFA_INSTANCE_FIELD_IN_ENUM);
3519     }
3520
3521     bmtEnumFields->dwNumDeclaredFields = bmtEnumFields->dwNumStaticFields + bmtEnumFields->dwNumInstanceFields;
3522 }
3523
3524 //*******************************************************************************
3525 //
3526 // Used by BuildMethodTable
3527 //
3528 // Determines the maximum size of the vtable and allocates the temporary storage arrays
3529 // Also copies the parent's vtable into the working vtable.
3530 //
3531 VOID    MethodTableBuilder::AllocateWorkingSlotTables()
3532 {
3533     CONTRACTL
3534     {
3535         STANDARD_VM_CHECK;
3536         PRECONDITION(CheckPointer(this));
3537         PRECONDITION(CheckPointer(bmtAllocator));
3538         PRECONDITION(CheckPointer(bmtMFDescs));
3539         PRECONDITION(CheckPointer(bmtMetaData));
3540         PRECONDITION(CheckPointer(bmtVT));
3541         PRECONDITION(CheckPointer(bmtEnumFields));
3542         PRECONDITION(CheckPointer(bmtInterface));
3543         PRECONDITION(CheckPointer(bmtFP));
3544         PRECONDITION(CheckPointer(bmtParent));
3545
3546     }
3547     CONTRACTL_END;
3548
3549     // Allocate a FieldDesc* for each field
3550     bmtMFDescs->ppFieldDescList = new (GetStackingAllocator()) FieldDesc*[bmtMetaData->cFields];
3551     ZeroMemory(bmtMFDescs->ppFieldDescList, bmtMetaData->cFields * sizeof(FieldDesc *));
3552
3553     // Create a temporary function table (we don't know how large the vtable will be until the very end,
3554     // since we don't yet know how many declared methods are overrides vs. newslots).
3555
3556     if (IsValueClass())
3557     {   // ValueClass virtuals are converted into non-virtual methods and the virtual slots
3558         // become unboxing stubs that forward to these new non-virtual methods. This has the
3559         // side effect of doubling the number of slots introduced by newslot virtuals.
3560         bmtVT->dwMaxVtableSize += NumDeclaredMethods();
3561     }
3562
3563     _ASSERTE(!HasParent() || (bmtInterface->dwInterfaceMapSize - GetParentMethodTable()->GetNumInterfaces()) >= 0);
3564
3565     if (HasParent())
3566     {   // Add parent vtable size. <TODO> This should actually be the parent's virtual method count. </TODO>
3567         bmtVT->dwMaxVtableSize += bmtParent->pSlotTable->GetSlotCount();
3568     }
3569
3570     S_SLOT_INDEX cMaxSlots = AsClrSafeInt(bmtVT->dwMaxVtableSize) + AsClrSafeInt(NumDeclaredMethods());
3571
3572     if (cMaxSlots.IsOverflow() || MAX_SLOT_INDEX < cMaxSlots.Value())
3573         cMaxSlots = S_SLOT_INDEX(MAX_SLOT_INDEX);
3574
3575     // Allocate the temporary vtable
3576     bmtVT->pSlotTable = new (GetStackingAllocator())
3577         bmtMethodSlotTable(cMaxSlots.Value(), GetStackingAllocator());
3578
3579     if (HasParent())
3580     {
3581 #if 0
3582         // @<TODO>todo: Figure out the right way to override Equals for value
3583         // types only.
3584         //
3585         // This is broken because
3586         // (a) g_pObjectClass->FindMethod("Equals", &gsig_IM_Obj_RetBool); will return
3587         //      the EqualsValue method
3588         // (b) When CoreLib has been preloaded (and thus the munge already done
3589         //      ahead of time), we cannot easily find both methods
3590         //      to compute EqualsAddr & EqualsSlot
3591         //
3592         // For now, the Equals method has a runtime check to see if it's
3593         // comparing value types.
3594         //</TODO>
3595
3596         // If it is a value type, over ride a few of the base class methods.
3597         if (IsValueClass())
3598         {
3599             static WORD EqualsSlot;
3600
3601             // If we haven't been through here yet, get some stuff from the Object class definition.
3602             if (EqualsSlot == NULL)
3603             {
3604                 // Get the slot of the Equals method.
3605                 MethodDesc *pEqualsMD = g_pObjectClass->FindMethod("Equals", &gsig_IM_Obj_RetBool);
3606                 THROW_BAD_FORMAT_MAYBE(pEqualsMD != NULL, 0, this);
3607                 EqualsSlot = pEqualsMD->GetSlot();
3608
3609                 // Get the address of the EqualsValue method.
3610                 MethodDesc *pEqualsValueMD = g_pObjectClass->FindMethod("EqualsValue", &gsig_IM_Obj_RetBool);
3611                 THROW_BAD_FORMAT_MAYBE(pEqualsValueMD != NULL, 0, this);
3612
3613                 // Patch the EqualsValue method desc in a dangerous way to
3614                 // look like the Equals method desc.
3615                 pEqualsValueMD->SetSlot(EqualsSlot);
3616                 pEqualsValueMD->SetMemberDef(pEqualsMD->GetMemberDef());
3617             }
3618
3619             // Override the valuetype "Equals" with "EqualsValue".
3620             bmtVT->SetMethodDescForSlot(EqualsSlot, EqualsSlot);
3621         }
3622 #endif // 0
3623     }
3624
3625     S_UINT32 cEntries = S_UINT32(2) * S_UINT32(NumDeclaredMethods());
3626     if (cEntries.IsOverflow())
3627     {
3628         ThrowHR(COR_E_OVERFLOW);
3629     }
3630 }
3631
3632 //*******************************************************************************
3633 //
3634 // Used by BuildMethodTable
3635 //
3636 // Allocate a MethodDesc* for each method (needed later when doing interfaces), and a FieldDesc* for each field
3637 //
3638 VOID MethodTableBuilder::AllocateFieldDescs()
3639 {
3640     CONTRACTL
3641     {
3642         STANDARD_VM_CHECK;
3643         PRECONDITION(CheckPointer(this));
3644         PRECONDITION(CheckPointer(bmtAllocator));
3645         PRECONDITION(CheckPointer(bmtMFDescs));
3646         PRECONDITION(CheckPointer(bmtMetaData));
3647         PRECONDITION(CheckPointer(bmtVT));
3648         PRECONDITION(CheckPointer(bmtEnumFields));
3649         PRECONDITION(CheckPointer(bmtFP));
3650         PRECONDITION(CheckPointer(bmtParent));
3651
3652     }
3653     CONTRACTL_END;
3654
3655     // We'll be counting the # fields of each size as we go along
3656     for (DWORD i = 0; i <= MAX_LOG2_PRIMITIVE_FIELD_SIZE; i++)
3657     {
3658         bmtFP->NumRegularStaticFieldsOfSize[i]    = 0;
3659         bmtFP->NumThreadStaticFieldsOfSize[i]    = 0;
3660         bmtFP->NumInstanceFieldsOfSize[i]  = 0;
3661     }
3662
3663     //
3664     // Allocate blocks of MethodDescs and FieldDescs for all declared methods and fields
3665     //
3666     // In order to avoid allocating a field pointing back to the method
3667     // table in every single method desc, we allocate memory in the
3668     // following manner:
3669     //   o  Field descs get a single contiguous block.
3670     //   o  Method descs of different sizes (normal vs NDirect) are
3671     //      allocated in different MethodDescChunks.
3672     //   o  Each method desc chunk starts with a header, and has
3673     //      at most MAX_ method descs (if there are more
3674     //      method descs of a given size, multiple chunks are allocated).
3675     // This way method descs can use an 8-bit offset field to locate the
3676     // pointer to their method table.
3677     //
3678
3679     /////////////////////////////////////////////////////////////////
3680     // Allocate fields
3681     if (NumDeclaredFields() > 0)
3682     {
3683         GetHalfBakedClass()->SetFieldDescList((FieldDesc *)
3684             AllocateFromHighFrequencyHeap(S_SIZE_T(NumDeclaredFields()) * S_SIZE_T(sizeof(FieldDesc))));
3685         INDEBUG(GetClassLoader()->m_dwDebugFieldDescs += NumDeclaredFields();)
3686         INDEBUG(GetClassLoader()->m_dwFieldDescData += (NumDeclaredFields() * sizeof(FieldDesc));)
3687     }
3688 }
3689
3690 #ifdef FEATURE_DOUBLE_ALIGNMENT_HINT
3691 //*******************************************************************************
3692 //
3693 // Heuristic to determine if we should have instances of this class 8 byte aligned
3694 //
3695 BOOL MethodTableBuilder::ShouldAlign8(DWORD dwR8Fields, DWORD dwTotalFields)
3696 {
3697     LIMITED_METHOD_CONTRACT;
3698
3699     return dwR8Fields*2>dwTotalFields && dwR8Fields>=2;
3700 }
3701 #endif
3702
3703 //*******************************************************************************
3704 BOOL MethodTableBuilder::IsSelfReferencingStaticValueTypeField(mdToken     dwByValueClassToken,
3705                                                                bmtInternalInfo* bmtInternal,
3706                                                                const bmtGenericsInfo *bmtGenerics,
3707                                                                PCCOR_SIGNATURE pMemberSignature,
3708                                                                DWORD       cMemberSignature)
3709 {
3710     STANDARD_VM_CONTRACT;
3711
3712     if (dwByValueClassToken != this->GetCl())
3713     {
3714         return FALSE;
3715     }
3716
3717     if (!bmtGenerics->HasInstantiation())
3718     {
3719         return TRUE;
3720     }
3721
3722     // The value class is generic.  Check that the signature of the field
3723     // is _exactly_ equivalent to VC<!0, !1, !2, ...>.  Do this by consing up a fake
3724     // signature.
3725     DWORD nGenericArgs = bmtGenerics->GetNumGenericArgs();
3726     CONSISTENCY_CHECK(nGenericArgs != 0);
3727
3728     SigBuilder sigBuilder;
3729
3730     sigBuilder.AppendElementType(ELEMENT_TYPE_GENERICINST);
3731     sigBuilder.AppendElementType(ELEMENT_TYPE_VALUETYPE);
3732     sigBuilder.AppendToken(dwByValueClassToken);
3733     sigBuilder.AppendData(nGenericArgs);
3734     for (unsigned int typearg = 0; typearg < nGenericArgs; typearg++)
3735     {
3736         sigBuilder.AppendElementType(ELEMENT_TYPE_VAR);
3737         sigBuilder.AppendData(typearg);
3738     }
3739
3740     DWORD cFakeSig;
3741     PCCOR_SIGNATURE pFakeSig = (PCCOR_SIGNATURE)sigBuilder.GetSignature(&cFakeSig);
3742
3743     PCCOR_SIGNATURE pFieldSig = pMemberSignature + 1; // skip the CALLCONV_FIELD
3744
3745     return MetaSig::CompareElementType(pFakeSig, pFieldSig,
3746                                        pFakeSig + cFakeSig,  pMemberSignature + cMemberSignature,
3747                                        GetModule(), GetModule(),
3748                                        NULL, NULL);
3749
3750 }
3751
3752 //*******************************************************************************
3753 //
3754 // Used pByValueClass cache to mark self-references
3755 //
3756 static BOOL IsSelfRef(MethodTable * pMT)
3757 {
3758     return pMT == (MethodTable *)-1;
3759 }
3760
3761 //*******************************************************************************
3762 //
3763 // Used by BuildMethodTable
3764 //
3765 // Go thru all fields and initialize their FieldDescs.
3766 //
3767 #ifdef _PREFAST_
3768 #pragma warning(push)
3769 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
3770 #endif // _PREFAST_
3771
3772 VOID    MethodTableBuilder::InitializeFieldDescs(FieldDesc *pFieldDescList,
3773                                                  const LayoutRawFieldInfo* pLayoutRawFieldInfos,
3774                                                  bmtInternalInfo* bmtInternal,
3775                                                  const bmtGenericsInfo* bmtGenerics,
3776                                                  bmtMetaDataInfo* bmtMetaData,
3777                                                  bmtEnumFieldInfo* bmtEnumFields,
3778                                                  bmtErrorInfo* bmtError,
3779                                                  MethodTable *** pByValueClassCache,
3780                                                  bmtMethAndFieldDescs* bmtMFDescs,
3781                                                  bmtFieldPlacement* bmtFP,
3782                                                  unsigned* totalDeclaredSize)
3783 {
3784     CONTRACTL
3785     {
3786         STANDARD_VM_CHECK;
3787         PRECONDITION(CheckPointer(this));
3788         PRECONDITION(CheckPointer(bmtInternal));
3789         PRECONDITION(CheckPointer(bmtGenerics));
3790         PRECONDITION(CheckPointer(bmtMetaData));
3791         PRECONDITION(CheckPointer(bmtEnumFields));
3792         PRECONDITION(CheckPointer(bmtError));
3793         PRECONDITION(CheckPointer(pByValueClassCache));
3794         PRECONDITION(CheckPointer(bmtMFDescs));
3795         PRECONDITION(CheckPointer(bmtFP));
3796         PRECONDITION(CheckPointer(totalDeclaredSize));
3797     }
3798     CONTRACTL_END;
3799
3800     DWORD i;
3801     IMDInternalImport * pInternalImport = GetMDImport(); // to avoid multiple dereferencings
3802
3803 //========================================================================
3804 // BEGIN:
3805 //    Go thru all fields and initialize their FieldDescs.
3806 //========================================================================
3807
3808     DWORD   dwCurrentDeclaredField = 0;
3809     DWORD   dwCurrentStaticField   = 0;
3810     DWORD   dwCurrentThreadStaticField = 0;
3811
3812
3813     DWORD   dwR8Fields              = 0;        // Number of R8's the class has
3814
3815 #ifdef FEATURE_64BIT_ALIGNMENT
3816     // Track whether any field in this type requires 8-byte alignment
3817     BOOL    fFieldRequiresAlign8 = HasParent() ? GetParentMethodTable()->RequiresAlign8() : FALSE;
3818 #endif
3819 #if defined(EnC_SUPPORTED)
3820     bool isEnCField = pFieldDescList != NULL && pFieldDescList->IsEnCNew();
3821 #else
3822     bool isEnCField = false;
3823 #endif // EnC_SUPPORTED
3824
3825     for (i = 0; i < bmtMetaData->cFields; i++)
3826     {
3827         PCCOR_SIGNATURE pMemberSignature;
3828         DWORD       cMemberSignature;
3829         DWORD       dwMemberAttrs;
3830
3831         dwMemberAttrs = bmtMetaData->pFieldAttrs[i];
3832
3833         BOOL fIsStatic = IsFdStatic(dwMemberAttrs);
3834
3835         // We don't store static final primitive fields in the class layout
3836         if (IsFdLiteral(dwMemberAttrs))
3837             continue;
3838
3839         if (!IsFdPublic(dwMemberAttrs))
3840             SetHasNonPublicFields();
3841
3842         IfFailThrow(pInternalImport->GetSigOfFieldDef(bmtMetaData->pFields[i], &cMemberSignature, &pMemberSignature));
3843         // Signature validation
3844         IfFailThrow(validateTokenSig(bmtMetaData->pFields[i],pMemberSignature,cMemberSignature,dwMemberAttrs,pInternalImport));
3845
3846         FieldDesc * pFD;
3847         DWORD       dwLog2FieldSize = 0;
3848         BOOL        bCurrentFieldIsGCPointer = FALSE;
3849         mdToken     dwByValueClassToken = 0;
3850         MethodTable * pByValueClass = NULL;
3851         BOOL        fIsByValue = FALSE;
3852         BOOL        fIsThreadStatic = FALSE;
3853         BOOL        fHasRVA = FALSE;
3854
3855         MetaSig fsig(pMemberSignature,
3856                      cMemberSignature,
3857                      GetModule(),
3858                      &bmtGenerics->typeContext,
3859                      MetaSig::sigField);
3860         CorElementType ElementType = fsig.NextArg();
3861
3862
3863         // Get type
3864         if (!isCallConv(fsig.GetCallingConvention(), IMAGE_CEE_CS_CALLCONV_FIELD))
3865         {
3866             IfFailThrow(COR_E_TYPELOAD);
3867         }
3868
3869         // Determine if a static field is special i.e. RVA based, local to
3870         // a thread or a context
3871         if (fIsStatic)
3872         {
3873             if (IsFdHasFieldRVA(dwMemberAttrs))
3874             {
3875                 fHasRVA = TRUE;
3876             }
3877
3878             HRESULT hr;
3879
3880             hr = GetCustomAttribute(bmtMetaData->pFields[i],
3881                                     WellKnownAttribute::ThreadStatic,
3882                                     NULL, NULL);
3883             IfFailThrow(hr);
3884             if (hr == S_OK)
3885             {
3886                 fIsThreadStatic = TRUE;
3887             }
3888
3889
3890             if (ElementType == ELEMENT_TYPE_VALUETYPE)
3891             {
3892                 hr = GetCustomAttribute(bmtMetaData->pFields[i],
3893                                         WellKnownAttribute::FixedAddressValueType,
3894                                         NULL, NULL);
3895                 IfFailThrow(hr);
3896                 if (hr == S_OK)
3897                 {
3898                     bmtFP->fHasFixedAddressValueTypes = true;
3899                 }
3900             }
3901
3902
3903             // Do some sanity checks that we are not mixing context and thread
3904             // relative statics.
3905             if (fHasRVA && fIsThreadStatic)
3906             {
3907                 IfFailThrow(COR_E_TYPELOAD);
3908             }
3909
3910             if (bmtFP->fHasFixedAddressValueTypes && GetAssembly()->IsCollectible())
3911             {
3912                 BuildMethodTableThrowException(IDS_CLASSLOAD_COLLECTIBLEFIXEDVTATTR);
3913             }
3914         }
3915
3916
3917     GOT_ELEMENT_TYPE:
3918         // Type to store in FieldDesc - we don't want to have extra case statements for
3919         // ELEMENT_TYPE_STRING, SDARRAY etc., so we convert all object types to CLASS.
3920         // Also, BOOLEAN, CHAR are converted to U1, I2.
3921         CorElementType FieldDescElementType = ElementType;
3922
3923         switch (ElementType)
3924         {
3925         case ELEMENT_TYPE_I1:
3926         case ELEMENT_TYPE_U1:
3927             {
3928                 dwLog2FieldSize = 0;
3929                 break;
3930             }
3931
3932         case ELEMENT_TYPE_I2:
3933         case ELEMENT_TYPE_U2:
3934             {
3935                 dwLog2FieldSize = 1;
3936                 break;
3937             }
3938
3939         case ELEMENT_TYPE_I4:
3940         case ELEMENT_TYPE_U4:
3941         IN_TARGET_32BIT(case ELEMENT_TYPE_I:)
3942         IN_TARGET_32BIT(case ELEMENT_TYPE_U:)
3943         case ELEMENT_TYPE_R4:
3944             {
3945                 dwLog2FieldSize = 2;
3946                 break;
3947             }
3948
3949         case ELEMENT_TYPE_BOOLEAN:
3950             {
3951                 //                FieldDescElementType = ELEMENT_TYPE_U1;
3952                 dwLog2FieldSize = 0;
3953                 break;
3954             }
3955
3956         case ELEMENT_TYPE_CHAR:
3957             {
3958                 //                FieldDescElementType = ELEMENT_TYPE_U2;
3959                 dwLog2FieldSize = 1;
3960                 break;
3961             }
3962
3963         case ELEMENT_TYPE_R8:
3964             {
3965                 dwR8Fields++;
3966
3967                 // Deliberate fall through...
3968                 FALLTHROUGH;
3969             }
3970
3971         case ELEMENT_TYPE_I8:
3972         case ELEMENT_TYPE_U8:
3973         IN_TARGET_64BIT(case ELEMENT_TYPE_I:)
3974         IN_TARGET_64BIT(case ELEMENT_TYPE_U:)
3975             {
3976 #ifdef FEATURE_64BIT_ALIGNMENT
3977                 // Record that this field requires alignment for Int64/UInt64.
3978                 if(!fIsStatic)
3979                     fFieldRequiresAlign8 = true;
3980 #endif
3981                 dwLog2FieldSize = 3;
3982                 break;
3983             }
3984
3985         case ELEMENT_TYPE_FNPTR:
3986         case ELEMENT_TYPE_PTR:   // ptrs are unmanaged scalars, for layout
3987             {
3988                 dwLog2FieldSize = LOG2_PTRSIZE;
3989                 break;
3990             }
3991
3992         case ELEMENT_TYPE_BYREF:
3993             {
3994                 dwLog2FieldSize = LOG2_PTRSIZE;
3995                 if (fIsStatic)
3996                 {
3997                     // Byref-like types cannot be used for static fields
3998                     BuildMethodTableThrowException(IDS_CLASSLOAD_BYREF_OR_BYREFLIKE_STATICFIELD);
3999                 }
4000                 if (!bmtFP->fIsByRefLikeType)
4001                 {
4002                     // Non-byref-like types cannot contain byref-like instance fields
4003                     BuildMethodTableThrowException(IDS_CLASSLOAD_BYREF_OR_BYREFLIKE_INSTANCEFIELD);
4004                 }
4005                 break;
4006             }
4007
4008         case ELEMENT_TYPE_TYPEDBYREF:
4009             {
4010                 goto IS_VALUETYPE;
4011             }
4012
4013         // Class type variable (method type variables aren't allowed in fields)
4014         // These only occur in open types used for verification/reflection.
4015         case ELEMENT_TYPE_VAR:
4016         case ELEMENT_TYPE_MVAR:
4017            // deliberate drop through - do fake field layout
4018         case ELEMENT_TYPE_STRING:
4019         case ELEMENT_TYPE_SZARRAY:      // single dim, zero
4020         case ELEMENT_TYPE_ARRAY:        // all other arrays
4021         case ELEMENT_TYPE_CLASS: // objectrefs
4022         case ELEMENT_TYPE_OBJECT:
4023             {
4024                 dwLog2FieldSize = LOG2_PTRSIZE;
4025                 bCurrentFieldIsGCPointer = TRUE;
4026                 FieldDescElementType = ELEMENT_TYPE_CLASS;
4027
4028                 if (!fIsStatic)
4029                 {
4030                     SetHasFieldsWhichMustBeInited();
4031                 }
4032                 else
4033                 {   // EnumerateFieldDescs already counted the total number of static vs. instance
4034                     // fields, now we're further subdividing the static field count by GC and non-GC.
4035                     bmtEnumFields->dwNumStaticObjRefFields++;
4036                     if (fIsThreadStatic)
4037                         bmtEnumFields->dwNumThreadStaticObjRefFields++;
4038                 }
4039                 break;
4040             }
4041
4042         case ELEMENT_TYPE_VALUETYPE: // a byvalue class field
4043             {
4044                 Module * pTokenModule;
4045                 dwByValueClassToken = fsig.GetArgProps().PeekValueTypeTokenClosed(GetModule(), &bmtGenerics->typeContext, &pTokenModule);
4046
4047                 // By-value class
4048                 BAD_FORMAT_NOTHROW_ASSERT(dwByValueClassToken != 0);
4049
4050                 if (this->IsValueClass() && (pTokenModule == GetModule()))
4051                 {
4052                     if (TypeFromToken(dwByValueClassToken) == mdtTypeRef)
4053                     {
4054                         // It's a typeref - check if it's a class that has a static field of itself
4055                         LPCUTF8 pszNameSpace;
4056                         LPCUTF8 pszClassName;
4057                         if (FAILED(pInternalImport->GetNameOfTypeRef(dwByValueClassToken, &pszNameSpace, &pszClassName)))
4058                         {
4059                             BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
4060                         }
4061
4062                         if (IsStrLongerThan((char *)pszClassName, MAX_CLASS_NAME)
4063                             || IsStrLongerThan((char *)pszNameSpace, MAX_CLASS_NAME)
4064                             || (strlen(pszClassName) + strlen(pszNameSpace) + 1 >= MAX_CLASS_NAME))
4065                         {
4066                             BuildMethodTableThrowException(BFA_TYPEREG_NAME_TOO_LONG, mdMethodDefNil);
4067                         }
4068
4069                         mdToken tkRes;
4070                         if (FAILED(pInternalImport->GetResolutionScopeOfTypeRef(dwByValueClassToken, &tkRes)))
4071                         {
4072                             BuildMethodTableThrowException(BFA_BAD_TYPEREF_TOKEN, dwByValueClassToken);
4073                         }
4074
4075                         if (TypeFromToken(tkRes) == mdtTypeRef)
4076                         {
4077                             if (!pInternalImport->IsValidToken(tkRes))
4078                             {
4079                                 BuildMethodTableThrowException(BFA_BAD_TYPEREF_TOKEN, mdMethodDefNil);
4080                             }
4081                         }
4082                         else
4083                         {
4084                             tkRes = mdTokenNil;
4085                         }
4086
4087                         if (FAILED(pInternalImport->FindTypeDef(pszNameSpace,
4088                                                                 pszClassName,
4089                                                                 tkRes,
4090                                                                 &dwByValueClassToken)))
4091                         {
4092                             dwByValueClassToken = mdTokenNil;
4093                         }
4094                     } // If field is static typeref
4095
4096                     BOOL selfref = IsSelfReferencingStaticValueTypeField(dwByValueClassToken,
4097                                                                     bmtInternal,
4098                                                                     bmtGenerics,
4099                                                                     pMemberSignature,
4100                                                                     cMemberSignature);
4101
4102                     if (selfref)
4103                     {   // immediately self-referential fields must be static.
4104                         if (!fIsStatic)
4105                         {
4106                             BuildMethodTableThrowException(IDS_CLASSLOAD_VALUEINSTANCEFIELD, mdMethodDefNil);
4107                         }
4108
4109                         if (!IsValueClass())
4110                         {
4111                             BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_MUST_BE_BYVAL, mdTokenNil);
4112                         }
4113
4114                         pByValueClass = (MethodTable *)-1;
4115                     }
4116                 } // If 'this' is a value class
4117             }
4118             // TypedReference shares the rest of the code here
4119 IS_VALUETYPE:
4120             {
4121                 fIsByValue = TRUE;
4122
4123                 // It's not self-referential so try to load it
4124                 if (pByValueClass == NULL)
4125                 {
4126                     // Loading a non-self-ref valuetype field.
4127                     OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOAD_APPROXPARENTS);
4128                     if (isEnCField || fIsStatic)
4129                     {
4130                         // EnCFieldDescs are not created at normal MethodTableBuilder time, and don't need to avoid recursive generic instantiation
4131                         pByValueClass = fsig.GetArgProps().GetTypeHandleThrowing(GetModule(),
4132                                                                             &bmtGenerics->typeContext,
4133                                                                              ClassLoader::LoadTypes,
4134                                                                              CLASS_LOAD_APPROXPARENTS,
4135                                                                              TRUE
4136                                                                              ).GetMethodTable();
4137                     }
4138                     else
4139                     {
4140                         // We load the approximate type of the field to avoid recursion problems.
4141                         // MethodTable::DoFullyLoad() will later load it fully
4142                         SigPointer::HandleRecursiveGenericsForFieldLayoutLoad recursiveControl;
4143                         recursiveControl.pModuleWithTokenToAvoidIfPossible = GetModule();
4144                         recursiveControl.tkTypeDefToAvoidIfPossible = GetCl();
4145                         pByValueClass = fsig.GetArgProps().GetTypeHandleThrowing(GetModule(),
4146                                                                                 &bmtGenerics->typeContext,
4147                                                                                 ClassLoader::LoadTypes,
4148                                                                                 CLASS_LOAD_APPROXPARENTS,
4149                                                                                 TRUE, NULL, NULL, NULL,
4150                                                                                 &recursiveControl).GetMethodTable();
4151                     }
4152                 }
4153
4154                 // #FieldDescTypeMorph  IF it is an enum, strip it down to its underlying type
4155                 if (IsSelfRef(pByValueClass) ? IsEnum() : pByValueClass->IsEnum())
4156                 {
4157                     if (IsSelfRef(pByValueClass))
4158                     {   // It is self-referencing enum (ValueType) static field - it is forbidden in the ECMA spec, but supported by CLR since v1
4159                         // Note: literal static fields are skipped early in this loop
4160                         if (bmtMFDescs->ppFieldDescList[0] == NULL)
4161                         {   // The field is defined before (the only) instance field
4162                             // AppCompat with 3.5 SP1 and 4.0 RTM behavior
4163                             BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil);
4164                         }
4165                         // 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
4166                         // later in this method)
4167                         // Therefore we do not have to run code:VerifySelfReferencingStaticValueTypeFields_WithRVA or code:#SelfReferencingStaticValueTypeField_Checks
4168                     }
4169                     BAD_FORMAT_NOTHROW_ASSERT((IsSelfRef(pByValueClass) ?
4170                             bmtEnumFields->dwNumInstanceFields : pByValueClass->GetNumInstanceFields())
4171                                 == 1); // enums must have exactly one field
4172                     FieldDesc * enumField = IsSelfRef(pByValueClass) ?
4173                             bmtMFDescs->ppFieldDescList[0] : pByValueClass->GetApproxFieldDescListRaw();
4174                     BAD_FORMAT_NOTHROW_ASSERT(!enumField->IsStatic());   // no real static fields on enums
4175                     ElementType = enumField->GetFieldType();
4176                     BAD_FORMAT_NOTHROW_ASSERT(ElementType != ELEMENT_TYPE_VALUETYPE);
4177                     fIsByValue = FALSE; // we're going to treat it as the underlying type now
4178                     goto GOT_ELEMENT_TYPE;
4179                 }
4180
4181                 // Check ByRefLike fields
4182                 if (!IsSelfRef(pByValueClass) && pByValueClass->IsByRefLike())
4183                 {
4184                     if (fIsStatic)
4185                     {
4186                         // Byref-like types cannot be used for static fields
4187                         BuildMethodTableThrowException(IDS_CLASSLOAD_BYREF_OR_BYREFLIKE_STATICFIELD);
4188                     }
4189                     if (!bmtFP->fIsByRefLikeType)
4190                     {
4191                         // Non-byref-like types cannot contain byref-like instance fields
4192                         BuildMethodTableThrowException(IDS_CLASSLOAD_BYREF_OR_BYREFLIKE_INSTANCEFIELD);
4193                     }
4194                 }
4195
4196                 if (!IsSelfRef(pByValueClass) && pByValueClass->GetClass()->HasNonPublicFields())
4197                 {   // If a class has a field of type ValueType with non-public fields in it,
4198                     // the class must "inherit" this characteristic
4199                     SetHasNonPublicFields();
4200                 }
4201
4202                 if (!fHasRVA)
4203                 {
4204                     if (!fIsStatic)
4205                     {
4206                         // Inherit instance attributes
4207                         EEClass * pFieldClass = pByValueClass->GetClass();
4208
4209 #ifdef FEATURE_64BIT_ALIGNMENT
4210                         // If a value type requires 8-byte alignment this requirement must be inherited by any
4211                         // class/struct that embeds it as a field.
4212                         if (pFieldClass->IsAlign8Candidate())
4213                             fFieldRequiresAlign8 = true;
4214 #endif
4215                         if (pFieldClass->HasNonPublicFields())
4216                             SetHasNonPublicFields();
4217                         if (pFieldClass->HasFieldsWhichMustBeInited())
4218                             SetHasFieldsWhichMustBeInited();
4219
4220 #ifdef FEATURE_READYTORUN
4221                         if (!(pByValueClass->IsTruePrimitive() || pByValueClass->IsEnum()))
4222                         {
4223                             CheckLayoutDependsOnOtherModules(pByValueClass);
4224                         }
4225 #endif
4226                     }
4227                     else
4228                     {   // Increment the number of static fields that contain object references.
4229                         bmtEnumFields->dwNumStaticBoxedFields++;
4230                         if (fIsThreadStatic)
4231                             bmtEnumFields->dwNumThreadStaticBoxedFields++;
4232                     }
4233                 }
4234
4235                 if (*pByValueClassCache == NULL)
4236                 {
4237                     DWORD dwNumFields = bmtEnumFields->dwNumInstanceFields + bmtEnumFields->dwNumStaticFields;
4238
4239                     *pByValueClassCache = new (GetStackingAllocator()) MethodTable * [dwNumFields];
4240                     memset (*pByValueClassCache, 0, dwNumFields * sizeof(MethodTable **));
4241                 }
4242
4243                 // Thread static fields come after instance fields and regular static fields in this list
4244                 if (fIsThreadStatic)
4245                 {
4246                     (*pByValueClassCache)[bmtEnumFields->dwNumInstanceFields + bmtEnumFields->dwNumStaticFields - bmtEnumFields->dwNumThreadStaticFields + dwCurrentThreadStaticField] = pByValueClass;
4247                     // make sure to record the correct size for static field
4248                     // layout
4249                     dwLog2FieldSize = LOG2_PTRSIZE; // handle
4250                 }
4251                 // Regular static fields come after instance fields in this list
4252                 else if (fIsStatic)
4253                 {
4254                     (*pByValueClassCache)[bmtEnumFields->dwNumInstanceFields + dwCurrentStaticField] = pByValueClass;
4255                     // make sure to record the correct size for static field
4256                     // layout
4257                     dwLog2FieldSize = LOG2_PTRSIZE; // handle
4258                 }
4259                 else
4260                 {
4261                     (*pByValueClassCache)[dwCurrentDeclaredField] = pByValueClass;
4262                     dwLog2FieldSize = 0; // unused
4263                 }
4264
4265                 break;
4266             }
4267         default:
4268             {
4269                 BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil);
4270             }
4271         }
4272
4273         if (!fIsStatic)
4274         {
4275             pFD = &pFieldDescList[dwCurrentDeclaredField]; // lgtm [cpp/upcast-array-pointer-arithmetic] - The call of concern in FixupFieldDescForEnC, initializes this loop invariant to 1, so will never be > 1.
4276             *totalDeclaredSize += (1 << dwLog2FieldSize);
4277         }
4278         else /* (dwMemberAttrs & mdStatic) */
4279         {
4280             if (fIsThreadStatic)
4281             {
4282                 pFD = &pFieldDescList[bmtEnumFields->dwNumInstanceFields + bmtEnumFields->dwNumStaticFields - bmtEnumFields->dwNumThreadStaticFields + dwCurrentThreadStaticField]; // lgtm [cpp/upcast-array-pointer-arithmetic] - The call of concern in FixupFieldDescForEnC, initializes this loop invariant to 1, so will never be > 1.
4283             }
4284             else
4285             {
4286                 pFD = &pFieldDescList[bmtEnumFields->dwNumInstanceFields + dwCurrentStaticField]; // lgtm [cpp/upcast-array-pointer-arithmetic] - The call of concern in FixupFieldDescForEnC, initializes this loop invariant to 1, so will never be > 1.
4287             }
4288         }
4289
4290         bmtMFDescs->ppFieldDescList[i] = pFD;
4291
4292         const LayoutRawFieldInfo *pLayoutFieldInfo = NULL;
4293
4294         if (HasLayout())
4295         {
4296             const LayoutRawFieldInfo *pwalk = pLayoutRawFieldInfos;
4297             while (pwalk->m_MD != mdFieldDefNil)
4298             {
4299                 if (pwalk->m_MD == bmtMetaData->pFields[i])
4300                 {
4301                     pLayoutFieldInfo = pwalk;
4302                     break;
4303                 }
4304                 pwalk++;
4305             }
4306         }
4307
4308         LPCSTR pszFieldName = NULL;
4309 #ifdef _DEBUG
4310         if (FAILED(pInternalImport->GetNameOfFieldDef(bmtMetaData->pFields[i], &pszFieldName)))
4311         {
4312             pszFieldName = "Invalid FieldDef record";
4313         }
4314 #endif
4315         // #InitCall Initialize contents of the field descriptor called from
4316         pFD->Init(
4317                   bmtMetaData->pFields[i],
4318                   FieldDescElementType,
4319                   dwMemberAttrs,
4320                   fIsStatic,
4321                   fHasRVA,
4322                   fIsThreadStatic,
4323                   pszFieldName
4324                   );
4325
4326         // We're using FieldDesc::m_pMTOfEnclosingClass to temporarily store the field's size.
4327         //
4328         if (fIsByValue)
4329         {
4330             if (!fIsStatic &&
4331                 (IsBlittable() || HasExplicitFieldOffsetLayout()))
4332             {
4333                 (DWORD_PTR &)pFD->m_pMTOfEnclosingClass =
4334                     (*pByValueClassCache)[dwCurrentDeclaredField]->GetNumInstanceFieldBytes();
4335
4336                 if (pLayoutFieldInfo)
4337                     IfFailThrow(pFD->SetOffset(pLayoutFieldInfo->m_placement.m_offset));
4338                 else
4339                     pFD->SetOffset(FIELD_OFFSET_VALUE_CLASS);
4340             }
4341             else if (!fIsStatic && IsManagedSequential())
4342             {
4343                 (DWORD_PTR &)pFD->m_pMTOfEnclosingClass =
4344                     (*pByValueClassCache)[dwCurrentDeclaredField]->GetNumInstanceFieldBytes();
4345
4346                 IfFailThrow(pFD->SetOffset(pLayoutFieldInfo->m_placement.m_offset));
4347             }
4348             else
4349             {
4350                 // static value class fields hold a handle, which is ptr sized
4351                 // (instance field layout ignores this value)
4352                 (DWORD_PTR&)(pFD->m_pMTOfEnclosingClass) = LOG2_PTRSIZE;
4353                 pFD->SetOffset(FIELD_OFFSET_VALUE_CLASS);
4354             }
4355         }
4356         else
4357         {
4358             (DWORD_PTR &)(pFD->m_pMTOfEnclosingClass) = (size_t)dwLog2FieldSize;
4359
4360             // -1 (FIELD_OFFSET_UNPLACED) means that this is a non-GC field that has not yet been placed
4361             // -2 (FIELD_OFFSET_UNPLACED_GC_PTR) means that this is a GC pointer field that has not yet been placed
4362
4363             // If there is any kind of explicit layout information for this field, use it. If not, then
4364             // mark it as either GC or non-GC and as unplaced; it will get placed later on in an optimized way.
4365
4366             if ((IsBlittable() || HasExplicitFieldOffsetLayout()) && !fIsStatic)
4367                 IfFailThrow(pFD->SetOffset(pLayoutFieldInfo->m_placement.m_offset));
4368             else if (IsManagedSequential() && !fIsStatic)
4369                 IfFailThrow(pFD->SetOffset(pLayoutFieldInfo->m_placement.m_offset));
4370             else if (bCurrentFieldIsGCPointer)
4371                 pFD->SetOffset(FIELD_OFFSET_UNPLACED_GC_PTR);
4372             else
4373                 pFD->SetOffset(FIELD_OFFSET_UNPLACED);
4374         }
4375
4376         if (!fIsStatic)
4377         {
4378             if (!fIsByValue)
4379             {
4380                 if (++bmtFP->NumInstanceFieldsOfSize[dwLog2FieldSize] == 1)
4381                     bmtFP->FirstInstanceFieldOfSize[dwLog2FieldSize] = dwCurrentDeclaredField;
4382             }
4383
4384             dwCurrentDeclaredField++;
4385
4386             if (bCurrentFieldIsGCPointer)
4387             {
4388                 bmtFP->NumInstanceGCPointerFields++;
4389             }
4390         }
4391         else /* static fields */
4392         {
4393             // Static fields are stored in the vtable after the vtable and interface slots.  We don't
4394             // know how large the vtable will be, so we will have to fixup the slot number by
4395             // <vtable + interface size> later.
4396
4397             if (fIsThreadStatic)
4398             {
4399                 dwCurrentThreadStaticField++;
4400             }
4401             else
4402             {
4403                 dwCurrentStaticField++;
4404             }
4405
4406             if (fHasRVA)
4407             {
4408                 if (FieldDescElementType == ELEMENT_TYPE_CLASS)
4409                 {   // RVA fields are not allowed to have GC pointers.
4410                     BAD_FORMAT_NOTHROW_ASSERT(!"ObjectRef in an RVA field");
4411                     BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil);
4412                 }
4413                 if (FieldDescElementType == ELEMENT_TYPE_VALUETYPE)
4414                 {
4415                     if (IsSelfRef(pByValueClass))
4416                     {   // We will verify self-referencing statics after the loop through all fields - see code:#SelfReferencingStaticValueTypeField_Checks
4417                         bmtFP->fHasSelfReferencingStaticValueTypeField_WithRVA = TRUE;
4418                     }
4419                     else
4420                     {
4421                         if (pByValueClass->GetClass()->HasFieldsWhichMustBeInited())
4422                         {   // RVA fields are not allowed to have GC pointers.
4423                             BAD_FORMAT_NOTHROW_ASSERT(!"ObjectRef in an RVA field");
4424                             BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil);
4425                         }
4426                     }
4427                 }
4428
4429                 // Set the field offset
4430                 DWORD rva;
4431                 IfFailThrow(pInternalImport->GetFieldRVA(pFD->GetMemberDef(), &rva));
4432
4433                 // The PE should be loaded by now.
4434                 _ASSERT(GetModule()->GetPEAssembly()->IsLoaded());
4435
4436                 DWORD fldSize;
4437                 if (FieldDescElementType == ELEMENT_TYPE_VALUETYPE)
4438                 {
4439                     if (IsSelfRef(pByValueClass))
4440                     {
4441                         _ASSERTE(bmtFP->fHasSelfReferencingStaticValueTypeField_WithRVA);
4442
4443                         // We do not known the size yet
4444                         _ASSERTE(bmtFP->NumInstanceFieldBytes == 0);
4445                         // We will check just the RVA with size 0 now, the full size verification will happen in code:VerifySelfReferencingStaticValueTypeFields_WithRVA
4446                         fldSize = 0;
4447                     }
4448                     else
4449                     {
4450                         fldSize = pByValueClass->GetNumInstanceFieldBytes();
4451                     }
4452                 }
4453                 else
4454                 {
4455                     fldSize = GetSizeForCorElementType(FieldDescElementType);
4456                 }
4457
4458                 pFD->SetOffsetRVA(rva);
4459             }
4460             else if (fIsThreadStatic)
4461             {
4462                 bmtFP->NumThreadStaticFieldsOfSize[dwLog2FieldSize]++;
4463
4464                 if (bCurrentFieldIsGCPointer)
4465                     bmtFP->NumThreadStaticGCPointerFields++;
4466
4467                 if (fIsByValue)
4468                     bmtFP->NumThreadStaticGCBoxedFields++;
4469             }
4470             else
4471             {
4472                 bmtFP->NumRegularStaticFieldsOfSize[dwLog2FieldSize]++;
4473
4474                 if (bCurrentFieldIsGCPointer)
4475                     bmtFP->NumRegularStaticGCPointerFields++;
4476
4477                 if (fIsByValue)
4478                     bmtFP->NumRegularStaticGCBoxedFields++;
4479             }
4480         }
4481     }
4482     // We processed all fields
4483
4484     //#SelfReferencingStaticValueTypeField_Checks
4485     if (bmtFP->fHasSelfReferencingStaticValueTypeField_WithRVA)
4486     {   // The type has self-referencing static ValueType field with RVA, do more checks now that depend on all fields being processed
4487
4488         // For enums we already checked its underlying type, we should not get here
4489         _ASSERTE(!IsEnum());
4490
4491         if (HasFieldsWhichMustBeInited())
4492         {   // RVA fields are not allowed to have GC pointers.
4493             BAD_FORMAT_NOTHROW_ASSERT(!"ObjectRef in an RVA self-referencing static field");
4494             BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil);
4495         }
4496     }
4497
4498     DWORD dwNumInstanceFields = dwCurrentDeclaredField + (HasParent() ? GetParentMethodTable()->GetNumInstanceFields() : 0);
4499     DWORD dwNumStaticFields = bmtEnumFields->dwNumStaticFields;
4500     DWORD dwNumThreadStaticFields = bmtEnumFields->dwNumThreadStaticFields;
4501
4502     if (!FitsIn<WORD>(dwNumInstanceFields) ||
4503         !FitsIn<WORD>(dwNumStaticFields))
4504     {   // An implementation limitation means that it's an error if there are greater that MAX_WORD fields.
4505         BuildMethodTableThrowException(IDS_EE_TOOMANYFIELDS);
4506     }
4507
4508     if (!isEnCField)
4509     {
4510         GetHalfBakedClass()->SetNumInstanceFields((WORD)dwNumInstanceFields);
4511         GetHalfBakedClass()->SetNumStaticFields((WORD)dwNumStaticFields);
4512         GetHalfBakedClass()->SetNumThreadStaticFields((WORD)dwNumThreadStaticFields);
4513     }
4514
4515     if (bmtFP->fHasFixedAddressValueTypes)
4516     {
4517         // To make things simpler, if the class has any field with this requirement, we'll set
4518         // all the statics to have this property. This allows us to only need to persist one bit
4519         // for the ngen case.
4520         GetHalfBakedClass()->SetHasFixedAddressVTStatics();
4521     }
4522
4523 #ifdef FEATURE_64BIT_ALIGNMENT
4524     // For types with layout we drop any 64-bit alignment requirement if the packing size was less than 8
4525     // bytes (this mimics what the native compiler does and ensures we match up calling conventions during
4526     // interop).
4527     // We don't do this for types that are marked as sequential but end up with auto-layout due to containing pointers,
4528     // as auto-layout ignores any Pack directives.
4529     if (HasLayout() && (HasExplicitFieldOffsetLayout() || IsManagedSequential()) && GetLayoutInfo()->GetPackingSize() < 8)
4530     {
4531         fFieldRequiresAlign8 = false;
4532     }
4533
4534     if (fFieldRequiresAlign8)
4535     {
4536         SetAlign8Candidate();
4537     }
4538 #endif // FEATURE_64BIT_ALIGNMENT
4539
4540 #ifdef FEATURE_DOUBLE_ALIGNMENT_HINT
4541     if (ShouldAlign8(dwR8Fields, dwNumInstanceFields))
4542     {
4543         SetAlign8Candidate();
4544     }
4545 #endif // FEATURE_DOUBLE_ALIGNMENT_HINT
4546
4547
4548     //========================================================================
4549     // END:
4550     //    Go thru all fields and initialize their FieldDescs.
4551     //========================================================================
4552
4553     return;
4554 } // MethodTableBuilder::InitializeFieldDescs
4555
4556 #ifdef _PREFAST_
4557 #pragma warning(pop)
4558 #endif
4559
4560 //*******************************************************************************
4561 // Verify self-referencing static ValueType fields with RVA (when the size of the ValueType is known).
4562 void
4563 MethodTableBuilder::VerifySelfReferencingStaticValueTypeFields_WithRVA(
4564     MethodTable ** pByValueClassCache)
4565 {
4566     STANDARD_VM_CONTRACT;
4567
4568     _ASSERTE(bmtFP->fHasSelfReferencingStaticValueTypeField_WithRVA);
4569     // Enum's static self-referencing fields have been verified as the underlying type of the enum, we should not get here for them
4570     _ASSERTE(!IsEnum());
4571     // The size of the ValueType should be known at this point (the caller throws if it is 0)
4572     _ASSERTE(bmtFP->NumInstanceFieldBytes != 0);
4573
4574     FieldDesc * pFieldDescList = GetApproxFieldDescListRaw();
4575     DWORD nFirstThreadStaticFieldIndex = bmtEnumFields->dwNumInstanceFields + bmtEnumFields->dwNumStaticFields - bmtEnumFields->dwNumThreadStaticFields;
4576     for (DWORD i = bmtEnumFields->dwNumInstanceFields; i < nFirstThreadStaticFieldIndex; i++)
4577     {
4578         FieldDesc * pFD = &pFieldDescList[i];
4579         _ASSERTE(pFD->IsStatic());
4580
4581         if (pFD->IsRVA() && pFD->IsByValue())
4582         {
4583             _ASSERTE(pByValueClassCache[i] != NULL);
4584
4585             if (IsSelfRef(pByValueClassCache[i]))
4586             {
4587                 DWORD rva;
4588                 IfFailThrow(GetMDImport()->GetFieldRVA(pFD->GetMemberDef(), &rva));
4589             }
4590         }
4591     }
4592 } // MethodTableBuilder::VerifySelfReferencingStaticValueTypeFields_WithRVA
4593
4594 //*******************************************************************************
4595 // Returns true if hEnclosingTypeCandidate encloses, at any arbitrary depth,
4596 // hNestedTypeCandidate; returns false otherwise.
4597
4598 bool MethodTableBuilder::IsEnclosingNestedTypePair(
4599     bmtTypeHandle hEnclosingTypeCandidate,
4600     bmtTypeHandle hNestedTypeCandidate)
4601 {
4602     STANDARD_VM_CONTRACT;
4603
4604     CONSISTENCY_CHECK(!hEnclosingTypeCandidate.IsNull());
4605     CONSISTENCY_CHECK(!hNestedTypeCandidate.IsNull());
4606     CONSISTENCY_CHECK(!bmtTypeHandle::Equal(hEnclosingTypeCandidate, hNestedTypeCandidate));
4607
4608     Module * pModule = hEnclosingTypeCandidate.GetModule();
4609
4610     if (pModule != hNestedTypeCandidate.GetModule())
4611     {   // If the modules aren't the same, then there's no way
4612         // hBase could be an enclosing type of hChild. We make
4613         // this check early so that the code can deal with only
4614         // one Module and IMDInternalImport instance and can avoid
4615         // extra checks.
4616         return false;
4617     }
4618
4619     IMDInternalImport * pMDImport = pModule->GetMDImport();
4620
4621     mdTypeDef tkEncl = hEnclosingTypeCandidate.GetTypeDefToken();
4622     mdTypeDef tkNest = hNestedTypeCandidate.GetTypeDefToken();
4623
4624     while (tkEncl != tkNest)
4625     {   // Do this using the metadata APIs because MethodTableBuilder does
4626         // not construct type representations for enclosing type chains.
4627         if (FAILED(pModule->m_pEnclosingTypeMap->GetEnclosingTypeNoThrow(tkNest, &tkNest, pMDImport)))
4628         {   // tokNest is not a nested type.
4629             return false;
4630         }
4631     }
4632
4633     // tkNest's enclosing type is tkEncl, so we've shown that
4634     // hEnclosingTypeCandidate encloses hNestedTypeCandidate
4635     return true;
4636 }
4637
4638 //*******************************************************************************
4639 // Given an arbitrary nesting+subclassing pattern like this:
4640 //
4641 // class C1 {
4642 //     private virtual void Foo() { ... }
4643 //     class C2 : C1 {
4644 //       ...
4645 //         class CN : CN-1 {
4646 //             private override void Foo() { ... }
4647 //         }
4648 //       ...
4649 //     }
4650 // }
4651 //
4652 // this method will return true, where hChild == N and hBase == C1
4653 //
4654 // Note that there is no requirement that a type derive from its immediately
4655 // enclosing type, but can skip a level, such as this example:
4656 //
4657 // class A
4658 // {
4659 //     private virtual void Foo() { }
4660 //     public class B
4661 //     {
4662 //         public class C : A
4663 //         {
4664 //             private override void Foo() { }
4665 //         }
4666 //     }
4667 // }
4668 //
4669 // NOTE: IMPORTANT: This code assumes that hBase is indeed a base type of hChild,
4670 //                  and behaviour is undefined if this is not the case.
4671
4672 bool MethodTableBuilder::IsBaseTypeAlsoEnclosingType(
4673     bmtTypeHandle hBase,
4674     bmtTypeHandle hChild)
4675 {
4676     STANDARD_VM_CONTRACT;
4677
4678     CONSISTENCY_CHECK(!hBase.IsNull());
4679     CONSISTENCY_CHECK(!hChild.IsNull());
4680     CONSISTENCY_CHECK(!bmtTypeHandle::Equal(hBase, hChild));
4681
4682     // The idea of this algorithm is that if we climb the inheritance chain
4683     // starting at hChild then we'll eventually hit hBase. If we check that
4684     // for every (hParent, hChild) pair in the chain that hParent encloses
4685     // hChild, then we've shown that hBase encloses hChild.
4686
4687     while (!bmtTypeHandle::Equal(hBase, hChild))
4688     {
4689         CONSISTENCY_CHECK(!hChild.GetParentType().IsNull());
4690         bmtTypeHandle hParent(hChild.GetParentType());
4691
4692         if (!IsEnclosingNestedTypePair(hParent, hChild))
4693         {   // First, the parent type must enclose the child type.
4694             // If this is not the case we fail immediately.
4695             return false;
4696         }
4697
4698         // Move up one in the inheritance chain, and try again.
4699         hChild = hParent;
4700     }
4701
4702     // If the loop worked itself from the original hChild all the way
4703     // up to hBase, then we know that for every (hParent, hChild)
4704     // pair in the chain that hParent enclosed hChild, and so we know
4705     // that hBase encloses the original hChild
4706     return true;
4707 }
4708
4709 //*******************************************************************************
4710 BOOL MethodTableBuilder::TestOverrideForAccessibility(
4711     bmtMethodHandle hParentMethod,
4712     bmtTypeHandle   hChildType)
4713 {
4714     STANDARD_VM_CONTRACT;
4715
4716     bmtTypeHandle hParentType(hParentMethod.GetOwningType());
4717
4718     Module * pParentModule = hParentType.GetModule();
4719     Module * pChildModule = hChildType.GetModule();
4720
4721     Assembly * pParentAssembly = pParentModule->GetAssembly();
4722     Assembly * pChildAssembly = pChildModule->GetAssembly();
4723
4724     BOOL isSameAssembly = (pChildAssembly == pParentAssembly);
4725
4726     DWORD dwParentAttrs = hParentMethod.GetDeclAttrs();
4727
4728     // AKA "strict bit". This means that overridability is tightly bound to accessibility.
4729     if (IsMdCheckAccessOnOverride(dwParentAttrs))
4730     {
4731         // Same Assembly
4732         if (isSameAssembly || pParentAssembly->GrantsFriendAccessTo(pChildAssembly, hParentMethod.GetMethodDesc())
4733             || pChildAssembly->IgnoresAccessChecksTo(pParentAssembly))
4734         {
4735             // Can always override any method that has accessibility greater than mdPrivate
4736             if ((dwParentAttrs & mdMemberAccessMask) > mdPrivate)
4737             {   // Fall through
4738             }
4739             // Generally, types cannot override inherited mdPrivate methods, except:
4740             // Types can access enclosing type's private members, so it can
4741             // override them if the nested type extends its enclosing type.
4742             else if ((dwParentAttrs & mdMemberAccessMask) == mdPrivate &&
4743                      IsBaseTypeAlsoEnclosingType(hParentType, hChildType))
4744             {   // Fall through
4745             }
4746             else
4747             {
4748                 return FALSE;
4749             }
4750         }
4751         // Cross-Assembly
4752         else
4753         {
4754             // If the method marks itself as check visibility the method must be
4755             // public, FamORAssem, or family
4756             if((dwParentAttrs & mdMemberAccessMask) <= mdAssem)
4757             {
4758                 return FALSE;
4759             }
4760         }
4761     }
4762     return TRUE;
4763 }
4764
4765 //*******************************************************************************
4766 VOID MethodTableBuilder::TestOverRide(bmtMethodHandle hParentMethod,
4767                                       bmtMethodHandle hChildMethod)
4768 {
4769     CONTRACTL {
4770         STANDARD_VM_CHECK;
4771         PRECONDITION(IsMdVirtual(hParentMethod.GetDeclAttrs()));
4772         PRECONDITION(IsMdVirtual(hChildMethod.GetDeclAttrs()));
4773     } CONTRACTL_END;
4774
4775     DWORD dwAttrs = hChildMethod.GetDeclAttrs();
4776     DWORD dwParentAttrs = hParentMethod.GetDeclAttrs();
4777
4778     Module *pModule = hChildMethod.GetOwningType().GetModule();
4779     Module *pParentModule = hParentMethod.GetOwningType().GetModule();
4780
4781     Assembly *pAssembly = pModule->GetAssembly();
4782     Assembly *pParentAssembly = pParentModule->GetAssembly();
4783
4784     BOOL isSameModule = (pModule == pParentModule);
4785     BOOL isSameAssembly = (pAssembly == pParentAssembly);
4786
4787     if (!TestOverrideForAccessibility(hParentMethod, hChildMethod.GetOwningType()))
4788     {
4789         BuildMethodTableThrowException(IDS_CLASSLOAD_MI_ACCESS_FAILURE, hChildMethod.GetMethodSignature().GetToken());
4790     }
4791
4792     //
4793     // Refer to Partition II, 9.3.3 for more information on what is permitted.
4794     //
4795
4796     enum WIDENING_STATUS
4797     {
4798         e_NO,       // NO
4799         e_YES,      // YES
4800         e_SA,       // YES, but only when same assembly
4801         e_NSA,      // YES, but only when NOT same assembly
4802         e_SM,       // YES, but only when same module
4803     };
4804
4805     static_assert_no_msg(mdPrivateScope == 0x00);
4806     static_assert_no_msg(mdPrivate      == 0x01);
4807     static_assert_no_msg(mdFamANDAssem  == 0x02);
4808     static_assert_no_msg(mdAssem        == 0x03);
4809     static_assert_no_msg(mdFamily       == 0x04);
4810     static_assert_no_msg(mdFamORAssem   == 0x05);
4811     static_assert_no_msg(mdPublic       == 0x06);
4812
4813     static const DWORD dwCount = mdPublic - mdPrivateScope + 1;
4814     static const WIDENING_STATUS rgWideningTable[dwCount][dwCount] =
4815
4816     //               |        Base type
4817     // Subtype       |        mdPrivateScope  mdPrivate   mdFamANDAssem   mdAssem     mdFamily    mdFamORAssem    mdPublic
4818     // --------------+-------------------------------------------------------------------------------------------------------
4819     /*mdPrivateScope | */ { { e_SM,           e_NO,       e_NO,           e_NO,       e_NO,       e_NO,           e_NO    },
4820     /*mdPrivate      | */   { e_SM,           e_YES,      e_NO,           e_NO,       e_NO,       e_NO,           e_NO    },
4821     /*mdFamANDAssem  | */   { e_SM,           e_YES,      e_SA,           e_NO,       e_NO,       e_NO,           e_NO    },
4822     /*mdAssem        | */   { e_SM,           e_YES,      e_SA,           e_SA,       e_NO,       e_NO,           e_NO    },
4823     /*mdFamily       | */   { e_SM,           e_YES,      e_YES,          e_NO,       e_YES,      e_NSA,          e_NO    },
4824     /*mdFamORAssem   | */   { e_SM,           e_YES,      e_YES,          e_SA,       e_YES,      e_YES,          e_NO    },
4825     /*mdPublic       | */   { e_SM,           e_YES,      e_YES,          e_YES,      e_YES,      e_YES,          e_YES   } };
4826
4827     DWORD idxParent = (dwParentAttrs & mdMemberAccessMask) - mdPrivateScope;
4828     DWORD idxMember = (dwAttrs & mdMemberAccessMask) - mdPrivateScope;
4829     CONSISTENCY_CHECK(idxParent < dwCount);
4830     CONSISTENCY_CHECK(idxMember < dwCount);
4831
4832     WIDENING_STATUS entry = rgWideningTable[idxMember][idxParent];
4833
4834     if (entry == e_NO ||
4835         (entry == e_SA && !isSameAssembly && !pParentAssembly->GrantsFriendAccessTo(pAssembly, hParentMethod.GetMethodDesc())
4836          && !pAssembly->IgnoresAccessChecksTo(pParentAssembly)) ||
4837         (entry == e_NSA && isSameAssembly) ||
4838         (entry == e_SM && !isSameModule)
4839        )
4840     {
4841         BuildMethodTableThrowException(IDS_CLASSLOAD_REDUCEACCESS, hChildMethod.GetMethodSignature().GetToken());
4842     }
4843
4844     return;
4845 }
4846
4847 //*******************************************************************************
4848 VOID MethodTableBuilder::TestMethodImpl(
4849     bmtMethodHandle hDeclMethod,
4850     bmtMethodHandle hImplMethod)
4851 {
4852     CONTRACTL
4853     {
4854         STANDARD_VM_CHECK;
4855         PRECONDITION(!hDeclMethod.IsNull());
4856         PRECONDITION(!hImplMethod.IsNull());
4857     }
4858     CONTRACTL_END
4859
4860     Module * pDeclModule = hDeclMethod.GetOwningType().GetModule();
4861     Module * pImplModule = hImplMethod.GetOwningType().GetModule();
4862
4863     mdTypeDef tokDecl = hDeclMethod.GetMethodSignature().GetToken();
4864     mdTypeDef tokImpl = hImplMethod.GetMethodSignature().GetToken();
4865
4866     BOOL isSameModule = pDeclModule->Equals(pImplModule);
4867
4868     IMDInternalImport *pIMDDecl = pDeclModule->GetMDImport();
4869     IMDInternalImport *pIMDImpl = pImplModule->GetMDImport();
4870
4871     DWORD dwDeclAttrs;
4872     if (FAILED(pIMDDecl->GetMethodDefProps(tokDecl, &dwDeclAttrs)))
4873     {
4874         BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
4875     }
4876     DWORD dwImplAttrs;
4877     if (FAILED(pIMDImpl->GetMethodDefProps(tokImpl, &dwImplAttrs)))
4878     {
4879         BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
4880     }
4881
4882     HRESULT hr = COR_E_TYPELOAD;
4883
4884     if (!IsMdVirtual(dwDeclAttrs))
4885     {
4886         BuildMethodTableThrowException(IDS_CLASSLOAD_MI_NONVIRTUAL_DECL);
4887     }
4888     if (!!IsMdVirtual(dwImplAttrs) != !!IsMdAbstract(dwImplAttrs) && IsMdStatic(dwImplAttrs))
4889     {
4890         BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MUSTBEVIRTUAL);
4891     }
4892     if (!IsMdVirtual(dwImplAttrs) && !IsMdStatic(dwImplAttrs))
4893     {
4894         BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MUSTBEVIRTUAL);
4895     }
4896     // Virtual methods on classes/valuetypes cannot be static
4897     if (IsMdStatic(dwDeclAttrs) && !hDeclMethod.GetOwningType().IsInterface())
4898     {
4899         BuildMethodTableThrowException(IDS_CLASSLOAD_STATICVIRTUAL);
4900     }
4901     if ((!!IsMdStatic(dwImplAttrs)) != (!!IsMdStatic(dwDeclAttrs)))
4902     {
4903         BuildMethodTableThrowException(IDS_CLASSLOAD_STATICVIRTUAL);
4904     }
4905     if (IsMdFinal(dwDeclAttrs))
4906     {
4907         BuildMethodTableThrowException(IDS_CLASSLOAD_MI_FINAL_DECL);
4908     }
4909
4910     // Non-static interface method body that has methodimpl should always be final
4911     if (IsInterface() && !IsMdStatic(dwDeclAttrs) && !IsMdFinal(dwImplAttrs))
4912     {
4913         BuildMethodTableThrowException(IDS_CLASSLOAD_MI_FINAL_IMPL);
4914     }
4915
4916     // Since MethodImpl's do not affect the visibility of the Decl method, there's
4917     // no need to check.
4918
4919     // If Decl's parent is other than this class, Decl must not be private
4920     mdTypeDef tkImplParent = mdTypeDefNil;
4921     mdTypeDef tkDeclParent = mdTypeDefNil;
4922
4923     if (FAILED(hr = pIMDDecl->GetParentToken(tokDecl, &tkDeclParent)))
4924     {
4925         BuildMethodTableThrowException(hr, *bmtError);
4926     }
4927     if (FAILED(hr = pIMDImpl->GetParentToken(tokImpl, &tkImplParent)))
4928     {
4929         BuildMethodTableThrowException(hr, *bmtError);
4930     }
4931
4932     // Make sure that we test for accessibility restrictions only if the decl is
4933     // not within our own type, as we are allowed to methodImpl a private with the
4934     // strict bit set if it is in our own type.
4935     if (!isSameModule || tkDeclParent != tkImplParent)
4936     {
4937         if (!TestOverrideForAccessibility(hDeclMethod, hImplMethod.GetOwningType()))
4938         {
4939             BuildMethodTableThrowException(IDS_CLASSLOAD_MI_ACCESS_FAILURE, tokImpl);
4940         }
4941
4942         // Decl's parent must not be tdSealed
4943         mdToken tkGrandParentDummyVar;
4944         DWORD dwDeclTypeAttrs;
4945         if (FAILED(hr = pIMDDecl->GetTypeDefProps(tkDeclParent, &dwDeclTypeAttrs, &tkGrandParentDummyVar)))
4946         {
4947             BuildMethodTableThrowException(hr, *bmtError);
4948         }
4949         if (IsTdSealed(dwDeclTypeAttrs))
4950         {
4951             BuildMethodTableThrowException(IDS_CLASSLOAD_MI_SEALED_DECL);
4952         }
4953     }
4954
4955     return;
4956 }
4957
4958
4959 //*******************************************************************************
4960 //
4961 // Used by BuildMethodTable
4962 //
4963 VOID
4964 MethodTableBuilder::ValidateMethods()
4965 {
4966     CONTRACTL
4967     {
4968         STANDARD_VM_CHECK;
4969
4970         PRECONDITION(CheckPointer(this));
4971         PRECONDITION(CheckPointer(bmtInternal));
4972         PRECONDITION(CheckPointer(bmtMetaData));
4973         PRECONDITION(CheckPointer(bmtError));
4974         PRECONDITION(CheckPointer(bmtProp));
4975         PRECONDITION(CheckPointer(bmtInterface));
4976         PRECONDITION(CheckPointer(bmtParent));
4977         PRECONDITION(CheckPointer(bmtMFDescs));
4978         PRECONDITION(CheckPointer(bmtEnumFields));
4979         PRECONDITION(CheckPointer(bmtMethodImpl));
4980         PRECONDITION(CheckPointer(bmtVT));
4981     }
4982     CONTRACTL_END;
4983
4984     // Used to keep track of located default and type constructors.
4985     CONSISTENCY_CHECK(bmtVT->pCCtor == NULL);
4986     CONSISTENCY_CHECK(bmtVT->pDefaultCtor == NULL);
4987
4988     // Fetch the hard-coded signatures for the type constructor and the
4989     // default constructor and create MethodSignature objects for both at
4990     // the method level so this does not happen for every specialname
4991     // method.
4992
4993     Signature sig;
4994
4995     sig = CoreLibBinder::GetSignature(&gsig_SM_RetVoid);
4996
4997     MethodSignature cctorSig(CoreLibBinder::GetModule(),
4998                              COR_CCTOR_METHOD_NAME,
4999                              sig.GetRawSig(), sig.GetRawSigLen());
5000
5001     sig = CoreLibBinder::GetSignature(&gsig_IM_RetVoid);
5002
5003     MethodSignature defaultCtorSig(CoreLibBinder::GetModule(),
5004                                    COR_CTOR_METHOD_NAME,
5005                                    sig.GetRawSig(), sig.GetRawSigLen());
5006
5007     Module * pModule = GetModule();
5008     DeclaredMethodIterator it(*this);
5009     while (it.Next())
5010     {
5011         if (IsMdRTSpecialName(it.Attrs()))
5012         {
5013             if (IsMdVirtual(it.Attrs()))
5014             {   // Virtual specialname methods are illegal
5015                 BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
5016             }
5017
5018             // Constructors (.ctor) and class initialisers (.cctor) are special
5019             const MethodSignature &curSig(it->GetMethodSignature());
5020
5021             if (IsMdStatic(it.Attrs()))
5022             {   // The only rtSpecialName static method allowed is the .cctor
5023                 if (!curSig.ExactlyEqual(cctorSig))
5024                 {   // Bad method
5025                     BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
5026                 }
5027
5028                 // Remember it for later
5029                 bmtVT->pCCtor = *it;
5030             }
5031             else
5032             {
5033                 if(!MethodSignature::NamesEqual(curSig, defaultCtorSig))
5034                 {   // The only rtSpecialName instance methods allowed are .ctors
5035                     BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
5036                 }
5037
5038                 // .ctor must return void
5039                 MetaSig methodMetaSig(curSig.GetSignature(),
5040                                         static_cast<DWORD>(curSig.GetSignatureLength()),
5041                                         curSig.GetModule(),
5042                                         NULL);
5043
5044                 if (methodMetaSig.GetReturnType() != ELEMENT_TYPE_VOID)
5045                 {   // All constructors must have a void return type
5046                     BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
5047                 }
5048
5049                 // See if this is a default constructor.  If so, remember it for later.
5050                 if (curSig.ExactlyEqual(defaultCtorSig))
5051                 {
5052                     bmtVT->pDefaultCtor = *it;
5053                 }
5054             }
5055         }
5056
5057         // Make sure that fcalls have a 0 rva.  This is assumed by the prejit fixup logic
5058         if (it.MethodType() == mcFCall && it.RVA() != 0)
5059         {
5060             BuildMethodTableThrowException(BFA_ECALLS_MUST_HAVE_ZERO_RVA, it.Token());
5061         }
5062
5063         // check for proper use of the Managed and native flags
5064         if (IsMiManaged(it.ImplFlags()))
5065         {
5066             if (IsMiIL(it.ImplFlags()) || IsMiRuntime(it.ImplFlags())) // IsMiOPTIL(it.ImplFlags()) no longer supported
5067             {
5068                 // No need to set code address, pre stub used automatically.
5069             }
5070             else
5071             {
5072                 if (IsMiNative(it.ImplFlags()))
5073                 {
5074                     // For now simply disallow managed native code if you turn this on you have to at least
5075                     // insure that we have SkipVerificationPermission or equivalent
5076                     BuildMethodTableThrowException(BFA_MANAGED_NATIVE_NYI, it.Token());
5077                 }
5078                 else
5079                 {
5080                     BuildMethodTableThrowException(BFA_BAD_IMPL_FLAGS, it.Token());
5081                 }
5082             }
5083         }
5084         else
5085         {
5086             if (IsMiNative(it.ImplFlags()) && IsGlobalClass())
5087             {
5088                 // global function unmanaged entrypoint via IJW thunk was handled
5089                 // above.
5090             }
5091             else
5092             {
5093                 BuildMethodTableThrowException(IDS_CLASSLOAD_BAD_UNMANAGED_RVA, it.Token());
5094             }
5095             if (it.MethodType() != mcNDirect)
5096             {
5097                 BuildMethodTableThrowException(BFA_BAD_UNMANAGED_ENTRY_POINT);
5098             }
5099         }
5100
5101         // Vararg methods are not allowed inside generic classes
5102         // and nor can they be generic methods.
5103         if (bmtGenerics->GetNumGenericArgs() > 0 || (it.MethodType() == mcInstantiated) )
5104         {
5105             DWORD cMemberSignature;
5106             PCCOR_SIGNATURE pMemberSignature = it.GetSig(&cMemberSignature);
5107             // We've been trying to avoid asking for the signature - now we need it
5108             if (pMemberSignature == NULL)
5109             {
5110                 pMemberSignature = it.GetSig(&cMemberSignature);
5111             }
5112
5113             if (MetaSig::IsVarArg(Signature(pMemberSignature, cMemberSignature)))
5114             {
5115                 BuildMethodTableThrowException(BFA_GENCODE_NOT_BE_VARARG);
5116             }
5117         }
5118
5119         if (IsMdVirtual(it.Attrs()) && IsMdPublic(it.Attrs()) && it.Name() == NULL)
5120         {
5121             BuildMethodTableThrowException(IDS_CLASSLOAD_NOMETHOD_NAME);
5122         }
5123
5124         if (it.IsMethodImpl())
5125         {
5126             if (!IsMdVirtual(it.Attrs()) && !IsMdStatic(it.Attrs()))
5127             {
5128                 // Non-virtual methods may only participate in a methodImpl pair when
5129                 // they are static and they implement a virtual static interface method.
5130                 BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MUSTBEVIRTUAL, it.Token());
5131             }
5132         }
5133
5134         // Virtual static methods are only allowed on interfaces and they must be abstract.
5135         if (IsMdStatic(it.Attrs()) && IsMdVirtual(it.Attrs()))
5136         {
5137             if (!IsInterface())
5138             {
5139                 BuildMethodTableThrowException(IDS_CLASSLOAD_STATICVIRTUAL, it.Token());
5140             }
5141         }
5142     }
5143 }
5144
5145 //*******************************************************************************
5146 // Essentially, this is a helper method that combines calls to InitMethodDesc and
5147 // SetSecurityFlagsOnMethod. It then assigns the newly initialized MethodDesc to
5148 // the bmtMDMethod.
5149 VOID
5150 MethodTableBuilder::InitNewMethodDesc(
5151     bmtMDMethod * pMethod,
5152     MethodDesc * pNewMD)
5153 {
5154     STANDARD_VM_CONTRACT;
5155
5156     //
5157     // First, set all flags that control layout of optional slots
5158     //
5159     pNewMD->SetClassification(pMethod->GetMethodType());
5160
5161     if (pMethod->GetMethodImplType() == METHOD_IMPL)
5162         pNewMD->SetHasMethodImplSlot();
5163
5164     if (pMethod->GetSlotIndex() >= bmtVT->cVtableSlots)
5165         pNewMD->SetHasNonVtableSlot();
5166
5167     if (NeedsNativeCodeSlot(pMethod))
5168         pNewMD->SetHasNativeCodeSlot();
5169
5170     // Now we know the classification we can allocate the correct type of
5171     // method desc and perform any classification specific initialization.
5172
5173     LPCSTR pName = pMethod->GetMethodSignature().GetName();
5174     if (pName == NULL)
5175     {
5176         if (FAILED(GetMDImport()->GetNameOfMethodDef(pMethod->GetMethodSignature().GetToken(), &pName)))
5177         {
5178             BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
5179         }
5180     }
5181
5182 #ifdef _DEBUG
5183     LPCUTF8 pszDebugMethodName;
5184     if (FAILED(GetMDImport()->GetNameOfMethodDef(pMethod->GetMethodSignature().GetToken(), &pszDebugMethodName)))
5185     {
5186         pszDebugMethodName = "Invalid MethodDef record";
5187     }
5188     S_SIZE_T safeLen = S_SIZE_T(strlen(pszDebugMethodName)) + S_SIZE_T(1);
5189     if(safeLen.IsOverflow())
5190         COMPlusThrowHR(COR_E_OVERFLOW);
5191
5192     size_t len = safeLen.Value();
5193     LPCUTF8 pszDebugMethodNameCopy = (char*) AllocateFromLowFrequencyHeap(safeLen);
5194     strcpy_s((char *) pszDebugMethodNameCopy, len, pszDebugMethodName);
5195 #endif // _DEBUG
5196
5197     // Do the init specific to each classification of MethodDesc & assign some common fields
5198     InitMethodDesc(pNewMD,
5199                    pMethod->GetMethodType(),
5200                    pMethod->GetMethodSignature().GetToken(),
5201                    pMethod->GetImplAttrs(),
5202                    pMethod->GetDeclAttrs(),
5203                    FALSE,    // fEnC
5204                    pMethod->GetRVA(),
5205                    GetMDImport(),
5206                    pName
5207                    COMMA_INDEBUG(pszDebugMethodNameCopy)
5208                    COMMA_INDEBUG(GetDebugClassName())
5209                    COMMA_INDEBUG("") // FIX this happens on global methods, give better info
5210                   );
5211
5212     pMethod->SetMethodDesc(pNewMD);
5213
5214     bmtRTMethod * pParentMethod = NULL;
5215
5216     if (HasParent())
5217     {
5218         SLOT_INDEX idx = pMethod->GetSlotIndex();
5219         CONSISTENCY_CHECK(idx != INVALID_SLOT_INDEX);
5220
5221         if (idx < GetParentMethodTable()->GetNumVirtuals())
5222         {
5223             pParentMethod = (*bmtParent->pSlotTable)[idx].Decl().AsRTMethod();
5224         }
5225     }
5226
5227     // Turn off inlining for any calls
5228     // that are marked in the metadata as not being inlineable.
5229     if(IsMiNoInlining(pMethod->GetImplAttrs()))
5230     {
5231         pNewMD->SetNotInline(true);
5232     }
5233
5234     // Check for methods marked as [Intrinsic]
5235     if (GetModule()->IsSystem())
5236     {
5237         if (bmtProp->fIsHardwareIntrinsic || (S_OK == GetCustomAttribute(pMethod->GetMethodSignature().GetToken(),
5238                                                     WellKnownAttribute::Intrinsic,
5239                                                     NULL,
5240                                                     NULL)))
5241         {
5242             pNewMD->SetIsIntrinsic();
5243         }
5244
5245     }
5246
5247     pNewMD->SetSlot(pMethod->GetSlotIndex());
5248 }
5249
5250 //*******************************************************************************
5251 // Determine vtable placement for each non-virtual in the class, while also
5252 // looking for default and type constructors.
5253 VOID
5254 MethodTableBuilder::PlaceNonVirtualMethods()
5255 {
5256     CONTRACTL
5257     {
5258         STANDARD_VM_CHECK;
5259
5260         PRECONDITION(CheckPointer(this));
5261         PRECONDITION(CheckPointer(bmtInternal));
5262         PRECONDITION(CheckPointer(bmtMetaData));
5263         PRECONDITION(CheckPointer(bmtError));
5264         PRECONDITION(CheckPointer(bmtProp));
5265         PRECONDITION(CheckPointer(bmtInterface));
5266         PRECONDITION(CheckPointer(bmtParent));
5267         PRECONDITION(CheckPointer(bmtMFDescs));
5268         PRECONDITION(CheckPointer(bmtEnumFields));
5269         PRECONDITION(CheckPointer(bmtMethodImpl));
5270         PRECONDITION(CheckPointer(bmtVT));
5271     }
5272     CONTRACTL_END;
5273
5274     INDEBUG(bmtVT->SealVirtualSlotSection();)
5275
5276     //
5277     // For each non-virtual method, place the method in the next available non-virtual method slot.
5278     //
5279
5280     // Place the cctor and default ctor first. code::MethodTableGetCCtorSlot and code:MethodTable::GetDefaultCtorSlot
5281     // depends on this.
5282     if (bmtVT->pCCtor != NULL)
5283     {
5284         if (!bmtVT->AddNonVirtualMethod(bmtVT->pCCtor))
5285             BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
5286     }
5287
5288     if (bmtVT->pDefaultCtor != NULL)
5289     {
5290         if (!bmtVT->AddNonVirtualMethod(bmtVT->pDefaultCtor))
5291             BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
5292     }
5293
5294     // We use slot during remoting and to map methods between generic instantiations
5295     // (see MethodTable::GetParallelMethodDesc). The current implementation
5296     // of this mechanism requires real slots.
5297     BOOL fCanHaveNonVtableSlots = (bmtGenerics->GetNumGenericArgs() == 0) && !IsInterface();
5298
5299     // Flag to avoid second pass when possible
5300     BOOL fHasNonVtableSlots = FALSE;
5301
5302     //
5303     // Place all methods that require real vtable slot first. This is necessary so
5304     // that they get consequitive slot numbers right after virtual slots.
5305     //
5306
5307     DeclaredMethodIterator it(*this);
5308     while (it.Next())
5309     {
5310         // Skip methods that are placed already
5311         if (it->GetSlotIndex() != INVALID_SLOT_INDEX)
5312             continue;
5313
5314 #ifdef _DEBUG
5315         if(GetHalfBakedClass()->m_fDebuggingClass && g_pConfig->ShouldBreakOnMethod(it.Name()))
5316             CONSISTENCY_CHECK_MSGF(false, ("BreakOnMethodName: '%s' ", it.Name()));
5317 #endif // _DEBUG
5318
5319         if (!fCanHaveNonVtableSlots ||
5320             it->GetMethodType() == mcInstantiated)
5321         {
5322             // We use slot during remoting and to map methods between generic instantiations
5323             // (see MethodTable::GetParallelMethodDesc). The current implementation
5324             // of this mechanism requires real slots.
5325         }
5326         else
5327         {
5328             // This method does not need real vtable slot
5329             fHasNonVtableSlots = TRUE;
5330             continue;
5331         }
5332
5333         // This will update slot index in bmtMDMethod
5334         if (!bmtVT->AddNonVirtualMethod(*it))
5335             BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
5336     }
5337
5338     // Remeber last real vtable slot
5339     bmtVT->cVtableSlots = bmtVT->cTotalSlots;
5340
5341     // Are there any Non-vtable slots to place?
5342     if (!fHasNonVtableSlots)
5343         return;
5344
5345     //
5346     // Now, place the remaining methods. They will get non-vtable slot.
5347     //
5348
5349     DeclaredMethodIterator it2(*this);
5350     while (it2.Next())
5351     {
5352         // Skip methods that are placed already
5353         if (it2->GetSlotIndex() != INVALID_SLOT_INDEX)
5354             continue;
5355
5356         if (!bmtVT->AddNonVirtualMethod(*it2))
5357             BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
5358     }
5359
5360 }
5361
5362 //*******************************************************************************
5363 // Determine vtable placement for each virtual member in this class.
5364 VOID
5365 MethodTableBuilder::PlaceVirtualMethods()
5366 {
5367     CONTRACTL
5368     {
5369         STANDARD_VM_CHECK;
5370
5371         PRECONDITION(CheckPointer(this));
5372         PRECONDITION(CheckPointer(bmtInternal));
5373         PRECONDITION(CheckPointer(bmtMetaData));
5374         PRECONDITION(CheckPointer(bmtError));
5375         PRECONDITION(CheckPointer(bmtProp));
5376         PRECONDITION(CheckPointer(bmtInterface));
5377         PRECONDITION(CheckPointer(bmtParent));
5378         PRECONDITION(CheckPointer(bmtMFDescs));
5379         PRECONDITION(CheckPointer(bmtEnumFields));
5380         PRECONDITION(CheckPointer(bmtMethodImpl));
5381         PRECONDITION(CheckPointer(bmtVT));
5382     }
5383     CONTRACTL_END;
5384
5385 #ifdef _DEBUG
5386     LPCUTF8 pszDebugName, pszDebugNamespace;
5387     if (FAILED(GetMDImport()->GetNameOfTypeDef(GetCl(), &pszDebugName, &pszDebugNamespace)))
5388     {
5389         pszDebugName = pszDebugNamespace = "Invalid TypeDef record";
5390     }
5391 #endif // _DEBUG
5392
5393     //
5394     // For each virtual method
5395     //  - If the method is not declared as newslot, search all virtual methods in the parent
5396     //    type for an override candidate.
5397     //      - If such a candidate is found, test to see if the override is valid. If
5398     //        the override is not valid, throw TypeLoadException
5399     //  - If a candidate is found above, place the method in the inherited slot as both
5400     //    the Decl and the Impl.
5401     //  - Else, place the method in the next available empty vtable slot.
5402     //
5403
5404     DeclaredMethodIterator it(*this);
5405     while (it.Next())
5406     {
5407         if (!IsMdVirtual(it.Attrs()) || IsMdStatic(it.Attrs()))
5408         {   // Only processing declared virtual instance methods
5409             continue;
5410         }
5411
5412 #ifdef _DEBUG
5413         if(GetHalfBakedClass()->m_fDebuggingClass && g_pConfig->ShouldBreakOnMethod(it.Name()))
5414             CONSISTENCY_CHECK_MSGF(false, ("BreakOnMethodName: '%s' ", it.Name()));
5415 #endif // _DEBUG
5416
5417         // If this member is a method which overrides a parent method, it will be set to non-NULL
5418         bmtRTMethod * pParentMethod = NULL;
5419
5420         // Hash that a method with this name exists in this class
5421         // Note that ctors and static ctors are not added to the table
5422         BOOL fMethodConstraintsMatch = FALSE;
5423
5424         // If the member is marked with a new slot we do not need to find it in the parent
5425         if (HasParent() && !IsMdNewSlot(it.Attrs()))
5426         {
5427             // Attempt to find the method with this name and signature in the parent class.
5428             // This method may or may not create pParentMethodHash (if it does not already exist).
5429             // It also may or may not fill in pMemberSignature/cMemberSignature.
5430             // An error is only returned when we can not create the hash.
5431             // NOTE: This operation touches metadata
5432             pParentMethod = LoaderFindMethodInParentClass(
5433                 it->GetMethodSignature(), bmtProp->fNoSanityChecks ? NULL : &fMethodConstraintsMatch);
5434
5435             if (pParentMethod != NULL)
5436             {   // Found an override candidate
5437                 DWORD dwParentAttrs = pParentMethod->GetDeclAttrs();
5438
5439                 if (!IsMdVirtual(dwParentAttrs))
5440                 {   // Can't override a non-virtual methods
5441                     BuildMethodTableThrowException(BFA_NONVIRT_NO_SEARCH, it.Token());
5442                 }
5443
5444                 if(IsMdFinal(dwParentAttrs))
5445                 {   // Can't override a final methods
5446                     BuildMethodTableThrowException(IDS_CLASSLOAD_MI_FINAL_DECL, it.Token());
5447                 }
5448
5449                 if(!bmtProp->fNoSanityChecks)
5450                 {
5451                     TestOverRide(bmtMethodHandle(pParentMethod),
5452                                  bmtMethodHandle(*it));
5453
5454                     if (!fMethodConstraintsMatch)
5455                     {
5456                         BuildMethodTableThrowException(
5457                                 IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_IMPLICIT_OVERRIDE,
5458                                 it.Token());
5459                     }
5460                 }
5461             }
5462         }
5463
5464         // vtable method
5465         if (IsInterface())
5466         {
5467             CONSISTENCY_CHECK(pParentMethod == NULL);
5468             // Also sets new slot number on bmtRTMethod and MethodDesc
5469             if (!bmtVT->AddVirtualMethod(*it))
5470                 BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
5471         }
5472         else if (pParentMethod != NULL)
5473         {
5474             bmtVT->SetVirtualMethodOverride(pParentMethod->GetSlotIndex(), *it);
5475         }
5476         else
5477         {
5478             if (!bmtVT->AddVirtualMethod(*it))
5479                 BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
5480         }
5481     }
5482 }
5483
5484 // Given an interface map entry, and a name+signature, compute the method on the interface
5485 // that the name+signature corresponds to. Used by ProcessMethodImpls and ProcessInexactMethodImpls
5486 // Always returns the first match that it finds. Affects the ambiguities in code:#ProcessInexactMethodImpls_Ambiguities
5487 MethodTableBuilder::bmtMethodHandle
5488 MethodTableBuilder::FindDeclMethodOnInterfaceEntry(bmtInterfaceEntry *pItfEntry, MethodSignature &declSig, bool searchForStaticMethods)
5489 {
5490     STANDARD_VM_CONTRACT;
5491
5492     bmtMethodHandle declMethod;
5493
5494     bmtInterfaceEntry::InterfaceSlotIterator slotIt =
5495         pItfEntry->IterateInterfaceSlots(GetStackingAllocator(), searchForStaticMethods);
5496     // Check for exact match
5497     for (; !slotIt.AtEnd(); slotIt.Next())
5498     {
5499         bmtRTMethod * pCurDeclMethod = slotIt->Decl().AsRTMethod();
5500
5501         if (declSig.ExactlyEqual(pCurDeclMethod->GetMethodSignature().GetSignatureWithoutSubstitution()))
5502         {
5503             declMethod = slotIt->Decl();
5504             break;
5505         }
5506     }
5507     slotIt.ResetToStart();
5508
5509     // Check for equivalent match if exact match wasn't found
5510     if (declMethod.IsNull())
5511     {
5512         for (; !slotIt.AtEnd(); slotIt.Next())
5513         {
5514             bmtRTMethod * pCurDeclMethod = slotIt->Decl().AsRTMethod();
5515
5516             // Type Equivalence is forbidden in MethodImpl MemberRefs
5517             if (declSig.Equivalent(pCurDeclMethod->GetMethodSignature().GetSignatureWithoutSubstitution()))
5518             {
5519                 declMethod = slotIt->Decl();
5520                 break;
5521             }
5522         }
5523     }
5524
5525     return declMethod;
5526 }
5527
5528 //*******************************************************************************
5529 //
5530 // Used by BuildMethodTable
5531 // Process the list of inexact method impls generated during ProcessMethodImpls.
5532 // This list is used to cause a methodImpl to an interface to override
5533 // methods on several equivalent interfaces in the interface map. This logic is necessary
5534 // so that in the presence of an embedded interface the behavior appears to mimic
5535 // the behavior if the interface was not embedded.
5536 //
5537 // In particular, the logic here is to handle cases such as
5538 //
5539 //  Assembly A
5540 // [TypeIdentifier("x","y")]
5541 // interface I'
5542 // {  void Method(); }
5543 // interface IOther : I' {}
5544 //
5545 //  Assembly B
5546 // [TypeIdentifier("x","y")]
5547 // interface I
5548 // {  void Method(); }
5549 // class Test : I, IOther
5550 // {
5551 //     void I.Method()
5552 //     {}
5553 // }
5554 //
5555 // In this case, there is one method, and one methodimpl, but there are 2 interfaces on the class that both
5556 // require an implementation of their method. The correct semantic for type equivalence, is that any
5557 // methodimpl directly targeting a method on an interface must be respected, and if it also applies to a type
5558 // equivalent interface method, then if that method was not methodimpl'd directly, then the methodimpl should apply
5559 // there as well. The ProcessInexactMethodImpls function does this secondary MethodImpl mapping.
5560 //
5561 //#ProcessInexactMethodImpls_Ambiguities
5562 // In the presence of ambiguities, such as there are 3 equivalent interfaces implemented on a class and 2 methodimpls,
5563 // we will apply the 2 method impls exactly to appropriate interface methods, and arbitrarily pick one to apply to the
5564 // other interface. This is clearly ambiguous, but tricky to detect in the type loader efficiently, and should hopefully
5565 // not cause too many problems.
5566 //
5567 VOID
5568 MethodTableBuilder::ProcessInexactMethodImpls()
5569 {
5570     STANDARD_VM_CONTRACT;
5571
5572     if (bmtMethod->dwNumberInexactMethodImplCandidates == 0)
5573         return;
5574
5575     DeclaredMethodIterator it(*this);
5576     while (it.Next())
5577     {
5578         // Non-virtual methods cannot be classified as methodImpl - we should have thrown an
5579         // error before reaching this point.
5580         CONSISTENCY_CHECK(!(!IsMdVirtual(it.Attrs()) && it.IsMethodImpl()));
5581
5582         if (!IsMdVirtual(it.Attrs()))
5583         {   // Only virtual methods can participate in methodImpls
5584             continue;
5585         }
5586
5587         if(!it.IsMethodImpl())
5588         {
5589             // Skip methods which are not the bodies of MethodImpl specifications
5590             continue;
5591         }
5592
5593         // If this method serves as the BODY of a MethodImpl specification, then
5594         // we should iterate all the MethodImpl's for this class and see just how many
5595         // of them this method participates in as the BODY.
5596         for(DWORD m = 0; m < bmtMethod->dwNumberMethodImpls; m++)
5597         {
5598             // Inexact matching logic only works on MethodImpls that have been opted into inexactness by ProcessMethodImpls.
5599             if (!bmtMetaData->rgMethodImplTokens[m].fConsiderDuringInexactMethodImplProcessing)
5600             {
5601                 continue;
5602             }
5603
5604             // If the methodimpl we are working with does not match this method, continue to next methodimpl
5605             if(it.Token() != bmtMetaData->rgMethodImplTokens[m].methodBody)
5606             {
5607                 continue;
5608             }
5609
5610             bool fMatchFound = false;
5611
5612             LPCUTF8 szName = NULL;
5613             PCCOR_SIGNATURE pSig = NULL;
5614             ULONG cbSig;
5615
5616             mdToken mdDecl = bmtMetaData->rgMethodImplTokens[m].methodDecl;
5617
5618             if (TypeFromToken(mdDecl) == mdtMethodDef)
5619             {   // Different methods are aused to access MethodDef and MemberRef
5620                 // names and signatures.
5621                 if (FAILED(GetMDImport()->GetNameOfMethodDef(mdDecl, &szName)) ||
5622                     FAILED(GetMDImport()->GetSigOfMethodDef(mdDecl, &cbSig, &pSig)))
5623                 {
5624                     BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
5625                 }
5626             }
5627             else
5628             {
5629                 if (FAILED(GetMDImport()->GetNameAndSigOfMemberRef(mdDecl, &pSig, &cbSig, &szName)))
5630                 {
5631                     BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
5632                 }
5633             }
5634
5635             MethodSignature declSig(GetModule(), szName, pSig, cbSig, NULL);
5636             bmtInterfaceEntry * pItfEntry = NULL;
5637
5638             for (DWORD i = 0; i < bmtInterface->dwInterfaceMapSize; i++)
5639             {
5640                 if (bmtInterface->pInterfaceMap[i].GetInterfaceEquivalenceSet() != bmtMetaData->rgMethodImplTokens[m].interfaceEquivalenceSet)
5641                     continue;
5642
5643                 bmtMethodHandle declMethod;
5644                 pItfEntry = &bmtInterface->pInterfaceMap[i];
5645
5646                 // Search for declmethod on this interface
5647                 declMethod = FindDeclMethodOnInterfaceEntry(pItfEntry, declSig);
5648
5649                 // If we didn't find a match, continue on to next interface in the equivalence set
5650                 if (declMethod.IsNull())
5651                     continue;
5652
5653                 if (!IsMdVirtual(declMethod.GetDeclAttrs()))
5654                 {   // Make sure the decl is virtual
5655                     BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MUSTBEVIRTUAL, it.Token());
5656                 }
5657
5658                 fMatchFound = true;
5659
5660                 bool fPreexistingImplFound = false;
5661
5662                 // Check to ensure there isn't already a matching declMethod in the method impl list
5663                 for (DWORD iMethodImpl = 0; iMethodImpl < bmtMethodImpl->pIndex; iMethodImpl++)
5664                 {
5665                     if (bmtMethodImpl->GetDeclarationMethod(iMethodImpl) == declMethod)
5666                     {
5667                         fPreexistingImplFound = true;
5668                         break;
5669                     }
5670                 }
5671
5672                 // Search for other matches
5673                 if (fPreexistingImplFound)
5674                     continue;
5675
5676                 if (bmtMetaData->rgMethodImplTokens[m].fRequiresCovariantReturnTypeChecking)
5677                 {
5678                     it->GetMethodDesc()->SetRequiresCovariantReturnTypeChecking();
5679                 }
5680
5681                 // Otherwise, record the method impl discovery if the match is
5682                 bmtMethodImpl->AddMethodImpl(*it, declMethod, bmtMetaData->rgMethodImplTokens[m].methodDecl, GetStackingAllocator());
5683             }
5684
5685             if (!fMatchFound && bmtMetaData->rgMethodImplTokens[m].fThrowIfUnmatchedDuringInexactMethodImplProcessing)
5686             {
5687                 BuildMethodTableThrowException(IDS_CLASSLOAD_MI_DECLARATIONNOTFOUND, it.Token());
5688             }
5689         }
5690     }
5691 }
5692
5693 //*******************************************************************************
5694 //
5695 // Used by BuildMethodTable
5696 //
5697 VOID
5698 MethodTableBuilder::ProcessMethodImpls()
5699 {
5700     STANDARD_VM_CONTRACT;
5701
5702     if (bmtMetaData->fHasCovariantOverride)
5703     {
5704         GetHalfBakedClass()->SetHasCovariantOverride();
5705     }
5706     if (GetParentMethodTable() != NULL)
5707     {
5708         EEClass* parentClass = GetParentMethodTable()->GetClass();
5709         if (parentClass->HasCovariantOverride())
5710             GetHalfBakedClass()->SetHasCovariantOverride();
5711         if (parentClass->HasVTableMethodImpl())
5712             GetHalfBakedClass()->SetHasVTableMethodImpl();
5713     }
5714
5715     if (bmtMethod->dwNumberMethodImpls == 0)
5716         return;
5717
5718     HRESULT hr = S_OK;
5719
5720     DeclaredMethodIterator it(*this);
5721     while (it.Next())
5722     {
5723         bool isVirtualStaticOverride = it.IsMethodImpl() && IsMdStatic(it.Attrs()) &&
5724             !!IsMdVirtual(it.Attrs()) == !!IsMdAbstract(it.Attrs());
5725
5726         if (isVirtualStaticOverride && bmtProp->fNoSanityChecks)
5727         {
5728             // Non-virtual methods can only be classified as methodImpl when implementing
5729             // static virtual methods.
5730             CONSISTENCY_CHECK(IsMdStatic(it.Attrs()));
5731             continue;
5732         }
5733
5734         // If this method serves as the BODY of a MethodImpl specification, then
5735         // we should iterate all the MethodImpl's for this class and see just how many
5736         // of them this method participates in as the BODY.
5737         if(it.IsMethodImpl())
5738         {
5739             for(DWORD m = 0; m < bmtMethod->dwNumberMethodImpls; m++)
5740             {
5741                 if(it.Token() == bmtMetaData->rgMethodImplTokens[m].methodBody)
5742                 {
5743                     mdToken mdDecl = bmtMetaData->rgMethodImplTokens[m].methodDecl;
5744                     bmtMethodHandle declMethod;
5745
5746                     // Get the parent token for the decl method token
5747                     mdToken tkParent = mdTypeDefNil;
5748                     if (TypeFromToken(mdDecl) == mdtMethodDef || TypeFromToken(mdDecl) == mdtMemberRef)
5749                     {
5750                         if (FAILED(hr = GetMDImport()->GetParentToken(mdDecl,&tkParent)))
5751                         {
5752                             BuildMethodTableThrowException(hr, *bmtError);
5753                         }
5754                     }
5755
5756                     if (GetCl() == tkParent)
5757                     {   // The DECL has been declared within the class that we're currently building.
5758                         hr = S_OK;
5759
5760                         if(bmtError->pThrowable != NULL)
5761                         {
5762                             *(bmtError->pThrowable) = NULL;
5763                         }
5764
5765                         if(TypeFromToken(mdDecl) != mdtMethodDef)
5766                         {
5767                             if (FAILED(hr = FindMethodDeclarationForMethodImpl(
5768                                                 mdDecl, &mdDecl, TRUE)))
5769                             {
5770                                 BuildMethodTableThrowException(hr, *bmtError);
5771                             }
5772                         }
5773
5774                         CONSISTENCY_CHECK(TypeFromToken(mdDecl) == mdtMethodDef);
5775                         declMethod = bmtMethod->FindDeclaredMethodByToken(mdDecl);
5776                     }
5777                     else
5778                     {   // We can't call GetDescFromMemberDefOrRef here because this
5779                         // method depends on a fully-loaded type, including parent types,
5780                         // which is not always guaranteed. In particular, it requires that
5781                         // the instantiation dictionary be filled. The solution is the following:
5782                         //   1. Load the approximate type that the method belongs to.
5783                         //   2. Get or create the correct substitution for the type involved
5784                         //   3. Iterate the introduced methods on that type looking for a matching
5785                         //      method.
5786
5787                         LPCUTF8 szName = NULL;
5788                         PCCOR_SIGNATURE pSig = NULL;
5789                         ULONG cbSig;
5790                         if (TypeFromToken(mdDecl) == mdtMethodDef)
5791                         {   // Different methods are aused to access MethodDef and MemberRef
5792                             // names and signatures.
5793                             if (FAILED(GetMDImport()->GetNameOfMethodDef(mdDecl, &szName)) ||
5794                                 FAILED(GetMDImport()->GetSigOfMethodDef(mdDecl, &cbSig, &pSig)))
5795                             {
5796                                 BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
5797                             }
5798                         }
5799                         else
5800                         {
5801                             if (FAILED(GetMDImport()->GetNameAndSigOfMemberRef(mdDecl, &pSig, &cbSig, &szName)))
5802                             {
5803                                 BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
5804                             }
5805                         }
5806
5807                         Substitution *pDeclSubst = &bmtMetaData->pMethodDeclSubsts[m];
5808
5809                         MethodTable * pDeclMT = NULL;
5810                         MethodSignature declSig(GetModule(), szName, pSig, cbSig, NULL);
5811
5812                         {   // 1. Load the approximate type.
5813                             // Block for the LoadsTypeViolation.
5814                             CONTRACT_VIOLATION(LoadsTypeViolation);
5815                             pDeclMT = ClassLoader::LoadTypeDefOrRefOrSpecThrowing(
5816                                 GetModule(),
5817                                 tkParent,
5818                                 &bmtGenerics->typeContext,
5819                                 ClassLoader::ThrowIfNotFound,
5820                                 ClassLoader::PermitUninstDefOrRef,
5821                                 ClassLoader::LoadTypes,
5822                                 CLASS_LOAD_APPROXPARENTS,
5823                                 TRUE).GetMethodTable()->GetCanonicalMethodTable();
5824                         }
5825
5826                         {   // 2. Get or create the correct substitution
5827                             if (pDeclMT->IsInterface())
5828                             {
5829                                 // If the declaration method is a part of an interface, search through
5830                                 // the interface map to find the matching interface so we can provide
5831                                 // the correct substitution chain.
5832                                 bmtRTType *pDeclType = NULL;
5833
5834                                 bmtInterfaceEntry * pItfEntry = NULL;
5835                                 for (DWORD i = 0; i < bmtInterface->dwInterfaceMapSize; i++)
5836                                 {
5837                                     bmtRTType * pCurItf = bmtInterface->pInterfaceMap[i].GetInterfaceType();
5838                                     // Type Equivalence is not respected for this comparison as you can have multiple type equivalent interfaces on a class
5839                                     TokenPairList newVisited = TokenPairList::AdjustForTypeEquivalenceForbiddenScope(NULL);
5840                                     if (MetaSig::CompareTypeDefsUnderSubstitutions(
5841                                         pCurItf->GetMethodTable(),      pDeclMT,
5842                                         &pCurItf->GetSubstitution(),    pDeclSubst,
5843                                         &newVisited))
5844                                     {
5845                                         pItfEntry = &bmtInterface->pInterfaceMap[i];
5846                                         pDeclType = pCurItf;
5847                                         break;
5848                                     }
5849                                 }
5850
5851                                 if (IsInterface())
5852                                 {
5853                                     if (pDeclType == NULL)
5854                                     {
5855                                         // Interface is not implemented by this type.
5856                                         BuildMethodTableThrowException(IDS_CLASSLOAD_MI_NOTIMPLEMENTED, it.Token());
5857                                     }
5858                                 }
5859                                 else
5860                                 {
5861                                     if (pDeclType == NULL)
5862                                     {
5863                                         DWORD equivalenceSet = 0;
5864
5865                                         for (DWORD i = 0; i < bmtInterface->dwInterfaceMapSize; i++)
5866                                         {
5867                                             bmtRTType * pCurItf = bmtInterface->pInterfaceMap[i].GetInterfaceType();
5868                                             // Type Equivalence is respected for this comparison as we just need to find an
5869                                             // equivalent interface, the particular interface is unimportant
5870                                             if (MetaSig::CompareTypeDefsUnderSubstitutions(
5871                                                 pCurItf->GetMethodTable(), pDeclMT,
5872                                                 &pCurItf->GetSubstitution(), pDeclSubst,
5873                                                 NULL))
5874                                             {
5875                                                 equivalenceSet = bmtInterface->pInterfaceMap[i].GetInterfaceEquivalenceSet();
5876                                                 pItfEntry = &bmtInterface->pInterfaceMap[i];
5877                                                 break;
5878                                             }
5879                                         }
5880
5881                                         if (equivalenceSet == 0)
5882                                         {
5883                                             // Interface is not implemented by this type.
5884                                             BuildMethodTableThrowException(IDS_CLASSLOAD_MI_NOTIMPLEMENTED, it.Token());
5885                                         }
5886
5887                                         // Interface is not implemented by this type exactly. We need to consider this MethodImpl on non exact interface matches,
5888                                         // as the only match may be one of the non-exact matches
5889                                         bmtMetaData->rgMethodImplTokens[m].fConsiderDuringInexactMethodImplProcessing = true;
5890                                         bmtMetaData->rgMethodImplTokens[m].fThrowIfUnmatchedDuringInexactMethodImplProcessing = true;
5891                                         bmtMetaData->rgMethodImplTokens[m].interfaceEquivalenceSet = equivalenceSet;
5892                                         bmtMethod->dwNumberInexactMethodImplCandidates++;
5893                                         continue; // Move on to other MethodImpls
5894                                     }
5895                                     else
5896                                     {
5897                                         // This method impl may need to match other methods during inexact processing
5898                                         if (pItfEntry->InEquivalenceSetWithMultipleEntries())
5899                                         {
5900                                             bmtMetaData->rgMethodImplTokens[m].fConsiderDuringInexactMethodImplProcessing = true;
5901                                             bmtMetaData->rgMethodImplTokens[m].fThrowIfUnmatchedDuringInexactMethodImplProcessing = false;
5902                                             bmtMetaData->rgMethodImplTokens[m].interfaceEquivalenceSet = pItfEntry->GetInterfaceEquivalenceSet();
5903                                             bmtMethod->dwNumberInexactMethodImplCandidates++;
5904                                         }
5905                                     }
5906                                 }
5907
5908                                 // 3. Find the matching method.
5909                                 declMethod = FindDeclMethodOnInterfaceEntry(pItfEntry, declSig, isVirtualStaticOverride); // Search for statics when the impl is non-virtual
5910                             }
5911                             else
5912                             {
5913                                 GetHalfBakedClass()->SetHasVTableMethodImpl();
5914                                 declMethod = FindDeclMethodOnClassInHierarchy(it, pDeclMT, declSig);
5915                             }
5916
5917                             if (declMethod.IsNull())
5918                             {   // Would prefer to let this fall out to the BuildMethodTableThrowException
5919                                 // below, but due to v2.0 and earlier behaviour throwing a MissingMethodException,
5920                                 // primarily because this code used to be a simple call to
5921                                 // MemberLoader::GetDescFromMemberDefOrRef (see above for reason why),
5922                                 // we must continue to do the same.
5923                                 MemberLoader::ThrowMissingMethodException(
5924                                     pDeclMT,
5925                                     declSig.GetName(),
5926                                     declSig.GetModule(),
5927                                     declSig.GetSignature(),
5928                                     static_cast<DWORD>(declSig.GetSignatureLength()),
5929                                     &bmtGenerics->typeContext);
5930                             }
5931                         }
5932                     }
5933
5934                     if (declMethod.IsNull())
5935                     {   // Method not found, throw.
5936                         BuildMethodTableThrowException(IDS_CLASSLOAD_MI_DECLARATIONNOTFOUND, it.Token());
5937                     }
5938
5939                     if (!IsMdVirtual(declMethod.GetDeclAttrs()))
5940                     {   // Make sure the decl is virtual
5941                         BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MUSTBEVIRTUAL, it.Token());
5942                     }
5943
5944                     if (isVirtualStaticOverride)
5945                     {
5946                         // Non-virtual methods can only be classified as methodImpl when implementing
5947                         // static virtual methods.
5948                         ValidateStaticMethodImpl(declMethod, *it);//bmtMethodHandle(pCurImplMethod));
5949                         continue;
5950                     }
5951
5952                     if (bmtMetaData->rgMethodImplTokens[m].fRequiresCovariantReturnTypeChecking)
5953                     {
5954                         it->GetMethodDesc()->SetRequiresCovariantReturnTypeChecking();
5955                     }
5956
5957                     bmtMethodImpl->AddMethodImpl(*it, declMethod, mdDecl, GetStackingAllocator());
5958                 }
5959             }
5960         }
5961     } /* end ... for each member */
5962 }
5963
5964
5965 MethodTableBuilder::bmtMethodHandle MethodTableBuilder::FindDeclMethodOnClassInHierarchy(const DeclaredMethodIterator& it, MethodTable * pDeclMT, MethodSignature &declSig)
5966 {
5967     bmtRTType * pDeclType = NULL;
5968     bmtMethodHandle declMethod;
5969     // Assume the MethodTable is a parent of the current type,
5970     // and create the substitution chain to match it.
5971
5972     for (bmtRTType *pCur = GetParentType();
5973             pCur != NULL;
5974             pCur = pCur->GetParentType())
5975     {
5976         if (pCur->GetMethodTable() == pDeclMT)
5977         {
5978             pDeclType = pCur;
5979             break;
5980         }
5981     }
5982
5983     // Instead of using the Substitution chain that reaches back to the type being loaded, instead
5984     // use a substitution chain that points back to the open type associated with the memberref of the declsig.
5985     Substitution emptySubstitution;
5986     Substitution* pDeclTypeSubstitution = &emptySubstitution;
5987     DWORD lengthOfSubstitutionChainHandled = pDeclType->GetSubstitution().GetLength();
5988
5989     if (pDeclType == NULL)
5990     {   // Method's type is not a parent.
5991         BuildMethodTableThrowException(IDS_CLASSLOAD_MI_DECLARATIONNOTFOUND, it.Token());
5992     }
5993
5994     // 3. Find the matching method.
5995     bmtRTType *pCurDeclType = pDeclType;
5996     do
5997     {
5998         // Update the substitution in use for matching the method. If the substitution length is greater
5999         // than the previously processed data, add onto the end of the chain.
6000         {
6001             DWORD declTypeSubstitionLength = pCurDeclType->GetSubstitution().GetLength();
6002             if (declTypeSubstitionLength > lengthOfSubstitutionChainHandled)
6003             {
6004                 void *pNewSubstitutionMem = _alloca(sizeof(Substitution));
6005                 Substitution substitutionToClone = pCurDeclType->GetSubstitution();
6006
6007                 Substitution *pNewSubstitution = new(pNewSubstitutionMem) Substitution(substitutionToClone.GetModule(), substitutionToClone.GetInst(), pDeclTypeSubstitution);
6008                 pDeclTypeSubstitution = pNewSubstitution;
6009                 lengthOfSubstitutionChainHandled = declTypeSubstitionLength;
6010             }
6011         }
6012
6013         // two pass algorithm. search for exact matches followed
6014         // by equivalent matches.
6015         for (int iPass = 0; (iPass < 2) && (declMethod.IsNull()); iPass++)
6016         {
6017             MethodTable *pCurDeclMT = pCurDeclType->GetMethodTable();
6018
6019             MethodTable::IntroducedMethodIterator methIt(pCurDeclMT);
6020             for(; methIt.IsValid(); methIt.Next())
6021             {
6022                 MethodDesc * pCurMD = methIt.GetMethodDesc();
6023
6024                 if (pCurDeclMT != pDeclMT)
6025                 {
6026                     // If the method isn't on the declaring type, then it must be virtual.
6027                     if (!pCurMD->IsVirtual())
6028                         continue;
6029                 }
6030                 if (strcmp(declSig.GetName(), pCurMD->GetName()) == 0)
6031                 {
6032                     PCCOR_SIGNATURE pCurMDSig;
6033                     DWORD cbCurMDSig;
6034                     pCurMD->GetSig(&pCurMDSig, &cbCurMDSig);
6035
6036                     // First pass searches for declaration methods should not use type equivalence
6037                     TokenPairList newVisited = TokenPairList::AdjustForTypeEquivalenceForbiddenScope(NULL);
6038
6039                     if (MetaSig::CompareMethodSigs(
6040                         declSig.GetSignature(),
6041                         static_cast<DWORD>(declSig.GetSignatureLength()),
6042                         declSig.GetModule(),
6043                         NULL, // Do not use the substitution of declSig, as we have adjusted the pDeclTypeSubstitution such that it must not be used.
6044                         pCurMDSig,
6045                         cbCurMDSig,
6046                         pCurMD->GetModule(),
6047                         pDeclTypeSubstitution,
6048                         FALSE,
6049                         iPass == 0 ? &newVisited : NULL))
6050                     {
6051                         declMethod = (*bmtParent->pSlotTable)[pCurMD->GetSlot()].Decl();
6052                         break;
6053                     }
6054                 }
6055             }
6056         }
6057
6058         pCurDeclType = pCurDeclType->GetParentType();
6059     } while ((pCurDeclType != NULL) && (declMethod.IsNull()));
6060
6061     return declMethod;
6062 }
6063 //*******************************************************************************
6064 // InitMethodDesc takes a pointer to space that's already allocated for the
6065 // particular type of MethodDesc, and initializes based on the other info.
6066 // This factors logic between PlaceMembers (the regular code path) & AddMethod
6067 // (Edit & Continue (EnC) code path) so we don't have to maintain separate copies.
6068 VOID
6069 MethodTableBuilder::InitMethodDesc(
6070     MethodDesc *        pNewMD, // This is should actually be of the correct sub-type, based on Classification
6071     DWORD               Classification,
6072     mdToken             tok,
6073     DWORD               dwImplFlags,
6074     DWORD               dwMemberAttrs,
6075     BOOL                fEnC,
6076     DWORD               RVA,        // Only needed for NDirect case
6077     IMDInternalImport * pIMDII,     // Needed for NDirect, EEImpl(Delegate) cases
6078     LPCSTR              pMethodName // Only needed for mcEEImpl (Delegate) case
6079     COMMA_INDEBUG(LPCUTF8 pszDebugMethodName)
6080     COMMA_INDEBUG(LPCUTF8 pszDebugClassName)
6081     COMMA_INDEBUG(LPCUTF8 pszDebugMethodSignature)
6082     )
6083 {
6084     CONTRACTL
6085     {
6086         THROWS;
6087         if (fEnC) { GC_NOTRIGGER; } else { GC_TRIGGERS; }
6088         MODE_ANY;
6089     }
6090     CONTRACTL_END;
6091
6092     LOG((LF_CORDB, LL_EVERYTHING, "MTB::IMD: pNewMD:%p (%u) EnC: %s tok:0x%08x (%s::%s)\n",
6093         pNewMD, Classification, (fEnC ? "true" : "false"), tok, pszDebugClassName, pszDebugMethodName));
6094
6095     // Now we know the classification we can perform any classification specific initialization.
6096
6097     // The method desc is zero inited by the caller.
6098
6099     switch (Classification)
6100     {
6101     case mcNDirect:
6102         {
6103             // NDirect specific initialization.
6104             NDirectMethodDesc *pNewNMD = (NDirectMethodDesc*)pNewMD;
6105
6106             // Allocate writeable data
6107             pNewNMD->ndirect.m_pWriteableData = (NDirectWriteableData*)
6108                 AllocateFromHighFrequencyHeap(S_SIZE_T(sizeof(NDirectWriteableData)));
6109
6110 #ifdef HAS_NDIRECT_IMPORT_PRECODE
6111             pNewNMD->ndirect.m_pImportThunkGlue = Precode::Allocate(PRECODE_NDIRECT_IMPORT, pNewMD,
6112                 GetLoaderAllocator(), GetMemTracker())->AsNDirectImportPrecode();
6113 #else // !HAS_NDIRECT_IMPORT_PRECODE
6114             pNewNMD->GetNDirectImportThunkGlue()->Init(pNewNMD);
6115 #endif // !HAS_NDIRECT_IMPORT_PRECODE
6116
6117 #if defined(TARGET_X86)
6118             pNewNMD->ndirect.m_cbStackArgumentSize = 0xFFFF;
6119 #endif // defined(TARGET_X86)
6120
6121             // If the RVA of a native method is set, this is an early-bound IJW call
6122             if (RVA != 0 && IsMiUnmanaged(dwImplFlags) && IsMiNative(dwImplFlags))
6123             {
6124                 // Note that we cannot initialize the stub directly now in the general case,
6125                 // as LoadLibrary may not have been performed yet.
6126                 pNewNMD->SetIsEarlyBound();
6127             }
6128
6129             pNewNMD->GetWriteableData()->m_pNDirectTarget = pNewNMD->GetNDirectImportThunkGlue()->GetEntrypoint();
6130         }
6131         break;
6132
6133     case mcFCall:
6134         break;
6135
6136     case mcEEImpl:
6137         // For the Invoke method we will set a standard invoke method.
6138         BAD_FORMAT_NOTHROW_ASSERT(IsDelegate());
6139
6140         // For the asserts, either the pointer is NULL (since the class hasn't
6141         // been constructed yet), or we're in EnC mode, meaning that the class
6142         // does exist, but we may be re-assigning the field to point to an
6143         // updated MethodDesc
6144
6145         // It is not allowed for EnC to replace one of the runtime builtin methods
6146
6147         if (strcmp(pMethodName, "Invoke") == 0)
6148         {
6149             BAD_FORMAT_NOTHROW_ASSERT(((DelegateEEClass*)GetHalfBakedClass())->m_pInvokeMethod == NULL);
6150             ((DelegateEEClass*)GetHalfBakedClass())->m_pInvokeMethod = pNewMD;
6151         }
6152         else if (strcmp(pMethodName, "BeginInvoke") == 0)
6153         {
6154             BAD_FORMAT_NOTHROW_ASSERT(((DelegateEEClass*)GetHalfBakedClass())->m_pBeginInvokeMethod == NULL);
6155             ((DelegateEEClass*)GetHalfBakedClass())->m_pBeginInvokeMethod = pNewMD;
6156         }
6157         else if (strcmp(pMethodName, "EndInvoke") == 0)
6158         {
6159             BAD_FORMAT_NOTHROW_ASSERT(((DelegateEEClass*)GetHalfBakedClass())->m_pEndInvokeMethod == NULL);
6160             ((DelegateEEClass*)GetHalfBakedClass())->m_pEndInvokeMethod = pNewMD;
6161         }
6162         else
6163         {
6164             BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
6165         }
6166
6167         // StoredSig specific initialization
6168         {
6169             StoredSigMethodDesc *pNewSMD = (StoredSigMethodDesc*) pNewMD;;
6170             DWORD cSig;
6171             PCCOR_SIGNATURE pSig;
6172             if (FAILED(pIMDII->GetSigOfMethodDef(tok, &cSig, &pSig)))
6173             {
6174                 BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
6175             }
6176             pNewSMD->SetStoredMethodSig(pSig, cSig);
6177         }
6178         break;
6179
6180 #ifdef FEATURE_COMINTEROP
6181     case mcComInterop:
6182 #endif // FEATURE_COMINTEROP
6183     case mcIL:
6184         break;
6185
6186     case mcInstantiated:
6187         {
6188             // Initialize the typical instantiation.
6189             InstantiatedMethodDesc* pNewIMD = pNewMD->AsInstantiatedMethodDesc();
6190
6191             //data has the same lifetime as method table, use our allocator
6192             pNewIMD->SetupGenericMethodDefinition(
6193                 pIMDII,
6194                 GetLoaderAllocator(),
6195                 GetMemTracker(),
6196                 GetModule(),
6197                 tok);
6198         }
6199         break;
6200
6201     default:
6202         BAD_FORMAT_NOTHROW_ASSERT(!"Failed to set a method desc classification");
6203     }
6204
6205     // Check the method desc's classification.
6206     _ASSERTE(pNewMD->GetClassification() == Classification);
6207
6208     pNewMD->SetMemberDef(tok);
6209
6210     if (IsMdStatic(dwMemberAttrs))
6211         pNewMD->SetStatic();
6212
6213 #ifdef EnC_SUPPORTED
6214     if (fEnC)
6215         pNewMD->SetIsEnCAddedMethod();
6216 #endif // EnC_SUPPORTED
6217
6218 #ifdef _DEBUG
6219     // Mark as many methods as synchronized as possible.
6220     //
6221     // Note that this can easily cause programs to deadlock, and that
6222     // should not be treated as a bug in the program.
6223
6224     static ConfigDWORD stressSynchronized;
6225     DWORD stressSynchronizedVal = stressSynchronized.val(CLRConfig::INTERNAL_stressSynchronized);
6226
6227     bool isStressSynchronized =  stressSynchronizedVal &&
6228         pNewMD->IsIL() && // Synchronized is not supported on Ecalls, NDirect method, etc
6229         // IsValueClass() and IsEnum() do not work for System.ValueType and System.Enum themselves
6230         ((g_pValueTypeClass != NULL && g_pEnumClass != NULL &&
6231           !IsValueClass()) || // Can not synchronize on byref "this"
6232           IsMdStatic(dwMemberAttrs)) && // IsStatic() blows up in _DEBUG as pNewMD is not fully inited
6233         g_pObjectClass != NULL; // Ignore Object:* since "this" could be a boxed object
6234
6235     // stressSynchronized=1 turns off the stress in the system domain to reduce
6236     // the chances of spurious deadlocks. Deadlocks in user code can still occur.
6237     // stressSynchronized=2 will probably cause more deadlocks, and is not recommended
6238     if (stressSynchronizedVal == 1 && GetAssembly()->IsSystem())
6239         isStressSynchronized = false;
6240
6241     if (IsMiSynchronized(dwImplFlags) || isStressSynchronized)
6242 #else // !_DEBUG
6243     if (IsMiSynchronized(dwImplFlags))
6244 #endif // !_DEBUG
6245         pNewMD->SetSynchronized();
6246
6247 #ifdef _DEBUG
6248     pNewMD->m_pszDebugMethodName = (LPUTF8)pszDebugMethodName;
6249     pNewMD->m_pszDebugClassName  = (LPUTF8)pszDebugClassName;
6250     pNewMD->m_pDebugMethodTable = GetHalfBakedMethodTable();
6251
6252     if (pszDebugMethodSignature == NULL)
6253         pNewMD->m_pszDebugMethodSignature = FormatSig(pNewMD,pNewMD->GetLoaderAllocator()->GetLowFrequencyHeap(),GetMemTracker());
6254     else
6255         pNewMD->m_pszDebugMethodSignature = pszDebugMethodSignature;
6256 #endif // _DEBUG
6257 } // MethodTableBuilder::InitMethodDesc
6258
6259 //*******************************************************************************
6260 //
6261 // Used by BuildMethodTable
6262 //
6263 VOID
6264 MethodTableBuilder::AddMethodImplDispatchMapping(
6265     DispatchMapTypeID typeID,
6266     SLOT_INDEX        slotNumber,
6267     bmtMDMethod *     pImplMethod)
6268 {
6269     STANDARD_VM_CONTRACT;
6270
6271     MethodDesc * pMDImpl = pImplMethod->GetMethodDesc();
6272
6273     // Look for an existing entry in the map.
6274     DispatchMapBuilder::Iterator it(bmtVT->pDispatchMapBuilder);
6275     if (bmtVT->pDispatchMapBuilder->Find(typeID, slotNumber, it))
6276     {
6277         // Throw if this entry has already previously been MethodImpl'd.
6278         if (it.IsMethodImpl())
6279         {
6280             // NOTE: This is where we check for duplicate overrides. This is the easiest place to check
6281             //       because duplicate overrides could in fact have separate MemberRefs to the same
6282             //       member and so just comparing tokens at the very start would not be enough.
6283             if (it.GetTargetMD() != pMDImpl)
6284             {
6285                 BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MULTIPLEOVERRIDES, pMDImpl->GetMemberDef());
6286             }
6287         }
6288         // This is the first MethodImpl. That's ok.
6289         else
6290         {
6291             it.SetTarget(pMDImpl);
6292             it.SetIsMethodImpl();
6293         }
6294     }
6295     // A mapping for this interface method does not exist, so insert it.
6296     else
6297     {
6298         bmtVT->pDispatchMapBuilder->InsertMDMapping(
6299             typeID,
6300             slotNumber,
6301             pMDImpl,
6302             TRUE);
6303     }
6304
6305     // Save the entry into the vtable as well, if it isn't an interface methodImpl
6306     if (typeID == DispatchMapTypeID::ThisClassID())
6307     {
6308         bmtVT->SetVirtualMethodImpl(slotNumber, pImplMethod);
6309     }
6310 } // MethodTableBuilder::AddMethodImplDispatchMapping
6311
6312 //*******************************************************************************
6313 VOID
6314 MethodTableBuilder::MethodImplCompareSignatures(
6315     bmtMethodHandle     hDecl,
6316     bmtMethodHandle     hImpl,
6317     BOOL                allowCovariantReturn,
6318     DWORD               dwConstraintErrorCode)
6319 {
6320     CONTRACTL {
6321         STANDARD_VM_CHECK;
6322         PRECONDITION(!hDecl.IsNull());
6323         PRECONDITION(!hImpl.IsNull());
6324         PRECONDITION(TypeFromToken(hDecl.GetMethodSignature().GetToken()) == mdtMethodDef);
6325         PRECONDITION(TypeFromToken(hImpl.GetMethodSignature().GetToken()) == mdtMethodDef);
6326     } CONTRACTL_END;
6327
6328     const MethodSignature &declSig(hDecl.GetMethodSignature());
6329     const MethodSignature &implSig(hImpl.GetMethodSignature());
6330
6331     if (!MethodSignature::SignaturesEquivalent(declSig, implSig, allowCovariantReturn))
6332     {
6333         LOG((LF_CLASSLOADER, LL_INFO1000, "BADSIG placing MethodImpl: %x\n", declSig.GetToken()));
6334         BuildMethodTableThrowException(COR_E_TYPELOAD, IDS_CLASSLOAD_MI_BADSIGNATURE, declSig.GetToken());
6335     }
6336
6337     //now compare the method constraints
6338     if ((*declSig.GetSignature()) & IMAGE_CEE_CS_CALLCONV_GENERIC)
6339     {
6340         if (!MetaSig::CompareMethodConstraints(implSig.GetSubstitution(), implSig.GetModule(), implSig.GetToken(),
6341                                             declSig.GetSubstitution(), declSig.GetModule(), declSig.GetToken()))
6342         {
6343             BuildMethodTableThrowException(dwConstraintErrorCode, implSig.GetToken());
6344         }
6345     }
6346 }
6347
6348 //*******************************************************************************
6349 // We should have collected all the method impls. Cycle through them creating the method impl
6350 // structure that holds the information about which slots are overridden.
6351 VOID
6352 MethodTableBuilder::PlaceMethodImpls()
6353 {
6354     STANDARD_VM_CONTRACT;
6355
6356     if(bmtMethodImpl->pIndex == 0)
6357     {
6358         return;
6359     }
6360
6361     // Allocate some temporary storage. The number of overrides for a single method impl
6362     // cannot be greater then the number of vtable slots for classes. But for interfaces
6363     // it might contain overrides for other interface methods.
6364     DWORD dwMaxSlotSize = IsInterface() ? bmtMethod->dwNumberMethodImpls : bmtVT->cVirtualSlots;
6365
6366     DWORD * slots = new (GetStackingAllocator()) DWORD[dwMaxSlotSize];
6367     mdToken * tokens = new (GetStackingAllocator()) mdToken[dwMaxSlotSize];
6368     MethodDesc ** replaced = new (GetStackingAllocator()) MethodDesc*[dwMaxSlotSize];
6369
6370     DWORD iEntry = 0;
6371     bmtMDMethod * pCurImplMethod = bmtMethodImpl->GetImplementationMethod(iEntry);
6372
6373     DWORD slotIndex = 0;
6374
6375     // The impls are sorted according to the method descs for the body of the method impl.
6376     // Loop through the impls until the next body is found. When a single body
6377     // has been done move the slots implemented and method descs replaced into the storage
6378     // found on the body method desc.
6379     while (true)
6380     {   // collect information until we reach the next body
6381
6382         tokens[slotIndex] = bmtMethodImpl->GetDeclarationToken(iEntry);
6383
6384         // Get the declaration part of the method impl. It will either be a token
6385         // (declaration is on this type) or a method desc.
6386         bmtMethodHandle hDeclMethod = bmtMethodImpl->GetDeclarationMethod(iEntry);
6387
6388         // Don't place static virtual method overrides in the vtable
6389         if (!IsMdStatic(hDeclMethod.GetDeclAttrs()))
6390         {
6391             if(hDeclMethod.IsMDMethod())
6392             {
6393                 // The declaration is on the type being built
6394                 bmtMDMethod * pCurDeclMethod = hDeclMethod.AsMDMethod();
6395
6396                 mdToken mdef = pCurDeclMethod->GetMethodSignature().GetToken();
6397                 if (bmtMethodImpl->IsBody(mdef))
6398                 {   // A method declared on this class cannot be both a decl and an impl
6399                     BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MULTIPLEOVERRIDES, mdef);
6400                 }
6401
6402                 if (IsInterface())
6403                 {
6404                     // Throws
6405                     PlaceInterfaceDeclarationOnInterface(
6406                         hDeclMethod,
6407                         pCurImplMethod,
6408                         slots,              // Adds override to the slot and replaced arrays.
6409                         replaced,
6410                         &slotIndex,
6411                         dwMaxSlotSize);     // Increments count
6412                 }
6413                 else
6414                 {
6415                     // Throws
6416                     PlaceLocalDeclarationOnClass(
6417                         pCurDeclMethod,
6418                         pCurImplMethod,
6419                         slots,              // Adds override to the slot and replaced arrays.
6420                         replaced,
6421                         &slotIndex,
6422                         dwMaxSlotSize);     // Increments count
6423                 }
6424             }
6425             else
6426             {
6427                 bmtRTMethod * pCurDeclMethod = hDeclMethod.AsRTMethod();
6428
6429                 if (IsInterface())
6430                 {
6431                     // Throws
6432                     PlaceInterfaceDeclarationOnInterface(
6433                         hDeclMethod,
6434                         pCurImplMethod,
6435                         slots,              // Adds override to the slot and replaced arrays.
6436                         replaced,
6437                         &slotIndex,
6438                         dwMaxSlotSize);     // Increments count
6439                 }
6440                 else
6441                 {
6442                     // Do not use pDecl->IsInterface here as that asks the method table and the MT may not yet be set up.
6443                     if (pCurDeclMethod->GetOwningType()->IsInterface())
6444                     {
6445                         // Throws
6446                         PlaceInterfaceDeclarationOnClass(
6447                             pCurDeclMethod,
6448                             pCurImplMethod);
6449                     }
6450                     else
6451                     {
6452                         // Throws
6453                         PlaceParentDeclarationOnClass(
6454                             pCurDeclMethod,
6455                             pCurImplMethod,
6456                             slots,
6457                             replaced,
6458                             &slotIndex,
6459                             dwMaxSlotSize);        // Increments count
6460                     }
6461                 }
6462             }
6463         }
6464
6465         iEntry++;
6466
6467         if(iEntry == bmtMethodImpl->pIndex)
6468         {
6469             // We hit the end of the list so dump the current data and leave
6470             WriteMethodImplData(pCurImplMethod, slotIndex, slots, tokens, replaced);
6471             break;
6472         }
6473         else
6474         {
6475             bmtMDMethod * pNextImplMethod = bmtMethodImpl->GetImplementationMethod(iEntry);
6476
6477             if (pNextImplMethod != pCurImplMethod)
6478             {
6479                 // If we're moving on to a new body, dump the current data and reset the counter
6480                 WriteMethodImplData(pCurImplMethod, slotIndex, slots, tokens, replaced);
6481                 slotIndex = 0;
6482             }
6483
6484             pCurImplMethod = pNextImplMethod;
6485         }
6486     }  // while(next != NULL)
6487 } // MethodTableBuilder::PlaceMethodImpls
6488
6489 //*******************************************************************************
6490 VOID
6491 MethodTableBuilder::WriteMethodImplData(
6492     bmtMDMethod * pImplMethod,
6493     DWORD         cSlots,
6494     DWORD *       rgSlots,
6495     mdToken *     rgTokens,
6496     MethodDesc ** rgDeclMD)
6497 {
6498     STANDARD_VM_CONTRACT;
6499
6500     // Use the number of overrides to
6501     // push information on to the method desc. We store the slots that
6502     // are overridden and the method desc that is replaced. That way
6503     // when derived classes need to determine if the method is to be
6504     // overridden then it can check the name against the replaced
6505     // method desc not the bodies name.
6506     if (cSlots == 0)
6507     {
6508         //@TODO:NEWVTWORK: Determine methodImpl status so that we don't need this workaround.
6509         //@TODO:NEWVTWORK: This occurs when only interface decls are involved, since
6510         //@TODO:NEWVTWORK: these are stored in the dispatch map and not on the methoddesc.
6511     }
6512     else
6513     {
6514         MethodImpl * pImpl = pImplMethod->GetMethodDesc()->GetMethodImpl();
6515
6516         // Set the size of the info the MethodImpl needs to keep track of.
6517         pImpl->SetSize(GetLoaderAllocator()->GetHighFrequencyHeap(), GetMemTracker(), cSlots);
6518
6519         if (!IsInterface())
6520         {
6521             // If we are currently builting an interface, the slots here has no meaning and we can skip it
6522             // Sort the two arrays in slot index order
6523             // This is required in MethodImpl::FindSlotIndex and MethodImpl::Iterator as we'll be using
6524             // binary search later
6525             for (DWORD i = 0; i < cSlots; i++)
6526             {
6527                 unsigned int min = i;
6528                 for (DWORD j = i + 1; j < cSlots; j++)
6529                 {
6530                     if (rgSlots[j] < rgSlots[min])
6531                     {
6532                         min = j;
6533                     }
6534                 }
6535
6536                 if (min != i)
6537                 {
6538                     MethodDesc * mTmp = rgDeclMD[i];
6539                     rgDeclMD[i] = rgDeclMD[min];
6540                     rgDeclMD[min] = mTmp;
6541
6542                     DWORD sTmp = rgSlots[i];
6543                     rgSlots[i] = rgSlots[min];
6544                     rgSlots[min] = sTmp;
6545
6546                     mdToken tTmp = rgTokens[i];
6547                     rgTokens[i] = rgTokens[min];
6548                     rgTokens[min] = tTmp;
6549                 }
6550             }
6551         }
6552
6553         // Go and set the method impl
6554         pImpl->SetData(rgSlots, rgTokens, rgDeclMD);
6555
6556         GetHalfBakedClass()->SetContainsMethodImpls();
6557     }
6558 } // MethodTableBuilder::WriteMethodImplData
6559
6560 //*******************************************************************************
6561 VOID
6562 MethodTableBuilder::PlaceLocalDeclarationOnClass(
6563     bmtMDMethod * pDecl,
6564     bmtMDMethod * pImpl,
6565     DWORD *       slots,
6566     MethodDesc ** replaced,
6567     DWORD *       pSlotIndex,
6568     DWORD         dwMaxSlotSize)
6569 {
6570     CONTRACTL
6571     {
6572         STANDARD_VM_CHECK;
6573         PRECONDITION(CheckPointer(bmtVT->pDispatchMapBuilder));
6574         PRECONDITION(CheckPointer(pDecl));
6575         PRECONDITION(CheckPointer(pImpl));
6576     }
6577     CONTRACTL_END
6578
6579     if (!bmtProp->fNoSanityChecks)
6580     {
6581         ///////////////////////////////
6582         // Verify the signatures match
6583
6584         MethodImplCompareSignatures(
6585             pDecl,
6586             pImpl,
6587             FALSE /* allowCovariantReturn */,
6588             IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_LOCAL_METHOD_IMPL);
6589
6590         ///////////////////////////////
6591         // Validate the method impl.
6592
6593         TestMethodImpl(
6594             bmtMethodHandle(pDecl),
6595             bmtMethodHandle(pImpl));
6596     }
6597
6598     // Don't allow overrides for any of the four special runtime implemented delegate methods
6599     if (IsDelegate())
6600     {
6601         LPCUTF8 strMethodName = pDecl->GetMethodSignature().GetName();
6602         if ((strcmp(strMethodName, COR_CTOR_METHOD_NAME) == 0) ||
6603             (strcmp(strMethodName, "Invoke")             == 0) ||
6604             (strcmp(strMethodName, "BeginInvoke")        == 0) ||
6605             (strcmp(strMethodName, "EndInvoke")          == 0))
6606         {
6607             BuildMethodTableThrowException(
6608                 IDS_CLASSLOAD_MI_CANNOT_OVERRIDE,
6609                 pDecl->GetMethodSignature().GetToken());
6610         }
6611     }
6612
6613     ///////////////////
6614     // Add the mapping
6615
6616     // Call helper to add it. Will throw if decl is already MethodImpl'd
6617     CONSISTENCY_CHECK(pDecl->GetSlotIndex() == static_cast<SLOT_INDEX>(pDecl->GetMethodDesc()->GetSlot()));
6618     AddMethodImplDispatchMapping(
6619         DispatchMapTypeID::ThisClassID(),
6620         pDecl->GetSlotIndex(),
6621         pImpl);
6622
6623     // We implement this slot, record it
6624     ASSERT(*pSlotIndex < dwMaxSlotSize);
6625     slots[*pSlotIndex] = pDecl->GetSlotIndex();
6626     replaced[*pSlotIndex] = pDecl->GetMethodDesc();
6627
6628     // increment the counter
6629     (*pSlotIndex)++;
6630 } // MethodTableBuilder::PlaceLocalDeclarationOnClass
6631
6632 //*******************************************************************************
6633 VOID MethodTableBuilder::PlaceInterfaceDeclarationOnClass(
6634     bmtRTMethod *     pDecl,
6635     bmtMDMethod *     pImpl)
6636 {
6637     CONTRACTL {
6638         STANDARD_VM_CHECK;
6639         PRECONDITION(CheckPointer(pDecl));
6640         PRECONDITION(CheckPointer(pImpl));
6641         PRECONDITION(pDecl->GetMethodDesc()->IsInterface());
6642         PRECONDITION(CheckPointer(bmtVT->pDispatchMapBuilder));
6643     } CONTRACTL_END;
6644
6645     MethodDesc *  pDeclMD = pDecl->GetMethodDesc();
6646     MethodTable * pDeclMT = pDeclMD->GetMethodTable();
6647
6648     // Note that the fact that pDecl is non-NULL means that we found the
6649     // declaration token to be owned by a declared interface for this type.
6650
6651     if (!bmtProp->fNoSanityChecks)
6652     {
6653         ///////////////////////////////
6654         // Verify the signatures match
6655
6656         MethodImplCompareSignatures(
6657             pDecl,
6658             pImpl,
6659             FALSE /* allowCovariantReturn */,
6660             IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_INTERFACE_METHOD_IMPL);
6661
6662         ///////////////////////////////
6663         // Validate the method impl.
6664
6665         TestMethodImpl(
6666             bmtMethodHandle(pDecl),
6667             bmtMethodHandle(pImpl));
6668     }
6669
6670     ///////////////////
6671     // Add the mapping
6672
6673     // Note that we need only one DispatchMapTypeID for this interface (though there might be more if there
6674     // are duplicates). The first one is easy to get, but we could (in theory) use the last one or a random
6675     // one.
6676     // Q: Why don't we have to place this method for all duplicate interfaces? Because VSD knows about
6677     // duplicates and finds the right (latest) implementation for us - see
6678     // code:MethodTable::MethodDataInterfaceImpl::PopulateNextLevel#ProcessAllDuplicates.
6679     UINT32 cInterfaceDuplicates;
6680     DispatchMapTypeID firstDispatchMapTypeID;
6681     ComputeDispatchMapTypeIDs(
6682         pDeclMT,
6683         pDecl->GetMethodSignature().GetSubstitution(),
6684         &firstDispatchMapTypeID,
6685         1,
6686         &cInterfaceDuplicates);
6687     CONSISTENCY_CHECK(cInterfaceDuplicates >= 1);
6688     CONSISTENCY_CHECK(firstDispatchMapTypeID.IsImplementedInterface());
6689
6690     // Call helper to add it. Will throw if decl is already MethodImpl'd
6691     CONSISTENCY_CHECK(pDecl->GetSlotIndex() == static_cast<SLOT_INDEX>(pDecl->GetMethodDesc()->GetSlot()));
6692     AddMethodImplDispatchMapping(
6693         firstDispatchMapTypeID,
6694         pDecl->GetSlotIndex(),
6695         pImpl);
6696
6697 #ifdef _DEBUG
6698     if (bmtInterface->dbg_fShouldInjectInterfaceDuplicates)
6699     {   // We injected interface duplicates
6700
6701         // We have to MethodImpl all interface duplicates as all duplicates are 'declared on type' (see
6702         // code:#InjectInterfaceDuplicates_ApproxInterfaces)
6703         DispatchMapTypeID * rgDispatchMapTypeIDs = (DispatchMapTypeID *)_alloca(sizeof(DispatchMapTypeID) * cInterfaceDuplicates);
6704         ComputeDispatchMapTypeIDs(
6705             pDeclMT,
6706             pDecl->GetMethodSignature().GetSubstitution(),
6707             rgDispatchMapTypeIDs,
6708             cInterfaceDuplicates,
6709             &cInterfaceDuplicates);
6710         for (UINT32 nInterfaceDuplicate = 1; nInterfaceDuplicate < cInterfaceDuplicates; nInterfaceDuplicate++)
6711         {
6712             // Add MethodImpl record for each injected interface duplicate
6713             AddMethodImplDispatchMapping(
6714                 rgDispatchMapTypeIDs[nInterfaceDuplicate],
6715                 pDecl->GetSlotIndex(),
6716                 pImpl);
6717         }
6718     }
6719 #endif //_DEBUG
6720 } // MethodTableBuilder::PlaceInterfaceDeclarationOnClass
6721
6722 //*******************************************************************************
6723 VOID MethodTableBuilder::PlaceInterfaceDeclarationOnInterface(
6724     bmtMethodHandle hDecl,
6725     bmtMDMethod   *pImpl,
6726     DWORD *       slots,
6727     MethodDesc ** replaced,
6728     DWORD *       pSlotIndex,
6729     DWORD         dwMaxSlotSize)
6730 {
6731     CONTRACTL {
6732         STANDARD_VM_CHECK;
6733         PRECONDITION(CheckPointer(pImpl));
6734         PRECONDITION(IsInterface());
6735         PRECONDITION(hDecl.GetMethodDesc()->IsInterface());
6736     } CONTRACTL_END;
6737
6738     MethodDesc *  pDeclMD = hDecl.GetMethodDesc();
6739
6740     if (!bmtProp->fNoSanityChecks)
6741     {
6742         ///////////////////////////////
6743         // Verify the signatures match
6744
6745         MethodImplCompareSignatures(
6746             hDecl,
6747             bmtMethodHandle(pImpl),
6748             FALSE /* allowCovariantReturn */,
6749             IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_INTERFACE_METHOD_IMPL);
6750
6751         ///////////////////////////////
6752         // Validate the method impl.
6753
6754         TestMethodImpl(hDecl, bmtMethodHandle(pImpl));
6755     }
6756
6757     // We implement this slot, record it
6758     ASSERT(*pSlotIndex < dwMaxSlotSize);
6759     slots[*pSlotIndex] = hDecl.GetSlotIndex();
6760     replaced[*pSlotIndex] = pDeclMD;
6761
6762     // increment the counter
6763     (*pSlotIndex)++;
6764 } // MethodTableBuilder::PlaceInterfaceDeclarationOnInterface
6765
6766 //*******************************************************************************
6767 VOID
6768 MethodTableBuilder::PlaceParentDeclarationOnClass(
6769     bmtRTMethod * pDecl,
6770     bmtMDMethod * pImpl,
6771     DWORD *       slots,
6772     MethodDesc**  replaced,
6773     DWORD *       pSlotIndex,
6774     DWORD         dwMaxSlotSize)
6775 {
6776     CONTRACTL {
6777         STANDARD_VM_CHECK;
6778         PRECONDITION(CheckPointer(pDecl));
6779         PRECONDITION(CheckPointer(pImpl));
6780         PRECONDITION(CheckPointer(bmtVT->pDispatchMapBuilder));
6781         PRECONDITION(CheckPointer(GetParentMethodTable()));
6782     } CONTRACTL_END;
6783
6784     MethodDesc * pDeclMD = pDecl->GetMethodDesc();
6785
6786     // Note that the fact that pDecl is non-NULL means that we found the
6787     // declaration token to be owned by a parent type.
6788
6789     if (!bmtProp->fNoSanityChecks)
6790     {
6791         /////////////////////////////////////////
6792         // Verify that the signatures match
6793
6794         MethodImplCompareSignatures(
6795             pDecl,
6796             pImpl,
6797             TRUE /* allowCovariantReturn */,
6798             IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_PARENT_METHOD_IMPL);
6799
6800         ////////////////////////////////
6801         // Verify rules of method impls
6802
6803         TestMethodImpl(
6804             bmtMethodHandle(pDecl),
6805             bmtMethodHandle(pImpl));
6806     }
6807
6808     ///////////////////
6809     // Add the mapping
6810
6811     // Call helper to add it. Will throw if DECL is already MethodImpl'd
6812     AddMethodImplDispatchMapping(
6813         DispatchMapTypeID::ThisClassID(),
6814         pDeclMD->GetSlot(),
6815         pImpl);
6816
6817     // We implement this slot, record it
6818     ASSERT(*pSlotIndex < dwMaxSlotSize);
6819     slots[*pSlotIndex] = pDeclMD->GetSlot();
6820     replaced[*pSlotIndex] = pDeclMD;
6821
6822     // increment the counter
6823     (*pSlotIndex)++;
6824 } // MethodTableBuilder::PlaceParentDeclarationOnClass
6825
6826 VOID MethodTableBuilder::ValidateStaticMethodImpl(
6827     bmtMethodHandle     hDecl,
6828     bmtMethodHandle     hImpl)
6829 {
6830     // While we don't want to place the static method impl declarations on the class/interface, we do
6831     // need to validate the method constraints and signature are compatible
6832     if (!bmtProp->fNoSanityChecks)
6833     {
6834         ///////////////////////////////
6835         // Verify the signatures match
6836
6837         MethodImplCompareSignatures(
6838             hDecl,
6839             hImpl,
6840             FALSE /* allowCovariantReturn */,
6841             IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_INTERFACE_METHOD_IMPL);
6842
6843         ///////////////////////////////
6844         // Validate the method impl.
6845
6846         TestMethodImpl(hDecl, hImpl);
6847     }
6848 }
6849
6850 //*******************************************************************************
6851 // This will validate that all interface methods that were matched during
6852 // layout also validate against type constraints.
6853
6854 VOID MethodTableBuilder::ValidateInterfaceMethodConstraints()
6855 {
6856     STANDARD_VM_CONTRACT;
6857
6858     DispatchMapBuilder::Iterator it(bmtVT->pDispatchMapBuilder);
6859     for (; it.IsValid(); it.Next())
6860     {
6861         if (it.GetTypeID() != DispatchMapTypeID::ThisClassID())
6862         {
6863             bmtRTType * pItf = bmtInterface->pInterfaceMap[it.GetTypeID().GetInterfaceNum()].GetInterfaceType();
6864
6865             // Grab the method token
6866             MethodTable * pMTItf = pItf->GetMethodTable();
6867             CONSISTENCY_CHECK(CheckPointer(pMTItf->GetMethodDescForSlot(it.GetSlotNumber())));
6868             mdMethodDef mdTok = pItf->GetMethodTable()->GetMethodDescForSlot(it.GetSlotNumber())->GetMemberDef();
6869
6870             // Default to the current module. The code immediately below determines if this
6871             // assumption is incorrect.
6872             Module *          pTargetModule          = GetModule();
6873
6874             // Get the module of the target method. Get it through the chunk to
6875             // avoid triggering the assert that MethodTable is non-NULL. It may
6876             // be null since it may belong to the type we're building right now.
6877             MethodDesc *      pTargetMD              = it.GetTargetMD();
6878
6879             // If pTargetMT is null, this indicates that the target MethodDesc belongs
6880             // to the current type. Otherwise, the MethodDesc MUST be owned by a parent
6881             // of the type we're building.
6882             BOOL              fTargetIsOwnedByParent = pTargetMD->GetMethodTable() != NULL;
6883
6884             // If the method is owned by a parent, we need to use the parent's module,
6885             // and we must construct the substitution chain all the way up to the parent.
6886             const Substitution *pSubstTgt = NULL;
6887             if (fTargetIsOwnedByParent)
6888             {
6889                 CONSISTENCY_CHECK(CheckPointer(GetParentType()));
6890                 bmtRTType *pTargetType = bmtRTType::FindType(GetParentType(), pTargetMD->GetMethodTable());
6891                 pSubstTgt = &pTargetType->GetSubstitution();
6892                 pTargetModule = pTargetType->GetModule();
6893             }
6894
6895             // Now compare the method constraints.
6896             if ((pTargetMD->GetClassification() == mcInstantiated) && !MetaSig::CompareMethodConstraints(pSubstTgt,
6897                                                    pTargetModule,
6898                                                    pTargetMD->GetMemberDef(),
6899                                                    &pItf->GetSubstitution(),
6900                                                    pMTItf->GetModule(),
6901                                                    mdTok))
6902             {
6903                 LOG((LF_CLASSLOADER, LL_INFO1000,
6904                      "BADCONSTRAINTS on interface method implementation: %x\n", pTargetMD));
6905                 // This exception will be due to an implicit implementation, since explicit errors
6906                 // will be detected in MethodImplCompareSignatures (for now, anyway).
6907                 CONSISTENCY_CHECK(!it.IsMethodImpl());
6908                 DWORD idsError = it.IsMethodImpl() ?
6909                                  IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_INTERFACE_METHOD_IMPL :
6910                                  IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_IMPLICIT_IMPLEMENTATION;
6911                 if (fTargetIsOwnedByParent)
6912                 {
6913                     DefineFullyQualifiedNameForClass();
6914                     LPCUTF8 szClassName = GetFullyQualifiedNameForClassNestedAware(pTargetMD->GetMethodTable());
6915                     LPCUTF8 szMethodName = pTargetMD->GetName();
6916
6917                     CQuickBytes qb;
6918                     // allocate enough room for "<class>.<method>\0"
6919                     size_t cchFullName = strlen(szClassName) + 1 + strlen(szMethodName) + 1;
6920                     LPUTF8 szFullName = (LPUTF8) qb.AllocThrows(cchFullName);
6921                     strcpy_s(szFullName, cchFullName, szClassName);
6922                     strcat_s(szFullName, cchFullName, ".");
6923                     strcat_s(szFullName, cchFullName, szMethodName);
6924
6925                     BuildMethodTableThrowException(idsError, szFullName);
6926                 }
6927                 else
6928                 {
6929                     BuildMethodTableThrowException(idsError, pTargetMD->GetMemberDef());
6930                 }
6931             }
6932         }
6933     }
6934 } // MethodTableBuilder::ValidateInterfaceMethodConstraints
6935
6936 //*******************************************************************************
6937 // Used to allocate and initialize MethodDescs (both the boxed and unboxed entrypoints)
6938 VOID MethodTableBuilder::AllocAndInitMethodDescs()
6939 {
6940     STANDARD_VM_CONTRACT;
6941
6942     //
6943     // Go over all MethodDescs and create smallest number of MethodDescChunks possible.
6944     //
6945     // Iterate over all methods and start a new chunk only if:
6946     //  - Token range (upper 24 bits of the method token) has changed.
6947     //  - The maximum size of the chunk has been reached.
6948     //
6949
6950     int currentTokenRange = -1; // current token range
6951     SIZE_T sizeOfMethodDescs = 0; // current running size of methodDesc chunk
6952     int startIndex = 0; // start of the current chunk (index into bmtMethod array)
6953
6954     // Limit the maximum MethodDescs per chunk by the number of precodes that can fit to a single memory page,
6955     // since we allocate consecutive temporary entry points for all MethodDescs in the whole chunk.
6956     DWORD maxPrecodesPerPage = Precode::GetMaxTemporaryEntryPointsCount();
6957     DWORD methodDescCount = 0;
6958
6959     DeclaredMethodIterator it(*this);
6960     while (it.Next())
6961     {
6962         DWORD currentSlotMethodDescCount = 1;
6963         int tokenRange = GetTokenRange(it.Token());
6964
6965         // This code assumes that iterator returns tokens in ascending order. If this assumption does not hold,
6966         // the code will still work with small performance penalty (method desc chunk layout will be less efficient).
6967         _ASSERTE(tokenRange >= currentTokenRange);
6968
6969         SIZE_T size = MethodDesc::GetBaseSize(it->GetMethodType());
6970
6971         // Add size of optional slots
6972
6973         if (it->GetMethodImplType() == METHOD_IMPL)
6974             size += sizeof(MethodImpl);
6975
6976         if (it->GetSlotIndex() >= bmtVT->cVtableSlots)
6977             size += sizeof(MethodDesc::NonVtableSlot); // slot
6978
6979         if (NeedsNativeCodeSlot(*it))
6980             size += sizeof(MethodDesc::NativeCodeSlot);
6981
6982         // See comment in AllocAndInitMethodDescChunk
6983         if (NeedsTightlyBoundUnboxingStub(*it))
6984         {
6985             currentSlotMethodDescCount = 2;
6986             size *= 2;
6987
6988             if (bmtGenerics->GetNumGenericArgs() == 0) {
6989                 size += sizeof(MethodDesc::NonVtableSlot);
6990             }
6991             else {
6992                 bmtVT->cVtableSlots++;
6993             }
6994         }
6995
6996         if (tokenRange != currentTokenRange ||
6997             sizeOfMethodDescs + size > MethodDescChunk::MaxSizeOfMethodDescs ||
6998             methodDescCount + currentSlotMethodDescCount > maxPrecodesPerPage)
6999         {
7000             if (sizeOfMethodDescs != 0)
7001             {
7002                 AllocAndInitMethodDescChunk(startIndex, it.CurrentIndex() - startIndex, sizeOfMethodDescs);
7003                 startIndex = it.CurrentIndex();
7004             }
7005
7006             currentTokenRange = tokenRange;
7007             sizeOfMethodDescs = 0;
7008             methodDescCount = 0;
7009         }
7010
7011         sizeOfMethodDescs += size;
7012         methodDescCount += currentSlotMethodDescCount;
7013     }
7014
7015     if (sizeOfMethodDescs != 0)
7016     {
7017         AllocAndInitMethodDescChunk(startIndex, NumDeclaredMethods() - startIndex, sizeOfMethodDescs);
7018     }
7019 }
7020
7021 //*******************************************************************************
7022 // Allocates and initializes one method desc chunk.
7023 //
7024 // Arguments:
7025 //    startIndex - index of first method in bmtMethod array.
7026 //    count - number of methods in this chunk (contiguous region from startIndex)
7027 //    sizeOfMethodDescs - total expected size of MethodDescs in this chunk
7028 //
7029 // Used by AllocAndInitMethodDescs.
7030 //
7031 VOID MethodTableBuilder::AllocAndInitMethodDescChunk(COUNT_T startIndex, COUNT_T count, SIZE_T sizeOfMethodDescs)
7032 {
7033     CONTRACTL {
7034         STANDARD_VM_CHECK;
7035         PRECONDITION(sizeOfMethodDescs <= MethodDescChunk::MaxSizeOfMethodDescs);
7036     } CONTRACTL_END;
7037
7038     void * pMem = GetMemTracker()->Track(
7039         GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(TADDR) + sizeof(MethodDescChunk) + sizeOfMethodDescs)));
7040
7041     // Skip pointer to temporary entrypoints
7042     MethodDescChunk * pChunk = (MethodDescChunk *)((BYTE*)pMem + sizeof(TADDR));
7043
7044     COUNT_T methodDescCount = 0;
7045
7046     SIZE_T offset = sizeof(MethodDescChunk);
7047
7048 #ifdef _PREFAST_
7049 #pragma warning(push)
7050 #pragma warning(disable:22019) // Suppress PREFast warning about integer underflow
7051 #endif // _PREFAST_
7052     for (COUNT_T i = 0; i < count; i++)
7053 #ifdef _PREFAST_
7054 #pragma warning(pop)
7055 #endif // _PREFAST_
7056
7057     {
7058         bmtMDMethod * pMDMethod = (*bmtMethod)[static_cast<SLOT_INDEX>(startIndex + i)];
7059
7060         MethodDesc * pMD = (MethodDesc *)((BYTE *)pChunk + offset);
7061
7062         pMD->SetChunkIndex(pChunk);
7063         pMD->SetMethodDescIndex(methodDescCount);
7064
7065         InitNewMethodDesc(pMDMethod, pMD);
7066
7067 #ifdef _PREFAST_
7068 #pragma warning(push)
7069 #pragma warning(disable:22018) // Suppress PREFast warning about integer underflow
7070 #endif // _PREFAST_
7071         offset += pMD->SizeOf();
7072 #ifdef _PREFAST_
7073 #pragma warning(pop)
7074 #endif // _PREFAST_
7075
7076         methodDescCount++;
7077
7078         // If we're a value class, we want to create duplicate slots
7079         // and MethodDescs for all methods in the vtable
7080         // section (i.e. not non-virtual instance methods or statics).
7081         // In the name of uniformity it would be much nicer
7082         // if we created _all_ value class BoxedEntryPointStubs at this point.
7083         // However, non-virtual instance methods only require unboxing
7084         // stubs in the rare case that we create a delegate to such a
7085         // method, and thus it would be inefficient to create them on
7086         // loading: after all typical structs will have many non-virtual
7087         // instance methods.
7088         //
7089         // Unboxing stubs for non-virtual instance methods are created
7090         // in code:MethodDesc::FindOrCreateAssociatedMethodDesc.
7091
7092         if (NeedsTightlyBoundUnboxingStub(pMDMethod))
7093         {
7094             MethodDesc * pUnboxedMD = (MethodDesc *)((BYTE *)pChunk + offset);
7095
7096             //////////////////////////////////
7097             // Initialize the new MethodDesc
7098
7099             // <NICE> memcpy operations on data structures like MethodDescs are extremely fragile
7100             // and should not be used.  We should go to the effort of having proper constructors
7101             // in the MethodDesc class. </NICE>
7102
7103             memcpy(pUnboxedMD, pMD, pMD->SizeOf());
7104
7105             // Reset the chunk index
7106             pUnboxedMD->SetChunkIndex(pChunk);
7107             pUnboxedMD->SetMethodDescIndex(methodDescCount);
7108
7109             if (bmtGenerics->GetNumGenericArgs() == 0) {
7110                 pUnboxedMD->SetHasNonVtableSlot();
7111             }
7112
7113             //////////////////////////////////////////////////////////
7114             // Modify the original MethodDesc to be an unboxing stub
7115
7116             pMD->SetIsUnboxingStub();
7117
7118             ////////////////////////////////////////////////////////////////////
7119             // Add the new MethodDesc to the non-virtual portion of the vtable
7120
7121             if (!bmtVT->AddUnboxedMethod(pMDMethod))
7122                 BuildMethodTableThrowException(IDS_CLASSLOAD_TOO_MANY_METHODS);
7123
7124             pUnboxedMD->SetSlot(pMDMethod->GetUnboxedSlotIndex());
7125             pMDMethod->SetUnboxedMethodDesc(pUnboxedMD);
7126
7127             offset += pUnboxedMD->SizeOf();
7128             methodDescCount++;
7129         }
7130     }
7131     _ASSERTE(offset == sizeof(MethodDescChunk) + sizeOfMethodDescs);
7132
7133     pChunk->SetSizeAndCount(sizeOfMethodDescs, methodDescCount);
7134
7135     GetHalfBakedClass()->AddChunk(pChunk);
7136 }
7137
7138 //*******************************************************************************
7139 BOOL
7140 MethodTableBuilder::NeedsTightlyBoundUnboxingStub(bmtMDMethod * pMDMethod)
7141 {
7142     STANDARD_VM_CONTRACT;
7143
7144     return IsValueClass() &&
7145            !IsMdStatic(pMDMethod->GetDeclAttrs()) &&
7146            IsMdVirtual(pMDMethod->GetDeclAttrs()) &&
7147            (pMDMethod->GetMethodType() != mcInstantiated) &&
7148            !IsMdRTSpecialName(pMDMethod->GetDeclAttrs());
7149 }
7150
7151 //*******************************************************************************
7152 BOOL
7153 MethodTableBuilder::NeedsNativeCodeSlot(bmtMDMethod * pMDMethod)
7154 {
7155     LIMITED_METHOD_CONTRACT;
7156
7157
7158 #ifdef FEATURE_TIERED_COMPILATION
7159     // Keep in-sync with MethodDesc::DetermineAndSetIsEligibleForTieredCompilation()
7160     if ((g_pConfig->TieredCompilation() &&
7161
7162         // Policy - If QuickJit is disabled and the module does not have any pregenerated code, the method would be ineligible
7163         // for tiering currently to avoid some unnecessary overhead
7164         (g_pConfig->TieredCompilation_QuickJit() || GetModule()->IsReadyToRun()) &&
7165
7166         (pMDMethod->GetMethodType() == mcIL || pMDMethod->GetMethodType() == mcInstantiated))
7167
7168 #ifdef FEATURE_REJIT
7169         ||
7170
7171         // Methods that are R2R need precode if ReJIT is enabled. Keep this in sync with MethodDesc::IsEligibleForReJIT()
7172         (ReJitManager::IsReJITEnabled() &&
7173
7174             pMDMethod->GetMethodType() == mcIL &&
7175
7176             !GetModule()->IsCollectible() &&
7177
7178             !GetModule()->IsEditAndContinueEnabled())
7179 #endif // FEATURE_REJIT
7180         )
7181     {
7182         return TRUE;
7183     }
7184 #endif
7185
7186 #ifdef FEATURE_DEFAULT_INTERFACES
7187     if (IsInterface())
7188     {
7189         DWORD attrs = pMDMethod->GetDeclAttrs();
7190         if (!IsMdStatic(attrs) && IsMdVirtual(attrs) && !IsMdAbstract(attrs))
7191         {
7192             // Default interface method. Since interface methods currently need to have a precode, the native code slot will be
7193             // used to retrieve the native code entry point, instead of getting it from the precode, which is not reliable with
7194             // debuggers setting breakpoints.
7195             return TRUE;
7196         }
7197     }
7198 #endif
7199
7200 #if defined(FEATURE_JIT_PITCHING)
7201     if ((CLRConfig::GetConfigValue(CLRConfig::INTERNAL_JitPitchEnabled) != 0) &&
7202         (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_JitPitchMemThreshold) != 0))
7203         return TRUE;
7204 #endif
7205
7206     return GetModule()->IsEditAndContinueEnabled();
7207 }
7208
7209 //*******************************************************************************
7210 VOID
7211 MethodTableBuilder::AllocAndInitDictionary()
7212 {
7213     STANDARD_VM_CONTRACT;
7214
7215     // Allocate dictionary layout used by all compatible instantiations
7216
7217     if (bmtGenerics->fSharedByGenericInstantiations && !bmtGenerics->fContainsGenericVariables)
7218     {
7219         // We use the number of methods as a heuristic for the number of slots in the dictionary
7220         // attached to shared class method tables.
7221         // If there are no declared methods then we have no slots, and we will never do any token lookups
7222         //
7223         // Heuristics
7224         //  - Classes with a small number of methods (2-3) tend to be more likely to use new slots,
7225         //    i.e. further methods tend to reuse slots from previous methods.
7226         //      = treat all classes with only 2-3 methods as if they have an extra method.
7227         //  - Classes with more generic parameters tend to use more slots.
7228         //      = multiply by 1.5 for 2 params or more
7229
7230         DWORD numMethodsAdjusted =
7231             (bmtMethod->dwNumDeclaredNonAbstractMethods == 0)
7232             ? 0
7233             : (bmtMethod->dwNumDeclaredNonAbstractMethods < 3)
7234             ? 3
7235             : bmtMethod->dwNumDeclaredNonAbstractMethods;
7236
7237         _ASSERTE(bmtGenerics->GetNumGenericArgs() != 0);
7238         DWORD nTypeFactorBy2 = (bmtGenerics->GetNumGenericArgs() == 1)
7239                                ? 2
7240                                : 3;
7241
7242         DWORD estNumTypeSlots = (numMethodsAdjusted * nTypeFactorBy2 + 2) / 3;
7243         // estNumTypeSlots should fit in a WORD as long as we maintain the current
7244         // limit on the number of methods in a type (approx 2^16).
7245         _ASSERTE(FitsIn<WORD>(estNumTypeSlots));
7246         WORD numTypeSlots = static_cast<WORD>(estNumTypeSlots);
7247
7248         if (numTypeSlots > 0)
7249         {
7250             // Dictionary layout is an optional field on EEClass, so ensure the optional field descriptor has
7251             // been allocated.
7252             EnsureOptionalFieldsAreAllocated(GetHalfBakedClass(), m_pAllocMemTracker, GetLoaderAllocator()->GetLowFrequencyHeap());
7253             GetHalfBakedClass()->SetDictionaryLayout(DictionaryLayout::Allocate(numTypeSlots, bmtAllocator, m_pAllocMemTracker));
7254         }
7255     }
7256
7257 }
7258
7259 //*******************************************************************************
7260 //
7261 // Used by BuildMethodTable
7262 //
7263 // Compute the set of interfaces which are equivalent. Duplicates in the interface map
7264 // will be placed into different equivalence sets unless they participate in type equivalence.
7265 // This is a bit odd, but it turns out we only need to know about equivalence classes if
7266 // there is type equivalence involved in the interface, and not detecting, or detecting equivalence
7267 // in other cases does not result in differing behavior.
7268 //
7269 // By restricting the reasons for having equivalence matches, we reduce the algorithm from one which
7270 // is O(n*n) best case to an algorithm which will typically execute something more like O(m*n) best case time
7271 // where m is the number of generic interface (although still n*n in worst case). The assumption is that equivalent
7272 // and generic interfaces are relatively rare.
7273 VOID
7274 MethodTableBuilder::ComputeInterfaceMapEquivalenceSet()
7275 {
7276     STANDARD_VM_CONTRACT;
7277
7278     UINT32 nextEquivalenceSet = 1;
7279
7280     for (DWORD dwCurInterface = 0;
7281          dwCurInterface < bmtInterface->dwInterfaceMapSize;
7282          dwCurInterface++)
7283     {
7284         // Keep track of the current interface we are trying to calculate the equivalence set of
7285         bmtInterfaceEntry *     pCurItfEntry = &bmtInterface->pInterfaceMap[dwCurInterface];
7286         bmtRTType *             pCurItf      = pCurItfEntry->GetInterfaceType();
7287         MethodTable *           pCurItfMT    = pCurItf->GetMethodTable();
7288         const Substitution *    pCurItfSubst = &pCurItf->GetSubstitution();
7289
7290         UINT32 currentEquivalenceSet = 0;
7291
7292         // Only interfaces with type equivalence, or that are generic need to be compared for equivalence
7293         if (pCurItfMT->HasTypeEquivalence() || pCurItfMT->HasInstantiation())
7294         {
7295             for (DWORD dwCurInterfaceCompare = 0;
7296                  dwCurInterfaceCompare < dwCurInterface;
7297                  dwCurInterfaceCompare++)
7298             {
7299                 // Keep track of the current interface we are trying to calculate the equivalence set of
7300                 bmtInterfaceEntry *     pCompareItfEntry = &bmtInterface->pInterfaceMap[dwCurInterfaceCompare];
7301                 bmtRTType *             pCompareItf      = pCompareItfEntry->GetInterfaceType();
7302                 MethodTable *           pCompareItfMT    = pCompareItf->GetMethodTable();
7303                 const Substitution *    pCompareItfSubst = &pCompareItf->GetSubstitution();
7304
7305                 // Only interfaces with type equivalence, or that are generic need to be compared for equivalence
7306                 if (pCompareItfMT->HasTypeEquivalence() || pCompareItfMT->HasInstantiation())
7307                 {
7308                     if (MetaSig::CompareTypeDefsUnderSubstitutions(pCurItfMT,
7309                                                                    pCompareItfMT,
7310                                                                    pCurItfSubst,
7311                                                                    pCompareItfSubst,
7312                                                                    NULL))
7313                     {
7314                         currentEquivalenceSet = pCompareItfEntry->GetInterfaceEquivalenceSet();
7315                         // Use the equivalence set of the interface map entry we just found
7316                         pCurItfEntry->SetInterfaceEquivalenceSet(currentEquivalenceSet, true);
7317                         // Update the interface map entry we just found to indicate that it is part of an equivalence
7318                         // set with multiple entries.
7319                         pCompareItfEntry->SetInterfaceEquivalenceSet(currentEquivalenceSet, true);
7320                         break;
7321                     }
7322                 }
7323             }
7324         }
7325
7326         // If we did not find an equivalent interface above, use the next available equivalence set indicator
7327         if (currentEquivalenceSet == 0)
7328         {
7329             pCurItfEntry->SetInterfaceEquivalenceSet(nextEquivalenceSet, false);
7330             nextEquivalenceSet++;
7331         }
7332     }
7333 }
7334
7335 //*******************************************************************************
7336 //
7337 // Used by PlaceInterfaceMethods
7338 //
7339 // Given an interface in our interface map, and a particular method on that interface, place
7340 // a method from the parent types implementation of an equivalent interface into that method
7341 // slot. Used by PlaceInterfaceMethods to make equivalent interface implementations have the
7342 // same behavior as if the parent interface was implemented on this type instead of an equivalent interface.
7343 //
7344 // This logic is used in situations such as below. I and I' are equivalent interfaces
7345 //
7346 //#
7347 // class Base : I
7348 // {void I.Method() { } }
7349 // interface IOther : I' {}
7350 // class Derived : IOther
7351 // { virtual void Method() {}}
7352 //
7353 // We should Map I'.Method to Base.Method, not Derived.Method
7354 //
7355 // Another example
7356 // class Base : I
7357 // { virtual void Method() }
7358 // interface IOther : I' {}
7359 // class Derived : IOther
7360 // { virtual void Method() {}}
7361 //
7362 // We should map I'.Method to Base.Method, not Derived.Method
7363 //
7364 // class Base : I
7365 // {void I.Method() { } }
7366 // class Derived : I'
7367 // {}
7368 //
7369 // We should Map I'.Method to Base.Method, and not throw TypeLoadException
7370 //
7371 #ifdef FEATURE_COMINTEROP
7372 VOID
7373 MethodTableBuilder::PlaceMethodFromParentEquivalentInterfaceIntoInterfaceSlot(
7374     bmtInterfaceEntry::InterfaceSlotIterator & itfSlotIt,
7375     bmtInterfaceEntry *                        pCurItfEntry,
7376     DispatchMapTypeID **                       prgInterfaceDispatchMapTypeIDs,
7377     DWORD                                      dwCurInterface)
7378 {
7379     STANDARD_VM_CONTRACT;
7380
7381     bmtRTMethod * pCurItfMethod = itfSlotIt->Decl().AsRTMethod();
7382
7383     if (itfSlotIt->Impl() != INVALID_SLOT_INDEX)
7384     {
7385         return;
7386     }
7387
7388     // For every equivalent interface entry that was actually implemented by parent, then look at equivalent method slot on that entry
7389     // and if it matches and has a slot implementation, then record and continue
7390     for (DWORD dwEquivalentInterface = 0;
7391          (dwEquivalentInterface < bmtInterface->dwInterfaceMapSize) && (itfSlotIt->Impl() == INVALID_SLOT_INDEX);
7392          dwEquivalentInterface++)
7393     {
7394         bmtInterfaceEntry *  pEquivItfEntry = &bmtInterface->pInterfaceMap[dwEquivalentInterface];
7395         bmtRTType *          pEquivItf      = pEquivItfEntry->GetInterfaceType();
7396         MethodTable *        pEquivItfMT    = pEquivItf->GetMethodTable();
7397         const Substitution * pEquivItfSubst = &pEquivItf->GetSubstitution();
7398         if (pEquivItfEntry->GetInterfaceEquivalenceSet() != pCurItfEntry->GetInterfaceEquivalenceSet())
7399         {
7400             // Not equivalent
7401             continue;
7402         }
7403         if (!pEquivItfEntry->IsImplementedByParent())
7404         {
7405             // Not implemented by parent
7406             continue;
7407         }
7408
7409         WORD slot = static_cast<WORD>(itfSlotIt.CurrentIndex());
7410         BOOL fFound = FALSE;
7411
7412         // Determine which slot on the equivalent interface would map to the slot we are attempting to fill
7413         // in with an implementation.
7414         WORD otherMTSlot = GetEquivalentMethodSlot(pCurItfEntry->GetInterfaceType()->GetMethodTable(),
7415                                                    pEquivItfEntry->GetInterfaceType()->GetMethodTable(),
7416                                                    slot,
7417                                                    &fFound);
7418
7419         if (fFound)
7420         {
7421             UINT32 cInterfaceDuplicates;
7422             if (*prgInterfaceDispatchMapTypeIDs == NULL)
7423             {
7424                 *prgInterfaceDispatchMapTypeIDs =
7425                     new (GetStackingAllocator()) DispatchMapTypeID[bmtInterface->dwInterfaceMapSize];
7426             }
7427
7428             // Compute all TypeIDs for this interface (all duplicates in the interface map)
7429             ComputeDispatchMapTypeIDs(
7430                 pEquivItfMT,
7431                 pEquivItfSubst,
7432                 *prgInterfaceDispatchMapTypeIDs,
7433                 bmtInterface->dwInterfaceMapSize,
7434                 &cInterfaceDuplicates);
7435             // There cannot be more duplicates than number of interfaces
7436             _ASSERTE(cInterfaceDuplicates <= bmtInterface->dwInterfaceMapSize);
7437             _ASSERTE(cInterfaceDuplicates > 0);
7438
7439             // NOTE: This override does not cache the resulting MethodData object
7440             MethodTable::MethodDataWrapper hParentData;
7441             hParentData = MethodTable::GetMethodData(
7442                     *prgInterfaceDispatchMapTypeIDs,
7443                     cInterfaceDuplicates,
7444                     pEquivItfMT,
7445                     GetParentMethodTable());
7446
7447             SLOT_INDEX slotIndex = static_cast<SLOT_INDEX>
7448                 (hParentData->GetImplSlotNumber(static_cast<UINT32>(otherMTSlot)));
7449
7450             // Interface is implemented on parent abstract type and this particular slot was not implemented
7451             if (slotIndex == INVALID_SLOT_INDEX)
7452             {
7453                 continue;
7454             }
7455
7456             bmtMethodSlot & parentSlotImplementation = (*bmtParent->pSlotTable)[slotIndex];
7457             bmtMethodHandle & parentImplementation = parentSlotImplementation.Impl();
7458
7459             // Check to verify that the equivalent slot on the equivalent interface actually matches the method
7460             // on the current interface. If not, then the slot is not a match, and we should search other interfaces
7461             // for an implementation of the method.
7462             if (!MethodSignature::SignaturesEquivalent(pCurItfMethod->GetMethodSignature(), parentImplementation.GetMethodSignature(), FALSE))
7463             {
7464                 continue;
7465             }
7466
7467             itfSlotIt->Impl() = slotIndex;
7468
7469             MethodDesc * pMD = hParentData->GetImplMethodDesc(static_cast<UINT32>(otherMTSlot));
7470
7471             DispatchMapTypeID dispatchMapTypeID =
7472                 DispatchMapTypeID::InterfaceClassID(dwCurInterface);
7473             bmtVT->pDispatchMapBuilder->InsertMDMapping(
7474                 dispatchMapTypeID,
7475                 static_cast<UINT32>(itfSlotIt.CurrentIndex()),
7476                 pMD,
7477                 FALSE);
7478         }
7479     }
7480 } // MethodTableBuilder::PlaceMethodFromParentEquivalentInterfaceIntoInterfaceSlot
7481 #endif // FEATURE_COMINTEROP
7482
7483 //*******************************************************************************
7484 //
7485 // Used by BuildMethodTable
7486 //
7487 //
7488 // If we are a class, then there may be some unplaced vtable methods (which are by definition
7489 // interface methods, otherwise they'd already have been placed).  Place as many unplaced methods
7490 // as possible, in the order preferred by interfaces.  However, do not allow any duplicates - once
7491 // a method has been placed, it cannot be placed again - if we are unable to neatly place an interface,
7492 // create duplicate slots for it starting at dwCurrentDuplicateVtableSlot.  Fill out the interface
7493 // map for all interfaces as they are placed.
7494 //
7495 // If we are an interface, then all methods are already placed.  Fill out the interface map for
7496 // interfaces as they are placed.
7497 //
7498 // BEHAVIOUR (based on Partition II: 11.2, not including MethodImpls)
7499 //   C is current class, P is a parent class, I is the interface being implemented
7500 //
7501 //   FOREACH interface I implemented by this class C
7502 //     FOREACH method I::M
7503 //       IF I is EXPLICITLY implemented by C
7504 //         IF some method C::M matches I::M
7505 //           USE C::M as implementation for I::M
7506 //         ELIF we inherit a method P::M that matches I::M
7507 //           USE P::M as implementation for I::M
7508 //         ENDIF
7509 //       ELSE
7510 //         IF I::M lacks implementation
7511 //           IF some method C::M matches I::M
7512 //             USE C::M as implementation for I::M
7513 //           ELIF we inherit a method P::M that matches I::M
7514 //             USE P::M as implementation for I::M
7515 //           ELIF I::M was implemented by the parent type with method Parent::M
7516 //             USE Parent::M for the implementation of I::M // VSD does this by default if we really
7517 //                                                           // implemented I on the parent type, but
7518 //                                                           // equivalent interfaces need to make this
7519 //                                                           // explicit
7520 //           ENDIF
7521 //         ENDIF
7522 //       ENDIF
7523 //     ENDFOR
7524 //   ENDFOR
7525 //
7526
7527 VOID
7528 MethodTableBuilder::PlaceInterfaceMethods()
7529 {
7530     STANDARD_VM_CONTRACT;
7531
7532     BOOL fParentInterface;
7533     DispatchMapTypeID * rgInterfaceDispatchMapTypeIDs = NULL;
7534
7535     for (DWORD dwCurInterface = 0;
7536          dwCurInterface < bmtInterface->dwInterfaceMapSize;
7537          dwCurInterface++)
7538     {
7539         // Default to being implemented by the current class
7540         fParentInterface = FALSE;
7541
7542         // Keep track of the current interface we are trying to place
7543         bmtInterfaceEntry *     pCurItfEntry = &bmtInterface->pInterfaceMap[dwCurInterface];
7544         bmtRTType *             pCurItf      = pCurItfEntry->GetInterfaceType();
7545         MethodTable *           pCurItfMT    = pCurItf->GetMethodTable();
7546         const Substitution *    pCurItfSubst = &pCurItf->GetSubstitution();
7547
7548         //
7549         // There are three reasons why an interface could be in the implementation list
7550         // 1. Inherited from parent
7551         // 2. Explicitly declared in the implements list
7552         // 3. Implicitly declared through the implements list of an explicitly declared interface
7553         //
7554         // The reason these cases need to be distinguished is that an inherited interface that is
7555         // also explicitly redeclared in the implements list must be fully reimplemented using the
7556         // virtual methods of this type (thereby using matching methods in this type that may have
7557         // a different slot than an inherited method, but hidden it by name & sig); however all
7558         // implicitly redeclared interfaces should not be fully reimplemented if they were also
7559         // inherited from the parent.
7560         //
7561         // Example:
7562         //   interface I1 : I2
7563         //   class A : I1
7564         //   class B : A, I1
7565         //
7566         // In this example I1 must be fully reimplemented on B, but B can inherit the implementation
7567         // of I2.
7568         //
7569
7570         if (pCurItfEntry->IsImplementedByParent())
7571         {
7572             if (!pCurItfEntry->IsDeclaredOnType())
7573             {
7574                 fParentInterface = TRUE;
7575             }
7576         }
7577
7578         bool fEquivalentInterfaceImplementedByParent = pCurItfEntry->IsImplementedByParent();
7579         bool fEquivalentInterfaceDeclaredOnType = pCurItfEntry->IsDeclaredOnType();
7580
7581         if (pCurItfEntry->InEquivalenceSetWithMultipleEntries())
7582         {
7583             for (DWORD dwEquivalentInterface = 0;
7584                  dwEquivalentInterface < bmtInterface->dwInterfaceMapSize;
7585                  dwEquivalentInterface++)
7586             {
7587                 bmtInterfaceEntry *     pEquivItfEntry = &bmtInterface->pInterfaceMap[dwEquivalentInterface];
7588                 if (pEquivItfEntry->GetInterfaceEquivalenceSet() != pCurItfEntry->GetInterfaceEquivalenceSet())
7589                 {
7590                     // Not equivalent
7591                     continue;
7592                 }
7593                 if (pEquivItfEntry->IsImplementedByParent())
7594                 {
7595                     fEquivalentInterfaceImplementedByParent = true;
7596                 }
7597                 if (pEquivItfEntry->IsDeclaredOnType())
7598                 {
7599                     fEquivalentInterfaceDeclaredOnType = true;
7600                 }
7601
7602                 if (fEquivalentInterfaceDeclaredOnType && fEquivalentInterfaceImplementedByParent)
7603                     break;
7604             }
7605         }
7606
7607         bool fParentInterfaceEquivalent = fEquivalentInterfaceImplementedByParent && !fEquivalentInterfaceDeclaredOnType;
7608
7609         CONSISTENCY_CHECK(!fParentInterfaceEquivalent || HasParent());
7610
7611         if (fParentInterfaceEquivalent)
7612         {
7613             // In the case the fParentInterface is TRUE, virtual overrides are enough and the interface
7614             // does not have to be explicitly (re)implemented. The only exception is if the parent is
7615             // abstract, in which case an inherited interface may not be fully implemented yet.
7616             // This is an optimization that allows us to skip the more expensive slot filling in below.
7617             // Note that the check here is for fParentInterface and not for fParentInterfaceEquivalent.
7618             // This is necessary as if the interface is not actually implemented on the parent type we will
7619             // need to fill in the slot table below.
7620             if (fParentInterface && !GetParentMethodTable()->IsAbstract())
7621             {
7622                 continue;
7623             }
7624
7625             {
7626                 // We will reach here in two cases.
7627                 // 1 .The parent is abstract and the interface has been declared on the parent,
7628                 // and possibly partially implemented, so we need to populate the
7629                 // bmtInterfaceSlotImpl table for this interface with the implementation slot
7630                 // information.
7631                 // 2 .The the interface has not been declared on the parent,
7632                 // but an equivalent interface has been. So we need to populate the
7633                 // bmtInterfaceSlotImpl table for this interface with the implementation slot
7634                 // information from one of the parent equivalent interfaces. We may or may not
7635                 // find implementations for all of the methods on the interface on the parent type.
7636                 // The parent type may or may not be abstract.
7637
7638                 MethodTable::MethodDataWrapper hParentData;
7639                 CONSISTENCY_CHECK(CheckPointer(GetParentMethodTable()));
7640
7641                 if (rgInterfaceDispatchMapTypeIDs == NULL)
7642                 {
7643                     rgInterfaceDispatchMapTypeIDs =
7644                         new (GetStackingAllocator()) DispatchMapTypeID[bmtInterface->dwInterfaceMapSize];
7645                 }
7646
7647                 if (pCurItfEntry->IsImplementedByParent())
7648                 {
7649                     UINT32 cInterfaceDuplicates;
7650                     // Compute all TypeIDs for this interface (all duplicates in the interface map)
7651                     ComputeDispatchMapTypeIDs(
7652                         pCurItfMT,
7653                         pCurItfSubst,
7654                         rgInterfaceDispatchMapTypeIDs,
7655                         bmtInterface->dwInterfaceMapSize,
7656                         &cInterfaceDuplicates);
7657                     // There cannot be more duplicates than number of interfaces
7658                     _ASSERTE(cInterfaceDuplicates <= bmtInterface->dwInterfaceMapSize);
7659                     _ASSERTE(cInterfaceDuplicates > 0);
7660
7661                     //#InterfaceMap_UseParentInterfaceImplementations
7662                     // We rely on the fact that interface map of parent type is subset of this type (incl.
7663                     // duplicates), see code:#InterfaceMap_SupersetOfParent
7664                     // NOTE: This override does not cache the resulting MethodData object
7665                     hParentData = MethodTable::GetMethodData(
7666                             rgInterfaceDispatchMapTypeIDs,
7667                             cInterfaceDuplicates,
7668                             pCurItfMT,
7669                             GetParentMethodTable());
7670
7671                     bmtInterfaceEntry::InterfaceSlotIterator itfSlotIt =
7672                         pCurItfEntry->IterateInterfaceSlots(GetStackingAllocator());
7673                     for (; !itfSlotIt.AtEnd(); itfSlotIt.Next())
7674                     {
7675                         itfSlotIt->Impl() = static_cast<SLOT_INDEX>
7676                             (hParentData->GetImplSlotNumber(static_cast<UINT32>(itfSlotIt.CurrentIndex())));
7677                     }
7678                 }
7679 #ifdef FEATURE_COMINTEROP
7680                 else
7681                 {
7682                     // Iterate through the methods on the interface, and if they have a slot which was filled in
7683                     // on an equivalent interface inherited from the parent fill in the appropriate slot.
7684                     // This code path is only used when there is an implicit implementation of an interface
7685                     // that was not implemented on a parent type, but there was an equivalent interface implemented
7686                     // on a parent type.
7687                     bmtInterfaceEntry::InterfaceSlotIterator itfSlotIt =
7688                         pCurItfEntry->IterateInterfaceSlots(GetStackingAllocator());
7689                     for (; !itfSlotIt.AtEnd(); itfSlotIt.Next())
7690                     {
7691                         PlaceMethodFromParentEquivalentInterfaceIntoInterfaceSlot(itfSlotIt, pCurItfEntry, &rgInterfaceDispatchMapTypeIDs, dwCurInterface);
7692                     }
7693                 }
7694 #endif // FEATURE_COMINTEROP
7695             }
7696         }
7697
7698         // For each method declared in this interface
7699         bmtInterfaceEntry::InterfaceSlotIterator itfSlotIt =
7700             pCurItfEntry->IterateInterfaceSlots(GetStackingAllocator());
7701         for (; !itfSlotIt.AtEnd(); ++itfSlotIt)
7702         {
7703             if (fParentInterfaceEquivalent)
7704             {
7705                 if (itfSlotIt->Impl() != INVALID_SLOT_INDEX)
7706                 {   // If this interface is not explicitly declared on this class, and the interface slot has already been
7707                     // given an implementation, then the only way to provide a new implementation is through an override
7708                     // or through a MethodImpl. This is necessary in addition to the continue statement before this for
7709                     // loop because an abstract interface can still have a partial implementation and it is necessary to
7710                     // skip those interface slots that have already been satisfied.
7711                     continue;
7712                 }
7713             }
7714
7715             BOOL                    fFoundMatchInBuildingClass = FALSE;
7716             bmtInterfaceSlotImpl &  curItfSlot = *itfSlotIt;
7717             bmtRTMethod *           pCurItfMethod = curItfSlot.Decl().AsRTMethod();
7718             const MethodSignature & curItfMethodSig = pCurItfMethod->GetMethodSignature();
7719
7720             //
7721             // First, try to find the method explicitly declared in our class
7722             //
7723
7724             DeclaredMethodIterator methIt(*this);
7725             while (methIt.Next())
7726             {
7727                 // Note that non-publics can legally be exposed via an interface, but only
7728                 // through methodImpls.
7729                 if (IsMdVirtual(methIt.Attrs()) && IsMdPublic(methIt.Attrs()))
7730                 {
7731 #ifdef _DEBUG
7732                     if(GetHalfBakedClass()->m_fDebuggingClass && g_pConfig->ShouldBreakOnMethod(methIt.Name()))
7733                         CONSISTENCY_CHECK_MSGF(false, ("BreakOnMethodName: '%s' ", methIt.Name()));
7734 #endif // _DEBUG
7735
7736                     if (pCurItfMethod->GetMethodSignature().Equivalent(methIt->GetMethodSignature()))
7737                     {
7738                         fFoundMatchInBuildingClass = TRUE;
7739                         curItfSlot.Impl() = methIt->GetSlotIndex();
7740
7741                         DispatchMapTypeID dispatchMapTypeID =
7742                             DispatchMapTypeID::InterfaceClassID(dwCurInterface);
7743                         bmtVT->pDispatchMapBuilder->InsertMDMapping(
7744                             dispatchMapTypeID,
7745                             static_cast<UINT32>(itfSlotIt.CurrentIndex()),
7746                             methIt->GetMethodDesc(),
7747                             FALSE);
7748
7749                         break;
7750                     }
7751                 }
7752             } // end ... try to find method
7753
7754             //
7755             // The ECMA CLR spec states that a type will inherit interface implementations
7756             // and that explicit re-declaration of an inherited interface will try to match
7757             // only newslot methods with methods in the re-declared interface (note that
7758             // this also takes care of matching against unsatisfied interface methods in
7759             // the abstract parent type scenario).
7760             //
7761             // So, if the interface was not declared on a parent and we haven't found a
7762             // newslot method declared on this type as a match, search all remaining
7763             // public virtual methods (including overrides declared on this type) for a
7764             // match.
7765             //
7766             // Please see bug VSW577403 and VSW593884 for details of this breaking change.
7767             //
7768             if (!fFoundMatchInBuildingClass &&
7769                 !fEquivalentInterfaceImplementedByParent)
7770             {
7771                 if (HasParent())
7772                 {
7773                     // Iterate backward through the parent's method table. This is important to
7774                     // find the most derived method.
7775                     bmtParentInfo::Iterator parentMethodIt = bmtParent->IterateSlots();
7776                     parentMethodIt.ResetToEnd();
7777                     while (parentMethodIt.Prev())
7778                     {
7779                         bmtRTMethod * pCurParentMethod = parentMethodIt->Decl().AsRTMethod();
7780                         DWORD dwAttrs = pCurParentMethod->GetDeclAttrs();
7781                         if (!IsMdVirtual(dwAttrs) || !IsMdPublic(dwAttrs))
7782                         {   // Only match mdPublic mdVirtual methods for interface implementation
7783                             continue;
7784                         }
7785
7786                         if (curItfMethodSig.Equivalent(pCurParentMethod->GetMethodSignature()))
7787                         {
7788                             fFoundMatchInBuildingClass = TRUE;
7789                             curItfSlot.Impl() = pCurParentMethod->GetSlotIndex();
7790
7791                             DispatchMapTypeID dispatchMapTypeID =
7792                                 DispatchMapTypeID::InterfaceClassID(dwCurInterface);
7793                             bmtVT->pDispatchMapBuilder->InsertMDMapping(
7794                                 dispatchMapTypeID,
7795                                 static_cast<UINT32>(itfSlotIt.CurrentIndex()),
7796                                 pCurParentMethod->GetMethodDesc(),
7797                                 FALSE);
7798
7799                             break;
7800                         }
7801                     } // end ... try to find parent method
7802                 }
7803             }
7804
7805             // For type equivalent interfaces that had an equivalent interface implemented by their parent
7806             // and where the previous logic to fill in the method based on the virtual mappings on the type have
7807             // failed, we should attempt to get the mappings from the equivalent interfaces declared on parent types
7808             // of the type we are currently building.
7809 #ifdef FEATURE_COMINTEROP
7810             if (!fFoundMatchInBuildingClass && fEquivalentInterfaceImplementedByParent && !pCurItfEntry->IsImplementedByParent())
7811             {
7812                 PlaceMethodFromParentEquivalentInterfaceIntoInterfaceSlot(itfSlotIt, pCurItfEntry, &rgInterfaceDispatchMapTypeIDs, dwCurInterface);
7813             }
7814 #endif
7815         }
7816     }
7817 } // MethodTableBuilder::PlaceInterfaceMethods
7818
7819
7820 //*******************************************************************************
7821 //
7822 // Used by BuildMethodTable
7823 //
7824 // Place static fields
7825 //
7826 VOID MethodTableBuilder::PlaceRegularStaticFields()
7827 {
7828     STANDARD_VM_CONTRACT;
7829
7830     DWORD i;
7831
7832     LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Placing statics for %s\n", this->GetDebugClassName()));
7833
7834     //
7835     // Place gc refs and value types first, as they need to have handles created for them.
7836     // (Placing them together allows us to easily create the handles when Restoring the class,
7837     // and when initializing new DLS for the class.)
7838     //
7839
7840     DWORD   dwCumulativeStaticFieldPos = 0 ;
7841     DWORD   dwCumulativeStaticGCFieldPos = 0;
7842     DWORD   dwCumulativeStaticBoxFieldPos = 0;
7843
7844     // We don't need to do any calculations for the gc refs or valuetypes, as they're
7845     // guaranteed to be aligned in ModuleStaticsInfo
7846     bmtFP->NumRegularStaticFieldsOfSize[LOG2_PTRSIZE] -=
7847         bmtFP->NumRegularStaticGCBoxedFields + bmtFP->NumRegularStaticGCPointerFields;
7848
7849     // Place fields, largest first, padding so that each group is aligned to its natural size
7850     for (i = MAX_LOG2_PRIMITIVE_FIELD_SIZE; (signed int) i >= 0; i--)
7851     {
7852         // Fields of this size start at the next available location
7853         bmtFP->RegularStaticFieldStart[i] = dwCumulativeStaticFieldPos;
7854         dwCumulativeStaticFieldPos += (bmtFP->NumRegularStaticFieldsOfSize[i] << i);
7855
7856         // Reset counters for the loop after this one
7857         bmtFP->NumRegularStaticFieldsOfSize[i]    = 0;
7858     }
7859
7860
7861     if (dwCumulativeStaticFieldPos > FIELD_OFFSET_LAST_REAL_OFFSET)
7862         BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
7863
7864     DWORD dwNumHandleStatics = bmtFP->NumRegularStaticGCBoxedFields + bmtFP->NumRegularStaticGCPointerFields;
7865     if (!FitsIn<WORD>(dwNumHandleStatics))
7866     {   // Overflow.
7867         BuildMethodTableThrowException(IDS_EE_TOOMANYFIELDS);
7868     }
7869     SetNumHandleRegularStatics(static_cast<WORD>(dwNumHandleStatics));
7870
7871     if (!FitsIn<WORD>(bmtFP->NumRegularStaticGCBoxedFields))
7872     {   // Overflow.
7873         BuildMethodTableThrowException(IDS_EE_TOOMANYFIELDS);
7874     }
7875     SetNumBoxedRegularStatics(static_cast<WORD>(bmtFP->NumRegularStaticGCBoxedFields));
7876
7877     // Tell the module to give us the offsets we'll be using and commit space for us
7878     // if necessary
7879     DWORD dwNonGCOffset, dwGCOffset;
7880     GetModule()->GetOffsetsForRegularStaticData(bmtInternal->pType->GetTypeDefToken(),
7881                                                 bmtProp->fDynamicStatics,
7882                                                 GetNumHandleRegularStatics(), dwCumulativeStaticFieldPos,
7883                                                 &dwGCOffset, &dwNonGCOffset);
7884
7885     // Allocate boxed statics first ("x << LOG2_PTRSIZE" is equivalent to "x * sizeof(void *)")
7886     dwCumulativeStaticGCFieldPos = bmtFP->NumRegularStaticGCBoxedFields<<LOG2_PTRSIZE;
7887
7888     FieldDesc *pFieldDescList = GetApproxFieldDescListRaw();
7889     // Place static fields
7890     for (i = 0; i < bmtEnumFields->dwNumStaticFields - bmtEnumFields->dwNumThreadStaticFields; i++)
7891     {
7892         FieldDesc * pCurField   = &pFieldDescList[bmtEnumFields->dwNumInstanceFields+i];
7893         DWORD dwLog2FieldSize   = (DWORD)(DWORD_PTR&)pCurField->m_pMTOfEnclosingClass; // log2(field size)
7894         DWORD dwOffset          = (DWORD) pCurField->m_dwOffset; // offset or type of field
7895
7896         switch (dwOffset)
7897         {
7898         case FIELD_OFFSET_UNPLACED_GC_PTR:
7899             // Place GC reference static field
7900             pCurField->SetOffset(dwCumulativeStaticGCFieldPos + dwGCOffset);
7901             dwCumulativeStaticGCFieldPos += 1<<LOG2_PTRSIZE;
7902             LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Field placed at GC offset 0x%x\n", pCurField->GetOffset()));
7903
7904             break;
7905
7906         case FIELD_OFFSET_VALUE_CLASS:
7907             // Place boxed GC reference static field
7908             pCurField->SetOffset(dwCumulativeStaticBoxFieldPos + dwGCOffset);
7909             dwCumulativeStaticBoxFieldPos += 1<<LOG2_PTRSIZE;
7910             LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Field placed at GC offset 0x%x\n", pCurField->GetOffset()));
7911
7912             break;
7913
7914         case FIELD_OFFSET_UNPLACED:
7915             // Place non-GC static field
7916             pCurField->SetOffset(bmtFP->RegularStaticFieldStart[dwLog2FieldSize] +
7917                                  (bmtFP->NumRegularStaticFieldsOfSize[dwLog2FieldSize] << dwLog2FieldSize) +
7918                                  dwNonGCOffset);
7919             bmtFP->NumRegularStaticFieldsOfSize[dwLog2FieldSize]++;
7920             LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Field placed at non GC offset 0x%x\n", pCurField->GetOffset()));
7921             break;
7922
7923         default:
7924             // RVA field
7925             break;
7926         }
7927
7928         LOG((LF_CLASSLOADER, LL_INFO1000000, "Offset of %s: %i\n", pCurField->m_debugName, pCurField->GetOffset()));
7929     }
7930
7931     if (bmtProp->fDynamicStatics)
7932     {
7933         _ASSERTE(dwNonGCOffset == 0 ||  // no statics at all
7934                  dwNonGCOffset == OFFSETOF__DomainLocalModule__NormalDynamicEntry__m_pDataBlob); // We need space to point to the GC statics
7935         bmtProp->dwNonGCRegularStaticFieldBytes = dwCumulativeStaticFieldPos;
7936     }
7937     else
7938     {
7939         bmtProp->dwNonGCRegularStaticFieldBytes = 0; // Non dynamics shouldnt be using this
7940     }
7941     LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Static field bytes needed (0 is normal for non dynamic case)%i\n", bmtProp->dwNonGCRegularStaticFieldBytes));
7942 }
7943
7944
7945 VOID MethodTableBuilder::PlaceThreadStaticFields()
7946 {
7947     STANDARD_VM_CONTRACT;
7948
7949     DWORD i;
7950
7951     LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: Placing ThreadStatics for %s\n", this->GetDebugClassName()));
7952
7953     //
7954     // Place gc refs and value types first, as they need to have handles created for them.
7955     // (Placing them together allows us to easily create the handles when Restoring the class,
7956     // and when initializing new DLS for the class.)
7957     //
7958
7959     DWORD   dwCumulativeStaticFieldPos = 0 ;
7960     DWORD   dwCumulativeStaticGCFieldPos = 0;
7961     DWORD   dwCumulativeStaticBoxFieldPos = 0;
7962
7963     // We don't need to do any calculations for the gc refs or valuetypes, as they're
7964     // guaranteed to be aligned in ModuleStaticsInfo
7965     bmtFP->NumThreadStaticFieldsOfSize[LOG2_PTRSIZE] -=
7966         bmtFP->NumThreadStaticGCBoxedFields + bmtFP->NumThreadStaticGCPointerFields;
7967
7968     // Place fields, largest first, padding so that each group is aligned to its natural size
7969     for (i = MAX_LOG2_PRIMITIVE_FIELD_SIZE; (signed int) i >= 0; i--)
7970     {
7971         // Fields of this size start at the next available location
7972         bmtFP->ThreadStaticFieldStart[i] = dwCumulativeStaticFieldPos;
7973         dwCumulativeStaticFieldPos += (bmtFP->NumThreadStaticFieldsOfSize[i] << i);
7974
7975         // Reset counters for the loop after this one
7976         bmtFP->NumThreadStaticFieldsOfSize[i]    = 0;
7977     }
7978
7979
7980     if (dwCumulativeStaticFieldPos > FIELD_OFFSET_LAST_REAL_OFFSET)
7981         BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
7982
7983     DWORD dwNumHandleStatics = bmtFP->NumThreadStaticGCBoxedFields + bmtFP->NumThreadStaticGCPointerFields;
7984     if (!FitsIn<WORD>(dwNumHandleStatics))
7985     {   // Overflow.
7986         BuildMethodTableThrowException(IDS_EE_TOOMANYFIELDS);
7987     }
7988
7989     SetNumHandleThreadStatics(static_cast<WORD>(dwNumHandleStatics));
7990
7991     if (!FitsIn<WORD>(bmtFP->NumThreadStaticGCBoxedFields))
7992     {   // Overflow.
7993         BuildMethodTableThrowException(IDS_EE_TOOMANYFIELDS);
7994     }
7995
7996     SetNumBoxedThreadStatics(static_cast<WORD>(bmtFP->NumThreadStaticGCBoxedFields));
7997
7998     // Tell the module to give us the offsets we'll be using and commit space for us
7999     // if necessary
8000     DWORD dwNonGCOffset, dwGCOffset;
8001
8002     GetModule()->GetOffsetsForThreadStaticData(bmtInternal->pType->GetTypeDefToken(),
8003                                                bmtProp->fDynamicStatics,
8004                                                GetNumHandleThreadStatics(), dwCumulativeStaticFieldPos,
8005                                                &dwGCOffset, &dwNonGCOffset);
8006
8007     // Allocate boxed statics first ("x << LOG2_PTRSIZE" is equivalent to "x * sizeof(void *)")
8008     dwCumulativeStaticGCFieldPos = bmtFP->NumThreadStaticGCBoxedFields<<LOG2_PTRSIZE;
8009
8010     FieldDesc *pFieldDescList = GetHalfBakedClass()->GetFieldDescList();
8011     // Place static fields
8012     for (i = 0; i < bmtEnumFields->dwNumThreadStaticFields; i++)
8013     {
8014         FieldDesc * pCurField   = &pFieldDescList[bmtEnumFields->dwNumInstanceFields + bmtEnumFields->dwNumStaticFields - bmtEnumFields->dwNumThreadStaticFields + i];
8015         DWORD dwLog2FieldSize   = (DWORD)(DWORD_PTR&)pCurField->m_pMTOfEnclosingClass; // log2(field size)
8016         DWORD dwOffset          = (DWORD) pCurField->m_dwOffset; // offset or type of field
8017
8018         switch (dwOffset)
8019         {
8020         case FIELD_OFFSET_UNPLACED_GC_PTR:
8021             // Place GC reference static field
8022             pCurField->SetOffset(dwCumulativeStaticGCFieldPos + dwGCOffset);
8023             dwCumulativeStaticGCFieldPos += 1<<LOG2_PTRSIZE;
8024             LOG((LF_CLASSLOADER, LL_INFO10000, "THREAD STATICS: Field placed at GC offset 0x%x\n", pCurField->GetOffset()));
8025
8026             break;
8027
8028         case FIELD_OFFSET_VALUE_CLASS:
8029             // Place boxed GC reference static field
8030             pCurField->SetOffset(dwCumulativeStaticBoxFieldPos + dwGCOffset);
8031             dwCumulativeStaticBoxFieldPos += 1<<LOG2_PTRSIZE;
8032             LOG((LF_CLASSLOADER, LL_INFO10000, "THREAD STATICS: Field placed at GC offset 0x%x\n", pCurField->GetOffset()));
8033
8034             break;
8035
8036         case FIELD_OFFSET_UNPLACED:
8037             // Place non-GC static field
8038             pCurField->SetOffset(bmtFP->ThreadStaticFieldStart[dwLog2FieldSize] +
8039                                  (bmtFP->NumThreadStaticFieldsOfSize[dwLog2FieldSize] << dwLog2FieldSize) +
8040                                  dwNonGCOffset);
8041             bmtFP->NumThreadStaticFieldsOfSize[dwLog2FieldSize]++;
8042             LOG((LF_CLASSLOADER, LL_INFO10000, "THREAD STATICS: Field placed at non GC offset 0x%x\n", pCurField->GetOffset()));
8043             break;
8044
8045         default:
8046             // RVA field
8047             break;
8048         }
8049
8050         LOG((LF_CLASSLOADER, LL_INFO1000000, "Offset of %s: %i\n", pCurField->m_debugName, pCurField->GetOffset()));
8051     }
8052
8053     if (bmtProp->fDynamicStatics)
8054     {
8055         _ASSERTE(dwNonGCOffset == 0 ||  // no thread statics at all
8056                  dwNonGCOffset == OFFSETOF__ThreadLocalModule__DynamicEntry__m_pDataBlob); // We need space to point to the GC statics
8057         bmtProp->dwNonGCThreadStaticFieldBytes = dwCumulativeStaticFieldPos;
8058     }
8059     else
8060     {
8061         bmtProp->dwNonGCThreadStaticFieldBytes = 0; // Non dynamics shouldnt be using this
8062     }
8063     LOG((LF_CLASSLOADER, LL_INFO10000, "STATICS: ThreadStatic field bytes needed (0 is normal for non dynamic case)%i\n", bmtProp->dwNonGCThreadStaticFieldBytes));
8064 }
8065
8066 //*******************************************************************************
8067 //
8068 // Used by BuildMethodTable
8069 //
8070 // Place instance fields
8071 //
8072 VOID    MethodTableBuilder::PlaceInstanceFields(MethodTable ** pByValueClassCache)
8073 {
8074     STANDARD_VM_CONTRACT;
8075
8076
8077     DWORD i;
8078
8079         //===============================================================
8080         // BEGIN: Place instance fields
8081         //===============================================================
8082
8083         FieldDesc *pFieldDescList = GetHalfBakedClass()->GetFieldDescList();
8084         DWORD   dwCumulativeInstanceFieldPos;
8085
8086         bool isAllGCPointers = true;
8087
8088         // Instance fields start right after the parent
8089         if (HasParent())
8090         {
8091             MethodTable* pParentMT = GetParentMethodTable();
8092             if (pParentMT->HasLayout() && pParentMT->GetLayoutInfo()->IsZeroSized())
8093             {
8094                 // If the parent type has sequential/explicit layout and is "zero sized"
8095                 // then we don't want to use the actual class size here.
8096                 // That includes an extra byte that isn't actually used, so we shouldn't
8097                 // count it here.
8098                 dwCumulativeInstanceFieldPos = 0;
8099             }
8100             else
8101             {
8102                 dwCumulativeInstanceFieldPos = pParentMT->GetNumInstanceFieldBytes();
8103             }
8104
8105             if (pParentMT->GetNumInstanceFields() != 0 && !pParentMT->IsAllGCPointers())
8106             {
8107                 isAllGCPointers = false;
8108             }
8109         }
8110         else
8111         {
8112             dwCumulativeInstanceFieldPos = 0;
8113         }
8114
8115         DWORD dwOffsetBias = 0;
8116 #ifdef FEATURE_64BIT_ALIGNMENT
8117         // On platforms where the alignment of 64-bit primitives is a requirement (but we're not guaranteed
8118         // this implicitly by the GC) field offset 0 is actually not 8-byte aligned in reference classes.
8119         // That's because all such platforms are currently 32-bit and the 4-byte MethodTable pointer pushes us
8120         // out of alignment. Ideally we'd solve this by arranging to have the object header allocated at a
8121         // 4-byte offset from an 8-byte boundary, but this is difficult to achieve for objects allocated on
8122         // the large object heap (which actually requires headers to be 8-byte aligned).
8123         //
8124         // So we adjust dwCumulativeInstanceFieldPos to account for the MethodTable* and our alignment
8125         // calculations will automatically adjust and add padding as necessary. We need to remove this
8126         // adjustment when setting the field offset in the field desc, however, since the rest of the system
8127         // expects that value to not include the MethodTable*.
8128         //
8129         // This happens only for reference classes: value type field 0 really does lie at offset 0 for unboxed
8130         // value types. We deal with boxed value types by allocating their headers mis-aligned (luckily for us
8131         // value types can never get large enough to allocate on the LOH).
8132         if (!IsValueClass())
8133         {
8134             dwOffsetBias = TARGET_POINTER_SIZE;
8135             dwCumulativeInstanceFieldPos += dwOffsetBias;
8136         }
8137 #endif // FEATURE_64BIT_ALIGNMENT
8138
8139 #ifdef FEATURE_READYTORUN
8140         if (NeedsAlignedBaseOffset())
8141         {
8142             // READYTORUN: FUTURE: Use the minimum possible alignment, reduce padding when inheriting within same bubble
8143             DWORD dwAlignment = DATA_ALIGNMENT;
8144 #ifdef FEATURE_64BIT_ALIGNMENT
8145             if (GetHalfBakedClass()->IsAlign8Candidate())
8146                 dwAlignment = 8;
8147 #endif
8148             dwCumulativeInstanceFieldPos = (DWORD)ALIGN_UP(dwCumulativeInstanceFieldPos, dwAlignment);
8149         }
8150 #endif // FEATURE_READYTORUN
8151
8152         // place small fields first if the parent have a number of field bytes that is not aligned
8153         if (!IS_ALIGNED(dwCumulativeInstanceFieldPos, DATA_ALIGNMENT))
8154         {
8155             for (i = 0; i < MAX_LOG2_PRIMITIVE_FIELD_SIZE; i++) {
8156                 DWORD j;
8157
8158                 if (IS_ALIGNED(dwCumulativeInstanceFieldPos, size_t{ 1 } << (i + 1)))
8159                     continue;
8160
8161                 // check whether there are any bigger fields
8162                 for (j = i + 1; j <= MAX_LOG2_PRIMITIVE_FIELD_SIZE; j++) {
8163                     if (bmtFP->NumInstanceFieldsOfSize[j] != 0)
8164                         break;
8165                 }
8166                 // nothing to gain if there are no bigger fields
8167                 // (the subsequent loop will place fields from large to small fields)
8168                 if (j > MAX_LOG2_PRIMITIVE_FIELD_SIZE)
8169                     break;
8170
8171                 // check whether there are any small enough fields
8172                 for (j = i; (signed int) j >= 0; j--) {
8173                     if (bmtFP->NumInstanceFieldsOfSize[j] != 0)
8174                         break;
8175                     // TODO: since we will refuse to place GC references we should filter them out here.
8176                     // otherwise the "back-filling" process stops completely.
8177                     // (PlaceInstanceFields)
8178                     // the following code would fix the issue (a replacement for the code above this comment):
8179                     // if (bmtFP->NumInstanceFieldsOfSize[j] != 0 &&
8180                     //     (j != LOG2SLOT || bmtFP->NumInstanceFieldsOfSize[j] > bmtFP->NumInstanceGCPointerFields))
8181                     // {
8182                     //     break;
8183                     // }
8184
8185                 }
8186                 // nothing to play with if there are no smaller fields
8187                 if ((signed int) j < 0)
8188                     break;
8189                 // eventually go back and use the smaller field as filling
8190                 i = j;
8191
8192                 CONSISTENCY_CHECK(bmtFP->NumInstanceFieldsOfSize[i] != 0);
8193
8194                 j = bmtFP->FirstInstanceFieldOfSize[i];
8195
8196                 // Avoid reordering of gcfields
8197                 if (i == LOG2SLOT) {
8198                     for ( ; j < bmtEnumFields->dwNumInstanceFields; j++) {
8199                         if ((pFieldDescList[j].GetOffset() == FIELD_OFFSET_UNPLACED) &&
8200                             ((DWORD_PTR&)pFieldDescList[j].m_pMTOfEnclosingClass == (size_t)i))
8201                             break;
8202                     }
8203
8204                     // out of luck - can't reorder gc fields
8205                     if (j >= bmtEnumFields->dwNumInstanceFields)
8206                         break;
8207                 }
8208
8209                 // Place the field
8210                 dwCumulativeInstanceFieldPos = (DWORD)ALIGN_UP(dwCumulativeInstanceFieldPos, size_t{ 1 } << i);
8211
8212                 pFieldDescList[j].SetOffset(dwCumulativeInstanceFieldPos - dwOffsetBias);
8213                 dwCumulativeInstanceFieldPos += (1 << i);
8214
8215                 // We've placed this field now, so there is now one less of this size field to place
8216                 if (--bmtFP->NumInstanceFieldsOfSize[i] == 0)
8217                     continue;
8218
8219                 // We are done in this round if we haven't picked the first field
8220                 if (bmtFP->FirstInstanceFieldOfSize[i] != j)
8221                     continue;
8222
8223                 // Update FirstInstanceFieldOfSize[i] to point to the next such field
8224                 for (j = j+1; j < bmtEnumFields->dwNumInstanceFields; j++)
8225                 {
8226                     // The log of the field size is stored in the method table
8227                     if ((DWORD_PTR&)pFieldDescList[j].m_pMTOfEnclosingClass == (size_t)i)
8228                     {
8229                         bmtFP->FirstInstanceFieldOfSize[i] = j;
8230                         break;
8231                     }
8232                 }
8233                 _ASSERTE(j < bmtEnumFields->dwNumInstanceFields);
8234             }
8235         }
8236
8237         // Place fields, largest first
8238         for (i = MAX_LOG2_PRIMITIVE_FIELD_SIZE; (signed int) i >= 0; i--)
8239         {
8240             if (bmtFP->NumInstanceFieldsOfSize[i] == 0)
8241                 continue;
8242
8243             // Align instance fields if we aren't already
8244 #if defined(TARGET_X86) && defined(UNIX_X86_ABI)
8245             DWORD dwDataAlignment = min(1 << i, DATA_ALIGNMENT);
8246 #else
8247             DWORD dwDataAlignment = 1 << i;
8248 #endif
8249             dwCumulativeInstanceFieldPos = (DWORD)ALIGN_UP(dwCumulativeInstanceFieldPos, dwDataAlignment);
8250
8251             // Fields of this size start at the next available location
8252             bmtFP->InstanceFieldStart[i] = dwCumulativeInstanceFieldPos;
8253             dwCumulativeInstanceFieldPos += (bmtFP->NumInstanceFieldsOfSize[i] << i);
8254
8255             // Reset counters for the loop after this one
8256             bmtFP->NumInstanceFieldsOfSize[i]  = 0;
8257         }
8258
8259
8260         // Make corrections to reserve space for GC Pointer Fields
8261         //
8262         // The GC Pointers simply take up the top part of the region associated
8263         // with fields of that size (GC pointers can be 64 bit on certain systems)
8264         if (bmtFP->NumInstanceGCPointerFields)
8265         {
8266             bmtFP->GCPointerFieldStart = bmtFP->InstanceFieldStart[LOG2SLOT] - dwOffsetBias;
8267             bmtFP->InstanceFieldStart[LOG2SLOT] = bmtFP->InstanceFieldStart[LOG2SLOT] + (bmtFP->NumInstanceGCPointerFields << LOG2SLOT);
8268             bmtFP->NumInstanceGCPointerFields = 0;     // reset to zero here, counts up as pointer slots are assigned below
8269         }
8270
8271         // Place instance fields - be careful not to place any already-placed fields
8272         for (i = 0; i < bmtEnumFields->dwNumInstanceFields; i++)
8273         {
8274             DWORD dwFieldSize   = (DWORD)(DWORD_PTR&)pFieldDescList[i].m_pMTOfEnclosingClass;
8275             DWORD dwOffset;
8276
8277             dwOffset = pFieldDescList[i].GetOffset();
8278
8279             // Don't place already-placed fields
8280             if ((dwOffset == FIELD_OFFSET_UNPLACED || dwOffset == FIELD_OFFSET_UNPLACED_GC_PTR || dwOffset == FIELD_OFFSET_VALUE_CLASS))
8281             {
8282                 if (dwOffset == FIELD_OFFSET_UNPLACED_GC_PTR)
8283                 {
8284                     pFieldDescList[i].SetOffset(bmtFP->GCPointerFieldStart + (bmtFP->NumInstanceGCPointerFields << LOG2SLOT));
8285                     bmtFP->NumInstanceGCPointerFields++;
8286                 }
8287                 else if (pFieldDescList[i].IsByValue() == FALSE) // it's a regular field
8288                 {
8289                     pFieldDescList[i].SetOffset(bmtFP->InstanceFieldStart[dwFieldSize] + (bmtFP->NumInstanceFieldsOfSize[dwFieldSize] << dwFieldSize) - dwOffsetBias);
8290                     bmtFP->NumInstanceFieldsOfSize[dwFieldSize]++;
8291                 }
8292             }
8293         }
8294
8295         DWORD dwNumGCPointerSeries;
8296         // Save Number of pointer series
8297         if (bmtFP->NumInstanceGCPointerFields)
8298             dwNumGCPointerSeries = bmtParent->NumParentPointerSeries + 1;
8299         else
8300             dwNumGCPointerSeries = bmtParent->NumParentPointerSeries;
8301
8302         bool containsGCPointers = bmtFP->NumInstanceGCPointerFields > 0;
8303         // Place by value class fields last
8304         // Update the number of GC pointer series
8305         // Calculate largest alignment requirement
8306         int largestAlignmentRequirement = 1;
8307         for (i = 0; i < bmtEnumFields->dwNumInstanceFields; i++)
8308         {
8309             if (pFieldDescList[i].IsByValue())
8310             {
8311                 MethodTable * pByValueMT = pByValueClassCache[i];
8312
8313 #if !defined(TARGET_64BIT) && (DATA_ALIGNMENT > 4)
8314                 if (pByValueMT->GetNumInstanceFieldBytes() >= DATA_ALIGNMENT)
8315                 {
8316                     dwCumulativeInstanceFieldPos = (DWORD)ALIGN_UP(dwCumulativeInstanceFieldPos, DATA_ALIGNMENT);
8317                     largestAlignmentRequirement = max(largestAlignmentRequirement, DATA_ALIGNMENT);
8318                 }
8319                 else
8320 #elif defined(FEATURE_64BIT_ALIGNMENT)
8321                 if (pByValueMT->RequiresAlign8())
8322                 {
8323                     dwCumulativeInstanceFieldPos = (DWORD)ALIGN_UP(dwCumulativeInstanceFieldPos, 8);
8324                     largestAlignmentRequirement = max(largestAlignmentRequirement, 8);
8325                 }
8326                 else
8327 #endif // FEATURE_64BIT_ALIGNMENT
8328                 if (pByValueMT->ContainsPointers())
8329                 {
8330                     // this field type has GC pointers in it, which need to be pointer-size aligned
8331                     // so do this if it has not been done already
8332                     dwCumulativeInstanceFieldPos = (DWORD)ALIGN_UP(dwCumulativeInstanceFieldPos, TARGET_POINTER_SIZE);
8333                     largestAlignmentRequirement = max(largestAlignmentRequirement, TARGET_POINTER_SIZE);
8334                     containsGCPointers = true;
8335                 }
8336                 else
8337                 {
8338                     int fieldAlignmentRequirement = pByValueMT->GetFieldAlignmentRequirement();
8339                     largestAlignmentRequirement = max(largestAlignmentRequirement, fieldAlignmentRequirement);
8340                     dwCumulativeInstanceFieldPos = (DWORD)ALIGN_UP(dwCumulativeInstanceFieldPos, fieldAlignmentRequirement);
8341                 }
8342
8343                 pFieldDescList[i].SetOffset(dwCumulativeInstanceFieldPos - dwOffsetBias);
8344                 dwCumulativeInstanceFieldPos += pByValueMT->GetNumInstanceFieldBytes();
8345
8346                 if (pByValueMT->ContainsPointers())
8347                 {
8348                     // Add pointer series for by-value classes
8349                     dwNumGCPointerSeries += (DWORD)CGCDesc::GetCGCDescFromMT(pByValueMT)->GetNumSeries();
8350                 }
8351
8352                 if (!pByValueMT->ContainsPointers() || !pByValueMT->IsAllGCPointers())
8353                 {
8354                     isAllGCPointers = false;
8355                 }
8356             }
8357             else
8358             {
8359                 // non-value-type fields always require pointer alignment
8360                 // This does not account for types that are marked IsAlign8Candidate due to 8-byte fields
8361                 // but that is explicitly handled when we calculate the final alignment for the type.
8362                 largestAlignmentRequirement = max(largestAlignmentRequirement, TARGET_POINTER_SIZE);
8363
8364                 if (!pFieldDescList[i].IsObjRef())
8365                 {
8366                     isAllGCPointers = false;
8367                 }
8368             }
8369         }
8370
8371             // Can be unaligned
8372         DWORD dwNumInstanceFieldBytes = dwCumulativeInstanceFieldPos - dwOffsetBias;
8373
8374         if (IsValueClass())
8375         {
8376             // Like C++ we enforce that there can be no 0 length structures.
8377             // Thus for a value class with no fields, we 'pad' the length to be 1
8378             if (dwNumInstanceFieldBytes == 0)
8379             {
8380                 dwNumInstanceFieldBytes = 1;
8381                 isAllGCPointers = false;
8382             }
8383
8384             // The JITs like to copy full machine words,
8385             //  so if the size is bigger than a void* round it up to minAlign
8386             // and if the size is smaller than void* round it up to next power of two
8387             unsigned minAlign;
8388
8389 #ifdef FEATURE_64BIT_ALIGNMENT
8390             if (GetHalfBakedClass()->IsAlign8Candidate()) {
8391                 minAlign = 8;
8392             }
8393             else
8394 #endif // FEATURE_64BIT_ALIGNMENT
8395             if (dwNumInstanceFieldBytes > TARGET_POINTER_SIZE) {
8396                 minAlign = containsGCPointers ? TARGET_POINTER_SIZE : (unsigned)largestAlignmentRequirement;
8397             }
8398             else {
8399                 minAlign = 1;
8400                 while (minAlign < dwNumInstanceFieldBytes)
8401                     minAlign *= 2;
8402             }
8403
8404             if (minAlign != min(dwNumInstanceFieldBytes, TARGET_POINTER_SIZE))
8405             {
8406                 EnsureOptionalFieldsAreAllocated(GetHalfBakedClass(), m_pAllocMemTracker, GetLoaderAllocator()->GetLowFrequencyHeap());
8407                 GetHalfBakedClass()->GetOptionalFields()->m_requiredFieldAlignment = (BYTE)minAlign;
8408                 GetHalfBakedClass()->SetHasCustomFieldAlignment();
8409             }
8410
8411             dwNumInstanceFieldBytes = (dwNumInstanceFieldBytes + minAlign-1) & ~(minAlign-1);
8412         }
8413
8414         if (dwNumInstanceFieldBytes > FIELD_OFFSET_LAST_REAL_OFFSET) {
8415             BuildMethodTableThrowException(IDS_CLASSLOAD_FIELDTOOLARGE);
8416         }
8417
8418         if (bmtFP->NumInlineArrayElements > 1)
8419         {
8420             INT64 extendedSize = (INT64)dwNumInstanceFieldBytes * (INT64)bmtFP->NumInlineArrayElements;
8421             // limit the max size of array instance to 1MiB
8422             const INT64 maxSize = 1024 * 1024;
8423             if (extendedSize > maxSize)
8424             {
8425                 BuildMethodTableThrowException(IDS_CLASSLOAD_FIELDTOOLARGE);
8426             }
8427
8428             dwNumInstanceFieldBytes = (DWORD)extendedSize;
8429
8430             if (pFieldDescList[0].IsByValue())
8431             {
8432                 dwNumGCPointerSeries *= bmtFP->NumInlineArrayElements;
8433             }
8434         }
8435
8436         bmtFP->fIsAllGCPointers = isAllGCPointers && dwNumGCPointerSeries;
8437         if (bmtFP->fIsAllGCPointers)
8438         {
8439             // we can use optimized form of GCDesc taking one serie
8440             dwNumGCPointerSeries = 1;
8441         }
8442
8443         bmtFP->NumInstanceFieldBytes = dwNumInstanceFieldBytes;
8444
8445         bmtFP->NumGCPointerSeries = dwNumGCPointerSeries;
8446
8447         //===============================================================
8448         // END: Place instance fields
8449         //===============================================================
8450 }
8451
8452 //*******************************************************************************
8453 // this accesses the field size which is temporarily stored in m_pMTOfEnclosingClass
8454 // during class loading. Don't use any other time
8455 DWORD MethodTableBuilder::GetFieldSize(FieldDesc *pFD)
8456 {
8457     STATIC_CONTRACT_NOTHROW;
8458     STATIC_CONTRACT_GC_NOTRIGGER;
8459     STATIC_CONTRACT_FORBID_FAULT;
8460
8461         // We should only be calling this while this class is being built.
8462     _ASSERTE(GetHalfBakedMethodTable() == 0);
8463     BAD_FORMAT_NOTHROW_ASSERT(! pFD->IsByValue() || HasExplicitFieldOffsetLayout());
8464
8465     if (pFD->IsByValue())
8466         return (DWORD)(DWORD_PTR&)(pFD->m_pMTOfEnclosingClass);
8467     return (1 << (DWORD)(DWORD_PTR&)(pFD->m_pMTOfEnclosingClass));
8468 }
8469
8470 #ifdef UNIX_AMD64_ABI
8471 // checks whether the struct is enregisterable.
8472 void MethodTableBuilder::SystemVAmd64CheckForPassStructInRegister(MethodTable** pByValueClassCache)
8473 {
8474     STANDARD_VM_CONTRACT;
8475
8476     // This method should be called for valuetypes only
8477     _ASSERTE(IsValueClass());
8478
8479     TypeHandle th(GetHalfBakedMethodTable());
8480
8481     if (th.IsTypeDesc())
8482     {
8483         // Not an enregisterable managed structure.
8484         return;
8485     }
8486
8487     DWORD totalStructSize = bmtFP->NumInstanceFieldBytes;
8488
8489     // If num of bytes for the fields is bigger than CLR_SYSTEMV_MAX_STRUCT_BYTES_TO_PASS_IN_REGISTERS
8490     // pass through stack
8491     if (totalStructSize > CLR_SYSTEMV_MAX_STRUCT_BYTES_TO_PASS_IN_REGISTERS)
8492     {
8493         LOG((LF_JIT, LL_EVERYTHING, "**** SystemVAmd64CheckForPassStructInRegister: struct %s is too big to pass in registers (%d bytes)\n",
8494                this->GetDebugClassName(), totalStructSize));
8495         return;
8496     }
8497
8498     const bool useNativeLayout = false;
8499     // Iterate through the fields and make sure they meet requirements to pass in registers
8500     SystemVStructRegisterPassingHelper helper((unsigned int)totalStructSize);
8501     if (GetHalfBakedMethodTable()->ClassifyEightBytes(&helper, 0, 0, useNativeLayout, pByValueClassCache))
8502     {
8503         LOG((LF_JIT, LL_EVERYTHING, "**** SystemVAmd64CheckForPassStructInRegister: struct %s is enregisterable\n",
8504                this->GetDebugClassName()));
8505
8506         // All the above tests passed. It's registers passed struct!
8507         GetHalfBakedMethodTable()->SetRegPassedStruct();
8508
8509         StoreEightByteClassification(&helper);
8510     }
8511     else
8512     {
8513         LOG((LF_JIT, LL_EVERYTHING, "**** SystemVAmd64CheckForPassStructInRegister: struct %s is _not_ enregisterable\n",
8514                this->GetDebugClassName()));
8515     }
8516 }
8517
8518 // Store the eightbyte classification into the EEClass
8519 void MethodTableBuilder::StoreEightByteClassification(SystemVStructRegisterPassingHelper* helper)
8520 {
8521     EEClass* eeClass = GetHalfBakedMethodTable()->GetClass();
8522     LoaderAllocator* pAllocator = MethodTableBuilder::GetLoaderAllocator();
8523     AllocMemTracker* pamTracker = MethodTableBuilder::GetMemTracker();
8524     EnsureOptionalFieldsAreAllocated(eeClass, pamTracker, pAllocator->GetLowFrequencyHeap());
8525     eeClass->SetEightByteClassification(helper->eightByteCount, helper->eightByteClassifications, helper->eightByteSizes);
8526 }
8527
8528 #endif // UNIX_AMD64_ABI
8529
8530 //---------------------------------------------------------------------------------------
8531 //
8532 // make sure that no object fields are overlapped incorrectly and define the
8533 // GC pointer series for the class. We are assuming that this class will always be laid out within
8534 // its enclosing class by the compiler in such a way that offset 0 will be the correct alignment
8535 // for object ref fields so we don't need to try to align it
8536 //
8537 VOID
8538 MethodTableBuilder::HandleExplicitLayout(
8539     MethodTable ** pByValueClassCache)
8540 {
8541     STANDARD_VM_CONTRACT;
8542
8543     // Instance slice size is the total size of an instance, and is calculated as
8544     // the field whose offset and size add to the greatest number.
8545     UINT instanceSliceSize = 0;
8546
8547     UINT i;
8548     for (i = 0; i < bmtMetaData->cFields; i++)
8549     {
8550         FieldDesc *pFD = bmtMFDescs->ppFieldDescList[i];
8551         if (pFD == NULL || pFD->IsStatic())
8552         {
8553             continue;
8554         }
8555
8556         UINT fieldExtent = 0;
8557         if (!ClrSafeInt<UINT>::addition(pFD->GetOffset(), GetFieldSize(pFD), fieldExtent))
8558         {
8559             BuildMethodTableThrowException(COR_E_OVERFLOW);
8560         }
8561
8562         if (fieldExtent > instanceSliceSize)
8563         {
8564             instanceSliceSize = fieldExtent;
8565         }
8566     }
8567
8568     CQuickBytes qb;
8569     PREFIX_ASSUME(sizeof(bmtFieldLayoutTag) == 1);
8570     bmtFieldLayoutTag *pFieldLayout = (bmtFieldLayoutTag*)qb.AllocThrows(instanceSliceSize * sizeof(bmtFieldLayoutTag));
8571     for (i=0; i < instanceSliceSize; i++)
8572     {
8573         pFieldLayout[i] = empty;
8574     }
8575
8576     // Go through each field and look for invalid layout.
8577     // (note that we are more permissive than what Ecma allows. We only disallow the minimum set necessary to
8578     // close security holes.)
8579     //
8580     // This is what we implement:
8581     //
8582     // 1. Verify that every OREF or BYREF is on a valid alignment.
8583     // 2. Verify that OREFs only overlap with other OREFs.
8584     // 3. Verify that BYREFs only overlap with other BYREFs.
8585     // 4. If an OREF does overlap with another OREF, the class is marked unverifiable.
8586     // 5. If a BYREF does overlap with another BYREF, the class is marked unverifiable.
8587     // 6. If an overlap of any kind occurs, the class will be marked NotTightlyPacked (affects ValueType.Equals()).
8588     //
8589     bmtFieldLayoutTag emptyObject[TARGET_POINTER_SIZE];
8590     bmtFieldLayoutTag isObject[TARGET_POINTER_SIZE];
8591     bmtFieldLayoutTag isByRef[TARGET_POINTER_SIZE];
8592     for (i = 0; i < TARGET_POINTER_SIZE; i++)
8593     {
8594         emptyObject[i] = empty;
8595         isObject[i]    = oref;
8596         isByRef[i]     = byref;
8597     }
8598
8599     ExplicitClassTrust explicitClassTrust;
8600
8601     UINT valueClassCacheIndex = ((UINT)(-1));
8602     UINT badOffset = 0;
8603     FieldDesc * pFD = NULL;
8604     for (i = 0; i < bmtMetaData->cFields; i++)
8605     {
8606         // Note about this loop body:
8607         //
8608         // This loop is coded to make it as hard as possible to allow a field to be trusted when it shouldn't.
8609         //
8610         // Every path in this loop body must lead to an explicit decision as to whether the field nonoverlaps,
8611         // overlaps in a verifiable fashion, overlaps in a nonverifiable fashion or overlaps in a completely illegal fashion.
8612         //
8613         // It must call fieldTrust.SetTrust() with the appropriate result. If you don't call it, fieldTrust's destructor
8614         // will intentionally default to kNone and mark the entire class illegal.
8615         //
8616         // If your result is anything but kNone (class is illegal), you must also explicitly "continue" the loop.
8617         // There is a "break" at end of this loop body that will abort the loop if you don't do this. And
8618         // if you don't finish iterating through all the fields, this function will automatically mark the entire
8619         // class illegal. This rule is a vestige of an earlier version of this function.
8620
8621         // This object's dtor will aggregate the trust decision for this field into the trust level for the class as a whole.
8622         ExplicitFieldTrustHolder fieldTrust(&explicitClassTrust);
8623
8624         pFD = bmtMFDescs->ppFieldDescList[i];
8625         if (pFD == NULL || pFD->IsStatic())
8626         {
8627             fieldTrust.SetTrust(ExplicitFieldTrust::kNonOverlaid);
8628             continue;
8629         }
8630
8631         // "i" indexes all fields, valueClassCacheIndex indexes non-static fields only. Don't get them confused!
8632         valueClassCacheIndex++;
8633
8634         CorElementType type = pFD->GetFieldType();
8635         if (CorTypeInfo::IsObjRef(type) || CorTypeInfo::IsByRef(type))
8636         {
8637             // Check that the field is pointer aligned
8638             if ((pFD->GetOffset() & ((ULONG)TARGET_POINTER_SIZE - 1)) != 0)
8639             {
8640                 badOffset = pFD->GetOffset();
8641                 fieldTrust.SetTrust(ExplicitFieldTrust::kNone);
8642
8643                 // If we got here, OREF or BYREF field was not pointer aligned. THROW.
8644                 break;
8645             }
8646
8647             // Determine which tag type we are working with.
8648             bmtFieldLayoutTag tag;
8649             SIZE_T tagBlockSize;
8650             void* tagBlock;
8651             if (CorTypeInfo::IsObjRef(type))
8652             {
8653                 tagBlockSize = sizeof(isObject);
8654                 tagBlock = (void*)isObject;
8655                 tag = oref;
8656             }
8657             else
8658             {
8659                 _ASSERTE(CorTypeInfo::IsByRef(type));
8660                 tagBlockSize = sizeof(isByRef);
8661                 tagBlock = (void*)isByRef;
8662                 tag = byref;
8663             }
8664
8665             // Check if there is overlap with its own tag type
8666             if (memcmp((void *)&pFieldLayout[pFD->GetOffset()], tagBlock, tagBlockSize) == 0)
8667             {
8668                 // If we got here, there is tag type overlap. We permit this but mark the class unverifiable.
8669                 fieldTrust.SetTrust(ExplicitFieldTrust::kLegal);
8670                 continue;
8671             }
8672             // check if typed layout is empty at this point
8673             if (memcmp((void *)&pFieldLayout[pFD->GetOffset()], (void *)emptyObject, sizeof(emptyObject)) == 0)
8674             {
8675                 // If we got here, this tag type is overlapping no other fields (yet).
8676                 // Record that these bytes now contain the current tag type.
8677                 memset((void *)&pFieldLayout[pFD->GetOffset()], tag, tagBlockSize);
8678                 fieldTrust.SetTrust(ExplicitFieldTrust::kNonOverlaid);
8679                 continue;
8680             }
8681
8682             // If we got here, the tag overlaps something else. THROW.
8683             badOffset = pFD->GetOffset();
8684             fieldTrust.SetTrust(ExplicitFieldTrust::kNone);
8685             break;
8686         }
8687         else
8688         {
8689             UINT fieldSize;
8690             if (!pFD->IsByValue())
8691             {
8692                 fieldSize = GetFieldSize(pFD);
8693             }
8694             else
8695             {
8696                 MethodTable *pByValueMT = pByValueClassCache[valueClassCacheIndex];
8697                 if (pByValueMT->IsByRefLike() || pByValueMT->ContainsPointers())
8698                 {
8699                     if ((pFD->GetOffset() & ((ULONG)TARGET_POINTER_SIZE - 1)) != 0)
8700                     {
8701                         // If we got here, then a ByRefLike valuetype or a valuetype containing an OREF was misaligned.
8702                         badOffset = pFD->GetOffset();
8703                         fieldTrust.SetTrust(ExplicitFieldTrust::kNone);
8704                         break;
8705                     }
8706
8707                     ExplicitFieldTrust::TrustLevel trust = CheckValueClassLayout(pByValueMT, &pFieldLayout[pFD->GetOffset()]);
8708                     fieldTrust.SetTrust(trust);
8709
8710                     if (trust != ExplicitFieldTrust::kNone)
8711                     {
8712                         continue;
8713                     }
8714                     else
8715                     {
8716                         // If we got here, then an OREF/BYREF inside the valuetype illegally overlapped a non-OREF field. THROW.
8717                         badOffset = pFD->GetOffset();
8718                         break;
8719                     }
8720                     break;
8721                 }
8722                 // no pointers so fall through to do standard checking
8723                 fieldSize = pByValueMT->GetNumInstanceFieldBytes();
8724             }
8725
8726             // If we got here, we are trying to place a non-OREF (or a valuetype composed of non-OREFs.)
8727             // Look for any orefs or byrefs under this field
8728             bmtFieldLayoutTag* loc = NULL;
8729             bmtFieldLayoutTag* currOffset = pFieldLayout + pFD->GetOffset();
8730             bmtFieldLayoutTag* endOffset = currOffset + fieldSize;
8731             for (; currOffset < endOffset; ++currOffset)
8732             {
8733                 if (*currOffset == oref || *currOffset == byref)
8734                 {
8735                     loc = currOffset;
8736                     break;
8737                 }
8738             }
8739
8740             if (loc == NULL)
8741             {
8742                 // If we have a nonoref in the range then we are doing an overlay
8743                 if(memchr((void*)&pFieldLayout[pFD->GetOffset()], nonoref, fieldSize))
8744                 {
8745                     fieldTrust.SetTrust(ExplicitFieldTrust::kVerifiable);
8746                 }
8747                 else
8748                 {
8749                     fieldTrust.SetTrust(ExplicitFieldTrust::kNonOverlaid);
8750                 }
8751                 memset((void*)&pFieldLayout[pFD->GetOffset()], nonoref, fieldSize);
8752                 continue;
8753             }
8754
8755             // If we got here, we tried to place a non-OREF (or a valuetype composed of non-OREFs)
8756             // on top of an OREF/BYREF. THROW.
8757             badOffset = (UINT)(loc - pFieldLayout);
8758             fieldTrust.SetTrust(ExplicitFieldTrust::kNone);
8759             break;
8760             // anything else is an error
8761         }
8762
8763         // We have to comment out this assert because otherwise, the compiler refuses to build because the _ASSERT is unreachable
8764         // (Thanks for nothing, compiler, that's what the assert is trying to enforce!) But the intent of the assert is correct.
8765         //_ASSERTE(!"You aren't supposed to be here. Some path inside the loop body did not execute an explicit break or continue.");
8766
8767
8768         // If we got here, some code above failed to execute an explicit "break" or "continue." This is a bug! To be safe,
8769         // we will put a catchall "break" here which will cause the typeload to abort (albeit with a probably misleading
8770         // error message.)
8771         break;
8772     }
8773
8774     // We only break out of the loop above if we detected an error.
8775     if (i < bmtMetaData->cFields || !explicitClassTrust.IsLegal())
8776     {
8777         ThrowFieldLayoutError(GetCl(),
8778                               GetModule(),
8779                               badOffset,
8780                               IDS_CLASSLOAD_EXPLICIT_LAYOUT);
8781     }
8782
8783     if (!explicitClassTrust.IsNonOverlaid())
8784     {
8785         SetHasOverlaidFields();
8786     }
8787
8788     FindPointerSeriesExplicit(instanceSliceSize, pFieldLayout);
8789
8790     // Fixup the offset to include parent as current offsets are relative to instance slice
8791     // Could do this earlier, but it's just easier to assume instance relative for most
8792     // of the earlier calculations
8793
8794     // Instance fields start right after the parent
8795     S_UINT32 dwInstanceSliceOffset = S_UINT32(HasParent() ? GetParentMethodTable()->GetNumInstanceFieldBytes() : 0);
8796     if (bmtGCSeries->numSeries != 0)
8797     {
8798         dwInstanceSliceOffset.AlignUp(TARGET_POINTER_SIZE);
8799     }
8800     if (dwInstanceSliceOffset.IsOverflow())
8801     {
8802         // addition overflow or cast truncation
8803         BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
8804     }
8805
8806     S_UINT32 numInstanceFieldBytes = dwInstanceSliceOffset + S_UINT32(instanceSliceSize);
8807
8808     if (IsValueClass())
8809     {
8810         ULONG clstotalsize;
8811         if (FAILED(GetMDImport()->GetClassTotalSize(GetCl(), &clstotalsize)))
8812         {
8813             clstotalsize = 0;
8814         }
8815
8816         if (clstotalsize != 0)
8817         {
8818             // size must be large enough to accommodate layout. If not, we use the layout size instead.
8819             if (!numInstanceFieldBytes.IsOverflow() && clstotalsize >= numInstanceFieldBytes.Value())
8820             {
8821                 numInstanceFieldBytes = S_UINT32(clstotalsize);
8822             }
8823         }
8824         else
8825         {
8826             // align up to the alignment requirements of the members of this value type.
8827             numInstanceFieldBytes.AlignUp(GetLayoutInfo()->m_ManagedLargestAlignmentRequirementOfAllMembers);
8828             if (numInstanceFieldBytes.IsOverflow())
8829             {
8830                 // addition overflow or cast truncation
8831                 BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
8832             }
8833         }
8834
8835         if (!numInstanceFieldBytes.IsOverflow() && numInstanceFieldBytes.Value() == 0)
8836         {
8837             // If we calculate a 0-byte size here, we should have also calculated a 0-byte size
8838             // in the initial layout algorithm.
8839             _ASSERTE(GetLayoutInfo()->IsZeroSized());
8840             numInstanceFieldBytes = S_UINT32(1);
8841         }
8842     }
8843
8844     // The GC requires that all valuetypes containing orefs be sized to a multiple of TARGET_POINTER_SIZE.
8845     if (bmtGCSeries->numSeries != 0)
8846     {
8847         numInstanceFieldBytes.AlignUp(TARGET_POINTER_SIZE);
8848     }
8849     if (numInstanceFieldBytes.IsOverflow())
8850     {
8851         // addition overflow or cast truncation
8852         BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL);
8853     }
8854
8855     // Set the total size
8856     bmtFP->NumInstanceFieldBytes = numInstanceFieldBytes.Value();
8857
8858     for (i = 0; i < bmtMetaData->cFields; i++)
8859     {
8860         FieldDesc * pTempFD = bmtMFDescs->ppFieldDescList[i];
8861         if ((pTempFD == NULL) || pTempFD->IsStatic())
8862         {
8863             continue;
8864         }
8865         HRESULT hr = pTempFD->SetOffset(pTempFD->GetOffset() + dwInstanceSliceOffset.Value());
8866         if (FAILED(hr))
8867         {
8868             BuildMethodTableThrowException(hr, *bmtError);
8869         }
8870     }
8871 } // MethodTableBuilder::HandleExplicitLayout
8872
8873 //*******************************************************************************
8874 // make sure that no object fields are overlapped incorrectly, returns the trust level
8875 /*static*/ ExplicitFieldTrust::TrustLevel MethodTableBuilder::CheckValueClassLayout(MethodTable * pMT, bmtFieldLayoutTag *pFieldLayout)
8876 {
8877     STANDARD_VM_CONTRACT;
8878
8879     // ByRefLike types need to be checked for ByRef fields.
8880     if (pMT->IsByRefLike())
8881         return CheckByRefLikeValueClassLayout(pMT, pFieldLayout);
8882
8883     // Build a layout of the value class (vc). Don't know the sizes of all the fields easily, but
8884     // do know (a) vc is already consistent so don't need to check it's overlaps and
8885     // (b) size and location of all objectrefs. So build it by setting all non-oref
8886     // then fill in the orefs later if present.
8887     UINT fieldSize = pMT->GetNumInstanceFieldBytes();
8888
8889     CQuickBytes qb;
8890     bmtFieldLayoutTag *vcLayout = (bmtFieldLayoutTag*) qb.AllocThrows(fieldSize * sizeof(bmtFieldLayoutTag));
8891     memset((void*)vcLayout, nonoref, fieldSize);
8892
8893     // If the type contains pointers fill it out from the GC data
8894     if (pMT->ContainsPointers())
8895     {
8896         // use pointer series to locate the orefs
8897         CGCDesc* map = CGCDesc::GetCGCDescFromMT(pMT);
8898         CGCDescSeries *pSeries = map->GetLowestSeries();
8899
8900         for (SIZE_T j = 0; j < map->GetNumSeries(); j++)
8901         {
8902             CONSISTENCY_CHECK(pSeries <= map->GetHighestSeries());
8903
8904             memset((void*)&vcLayout[pSeries->GetSeriesOffset() - OBJECT_SIZE], oref, pSeries->GetSeriesSize() + pMT->GetBaseSize());
8905             pSeries++;
8906         }
8907     }
8908
8909     ExplicitClassTrust explicitClassTrust;
8910     for (UINT i=0; i < fieldSize; i++)
8911     {
8912         ExplicitFieldTrustHolder fieldTrust(&explicitClassTrust);
8913
8914         if (vcLayout[i] == oref) {
8915             switch (pFieldLayout[i]) {
8916                 // oref <--> empty
8917                 case empty:
8918                     pFieldLayout[i] = oref;
8919                     fieldTrust.SetTrust(ExplicitFieldTrust::kNonOverlaid);
8920                     break;
8921
8922                 // oref <--> nonoref
8923                 case nonoref:
8924                     fieldTrust.SetTrust(ExplicitFieldTrust::kNone);
8925                     break;
8926
8927                 // oref <--> oref
8928                 case oref:
8929                     fieldTrust.SetTrust(ExplicitFieldTrust::kLegal);
8930                     break;
8931
8932                 default:
8933                     _ASSERTE(!"Can't get here.");
8934                 }
8935         } else if (vcLayout[i] == nonoref) {
8936             switch (pFieldLayout[i]) {
8937                 // nonoref <--> empty
8938                 case empty:
8939                     pFieldLayout[i] = nonoref;
8940                     fieldTrust.SetTrust(ExplicitFieldTrust::kNonOverlaid);
8941                     break;
8942
8943                 // nonoref <--> nonoref
8944                 case nonoref:
8945                     fieldTrust.SetTrust(ExplicitFieldTrust::kVerifiable);
8946                     break;
8947
8948                 // nonoref <--> oref
8949                 case oref:
8950                     fieldTrust.SetTrust(ExplicitFieldTrust::kNone);
8951                     break;
8952
8953                 default:
8954                     _ASSERTE(!"Can't get here.");
8955             }
8956         } else {
8957             _ASSERTE(!"Can't get here.");
8958         }
8959     }
8960
8961     return explicitClassTrust.GetTrustLevel();
8962 }
8963
8964
8965 //*******************************************************************************
8966 // make sure that no byref/object fields are overlapped, returns the trust level
8967 /*static*/ ExplicitFieldTrust::TrustLevel MethodTableBuilder::CheckByRefLikeValueClassLayout(MethodTable * pMT, bmtFieldLayoutTag *pFieldLayout)
8968 {
8969     STANDARD_VM_CONTRACT;
8970     _ASSERTE(pMT->IsByRefLike());
8971
8972     ExplicitClassTrust explicitClassTrust;
8973
8974     ExplicitFieldTrust::TrustLevel trust;
8975     ApproxFieldDescIterator fieldIterator(pMT, ApproxFieldDescIterator::INSTANCE_FIELDS);
8976     for (FieldDesc *pFD = fieldIterator.Next(); pFD != NULL; pFD = fieldIterator.Next())
8977     {
8978         ExplicitFieldTrustHolder fieldTrust(&explicitClassTrust);
8979         int fieldStartIndex = pFD->GetOffset();
8980
8981         if (pFD->GetFieldType() == ELEMENT_TYPE_VALUETYPE)
8982         {
8983             MethodTable *pFieldMT = pFD->GetApproxFieldTypeHandleThrowing().AsMethodTable();
8984             trust = CheckValueClassLayout(pFieldMT, &pFieldLayout[fieldStartIndex]);
8985         }
8986         else if (pFD->IsObjRef())
8987         {
8988             _ASSERTE(fieldStartIndex % TARGET_POINTER_SIZE == 0);
8989             trust = MarkTagType(&pFieldLayout[fieldStartIndex], TARGET_POINTER_SIZE, oref);
8990         }
8991         else if (pFD->IsByRef())
8992         {
8993             _ASSERTE(fieldStartIndex % TARGET_POINTER_SIZE == 0);
8994             trust = MarkTagType(&pFieldLayout[fieldStartIndex], TARGET_POINTER_SIZE, byref);
8995         }
8996         else
8997         {
8998             trust = MarkTagType(&pFieldLayout[fieldStartIndex], pFD->GetSize(), nonoref);
8999         }
9000
9001         fieldTrust.SetTrust(trust);
9002
9003         // Some invalid overlap was detected.
9004         if (trust == ExplicitFieldTrust::kNone)
9005             break;
9006     }
9007
9008     return explicitClassTrust.GetTrustLevel();
9009 }
9010
9011 //*******************************************************************************
9012 // Set the field's tag type and/or detect invalid overlap
9013 /*static*/ ExplicitFieldTrust::TrustLevel MethodTableBuilder::MarkTagType(bmtFieldLayoutTag* field, SIZE_T fieldSize, bmtFieldLayoutTag tagType)
9014 {
9015     STANDARD_VM_CONTRACT;
9016     _ASSERTE(field != NULL);
9017     _ASSERTE(fieldSize != 0);
9018     _ASSERTE(tagType != empty);
9019
9020     ExplicitFieldTrust::TrustLevel trust = ExplicitFieldTrust::kMaxTrust;
9021     for (SIZE_T i = 0; i < fieldSize; ++i)
9022     {
9023         if (field[i] == empty)
9024         {
9025             // Nothing set for overlap, mark as requested.
9026             field[i] = tagType;
9027         }
9028         else if (field[i] == tagType)
9029         {
9030             // Only a overlapped nonoref tag is verifiable, all others are simply legal.
9031             ExplicitFieldTrust::TrustLevel overlapTrust = tagType == nonoref ? ExplicitFieldTrust::kVerifiable : ExplicitFieldTrust::kLegal;
9032
9033             // The ExplicitFieldTrust enum is ranked in descending order of trust.
9034             // We always take the computed minimum trust level.
9035             trust = min(trust, overlapTrust);
9036         }
9037         else
9038         {
9039             // A non-equal overlap was detected. There is no trust for the type.
9040             trust = ExplicitFieldTrust::kNone;
9041             break;
9042         }
9043     }
9044
9045     return trust;
9046 }
9047
9048 //*******************************************************************************
9049 void MethodTableBuilder::FindPointerSeriesExplicit(UINT instanceSliceSize,
9050                                                    bmtFieldLayoutTag *pFieldLayout)
9051 {
9052     STANDARD_VM_CONTRACT;
9053
9054
9055     // Allocate a structure to track the series. We know that the worst case is a
9056     // ref-non-ref-non, and since only ref series are recorded and non-ref series
9057     // are skipped, the max number of series is total instance size / 2 / sizeof(ref).
9058     // But watch out for the case where we have e.g. an instanceSlizeSize of 4.
9059     DWORD sz = (instanceSliceSize + (2 * TARGET_POINTER_SIZE) - 1);
9060     bmtGCSeries->pSeries = new bmtGCSeriesInfo::Series[sz/2/ TARGET_POINTER_SIZE];
9061
9062     bmtFieldLayoutTag *loc = pFieldLayout;
9063     bmtFieldLayoutTag *layoutEnd = pFieldLayout + instanceSliceSize;
9064     while (loc < layoutEnd)
9065     {
9066         // Find the next OREF entry.
9067         loc = (bmtFieldLayoutTag*)memchr((void*)loc, oref, layoutEnd-loc);
9068         if (loc == NULL)
9069         {
9070             break;
9071         }
9072
9073         // Find the next non-OREF entry
9074         bmtFieldLayoutTag *cur = loc;
9075         while(cur < layoutEnd && *cur == oref)
9076         {
9077             cur++;
9078         }
9079
9080         // so we have a GC series at loc for cur-loc bytes
9081         bmtGCSeries->pSeries[bmtGCSeries->numSeries].offset = (DWORD)(loc - pFieldLayout);
9082         bmtGCSeries->pSeries[bmtGCSeries->numSeries].len = (DWORD)(cur - loc);
9083
9084         CONSISTENCY_CHECK(IS_ALIGNED(cur - loc, TARGET_POINTER_SIZE));
9085
9086         bmtGCSeries->numSeries++;
9087         loc = cur;
9088     }
9089
9090     // Calculate the total series count including the parent, if a parent exists.
9091
9092     bmtFP->NumGCPointerSeries = bmtParent->NumParentPointerSeries + bmtGCSeries->numSeries;
9093
9094     // since the GC series are computed from a ref map,
9095     // in most cases where optimized GCDesc could be used, that is what we will compute anyways,
9096     // so we will not try optimizing this case.
9097     bmtFP->fIsAllGCPointers = false;
9098 }
9099
9100 //*******************************************************************************
9101 VOID
9102 MethodTableBuilder::HandleGCForExplicitLayout()
9103 {
9104     STANDARD_VM_CONTRACT;
9105
9106     MethodTable *pMT = GetHalfBakedMethodTable();
9107
9108     if (bmtFP->NumGCPointerSeries != 0)
9109     {
9110         pMT->SetContainsPointers();
9111
9112         // Copy the pointer series map from the parent
9113         CGCDesc::Init( (PVOID) pMT, bmtFP->NumGCPointerSeries );
9114         if (bmtParent->NumParentPointerSeries != 0)
9115         {
9116             size_t ParentGCSize = CGCDesc::ComputeSize(bmtParent->NumParentPointerSeries);
9117             memcpy( (PVOID) (((BYTE*) pMT) - ParentGCSize),
9118                     (PVOID) (((BYTE*) GetParentMethodTable()) - ParentGCSize),
9119                     ParentGCSize - sizeof(size_t)   // sizeof(size_t) is the NumSeries count
9120                   );
9121         }
9122
9123         UINT32 dwInstanceSliceOffset = AlignUp(HasParent() ? GetParentMethodTable()->GetNumInstanceFieldBytes() : 0, TARGET_POINTER_SIZE);
9124
9125         // Build the pointer series map for this pointers in this instance
9126         CGCDescSeries *pSeries = ((CGCDesc*)pMT)->GetLowestSeries();
9127         for (UINT i=0; i < bmtGCSeries->numSeries; i++) {
9128             // See gcdesc.h for an explanation of why we adjust by subtracting BaseSize
9129             BAD_FORMAT_NOTHROW_ASSERT(pSeries <= CGCDesc::GetCGCDescFromMT(pMT)->GetHighestSeries());
9130
9131             pSeries->SetSeriesSize( (size_t) bmtGCSeries->pSeries[i].len - (size_t) pMT->GetBaseSize() );
9132             pSeries->SetSeriesOffset(bmtGCSeries->pSeries[i].offset + OBJECT_SIZE + dwInstanceSliceOffset);
9133             pSeries++;
9134         }
9135
9136         // Adjust the inherited series - since the base size has increased by "# new field instance bytes", we need to
9137         // subtract that from all the series (since the series always has BaseSize subtracted for it - see gcdesc.h)
9138         CGCDescSeries *pHighest = CGCDesc::GetCGCDescFromMT(pMT)->GetHighestSeries();
9139         while (pSeries <= pHighest)
9140         {
9141             CONSISTENCY_CHECK(CheckPointer(GetParentMethodTable()));
9142             pSeries->SetSeriesSize( pSeries->GetSeriesSize() - ((size_t) pMT->GetBaseSize() - (size_t) GetParentMethodTable()->GetBaseSize()) );
9143             pSeries++;
9144         }
9145     }
9146
9147     delete [] bmtGCSeries->pSeries;
9148     bmtGCSeries->pSeries = NULL;
9149 } // MethodTableBuilder::HandleGCForExplicitLayout
9150
9151 static
9152 BOOL
9153 InsertMethodTable(
9154     MethodTable  *pNew,
9155     MethodTable **pArray,
9156     DWORD         nArraySizeMax,
9157     DWORD        *pNumAssigned)
9158 {
9159     LIMITED_METHOD_CONTRACT;
9160
9161     for (DWORD j = 0; j < (*pNumAssigned); j++)
9162     {
9163         if (pNew == pArray[j])
9164         {
9165 #ifdef _DEBUG
9166             LOG((LF_CLASSLOADER, LL_INFO1000, "GENERICS: Found duplicate interface %s (%p) at position %d out of %d\n", pNew->GetDebugClassName(), pNew, j, *pNumAssigned));
9167 #endif
9168             return pNew->HasInstantiation(); // bail out - we found a duplicate instantiated interface
9169         }
9170         else
9171         {
9172 #ifdef _DEBUG
9173             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));
9174 #endif
9175         }
9176     }
9177     if (*pNumAssigned >= nArraySizeMax)
9178     {
9179         LOG((LF_CLASSLOADER, LL_INFO1000, "GENERICS: Found interface %s (%p) exceeding size %d of interface array\n", pNew->GetDebugClassName(), pNew, nArraySizeMax));
9180         return TRUE;
9181     }
9182     LOG((LF_CLASSLOADER, LL_INFO1000, "GENERICS: Inserting interface %s (%p) at position %d\n", pNew->GetDebugClassName(), pNew, *pNumAssigned));
9183     pArray[(*pNumAssigned)++] = pNew;
9184     return FALSE;
9185 } // InsertMethodTable
9186
9187 //*******************************************************************************
9188 // --------------------------------------------------------------------------------------------
9189 // Copy virtual slots inherited from parent:
9190 //
9191 // In types where covariant returns are used, inherited virtual slots may not yet be fully
9192 // resolved during initial MethodTable building. This method will update them based on the
9193 // values computed during exact parent calculation of the parent type.
9194 /* static */
9195 void MethodTableBuilder::CopyExactParentSlots(MethodTable *pMT)
9196 {
9197     CONTRACTL
9198     {
9199         STANDARD_VM_CHECK;
9200         PRECONDITION(CheckPointer(pMT));
9201     }
9202     CONTRACTL_END;
9203
9204     DWORD nParentVirtuals = pMT->GetNumParentVirtuals();
9205     if (nParentVirtuals == 0)
9206         return;
9207
9208     //
9209     // Update all inherited virtual slots to match exact parent
9210     //
9211
9212     if (!pMT->IsCanonicalMethodTable())
9213     {
9214         //
9215         // Copy all slots for non-canonical methodtables to avoid touching methoddescs.
9216         //
9217         MethodTable * pCanonMT = pMT->GetCanonicalMethodTable();
9218
9219         // Do not write into vtable chunks shared with parent. It would introduce race
9220         // with code:MethodDesc::SetStableEntryPointInterlocked.
9221         //
9222         // Non-canonical method tables either share everything or nothing so it is sufficient to check
9223         // just the first indirection to detect sharing.
9224         if (pMT->GetVtableIndirections()[0] != pCanonMT->GetVtableIndirections()[0])
9225         {
9226             MethodTable::MethodDataWrapper hCanonMTData(MethodTable::GetMethodData(pCanonMT, FALSE));
9227             for (DWORD i = 0; i < nParentVirtuals; i++)
9228             {
9229                 pMT->CopySlotFrom(i, hCanonMTData, pCanonMT);
9230             }
9231         }
9232     }
9233     else
9234     {
9235         MethodTable::MethodDataWrapper hMTData(MethodTable::GetMethodData(pMT, FALSE));
9236
9237         MethodTable * pParentMT = pMT->GetParentMethodTable();
9238         MethodTable::MethodDataWrapper hParentMTData(MethodTable::GetMethodData(pParentMT, FALSE));
9239
9240         for (DWORD i = 0; i < nParentVirtuals; i++)
9241         {
9242             // fix up wrongly-inherited method descriptors
9243             MethodDesc* pMD = hMTData->GetImplMethodDesc(i);
9244             CONSISTENCY_CHECK(CheckPointer(pMD));
9245             CONSISTENCY_CHECK(pMD == pMT->GetMethodDescForSlot(i));
9246
9247             if (pMD->GetMethodTable() == pMT)
9248                 continue;
9249
9250             // We need to re-inherit this slot from the exact parent.
9251
9252             DWORD indirectionIndex = MethodTable::GetIndexOfVtableIndirection(i);
9253             if (pMT->GetVtableIndirections()[indirectionIndex] == pParentMT->GetVtableIndirections()[indirectionIndex])
9254             {
9255                 // The slot lives in a chunk shared from the parent MT
9256                 continue;
9257             }
9258
9259             // The slot lives in an unshared chunk. We need to update the slot contents
9260             pMT->CopySlotFrom(i, hParentMTData, pParentMT);
9261         }
9262     }
9263 } // MethodTableBuilder::CopyExactParentSlots
9264
9265 bool InstantiationIsAllTypeVariables(const Instantiation &inst)
9266 {
9267     for (auto i = inst.GetNumArgs(); i > 0;)
9268     {
9269         TypeHandle th = inst[--i];
9270         if (!th.IsGenericVariable())
9271             return false;
9272     }
9273
9274     return true;
9275 }
9276
9277 //*******************************************************************************
9278 /* static */
9279 void
9280 MethodTableBuilder::LoadExactInterfaceMap(MethodTable *pMT)
9281 {
9282     CONTRACTL
9283     {
9284         STANDARD_VM_CHECK;
9285         PRECONDITION(CheckPointer(pMT));
9286     }
9287     CONTRACTL_END;
9288
9289     BOOL hasInstantiatedInterfaces = FALSE;
9290     MethodTable::InterfaceMapIterator it = pMT->IterateInterfaceMap();
9291     while (it.Next())
9292     {
9293         if (it.GetInterfaceApprox()->HasInstantiation())
9294         {
9295             hasInstantiatedInterfaces = TRUE;
9296             break;
9297         }
9298     }
9299
9300     // If we have some instantiated interfaces, then we have lots more work to do...
9301
9302     // In the worst case we have to use the metadata to
9303     //  (a) load the exact interfaces and determine the order in which they
9304     //      go.  We do those by re-running the interface layout algorithm
9305     //      and using metadata-comparisons to place interfaces in the list.
9306     //  (b) do a check to see if any ambiguity in the interface dispatch map is introduced
9307     //      by the instantiation
9308     // See code:#LoadExactInterfaceMap_Algorithm2
9309     //
9310     // However, we can do something simpler: we just use
9311     // the loaded interface method tables to determine ordering.  This can be done
9312     // if there are no duplicate instantiated interfaces in the interface
9313     // set.
9314     // See code:#LoadExactInterfaceMap_Algorithm1.
9315
9316     if (!hasInstantiatedInterfaces)
9317     {
9318         return;
9319     }
9320
9321     HRESULT hr;
9322     TypeHandle thisTH(pMT);
9323     SigTypeContext typeContext(thisTH);
9324     MethodTable *pParentMT = pMT->GetParentMethodTable();
9325
9326     //#LoadExactInterfaceMap_Algorithm1
9327     // Exact interface instantiation loading TECHNIQUE 1.
9328     // (a) For interfaces inherited from an instantiated parent class, just copy down from exact parent
9329     // (b) Grab newly declared interfaces by loading and then copying down all their inherited parents
9330     // (c) But check for any exact duplicates along the way
9331     // (d) If no duplicates then we can use the computed interface map we've created
9332     // (e) If duplicates found then use the slow metadata-based technique code:#LoadExactInterfaceMap_Algorithm2
9333     DWORD nInterfacesCount = pMT->GetNumInterfaces();
9334     MethodTable **pExactMTs = (MethodTable**) _alloca(sizeof(MethodTable *) * nInterfacesCount);
9335     BOOL duplicates;
9336     bool retry = false;
9337
9338     // Always use exact loading behavior with classes or shared generics, as they have to deal with inheritance, and the
9339     // inexact matching logic for classes would be more complex to write.
9340     // Also always use the exact loading behavior with any generic that contains generic variables, as the open type is used
9341     // to represent a type instantiated over its own generic variables, and the special marker type is currently the open type
9342     // and we make this case distinguishable by simply disallowing the optimization in those cases.
9343     bool retryWithExactInterfaces = !pMT->IsValueType() || pMT->IsSharedByGenericInstantiations() || pMT->ContainsGenericVariables();
9344
9345     DWORD nAssigned = 0;
9346     do
9347     {
9348         nAssigned = 0;
9349         retry = false;
9350         duplicates = false;
9351         if (pParentMT != NULL)
9352         {
9353             MethodTable::InterfaceMapIterator parentIt = pParentMT->IterateInterfaceMap();
9354             while (parentIt.Next())
9355             {
9356                 duplicates |= InsertMethodTable(parentIt.GetInterface(pParentMT, CLASS_LOAD_EXACTPARENTS), pExactMTs, nInterfacesCount, &nAssigned);
9357             }
9358         }
9359         InterfaceImplEnum ie(pMT->GetModule(), pMT->GetCl(), NULL);
9360         while ((hr = ie.Next()) == S_OK)
9361         {
9362             MethodTable *pNewIntfMT = ClassLoader::LoadTypeDefOrRefOrSpecThrowing(pMT->GetModule(),
9363                                                                                 ie.CurrentToken(),
9364                                                                                 &typeContext,
9365                                                                                 ClassLoader::ThrowIfNotFound,
9366                                                                                 ClassLoader::FailIfUninstDefOrRef,
9367                                                                                 ClassLoader::LoadTypes,
9368                                                                                 CLASS_LOAD_EXACTPARENTS,
9369                                                                                 TRUE,
9370                                                                                 (const Substitution*)0,
9371                                                                                 retryWithExactInterfaces ? NULL : pMT).GetMethodTable();
9372
9373             bool uninstGenericCase = !retryWithExactInterfaces && pNewIntfMT->IsSpecialMarkerTypeForGenericCasting();
9374
9375             duplicates |= InsertMethodTable(pNewIntfMT, pExactMTs, nInterfacesCount, &nAssigned);
9376
9377             // We have a special algorithm for interface maps in CoreLib, which doesn't expand interfaces, and assumes no ambiguous
9378             // duplicates. Code related to this is marked with #SpecialCorelibInterfaceExpansionAlgorithm
9379             if (!(pMT->GetModule()->IsSystem() && pMT->IsValueType()))
9380             {
9381                 MethodTable::InterfaceMapIterator intIt = pNewIntfMT->IterateInterfaceMap();
9382                 while (intIt.Next())
9383                 {
9384                     MethodTable *pItfPossiblyApprox = intIt.GetInterfaceApprox();
9385                     if (uninstGenericCase && pItfPossiblyApprox->HasInstantiation() && pItfPossiblyApprox->ContainsGenericVariables())
9386                     {
9387                         // We allow a limited set of interface generic shapes with type variables. In particular, we require the
9388                         // instantiations to be exactly simple type variables, and to have a relatively small number of generic arguments
9389                         // so that the fallback instantiating logic works efficiently
9390                         if (InstantiationIsAllTypeVariables(pItfPossiblyApprox->GetInstantiation()) && pItfPossiblyApprox->GetInstantiation().GetNumArgs() <= MethodTable::MaxGenericParametersForSpecialMarkerType)
9391                         {
9392                             pItfPossiblyApprox = ClassLoader::LoadTypeDefThrowing(pItfPossiblyApprox->GetModule(), pItfPossiblyApprox->GetCl(), ClassLoader::ThrowIfNotFound, ClassLoader::PermitUninstDefOrRef, 0, CLASS_LOAD_EXACTPARENTS).AsMethodTable();
9393                         }
9394                         else
9395                         {
9396                             retry = true;
9397                             break;
9398                         }
9399                     }
9400                     duplicates |= InsertMethodTable(intIt.GetInterface(pNewIntfMT, CLASS_LOAD_EXACTPARENTS), pExactMTs, nInterfacesCount, &nAssigned);
9401                 }
9402             }
9403
9404             if (retry)
9405                 break;
9406         }
9407
9408         if (retry)
9409         {
9410             retryWithExactInterfaces = true;
9411         }
9412     } while (retry);
9413
9414     if (FAILED(hr))
9415     {
9416         pMT->GetAssembly()->ThrowTypeLoadException(pMT->GetMDImport(), pMT->GetCl(), IDS_CLASSLOAD_BADFORMAT);
9417     }
9418 #ifdef _DEBUG
9419     if (!pMT->GetModule()->IsSystem())
9420     {
9421
9422         duplicates |= CLRConfig::GetConfigValue(CLRConfig::INTERNAL_AlwaysUseMetadataInterfaceMapLayout);
9423     }
9424
9425     //#InjectInterfaceDuplicates_LoadExactInterfaceMap
9426     // If we are injecting duplicates also for non-generic interfaces in check builds, we have to use
9427     // algorithm code:#LoadExactInterfaceMap_Algorithm2.
9428     // Has to be in sync with code:#InjectInterfaceDuplicates_Main.
9429     duplicates |= pMT->Debug_HasInjectedInterfaceDuplicates();
9430 #endif
9431     // We have a special algorithm for interface maps in CoreLib, which doesn't expand interfaces, and assumes no ambiguous
9432     // duplicates. Code related to this is marked with #SpecialCorelibInterfaceExpansionAlgorithm
9433     _ASSERTE(!duplicates || !(pMT->GetModule()->IsSystem() && pMT->IsValueType()));
9434
9435     CONSISTENCY_CHECK(duplicates || (nAssigned == pMT->GetNumInterfaces()));
9436     if (duplicates)
9437     {
9438         //#LoadExactInterfaceMap_Algorithm2
9439         // Exact interface instantiation loading TECHNIQUE 2 - The exact instantiation has caused some duplicates to
9440         // appear in the interface map!  This may not be an error: if the duplicates were ones that arose because of
9441         // inheritance from a parent type then we accept that.  For example
9442         //     class C<T> : I<T>
9443         //     class D<T> : C<T>, I<string>
9444         // is acceptable even when loading D<string>.  Note that in such a case
9445         // there will be two entries for I<string> in the final interface map for D<string>.
9446         // For dispatch the mappings in D take precedence.
9447         //
9448         // However we consider it an error if there is real ambiguity within
9449         // the interface definitions within the one class, e.g.
9450         //     class E<T> : I<T>, I<string>
9451         // In this situation it is not defined how to dispatch calls to I<string>: would
9452         // we use the bindings for I<T> or I<string>?
9453         //
9454         // Because we may had duplicates the interface map we created above may not
9455         // be the correct one: for example for D<string> above we would have computed
9456         // a map with only one entry.  This is incorrect: an exact instantiation's interface
9457         // map must have entries that match the ordering of the interface map in the generic case
9458         // (this is because code:#InterfaceMap_SupersetOfParent).
9459         //
9460         // So, in order to determine how to place the interfaces we need go back to
9461         // the metadata. We also do this to check if the presence of duplicates
9462         // has caused any potential ambiguity, i.e. the E<string> case above.
9463
9464         // First we do a GetCheckpoint for the thread-based allocator.  ExpandExactInheritedInterfaces allocates substitution chains
9465         // on the thread allocator rather than on the stack.
9466         ACQUIRE_STACKING_ALLOCATOR(pStackingAllocator);
9467
9468         // ***********************************************************
9469         // ****** This must be consistent with code:ExpandApproxInterface etc. *******
9470         //
9471         // The correlation to ExpandApproxInterfaces etc. simply drops out by how we
9472         // traverse interfaces.
9473         // ***********************************************************
9474
9475         bmtExactInterfaceInfo bmtExactInterface;
9476         bmtExactInterface.pInterfaceSubstitution = new (pStackingAllocator) Substitution[pMT->GetNumInterfaces()];
9477         bmtExactInterface.pExactMTs = pExactMTs;
9478         bmtExactInterface.nAssigned = 0;
9479         bmtExactInterface.typeContext = typeContext;
9480
9481         // Do the interfaces inherited from a parent class
9482         if ((pParentMT != NULL) && (pParentMT->GetNumInterfaces() > 0))
9483         {
9484             Substitution * pParentSubstForTypeLoad = new (pStackingAllocator) Substitution(
9485                 pMT->GetSubstitutionForParent(NULL));
9486             Substitution * pParentSubstForComparing = new (pStackingAllocator) Substitution(
9487                 pMT->GetSubstitutionForParent(NULL));
9488             ExpandExactInheritedInterfaces(
9489                 &bmtExactInterface,
9490                 pParentMT,
9491                 pParentSubstForTypeLoad,
9492                 pParentSubstForComparing,
9493                 pStackingAllocator,
9494                 retryWithExactInterfaces ? NULL : pMT);
9495         }
9496 #ifdef _DEBUG
9497         //#ExactInterfaceMap_SupersetOfParent
9498         // Check that parent's interface map is subset of this interface map
9499         // See code:#InterfaceMap_SupersetOfParent
9500         {
9501             _ASSERTE(pParentMT->GetNumInterfaces() == bmtExactInterface.nAssigned);
9502
9503             MethodTable::InterfaceMapIterator parentInterfacesIterator = pParentMT->IterateInterfaceMap();
9504             UINT32 nInterfaceIndex = 0;
9505             while (parentInterfacesIterator.Next())
9506             {
9507                 if (pMT->IsSharedByGenericInstantiations())
9508                 {   // The type is a canonical instantiation (contains _Canon)
9509                     // The interface instantiations of parent can be different (see
9510                     // code:#InterfaceMap_CanonicalSupersetOfParent), therefore we cannot compare
9511                     // MethodTables
9512                     _ASSERTE(parentInterfacesIterator.GetInterfaceInfo()->GetApproxMethodTable(pParentMT->GetLoaderModule())->HasSameTypeDefAs(
9513                         bmtExactInterface.pExactMTs[nInterfaceIndex]));
9514                 }
9515                 else
9516                 {   // It is not canonical instantiation, we can compare MethodTables
9517                     _ASSERTE(parentInterfacesIterator.GetInterfaceApprox() == bmtExactInterface.pExactMTs[nInterfaceIndex]);
9518                 }
9519                 nInterfaceIndex++;
9520             }
9521             _ASSERTE(nInterfaceIndex == bmtExactInterface.nAssigned);
9522         }
9523 #endif //_DEBUG
9524
9525         // If there are any __Canon instances in the type argument list, then we defer the
9526         // ambiguity checking until an exact instantiation.
9527         // As the C# compiler won't allow an ambiguous generic interface to be generated, we don't
9528         // need this logic for CoreLib. We can't use the sanity checks flag here, as these ambiguities
9529         // are specified to the exact instantiation in use, not just whether or not normal the type is
9530         // well formed in metadata.
9531         if (!pMT->IsSharedByGenericInstantiations() && !pMT->GetModule()->IsSystem())
9532         {
9533             // There are no __Canon types in the instantiation, so do ambiguity check.
9534             bmtInterfaceAmbiguityCheckInfo bmtCheckInfo;
9535             bmtCheckInfo.pMT = pMT;
9536             bmtCheckInfo.ppInterfaceSubstitutionChains = new (pStackingAllocator) Substitution *[pMT->GetNumInterfaces()];
9537             bmtCheckInfo.ppExactDeclaredInterfaces = new (pStackingAllocator) MethodTable *[pMT->GetNumInterfaces()];
9538             bmtCheckInfo.nAssigned = 0;
9539             bmtCheckInfo.typeContext = typeContext;
9540             MethodTableBuilder::InterfacesAmbiguityCheck(&bmtCheckInfo, pMT->GetModule(), pMT->GetCl(), NULL, pStackingAllocator);
9541         }
9542
9543         // OK, there is no ambiguity amongst the instantiated interfaces declared on this class.
9544         MethodTableBuilder::ExpandExactDeclaredInterfaces(
9545             &bmtExactInterface,
9546             pMT->GetModule(),
9547             pMT->GetCl(),
9548             NULL,
9549             NULL,
9550             pStackingAllocator,
9551             retryWithExactInterfaces ? NULL : pMT
9552             COMMA_INDEBUG(pMT));
9553         CONSISTENCY_CHECK(bmtExactInterface.nAssigned == pMT->GetNumInterfaces());
9554
9555         // We cannot process interface duplicates on types with __Canon. The duplicates are processed on
9556         // exact types only
9557         if (!pMT->IsSharedByGenericInstantiations())
9558         {
9559             // Process all pairs of duplicates in the interface map:
9560             //     i.e. If there are 3 duplicates of the same interface at indexes: i1, i2 and i3, then
9561             //     process pairs of indexes [i1,i2], [i1,i3] and [i2,i3].
9562             //  - Update 'declared on type' flag for those interfaces which duplicate is 'declared on type'
9563             //  - Check interface method implementation ambiguity code:#DuplicateInterface_MethodAmbiguity
9564             for (DWORD nOriginalIndex = 0; nOriginalIndex < nInterfacesCount; nOriginalIndex++)
9565             {
9566                 // Search for duplicates further in the interface map
9567                 for (DWORD nDuplicateIndex = nOriginalIndex + 1; nDuplicateIndex < nInterfacesCount; nDuplicateIndex++)
9568                 {
9569                     if (pExactMTs[nOriginalIndex] != pExactMTs[nDuplicateIndex])
9570                     {   // It's not a duplicate of original interface, skip it
9571                         continue;
9572                     }
9573                     // We found a duplicate
9574
9575                     // Set 'declared on type' flag if either original or duplicate interface is
9576                     // 'declared on type'
9577                     if (pMT->IsInterfaceDeclaredOnClass(nOriginalIndex) ||
9578                         pMT->IsInterfaceDeclaredOnClass(nDuplicateIndex))
9579                     {
9580                         //
9581                         // Note that both checks are needed:
9582                         //     A<T> : I<T>
9583                         //     B<T,U> : A<T>, I<U>
9584                         //     C<T,U> : B<T,U>, I<T>   // Reimplements interface from A<T>
9585                         // After code:BuildMethodTableThrowing algorithm, this will happen:
9586                         // B<int,int> will have interface map similar to B<T,U>:
9587                         //     I<int> ... not 'declared on type'
9588                         //     I<int> ... 'declared on type'
9589                         // C<int,int> will have interface map similar to C<T,U>:
9590                         //     I<int> ... 'declared on type'
9591                         //     I<int> ... not 'declared on type'
9592                         //
9593
9594                         pMT->SetInterfaceDeclaredOnClass(nOriginalIndex);
9595                         pMT->SetInterfaceDeclaredOnClass(nDuplicateIndex);
9596                     }
9597
9598                     //#DuplicateInterface_MethodAmbiguity
9599                     //
9600                     // In the ideal world we would now check for interface method implementation
9601                     // ambiguity in the instantiation, but that would be a technical breaking change
9602                     // (against 2.0 RTM/SP1).
9603                     // Therefore we ALLOW when interface method is implemented twice through this
9604                     // original and duplicate interface.
9605                     //
9606                     // This ambiguity pattern is therefore ALLOWED (can be expressed only in IL, not in C#):
9607                     //     I<T>
9608                     //         void Print(T t);
9609                     //     A<T> : I<T>    // abstract class
9610                     //     B<T,U> : A<T>, I<U>
9611                     //         void Print(T t) { ... }
9612                     //         void Print(U u) { ... }
9613                     //     Now B<int,int> has 2 implementations of I<int>.Print(int), while B<int,char> is
9614                     //     fine. Therefore an instantiation can introduce ambiguity.
9615
9616 #if 0 // Removing this code for now as it is a technical breaking change (against CLR 2.0 RTM/SP1).
9617       // We might decide later that we want to take this breaking change.
9618                     //
9619                     // Note that dispatch map entries are sorted by interface index and then interface
9620                     // method slot index.
9621                     //
9622                     DispatchMapTypeID originalTypeID = DispatchMapTypeID::InterfaceClassID(nOriginalIndex);
9623                     DispatchMap::EncodedMapIterator originalIt(pMT);
9624                     // Find first entry for original interface
9625                     while (originalIt.IsValid())
9626                     {
9627                         DispatchMapEntry *pEntry = originalIt.Entry();
9628                         if (pEntry->GetTypeID().ToUINT32() >= originalTypeID.ToUINT32())
9629                         {   // Found the place where original interface entries should be (dispatch map is
9630                             // sorted)
9631                             break;
9632                         }
9633                         originalIt.Next();
9634                     }
9635
9636                     DispatchMapTypeID duplicateTypeID = DispatchMapTypeID::InterfaceClassID(nDuplicateIndex);
9637                     DispatchMap::EncodedMapIterator duplicateIt(pMT);
9638                     // Find first entry for duplicate interface
9639                     while (duplicateIt.IsValid())
9640                     {
9641                         DispatchMapEntry *pEntry = duplicateIt.Entry();
9642                         if (pEntry->GetTypeID().ToUINT32() >= duplicateTypeID.ToUINT32())
9643                         {   // Found the place where original interface entries should be (dispatch map is
9644                             // sorted)
9645                             break;
9646                         }
9647                         duplicateIt.Next();
9648                     }
9649
9650                     // Compare original and duplicate interface entries in the dispatch map if they contain
9651                     // different implementation for the same interface method
9652                     while (true)
9653                     {
9654                         if (!originalIt.IsValid() || !duplicateIt.IsValid())
9655                         {   // We reached end of one dispatch map iterator
9656                             break;
9657                         }
9658                         DispatchMapEntry *pOriginalEntry = originalIt.Entry();
9659                         if (pOriginalEntry->GetTypeID().ToUINT32() != originalTypeID.ToUINT32())
9660                         {   // We reached behind original interface entries
9661                             break;
9662                         }
9663                         DispatchMapEntry *pDuplicateEntry = duplicateIt.Entry();
9664                         if (pDuplicateEntry->GetTypeID().ToUINT32() != duplicateTypeID.ToUINT32())
9665                         {   // We reached behind duplicate interface entries
9666                             break;
9667                         }
9668
9669                         if (pOriginalEntry->GetSlotNumber() == pDuplicateEntry->GetSlotNumber())
9670                         {   // Found duplicate implementation of interface method
9671                             if (pOriginalEntry->GetTargetSlotNumber() != pDuplicateEntry->GetTargetSlotNumber())
9672                             {   // Implementation of the slots is different
9673                                 bmtErrorInfo bmtError;
9674
9675                                 bmtError.pModule = pMT->GetModule();
9676                                 bmtError.cl = pMT->GetCl();
9677                                 bmtError.resIDWhy = IDS_CLASSLOAD_MI_MULTIPLEOVERRIDES;
9678                                 bmtError.szMethodNameForError = NULL;
9679                                 bmtError.pThrowable = NULL;
9680
9681                                 MethodDesc *pMD = pMT->GetMethodDescForSlot(pDuplicateEntry->GetTargetSlotNumber());
9682                                 bmtError.dMethodDefInError = pMD->GetMemberDef();
9683
9684                                 BuildMethodTableThrowException(COR_E_TYPELOAD, bmtError);
9685                             }
9686                             // The method is implemented by the same slot on both interfaces (original and
9687                             // duplicate)
9688
9689                             // Process next dispatch map entry
9690                             originalIt.Next();
9691                             duplicateIt.Next();
9692                             continue;
9693                         }
9694                         // Move iterator representing smaller interface method slot index (the dispatch map
9695                         // is sorted by slot indexes)
9696                         if (pOriginalEntry->GetSlotNumber() < pDuplicateEntry->GetSlotNumber())
9697                         {
9698                             originalIt.Next();
9699                             continue;
9700                         }
9701                         _ASSERTE(pOriginalEntry->GetSlotNumber() > pDuplicateEntry->GetSlotNumber());
9702                         duplicateIt.Next();
9703                     }
9704 #endif //0
9705                 }
9706                 // All duplicates of this original interface were processed
9707             }
9708             // All pairs of duplicates in the interface map are processed
9709         }
9710     }
9711     // Duplicates in the interface map are resolved
9712
9713     // OK, if we've got this far then pExactMTs should now hold the array of exact instantiated interfaces.
9714     MethodTable::InterfaceMapIterator thisIt = pMT->IterateInterfaceMap();
9715     DWORD i = 0;
9716     while (thisIt.Next())
9717     {
9718 #ifdef _DEBUG
9719         MethodTable *pNewMT = pExactMTs[i];
9720         CONSISTENCY_CHECK(thisIt.HasSameTypeDefAs(pNewMT));
9721 #endif // _DEBUG
9722         thisIt.SetInterface(pExactMTs[i]);
9723         i++;
9724     }
9725
9726 } // MethodTableBuilder::LoadExactInterfaceMap
9727
9728 //*******************************************************************************
9729 void
9730 MethodTableBuilder::ExpandExactInheritedInterfaces(
9731     bmtExactInterfaceInfo * bmtInfo,
9732     MethodTable *           pMT,
9733     const Substitution *    pSubstForTypeLoad,
9734     Substitution *          pSubstForComparing,
9735     StackingAllocator *     pStackingAllocator,
9736     MethodTable *           pMTInterfaceMapOwner)
9737 {
9738     STANDARD_VM_CONTRACT;
9739
9740     MethodTable *pParentMT = pMT->GetParentMethodTable();
9741
9742     // Backup type's substitution chain for comparing interfaces
9743     Substitution substForComparingBackup = *pSubstForComparing;
9744     // Make type an open type for comparing interfaces
9745     *pSubstForComparing = Substitution();
9746
9747     if (pParentMT)
9748     {
9749         // Chain parent's substitution for exact type load
9750         Substitution * pParentSubstForTypeLoad = new (pStackingAllocator) Substitution(
9751             pMT->GetSubstitutionForParent(pSubstForTypeLoad));
9752
9753         // Chain parent's substitution for comparing interfaces (note that this type is temporarily
9754         // considered as open type)
9755         Substitution * pParentSubstForComparing = new (pStackingAllocator) Substitution(
9756             pMT->GetSubstitutionForParent(pSubstForComparing));
9757
9758         ExpandExactInheritedInterfaces(
9759             bmtInfo,
9760             pParentMT,
9761             pParentSubstForTypeLoad,
9762             pParentSubstForComparing,
9763             pStackingAllocator,
9764             pMTInterfaceMapOwner);
9765     }
9766     ExpandExactDeclaredInterfaces(
9767         bmtInfo,
9768         pMT->GetModule(),
9769         pMT->GetCl(),
9770         pSubstForTypeLoad,
9771         pSubstForComparing,
9772         pStackingAllocator,
9773         pMTInterfaceMapOwner
9774         COMMA_INDEBUG(pMT));
9775
9776     // Restore type's substitution chain for comparing interfaces
9777     *pSubstForComparing = substForComparingBackup;
9778 } // MethodTableBuilder::ExpandExactInheritedInterfaces
9779
9780 //*******************************************************************************
9781 /* static */
9782 void
9783 MethodTableBuilder::ExpandExactDeclaredInterfaces(
9784     bmtExactInterfaceInfo *     bmtInfo,
9785     Module *                    pModule,
9786     mdToken                     typeDef,
9787     const Substitution *        pSubstForTypeLoad,
9788     Substitution *              pSubstForComparing,
9789     StackingAllocator *         pStackingAllocator,
9790     MethodTable *               pMTInterfaceMapOwner
9791     COMMA_INDEBUG(MethodTable * dbg_pClassMT))
9792 {
9793     STANDARD_VM_CONTRACT;
9794
9795     HRESULT hr;
9796     InterfaceImplEnum ie(pModule, typeDef, NULL);
9797     while ((hr = ie.Next()) == S_OK)
9798     {
9799         MethodTable * pInterface = ClassLoader::LoadTypeDefOrRefOrSpecThrowing(
9800             pModule,
9801             ie.CurrentToken(),
9802             &bmtInfo->typeContext,
9803             ClassLoader::ThrowIfNotFound,
9804             ClassLoader::FailIfUninstDefOrRef,
9805             ClassLoader::LoadTypes,
9806             CLASS_LOAD_EXACTPARENTS,
9807             TRUE,
9808             pSubstForTypeLoad,
9809             pMTInterfaceMapOwner).GetMethodTable();
9810
9811         Substitution ifaceSubstForTypeLoad(ie.CurrentToken(), pModule, pSubstForTypeLoad);
9812         Substitution ifaceSubstForComparing(ie.CurrentToken(), pModule, pSubstForComparing);
9813         ExpandExactInterface(
9814             bmtInfo,
9815             pInterface,
9816             &ifaceSubstForTypeLoad,
9817             &ifaceSubstForComparing,
9818             pStackingAllocator,
9819             pMTInterfaceMapOwner
9820             COMMA_INDEBUG(dbg_pClassMT));
9821     }
9822     if (FAILED(hr))
9823     {
9824         pModule->GetAssembly()->ThrowTypeLoadException(pModule->GetMDImport(), typeDef, IDS_CLASSLOAD_BADFORMAT);
9825     }
9826 } // MethodTableBuilder::ExpandExactDeclaredInterfaces
9827
9828 //*******************************************************************************
9829 void
9830 MethodTableBuilder::ExpandExactInterface(
9831     bmtExactInterfaceInfo *     bmtInfo,
9832     MethodTable *               pIntf,
9833     const Substitution *        pSubstForTypeLoad_OnStack,   // Allocated on stack!
9834     const Substitution *        pSubstForComparing_OnStack,  // Allocated on stack!
9835     StackingAllocator *         pStackingAllocator,
9836     MethodTable *               pMTInterfaceMapOwner
9837     COMMA_INDEBUG(MethodTable * dbg_pClassMT))
9838 {
9839     STANDARD_VM_CONTRACT;
9840
9841     // ****** This must be consistent with code:MethodTableBuilder::ExpandApproxInterface ******
9842
9843     // Is it already present according to the "generic" layout of the interfaces.
9844     // Note we use exactly the same algorithm as when we
9845     // determined the layout of the interface map for the "generic" version of the class.
9846     for (DWORD i = 0; i < bmtInfo->nAssigned; i++)
9847     {
9848         // Type Equivalence is not respected for this comparison as you can have multiple type equivalent interfaces on a class
9849         TokenPairList newVisited = TokenPairList::AdjustForTypeEquivalenceForbiddenScope(NULL);
9850         if (MetaSig::CompareTypeDefsUnderSubstitutions(bmtInfo->pExactMTs[i],
9851                                                        pIntf,
9852                                                        &bmtInfo->pInterfaceSubstitution[i],
9853                                                        pSubstForComparing_OnStack,
9854                                                        &newVisited))
9855         {
9856 #ifdef _DEBUG
9857             //#InjectInterfaceDuplicates_ExactInterfaces
9858             // We will inject duplicate interfaces in check builds.
9859             // Has to be in sync with code:#InjectInterfaceDuplicates_Main.
9860             if (dbg_pClassMT->Debug_HasInjectedInterfaceDuplicates())
9861             {   // Just pretend we didn't find this match
9862                 break;
9863             }
9864 #endif //_DEBUG
9865             return; // found it, don't add it again
9866         }
9867     }
9868
9869     // Add the interface and its sub-interfaces
9870     DWORD n = bmtInfo->nAssigned;
9871     bmtInfo->pExactMTs[n] = pIntf;
9872     bmtInfo->pInterfaceSubstitution[n] = *pSubstForComparing_OnStack;
9873     bmtInfo->nAssigned++;
9874
9875     Substitution * pSubstForTypeLoad = new (pStackingAllocator) Substitution(*pSubstForTypeLoad_OnStack);
9876
9877     ExpandExactDeclaredInterfaces(
9878         bmtInfo,
9879         pIntf->GetModule(),
9880         pIntf->GetCl(),
9881         pSubstForTypeLoad,
9882         &bmtInfo->pInterfaceSubstitution[n],
9883         pStackingAllocator,
9884         pMTInterfaceMapOwner
9885         COMMA_INDEBUG(dbg_pClassMT));
9886 } // MethodTableBuilder::ExpandExactInterface
9887
9888 //*******************************************************************************
9889 /* static */
9890 void MethodTableBuilder::InterfacesAmbiguityCheck(bmtInterfaceAmbiguityCheckInfo *bmtCheckInfo,
9891                                                   Module *pModule,
9892                                                   mdToken typeDef,
9893                                                   const Substitution *pSubstChain,
9894                                                   StackingAllocator *pStackingAllocator)
9895 {
9896     STANDARD_VM_CONTRACT;
9897
9898     HRESULT hr;
9899     InterfaceImplEnum ie(pModule, typeDef, pSubstChain);
9900     while ((hr = ie.Next()) == S_OK)
9901     {
9902         MethodTable *pInterface =
9903             ClassLoader::LoadTypeDefOrRefOrSpecThrowing(pModule, ie.CurrentToken(),
9904                                                         &bmtCheckInfo->typeContext,
9905                                                         ClassLoader::ThrowIfNotFound,
9906                                                         ClassLoader::FailIfUninstDefOrRef,
9907                                                         ClassLoader::LoadTypes,
9908                                                         CLASS_LOAD_EXACTPARENTS,
9909                                                         TRUE,
9910                                                         pSubstChain).GetMethodTable();
9911         InterfaceAmbiguityCheck(bmtCheckInfo, ie.CurrentSubst(), pInterface, pStackingAllocator);
9912     }
9913     if (FAILED(hr))
9914     {
9915         pModule->GetAssembly()->ThrowTypeLoadException(pModule->GetMDImport(), typeDef, IDS_CLASSLOAD_BADFORMAT);
9916     }
9917 }
9918
9919 //*******************************************************************************
9920 void MethodTableBuilder::InterfaceAmbiguityCheck(bmtInterfaceAmbiguityCheckInfo *bmtCheckInfo,
9921                                                  const Substitution *pItfSubstChain,
9922                                                  MethodTable *pIntf,
9923                                                  StackingAllocator *pStackingAllocator)
9924 {
9925     STANDARD_VM_CONTRACT;
9926
9927     // Is it already in the generic version of the freshly declared interfaces. We
9928     // do this based on metadata, i.e. via the substitution chains.
9929     // Note we use exactly the same algorithm as when we
9930     // determined the layout of the interface map for the "generic" version of the class.
9931     for (DWORD i = 0; i < bmtCheckInfo->nAssigned; i++)
9932     {
9933         // Type Equivalence is not respected for this comparison as you can have multiple type equivalent interfaces on a class
9934         TokenPairList newVisited = TokenPairList::AdjustForTypeEquivalenceForbiddenScope(NULL);
9935         if (MetaSig::CompareTypeDefsUnderSubstitutions(bmtCheckInfo->ppExactDeclaredInterfaces[i],
9936                                                        pIntf,
9937                                                        bmtCheckInfo->ppInterfaceSubstitutionChains[i],
9938                                                        pItfSubstChain,
9939                                                        &newVisited))
9940             return; // found it, don't add it again
9941     }
9942
9943     // OK, so it isn't a duplicate based on the generic IL, now check if the instantiation
9944     // makes it a duplicate.
9945     for (DWORD i = 0; i < bmtCheckInfo->nAssigned; i++)
9946     {
9947         if (bmtCheckInfo->ppExactDeclaredInterfaces[i] == pIntf)
9948         {
9949                 bmtCheckInfo->pMT->GetModule()->GetAssembly()->ThrowTypeLoadException(bmtCheckInfo->pMT->GetMDImport(),
9950                                                                                       bmtCheckInfo->pMT->GetCl(),
9951                                                                                       IDS_CLASSLOAD_OVERLAPPING_INTERFACES);
9952         }
9953     }
9954
9955     DWORD n = bmtCheckInfo->nAssigned;
9956     bmtCheckInfo->ppExactDeclaredInterfaces[n] = pIntf;
9957     bmtCheckInfo->ppInterfaceSubstitutionChains[n] = new (pStackingAllocator) Substitution[pItfSubstChain->GetLength()];
9958     pItfSubstChain->CopyToArray(bmtCheckInfo->ppInterfaceSubstitutionChains[n]);
9959
9960     bmtCheckInfo->nAssigned++;
9961     InterfacesAmbiguityCheck(bmtCheckInfo,pIntf->GetModule(),pIntf->GetCl(),pItfSubstChain, pStackingAllocator);
9962 }
9963
9964
9965 //*******************************************************************************
9966 void MethodTableBuilder::CheckForSystemTypes()
9967 {
9968     STANDARD_VM_CONTRACT;
9969
9970     LPCUTF8 name, nameSpace;
9971
9972     MethodTable * pMT = GetHalfBakedMethodTable();
9973     EEClass * pClass = GetHalfBakedClass();
9974
9975     // We can exit early for generic types - there are just a few cases to check for.
9976     if (bmtGenerics->HasInstantiation())
9977     {
9978         if (pMT->IsIntrinsicType() && pClass->HasLayout())
9979         {
9980             if (FAILED(GetMDImport()->GetNameOfTypeDef(GetCl(), &name, &nameSpace)))
9981             {
9982                 BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
9983             }
9984
9985             if (strcmp(nameSpace, g_IntrinsicsNS) == 0)
9986             {
9987                 EEClassLayoutInfo* pLayout = pClass->GetLayoutInfo();
9988
9989                 // The SIMD Hardware Intrinsic types correspond to fundamental data types in the underlying ABIs:
9990                 // * Vector64<T>:  __m64
9991                 // * Vector128<T>: __m128
9992                 // * Vector256<T>: __m256
9993
9994                 // These __m128 and __m256 types, among other requirements, are special in that they must always
9995                 // be aligned properly.
9996
9997                 if (strcmp(name, g_Vector64Name) == 0)
9998                 {
9999                     // The System V ABI for i386 defaults to 8-byte alignment for __m64, except for parameter passing,
10000                     // where it has an alignment of 4.
10001
10002                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 8; // sizeof(__m64)
10003                 }
10004                 else if (strcmp(name, g_Vector128Name) == 0)
10005                 {
10006     #ifdef TARGET_ARM
10007                     // The Procedure Call Standard for ARM defaults to 8-byte alignment for __m128
10008
10009                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 8;
10010     #else
10011                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 16; // sizeof(__m128)
10012     #endif // TARGET_ARM
10013                 }
10014                 else if (strcmp(name, g_Vector256Name) == 0)
10015                 {
10016     #ifdef TARGET_ARM
10017                     // No such type exists for the Procedure Call Standard for ARM. We will default
10018                     // to the same alignment as __m128, which is supported by the ABI.
10019
10020                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 8;
10021     #elif defined(TARGET_ARM64)
10022                     // The Procedure Call Standard for ARM 64-bit (with SVE support) defaults to
10023                     // 16-byte alignment for __m256.
10024
10025                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 16;
10026     #elif defined(TARGET_RISCV64)
10027                     // TODO-RISCV64: Update alignment to proper value when we implement RISC-V intrinsic.
10028                     // RISC-V Vector Extenstion Intrinsic Document
10029                     // https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/vector_type_infos.adoc
10030                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 16;
10031     #else
10032                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 32; // sizeof(__m256)
10033     #endif // TARGET_ARM elif TARGET_ARM64
10034                 }
10035                 else if (strcmp(name, g_Vector512Name) == 0)
10036                 {
10037     #ifdef TARGET_ARM
10038                     // No such type exists for the Procedure Call Standard for ARM. We will default
10039                     // to the same alignment as __m128, which is supported by the ABI.
10040
10041                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 8;
10042     #elif defined(TARGET_ARM64)
10043                     // The Procedure Call Standard for ARM 64-bit (with SVE support) defaults to
10044                     // 16-byte alignment for __m256.
10045
10046                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 16;
10047
10048     #elif defined(TARGET_RISCV64)
10049                     // TODO-RISCV64: Update alignment to proper value when we implement RISC-V intrinsic.
10050                     // RISC-V Vector Extenstion Intrinsic Document
10051                     // https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/vector_type_infos.adoc
10052                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 16;
10053     #else
10054                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 64; // sizeof(__m512)
10055     #endif // TARGET_ARM elif TARGET_ARM64
10056                 }
10057                 else
10058                 {
10059                     // These types should be handled or explicitly skipped below to ensure that we don't
10060                     // miss adding required ABI support for future types.
10061
10062                     _ASSERTE_MSG(FALSE, "Unhandled Hardware Intrinsic Type.");
10063                 }
10064
10065                 return;
10066             }
10067         }
10068
10069         if (g_pNullableClass != NULL)
10070         {
10071             _ASSERTE(g_pNullableClass->IsNullable());
10072
10073             // Pre-compute whether the class is a Nullable<T> so that code:Nullable::IsNullableType is efficient
10074             // This is useful to the performance of boxing/unboxing a Nullable
10075             if (GetCl() == g_pNullableClass->GetCl())
10076                 pMT->SetIsNullable();
10077
10078             return;
10079         }
10080     }
10081
10082     if (IsNested() || IsEnum())
10083         return;
10084
10085     if (FAILED(GetMDImport()->GetNameOfTypeDef(GetCl(), &name, &nameSpace)))
10086     {
10087         BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
10088     }
10089
10090     if (IsValueClass())
10091     {
10092         //
10093         // Value types
10094         //
10095
10096         // All special value types are in the system namespace
10097         if (strcmp(nameSpace, g_SystemNS) != 0)
10098             return;
10099
10100         // Check if it is a primitive type
10101         CorElementType type = CorTypeInfo::FindPrimitiveType(name);
10102         if (type != ELEMENT_TYPE_END)
10103         {
10104             pMT->SetInternalCorElementType(type);
10105             pMT->SetIsTruePrimitive();
10106
10107 #if defined(TARGET_X86) && defined(UNIX_X86_ABI)
10108             switch (type)
10109             {
10110                 // The System V ABI for i386 defines different packing for these types.
10111
10112                 case ELEMENT_TYPE_I8:
10113                 case ELEMENT_TYPE_U8:
10114                 case ELEMENT_TYPE_R8:
10115                 {
10116                     EEClassLayoutInfo * pLayout = pClass->GetLayoutInfo();
10117                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 4;
10118                     break;
10119                 }
10120
10121                 default:
10122                     break;
10123             }
10124 #endif // TARGET_X86 && UNIX_X86_ABI
10125
10126 #ifdef _DEBUG
10127             if (FAILED(GetMDImport()->GetNameOfTypeDef(GetCl(), &name, &nameSpace)))
10128             {
10129                 name = nameSpace = "Invalid TypeDef record";
10130             }
10131             LOG((LF_CLASSLOADER, LL_INFO10000, "%s::%s marked as primitive type %i\n", nameSpace, name, type));
10132 #endif // _DEBUG
10133         }
10134         else if (strcmp(name, g_NullableName) == 0)
10135         {
10136             pMT->SetIsNullable();
10137         }
10138         else if (strcmp(name, g_RuntimeArgumentHandleName) == 0)
10139         {
10140             pMT->SetInternalCorElementType (ELEMENT_TYPE_I);
10141         }
10142         else if (strcmp(name, g_RuntimeMethodHandleInternalName) == 0)
10143         {
10144             pMT->SetInternalCorElementType (ELEMENT_TYPE_I);
10145         }
10146         else if (strcmp(name, g_RuntimeFieldHandleInternalName) == 0)
10147         {
10148             pMT->SetInternalCorElementType (ELEMENT_TYPE_I);
10149         }
10150         else if ((strcmp(name, g_Int128Name) == 0) || (strcmp(name, g_UInt128Name) == 0))
10151         {
10152             EEClassLayoutInfo* pLayout = pClass->GetLayoutInfo();
10153             pLayout->SetIsInt128OrHasInt128Fields(TRUE);
10154 #ifdef TARGET_ARM
10155             // No such type exists for the Procedure Call Standard for ARM. We will default
10156             // to the same alignment as __m128, which is supported by the ABI.
10157
10158             pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 8;
10159 #elif defined(TARGET_64BIT) || defined(TARGET_X86)
10160
10161             // These types correspond to fundamental data types in the underlying ABIs:
10162             // * Int128:  __int128
10163             // * UInt128: unsigned __int128
10164             //
10165             // This behavior matches the ABI standard on various Unix platforms
10166             // On Windows, no standard for Int128 has been established yet,
10167             // although applying 16 byte alignment is consistent with treatment of 128 bit SSE types
10168             // even on X86
10169             pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 16; // sizeof(__int128)
10170 #else
10171 #error Unknown architecture
10172 #endif // TARGET_64BIT
10173         }
10174     }
10175     else
10176     {
10177         //
10178         // Reference types
10179         //
10180         if (strcmp(name, g_StringName) == 0 && strcmp(nameSpace, g_SystemNS) == 0)
10181         {
10182             // Strings are not "normal" objects, so we need to mess with their method table a bit
10183             // so that the GC can figure out how big each string is...
10184             DWORD baseSize = StringObject::GetBaseSize();
10185             pMT->SetBaseSize(baseSize);
10186
10187             GetHalfBakedClass()->SetBaseSizePadding(baseSize - bmtFP->NumInstanceFieldBytes);
10188
10189             pMT->SetComponentSize(2);
10190         }
10191         else if (strcmp(name, g_CriticalFinalizerObjectName) == 0 && strcmp(nameSpace, g_ConstrainedExecutionNS) == 0)
10192         {
10193             // To introduce a class with a critical finalizer,
10194             // we'll set the bit here.
10195             pMT->SetHasCriticalFinalizer();
10196         }
10197 #ifdef FEATURE_COMINTEROP
10198         else
10199         {
10200             bool bIsComObject = false;
10201
10202             if (strcmp(name, g_ComObjectName) == 0 && strcmp(nameSpace, g_SystemNS) == 0)
10203                 bIsComObject = true;
10204
10205
10206             if (bIsComObject)
10207             {
10208                 // Make System.__ComObject a ComImport type
10209                 // We can't do it using attribute as C# won't allow putting code in ComImport types
10210                 pMT->SetComObjectType();
10211
10212                 // COM objects need an optional field on the EEClass, so ensure this class instance has allocated
10213                 // the optional field descriptor.
10214                 EnsureOptionalFieldsAreAllocated(pClass, m_pAllocMemTracker, GetLoaderAllocator()->GetLowFrequencyHeap());
10215             }
10216         }
10217 #endif // FEATURE_COMINTEROP
10218     }
10219 }
10220
10221 //==========================================================================================
10222 // Helper to create a new method table. This is the only
10223 // way to allocate a new MT. Don't try calling new / ctor.
10224 // Called from SetupMethodTable
10225 // This needs to be kept consistent with MethodTable::GetSavedExtent()
10226 MethodTable * MethodTableBuilder::AllocateNewMT(
10227     Module *pLoaderModule,
10228     DWORD dwVtableSlots,
10229     DWORD dwVirtuals,
10230     DWORD dwGCSize,
10231     DWORD dwNumInterfaces,
10232     DWORD dwNumDicts,
10233     DWORD cbInstAndDict,
10234     MethodTable *pMTParent,
10235     ClassLoader *pClassLoader,
10236     LoaderAllocator *pAllocator,
10237     BOOL isInterface,
10238     BOOL fDynamicStatics,
10239     BOOL fHasGenericsStaticsInfo,
10240     BOOL fHasVirtualStaticMethods
10241 #ifdef FEATURE_COMINTEROP
10242         , BOOL fHasDynamicInterfaceMap
10243 #endif
10244         , AllocMemTracker *pamTracker
10245     )
10246 {
10247     CONTRACT (MethodTable*)
10248     {
10249         THROWS;
10250         GC_TRIGGERS;
10251         MODE_ANY;
10252         POSTCONDITION(CheckPointer(RETVAL));
10253     }
10254     CONTRACT_END;
10255
10256     DWORD dwNonVirtualSlots = dwVtableSlots - dwVirtuals;
10257
10258     // GCSize must be aligned
10259     _ASSERTE(IS_ALIGNED(dwGCSize, sizeof(void*)));
10260
10261     // size without the interface map
10262     S_SIZE_T cbTotalSize = S_SIZE_T(dwGCSize) + S_SIZE_T(sizeof(MethodTable));
10263
10264     // vtable
10265     cbTotalSize += MethodTable::GetNumVtableIndirections(dwVirtuals) * sizeof(MethodTable::VTableIndir_t);
10266
10267     DWORD dwMultipurposeSlotsMask = 0;
10268     if (dwNumInterfaces != 0)
10269         dwMultipurposeSlotsMask |= MethodTable::enum_flag_HasInterfaceMap;
10270     if (dwNumDicts != 0)
10271         dwMultipurposeSlotsMask |= MethodTable::enum_flag_HasPerInstInfo;
10272     if (bmtVT->pDispatchMapBuilder->Count() > 0)
10273         dwMultipurposeSlotsMask |= MethodTable::enum_flag_HasDispatchMapSlot;
10274     if (dwNonVirtualSlots != 0)
10275         dwMultipurposeSlotsMask |= MethodTable::enum_flag_HasNonVirtualSlots;
10276     if (pLoaderModule != GetModule())
10277         dwMultipurposeSlotsMask |= MethodTable::enum_flag_HasModuleOverride;
10278
10279     // Add space for optional members here. Same as GetOptionalMembersSize()
10280     cbTotalSize += MethodTable::GetOptionalMembersAllocationSize(dwMultipurposeSlotsMask,
10281                                                       fHasGenericsStaticsInfo,
10282                                                       RidFromToken(GetCl()) >= METHODTABLE_TOKEN_OVERFLOW);
10283
10284     // Interface map starts here
10285     S_SIZE_T offsetOfInterfaceMap = cbTotalSize;
10286
10287     cbTotalSize += S_SIZE_T(dwNumInterfaces) * S_SIZE_T(sizeof(InterfaceInfo_t));
10288
10289 #ifdef FEATURE_COMINTEROP
10290     // DynamicInterfaceMap have an extra DWORD added to the end of the normal interface
10291     // map. This will be used to store the count of dynamically added interfaces
10292     // (the ones that are not in  the metadata but are QI'ed for at runtime).
10293     cbTotalSize += S_SIZE_T(fHasDynamicInterfaceMap ? sizeof(DWORD_PTR) : 0);
10294 #endif
10295
10296     // Dictionary pointers start here
10297     S_SIZE_T offsetOfInstAndDict = cbTotalSize;
10298
10299     if (dwNumDicts != 0)
10300     {
10301         cbTotalSize += sizeof(GenericsDictInfo);
10302         cbTotalSize += S_SIZE_T(dwNumDicts) * S_SIZE_T(sizeof(MethodTable::PerInstInfoElem_t));
10303         cbTotalSize += cbInstAndDict;
10304     }
10305
10306     S_SIZE_T offsetOfUnsharedVtableChunks = cbTotalSize;
10307
10308     // We will share any parent vtable chunk that does not contain a method we overrode (or introduced)
10309     // For the rest, we need to allocate space
10310     for (DWORD i = 0; i < dwVirtuals; i++)
10311     {
10312         if (ChangesImplementationOfVirtualSlot(static_cast<SLOT_INDEX>(i)))
10313         {
10314             DWORD chunkStart = MethodTable::GetStartSlotForVtableIndirection(MethodTable::GetIndexOfVtableIndirection(i), dwVirtuals);
10315             DWORD chunkEnd = MethodTable::GetEndSlotForVtableIndirection(MethodTable::GetIndexOfVtableIndirection(i), dwVirtuals);
10316
10317             cbTotalSize += S_SIZE_T(chunkEnd - chunkStart) * S_SIZE_T(sizeof(PCODE));
10318
10319             i = chunkEnd - 1;
10320         }
10321     }
10322
10323     // Add space for the non-virtual slots array (pointed to by an optional member) if required
10324     // If there is only one non-virtual slot, we store it directly in the optional member and need no array
10325     S_SIZE_T offsetOfNonVirtualSlots = cbTotalSize;
10326     if (dwNonVirtualSlots > 1)
10327     {
10328         cbTotalSize += S_SIZE_T(dwNonVirtualSlots) * S_SIZE_T(sizeof(PCODE));
10329     }
10330
10331     BYTE *pData = (BYTE *)pamTracker->Track(pAllocator->GetHighFrequencyHeap()->AllocMem(cbTotalSize));
10332
10333     _ASSERTE(IS_ALIGNED(pData, TARGET_POINTER_SIZE));
10334
10335     // There should be no overflows if we have allocated the memory successfully
10336     _ASSERTE(!cbTotalSize.IsOverflow());
10337
10338     MethodTable* pMT = (MethodTable*)(pData + dwGCSize);
10339
10340     pMT->SetMultipurposeSlotsMask(dwMultipurposeSlotsMask);
10341
10342     MethodTableWriteableData * pMTWriteableData = (MethodTableWriteableData *) (BYTE *)
10343         pamTracker->Track(pAllocator->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(MethodTableWriteableData))));
10344     // Note: Memory allocated on loader heap is zero filled
10345     pMT->SetWriteableData(pMTWriteableData);
10346
10347     // This also disables IBC logging until the type is sufficiently initialized so
10348     // it needs to be done early
10349     pMTWriteableData->SetIsNotFullyLoadedForBuildMethodTable();
10350
10351 #ifdef _DEBUG
10352     pClassLoader->m_dwGCSize += dwGCSize;
10353     pClassLoader->m_dwInterfaceMapSize += (dwNumInterfaces * sizeof(InterfaceInfo_t));
10354     pClassLoader->m_dwMethodTableSize += (DWORD)cbTotalSize.Value();
10355     pClassLoader->m_dwVtableData += (dwVtableSlots * sizeof(PCODE));
10356 #endif // _DEBUG
10357
10358     // There should be no overflows if we have allocated the memory successfully
10359     _ASSERTE(!offsetOfUnsharedVtableChunks.IsOverflow());
10360     _ASSERTE(!offsetOfNonVirtualSlots.IsOverflow());
10361     _ASSERTE(!offsetOfInterfaceMap.IsOverflow());
10362     _ASSERTE(!offsetOfInstAndDict.IsOverflow());
10363
10364     // initialize the total number of slots
10365     pMT->SetNumVirtuals(static_cast<WORD>(dwVirtuals));
10366     if (fHasVirtualStaticMethods)
10367     {
10368         pMT->SetHasVirtualStaticMethods();
10369     }
10370
10371     pMT->SetParentMethodTable(pMTParent);
10372
10373     // Fill out the vtable indirection slots
10374     SIZE_T dwCurrentUnsharedSlotOffset = offsetOfUnsharedVtableChunks.Value();
10375     MethodTable::VtableIndirectionSlotIterator it = pMT->IterateVtableIndirectionSlots();
10376     while (it.Next())
10377     {
10378         BOOL shared = TRUE;
10379
10380         // Recalculate whether we will share this chunk
10381         for (DWORD i = it.GetStartSlot(); i < it.GetEndSlot(); i++)
10382         {
10383             if (ChangesImplementationOfVirtualSlot(static_cast<SLOT_INDEX>(i)))
10384             {
10385                 shared = FALSE;
10386                 break;
10387             }
10388         }
10389
10390         if (shared)
10391         {
10392             // Share the parent chunk
10393             _ASSERTE(it.GetEndSlot() <= pMTParent->GetNumVirtuals());
10394             it.SetIndirectionSlot(pMTParent->GetVtableIndirections()[it.GetIndex()]);
10395         }
10396         else
10397         {
10398             // Use the locally allocated chunk
10399             it.SetIndirectionSlot((MethodTable::VTableIndir2_t *)(pData+dwCurrentUnsharedSlotOffset));
10400             dwCurrentUnsharedSlotOffset += it.GetSize();
10401         }
10402     }
10403
10404 #ifdef FEATURE_COMINTEROP
10405     // Extensible RCW's are prefixed with the count of dynamic interfaces.
10406     if (fHasDynamicInterfaceMap)
10407     {
10408         _ASSERTE (dwNumInterfaces > 0);
10409         pMT->SetInterfaceMap ((WORD) (dwNumInterfaces), (InterfaceInfo_t*)(pData+offsetOfInterfaceMap.Value()+sizeof(DWORD_PTR)));
10410
10411         *(((DWORD_PTR *)pMT->GetInterfaceMap()) - 1) = 0;
10412     }
10413     else
10414 #endif // FEATURE_COMINTEROP
10415     {
10416         // interface map is at the end of the vtable
10417         pMT->SetInterfaceMap ((WORD) dwNumInterfaces, (InterfaceInfo_t *)(pData+offsetOfInterfaceMap.Value()));
10418     }
10419
10420     _ASSERTE(((WORD) dwNumInterfaces) == dwNumInterfaces);
10421
10422     if (fDynamicStatics)
10423     {
10424         pMT->SetDynamicStatics(fHasGenericsStaticsInfo);
10425     }
10426
10427     if (dwNonVirtualSlots > 0)
10428     {
10429         if (dwNonVirtualSlots > 1)
10430         {
10431             pMT->SetNonVirtualSlotsArray((PTR_PCODE)(pData+offsetOfNonVirtualSlots.Value()));
10432         }
10433         else
10434         {
10435             pMT->SetHasSingleNonVirtualSlot();
10436         }
10437     }
10438
10439     // the dictionary pointers follow the interface map
10440     if (dwNumDicts)
10441     {
10442         MethodTable::PerInstInfoElem_t *pPerInstInfo = (MethodTable::PerInstInfoElem_t *)(pData + offsetOfInstAndDict.Value() + sizeof(GenericsDictInfo));
10443
10444         pMT->SetPerInstInfo ( pPerInstInfo);
10445
10446         // Fill in the dictionary for this type, if it's instantiated
10447         if (cbInstAndDict)
10448         {
10449             MethodTable::PerInstInfoElem_t *pPInstInfo = (MethodTable::PerInstInfoElem_t *)(pPerInstInfo + (dwNumDicts-1));
10450             *pPInstInfo = (Dictionary*) (pPerInstInfo + dwNumDicts);
10451         }
10452     }
10453
10454 #ifdef _DEBUG
10455     pMT->m_pWriteableData->m_dwLastVerifedGCCnt = (DWORD)-1;
10456 #endif // _DEBUG
10457
10458     RETURN(pMT);
10459 }
10460
10461
10462 //*******************************************************************************
10463 //
10464 // Used by BuildMethodTable
10465 //
10466 // Setup the method table
10467 //
10468 #ifdef _PREFAST_
10469 #pragma warning(push)
10470 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
10471 #endif // _PREFAST_
10472
10473 VOID
10474 MethodTableBuilder::SetupMethodTable2(
10475         Module * pLoaderModule)
10476 {
10477     CONTRACTL
10478     {
10479         STANDARD_VM_CHECK;
10480         PRECONDITION(CheckPointer(this));
10481         PRECONDITION(CheckPointer(bmtVT));
10482         PRECONDITION(CheckPointer(bmtInterface));
10483         PRECONDITION(CheckPointer(bmtInternal));
10484         PRECONDITION(CheckPointer(bmtProp));
10485         PRECONDITION(CheckPointer(bmtMFDescs));
10486         PRECONDITION(CheckPointer(bmtEnumFields));
10487         PRECONDITION(CheckPointer(bmtError));
10488         PRECONDITION(CheckPointer(bmtMetaData));
10489         PRECONDITION(CheckPointer(bmtParent));
10490         PRECONDITION(CheckPointer(bmtGenerics));
10491     }
10492     CONTRACTL_END;
10493
10494     DWORD i;
10495
10496 #ifdef FEATURE_COMINTEROP
10497     BOOL fHasDynamicInterfaceMap = bmtInterface->dwInterfaceMapSize > 0 &&
10498                                    bmtProp->fIsComObjectType &&
10499                                    (GetParentMethodTable() != g_pObjectClass);
10500 #endif // FEATURE_COMINTEROP
10501
10502     EEClass *pClass = GetHalfBakedClass();
10503
10504     DWORD cbDictSlotSize = 0;
10505     DWORD cbDictAllocSize = 0;
10506     if (bmtGenerics->HasInstantiation())
10507     {
10508         cbDictAllocSize = DictionaryLayout::GetDictionarySizeFromLayout(bmtGenerics->GetNumGenericArgs(), pClass->GetDictionaryLayout(), &cbDictSlotSize);
10509     }
10510
10511     DWORD dwGCSize;
10512
10513     if (bmtFP->NumGCPointerSeries > 0)
10514     {
10515         dwGCSize = (DWORD)CGCDesc::ComputeSize(bmtFP->NumGCPointerSeries);
10516     }
10517     else
10518     {
10519         dwGCSize = 0;
10520     }
10521
10522     pClass->SetNumMethods(bmtVT->cTotalSlots);
10523     pClass->SetNumNonVirtualSlots(bmtVT->cVtableSlots - bmtVT->cVirtualSlots);
10524
10525     // Now setup the method table
10526     // interface map is allocated along with the method table
10527     MethodTable *pMT = AllocateNewMT(pLoaderModule,
10528                                    bmtVT->cVtableSlots,
10529                                    bmtVT->cVirtualSlots,
10530                                    dwGCSize,
10531                                    bmtInterface->dwInterfaceMapSize,
10532                                    bmtGenerics->numDicts,
10533                                    cbDictAllocSize,
10534                                    GetParentMethodTable(),
10535                                    GetClassLoader(),
10536                                    bmtAllocator,
10537                                    IsInterface(),
10538                                    bmtProp->fDynamicStatics,
10539                                    bmtProp->fGenericsStatics,
10540                                    bmtProp->fHasVirtualStaticMethods,
10541 #ifdef FEATURE_COMINTEROP
10542                                    fHasDynamicInterfaceMap,
10543 #endif
10544                                    GetMemTracker());
10545
10546     pMT->SetClass(pClass);
10547     pClass->m_pMethodTable = pMT;
10548     m_pHalfBakedMT = pMT;
10549
10550 #ifdef _DEBUG
10551     pMT->SetDebugClassName(GetDebugClassName());
10552 #endif
10553
10554     if (IsInterface())
10555         pMT->SetIsInterface();
10556
10557     if (GetParentMethodTable() != NULL)
10558     {
10559         if (GetParentMethodTable()->HasModuleDependencies())
10560         {
10561             pMT->SetHasModuleDependencies();
10562         }
10563         else
10564         {
10565             Module * pModule = GetModule();
10566             Module * pParentModule = GetParentMethodTable()->GetModule();
10567             if (pModule != pParentModule)
10568             {
10569                 pMT->SetHasModuleDependencies();
10570             }
10571         }
10572
10573         if (GetParentMethodTable()->HasPreciseInitCctors() || !pClass->IsBeforeFieldInit())
10574         {
10575             pMT->SetHasPreciseInitCctors();
10576         }
10577     }
10578
10579     // Must be done early because various methods test HasInstantiation() and ContainsGenericVariables()
10580     if (bmtGenerics->GetNumGenericArgs() != 0)
10581     {
10582         pMT->SetHasInstantiation(bmtGenerics->fTypicalInstantiation, bmtGenerics->fSharedByGenericInstantiations);
10583
10584         if (bmtGenerics->fContainsGenericVariables)
10585             pMT->SetContainsGenericVariables();
10586     }
10587
10588     if (bmtGenerics->numDicts != 0)
10589     {
10590         if (!FitsIn<WORD>(bmtGenerics->GetNumGenericArgs()))
10591         {
10592             BuildMethodTableThrowException(IDS_CLASSLOAD_TOOMANYGENERICARGS);
10593         }
10594
10595         pMT->SetDictInfo(bmtGenerics->numDicts,
10596             static_cast<WORD>(bmtGenerics->GetNumGenericArgs()));
10597     }
10598
10599     CONSISTENCY_CHECK(pMT->GetNumGenericArgs() == bmtGenerics->GetNumGenericArgs());
10600     CONSISTENCY_CHECK(pMT->GetNumDicts() == bmtGenerics->numDicts);
10601     CONSISTENCY_CHECK(pMT->HasInstantiation() == bmtGenerics->HasInstantiation());
10602     CONSISTENCY_CHECK(pMT->HasInstantiation() == !pMT->GetInstantiation().IsEmpty());
10603
10604     pMT->SetLoaderModule(pLoaderModule);
10605     pMT->SetLoaderAllocator(bmtAllocator);
10606
10607     pMT->SetModule(GetModule());
10608
10609     pMT->SetInternalCorElementType (ELEMENT_TYPE_CLASS);
10610
10611     SetNonGCRegularStaticFieldBytes (bmtProp->dwNonGCRegularStaticFieldBytes);
10612     SetNonGCThreadStaticFieldBytes (bmtProp->dwNonGCThreadStaticFieldBytes);
10613
10614 #ifdef FEATURE_TYPEEQUIVALENCE
10615     if (bmtProp->fHasTypeEquivalence)
10616     {
10617         pMT->SetHasTypeEquivalence();
10618     }
10619 #endif //FEATURE_TYPEEQUIVALENCE
10620
10621 #ifdef FEATURE_COMINTEROP
10622     if (bmtProp->fSparse)
10623         pClass->SetSparseForCOMInterop();
10624 #endif // FEATURE_COMINTEROP
10625
10626     if (bmtVT->pCCtor != NULL)
10627     {
10628         pMT->SetHasClassConstructor();
10629         CONSISTENCY_CHECK(pMT->GetClassConstructorSlot() == bmtVT->pCCtor->GetSlotIndex());
10630     }
10631     if (bmtVT->pDefaultCtor != NULL)
10632     {
10633         pMT->SetHasDefaultConstructor();
10634         CONSISTENCY_CHECK(pMT->GetDefaultConstructorSlot() == bmtVT->pDefaultCtor->GetSlotIndex());
10635     }
10636
10637     for (MethodDescChunk *pChunk = GetHalfBakedClass()->GetChunks(); pChunk != NULL; pChunk = pChunk->GetNextChunk())
10638     {
10639         pChunk->SetMethodTable(pMT);
10640     }
10641
10642 #ifdef _DEBUG
10643     {
10644         DeclaredMethodIterator it(*this);
10645         while (it.Next())
10646         {
10647             MethodDesc *pMD = it->GetMethodDesc();
10648             if (pMD != NULL)
10649             {
10650                 pMD->m_pDebugMethodTable = pMT;
10651                 pMD->m_pszDebugMethodSignature = FormatSig(pMD, GetLoaderAllocator()->GetLowFrequencyHeap(), GetMemTracker());
10652             }
10653             MethodDesc *pUnboxedMD = it->GetUnboxedMethodDesc();
10654             if (pUnboxedMD != NULL)
10655             {
10656                 pUnboxedMD->m_pDebugMethodTable = pMT;
10657                 pUnboxedMD->m_pszDebugMethodSignature = FormatSig(pUnboxedMD, GetLoaderAllocator()->GetLowFrequencyHeap(), GetMemTracker());
10658             }
10659         }
10660     }
10661 #endif // _DEBUG
10662
10663     // Note that for value classes, the following calculation is only appropriate
10664     // when the instance is in its "boxed" state.
10665     if (!IsInterface())
10666     {
10667         DWORD baseSize = Max<DWORD>(bmtFP->NumInstanceFieldBytes + OBJECT_BASESIZE, MIN_OBJECT_SIZE);
10668         baseSize = (baseSize + ALLOC_ALIGN_CONSTANT) & ~ALLOC_ALIGN_CONSTANT;  // m_BaseSize must be aligned
10669         pMT->SetBaseSize(baseSize);
10670
10671         GetHalfBakedClass()->SetBaseSizePadding(baseSize - bmtFP->NumInstanceFieldBytes);
10672
10673         if (bmtProp->fIsComObjectType)
10674         {   // Propagate the com specific info
10675             pMT->SetComObjectType();
10676 #ifdef FEATURE_COMINTEROP
10677             // COM objects need an optional field on the EEClass, so ensure this class instance has allocated
10678             // the optional field descriptor.
10679             EnsureOptionalFieldsAreAllocated(pClass, m_pAllocMemTracker, GetLoaderAllocator()->GetLowFrequencyHeap());
10680 #endif // FEATURE_COMINTEROP
10681         }
10682     }
10683     else
10684     {
10685 #ifdef FEATURE_COMINTEROP
10686         // If this is an interface then we need to set the ComInterfaceType to
10687         // -1 to indicate we have not yet determined the interface type.
10688         pClass->SetComInterfaceType((CorIfaceAttr)-1);
10689
10690         // If this is a special COM event interface, then mark the MT as such.
10691         if (bmtProp->fComEventItfType)
10692         {
10693             pClass->SetComEventItfType();
10694         }
10695 #endif // FEATURE_COMINTEROP
10696     }
10697     _ASSERTE((pMT->IsInterface() == 0) == (IsInterface() == 0));
10698
10699     FieldDesc *pFieldDescList = pClass->GetFieldDescList();
10700     // Set all field slots to point to the newly created MethodTable
10701     for (i = 0; i < (bmtEnumFields->dwNumStaticFields + bmtEnumFields->dwNumInstanceFields); i++)
10702     {
10703         pFieldDescList[i].m_pMTOfEnclosingClass = pMT;
10704     }
10705
10706     // Fill in type parameters before looking up exact parent or fetching the types of any field descriptors!
10707     // This must come before the use of GetFieldType in the value class representation optimization below.
10708     if (bmtGenerics->GetNumGenericArgs() != 0)
10709     {
10710         // Space has already been allocated for the instantiation but the parameters haven't been filled in
10711         Instantiation destInst = pMT->GetInstantiation();
10712         Instantiation inst = bmtGenerics->GetInstantiation();
10713
10714         // So fill them in...
10715         TypeHandle * pInstDest = (TypeHandle *)destInst.GetRawArgs();
10716         for (DWORD j = 0; j < bmtGenerics->GetNumGenericArgs(); j++)
10717         {
10718             pInstDest[j] = inst[j];
10719         }
10720
10721         PTR_DictionaryLayout pLayout = pClass->GetDictionaryLayout();
10722         if (pLayout != NULL)
10723         {
10724             _ASSERTE(pLayout->GetMaxSlots() > 0);
10725
10726             PTR_Dictionary pDictionarySlots = pMT->GetPerInstInfo()[bmtGenerics->numDicts - 1];
10727             DWORD* pSizeSlot = (DWORD*)(pDictionarySlots + bmtGenerics->GetNumGenericArgs());
10728             *pSizeSlot = cbDictSlotSize;
10729         }
10730     }
10731
10732     CorElementType normalizedType = ELEMENT_TYPE_CLASS;
10733     if (IsValueClass())
10734     {
10735         if (IsEnum())
10736         {
10737             if (GetNumInstanceFields() != 1 ||
10738                 !CorTypeInfo::IsPrimitiveType(pFieldDescList[0].GetFieldType()))
10739             {
10740                 BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil);
10741             }
10742             CONSISTENCY_CHECK(!pFieldDescList[0].IsStatic());
10743             normalizedType = pFieldDescList->GetFieldType();
10744         }
10745         else
10746         {
10747             normalizedType = ELEMENT_TYPE_VALUETYPE;
10748         }
10749     }
10750     pMT->SetInternalCorElementType(normalizedType);
10751
10752     if (bmtProp->fIsIntrinsicType)
10753     {
10754         pMT->SetIsIntrinsicType();
10755     }
10756
10757     if (GetModule()->IsSystem())
10758     {
10759         CheckForSystemTypes();
10760     }
10761
10762     // Now fill in the real interface map with the approximate interfaces
10763     if (bmtInterface->dwInterfaceMapSize > 0)
10764     {
10765         // First ensure we have enough space to record extra flag information for each interface (we don't
10766         // record this directly into each interface map entry since these flags don't pack well due to
10767         // alignment).
10768         PVOID pExtraInterfaceInfo = NULL;
10769         SIZE_T cbExtraInterfaceInfo = MethodTable::GetExtraInterfaceInfoSize(bmtInterface->dwInterfaceMapSize);
10770         if (cbExtraInterfaceInfo)
10771             pExtraInterfaceInfo = GetMemTracker()->Track(GetLoaderAllocator()->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(cbExtraInterfaceInfo)));
10772
10773         // Call this even in the case where pExtraInterfaceInfo == NULL (certain cases are optimized and don't
10774         // require extra buffer space).
10775         pMT->InitializeExtraInterfaceInfo(pExtraInterfaceInfo);
10776
10777         InterfaceInfo_t *pInterfaces = pMT->GetInterfaceMap();
10778
10779         CONSISTENCY_CHECK(CheckPointer(pInterfaces));
10780
10781         // Copy the interface map member by member so there is no junk in the padding.
10782         for (i = 0; i < bmtInterface->dwInterfaceMapSize; i++)
10783         {
10784             bmtInterfaceEntry * pEntry = &bmtInterface->pInterfaceMap[i];
10785
10786             if (pEntry->IsDeclaredOnType())
10787                 pMT->SetInterfaceDeclaredOnClass(i);
10788             _ASSERTE(!!pEntry->IsDeclaredOnType() == !!pMT->IsInterfaceDeclaredOnClass(i));
10789
10790             pInterfaces[i].SetMethodTable(pEntry->GetInterfaceType()->GetMethodTable());
10791         }
10792     }
10793
10794     pMT->SetCl(GetCl());
10795
10796     // The type is sufficiently initialized for most general purpose accessor methods to work.
10797     // Mark the type as restored to avoid avoid asserts. Note that this also enables IBC logging.
10798     pMT->GetWriteableDataForWrite()->SetIsRestoredForBuildMethodTable();
10799
10800 #ifdef _DEBUG
10801     // Store status if we tried to inject duplicate interfaces
10802     if (bmtInterface->dbg_fShouldInjectInterfaceDuplicates)
10803         pMT->Debug_SetHasInjectedInterfaceDuplicates();
10804 #endif //_DEBUG
10805
10806     // Keep bmtInterface data around since we no longer write the flags (IsDeclaredOnType and
10807     // IsImplementedByParent) into the interface map (these flags are only required during type loading).
10808
10809     {
10810         for (MethodDescChunk *pChunk = GetHalfBakedClass()->GetChunks(); pChunk != NULL; pChunk = pChunk->GetNextChunk())
10811         {
10812             // Make sure that temporary entrypoints are create for methods. NGEN uses temporary
10813             // entrypoints as surrogate keys for precodes.
10814             pChunk->EnsureTemporaryEntryPointsCreated(GetLoaderAllocator(), GetMemTracker());
10815         }
10816     }
10817
10818     {   // copy onto the real vtable (methods only)
10819         //@GENERICS: Because we sometimes load an inexact parent (see ClassLoader::GetParent) the inherited slots might
10820         // come from the wrong place and need fixing up once we know the exact parent
10821
10822         for (bmtVtable::Iterator slotIt = bmtVT->IterateSlots(); !slotIt.AtEnd(); ++slotIt)
10823         {
10824             SLOT_INDEX iCurSlot = static_cast<SLOT_INDEX>(slotIt.CurrentIndex());
10825
10826             // We want the unboxed MethodDesc if we're out of the virtual method range
10827             // and the method we're dealing with has an unboxing method. If so, then
10828             // the unboxing method was placed in the virtual section of the vtable and
10829             // we now need to place the unboxed version.
10830             MethodDesc * pMD = NULL;
10831             if (iCurSlot < bmtVT->cVirtualSlots || !slotIt->Impl().AsMDMethod()->IsUnboxing())
10832             {
10833                 pMD = slotIt->Impl().GetMethodDesc();
10834                 CONSISTENCY_CHECK(slotIt->Decl().GetSlotIndex() == iCurSlot);
10835             }
10836             else
10837             {
10838                 pMD = slotIt->Impl().AsMDMethod()->GetUnboxedMethodDesc();
10839                 CONSISTENCY_CHECK(pMD->GetSlot() == iCurSlot);
10840             }
10841
10842             CONSISTENCY_CHECK(CheckPointer(pMD));
10843
10844             if (pMD->GetMethodTable() != pMT)
10845             {
10846                 //
10847                 // Inherited slots
10848                 //
10849                 // Do not write into vtable chunks shared with parent. It would introduce race
10850                 // with code:MethodDesc::SetStableEntryPointInterlocked.
10851                 //
10852                 DWORD indirectionIndex = MethodTable::GetIndexOfVtableIndirection(iCurSlot);
10853                 if (GetParentMethodTable()->GetVtableIndirections()[indirectionIndex] != pMT->GetVtableIndirections()[indirectionIndex])
10854                     pMT->SetSlot(iCurSlot, pMD->GetInitialEntryPointForCopiedSlot());
10855             }
10856             else
10857             {
10858                 //
10859                 // Owned slots
10860                 //
10861                 _ASSERTE(iCurSlot >= bmtVT->cVirtualSlots || ChangesImplementationOfVirtualSlot(iCurSlot));
10862
10863                 PCODE addr = pMD->GetTemporaryEntryPoint();
10864                 _ASSERTE(addr != NULL);
10865
10866                 if (pMD->HasNonVtableSlot())
10867                 {
10868                     *((PCODE *)pMD->GetAddrOfSlot()) = addr;
10869                 }
10870                 else
10871                 {
10872                     pMT->SetSlot(iCurSlot, addr);
10873                 }
10874
10875                 if (pMD->GetSlot() == iCurSlot && pMD->RequiresStableEntryPoint())
10876                 {
10877                     // The rest of the system assumes that certain methods always have stable entrypoints.
10878                     // Create them now.
10879                     pMD->GetOrCreatePrecode();
10880                 }
10881             }
10882         }
10883     }
10884
10885     // If we have any entries, then finalize them and allocate the object in class loader heap
10886     DispatchMap                 *pDispatchMap        = NULL;
10887     DispatchMapBuilder          *pDispatchMapBuilder = bmtVT->pDispatchMapBuilder;
10888     CONSISTENCY_CHECK(CheckPointer(pDispatchMapBuilder));
10889
10890     if (pDispatchMapBuilder->Count() > 0)
10891     {
10892         // Create a map in stacking memory.
10893         BYTE * pbMap;
10894         UINT32 cbMap;
10895         DispatchMap::CreateEncodedMapping(
10896             pMT,
10897             pDispatchMapBuilder,
10898             pDispatchMapBuilder->GetAllocator(),
10899             &pbMap,
10900             &cbMap);
10901
10902         // Now finalize the impltable and allocate the block in the low frequency loader heap
10903         size_t objSize = (size_t) DispatchMap::GetObjectSize(cbMap);
10904         void * pv = AllocateFromLowFrequencyHeap(S_SIZE_T(objSize));
10905         _ASSERTE(pv != NULL);
10906
10907         // Use placement new
10908         pDispatchMap = new (pv) DispatchMap(pbMap, cbMap);
10909         pMT->SetDispatchMap(pDispatchMap);
10910
10911 #ifdef LOGGING
10912         g_sdStats.m_cDispatchMap++;
10913         g_sdStats.m_cbDispatchMap += (UINT32) objSize;
10914         LOG((LF_LOADER, LL_INFO1000, "SD: Dispatch map for %s: %d bytes for map, %d bytes total for object.\n",
10915             pMT->GetDebugClassName(), cbMap, objSize));
10916 #endif // LOGGING
10917
10918     }
10919
10920     // GetMethodData by default will cache its result. However, in the case that we're
10921     // building a MethodTable, we aren't guaranteed that this type is going to successfully
10922     // load and so caching it would result in errors down the road since the memory and
10923     // type occupying the same memory location would very likely be incorrect. The second
10924     // argument specifies that GetMethodData should not cache the returned object.
10925     MethodTable::MethodDataWrapper hMTData(MethodTable::GetMethodData(pMT, FALSE));
10926
10927     if (!IsInterface())
10928     {
10929         // Propagate inheritance.
10930
10931         // NOTE: In the world of unfolded interface this was used to propagate overrides into
10932         //       the unfolded interface vtables to make sure that overrides of virtual methods
10933         //       also overrode the interface methods that they contributed to. This had the
10934         //       unfortunate side-effect of also overwriting regular vtable slots that had been
10935         //       methodimpl'd and as a result changed the meaning of methodimpl from "substitute
10936         //       the body of method A with the body of method B" to "unify the slots of methods
10937         //       A and B". But now compilers have come to rely on this side-effect and it can
10938         //       not be brought back to its originally intended behaviour.
10939
10940         // For every slot whose body comes from another slot (determined by getting the MethodDesc
10941         // for a slot and seeing if MethodDesc::GetSlot returns a different value than the slot
10942         // from which the MethodDesc was recovered), copy the value of the slot stated by the
10943         // MethodDesc over top of the current slot.
10944
10945         // Because of the way slot unification works, we need to iterate the enture vtable until
10946         // no slots need updated. To understand this, imagine the following:
10947         //      C1::M1 is overridden by C2::M2
10948         //      C1::M2 is methodImpled by C1::M3
10949         //      C1::M3 is overridden by C2::M3
10950         // This should mean that C1::M1 is implemented by C2::M3, but if we didn't run the below
10951         // for loop a second time, this would not be propagated properly - it would only be placed
10952         // into the slot for C1::M2 and never make its way up to C1::M1.
10953
10954         BOOL fChangeMade;
10955         do
10956         {
10957             fChangeMade = FALSE;
10958             for (i = 0; i < pMT->GetNumVirtuals(); i++)
10959             {
10960                 MethodDesc* pMD = hMTData->GetImplMethodDesc(i);
10961
10962                 CONSISTENCY_CHECK(CheckPointer(pMD));
10963                 CONSISTENCY_CHECK(pMD == pMT->GetMethodDescForSlot(i));
10964
10965                 // This indicates that the method body in this slot was copied here through a methodImpl.
10966                 // Thus, copy the value of the slot from which the body originally came, in case it was
10967                 // overridden, to make sure the two slots stay in sync.
10968                 DWORD originalIndex = pMD->GetSlot();
10969                 if (originalIndex != i)
10970                 {
10971                     MethodDesc *pOriginalMD = hMTData->GetImplMethodDesc(originalIndex);
10972                     CONSISTENCY_CHECK(CheckPointer(pOriginalMD));
10973                     CONSISTENCY_CHECK(pOriginalMD == pMT->GetMethodDescForSlot(originalIndex));
10974                     if (pMD != pOriginalMD)
10975                     {
10976                         // Copy the slot value in the method's original slot.
10977                         pMT->SetSlot(i, pOriginalMD->GetInitialEntryPointForCopiedSlot());
10978                         hMTData->InvalidateCachedVirtualSlot(i);
10979
10980                         // Update the pMD to the new method desc we just copied over ourselves with. This will
10981                         // be used in the check for missing method block below.
10982                         pMD = pOriginalMD;
10983
10984                         // This method is now duplicate
10985                         pMD->SetDuplicate();
10986                         INDEBUG(g_dupMethods++;)
10987                         fChangeMade = TRUE;
10988                     }
10989                 }
10990             }
10991         }
10992         while (fChangeMade);
10993     }
10994
10995     if (!bmtProp->fNoSanityChecks)
10996         VerifyVirtualMethodsImplemented(hMTData);
10997
10998 #ifdef _DEBUG
10999     {
11000         for (bmtVtable::Iterator i = bmtVT->IterateSlots();
11001              !i.AtEnd(); ++i)
11002         {
11003             _ASSERTE(i->Impl().GetMethodDesc() != NULL);
11004         }
11005     }
11006 #endif // _DEBUG
11007
11008
11009 #ifdef FEATURE_COMINTEROP
11010     // for ComObject types, i.e. if the class extends from a COM Imported
11011     // class
11012     // make sure any interface implemented by the COM Imported class
11013     // is overridden fully, (OR) not overridden at all..
11014     if (bmtProp->fIsComObjectType)
11015     {
11016         MethodTable::InterfaceMapIterator intIt = pMT->IterateInterfaceMap();
11017         while (intIt.Next())
11018         {
11019             MethodTable* pIntfMT = intIt.GetInterface(pMT, pMT->GetLoadLevel());
11020             if (pIntfMT->GetNumVirtuals() != 0)
11021             {
11022                 BOOL hasComImportMethod = FALSE;
11023                 BOOL hasManagedMethod = FALSE;
11024
11025                 // NOTE: Avoid caching the MethodData object for the type being built.
11026                 MethodTable::MethodDataWrapper hItfImplData(MethodTable::GetMethodData(pIntfMT, pMT, FALSE));
11027                 MethodTable::MethodIterator it(hItfImplData);
11028                 for (;it.IsValid(); it.Next())
11029                 {
11030                     MethodDesc *pClsMD = NULL;
11031                     // If we fail to find an _IMPLEMENTATION_ for the interface MD, then
11032                     // we are a ComImportMethod, otherwise we still be a ComImportMethod or
11033                     // we can be a ManagedMethod.
11034                     DispatchSlot impl(it.GetTarget());
11035                     if (!impl.IsNull())
11036                     {
11037                         pClsMD = it.GetMethodDesc();
11038
11039                         CONSISTENCY_CHECK(!pClsMD->IsInterface());
11040                         if (pClsMD->GetClass()->IsComImport())
11041                         {
11042                             hasComImportMethod = TRUE;
11043                         }
11044                         else
11045                         {
11046                             hasManagedMethod = TRUE;
11047                         }
11048                     }
11049                     else
11050                     {
11051                         // Need to set the pClsMD for the error reporting below.
11052                         pClsMD = it.GetDeclMethodDesc();
11053                         CONSISTENCY_CHECK(CheckPointer(pClsMD));
11054                         hasComImportMethod = TRUE;
11055                     }
11056
11057                     // One and only one of the two must be set.
11058                     if ((hasComImportMethod && hasManagedMethod) ||
11059                         (!hasComImportMethod && !hasManagedMethod))
11060                     {
11061                         BuildMethodTableThrowException(IDS_EE_BAD_COMEXTENDS_CLASS, pClsMD->GetNameOnNonArrayClass());
11062                     }
11063                 }
11064             }
11065         }
11066     }
11067
11068     // For COM event interfaces, we need to make sure that all the methods are
11069     // methods to add or remove events. This means that they all need to take
11070     // a delegate derived class and have a void return type.
11071     if (bmtProp->fComEventItfType)
11072     {
11073         // COM event interfaces had better be interfaces.
11074         CONSISTENCY_CHECK(IsInterface());
11075
11076         // Go through all the methods and check the validity of the signature.
11077         // NOTE: Uses hMTData to avoid caching a MethodData object for the type being built.
11078         MethodTable::MethodIterator it(hMTData);
11079         for (;it.IsValid(); it.Next())
11080         {
11081             MethodDesc* pMD = it.GetMethodDesc();
11082             _ASSERTE(pMD);
11083
11084             MetaSig Sig(pMD);
11085
11086             {
11087                 CONTRACT_VIOLATION(LoadsTypeViolation);
11088                 if (Sig.GetReturnType() != ELEMENT_TYPE_VOID ||
11089                     Sig.NumFixedArgs() != 1 ||
11090                     Sig.NextArg() != ELEMENT_TYPE_CLASS ||
11091                     !Sig.GetLastTypeHandleThrowing().CanCastTo(TypeHandle(g_pDelegateClass)))
11092                 {
11093                     BuildMethodTableThrowException(IDS_EE_BAD_COMEVENTITF_CLASS, pMD->GetNameOnNonArrayClass());
11094                 }
11095             }
11096         }
11097     }
11098 #endif // FEATURE_COMINTEROP
11099
11100     // If this class uses any VTS (Version Tolerant Serialization) features
11101     // (event callbacks or OptionalField attributes) we've previously cached the
11102     // additional information in the bmtMFDescs structure. Now it's time to add
11103     // this information as an optional extension to the MethodTable.
11104 }
11105 #ifdef _PREFAST_
11106 #pragma warning(pop)
11107 #endif
11108
11109 // Returns true if there is at least one default implementation for this interface method
11110 // We don't care about conflicts at this stage in order to avoid impact type load performance
11111 BOOL MethodTableBuilder::HasDefaultInterfaceImplementation(bmtRTType *pDeclType, MethodDesc *pDeclMD)
11112 {
11113     STANDARD_VM_CONTRACT;
11114
11115 #ifdef FEATURE_DEFAULT_INTERFACES
11116     // If the interface method is already non-abstract, we are done
11117     if (!pDeclMD->IsAbstract())
11118         return TRUE;
11119
11120     // If the method is an abstract MethodImpl, this is a reabstraction:
11121     //
11122     // interface IFoo { void Frob() { } }
11123     // interface IBar : IFoo { abstract void IFoo.Frob() }
11124     //
11125     // We don't require these to have an implementation because they're final anyway.
11126     if (pDeclMD->IsMethodImpl())
11127     {
11128         assert(pDeclMD->IsFinal());
11129         return TRUE;
11130     }
11131
11132     int targetSlot = pDeclMD->GetSlot();
11133
11134     // Iterate over all the interfaces this type implements
11135     bmtInterfaceEntry * pItfEntry = NULL;
11136     for (DWORD i = 0; i < bmtInterface->dwInterfaceMapSize; i++)
11137     {
11138         bmtRTType * pCurItf = bmtInterface->pInterfaceMap[i].GetInterfaceType();
11139
11140         Module * pCurIntfModule = pCurItf->GetMethodTable()->GetModule();
11141
11142         // Go over the methods on the interface
11143         MethodTable::IntroducedMethodIterator methIt(pCurItf->GetMethodTable());
11144         for (; methIt.IsValid(); methIt.Next())
11145         {
11146             MethodDesc * pPotentialImpl = methIt.GetMethodDesc();
11147
11148             // If this interface method is not a MethodImpl, it can't possibly implement
11149             // the interface method we are looking for
11150             if (!pPotentialImpl->IsMethodImpl())
11151                 continue;
11152
11153             // Go over all the decls this MethodImpl is implementing
11154             MethodImpl::Iterator it(pPotentialImpl);
11155             for (; it.IsValid(); it.Next())
11156             {
11157                 MethodDesc *pPotentialDecl = it.GetMethodDesc();
11158
11159                 // Check this is a decl with the right slot
11160                 if (pPotentialDecl->GetSlot() != targetSlot)
11161                     continue;
11162
11163                 // Find out what interface this default implementation is implementing
11164                 mdToken tkParent;
11165                 IfFailThrow(pCurIntfModule->GetMDImport()->GetParentToken(it.GetToken(), &tkParent));
11166
11167                 // We can only load the approximate interface at this point
11168                 MethodTable * pPotentialInterfaceMT = ClassLoader::LoadTypeDefOrRefOrSpecThrowing(
11169                     pCurIntfModule,
11170                     tkParent,
11171                     &bmtGenerics->typeContext,
11172                     ClassLoader::ThrowIfNotFound,
11173                     ClassLoader::PermitUninstDefOrRef,
11174                     ClassLoader::LoadTypes,
11175                     CLASS_LOAD_APPROXPARENTS,
11176                     TRUE).GetMethodTable()->GetCanonicalMethodTable();
11177
11178                 // Is this a default implementation for the interface we are looking for?
11179                 if (pDeclType->GetMethodTable()->HasSameTypeDefAs(pPotentialInterfaceMT))
11180                 {
11181                     // If the type is not generic, matching defs are all we need
11182                     if (!pDeclType->GetMethodTable()->HasInstantiation())
11183                         return TRUE;
11184
11185                     // If this is generic, we need to compare under substitutions
11186                     Substitution curItfSubs(tkParent, pCurIntfModule, &pCurItf->GetSubstitution());
11187
11188                     // Type Equivalence is not respected for this comparison as you can have multiple type equivalent interfaces on a class
11189                     TokenPairList newVisited = TokenPairList::AdjustForTypeEquivalenceForbiddenScope(NULL);
11190                     if (MetaSig::CompareTypeDefsUnderSubstitutions(
11191                         pPotentialInterfaceMT, pDeclType->GetMethodTable(),
11192                         &curItfSubs, &pDeclType->GetSubstitution(),
11193                         &newVisited))
11194                     {
11195                         return TRUE;
11196                     }
11197                 }
11198             }
11199         }
11200     }
11201 #endif // FEATURE_DEFAULT_INTERFACES
11202
11203     return FALSE;
11204 }
11205
11206 void MethodTableBuilder::VerifyVirtualMethodsImplemented(MethodTable::MethodData * hMTData)
11207 {
11208     STANDARD_VM_CONTRACT;
11209
11210     //
11211     // This verification is not applicable or required in many cases
11212     //
11213
11214     if (IsAbstract() || IsInterface())
11215         return;
11216
11217 #ifdef FEATURE_COMINTEROP
11218     if (bmtProp->fIsComObjectType)
11219         return;
11220 #endif // FEATURE_COMINTEROP
11221
11222     // Since interfaces aren't laid out in the vtable for stub dispatch, what we need to do
11223     // is try to find an implementation for every interface contract by iterating through
11224     // the interfaces not declared on a parent.
11225     BOOL fParentIsAbstract = FALSE;
11226     if (HasParent())
11227     {
11228         fParentIsAbstract = GetParentMethodTable()->IsAbstract();
11229     }
11230
11231     // If the parent is abstract, we need to check that each virtual method is implemented
11232     if (fParentIsAbstract)
11233     {
11234         // NOTE: Uses hMTData to avoid caching a MethodData object for the type being built.
11235         MethodTable::MethodIterator it(hMTData);
11236         for (; it.IsValid() && it.IsVirtual(); it.Next())
11237         {
11238             MethodDesc *pMD = it.GetMethodDesc();
11239             if (pMD->IsAbstract())
11240             {
11241                 MethodDesc *pDeclMD = it.GetDeclMethodDesc();
11242                 BuildMethodTableThrowException(IDS_CLASSLOAD_NOTIMPLEMENTED, pDeclMD->GetNameOnNonArrayClass());
11243             }
11244         }
11245     }
11246
11247     DispatchMapTypeID * rgInterfaceDispatchMapTypeIDs =
11248         new (GetStackingAllocator()) DispatchMapTypeID[bmtInterface->dwInterfaceMapSize];
11249
11250     bmtInterfaceInfo::MapIterator intIt = bmtInterface->IterateInterfaceMap();
11251     for (; !intIt.AtEnd(); intIt.Next())
11252     {
11253         if (fParentIsAbstract || !intIt->IsImplementedByParent())
11254         {
11255             // Compute all TypeIDs for this interface (all duplicates in the interface map)
11256             UINT32 cInterfaceDuplicates;
11257             ComputeDispatchMapTypeIDs(
11258                 intIt->GetInterfaceType()->GetMethodTable(),
11259                 &intIt->GetInterfaceType()->GetSubstitution(),
11260                 rgInterfaceDispatchMapTypeIDs,
11261                 bmtInterface->dwInterfaceMapSize,
11262                 &cInterfaceDuplicates);
11263             _ASSERTE(cInterfaceDuplicates <= bmtInterface->dwInterfaceMapSize);
11264             _ASSERTE(cInterfaceDuplicates > 0);
11265
11266             // NOTE: This override does not cache the resulting MethodData object.
11267             MethodTable::MethodDataWrapper hData(MethodTable::GetMethodData(
11268                 rgInterfaceDispatchMapTypeIDs,
11269                 cInterfaceDuplicates,
11270                 intIt->GetInterfaceType()->GetMethodTable(),
11271                 GetHalfBakedMethodTable()));
11272             MethodTable::MethodIterator it(hData);
11273             for (; it.IsValid() && it.IsVirtual(); it.Next())
11274             {
11275                 if (it.GetTarget().IsNull())
11276                 {
11277                     MethodDesc *pMD = it.GetDeclMethodDesc();
11278
11279                     if (!HasDefaultInterfaceImplementation(intIt->GetInterfaceType(), pMD))
11280                         BuildMethodTableThrowException(IDS_CLASSLOAD_NOTIMPLEMENTED, pMD->GetNameOnNonArrayClass());
11281                 }
11282             }
11283         }
11284     }
11285 }
11286
11287 INT32 __stdcall IsDefined(Module *pModule, mdToken token, TypeHandle attributeClass)
11288 {
11289     CONTRACTL
11290     {
11291         THROWS;
11292         GC_TRIGGERS;
11293     }
11294     CONTRACTL_END;
11295
11296     BOOL isDefined = FALSE;
11297
11298     IMDInternalImport *pInternalImport = pModule->GetMDImport();
11299     BOOL isSealed = FALSE;
11300
11301     HENUMInternalHolder hEnum(pInternalImport);
11302     TypeHandle caTH;
11303
11304     // Get the enum first but don't get any values
11305     hEnum.EnumInit(mdtCustomAttribute, token);
11306
11307     ULONG cMax = pInternalImport->EnumGetCount(&hEnum);
11308     if (cMax)
11309     {
11310         // we have something to look at
11311
11312
11313         if (!attributeClass.IsNull())
11314             isSealed = attributeClass.GetMethodTable()->IsSealed();
11315
11316         // Loop through the Attributes and look for the requested one
11317         mdCustomAttribute cv;
11318         while (pInternalImport->EnumNext(&hEnum, &cv))
11319         {
11320             //
11321             // fetch the ctor
11322             mdToken     tkCtor;
11323             IfFailThrow(pInternalImport->GetCustomAttributeProps(cv, &tkCtor));
11324
11325             mdToken tkType = TypeFromToken(tkCtor);
11326             if(tkType != mdtMemberRef && tkType != mdtMethodDef)
11327                 continue; // we only deal with the ctor case
11328
11329             //
11330             // get the info to load the type, so we can check whether the current
11331             // attribute is a subtype of the requested attribute
11332             IfFailThrow(pInternalImport->GetParentToken(tkCtor, &tkType));
11333
11334             _ASSERTE(TypeFromToken(tkType) == mdtTypeRef || TypeFromToken(tkType) == mdtTypeDef);
11335             // load the type
11336             if (isSealed)
11337             {
11338                 caTH=ClassLoader::LoadTypeDefOrRefThrowing(pModule, tkType,
11339                                                            ClassLoader::ReturnNullIfNotFound,
11340                                                            ClassLoader::FailIfUninstDefOrRef,
11341                                                            TypeFromToken(tkType) == mdtTypeDef ? tdAllTypes : tdNoTypes);
11342             }
11343             else
11344             {
11345                 caTH = ClassLoader::LoadTypeDefOrRefThrowing(pModule, tkType,
11346                                                              ClassLoader::ReturnNullIfNotFound,
11347                                                              ClassLoader::FailIfUninstDefOrRef);
11348             }
11349             if (caTH.IsNull())
11350                 continue;
11351
11352             // a null class implies all custom attribute
11353             if (!attributeClass.IsNull())
11354             {
11355                 if (isSealed)
11356                 {
11357                     if (attributeClass != caTH)
11358                         continue;
11359                 }
11360                 else
11361                 {
11362                     if (!caTH.CanCastTo(attributeClass))
11363                         continue;
11364                 }
11365             }
11366
11367             //
11368             // if we are here we got one
11369             isDefined = TRUE;
11370             break;
11371         }
11372     }
11373
11374     return isDefined;
11375 }
11376
11377 //*******************************************************************************
11378 VOID MethodTableBuilder::CheckForRemotingProxyAttrib()
11379 {
11380     STANDARD_VM_CONTRACT;
11381
11382 }
11383
11384
11385 //*******************************************************************************
11386 // Checks for a bunch of special interface names and if it matches then it sets
11387 // bmtProp->fIsMngStandardItf to TRUE. Additionally, it checks to see if the
11388 // type is an interface and if it has ComEventInterfaceAttribute custom attribute
11389 // set, then it sets bmtProp->fComEventItfType to true.
11390 //
11391 // NOTE: This only does anything when COM interop is enabled.
11392
11393 VOID MethodTableBuilder::CheckForSpecialTypes()
11394 {
11395 #ifdef FEATURE_COMINTEROP
11396     STANDARD_VM_CONTRACT;
11397
11398
11399     Module *pModule = GetModule();
11400     IMDInternalImport *pMDImport = pModule->GetMDImport();
11401
11402     // Check to see if this type is a managed standard interface. All the managed
11403     // standard interfaces live in CoreLib so checking for that first
11404     // makes the strcmp that comes afterwards acceptable.
11405     if (pModule->IsSystem())
11406     {
11407         if (IsInterface())
11408         {
11409             LPCUTF8 pszClassName;
11410             LPCUTF8 pszClassNamespace;
11411             if (FAILED(pMDImport->GetNameOfTypeDef(GetCl(), &pszClassName, &pszClassNamespace)))
11412             {
11413                 pszClassName = pszClassNamespace = NULL;
11414             }
11415             if ((pszClassName != NULL) && (pszClassNamespace != NULL))
11416             {
11417                 LPUTF8 pszFullyQualifiedName = NULL;
11418                 MAKE_FULLY_QUALIFIED_NAME(pszFullyQualifiedName, pszClassNamespace, pszClassName);
11419
11420                 // This is just to give us a scope to break out of.
11421                 do
11422                 {
11423
11424 #define MNGSTDITF_BEGIN_INTERFACE(FriendlyName, strMngItfName, strUCOMMngItfName, strCustomMarshalerName, strCustomMarshalerCookie, strManagedViewName, NativeItfIID, bCanCastOnNativeItfQI) \
11425                     if (strcmp(strMngItfName, pszFullyQualifiedName) == 0) \
11426                     { \
11427                         bmtProp->fIsMngStandardItf = true; \
11428                         break; \
11429                     }
11430
11431 #define MNGSTDITF_DEFINE_METH_IMPL(FriendlyName, ECallMethName, MethName, MethSig, FcallDecl)
11432
11433 #define MNGSTDITF_END_INTERFACE(FriendlyName)
11434
11435 #include "mngstditflist.h"
11436
11437 #undef MNGSTDITF_BEGIN_INTERFACE
11438 #undef MNGSTDITF_DEFINE_METH_IMPL
11439 #undef MNGSTDITF_END_INTERFACE
11440
11441                 } while (FALSE);
11442             }
11443         }
11444     }
11445
11446     // Check to see if the type is a COM event interface (classic COM interop only).
11447     if (IsInterface())
11448     {
11449         HRESULT hr = GetCustomAttribute(GetCl(), WellKnownAttribute::ComEventInterface, NULL, NULL);
11450         if (hr == S_OK)
11451         {
11452             bmtProp->fComEventItfType = true;
11453         }
11454     }
11455 #endif // FEATURE_COMINTEROP
11456 }
11457
11458 #ifdef FEATURE_READYTORUN
11459
11460 bool ModulesAreDistributedAsAnIndivisibleUnit(Module* module1, Module* module2)
11461 {
11462     if (module1 == module2)
11463         return true;
11464
11465     bool nativeImagesIdentical = false;
11466     if (module1->GetCompositeNativeImage() != NULL)
11467     {
11468         return module1->GetCompositeNativeImage() == module2->GetCompositeNativeImage();
11469     }
11470
11471     return false;
11472 }
11473
11474 //*******************************************************************************
11475 VOID MethodTableBuilder::CheckLayoutDependsOnOtherModules(MethodTable * pDependencyMT)
11476 {
11477     STANDARD_VM_CONTRACT;
11478
11479     // These cases are expected to be handled by the caller
11480     _ASSERTE(!(pDependencyMT == g_pObjectClass || pDependencyMT->IsTruePrimitive() || ((g_pEnumClass != NULL) && pDependencyMT->IsEnum())));
11481
11482     //
11483     // WARNING: Changes in this algorithm are potential ReadyToRun breaking changes !!!
11484     //
11485     // Track whether field layout of this type depend on information outside its containing module and compilation unit
11486     //
11487     // It is a stronger condition than MethodTable::IsInheritanceChainLayoutFixedInCurrentVersionBubble().
11488     // It has to remain fixed across versioning changes in the module dependencies. In particular, it does
11489     // not take into account NonVersionable attribute. Otherwise, adding NonVersionable attribute to existing
11490     // type would be ReadyToRun incompatible change.
11491     //
11492     bool modulesDefinedInSameDistributionUnit = ModulesAreDistributedAsAnIndivisibleUnit(pDependencyMT->GetModule(), GetModule());
11493     bool dependsOnOtherModules = !modulesDefinedInSameDistributionUnit || pDependencyMT->GetClass()->HasLayoutDependsOnOtherModules();
11494
11495     if (dependsOnOtherModules)
11496         GetHalfBakedClass()->SetHasLayoutDependsOnOtherModules();
11497 }
11498
11499 BOOL MethodTableBuilder::NeedsAlignedBaseOffset()
11500 {
11501     STANDARD_VM_CONTRACT;
11502
11503     //
11504     // WARNING: Changes in this algorithm are potential ReadyToRun breaking changes !!!
11505     //
11506     // This method returns whether the type needs aligned base offset in order to have layout resilient to
11507     // base class layout changes.
11508     //
11509     if (IsValueClass())
11510         return FALSE;
11511
11512     MethodTable * pParentMT = GetParentMethodTable();
11513
11514     // Trivial parents
11515     if (pParentMT == NULL || pParentMT == g_pObjectClass)
11516         return FALSE;
11517
11518     // Always use the ReadyToRun field layout algorithm if the source IL image was ReadyToRun, independent on
11519     // whether ReadyToRun is actually enabled for the module. It is required to allow mixing and matching
11520     // ReadyToRun images with and without input bubble enabled.
11521     if (!GetModule()->GetPEAssembly()->IsReadyToRun())
11522     {
11523         // Always use ReadyToRun field layout algorithm to produce ReadyToRun images
11524         return FALSE;
11525     }
11526
11527     if (!ModulesAreDistributedAsAnIndivisibleUnit(GetModule(), pParentMT->GetModule()) ||
11528         pParentMT->GetClass()->HasLayoutDependsOnOtherModules())
11529     {
11530         return TRUE;
11531     }
11532
11533     return FALSE;
11534 }
11535 #endif // FEATURE_READYTORUN
11536
11537 //*******************************************************************************
11538 //
11539 // Used by BuildMethodTable
11540 //
11541 // Set the HasFinalizer and HasCriticalFinalizer flags
11542 //
11543 VOID MethodTableBuilder::SetFinalizationSemantics()
11544 {
11545     STANDARD_VM_CONTRACT;
11546
11547     if (g_pObjectFinalizerMD && !IsInterface() && !IsValueClass())
11548     {
11549         WORD slot = g_pObjectFinalizerMD->GetSlot();
11550
11551         // Objects not derived from Object will get marked as having a finalizer, if they have
11552         // sufficient virtual methods.  This will only be an issue if they can be allocated
11553         // in the GC heap (which will cause all sorts of other problems).
11554         if (slot < bmtVT->cVirtualSlots && (*bmtVT)[slot].Impl().GetMethodDesc() != g_pObjectFinalizerMD)
11555         {
11556             GetHalfBakedMethodTable()->SetHasFinalizer();
11557
11558             // The need for a critical finalizer can be inherited from a parent.
11559             // Since we set this automatically for CriticalFinalizerObject
11560             // elsewhere, the code below is the means by which any derived class
11561             // picks up the attribute.
11562             if (HasParent() && GetParentMethodTable()->HasCriticalFinalizer())
11563             {
11564                 GetHalfBakedMethodTable()->SetHasCriticalFinalizer();
11565             }
11566         }
11567     }
11568 }
11569
11570 //*******************************************************************************
11571 //
11572 // Used by BuildMethodTable
11573 //
11574 // Perform relevant GC calculations for value classes
11575 //
11576 VOID MethodTableBuilder::HandleGCForValueClasses(MethodTable ** pByValueClassCache)
11577 {
11578     STANDARD_VM_CONTRACT;
11579
11580     DWORD i;
11581
11582     EEClass *pClass = GetHalfBakedClass();
11583     MethodTable *pMT = GetHalfBakedMethodTable();
11584
11585     FieldDesc *pFieldDescList = pClass->GetFieldDescList();
11586
11587     // Note that for value classes, the following calculation is only appropriate
11588     // when the instance is in its "boxed" state.
11589     if (bmtFP->NumGCPointerSeries != 0)
11590     {
11591         CGCDescSeries *pSeries;
11592         CGCDescSeries *pHighest;
11593
11594         pMT->SetContainsPointers();
11595
11596         CGCDesc::Init( (PVOID) pMT, bmtFP->NumGCPointerSeries );
11597
11598         // special case when all instance fields are objects - we can encode that as one serie.
11599         if (bmtFP->fIsAllGCPointers)
11600         {
11601             _ASSERTE(bmtFP->NumGCPointerSeries == 1);
11602
11603             CGCDescSeries* pSeries = CGCDesc::GetCGCDescFromMT(pMT)->GetHighestSeries();
11604
11605             // the data is right after the method table ptr
11606             int offsetToData = TARGET_POINTER_SIZE;
11607
11608             // Set the size as the negative of the BaseSize (the GC always adds the total
11609             // size of the object, so what you end up with is the size of the data portion of the instance)
11610             pSeries->SetSeriesSize(-(SSIZE_T)(offsetToData + TARGET_POINTER_SIZE));
11611             pSeries->SetSeriesOffset(offsetToData);
11612
11613             return;
11614         }
11615
11616         // Copy the pointer series map from the parent
11617         if (bmtParent->NumParentPointerSeries != 0)
11618         {
11619             size_t ParentGCSize = CGCDesc::ComputeSize(bmtParent->NumParentPointerSeries);
11620             memcpy( (PVOID) (((BYTE*) pMT) - ParentGCSize),
11621                     (PVOID) (((BYTE*) GetParentMethodTable()) - ParentGCSize),
11622                     ParentGCSize - sizeof(size_t)   // sizeof(size_t) is the NumSeries count
11623                   );
11624
11625         }
11626
11627         DWORD repeat = 1;
11628         if (bmtFP->NumInlineArrayElements > 1)
11629         {
11630             repeat = bmtFP->NumInlineArrayElements;
11631         }
11632
11633         // Build the pointer series map for pointers in this instance
11634         pSeries = ((CGCDesc*)pMT)->GetLowestSeries();
11635         if (bmtFP->NumInstanceGCPointerFields)
11636         {
11637             // See gcdesc.h for an explanation of why we adjust by subtracting BaseSize
11638             pSeries->SetSeriesSize((size_t)(bmtFP->NumInstanceGCPointerFields * repeat * TARGET_POINTER_SIZE) - (size_t)pMT->GetBaseSize());
11639             pSeries->SetSeriesOffset(bmtFP->GCPointerFieldStart + OBJECT_SIZE);
11640             pSeries++;
11641         }
11642
11643         // Insert GC info for fields which are by-value classes
11644         for (i = 0; i < bmtEnumFields->dwNumInstanceFields; i++)
11645         {
11646             if (pFieldDescList[i].IsByValue())
11647             {
11648                 MethodTable* pByValueMT = pByValueClassCache[i];
11649
11650                 if (pByValueMT->ContainsPointers())
11651                 {
11652                     // Offset of the by value class in the class we are building, does NOT include Object
11653                     DWORD       dwCurrentOffset = pFieldDescList[i].GetOffset();
11654                     DWORD       dwElementSize = pByValueMT->GetBaseSize() - OBJECT_BASESIZE;
11655
11656                     // if we have an inline array, we will have only one formal instance field,
11657                     // but will have to replicate the layout "repeat" times.
11658                     for (DWORD r = 0; r < repeat; r++)
11659                     {
11660                         // The by value class may have more than one pointer series
11661                         CGCDescSeries* pByValueSeries = CGCDesc::GetCGCDescFromMT(pByValueMT)->GetLowestSeries();
11662                         SIZE_T dwNumByValueSeries = CGCDesc::GetCGCDescFromMT(pByValueMT)->GetNumSeries();
11663
11664                         for (SIZE_T j = 0; j < dwNumByValueSeries; j++)
11665                         {
11666                             size_t cbSeriesSize;
11667                             size_t cbSeriesOffset;
11668
11669                             _ASSERTE(pSeries <= CGCDesc::GetCGCDescFromMT(pMT)->GetHighestSeries());
11670
11671                             cbSeriesSize = pByValueSeries->GetSeriesSize();
11672
11673                             // Add back the base size of the by value class, since it's being transplanted to this class
11674                             cbSeriesSize += pByValueMT->GetBaseSize();
11675
11676                             // Subtract the base size of the class we're building
11677                             cbSeriesSize -= pMT->GetBaseSize();
11678
11679                             // Set current series we're building
11680                             pSeries->SetSeriesSize(cbSeriesSize);
11681
11682                             // Get offset into the value class of the first pointer field (includes a +Object)
11683                             cbSeriesOffset = pByValueSeries->GetSeriesOffset();
11684
11685                             // Add element N offset
11686                             cbSeriesOffset += r * dwElementSize;
11687
11688                             // Add it to the offset of the by value class in our class
11689                             cbSeriesOffset += dwCurrentOffset;
11690
11691                             pSeries->SetSeriesOffset(cbSeriesOffset); // Offset of field
11692                             pSeries++;
11693                             pByValueSeries++;
11694                         }
11695                     }
11696                 }
11697             }
11698         }
11699
11700         // Adjust the inherited series - since the base size has increased by "# new field instance bytes", we need to
11701         // subtract that from all the series (since the series always has BaseSize subtracted for it - see gcdesc.h)
11702         pHighest = CGCDesc::GetCGCDescFromMT(pMT)->GetHighestSeries();
11703         while (pSeries <= pHighest)
11704         {
11705             CONSISTENCY_CHECK(CheckPointer(GetParentMethodTable()));
11706             pSeries->SetSeriesSize( pSeries->GetSeriesSize() - ((size_t) pMT->GetBaseSize() - (size_t) GetParentMethodTable()->GetBaseSize()) );
11707             pSeries++;
11708         }
11709
11710         _ASSERTE(pSeries-1 <= CGCDesc::GetCGCDescFromMT(pMT)->GetHighestSeries());
11711     }
11712
11713 }
11714
11715 //*******************************************************************************
11716 //
11717 // Used by BuildMethodTable
11718 //
11719 // Check for the presence of type equivalence. If present, make sure
11720 // it is permitted to be on this type.
11721 //
11722
11723 void MethodTableBuilder::CheckForTypeEquivalence(
11724     WORD                     cBuildingInterfaceList,
11725     BuildingInterfaceInfo_t *pBuildingInterfaceList)
11726 {
11727     STANDARD_VM_CONTRACT;
11728
11729 #ifdef FEATURE_TYPEEQUIVALENCE
11730     bmtProp->fIsTypeEquivalent = !!IsTypeDefEquivalent(GetCl(), GetModule());
11731
11732     if (bmtProp->fIsTypeEquivalent)
11733     {
11734         BOOL comImportOrEventInterface = IsComImport();
11735 #ifdef FEATURE_COMINTEROP
11736         comImportOrEventInterface = comImportOrEventInterface || bmtProp->fComEventItfType;
11737 #endif // FEATURE_COMINTEROP
11738
11739         BOOL fTypeEquivalentNotPermittedDueToType = !((comImportOrEventInterface && IsInterface()) || IsValueClass() || IsDelegate());
11740         BOOL fTypeEquivalentNotPermittedDueToGenerics = bmtGenerics->HasInstantiation();
11741
11742         if (fTypeEquivalentNotPermittedDueToType || fTypeEquivalentNotPermittedDueToGenerics)
11743         {
11744             BuildMethodTableThrowException(IDS_CLASSLOAD_EQUIVALENTBADTYPE);
11745         }
11746
11747         GetHalfBakedClass()->SetIsEquivalentType();
11748     }
11749
11750     bmtProp->fHasTypeEquivalence = bmtProp->fIsTypeEquivalent;
11751
11752     if (!bmtProp->fHasTypeEquivalence)
11753     {
11754         // fHasTypeEquivalence flag is inherited from interfaces so we can quickly detect
11755         // types that implement type equivalent interfaces
11756         for (WORD i = 0; i < cBuildingInterfaceList; i++)
11757         {
11758             MethodTable *pItfMT = pBuildingInterfaceList[i].m_pMethodTable;
11759             if (pItfMT->HasTypeEquivalence())
11760             {
11761                 bmtProp->fHasTypeEquivalence = true;
11762                 break;
11763             }
11764         }
11765     }
11766
11767     if (!bmtProp->fHasTypeEquivalence)
11768     {
11769         // fHasTypeEquivalence flag is "inherited" from generic arguments so we can quickly detect
11770         // types like List<Str> where Str is a structure with the TypeIdentifierAttribute.
11771         if (bmtGenerics->HasInstantiation() && !bmtGenerics->IsTypicalTypeDefinition())
11772         {
11773             Instantiation inst = bmtGenerics->GetInstantiation();
11774             for (DWORD i = 0; i < inst.GetNumArgs(); i++)
11775             {
11776                 if (inst[i].HasTypeEquivalence())
11777                 {
11778                     bmtProp->fHasTypeEquivalence = true;
11779                     break;
11780                 }
11781             }
11782         }
11783     }
11784 #endif //FEATURE_TYPEEQUIVALENCE
11785 }
11786
11787 //*******************************************************************************
11788 //
11789 // Used by BuildMethodTable
11790 //
11791 // Before we make the final leap, make sure we've allocated all memory needed to
11792 // fill out the RID maps.
11793 //
11794 VOID MethodTableBuilder::EnsureRIDMapsCanBeFilled()
11795 {
11796     STANDARD_VM_CONTRACT;
11797
11798
11799     DWORD i;
11800
11801
11802     // Rather than call Ensure***CanBeStored() hundreds of times, we
11803     // will call it once on the largest token we find. This relies
11804     // on an invariant that RidMaps don't use some kind of sparse
11805     // allocation.
11806
11807     {
11808         mdMethodDef largest = mdMethodDefNil;
11809
11810         DeclaredMethodIterator it(*this);
11811         while (it.Next())
11812         {
11813             if (it.Token() > largest)
11814             {
11815                 largest = it.Token();
11816             }
11817         }
11818         if ( largest != mdMethodDefNil )
11819         {
11820             GetModule()->EnsureMethodDefCanBeStored(largest);
11821         }
11822     }
11823
11824     {
11825         mdFieldDef largest = mdFieldDefNil;
11826
11827         for (i = 0; i < bmtMetaData->cFields; i++)
11828         {
11829             if (bmtMetaData->pFields[i] > largest)
11830             {
11831                 largest = bmtMetaData->pFields[i];
11832             }
11833         }
11834         if ( largest != mdFieldDefNil )
11835         {
11836             GetModule()->EnsureFieldDefCanBeStored(largest);
11837         }
11838     }
11839 }
11840
11841 #ifdef FEATURE_COMINTEROP
11842 //*******************************************************************************
11843 void MethodTableBuilder::GetCoClassAttribInfo()
11844 {
11845     STANDARD_VM_CONTRACT;
11846     // Retrieve the CoClassAttribute CA.
11847     HRESULT hr = GetCustomAttribute(GetCl(), WellKnownAttribute::CoClass, NULL, NULL);
11848     if (hr == S_OK)
11849     {
11850         // COM class interfaces may lazily populate the m_pCoClassForIntf field of EEClass. This field is
11851         // optional so we must ensure the optional field descriptor has been allocated.
11852         EnsureOptionalFieldsAreAllocated(GetHalfBakedClass(), m_pAllocMemTracker, GetLoaderAllocator()->GetLowFrequencyHeap());
11853         SetIsComClassInterface();
11854     }
11855 }
11856 #endif // FEATURE_COMINTEROP
11857
11858 //*******************************************************************************
11859 void MethodTableBuilder::bmtMethodImplInfo::AddMethodImpl(
11860     bmtMDMethod * pImplMethod, bmtMethodHandle declMethod, mdToken declToken,
11861     StackingAllocator * pStackingAllocator)
11862 {
11863     STANDARD_VM_CONTRACT;
11864
11865     CONSISTENCY_CHECK(CheckPointer(pImplMethod));
11866     CONSISTENCY_CHECK(!declMethod.IsNull());
11867     if (pIndex >= cMaxIndex)
11868     {
11869         DWORD newEntriesCount = 0;
11870
11871         if (!ClrSafeInt<DWORD>::multiply(cMaxIndex, 2, newEntriesCount))
11872             ThrowHR(COR_E_OVERFLOW);
11873
11874         if (newEntriesCount == 0)
11875             newEntriesCount = 10;
11876
11877         // If we have to grow this array, we will not free the old array before we clean up the BuildMethodTable operation
11878         // because this is a stacking allocator. However, the old array will get freed when all the stack allocator is freed.
11879         Entry *rgEntriesNew = new (pStackingAllocator) Entry[newEntriesCount];
11880         if (cMaxIndex > 0)
11881             memcpy((void*)rgEntriesNew, rgEntries, sizeof(Entry) * cMaxIndex);
11882
11883         // Start using newly allocated array.
11884         rgEntries = rgEntriesNew;
11885         cMaxIndex = newEntriesCount;
11886     }
11887     rgEntries[pIndex++] = Entry(pImplMethod, declMethod, declToken);
11888 }
11889
11890 //*******************************************************************************
11891 // Returns TRUE if tok acts as a body for any methodImpl entry. FALSE, otherwise.
11892 BOOL MethodTableBuilder::bmtMethodImplInfo::IsBody(mdToken tok)
11893 {
11894     LIMITED_METHOD_CONTRACT;
11895     CONSISTENCY_CHECK(TypeFromToken(tok) == mdtMethodDef);
11896     for (DWORD i = 0; i < pIndex; i++)
11897     {
11898         if (GetBodyMethodDesc(i)->GetMemberDef() == tok)
11899         {
11900             return TRUE;
11901         }
11902     }
11903     return FALSE;
11904 }
11905
11906 //*******************************************************************************
11907 BYTE *
11908 MethodTableBuilder::AllocateFromHighFrequencyHeap(S_SIZE_T cbMem)
11909 {
11910     CONTRACTL
11911     {
11912         THROWS;
11913         GC_NOTRIGGER;
11914         MODE_ANY;
11915     }
11916     CONTRACTL_END;
11917     return (BYTE *)GetMemTracker()->Track(
11918         GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem(cbMem));
11919 }
11920
11921 //*******************************************************************************
11922 BYTE *
11923 MethodTableBuilder::AllocateFromLowFrequencyHeap(S_SIZE_T cbMem)
11924 {
11925     CONTRACTL
11926     {
11927         THROWS;
11928         GC_NOTRIGGER;
11929         MODE_ANY;
11930     }
11931     CONTRACTL_END;
11932     return (BYTE *)GetMemTracker()->Track(
11933         GetLoaderAllocator()->GetLowFrequencyHeap()->AllocMem(cbMem));
11934 }
11935
11936 //-------------------------------------------------------------------------------
11937 // Make best-case effort to obtain an image name for use in an error message.
11938 //
11939 // This routine must expect to be called before the this object is fully loaded.
11940 // It can return an empty if the name isn't available or the object isn't initialized
11941 // enough to get a name, but it mustn't crash.
11942 //-------------------------------------------------------------------------------
11943 LPCWSTR MethodTableBuilder::GetPathForErrorMessages()
11944 {
11945     STANDARD_VM_CONTRACT;
11946
11947     return GetModule()->GetPathForErrorMessages();
11948 }
11949
11950 BOOL MethodTableBuilder::ChangesImplementationOfVirtualSlot(SLOT_INDEX idx)
11951 {
11952     STANDARD_VM_CONTRACT;
11953
11954     BOOL fChangesImplementation = TRUE;
11955
11956     _ASSERTE(idx < bmtVT->cVirtualSlots);
11957
11958     if (HasParent() && idx < GetParentMethodTable()->GetNumVirtuals())
11959     {
11960         _ASSERTE(idx < bmtParent->pSlotTable->GetSlotCount());
11961         bmtMethodHandle VTImpl = (*bmtVT)[idx].Impl();
11962         bmtMethodHandle ParentImpl = (*bmtParent)[idx].Impl();
11963
11964         fChangesImplementation = VTImpl != ParentImpl;
11965
11966         // See code:MethodTableBuilder::SetupMethodTable2 and its logic
11967         // for handling MethodImpl's on parent classes which affect non interface
11968         // methods.
11969         if (!fChangesImplementation && (ParentImpl.GetSlotIndex() != idx))
11970             fChangesImplementation = TRUE;
11971
11972         // If the current vtable slot is MethodImpl, is it possible that it will be updated by
11973         // the ClassLoader::PropagateCovariantReturnMethodImplSlots.
11974         if (!fChangesImplementation && VTImpl.GetMethodDesc()->IsMethodImpl())
11975         {
11976             // Note: to know exactly whether the slot will be updated or not, we would need to check the
11977             // PreserveBaseOverridesAttribute presence on the current vtable slot and in the worst case
11978             // on all of its ancestors. This is expensive, so we don't do that check here and accept
11979             // the fact that we get some false positives and end up sharing less vtable chunks.
11980
11981             // Search the previous slots in the parent vtable for the same implementation. If it exists and it was
11982             // overridden, the ClassLoader::PropagateCovariantReturnMethodImplSlots will propagate the change to the current
11983             // slot (idx), so the implementation of it will change.
11984             MethodDesc* pParentMD = ParentImpl.GetMethodDesc();
11985             for (SLOT_INDEX i = 0; i < idx; i++)
11986             {
11987                 if ((*bmtParent)[i].Impl().GetMethodDesc() == pParentMD && (*bmtVT)[i].Impl().GetMethodDesc() != pParentMD)
11988                 {
11989                     fChangesImplementation = TRUE;
11990                     break;
11991                 }
11992             }
11993         }
11994     }
11995
11996     return fChangesImplementation;
11997 }
11998
11999 // Must be called prior to setting the value of any optional field on EEClass (on a debug build an assert will
12000 // fire if this invariant is violated).
12001 void MethodTableBuilder::EnsureOptionalFieldsAreAllocated(EEClass *pClass, AllocMemTracker *pamTracker, LoaderHeap *pHeap)
12002 {
12003     STANDARD_VM_CONTRACT;
12004
12005     if (pClass->HasOptionalFields())
12006         return;
12007
12008     EEClassOptionalFields *pOptFields = (EEClassOptionalFields*)
12009         pamTracker->Track(pHeap->AllocMem(S_SIZE_T(sizeof(EEClassOptionalFields))));
12010
12011     // Initialize default values for all optional fields.
12012     pOptFields->Init();
12013
12014     // Attach optional fields to the class.
12015     pClass->AttachOptionalFields(pOptFields);
12016 }
12017
12018 //---------------------------------------------------------------------------------------
12019 //
12020 // Gather information about a generic type
12021 // - number of parameters
12022 // - variance annotations
12023 // - dictionaries
12024 // - sharability
12025 //
12026 //static
12027 void
12028 MethodTableBuilder::GatherGenericsInfo(
12029     Module *          pModule,
12030     mdTypeDef         cl,
12031     Instantiation     inst,
12032     bmtGenericsInfo * bmtGenericsInfo,
12033     StackingAllocator*pStackingAllocator)
12034 {
12035     CONTRACTL
12036     {
12037         STANDARD_VM_CHECK;
12038         PRECONDITION(GetThreadNULLOk() != NULL);
12039         PRECONDITION(CheckPointer(pModule));
12040         PRECONDITION(CheckPointer(bmtGenericsInfo));
12041     }
12042     CONTRACTL_END;
12043
12044     IMDInternalImport * pInternalImport = pModule->GetMDImport();
12045
12046     // Enumerate the formal type parameters
12047     DWORD numGenericArgs = pModule->m_pTypeGenericInfoMap->GetGenericArgumentCount(cl, pInternalImport);
12048
12049     // Work out what kind of EEClass we're creating w.r.t. generics.  If there
12050     // are no generics involved this will be a VMFLAG_NONGENERIC.
12051     BOOL fHasVariance = FALSE;
12052     if (numGenericArgs > 0)
12053     {
12054         // Generic type verification
12055         {
12056             DWORD   dwAttr;
12057             mdToken tkParent;
12058             if (FAILED(pInternalImport->GetTypeDefProps(cl, &dwAttr, &tkParent)))
12059             {
12060                 pModule->GetAssembly()->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12061             }
12062             // A generic with explicit layout is not allowed.
12063             if (IsTdExplicitLayout(dwAttr))
12064             {
12065                 pModule->GetAssembly()->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_EXPLICIT_GENERIC);
12066             }
12067         }
12068
12069         bmtGenericsInfo->numDicts = 1;
12070
12071         mdGenericParam tkTyPar;
12072         bmtGenericsInfo->pVarianceInfo = new (pStackingAllocator) BYTE[numGenericArgs];
12073
12074         // If it has generic arguments but none have been specified, then load the instantiation at the formals
12075         if (inst.IsEmpty())
12076         {
12077             bmtGenericsInfo->fTypicalInstantiation = TRUE;
12078             S_UINT32 scbAllocSize = S_UINT32(numGenericArgs) * S_UINT32(sizeof(TypeHandle));
12079             TypeHandle * genericArgs = (TypeHandle *) pStackingAllocator->Alloc(scbAllocSize);
12080
12081             inst = Instantiation(genericArgs, numGenericArgs);
12082
12083             bmtGenericsInfo->fSharedByGenericInstantiations = FALSE;
12084         }
12085         else
12086         {
12087             bmtGenericsInfo->fTypicalInstantiation = FALSE;
12088
12089             bmtGenericsInfo->fSharedByGenericInstantiations = TypeHandle::IsCanonicalSubtypeInstantiation(inst);
12090             _ASSERTE(bmtGenericsInfo->fSharedByGenericInstantiations == ClassLoader::IsSharableInstantiation(inst));
12091
12092 #ifdef _DEBUG
12093             // Set typical instantiation MethodTable
12094             {
12095                 MethodTable * pTypicalInstantiationMT = pModule->LookupTypeDef(cl).AsMethodTable();
12096                 // Typical instantiation was already loaded by code:ClassLoader::LoadApproxTypeThrowing
12097                 _ASSERTE(pTypicalInstantiationMT != NULL);
12098                 bmtGenericsInfo->dbg_pTypicalInstantiationMT = pTypicalInstantiationMT;
12099             }
12100 #endif //_DEBUG
12101         }
12102
12103         TypeHandle * pDestInst = (TypeHandle *)inst.GetRawArgs();
12104         {
12105             HENUMInternal   hEnumGenericPars;
12106             HRESULT hr = pInternalImport->EnumInit(mdtGenericParam, cl, &hEnumGenericPars);
12107             if (FAILED(hr))
12108                 pModule->GetAssembly()->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12109
12110             // Protect multi-threaded access to Module.m_GenericParamToDescMap. Other threads may be loading the same type
12111             // to break type recursion dead-locks
12112             CrstHolder ch(&pModule->GetClassLoader()->m_AvailableTypesLock);
12113
12114             for (unsigned int i = 0; i < numGenericArgs; i++)
12115             {
12116                 pInternalImport->EnumNext(&hEnumGenericPars, &tkTyPar);
12117                 DWORD flags;
12118                 if (FAILED(pInternalImport->GetGenericParamProps(tkTyPar, NULL, &flags, NULL, NULL, NULL)))
12119                 {
12120                     pModule->GetAssembly()->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12121                 }
12122
12123                 if (bmtGenericsInfo->fTypicalInstantiation)
12124                 {
12125                     // code:Module.m_GenericParamToDescMap maps generic parameter RIDs to TypeVarTypeDesc
12126                     // instances so that we do not leak by allocating them all over again, if the type
12127                     // repeatedly fails to load.
12128                     TypeVarTypeDesc* pTypeVarTypeDesc = pModule->LookupGenericParam(tkTyPar);
12129                     if (pTypeVarTypeDesc == NULL)
12130                     {
12131                         // Do NOT use the alloc tracker for this memory as we need it stay allocated even if the load fails.
12132                         void* mem = (void*)pModule->GetLoaderAllocator()->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(TypeVarTypeDesc)));
12133                         pTypeVarTypeDesc = new (mem) TypeVarTypeDesc(pModule, cl, i, tkTyPar);
12134
12135                         pModule->StoreGenericParamThrowing(tkTyPar, pTypeVarTypeDesc);
12136                     }
12137                     pDestInst[i] = TypeHandle(pTypeVarTypeDesc);
12138                 }
12139
12140                 DWORD varianceAnnotation = flags & gpVarianceMask;
12141                 bmtGenericsInfo->pVarianceInfo[i] = static_cast<BYTE>(varianceAnnotation);
12142                 if (varianceAnnotation != gpNonVariant)
12143                 {
12144                     if (varianceAnnotation != gpContravariant && varianceAnnotation != gpCovariant)
12145                     {
12146                         pModule->GetAssembly()->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADVARIANCE);
12147                     }
12148                     else
12149                     {
12150                         fHasVariance = TRUE;
12151                     }
12152                 }
12153             }
12154         }
12155
12156         if (!fHasVariance)
12157             bmtGenericsInfo->pVarianceInfo = NULL;
12158     }
12159     else
12160     {
12161         bmtGenericsInfo->fTypicalInstantiation = FALSE;
12162         bmtGenericsInfo->fSharedByGenericInstantiations = FALSE;
12163         bmtGenericsInfo->numDicts = 0;
12164     }
12165
12166     bmtGenericsInfo->fContainsGenericVariables = MethodTable::ComputeContainsGenericVariables(inst);
12167
12168     SigTypeContext typeContext(inst, Instantiation());
12169     bmtGenericsInfo->typeContext = typeContext;
12170 } // MethodTableBuilder::GatherGenericsInfo
12171
12172 //=======================================================================
12173 // This is invoked from the class loader while building the internal structures for a type
12174 // This function should check if explicit layout metadata exists.
12175 //
12176 // Returns:
12177 //  TRUE    - yes, there's layout metadata
12178 //  FALSE   - no, there's no layout.
12179 //  fail    - throws a typeload exception
12180 //
12181 // If TRUE,
12182 //   *pNLType            gets set to nltAnsi or nltUnicode
12183 //   *pPackingSize       declared packing size
12184 //   *pfExplicitoffsets  offsets explicit in metadata or computed?
12185 //=======================================================================
12186 BOOL HasLayoutMetadata(Assembly* pAssembly, IMDInternalImport* pInternalImport, mdTypeDef cl, MethodTable* pParentMT, BYTE* pPackingSize, BYTE* pNLTType, BOOL* pfExplicitOffsets)
12187 {
12188     CONTRACTL
12189     {
12190         THROWS;
12191         GC_TRIGGERS;
12192         MODE_ANY;
12193         PRECONDITION(CheckPointer(pInternalImport));
12194         PRECONDITION(CheckPointer(pPackingSize));
12195         PRECONDITION(CheckPointer(pNLTType));
12196         PRECONDITION(CheckPointer(pfExplicitOffsets));
12197     }
12198     CONTRACTL_END;
12199
12200     HRESULT hr;
12201     ULONG clFlags;
12202     if (FAILED(pInternalImport->GetTypeDefProps(cl, &clFlags, NULL)))
12203     {
12204         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12205     }
12206
12207     if (IsTdAutoLayout(clFlags))
12208     {
12209         return FALSE;
12210     }
12211     else if (IsTdSequentialLayout(clFlags))
12212     {
12213         *pfExplicitOffsets = FALSE;
12214     }
12215     else if (IsTdExplicitLayout(clFlags))
12216     {
12217         *pfExplicitOffsets = TRUE;
12218     }
12219     else
12220     {
12221         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12222     }
12223
12224     // We now know this class has seq. or explicit layout. Ensure the parent does too.
12225     if (pParentMT && !(pParentMT->IsObjectClass() || pParentMT->IsValueTypeClass()) && !(pParentMT->HasLayout()))
12226         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12227
12228     if (IsTdAnsiClass(clFlags))
12229     {
12230         *pNLTType = nltAnsi;
12231     }
12232     else if (IsTdUnicodeClass(clFlags))
12233     {
12234         *pNLTType = nltUnicode;
12235     }
12236     else if (IsTdAutoClass(clFlags))
12237     {
12238 #ifdef TARGET_WINDOWS
12239         *pNLTType = nltUnicode;
12240 #else
12241         *pNLTType = nltAnsi; // We don't have a utf8 charset in metadata yet, but ANSI == UTF-8 off-Windows
12242 #endif
12243     }
12244     else
12245     {
12246         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12247     }
12248
12249     DWORD dwPackSize;
12250     hr = pInternalImport->GetClassPackSize(cl, &dwPackSize);
12251     if (FAILED(hr) || dwPackSize == 0)
12252         dwPackSize = DEFAULT_PACKING_SIZE;
12253
12254     // This has to be reduced to a BYTE value, so we had better make sure it fits. If
12255     // not, we'll throw an exception instead of trying to munge the value to what we
12256     // think the user might want.
12257     if (!FitsInU1((UINT64)(dwPackSize)))
12258     {
12259         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12260     }
12261
12262     *pPackingSize = (BYTE)dwPackSize;
12263
12264     return TRUE;
12265 }
12266
12267 //---------------------------------------------------------------------------------------
12268 //
12269 // This service is called for normal classes -- and for the pseudo class we invent to
12270 // hold the module's public members.
12271 //
12272 //static
12273 TypeHandle
12274 ClassLoader::CreateTypeHandleForTypeDefThrowing(
12275     Module *          pModule,
12276     mdTypeDef         cl,
12277     Instantiation     inst,
12278     AllocMemTracker * pamTracker)
12279 {
12280     CONTRACT(TypeHandle)
12281     {
12282         STANDARD_VM_CHECK;
12283         PRECONDITION(GetThreadNULLOk() != NULL);
12284         PRECONDITION(CheckPointer(pModule));
12285         POSTCONDITION(!RETVAL.IsNull());
12286         POSTCONDITION(CheckPointer(RETVAL.GetMethodTable()));
12287     }
12288     CONTRACT_END;
12289
12290     MethodTable * pMT = NULL;
12291
12292     MethodTable * pParentMethodTable = NULL;
12293     SigPointer    parentInst;
12294     mdTypeDef     tdEnclosing = mdTypeDefNil;
12295     DWORD         cInterfaces;
12296     BuildingInterfaceInfo_t * pInterfaceBuildInfo = NULL;
12297     IMDInternalImport *       pInternalImport = NULL;
12298     LayoutRawFieldInfo *      pLayoutRawFieldInfos = NULL;
12299     MethodTableBuilder::bmtGenericsInfo genericsInfo;
12300
12301     Assembly * pAssembly = pModule->GetAssembly();
12302     pInternalImport = pModule->GetMDImport();
12303
12304     if (TypeFromToken(cl) != mdtTypeDef || !pInternalImport->IsValidToken(cl))
12305     {
12306         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12307     }
12308
12309     // GetCheckpoint for the thread-based allocator
12310     // This checkpoint provides a scope for all transient allocations of data structures
12311     // used during class loading.
12312     // <NICE> Ideally a debug/checked build should pass around tokens indicating the Checkpoint
12313     // being used and check these dynamically </NICE>
12314     ACQUIRE_STACKING_ALLOCATOR(pStackingAllocator);
12315
12316     // Gather up generics info
12317     MethodTableBuilder::GatherGenericsInfo(pModule, cl, inst, &genericsInfo, pStackingAllocator);
12318
12319     Module * pLoaderModule = pModule;
12320     if (!inst.IsEmpty())
12321     {
12322         pLoaderModule = ClassLoader::ComputeLoaderModuleWorker(
12323             pModule,
12324             cl,
12325             inst,
12326             Instantiation());
12327         pLoaderModule->GetLoaderAllocator()->EnsureInstantiation(pModule, inst);
12328     }
12329
12330     LoaderAllocator * pAllocator = pLoaderModule->GetLoaderAllocator();
12331
12332     {
12333         // As this is loading a parent type, we are allowed to override the load type limit.
12334         OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOAD_APPROXPARENTS);
12335         pParentMethodTable = LoadApproxParentThrowing(pModule, cl, &parentInst, &genericsInfo.typeContext);
12336     }
12337
12338     if (pParentMethodTable != NULL)
12339     {
12340         // Since methods on System.Array assume the layout of arrays, we can not allow
12341         // subclassing of arrays, it is sealed from the users point of view.
12342         // Value types and enums should be sealed - disable inheritting from them (we cannot require sealed
12343         // flag because of AppCompat)
12344         if (pParentMethodTable->IsSealed() ||
12345             (pParentMethodTable == g_pArrayClass) ||
12346             pParentMethodTable->IsValueType())
12347         {
12348             pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_SEALEDPARENT);
12349         }
12350
12351         DWORD dwTotalDicts = genericsInfo.numDicts + pParentMethodTable->GetNumDicts();
12352         if (!FitsIn<WORD>(dwTotalDicts))
12353         {
12354             pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_TOOMANYGENERICARGS);
12355         }
12356         genericsInfo.numDicts = static_cast<WORD>(dwTotalDicts);
12357     }
12358
12359     GetEnclosingClassThrowing(pInternalImport, pModule, cl, &tdEnclosing);
12360
12361     BYTE nstructPackingSize = 0, nstructNLT = 0;
12362     BOOL fExplicitOffsets = FALSE;
12363     // NOTE: HasLayoutMetadata does not load classes
12364     BOOL fHasLayout =
12365         !genericsInfo.fContainsGenericVariables &&
12366         HasLayoutMetadata(
12367             pModule->GetAssembly(),
12368             pInternalImport,
12369             cl,
12370             pParentMethodTable,
12371             &nstructPackingSize,
12372             &nstructNLT,
12373             &fExplicitOffsets);
12374
12375     BOOL fIsEnum = ((g_pEnumClass != NULL) && (pParentMethodTable == g_pEnumClass));
12376
12377     // enums may not have layout because they derive from g_pEnumClass and that has no layout
12378     // this is enforced by HasLayoutMetadata above
12379     _ASSERTE(!(fIsEnum && fHasLayout));
12380
12381     // This is a delegate class if it derives from MulticastDelegate (we do not allow single cast delegates)
12382     BOOL fIsDelegate = pParentMethodTable && pParentMethodTable == g_pMulticastDelegateClass;
12383
12384     // Create a EEClass entry for it, filling out a few fields, such as the parent class token
12385     // (and the generic type should we be creating an instantiation)
12386     EEClass * pClass = MethodTableBuilder::CreateClass(
12387         pModule,
12388         cl,
12389         fHasLayout,
12390         fIsDelegate,
12391         fIsEnum,
12392         &genericsInfo,
12393         pAllocator,
12394         pamTracker);
12395
12396     if ((pParentMethodTable != NULL) && (pParentMethodTable == g_pDelegateClass))
12397     {
12398         // Note we do not allow single cast delegates
12399         if (pModule->GetAssembly() != SystemDomain::SystemAssembly())
12400         {
12401             pAssembly->ThrowTypeLoadException(pInternalImport, cl, BFA_CANNOT_INHERIT_FROM_DELEGATE);
12402         }
12403
12404 #ifdef _DEBUG
12405         // Only MultiCastDelegate should inherit from Delegate
12406         LPCUTF8 className;
12407         LPCUTF8 nameSpace;
12408         if (FAILED(pInternalImport->GetNameOfTypeDef(cl, &className, &nameSpace)))
12409         {
12410             className = nameSpace = "Invalid TypeDef record";
12411         }
12412         BAD_FORMAT_NOTHROW_ASSERT(strcmp(className, "MulticastDelegate") == 0);
12413 #endif
12414     }
12415
12416     if (fIsDelegate)
12417     {
12418         if (!pClass->IsSealed())
12419         {
12420             pAssembly->ThrowTypeLoadException(pInternalImport, cl, BFA_DELEGATE_CLASS_NOTSEALED);
12421         }
12422
12423         pClass->SetIsDelegate();
12424     }
12425
12426     if (tdEnclosing != mdTypeDefNil)
12427     {
12428         pClass->SetIsNested();
12429         THROW_BAD_FORMAT_MAYBE(IsTdNested(pClass->GetProtection()), VLDTR_E_TD_ENCLNOTNESTED, pModule);
12430     }
12431     else if (IsTdNested(pClass->GetProtection()))
12432     {
12433         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12434     }
12435
12436     // We only permit generic interfaces and delegates to have variant type parameters
12437     if (genericsInfo.pVarianceInfo != NULL && !pClass->IsInterface() && !fIsDelegate)
12438     {
12439         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_VARIANCE_CLASS);
12440     }
12441
12442     // Now load all the interfaces
12443     HENUMInternalHolder hEnumInterfaceImpl(pInternalImport);
12444     hEnumInterfaceImpl.EnumInit(mdtInterfaceImpl, cl);
12445
12446     cInterfaces = pInternalImport->EnumGetCount(&hEnumInterfaceImpl);
12447
12448     if (cInterfaces != 0)
12449     {
12450         DWORD i;
12451
12452         // Allocate the BuildingInterfaceList table
12453         pInterfaceBuildInfo = new (pStackingAllocator) BuildingInterfaceInfo_t[cInterfaces];
12454
12455         mdInterfaceImpl ii;
12456         for (i = 0; pInternalImport->EnumNext(&hEnumInterfaceImpl, &ii); i++)
12457         {
12458             // Get properties on this interface
12459             mdTypeRef crInterface;
12460             if (FAILED(pInternalImport->GetTypeOfInterfaceImpl(ii, &crInterface)))
12461             {
12462                 pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12463             }
12464             // validate the token
12465             mdToken crIntType =
12466                 (RidFromToken(crInterface) && pInternalImport->IsValidToken(crInterface)) ?
12467                 TypeFromToken(crInterface) :
12468                 0;
12469             switch (crIntType)
12470             {
12471                 case mdtTypeDef:
12472                 case mdtTypeRef:
12473                 case mdtTypeSpec:
12474                     break;
12475                 default:
12476                     pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_INTERFACENULL);
12477             }
12478
12479             TypeHandle intType;
12480
12481             {
12482                 OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOAD_APPROXPARENTS);
12483                 intType = LoadApproxTypeThrowing(pModule, crInterface, NULL, &genericsInfo.typeContext);
12484             }
12485
12486             pInterfaceBuildInfo[i].m_pMethodTable = intType.AsMethodTable();
12487             if (pInterfaceBuildInfo[i].m_pMethodTable == NULL)
12488             {
12489                 pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_INTERFACENULL);
12490             }
12491
12492             // Ensure this is an interface
12493             if (!pInterfaceBuildInfo[i].m_pMethodTable->IsInterface())
12494             {
12495                  pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_NOTINTERFACE);
12496             }
12497
12498             // Check interface for use of variant type parameters
12499             if ((genericsInfo.pVarianceInfo != NULL) && (TypeFromToken(crInterface) == mdtTypeSpec))
12500             {
12501                 ULONG cSig;
12502                 PCCOR_SIGNATURE pSig;
12503                 if (FAILED(pInternalImport->GetTypeSpecFromToken(crInterface, &pSig, &cSig)))
12504                 {
12505                     pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12506                 }
12507                 // Interfaces behave covariantly
12508                 if (!EEClass::CheckVarianceInSig(
12509                         genericsInfo.GetNumGenericArgs(),
12510                         genericsInfo.pVarianceInfo,
12511                         pModule,
12512                         SigPointer(pSig, cSig),
12513                         gpCovariant))
12514                 {
12515                     pAssembly->ThrowTypeLoadException(
12516                         pInternalImport,
12517                         cl,
12518                         IDS_CLASSLOAD_VARIANCE_IN_INTERFACE);
12519                 }
12520             }
12521         }
12522         _ASSERTE(i == cInterfaces);
12523     }
12524
12525     if (fHasLayout ||
12526         /* Variant delegates should not have any instance fields of the variant.
12527            type parameter. For now, we just completely disallow all fields even
12528            if they are non-variant or static, as it is not a useful scenario.
12529            @TODO: A more logical place for this check would be in
12530            MethodTableBuilder::EnumerateClassMembers() */
12531         (fIsDelegate && genericsInfo.pVarianceInfo))
12532     {
12533         // check for fields and variance
12534         ULONG               cFields;
12535         HENUMInternalHolder hEnumField(pInternalImport);
12536         hEnumField.EnumInit(mdtFieldDef, cl);
12537
12538         cFields = pInternalImport->EnumGetCount(&hEnumField);
12539
12540         if ((cFields != 0) && fIsDelegate && (genericsInfo.pVarianceInfo != NULL))
12541         {
12542             pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_VARIANCE_IN_DELEGATE);
12543         }
12544
12545         if (fHasLayout)
12546         {
12547             // Though we fail on this condition, we should never run into it.
12548             CONSISTENCY_CHECK(nstructPackingSize != 0);
12549             // MD Val check: PackingSize
12550             if((nstructPackingSize == 0)  ||
12551                (nstructPackingSize > 128) ||
12552                (nstructPackingSize & (nstructPackingSize-1)))
12553             {
12554                 THROW_BAD_FORMAT_MAYBE(!"ClassLayout:Invalid PackingSize", BFA_BAD_PACKING_SIZE, pModule);
12555                 pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12556             }
12557
12558             pLayoutRawFieldInfos = (LayoutRawFieldInfo *)pStackingAllocator->Alloc(
12559                 (S_UINT32(1) + S_UINT32(cFields)) * S_UINT32(sizeof(LayoutRawFieldInfo)));
12560
12561             {
12562                 // Warning: this can load classes
12563                 CONTRACT_VIOLATION(LoadsTypeViolation);
12564
12565                 // Set a flag that allows us to break dead-locks that are result of the LoadsTypeViolation
12566                 ThreadStateNCStackHolder tsNC(TRUE, Thread::TSNC_LoadsTypeViolation);
12567
12568                 EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing(
12569                     cl,
12570                     nstructPackingSize,
12571                     nstructNLT,
12572                     fExplicitOffsets,
12573                     pParentMethodTable,
12574                     cFields,
12575                     &hEnumField,
12576                     pModule,
12577                     &genericsInfo.typeContext,
12578                     &(((LayoutEEClass *)pClass)->m_LayoutInfo),
12579                     pLayoutRawFieldInfos,
12580                     pAllocator,
12581                     pamTracker);
12582             }
12583         }
12584     }
12585
12586     // Resolve this class, given that we know now that all of its dependencies are loaded and resolved.
12587     // !!! This must be the last thing in this TRY block: if MethodTableBuilder succeeds, it has published the class
12588     // and there is no going back.
12589     MethodTableBuilder builder(
12590         NULL,
12591         pClass,
12592         pStackingAllocator,
12593         pamTracker);
12594
12595     pMT = builder.BuildMethodTableThrowing(
12596         pAllocator,
12597         pLoaderModule,
12598         pModule,
12599         cl,
12600         pInterfaceBuildInfo,
12601         pLayoutRawFieldInfos,
12602         pParentMethodTable,
12603         &genericsInfo,
12604         parentInst,
12605         (WORD)cInterfaces);
12606
12607     RETURN(TypeHandle(pMT));
12608 } // ClassLoader::CreateTypeHandleForTypeDefThrowing