47024106985eee97789c137b8d4b73c0a9d89718
[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     #else
10027                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 32; // sizeof(__m256)
10028     #endif // TARGET_ARM elif TARGET_ARM64
10029                 }
10030                 else if (strcmp(name, g_Vector512Name) == 0)
10031                 {
10032     #ifdef TARGET_ARM
10033                     // No such type exists for the Procedure Call Standard for ARM. We will default
10034                     // to the same alignment as __m128, which is supported by the ABI.
10035
10036                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 8;
10037     #elif defined(TARGET_ARM64)
10038                     // The Procedure Call Standard for ARM 64-bit (with SVE support) defaults to
10039                     // 16-byte alignment for __m256.
10040
10041                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 16;
10042     #else
10043                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 64; // sizeof(__m512)
10044     #endif // TARGET_ARM elif TARGET_ARM64
10045                 }
10046                 else
10047                 {
10048                     // These types should be handled or explicitly skipped below to ensure that we don't
10049                     // miss adding required ABI support for future types.
10050
10051                     _ASSERTE_MSG(FALSE, "Unhandled Hardware Intrinsic Type.");
10052                 }
10053
10054                 return;
10055             }
10056         }
10057
10058         if (g_pNullableClass != NULL)
10059         {
10060             _ASSERTE(g_pNullableClass->IsNullable());
10061
10062             // Pre-compute whether the class is a Nullable<T> so that code:Nullable::IsNullableType is efficient
10063             // This is useful to the performance of boxing/unboxing a Nullable
10064             if (GetCl() == g_pNullableClass->GetCl())
10065                 pMT->SetIsNullable();
10066
10067             return;
10068         }
10069     }
10070
10071     if (IsNested() || IsEnum())
10072         return;
10073
10074     if (FAILED(GetMDImport()->GetNameOfTypeDef(GetCl(), &name, &nameSpace)))
10075     {
10076         BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT);
10077     }
10078
10079     if (IsValueClass())
10080     {
10081         //
10082         // Value types
10083         //
10084
10085         // All special value types are in the system namespace
10086         if (strcmp(nameSpace, g_SystemNS) != 0)
10087             return;
10088
10089         // Check if it is a primitive type
10090         CorElementType type = CorTypeInfo::FindPrimitiveType(name);
10091         if (type != ELEMENT_TYPE_END)
10092         {
10093             pMT->SetInternalCorElementType(type);
10094             pMT->SetIsTruePrimitive();
10095
10096 #if defined(TARGET_X86) && defined(UNIX_X86_ABI)
10097             switch (type)
10098             {
10099                 // The System V ABI for i386 defines different packing for these types.
10100
10101                 case ELEMENT_TYPE_I8:
10102                 case ELEMENT_TYPE_U8:
10103                 case ELEMENT_TYPE_R8:
10104                 {
10105                     EEClassLayoutInfo * pLayout = pClass->GetLayoutInfo();
10106                     pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 4;
10107                     break;
10108                 }
10109
10110                 default:
10111                     break;
10112             }
10113 #endif // TARGET_X86 && UNIX_X86_ABI
10114
10115 #ifdef _DEBUG
10116             if (FAILED(GetMDImport()->GetNameOfTypeDef(GetCl(), &name, &nameSpace)))
10117             {
10118                 name = nameSpace = "Invalid TypeDef record";
10119             }
10120             LOG((LF_CLASSLOADER, LL_INFO10000, "%s::%s marked as primitive type %i\n", nameSpace, name, type));
10121 #endif // _DEBUG
10122         }
10123         else if (strcmp(name, g_NullableName) == 0)
10124         {
10125             pMT->SetIsNullable();
10126         }
10127         else if (strcmp(name, g_RuntimeArgumentHandleName) == 0)
10128         {
10129             pMT->SetInternalCorElementType (ELEMENT_TYPE_I);
10130         }
10131         else if (strcmp(name, g_RuntimeMethodHandleInternalName) == 0)
10132         {
10133             pMT->SetInternalCorElementType (ELEMENT_TYPE_I);
10134         }
10135         else if (strcmp(name, g_RuntimeFieldHandleInternalName) == 0)
10136         {
10137             pMT->SetInternalCorElementType (ELEMENT_TYPE_I);
10138         }
10139         else if ((strcmp(name, g_Int128Name) == 0) || (strcmp(name, g_UInt128Name) == 0))
10140         {
10141             EEClassLayoutInfo* pLayout = pClass->GetLayoutInfo();
10142             pLayout->SetIsInt128OrHasInt128Fields(TRUE);
10143 #ifdef TARGET_ARM
10144             // No such type exists for the Procedure Call Standard for ARM. We will default
10145             // to the same alignment as __m128, which is supported by the ABI.
10146
10147             pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 8;
10148 #elif defined(TARGET_64BIT) || defined(TARGET_X86)
10149
10150             // These types correspond to fundamental data types in the underlying ABIs:
10151             // * Int128:  __int128
10152             // * UInt128: unsigned __int128
10153             //
10154             // This behavior matches the ABI standard on various Unix platforms
10155             // On Windows, no standard for Int128 has been established yet,
10156             // although applying 16 byte alignment is consistent with treatment of 128 bit SSE types
10157             // even on X86
10158             pLayout->m_ManagedLargestAlignmentRequirementOfAllMembers = 16; // sizeof(__int128)
10159 #else
10160 #error Unknown architecture
10161 #endif // TARGET_64BIT
10162         }
10163     }
10164     else
10165     {
10166         //
10167         // Reference types
10168         //
10169         if (strcmp(name, g_StringName) == 0 && strcmp(nameSpace, g_SystemNS) == 0)
10170         {
10171             // Strings are not "normal" objects, so we need to mess with their method table a bit
10172             // so that the GC can figure out how big each string is...
10173             DWORD baseSize = StringObject::GetBaseSize();
10174             pMT->SetBaseSize(baseSize);
10175
10176             GetHalfBakedClass()->SetBaseSizePadding(baseSize - bmtFP->NumInstanceFieldBytes);
10177
10178             pMT->SetComponentSize(2);
10179         }
10180         else if (strcmp(name, g_CriticalFinalizerObjectName) == 0 && strcmp(nameSpace, g_ConstrainedExecutionNS) == 0)
10181         {
10182             // To introduce a class with a critical finalizer,
10183             // we'll set the bit here.
10184             pMT->SetHasCriticalFinalizer();
10185         }
10186 #ifdef FEATURE_COMINTEROP
10187         else
10188         {
10189             bool bIsComObject = false;
10190
10191             if (strcmp(name, g_ComObjectName) == 0 && strcmp(nameSpace, g_SystemNS) == 0)
10192                 bIsComObject = true;
10193
10194
10195             if (bIsComObject)
10196             {
10197                 // Make System.__ComObject a ComImport type
10198                 // We can't do it using attribute as C# won't allow putting code in ComImport types
10199                 pMT->SetComObjectType();
10200
10201                 // COM objects need an optional field on the EEClass, so ensure this class instance has allocated
10202                 // the optional field descriptor.
10203                 EnsureOptionalFieldsAreAllocated(pClass, m_pAllocMemTracker, GetLoaderAllocator()->GetLowFrequencyHeap());
10204             }
10205         }
10206 #endif // FEATURE_COMINTEROP
10207     }
10208 }
10209
10210 //==========================================================================================
10211 // Helper to create a new method table. This is the only
10212 // way to allocate a new MT. Don't try calling new / ctor.
10213 // Called from SetupMethodTable
10214 // This needs to be kept consistent with MethodTable::GetSavedExtent()
10215 MethodTable * MethodTableBuilder::AllocateNewMT(
10216     Module *pLoaderModule,
10217     DWORD dwVtableSlots,
10218     DWORD dwVirtuals,
10219     DWORD dwGCSize,
10220     DWORD dwNumInterfaces,
10221     DWORD dwNumDicts,
10222     DWORD cbInstAndDict,
10223     MethodTable *pMTParent,
10224     ClassLoader *pClassLoader,
10225     LoaderAllocator *pAllocator,
10226     BOOL isInterface,
10227     BOOL fDynamicStatics,
10228     BOOL fHasGenericsStaticsInfo,
10229     BOOL fHasVirtualStaticMethods
10230 #ifdef FEATURE_COMINTEROP
10231         , BOOL fHasDynamicInterfaceMap
10232 #endif
10233         , AllocMemTracker *pamTracker
10234     )
10235 {
10236     CONTRACT (MethodTable*)
10237     {
10238         THROWS;
10239         GC_TRIGGERS;
10240         MODE_ANY;
10241         POSTCONDITION(CheckPointer(RETVAL));
10242     }
10243     CONTRACT_END;
10244
10245     DWORD dwNonVirtualSlots = dwVtableSlots - dwVirtuals;
10246
10247     // GCSize must be aligned
10248     _ASSERTE(IS_ALIGNED(dwGCSize, sizeof(void*)));
10249
10250     // size without the interface map
10251     S_SIZE_T cbTotalSize = S_SIZE_T(dwGCSize) + S_SIZE_T(sizeof(MethodTable));
10252
10253     // vtable
10254     cbTotalSize += MethodTable::GetNumVtableIndirections(dwVirtuals) * sizeof(MethodTable::VTableIndir_t);
10255
10256     DWORD dwMultipurposeSlotsMask = 0;
10257     if (dwNumInterfaces != 0)
10258         dwMultipurposeSlotsMask |= MethodTable::enum_flag_HasInterfaceMap;
10259     if (dwNumDicts != 0)
10260         dwMultipurposeSlotsMask |= MethodTable::enum_flag_HasPerInstInfo;
10261     if (bmtVT->pDispatchMapBuilder->Count() > 0)
10262         dwMultipurposeSlotsMask |= MethodTable::enum_flag_HasDispatchMapSlot;
10263     if (dwNonVirtualSlots != 0)
10264         dwMultipurposeSlotsMask |= MethodTable::enum_flag_HasNonVirtualSlots;
10265     if (pLoaderModule != GetModule())
10266         dwMultipurposeSlotsMask |= MethodTable::enum_flag_HasModuleOverride;
10267
10268     // Add space for optional members here. Same as GetOptionalMembersSize()
10269     cbTotalSize += MethodTable::GetOptionalMembersAllocationSize(dwMultipurposeSlotsMask,
10270                                                       fHasGenericsStaticsInfo,
10271                                                       RidFromToken(GetCl()) >= METHODTABLE_TOKEN_OVERFLOW);
10272
10273     // Interface map starts here
10274     S_SIZE_T offsetOfInterfaceMap = cbTotalSize;
10275
10276     cbTotalSize += S_SIZE_T(dwNumInterfaces) * S_SIZE_T(sizeof(InterfaceInfo_t));
10277
10278 #ifdef FEATURE_COMINTEROP
10279     // DynamicInterfaceMap have an extra DWORD added to the end of the normal interface
10280     // map. This will be used to store the count of dynamically added interfaces
10281     // (the ones that are not in  the metadata but are QI'ed for at runtime).
10282     cbTotalSize += S_SIZE_T(fHasDynamicInterfaceMap ? sizeof(DWORD_PTR) : 0);
10283 #endif
10284
10285     // Dictionary pointers start here
10286     S_SIZE_T offsetOfInstAndDict = cbTotalSize;
10287
10288     if (dwNumDicts != 0)
10289     {
10290         cbTotalSize += sizeof(GenericsDictInfo);
10291         cbTotalSize += S_SIZE_T(dwNumDicts) * S_SIZE_T(sizeof(MethodTable::PerInstInfoElem_t));
10292         cbTotalSize += cbInstAndDict;
10293     }
10294
10295     S_SIZE_T offsetOfUnsharedVtableChunks = cbTotalSize;
10296
10297     // We will share any parent vtable chunk that does not contain a method we overrode (or introduced)
10298     // For the rest, we need to allocate space
10299     for (DWORD i = 0; i < dwVirtuals; i++)
10300     {
10301         if (ChangesImplementationOfVirtualSlot(static_cast<SLOT_INDEX>(i)))
10302         {
10303             DWORD chunkStart = MethodTable::GetStartSlotForVtableIndirection(MethodTable::GetIndexOfVtableIndirection(i), dwVirtuals);
10304             DWORD chunkEnd = MethodTable::GetEndSlotForVtableIndirection(MethodTable::GetIndexOfVtableIndirection(i), dwVirtuals);
10305
10306             cbTotalSize += S_SIZE_T(chunkEnd - chunkStart) * S_SIZE_T(sizeof(PCODE));
10307
10308             i = chunkEnd - 1;
10309         }
10310     }
10311
10312     // Add space for the non-virtual slots array (pointed to by an optional member) if required
10313     // If there is only one non-virtual slot, we store it directly in the optional member and need no array
10314     S_SIZE_T offsetOfNonVirtualSlots = cbTotalSize;
10315     if (dwNonVirtualSlots > 1)
10316     {
10317         cbTotalSize += S_SIZE_T(dwNonVirtualSlots) * S_SIZE_T(sizeof(PCODE));
10318     }
10319
10320     BYTE *pData = (BYTE *)pamTracker->Track(pAllocator->GetHighFrequencyHeap()->AllocMem(cbTotalSize));
10321
10322     _ASSERTE(IS_ALIGNED(pData, TARGET_POINTER_SIZE));
10323
10324     // There should be no overflows if we have allocated the memory successfully
10325     _ASSERTE(!cbTotalSize.IsOverflow());
10326
10327     MethodTable* pMT = (MethodTable*)(pData + dwGCSize);
10328
10329     pMT->SetMultipurposeSlotsMask(dwMultipurposeSlotsMask);
10330
10331     MethodTableWriteableData * pMTWriteableData = (MethodTableWriteableData *) (BYTE *)
10332         pamTracker->Track(pAllocator->GetHighFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(MethodTableWriteableData))));
10333     // Note: Memory allocated on loader heap is zero filled
10334     pMT->SetWriteableData(pMTWriteableData);
10335
10336     // This also disables IBC logging until the type is sufficiently initialized so
10337     // it needs to be done early
10338     pMTWriteableData->SetIsNotFullyLoadedForBuildMethodTable();
10339
10340 #ifdef _DEBUG
10341     pClassLoader->m_dwGCSize += dwGCSize;
10342     pClassLoader->m_dwInterfaceMapSize += (dwNumInterfaces * sizeof(InterfaceInfo_t));
10343     pClassLoader->m_dwMethodTableSize += (DWORD)cbTotalSize.Value();
10344     pClassLoader->m_dwVtableData += (dwVtableSlots * sizeof(PCODE));
10345 #endif // _DEBUG
10346
10347     // There should be no overflows if we have allocated the memory successfully
10348     _ASSERTE(!offsetOfUnsharedVtableChunks.IsOverflow());
10349     _ASSERTE(!offsetOfNonVirtualSlots.IsOverflow());
10350     _ASSERTE(!offsetOfInterfaceMap.IsOverflow());
10351     _ASSERTE(!offsetOfInstAndDict.IsOverflow());
10352
10353     // initialize the total number of slots
10354     pMT->SetNumVirtuals(static_cast<WORD>(dwVirtuals));
10355     if (fHasVirtualStaticMethods)
10356     {
10357         pMT->SetHasVirtualStaticMethods();
10358     }
10359
10360     pMT->SetParentMethodTable(pMTParent);
10361
10362     // Fill out the vtable indirection slots
10363     SIZE_T dwCurrentUnsharedSlotOffset = offsetOfUnsharedVtableChunks.Value();
10364     MethodTable::VtableIndirectionSlotIterator it = pMT->IterateVtableIndirectionSlots();
10365     while (it.Next())
10366     {
10367         BOOL shared = TRUE;
10368
10369         // Recalculate whether we will share this chunk
10370         for (DWORD i = it.GetStartSlot(); i < it.GetEndSlot(); i++)
10371         {
10372             if (ChangesImplementationOfVirtualSlot(static_cast<SLOT_INDEX>(i)))
10373             {
10374                 shared = FALSE;
10375                 break;
10376             }
10377         }
10378
10379         if (shared)
10380         {
10381             // Share the parent chunk
10382             _ASSERTE(it.GetEndSlot() <= pMTParent->GetNumVirtuals());
10383             it.SetIndirectionSlot(pMTParent->GetVtableIndirections()[it.GetIndex()]);
10384         }
10385         else
10386         {
10387             // Use the locally allocated chunk
10388             it.SetIndirectionSlot((MethodTable::VTableIndir2_t *)(pData+dwCurrentUnsharedSlotOffset));
10389             dwCurrentUnsharedSlotOffset += it.GetSize();
10390         }
10391     }
10392
10393 #ifdef FEATURE_COMINTEROP
10394     // Extensible RCW's are prefixed with the count of dynamic interfaces.
10395     if (fHasDynamicInterfaceMap)
10396     {
10397         _ASSERTE (dwNumInterfaces > 0);
10398         pMT->SetInterfaceMap ((WORD) (dwNumInterfaces), (InterfaceInfo_t*)(pData+offsetOfInterfaceMap.Value()+sizeof(DWORD_PTR)));
10399
10400         *(((DWORD_PTR *)pMT->GetInterfaceMap()) - 1) = 0;
10401     }
10402     else
10403 #endif // FEATURE_COMINTEROP
10404     {
10405         // interface map is at the end of the vtable
10406         pMT->SetInterfaceMap ((WORD) dwNumInterfaces, (InterfaceInfo_t *)(pData+offsetOfInterfaceMap.Value()));
10407     }
10408
10409     _ASSERTE(((WORD) dwNumInterfaces) == dwNumInterfaces);
10410
10411     if (fDynamicStatics)
10412     {
10413         pMT->SetDynamicStatics(fHasGenericsStaticsInfo);
10414     }
10415
10416     if (dwNonVirtualSlots > 0)
10417     {
10418         if (dwNonVirtualSlots > 1)
10419         {
10420             pMT->SetNonVirtualSlotsArray((PTR_PCODE)(pData+offsetOfNonVirtualSlots.Value()));
10421         }
10422         else
10423         {
10424             pMT->SetHasSingleNonVirtualSlot();
10425         }
10426     }
10427
10428     // the dictionary pointers follow the interface map
10429     if (dwNumDicts)
10430     {
10431         MethodTable::PerInstInfoElem_t *pPerInstInfo = (MethodTable::PerInstInfoElem_t *)(pData + offsetOfInstAndDict.Value() + sizeof(GenericsDictInfo));
10432
10433         pMT->SetPerInstInfo ( pPerInstInfo);
10434
10435         // Fill in the dictionary for this type, if it's instantiated
10436         if (cbInstAndDict)
10437         {
10438             MethodTable::PerInstInfoElem_t *pPInstInfo = (MethodTable::PerInstInfoElem_t *)(pPerInstInfo + (dwNumDicts-1));
10439             *pPInstInfo = (Dictionary*) (pPerInstInfo + dwNumDicts);
10440         }
10441     }
10442
10443 #ifdef _DEBUG
10444     pMT->m_pWriteableData->m_dwLastVerifedGCCnt = (DWORD)-1;
10445 #endif // _DEBUG
10446
10447     RETURN(pMT);
10448 }
10449
10450
10451 //*******************************************************************************
10452 //
10453 // Used by BuildMethodTable
10454 //
10455 // Setup the method table
10456 //
10457 #ifdef _PREFAST_
10458 #pragma warning(push)
10459 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
10460 #endif // _PREFAST_
10461
10462 VOID
10463 MethodTableBuilder::SetupMethodTable2(
10464         Module * pLoaderModule)
10465 {
10466     CONTRACTL
10467     {
10468         STANDARD_VM_CHECK;
10469         PRECONDITION(CheckPointer(this));
10470         PRECONDITION(CheckPointer(bmtVT));
10471         PRECONDITION(CheckPointer(bmtInterface));
10472         PRECONDITION(CheckPointer(bmtInternal));
10473         PRECONDITION(CheckPointer(bmtProp));
10474         PRECONDITION(CheckPointer(bmtMFDescs));
10475         PRECONDITION(CheckPointer(bmtEnumFields));
10476         PRECONDITION(CheckPointer(bmtError));
10477         PRECONDITION(CheckPointer(bmtMetaData));
10478         PRECONDITION(CheckPointer(bmtParent));
10479         PRECONDITION(CheckPointer(bmtGenerics));
10480     }
10481     CONTRACTL_END;
10482
10483     DWORD i;
10484
10485 #ifdef FEATURE_COMINTEROP
10486     BOOL fHasDynamicInterfaceMap = bmtInterface->dwInterfaceMapSize > 0 &&
10487                                    bmtProp->fIsComObjectType &&
10488                                    (GetParentMethodTable() != g_pObjectClass);
10489 #endif // FEATURE_COMINTEROP
10490
10491     EEClass *pClass = GetHalfBakedClass();
10492
10493     DWORD cbDictSlotSize = 0;
10494     DWORD cbDictAllocSize = 0;
10495     if (bmtGenerics->HasInstantiation())
10496     {
10497         cbDictAllocSize = DictionaryLayout::GetDictionarySizeFromLayout(bmtGenerics->GetNumGenericArgs(), pClass->GetDictionaryLayout(), &cbDictSlotSize);
10498     }
10499
10500     DWORD dwGCSize;
10501
10502     if (bmtFP->NumGCPointerSeries > 0)
10503     {
10504         dwGCSize = (DWORD)CGCDesc::ComputeSize(bmtFP->NumGCPointerSeries);
10505     }
10506     else
10507     {
10508         dwGCSize = 0;
10509     }
10510
10511     pClass->SetNumMethods(bmtVT->cTotalSlots);
10512     pClass->SetNumNonVirtualSlots(bmtVT->cVtableSlots - bmtVT->cVirtualSlots);
10513
10514     // Now setup the method table
10515     // interface map is allocated along with the method table
10516     MethodTable *pMT = AllocateNewMT(pLoaderModule,
10517                                    bmtVT->cVtableSlots,
10518                                    bmtVT->cVirtualSlots,
10519                                    dwGCSize,
10520                                    bmtInterface->dwInterfaceMapSize,
10521                                    bmtGenerics->numDicts,
10522                                    cbDictAllocSize,
10523                                    GetParentMethodTable(),
10524                                    GetClassLoader(),
10525                                    bmtAllocator,
10526                                    IsInterface(),
10527                                    bmtProp->fDynamicStatics,
10528                                    bmtProp->fGenericsStatics,
10529                                    bmtProp->fHasVirtualStaticMethods,
10530 #ifdef FEATURE_COMINTEROP
10531                                    fHasDynamicInterfaceMap,
10532 #endif
10533                                    GetMemTracker());
10534
10535     pMT->SetClass(pClass);
10536     pClass->m_pMethodTable = pMT;
10537     m_pHalfBakedMT = pMT;
10538
10539 #ifdef _DEBUG
10540     pMT->SetDebugClassName(GetDebugClassName());
10541 #endif
10542
10543     if (IsInterface())
10544         pMT->SetIsInterface();
10545
10546     if (GetParentMethodTable() != NULL)
10547     {
10548         if (GetParentMethodTable()->HasModuleDependencies())
10549         {
10550             pMT->SetHasModuleDependencies();
10551         }
10552         else
10553         {
10554             Module * pModule = GetModule();
10555             Module * pParentModule = GetParentMethodTable()->GetModule();
10556             if (pModule != pParentModule)
10557             {
10558                 pMT->SetHasModuleDependencies();
10559             }
10560         }
10561
10562         if (GetParentMethodTable()->HasPreciseInitCctors() || !pClass->IsBeforeFieldInit())
10563         {
10564             pMT->SetHasPreciseInitCctors();
10565         }
10566     }
10567
10568     // Must be done early because various methods test HasInstantiation() and ContainsGenericVariables()
10569     if (bmtGenerics->GetNumGenericArgs() != 0)
10570     {
10571         pMT->SetHasInstantiation(bmtGenerics->fTypicalInstantiation, bmtGenerics->fSharedByGenericInstantiations);
10572
10573         if (bmtGenerics->fContainsGenericVariables)
10574             pMT->SetContainsGenericVariables();
10575     }
10576
10577     if (bmtGenerics->numDicts != 0)
10578     {
10579         if (!FitsIn<WORD>(bmtGenerics->GetNumGenericArgs()))
10580         {
10581             BuildMethodTableThrowException(IDS_CLASSLOAD_TOOMANYGENERICARGS);
10582         }
10583
10584         pMT->SetDictInfo(bmtGenerics->numDicts,
10585             static_cast<WORD>(bmtGenerics->GetNumGenericArgs()));
10586     }
10587
10588     CONSISTENCY_CHECK(pMT->GetNumGenericArgs() == bmtGenerics->GetNumGenericArgs());
10589     CONSISTENCY_CHECK(pMT->GetNumDicts() == bmtGenerics->numDicts);
10590     CONSISTENCY_CHECK(pMT->HasInstantiation() == bmtGenerics->HasInstantiation());
10591     CONSISTENCY_CHECK(pMT->HasInstantiation() == !pMT->GetInstantiation().IsEmpty());
10592
10593     pMT->SetLoaderModule(pLoaderModule);
10594     pMT->SetLoaderAllocator(bmtAllocator);
10595
10596     pMT->SetModule(GetModule());
10597
10598     pMT->SetInternalCorElementType (ELEMENT_TYPE_CLASS);
10599
10600     SetNonGCRegularStaticFieldBytes (bmtProp->dwNonGCRegularStaticFieldBytes);
10601     SetNonGCThreadStaticFieldBytes (bmtProp->dwNonGCThreadStaticFieldBytes);
10602
10603 #ifdef FEATURE_TYPEEQUIVALENCE
10604     if (bmtProp->fHasTypeEquivalence)
10605     {
10606         pMT->SetHasTypeEquivalence();
10607     }
10608 #endif //FEATURE_TYPEEQUIVALENCE
10609
10610 #ifdef FEATURE_COMINTEROP
10611     if (bmtProp->fSparse)
10612         pClass->SetSparseForCOMInterop();
10613 #endif // FEATURE_COMINTEROP
10614
10615     if (bmtVT->pCCtor != NULL)
10616     {
10617         pMT->SetHasClassConstructor();
10618         CONSISTENCY_CHECK(pMT->GetClassConstructorSlot() == bmtVT->pCCtor->GetSlotIndex());
10619     }
10620     if (bmtVT->pDefaultCtor != NULL)
10621     {
10622         pMT->SetHasDefaultConstructor();
10623         CONSISTENCY_CHECK(pMT->GetDefaultConstructorSlot() == bmtVT->pDefaultCtor->GetSlotIndex());
10624     }
10625
10626     for (MethodDescChunk *pChunk = GetHalfBakedClass()->GetChunks(); pChunk != NULL; pChunk = pChunk->GetNextChunk())
10627     {
10628         pChunk->SetMethodTable(pMT);
10629     }
10630
10631 #ifdef _DEBUG
10632     {
10633         DeclaredMethodIterator it(*this);
10634         while (it.Next())
10635         {
10636             MethodDesc *pMD = it->GetMethodDesc();
10637             if (pMD != NULL)
10638             {
10639                 pMD->m_pDebugMethodTable = pMT;
10640                 pMD->m_pszDebugMethodSignature = FormatSig(pMD, GetLoaderAllocator()->GetLowFrequencyHeap(), GetMemTracker());
10641             }
10642             MethodDesc *pUnboxedMD = it->GetUnboxedMethodDesc();
10643             if (pUnboxedMD != NULL)
10644             {
10645                 pUnboxedMD->m_pDebugMethodTable = pMT;
10646                 pUnboxedMD->m_pszDebugMethodSignature = FormatSig(pUnboxedMD, GetLoaderAllocator()->GetLowFrequencyHeap(), GetMemTracker());
10647             }
10648         }
10649     }
10650 #endif // _DEBUG
10651
10652     // Note that for value classes, the following calculation is only appropriate
10653     // when the instance is in its "boxed" state.
10654     if (!IsInterface())
10655     {
10656         DWORD baseSize = Max<DWORD>(bmtFP->NumInstanceFieldBytes + OBJECT_BASESIZE, MIN_OBJECT_SIZE);
10657         baseSize = (baseSize + ALLOC_ALIGN_CONSTANT) & ~ALLOC_ALIGN_CONSTANT;  // m_BaseSize must be aligned
10658         pMT->SetBaseSize(baseSize);
10659
10660         GetHalfBakedClass()->SetBaseSizePadding(baseSize - bmtFP->NumInstanceFieldBytes);
10661
10662         if (bmtProp->fIsComObjectType)
10663         {   // Propagate the com specific info
10664             pMT->SetComObjectType();
10665 #ifdef FEATURE_COMINTEROP
10666             // COM objects need an optional field on the EEClass, so ensure this class instance has allocated
10667             // the optional field descriptor.
10668             EnsureOptionalFieldsAreAllocated(pClass, m_pAllocMemTracker, GetLoaderAllocator()->GetLowFrequencyHeap());
10669 #endif // FEATURE_COMINTEROP
10670         }
10671     }
10672     else
10673     {
10674 #ifdef FEATURE_COMINTEROP
10675         // If this is an interface then we need to set the ComInterfaceType to
10676         // -1 to indicate we have not yet determined the interface type.
10677         pClass->SetComInterfaceType((CorIfaceAttr)-1);
10678
10679         // If this is a special COM event interface, then mark the MT as such.
10680         if (bmtProp->fComEventItfType)
10681         {
10682             pClass->SetComEventItfType();
10683         }
10684 #endif // FEATURE_COMINTEROP
10685     }
10686     _ASSERTE((pMT->IsInterface() == 0) == (IsInterface() == 0));
10687
10688     FieldDesc *pFieldDescList = pClass->GetFieldDescList();
10689     // Set all field slots to point to the newly created MethodTable
10690     for (i = 0; i < (bmtEnumFields->dwNumStaticFields + bmtEnumFields->dwNumInstanceFields); i++)
10691     {
10692         pFieldDescList[i].m_pMTOfEnclosingClass = pMT;
10693     }
10694
10695     // Fill in type parameters before looking up exact parent or fetching the types of any field descriptors!
10696     // This must come before the use of GetFieldType in the value class representation optimization below.
10697     if (bmtGenerics->GetNumGenericArgs() != 0)
10698     {
10699         // Space has already been allocated for the instantiation but the parameters haven't been filled in
10700         Instantiation destInst = pMT->GetInstantiation();
10701         Instantiation inst = bmtGenerics->GetInstantiation();
10702
10703         // So fill them in...
10704         TypeHandle * pInstDest = (TypeHandle *)destInst.GetRawArgs();
10705         for (DWORD j = 0; j < bmtGenerics->GetNumGenericArgs(); j++)
10706         {
10707             pInstDest[j] = inst[j];
10708         }
10709
10710         PTR_DictionaryLayout pLayout = pClass->GetDictionaryLayout();
10711         if (pLayout != NULL)
10712         {
10713             _ASSERTE(pLayout->GetMaxSlots() > 0);
10714
10715             PTR_Dictionary pDictionarySlots = pMT->GetPerInstInfo()[bmtGenerics->numDicts - 1];
10716             DWORD* pSizeSlot = (DWORD*)(pDictionarySlots + bmtGenerics->GetNumGenericArgs());
10717             *pSizeSlot = cbDictSlotSize;
10718         }
10719     }
10720
10721     CorElementType normalizedType = ELEMENT_TYPE_CLASS;
10722     if (IsValueClass())
10723     {
10724         if (IsEnum())
10725         {
10726             if (GetNumInstanceFields() != 1 ||
10727                 !CorTypeInfo::IsPrimitiveType(pFieldDescList[0].GetFieldType()))
10728             {
10729                 BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil);
10730             }
10731             CONSISTENCY_CHECK(!pFieldDescList[0].IsStatic());
10732             normalizedType = pFieldDescList->GetFieldType();
10733         }
10734         else
10735         {
10736             normalizedType = ELEMENT_TYPE_VALUETYPE;
10737         }
10738     }
10739     pMT->SetInternalCorElementType(normalizedType);
10740
10741     if (bmtProp->fIsIntrinsicType)
10742     {
10743         pMT->SetIsIntrinsicType();
10744     }
10745
10746     if (GetModule()->IsSystem())
10747     {
10748         CheckForSystemTypes();
10749     }
10750
10751     // Now fill in the real interface map with the approximate interfaces
10752     if (bmtInterface->dwInterfaceMapSize > 0)
10753     {
10754         // First ensure we have enough space to record extra flag information for each interface (we don't
10755         // record this directly into each interface map entry since these flags don't pack well due to
10756         // alignment).
10757         PVOID pExtraInterfaceInfo = NULL;
10758         SIZE_T cbExtraInterfaceInfo = MethodTable::GetExtraInterfaceInfoSize(bmtInterface->dwInterfaceMapSize);
10759         if (cbExtraInterfaceInfo)
10760             pExtraInterfaceInfo = GetMemTracker()->Track(GetLoaderAllocator()->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(cbExtraInterfaceInfo)));
10761
10762         // Call this even in the case where pExtraInterfaceInfo == NULL (certain cases are optimized and don't
10763         // require extra buffer space).
10764         pMT->InitializeExtraInterfaceInfo(pExtraInterfaceInfo);
10765
10766         InterfaceInfo_t *pInterfaces = pMT->GetInterfaceMap();
10767
10768         CONSISTENCY_CHECK(CheckPointer(pInterfaces));
10769
10770         // Copy the interface map member by member so there is no junk in the padding.
10771         for (i = 0; i < bmtInterface->dwInterfaceMapSize; i++)
10772         {
10773             bmtInterfaceEntry * pEntry = &bmtInterface->pInterfaceMap[i];
10774
10775             if (pEntry->IsDeclaredOnType())
10776                 pMT->SetInterfaceDeclaredOnClass(i);
10777             _ASSERTE(!!pEntry->IsDeclaredOnType() == !!pMT->IsInterfaceDeclaredOnClass(i));
10778
10779             pInterfaces[i].SetMethodTable(pEntry->GetInterfaceType()->GetMethodTable());
10780         }
10781     }
10782
10783     pMT->SetCl(GetCl());
10784
10785     // The type is sufficiently initialized for most general purpose accessor methods to work.
10786     // Mark the type as restored to avoid avoid asserts. Note that this also enables IBC logging.
10787     pMT->GetWriteableDataForWrite()->SetIsRestoredForBuildMethodTable();
10788
10789 #ifdef _DEBUG
10790     // Store status if we tried to inject duplicate interfaces
10791     if (bmtInterface->dbg_fShouldInjectInterfaceDuplicates)
10792         pMT->Debug_SetHasInjectedInterfaceDuplicates();
10793 #endif //_DEBUG
10794
10795     // Keep bmtInterface data around since we no longer write the flags (IsDeclaredOnType and
10796     // IsImplementedByParent) into the interface map (these flags are only required during type loading).
10797
10798     {
10799         for (MethodDescChunk *pChunk = GetHalfBakedClass()->GetChunks(); pChunk != NULL; pChunk = pChunk->GetNextChunk())
10800         {
10801             // Make sure that temporary entrypoints are create for methods. NGEN uses temporary
10802             // entrypoints as surrogate keys for precodes.
10803             pChunk->EnsureTemporaryEntryPointsCreated(GetLoaderAllocator(), GetMemTracker());
10804         }
10805     }
10806
10807     {   // copy onto the real vtable (methods only)
10808         //@GENERICS: Because we sometimes load an inexact parent (see ClassLoader::GetParent) the inherited slots might
10809         // come from the wrong place and need fixing up once we know the exact parent
10810
10811         for (bmtVtable::Iterator slotIt = bmtVT->IterateSlots(); !slotIt.AtEnd(); ++slotIt)
10812         {
10813             SLOT_INDEX iCurSlot = static_cast<SLOT_INDEX>(slotIt.CurrentIndex());
10814
10815             // We want the unboxed MethodDesc if we're out of the virtual method range
10816             // and the method we're dealing with has an unboxing method. If so, then
10817             // the unboxing method was placed in the virtual section of the vtable and
10818             // we now need to place the unboxed version.
10819             MethodDesc * pMD = NULL;
10820             if (iCurSlot < bmtVT->cVirtualSlots || !slotIt->Impl().AsMDMethod()->IsUnboxing())
10821             {
10822                 pMD = slotIt->Impl().GetMethodDesc();
10823                 CONSISTENCY_CHECK(slotIt->Decl().GetSlotIndex() == iCurSlot);
10824             }
10825             else
10826             {
10827                 pMD = slotIt->Impl().AsMDMethod()->GetUnboxedMethodDesc();
10828                 CONSISTENCY_CHECK(pMD->GetSlot() == iCurSlot);
10829             }
10830
10831             CONSISTENCY_CHECK(CheckPointer(pMD));
10832
10833             if (pMD->GetMethodTable() != pMT)
10834             {
10835                 //
10836                 // Inherited slots
10837                 //
10838                 // Do not write into vtable chunks shared with parent. It would introduce race
10839                 // with code:MethodDesc::SetStableEntryPointInterlocked.
10840                 //
10841                 DWORD indirectionIndex = MethodTable::GetIndexOfVtableIndirection(iCurSlot);
10842                 if (GetParentMethodTable()->GetVtableIndirections()[indirectionIndex] != pMT->GetVtableIndirections()[indirectionIndex])
10843                     pMT->SetSlot(iCurSlot, pMD->GetInitialEntryPointForCopiedSlot());
10844             }
10845             else
10846             {
10847                 //
10848                 // Owned slots
10849                 //
10850                 _ASSERTE(iCurSlot >= bmtVT->cVirtualSlots || ChangesImplementationOfVirtualSlot(iCurSlot));
10851
10852                 PCODE addr = pMD->GetTemporaryEntryPoint();
10853                 _ASSERTE(addr != NULL);
10854
10855                 if (pMD->HasNonVtableSlot())
10856                 {
10857                     *((PCODE *)pMD->GetAddrOfSlot()) = addr;
10858                 }
10859                 else
10860                 {
10861                     pMT->SetSlot(iCurSlot, addr);
10862                 }
10863
10864                 if (pMD->GetSlot() == iCurSlot && pMD->RequiresStableEntryPoint())
10865                 {
10866                     // The rest of the system assumes that certain methods always have stable entrypoints.
10867                     // Create them now.
10868                     pMD->GetOrCreatePrecode();
10869                 }
10870             }
10871         }
10872     }
10873
10874     // If we have any entries, then finalize them and allocate the object in class loader heap
10875     DispatchMap                 *pDispatchMap        = NULL;
10876     DispatchMapBuilder          *pDispatchMapBuilder = bmtVT->pDispatchMapBuilder;
10877     CONSISTENCY_CHECK(CheckPointer(pDispatchMapBuilder));
10878
10879     if (pDispatchMapBuilder->Count() > 0)
10880     {
10881         // Create a map in stacking memory.
10882         BYTE * pbMap;
10883         UINT32 cbMap;
10884         DispatchMap::CreateEncodedMapping(
10885             pMT,
10886             pDispatchMapBuilder,
10887             pDispatchMapBuilder->GetAllocator(),
10888             &pbMap,
10889             &cbMap);
10890
10891         // Now finalize the impltable and allocate the block in the low frequency loader heap
10892         size_t objSize = (size_t) DispatchMap::GetObjectSize(cbMap);
10893         void * pv = AllocateFromLowFrequencyHeap(S_SIZE_T(objSize));
10894         _ASSERTE(pv != NULL);
10895
10896         // Use placement new
10897         pDispatchMap = new (pv) DispatchMap(pbMap, cbMap);
10898         pMT->SetDispatchMap(pDispatchMap);
10899
10900 #ifdef LOGGING
10901         g_sdStats.m_cDispatchMap++;
10902         g_sdStats.m_cbDispatchMap += (UINT32) objSize;
10903         LOG((LF_LOADER, LL_INFO1000, "SD: Dispatch map for %s: %d bytes for map, %d bytes total for object.\n",
10904             pMT->GetDebugClassName(), cbMap, objSize));
10905 #endif // LOGGING
10906
10907     }
10908
10909     // GetMethodData by default will cache its result. However, in the case that we're
10910     // building a MethodTable, we aren't guaranteed that this type is going to successfully
10911     // load and so caching it would result in errors down the road since the memory and
10912     // type occupying the same memory location would very likely be incorrect. The second
10913     // argument specifies that GetMethodData should not cache the returned object.
10914     MethodTable::MethodDataWrapper hMTData(MethodTable::GetMethodData(pMT, FALSE));
10915
10916     if (!IsInterface())
10917     {
10918         // Propagate inheritance.
10919
10920         // NOTE: In the world of unfolded interface this was used to propagate overrides into
10921         //       the unfolded interface vtables to make sure that overrides of virtual methods
10922         //       also overrode the interface methods that they contributed to. This had the
10923         //       unfortunate side-effect of also overwriting regular vtable slots that had been
10924         //       methodimpl'd and as a result changed the meaning of methodimpl from "substitute
10925         //       the body of method A with the body of method B" to "unify the slots of methods
10926         //       A and B". But now compilers have come to rely on this side-effect and it can
10927         //       not be brought back to its originally intended behaviour.
10928
10929         // For every slot whose body comes from another slot (determined by getting the MethodDesc
10930         // for a slot and seeing if MethodDesc::GetSlot returns a different value than the slot
10931         // from which the MethodDesc was recovered), copy the value of the slot stated by the
10932         // MethodDesc over top of the current slot.
10933
10934         // Because of the way slot unification works, we need to iterate the enture vtable until
10935         // no slots need updated. To understand this, imagine the following:
10936         //      C1::M1 is overridden by C2::M2
10937         //      C1::M2 is methodImpled by C1::M3
10938         //      C1::M3 is overridden by C2::M3
10939         // This should mean that C1::M1 is implemented by C2::M3, but if we didn't run the below
10940         // for loop a second time, this would not be propagated properly - it would only be placed
10941         // into the slot for C1::M2 and never make its way up to C1::M1.
10942
10943         BOOL fChangeMade;
10944         do
10945         {
10946             fChangeMade = FALSE;
10947             for (i = 0; i < pMT->GetNumVirtuals(); i++)
10948             {
10949                 MethodDesc* pMD = hMTData->GetImplMethodDesc(i);
10950
10951                 CONSISTENCY_CHECK(CheckPointer(pMD));
10952                 CONSISTENCY_CHECK(pMD == pMT->GetMethodDescForSlot(i));
10953
10954                 // This indicates that the method body in this slot was copied here through a methodImpl.
10955                 // Thus, copy the value of the slot from which the body originally came, in case it was
10956                 // overridden, to make sure the two slots stay in sync.
10957                 DWORD originalIndex = pMD->GetSlot();
10958                 if (originalIndex != i)
10959                 {
10960                     MethodDesc *pOriginalMD = hMTData->GetImplMethodDesc(originalIndex);
10961                     CONSISTENCY_CHECK(CheckPointer(pOriginalMD));
10962                     CONSISTENCY_CHECK(pOriginalMD == pMT->GetMethodDescForSlot(originalIndex));
10963                     if (pMD != pOriginalMD)
10964                     {
10965                         // Copy the slot value in the method's original slot.
10966                         pMT->SetSlot(i, pOriginalMD->GetInitialEntryPointForCopiedSlot());
10967                         hMTData->InvalidateCachedVirtualSlot(i);
10968
10969                         // Update the pMD to the new method desc we just copied over ourselves with. This will
10970                         // be used in the check for missing method block below.
10971                         pMD = pOriginalMD;
10972
10973                         // This method is now duplicate
10974                         pMD->SetDuplicate();
10975                         INDEBUG(g_dupMethods++;)
10976                         fChangeMade = TRUE;
10977                     }
10978                 }
10979             }
10980         }
10981         while (fChangeMade);
10982     }
10983
10984     if (!bmtProp->fNoSanityChecks)
10985         VerifyVirtualMethodsImplemented(hMTData);
10986
10987 #ifdef _DEBUG
10988     {
10989         for (bmtVtable::Iterator i = bmtVT->IterateSlots();
10990              !i.AtEnd(); ++i)
10991         {
10992             _ASSERTE(i->Impl().GetMethodDesc() != NULL);
10993         }
10994     }
10995 #endif // _DEBUG
10996
10997
10998 #ifdef FEATURE_COMINTEROP
10999     // for ComObject types, i.e. if the class extends from a COM Imported
11000     // class
11001     // make sure any interface implemented by the COM Imported class
11002     // is overridden fully, (OR) not overridden at all..
11003     if (bmtProp->fIsComObjectType)
11004     {
11005         MethodTable::InterfaceMapIterator intIt = pMT->IterateInterfaceMap();
11006         while (intIt.Next())
11007         {
11008             MethodTable* pIntfMT = intIt.GetInterface(pMT, pMT->GetLoadLevel());
11009             if (pIntfMT->GetNumVirtuals() != 0)
11010             {
11011                 BOOL hasComImportMethod = FALSE;
11012                 BOOL hasManagedMethod = FALSE;
11013
11014                 // NOTE: Avoid caching the MethodData object for the type being built.
11015                 MethodTable::MethodDataWrapper hItfImplData(MethodTable::GetMethodData(pIntfMT, pMT, FALSE));
11016                 MethodTable::MethodIterator it(hItfImplData);
11017                 for (;it.IsValid(); it.Next())
11018                 {
11019                     MethodDesc *pClsMD = NULL;
11020                     // If we fail to find an _IMPLEMENTATION_ for the interface MD, then
11021                     // we are a ComImportMethod, otherwise we still be a ComImportMethod or
11022                     // we can be a ManagedMethod.
11023                     DispatchSlot impl(it.GetTarget());
11024                     if (!impl.IsNull())
11025                     {
11026                         pClsMD = it.GetMethodDesc();
11027
11028                         CONSISTENCY_CHECK(!pClsMD->IsInterface());
11029                         if (pClsMD->GetClass()->IsComImport())
11030                         {
11031                             hasComImportMethod = TRUE;
11032                         }
11033                         else
11034                         {
11035                             hasManagedMethod = TRUE;
11036                         }
11037                     }
11038                     else
11039                     {
11040                         // Need to set the pClsMD for the error reporting below.
11041                         pClsMD = it.GetDeclMethodDesc();
11042                         CONSISTENCY_CHECK(CheckPointer(pClsMD));
11043                         hasComImportMethod = TRUE;
11044                     }
11045
11046                     // One and only one of the two must be set.
11047                     if ((hasComImportMethod && hasManagedMethod) ||
11048                         (!hasComImportMethod && !hasManagedMethod))
11049                     {
11050                         BuildMethodTableThrowException(IDS_EE_BAD_COMEXTENDS_CLASS, pClsMD->GetNameOnNonArrayClass());
11051                     }
11052                 }
11053             }
11054         }
11055     }
11056
11057     // For COM event interfaces, we need to make sure that all the methods are
11058     // methods to add or remove events. This means that they all need to take
11059     // a delegate derived class and have a void return type.
11060     if (bmtProp->fComEventItfType)
11061     {
11062         // COM event interfaces had better be interfaces.
11063         CONSISTENCY_CHECK(IsInterface());
11064
11065         // Go through all the methods and check the validity of the signature.
11066         // NOTE: Uses hMTData to avoid caching a MethodData object for the type being built.
11067         MethodTable::MethodIterator it(hMTData);
11068         for (;it.IsValid(); it.Next())
11069         {
11070             MethodDesc* pMD = it.GetMethodDesc();
11071             _ASSERTE(pMD);
11072
11073             MetaSig Sig(pMD);
11074
11075             {
11076                 CONTRACT_VIOLATION(LoadsTypeViolation);
11077                 if (Sig.GetReturnType() != ELEMENT_TYPE_VOID ||
11078                     Sig.NumFixedArgs() != 1 ||
11079                     Sig.NextArg() != ELEMENT_TYPE_CLASS ||
11080                     !Sig.GetLastTypeHandleThrowing().CanCastTo(TypeHandle(g_pDelegateClass)))
11081                 {
11082                     BuildMethodTableThrowException(IDS_EE_BAD_COMEVENTITF_CLASS, pMD->GetNameOnNonArrayClass());
11083                 }
11084             }
11085         }
11086     }
11087 #endif // FEATURE_COMINTEROP
11088
11089     // If this class uses any VTS (Version Tolerant Serialization) features
11090     // (event callbacks or OptionalField attributes) we've previously cached the
11091     // additional information in the bmtMFDescs structure. Now it's time to add
11092     // this information as an optional extension to the MethodTable.
11093 }
11094 #ifdef _PREFAST_
11095 #pragma warning(pop)
11096 #endif
11097
11098 // Returns true if there is at least one default implementation for this interface method
11099 // We don't care about conflicts at this stage in order to avoid impact type load performance
11100 BOOL MethodTableBuilder::HasDefaultInterfaceImplementation(bmtRTType *pDeclType, MethodDesc *pDeclMD)
11101 {
11102     STANDARD_VM_CONTRACT;
11103
11104 #ifdef FEATURE_DEFAULT_INTERFACES
11105     // If the interface method is already non-abstract, we are done
11106     if (!pDeclMD->IsAbstract())
11107         return TRUE;
11108
11109     // If the method is an abstract MethodImpl, this is a reabstraction:
11110     //
11111     // interface IFoo { void Frob() { } }
11112     // interface IBar : IFoo { abstract void IFoo.Frob() }
11113     //
11114     // We don't require these to have an implementation because they're final anyway.
11115     if (pDeclMD->IsMethodImpl())
11116     {
11117         assert(pDeclMD->IsFinal());
11118         return TRUE;
11119     }
11120
11121     int targetSlot = pDeclMD->GetSlot();
11122
11123     // Iterate over all the interfaces this type implements
11124     bmtInterfaceEntry * pItfEntry = NULL;
11125     for (DWORD i = 0; i < bmtInterface->dwInterfaceMapSize; i++)
11126     {
11127         bmtRTType * pCurItf = bmtInterface->pInterfaceMap[i].GetInterfaceType();
11128
11129         Module * pCurIntfModule = pCurItf->GetMethodTable()->GetModule();
11130
11131         // Go over the methods on the interface
11132         MethodTable::IntroducedMethodIterator methIt(pCurItf->GetMethodTable());
11133         for (; methIt.IsValid(); methIt.Next())
11134         {
11135             MethodDesc * pPotentialImpl = methIt.GetMethodDesc();
11136
11137             // If this interface method is not a MethodImpl, it can't possibly implement
11138             // the interface method we are looking for
11139             if (!pPotentialImpl->IsMethodImpl())
11140                 continue;
11141
11142             // Go over all the decls this MethodImpl is implementing
11143             MethodImpl::Iterator it(pPotentialImpl);
11144             for (; it.IsValid(); it.Next())
11145             {
11146                 MethodDesc *pPotentialDecl = it.GetMethodDesc();
11147
11148                 // Check this is a decl with the right slot
11149                 if (pPotentialDecl->GetSlot() != targetSlot)
11150                     continue;
11151
11152                 // Find out what interface this default implementation is implementing
11153                 mdToken tkParent;
11154                 IfFailThrow(pCurIntfModule->GetMDImport()->GetParentToken(it.GetToken(), &tkParent));
11155
11156                 // We can only load the approximate interface at this point
11157                 MethodTable * pPotentialInterfaceMT = ClassLoader::LoadTypeDefOrRefOrSpecThrowing(
11158                     pCurIntfModule,
11159                     tkParent,
11160                     &bmtGenerics->typeContext,
11161                     ClassLoader::ThrowIfNotFound,
11162                     ClassLoader::PermitUninstDefOrRef,
11163                     ClassLoader::LoadTypes,
11164                     CLASS_LOAD_APPROXPARENTS,
11165                     TRUE).GetMethodTable()->GetCanonicalMethodTable();
11166
11167                 // Is this a default implementation for the interface we are looking for?
11168                 if (pDeclType->GetMethodTable()->HasSameTypeDefAs(pPotentialInterfaceMT))
11169                 {
11170                     // If the type is not generic, matching defs are all we need
11171                     if (!pDeclType->GetMethodTable()->HasInstantiation())
11172                         return TRUE;
11173
11174                     // If this is generic, we need to compare under substitutions
11175                     Substitution curItfSubs(tkParent, pCurIntfModule, &pCurItf->GetSubstitution());
11176
11177                     // Type Equivalence is not respected for this comparison as you can have multiple type equivalent interfaces on a class
11178                     TokenPairList newVisited = TokenPairList::AdjustForTypeEquivalenceForbiddenScope(NULL);
11179                     if (MetaSig::CompareTypeDefsUnderSubstitutions(
11180                         pPotentialInterfaceMT, pDeclType->GetMethodTable(),
11181                         &curItfSubs, &pDeclType->GetSubstitution(),
11182                         &newVisited))
11183                     {
11184                         return TRUE;
11185                     }
11186                 }
11187             }
11188         }
11189     }
11190 #endif // FEATURE_DEFAULT_INTERFACES
11191
11192     return FALSE;
11193 }
11194
11195 void MethodTableBuilder::VerifyVirtualMethodsImplemented(MethodTable::MethodData * hMTData)
11196 {
11197     STANDARD_VM_CONTRACT;
11198
11199     //
11200     // This verification is not applicable or required in many cases
11201     //
11202
11203     if (IsAbstract() || IsInterface())
11204         return;
11205
11206 #ifdef FEATURE_COMINTEROP
11207     if (bmtProp->fIsComObjectType)
11208         return;
11209 #endif // FEATURE_COMINTEROP
11210
11211     // Since interfaces aren't laid out in the vtable for stub dispatch, what we need to do
11212     // is try to find an implementation for every interface contract by iterating through
11213     // the interfaces not declared on a parent.
11214     BOOL fParentIsAbstract = FALSE;
11215     if (HasParent())
11216     {
11217         fParentIsAbstract = GetParentMethodTable()->IsAbstract();
11218     }
11219
11220     // If the parent is abstract, we need to check that each virtual method is implemented
11221     if (fParentIsAbstract)
11222     {
11223         // NOTE: Uses hMTData to avoid caching a MethodData object for the type being built.
11224         MethodTable::MethodIterator it(hMTData);
11225         for (; it.IsValid() && it.IsVirtual(); it.Next())
11226         {
11227             MethodDesc *pMD = it.GetMethodDesc();
11228             if (pMD->IsAbstract())
11229             {
11230                 MethodDesc *pDeclMD = it.GetDeclMethodDesc();
11231                 BuildMethodTableThrowException(IDS_CLASSLOAD_NOTIMPLEMENTED, pDeclMD->GetNameOnNonArrayClass());
11232             }
11233         }
11234     }
11235
11236     DispatchMapTypeID * rgInterfaceDispatchMapTypeIDs =
11237         new (GetStackingAllocator()) DispatchMapTypeID[bmtInterface->dwInterfaceMapSize];
11238
11239     bmtInterfaceInfo::MapIterator intIt = bmtInterface->IterateInterfaceMap();
11240     for (; !intIt.AtEnd(); intIt.Next())
11241     {
11242         if (fParentIsAbstract || !intIt->IsImplementedByParent())
11243         {
11244             // Compute all TypeIDs for this interface (all duplicates in the interface map)
11245             UINT32 cInterfaceDuplicates;
11246             ComputeDispatchMapTypeIDs(
11247                 intIt->GetInterfaceType()->GetMethodTable(),
11248                 &intIt->GetInterfaceType()->GetSubstitution(),
11249                 rgInterfaceDispatchMapTypeIDs,
11250                 bmtInterface->dwInterfaceMapSize,
11251                 &cInterfaceDuplicates);
11252             _ASSERTE(cInterfaceDuplicates <= bmtInterface->dwInterfaceMapSize);
11253             _ASSERTE(cInterfaceDuplicates > 0);
11254
11255             // NOTE: This override does not cache the resulting MethodData object.
11256             MethodTable::MethodDataWrapper hData(MethodTable::GetMethodData(
11257                 rgInterfaceDispatchMapTypeIDs,
11258                 cInterfaceDuplicates,
11259                 intIt->GetInterfaceType()->GetMethodTable(),
11260                 GetHalfBakedMethodTable()));
11261             MethodTable::MethodIterator it(hData);
11262             for (; it.IsValid() && it.IsVirtual(); it.Next())
11263             {
11264                 if (it.GetTarget().IsNull())
11265                 {
11266                     MethodDesc *pMD = it.GetDeclMethodDesc();
11267
11268                     if (!HasDefaultInterfaceImplementation(intIt->GetInterfaceType(), pMD))
11269                         BuildMethodTableThrowException(IDS_CLASSLOAD_NOTIMPLEMENTED, pMD->GetNameOnNonArrayClass());
11270                 }
11271             }
11272         }
11273     }
11274 }
11275
11276 INT32 __stdcall IsDefined(Module *pModule, mdToken token, TypeHandle attributeClass)
11277 {
11278     CONTRACTL
11279     {
11280         THROWS;
11281         GC_TRIGGERS;
11282     }
11283     CONTRACTL_END;
11284
11285     BOOL isDefined = FALSE;
11286
11287     IMDInternalImport *pInternalImport = pModule->GetMDImport();
11288     BOOL isSealed = FALSE;
11289
11290     HENUMInternalHolder hEnum(pInternalImport);
11291     TypeHandle caTH;
11292
11293     // Get the enum first but don't get any values
11294     hEnum.EnumInit(mdtCustomAttribute, token);
11295
11296     ULONG cMax = pInternalImport->EnumGetCount(&hEnum);
11297     if (cMax)
11298     {
11299         // we have something to look at
11300
11301
11302         if (!attributeClass.IsNull())
11303             isSealed = attributeClass.GetMethodTable()->IsSealed();
11304
11305         // Loop through the Attributes and look for the requested one
11306         mdCustomAttribute cv;
11307         while (pInternalImport->EnumNext(&hEnum, &cv))
11308         {
11309             //
11310             // fetch the ctor
11311             mdToken     tkCtor;
11312             IfFailThrow(pInternalImport->GetCustomAttributeProps(cv, &tkCtor));
11313
11314             mdToken tkType = TypeFromToken(tkCtor);
11315             if(tkType != mdtMemberRef && tkType != mdtMethodDef)
11316                 continue; // we only deal with the ctor case
11317
11318             //
11319             // get the info to load the type, so we can check whether the current
11320             // attribute is a subtype of the requested attribute
11321             IfFailThrow(pInternalImport->GetParentToken(tkCtor, &tkType));
11322
11323             _ASSERTE(TypeFromToken(tkType) == mdtTypeRef || TypeFromToken(tkType) == mdtTypeDef);
11324             // load the type
11325             if (isSealed)
11326             {
11327                 caTH=ClassLoader::LoadTypeDefOrRefThrowing(pModule, tkType,
11328                                                            ClassLoader::ReturnNullIfNotFound,
11329                                                            ClassLoader::FailIfUninstDefOrRef,
11330                                                            TypeFromToken(tkType) == mdtTypeDef ? tdAllTypes : tdNoTypes);
11331             }
11332             else
11333             {
11334                 caTH = ClassLoader::LoadTypeDefOrRefThrowing(pModule, tkType,
11335                                                              ClassLoader::ReturnNullIfNotFound,
11336                                                              ClassLoader::FailIfUninstDefOrRef);
11337             }
11338             if (caTH.IsNull())
11339                 continue;
11340
11341             // a null class implies all custom attribute
11342             if (!attributeClass.IsNull())
11343             {
11344                 if (isSealed)
11345                 {
11346                     if (attributeClass != caTH)
11347                         continue;
11348                 }
11349                 else
11350                 {
11351                     if (!caTH.CanCastTo(attributeClass))
11352                         continue;
11353                 }
11354             }
11355
11356             //
11357             // if we are here we got one
11358             isDefined = TRUE;
11359             break;
11360         }
11361     }
11362
11363     return isDefined;
11364 }
11365
11366 //*******************************************************************************
11367 VOID MethodTableBuilder::CheckForRemotingProxyAttrib()
11368 {
11369     STANDARD_VM_CONTRACT;
11370
11371 }
11372
11373
11374 //*******************************************************************************
11375 // Checks for a bunch of special interface names and if it matches then it sets
11376 // bmtProp->fIsMngStandardItf to TRUE. Additionally, it checks to see if the
11377 // type is an interface and if it has ComEventInterfaceAttribute custom attribute
11378 // set, then it sets bmtProp->fComEventItfType to true.
11379 //
11380 // NOTE: This only does anything when COM interop is enabled.
11381
11382 VOID MethodTableBuilder::CheckForSpecialTypes()
11383 {
11384 #ifdef FEATURE_COMINTEROP
11385     STANDARD_VM_CONTRACT;
11386
11387
11388     Module *pModule = GetModule();
11389     IMDInternalImport *pMDImport = pModule->GetMDImport();
11390
11391     // Check to see if this type is a managed standard interface. All the managed
11392     // standard interfaces live in CoreLib so checking for that first
11393     // makes the strcmp that comes afterwards acceptable.
11394     if (pModule->IsSystem())
11395     {
11396         if (IsInterface())
11397         {
11398             LPCUTF8 pszClassName;
11399             LPCUTF8 pszClassNamespace;
11400             if (FAILED(pMDImport->GetNameOfTypeDef(GetCl(), &pszClassName, &pszClassNamespace)))
11401             {
11402                 pszClassName = pszClassNamespace = NULL;
11403             }
11404             if ((pszClassName != NULL) && (pszClassNamespace != NULL))
11405             {
11406                 LPUTF8 pszFullyQualifiedName = NULL;
11407                 MAKE_FULLY_QUALIFIED_NAME(pszFullyQualifiedName, pszClassNamespace, pszClassName);
11408
11409                 // This is just to give us a scope to break out of.
11410                 do
11411                 {
11412
11413 #define MNGSTDITF_BEGIN_INTERFACE(FriendlyName, strMngItfName, strUCOMMngItfName, strCustomMarshalerName, strCustomMarshalerCookie, strManagedViewName, NativeItfIID, bCanCastOnNativeItfQI) \
11414                     if (strcmp(strMngItfName, pszFullyQualifiedName) == 0) \
11415                     { \
11416                         bmtProp->fIsMngStandardItf = true; \
11417                         break; \
11418                     }
11419
11420 #define MNGSTDITF_DEFINE_METH_IMPL(FriendlyName, ECallMethName, MethName, MethSig, FcallDecl)
11421
11422 #define MNGSTDITF_END_INTERFACE(FriendlyName)
11423
11424 #include "mngstditflist.h"
11425
11426 #undef MNGSTDITF_BEGIN_INTERFACE
11427 #undef MNGSTDITF_DEFINE_METH_IMPL
11428 #undef MNGSTDITF_END_INTERFACE
11429
11430                 } while (FALSE);
11431             }
11432         }
11433     }
11434
11435     // Check to see if the type is a COM event interface (classic COM interop only).
11436     if (IsInterface())
11437     {
11438         HRESULT hr = GetCustomAttribute(GetCl(), WellKnownAttribute::ComEventInterface, NULL, NULL);
11439         if (hr == S_OK)
11440         {
11441             bmtProp->fComEventItfType = true;
11442         }
11443     }
11444 #endif // FEATURE_COMINTEROP
11445 }
11446
11447 #ifdef FEATURE_READYTORUN
11448
11449 bool ModulesAreDistributedAsAnIndivisibleUnit(Module* module1, Module* module2)
11450 {
11451     if (module1 == module2)
11452         return true;
11453
11454     bool nativeImagesIdentical = false;
11455     if (module1->GetCompositeNativeImage() != NULL)
11456     {
11457         return module1->GetCompositeNativeImage() == module2->GetCompositeNativeImage();
11458     }
11459
11460     return false;
11461 }
11462
11463 //*******************************************************************************
11464 VOID MethodTableBuilder::CheckLayoutDependsOnOtherModules(MethodTable * pDependencyMT)
11465 {
11466     STANDARD_VM_CONTRACT;
11467
11468     // These cases are expected to be handled by the caller
11469     _ASSERTE(!(pDependencyMT == g_pObjectClass || pDependencyMT->IsTruePrimitive() || ((g_pEnumClass != NULL) && pDependencyMT->IsEnum())));
11470
11471     //
11472     // WARNING: Changes in this algorithm are potential ReadyToRun breaking changes !!!
11473     //
11474     // Track whether field layout of this type depend on information outside its containing module and compilation unit
11475     //
11476     // It is a stronger condition than MethodTable::IsInheritanceChainLayoutFixedInCurrentVersionBubble().
11477     // It has to remain fixed across versioning changes in the module dependencies. In particular, it does
11478     // not take into account NonVersionable attribute. Otherwise, adding NonVersionable attribute to existing
11479     // type would be ReadyToRun incompatible change.
11480     //
11481     bool modulesDefinedInSameDistributionUnit = ModulesAreDistributedAsAnIndivisibleUnit(pDependencyMT->GetModule(), GetModule());
11482     bool dependsOnOtherModules = !modulesDefinedInSameDistributionUnit || pDependencyMT->GetClass()->HasLayoutDependsOnOtherModules();
11483
11484     if (dependsOnOtherModules)
11485         GetHalfBakedClass()->SetHasLayoutDependsOnOtherModules();
11486 }
11487
11488 BOOL MethodTableBuilder::NeedsAlignedBaseOffset()
11489 {
11490     STANDARD_VM_CONTRACT;
11491
11492     //
11493     // WARNING: Changes in this algorithm are potential ReadyToRun breaking changes !!!
11494     //
11495     // This method returns whether the type needs aligned base offset in order to have layout resilient to
11496     // base class layout changes.
11497     //
11498     if (IsValueClass())
11499         return FALSE;
11500
11501     MethodTable * pParentMT = GetParentMethodTable();
11502
11503     // Trivial parents
11504     if (pParentMT == NULL || pParentMT == g_pObjectClass)
11505         return FALSE;
11506
11507     // Always use the ReadyToRun field layout algorithm if the source IL image was ReadyToRun, independent on
11508     // whether ReadyToRun is actually enabled for the module. It is required to allow mixing and matching
11509     // ReadyToRun images with and without input bubble enabled.
11510     if (!GetModule()->GetPEAssembly()->IsReadyToRun())
11511     {
11512         // Always use ReadyToRun field layout algorithm to produce ReadyToRun images
11513         return FALSE;
11514     }
11515
11516     if (!ModulesAreDistributedAsAnIndivisibleUnit(GetModule(), pParentMT->GetModule()) ||
11517         pParentMT->GetClass()->HasLayoutDependsOnOtherModules())
11518     {
11519         return TRUE;
11520     }
11521
11522     return FALSE;
11523 }
11524 #endif // FEATURE_READYTORUN
11525
11526 //*******************************************************************************
11527 //
11528 // Used by BuildMethodTable
11529 //
11530 // Set the HasFinalizer and HasCriticalFinalizer flags
11531 //
11532 VOID MethodTableBuilder::SetFinalizationSemantics()
11533 {
11534     STANDARD_VM_CONTRACT;
11535
11536     if (g_pObjectFinalizerMD && !IsInterface() && !IsValueClass())
11537     {
11538         WORD slot = g_pObjectFinalizerMD->GetSlot();
11539
11540         // Objects not derived from Object will get marked as having a finalizer, if they have
11541         // sufficient virtual methods.  This will only be an issue if they can be allocated
11542         // in the GC heap (which will cause all sorts of other problems).
11543         if (slot < bmtVT->cVirtualSlots && (*bmtVT)[slot].Impl().GetMethodDesc() != g_pObjectFinalizerMD)
11544         {
11545             GetHalfBakedMethodTable()->SetHasFinalizer();
11546
11547             // The need for a critical finalizer can be inherited from a parent.
11548             // Since we set this automatically for CriticalFinalizerObject
11549             // elsewhere, the code below is the means by which any derived class
11550             // picks up the attribute.
11551             if (HasParent() && GetParentMethodTable()->HasCriticalFinalizer())
11552             {
11553                 GetHalfBakedMethodTable()->SetHasCriticalFinalizer();
11554             }
11555         }
11556     }
11557 }
11558
11559 //*******************************************************************************
11560 //
11561 // Used by BuildMethodTable
11562 //
11563 // Perform relevant GC calculations for value classes
11564 //
11565 VOID MethodTableBuilder::HandleGCForValueClasses(MethodTable ** pByValueClassCache)
11566 {
11567     STANDARD_VM_CONTRACT;
11568
11569     DWORD i;
11570
11571     EEClass *pClass = GetHalfBakedClass();
11572     MethodTable *pMT = GetHalfBakedMethodTable();
11573
11574     FieldDesc *pFieldDescList = pClass->GetFieldDescList();
11575
11576     // Note that for value classes, the following calculation is only appropriate
11577     // when the instance is in its "boxed" state.
11578     if (bmtFP->NumGCPointerSeries != 0)
11579     {
11580         CGCDescSeries *pSeries;
11581         CGCDescSeries *pHighest;
11582
11583         pMT->SetContainsPointers();
11584
11585         CGCDesc::Init( (PVOID) pMT, bmtFP->NumGCPointerSeries );
11586
11587         // special case when all instance fields are objects - we can encode that as one serie.
11588         if (bmtFP->fIsAllGCPointers)
11589         {
11590             _ASSERTE(bmtFP->NumGCPointerSeries == 1);
11591
11592             CGCDescSeries* pSeries = CGCDesc::GetCGCDescFromMT(pMT)->GetHighestSeries();
11593
11594             // the data is right after the method table ptr
11595             int offsetToData = TARGET_POINTER_SIZE;
11596
11597             // Set the size as the negative of the BaseSize (the GC always adds the total
11598             // size of the object, so what you end up with is the size of the data portion of the instance)
11599             pSeries->SetSeriesSize(-(SSIZE_T)(offsetToData + TARGET_POINTER_SIZE));
11600             pSeries->SetSeriesOffset(offsetToData);
11601
11602             return;
11603         }
11604
11605         // Copy the pointer series map from the parent
11606         if (bmtParent->NumParentPointerSeries != 0)
11607         {
11608             size_t ParentGCSize = CGCDesc::ComputeSize(bmtParent->NumParentPointerSeries);
11609             memcpy( (PVOID) (((BYTE*) pMT) - ParentGCSize),
11610                     (PVOID) (((BYTE*) GetParentMethodTable()) - ParentGCSize),
11611                     ParentGCSize - sizeof(size_t)   // sizeof(size_t) is the NumSeries count
11612                   );
11613
11614         }
11615
11616         DWORD repeat = 1;
11617         if (bmtFP->NumInlineArrayElements > 1)
11618         {
11619             repeat = bmtFP->NumInlineArrayElements;
11620         }
11621
11622         // Build the pointer series map for pointers in this instance
11623         pSeries = ((CGCDesc*)pMT)->GetLowestSeries();
11624         if (bmtFP->NumInstanceGCPointerFields)
11625         {
11626             // See gcdesc.h for an explanation of why we adjust by subtracting BaseSize
11627             pSeries->SetSeriesSize((size_t)(bmtFP->NumInstanceGCPointerFields * repeat * TARGET_POINTER_SIZE) - (size_t)pMT->GetBaseSize());
11628             pSeries->SetSeriesOffset(bmtFP->GCPointerFieldStart + OBJECT_SIZE);
11629             pSeries++;
11630         }
11631
11632         // Insert GC info for fields which are by-value classes
11633         for (i = 0; i < bmtEnumFields->dwNumInstanceFields; i++)
11634         {
11635             if (pFieldDescList[i].IsByValue())
11636             {
11637                 MethodTable* pByValueMT = pByValueClassCache[i];
11638
11639                 if (pByValueMT->ContainsPointers())
11640                 {
11641                     // Offset of the by value class in the class we are building, does NOT include Object
11642                     DWORD       dwCurrentOffset = pFieldDescList[i].GetOffset();
11643                     DWORD       dwElementSize = pByValueMT->GetBaseSize() - OBJECT_BASESIZE;
11644
11645                     // if we have an inline array, we will have only one formal instance field,
11646                     // but will have to replicate the layout "repeat" times.
11647                     for (DWORD r = 0; r < repeat; r++)
11648                     {
11649                         // The by value class may have more than one pointer series
11650                         CGCDescSeries* pByValueSeries = CGCDesc::GetCGCDescFromMT(pByValueMT)->GetLowestSeries();
11651                         SIZE_T dwNumByValueSeries = CGCDesc::GetCGCDescFromMT(pByValueMT)->GetNumSeries();
11652
11653                         for (SIZE_T j = 0; j < dwNumByValueSeries; j++)
11654                         {
11655                             size_t cbSeriesSize;
11656                             size_t cbSeriesOffset;
11657
11658                             _ASSERTE(pSeries <= CGCDesc::GetCGCDescFromMT(pMT)->GetHighestSeries());
11659
11660                             cbSeriesSize = pByValueSeries->GetSeriesSize();
11661
11662                             // Add back the base size of the by value class, since it's being transplanted to this class
11663                             cbSeriesSize += pByValueMT->GetBaseSize();
11664
11665                             // Subtract the base size of the class we're building
11666                             cbSeriesSize -= pMT->GetBaseSize();
11667
11668                             // Set current series we're building
11669                             pSeries->SetSeriesSize(cbSeriesSize);
11670
11671                             // Get offset into the value class of the first pointer field (includes a +Object)
11672                             cbSeriesOffset = pByValueSeries->GetSeriesOffset();
11673
11674                             // Add element N offset
11675                             cbSeriesOffset += r * dwElementSize;
11676
11677                             // Add it to the offset of the by value class in our class
11678                             cbSeriesOffset += dwCurrentOffset;
11679
11680                             pSeries->SetSeriesOffset(cbSeriesOffset); // Offset of field
11681                             pSeries++;
11682                             pByValueSeries++;
11683                         }
11684                     }
11685                 }
11686             }
11687         }
11688
11689         // Adjust the inherited series - since the base size has increased by "# new field instance bytes", we need to
11690         // subtract that from all the series (since the series always has BaseSize subtracted for it - see gcdesc.h)
11691         pHighest = CGCDesc::GetCGCDescFromMT(pMT)->GetHighestSeries();
11692         while (pSeries <= pHighest)
11693         {
11694             CONSISTENCY_CHECK(CheckPointer(GetParentMethodTable()));
11695             pSeries->SetSeriesSize( pSeries->GetSeriesSize() - ((size_t) pMT->GetBaseSize() - (size_t) GetParentMethodTable()->GetBaseSize()) );
11696             pSeries++;
11697         }
11698
11699         _ASSERTE(pSeries-1 <= CGCDesc::GetCGCDescFromMT(pMT)->GetHighestSeries());
11700     }
11701
11702 }
11703
11704 //*******************************************************************************
11705 //
11706 // Used by BuildMethodTable
11707 //
11708 // Check for the presence of type equivalence. If present, make sure
11709 // it is permitted to be on this type.
11710 //
11711
11712 void MethodTableBuilder::CheckForTypeEquivalence(
11713     WORD                     cBuildingInterfaceList,
11714     BuildingInterfaceInfo_t *pBuildingInterfaceList)
11715 {
11716     STANDARD_VM_CONTRACT;
11717
11718 #ifdef FEATURE_TYPEEQUIVALENCE
11719     bmtProp->fIsTypeEquivalent = !!IsTypeDefEquivalent(GetCl(), GetModule());
11720
11721     if (bmtProp->fIsTypeEquivalent)
11722     {
11723         BOOL comImportOrEventInterface = IsComImport();
11724 #ifdef FEATURE_COMINTEROP
11725         comImportOrEventInterface = comImportOrEventInterface || bmtProp->fComEventItfType;
11726 #endif // FEATURE_COMINTEROP
11727
11728         BOOL fTypeEquivalentNotPermittedDueToType = !((comImportOrEventInterface && IsInterface()) || IsValueClass() || IsDelegate());
11729         BOOL fTypeEquivalentNotPermittedDueToGenerics = bmtGenerics->HasInstantiation();
11730
11731         if (fTypeEquivalentNotPermittedDueToType || fTypeEquivalentNotPermittedDueToGenerics)
11732         {
11733             BuildMethodTableThrowException(IDS_CLASSLOAD_EQUIVALENTBADTYPE);
11734         }
11735
11736         GetHalfBakedClass()->SetIsEquivalentType();
11737     }
11738
11739     bmtProp->fHasTypeEquivalence = bmtProp->fIsTypeEquivalent;
11740
11741     if (!bmtProp->fHasTypeEquivalence)
11742     {
11743         // fHasTypeEquivalence flag is inherited from interfaces so we can quickly detect
11744         // types that implement type equivalent interfaces
11745         for (WORD i = 0; i < cBuildingInterfaceList; i++)
11746         {
11747             MethodTable *pItfMT = pBuildingInterfaceList[i].m_pMethodTable;
11748             if (pItfMT->HasTypeEquivalence())
11749             {
11750                 bmtProp->fHasTypeEquivalence = true;
11751                 break;
11752             }
11753         }
11754     }
11755
11756     if (!bmtProp->fHasTypeEquivalence)
11757     {
11758         // fHasTypeEquivalence flag is "inherited" from generic arguments so we can quickly detect
11759         // types like List<Str> where Str is a structure with the TypeIdentifierAttribute.
11760         if (bmtGenerics->HasInstantiation() && !bmtGenerics->IsTypicalTypeDefinition())
11761         {
11762             Instantiation inst = bmtGenerics->GetInstantiation();
11763             for (DWORD i = 0; i < inst.GetNumArgs(); i++)
11764             {
11765                 if (inst[i].HasTypeEquivalence())
11766                 {
11767                     bmtProp->fHasTypeEquivalence = true;
11768                     break;
11769                 }
11770             }
11771         }
11772     }
11773 #endif //FEATURE_TYPEEQUIVALENCE
11774 }
11775
11776 //*******************************************************************************
11777 //
11778 // Used by BuildMethodTable
11779 //
11780 // Before we make the final leap, make sure we've allocated all memory needed to
11781 // fill out the RID maps.
11782 //
11783 VOID MethodTableBuilder::EnsureRIDMapsCanBeFilled()
11784 {
11785     STANDARD_VM_CONTRACT;
11786
11787
11788     DWORD i;
11789
11790
11791     // Rather than call Ensure***CanBeStored() hundreds of times, we
11792     // will call it once on the largest token we find. This relies
11793     // on an invariant that RidMaps don't use some kind of sparse
11794     // allocation.
11795
11796     {
11797         mdMethodDef largest = mdMethodDefNil;
11798
11799         DeclaredMethodIterator it(*this);
11800         while (it.Next())
11801         {
11802             if (it.Token() > largest)
11803             {
11804                 largest = it.Token();
11805             }
11806         }
11807         if ( largest != mdMethodDefNil )
11808         {
11809             GetModule()->EnsureMethodDefCanBeStored(largest);
11810         }
11811     }
11812
11813     {
11814         mdFieldDef largest = mdFieldDefNil;
11815
11816         for (i = 0; i < bmtMetaData->cFields; i++)
11817         {
11818             if (bmtMetaData->pFields[i] > largest)
11819             {
11820                 largest = bmtMetaData->pFields[i];
11821             }
11822         }
11823         if ( largest != mdFieldDefNil )
11824         {
11825             GetModule()->EnsureFieldDefCanBeStored(largest);
11826         }
11827     }
11828 }
11829
11830 #ifdef FEATURE_COMINTEROP
11831 //*******************************************************************************
11832 void MethodTableBuilder::GetCoClassAttribInfo()
11833 {
11834     STANDARD_VM_CONTRACT;
11835     // Retrieve the CoClassAttribute CA.
11836     HRESULT hr = GetCustomAttribute(GetCl(), WellKnownAttribute::CoClass, NULL, NULL);
11837     if (hr == S_OK)
11838     {
11839         // COM class interfaces may lazily populate the m_pCoClassForIntf field of EEClass. This field is
11840         // optional so we must ensure the optional field descriptor has been allocated.
11841         EnsureOptionalFieldsAreAllocated(GetHalfBakedClass(), m_pAllocMemTracker, GetLoaderAllocator()->GetLowFrequencyHeap());
11842         SetIsComClassInterface();
11843     }
11844 }
11845 #endif // FEATURE_COMINTEROP
11846
11847 //*******************************************************************************
11848 void MethodTableBuilder::bmtMethodImplInfo::AddMethodImpl(
11849     bmtMDMethod * pImplMethod, bmtMethodHandle declMethod, mdToken declToken,
11850     StackingAllocator * pStackingAllocator)
11851 {
11852     STANDARD_VM_CONTRACT;
11853
11854     CONSISTENCY_CHECK(CheckPointer(pImplMethod));
11855     CONSISTENCY_CHECK(!declMethod.IsNull());
11856     if (pIndex >= cMaxIndex)
11857     {
11858         DWORD newEntriesCount = 0;
11859
11860         if (!ClrSafeInt<DWORD>::multiply(cMaxIndex, 2, newEntriesCount))
11861             ThrowHR(COR_E_OVERFLOW);
11862
11863         if (newEntriesCount == 0)
11864             newEntriesCount = 10;
11865
11866         // If we have to grow this array, we will not free the old array before we clean up the BuildMethodTable operation
11867         // because this is a stacking allocator. However, the old array will get freed when all the stack allocator is freed.
11868         Entry *rgEntriesNew = new (pStackingAllocator) Entry[newEntriesCount];
11869         if (cMaxIndex > 0)
11870             memcpy((void*)rgEntriesNew, rgEntries, sizeof(Entry) * cMaxIndex);
11871
11872         // Start using newly allocated array.
11873         rgEntries = rgEntriesNew;
11874         cMaxIndex = newEntriesCount;
11875     }
11876     rgEntries[pIndex++] = Entry(pImplMethod, declMethod, declToken);
11877 }
11878
11879 //*******************************************************************************
11880 // Returns TRUE if tok acts as a body for any methodImpl entry. FALSE, otherwise.
11881 BOOL MethodTableBuilder::bmtMethodImplInfo::IsBody(mdToken tok)
11882 {
11883     LIMITED_METHOD_CONTRACT;
11884     CONSISTENCY_CHECK(TypeFromToken(tok) == mdtMethodDef);
11885     for (DWORD i = 0; i < pIndex; i++)
11886     {
11887         if (GetBodyMethodDesc(i)->GetMemberDef() == tok)
11888         {
11889             return TRUE;
11890         }
11891     }
11892     return FALSE;
11893 }
11894
11895 //*******************************************************************************
11896 BYTE *
11897 MethodTableBuilder::AllocateFromHighFrequencyHeap(S_SIZE_T cbMem)
11898 {
11899     CONTRACTL
11900     {
11901         THROWS;
11902         GC_NOTRIGGER;
11903         MODE_ANY;
11904     }
11905     CONTRACTL_END;
11906     return (BYTE *)GetMemTracker()->Track(
11907         GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem(cbMem));
11908 }
11909
11910 //*******************************************************************************
11911 BYTE *
11912 MethodTableBuilder::AllocateFromLowFrequencyHeap(S_SIZE_T cbMem)
11913 {
11914     CONTRACTL
11915     {
11916         THROWS;
11917         GC_NOTRIGGER;
11918         MODE_ANY;
11919     }
11920     CONTRACTL_END;
11921     return (BYTE *)GetMemTracker()->Track(
11922         GetLoaderAllocator()->GetLowFrequencyHeap()->AllocMem(cbMem));
11923 }
11924
11925 //-------------------------------------------------------------------------------
11926 // Make best-case effort to obtain an image name for use in an error message.
11927 //
11928 // This routine must expect to be called before the this object is fully loaded.
11929 // It can return an empty if the name isn't available or the object isn't initialized
11930 // enough to get a name, but it mustn't crash.
11931 //-------------------------------------------------------------------------------
11932 LPCWSTR MethodTableBuilder::GetPathForErrorMessages()
11933 {
11934     STANDARD_VM_CONTRACT;
11935
11936     return GetModule()->GetPathForErrorMessages();
11937 }
11938
11939 BOOL MethodTableBuilder::ChangesImplementationOfVirtualSlot(SLOT_INDEX idx)
11940 {
11941     STANDARD_VM_CONTRACT;
11942
11943     BOOL fChangesImplementation = TRUE;
11944
11945     _ASSERTE(idx < bmtVT->cVirtualSlots);
11946
11947     if (HasParent() && idx < GetParentMethodTable()->GetNumVirtuals())
11948     {
11949         _ASSERTE(idx < bmtParent->pSlotTable->GetSlotCount());
11950         bmtMethodHandle VTImpl = (*bmtVT)[idx].Impl();
11951         bmtMethodHandle ParentImpl = (*bmtParent)[idx].Impl();
11952
11953         fChangesImplementation = VTImpl != ParentImpl;
11954
11955         // See code:MethodTableBuilder::SetupMethodTable2 and its logic
11956         // for handling MethodImpl's on parent classes which affect non interface
11957         // methods.
11958         if (!fChangesImplementation && (ParentImpl.GetSlotIndex() != idx))
11959             fChangesImplementation = TRUE;
11960
11961         // If the current vtable slot is MethodImpl, is it possible that it will be updated by
11962         // the ClassLoader::PropagateCovariantReturnMethodImplSlots.
11963         if (!fChangesImplementation && VTImpl.GetMethodDesc()->IsMethodImpl())
11964         {
11965             // Note: to know exactly whether the slot will be updated or not, we would need to check the
11966             // PreserveBaseOverridesAttribute presence on the current vtable slot and in the worst case
11967             // on all of its ancestors. This is expensive, so we don't do that check here and accept
11968             // the fact that we get some false positives and end up sharing less vtable chunks.
11969
11970             // Search the previous slots in the parent vtable for the same implementation. If it exists and it was
11971             // overridden, the ClassLoader::PropagateCovariantReturnMethodImplSlots will propagate the change to the current
11972             // slot (idx), so the implementation of it will change.
11973             MethodDesc* pParentMD = ParentImpl.GetMethodDesc();
11974             for (SLOT_INDEX i = 0; i < idx; i++)
11975             {
11976                 if ((*bmtParent)[i].Impl().GetMethodDesc() == pParentMD && (*bmtVT)[i].Impl().GetMethodDesc() != pParentMD)
11977                 {
11978                     fChangesImplementation = TRUE;
11979                     break;
11980                 }
11981             }
11982         }
11983     }
11984
11985     return fChangesImplementation;
11986 }
11987
11988 // Must be called prior to setting the value of any optional field on EEClass (on a debug build an assert will
11989 // fire if this invariant is violated).
11990 void MethodTableBuilder::EnsureOptionalFieldsAreAllocated(EEClass *pClass, AllocMemTracker *pamTracker, LoaderHeap *pHeap)
11991 {
11992     STANDARD_VM_CONTRACT;
11993
11994     if (pClass->HasOptionalFields())
11995         return;
11996
11997     EEClassOptionalFields *pOptFields = (EEClassOptionalFields*)
11998         pamTracker->Track(pHeap->AllocMem(S_SIZE_T(sizeof(EEClassOptionalFields))));
11999
12000     // Initialize default values for all optional fields.
12001     pOptFields->Init();
12002
12003     // Attach optional fields to the class.
12004     pClass->AttachOptionalFields(pOptFields);
12005 }
12006
12007 //---------------------------------------------------------------------------------------
12008 //
12009 // Gather information about a generic type
12010 // - number of parameters
12011 // - variance annotations
12012 // - dictionaries
12013 // - sharability
12014 //
12015 //static
12016 void
12017 MethodTableBuilder::GatherGenericsInfo(
12018     Module *          pModule,
12019     mdTypeDef         cl,
12020     Instantiation     inst,
12021     bmtGenericsInfo * bmtGenericsInfo,
12022     StackingAllocator*pStackingAllocator)
12023 {
12024     CONTRACTL
12025     {
12026         STANDARD_VM_CHECK;
12027         PRECONDITION(GetThreadNULLOk() != NULL);
12028         PRECONDITION(CheckPointer(pModule));
12029         PRECONDITION(CheckPointer(bmtGenericsInfo));
12030     }
12031     CONTRACTL_END;
12032
12033     IMDInternalImport * pInternalImport = pModule->GetMDImport();
12034
12035     // Enumerate the formal type parameters
12036     DWORD numGenericArgs = pModule->m_pTypeGenericInfoMap->GetGenericArgumentCount(cl, pInternalImport);
12037
12038     // Work out what kind of EEClass we're creating w.r.t. generics.  If there
12039     // are no generics involved this will be a VMFLAG_NONGENERIC.
12040     BOOL fHasVariance = FALSE;
12041     if (numGenericArgs > 0)
12042     {
12043         // Generic type verification
12044         {
12045             DWORD   dwAttr;
12046             mdToken tkParent;
12047             if (FAILED(pInternalImport->GetTypeDefProps(cl, &dwAttr, &tkParent)))
12048             {
12049                 pModule->GetAssembly()->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12050             }
12051             // A generic with explicit layout is not allowed.
12052             if (IsTdExplicitLayout(dwAttr))
12053             {
12054                 pModule->GetAssembly()->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_EXPLICIT_GENERIC);
12055             }
12056         }
12057
12058         bmtGenericsInfo->numDicts = 1;
12059
12060         mdGenericParam tkTyPar;
12061         bmtGenericsInfo->pVarianceInfo = new (pStackingAllocator) BYTE[numGenericArgs];
12062
12063         // If it has generic arguments but none have been specified, then load the instantiation at the formals
12064         if (inst.IsEmpty())
12065         {
12066             bmtGenericsInfo->fTypicalInstantiation = TRUE;
12067             S_UINT32 scbAllocSize = S_UINT32(numGenericArgs) * S_UINT32(sizeof(TypeHandle));
12068             TypeHandle * genericArgs = (TypeHandle *) pStackingAllocator->Alloc(scbAllocSize);
12069
12070             inst = Instantiation(genericArgs, numGenericArgs);
12071
12072             bmtGenericsInfo->fSharedByGenericInstantiations = FALSE;
12073         }
12074         else
12075         {
12076             bmtGenericsInfo->fTypicalInstantiation = FALSE;
12077
12078             bmtGenericsInfo->fSharedByGenericInstantiations = TypeHandle::IsCanonicalSubtypeInstantiation(inst);
12079             _ASSERTE(bmtGenericsInfo->fSharedByGenericInstantiations == ClassLoader::IsSharableInstantiation(inst));
12080
12081 #ifdef _DEBUG
12082             // Set typical instantiation MethodTable
12083             {
12084                 MethodTable * pTypicalInstantiationMT = pModule->LookupTypeDef(cl).AsMethodTable();
12085                 // Typical instantiation was already loaded by code:ClassLoader::LoadApproxTypeThrowing
12086                 _ASSERTE(pTypicalInstantiationMT != NULL);
12087                 bmtGenericsInfo->dbg_pTypicalInstantiationMT = pTypicalInstantiationMT;
12088             }
12089 #endif //_DEBUG
12090         }
12091
12092         TypeHandle * pDestInst = (TypeHandle *)inst.GetRawArgs();
12093         {
12094             HENUMInternal   hEnumGenericPars;
12095             HRESULT hr = pInternalImport->EnumInit(mdtGenericParam, cl, &hEnumGenericPars);
12096             if (FAILED(hr))
12097                 pModule->GetAssembly()->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12098
12099             // Protect multi-threaded access to Module.m_GenericParamToDescMap. Other threads may be loading the same type
12100             // to break type recursion dead-locks
12101             CrstHolder ch(&pModule->GetClassLoader()->m_AvailableTypesLock);
12102
12103             for (unsigned int i = 0; i < numGenericArgs; i++)
12104             {
12105                 pInternalImport->EnumNext(&hEnumGenericPars, &tkTyPar);
12106                 DWORD flags;
12107                 if (FAILED(pInternalImport->GetGenericParamProps(tkTyPar, NULL, &flags, NULL, NULL, NULL)))
12108                 {
12109                     pModule->GetAssembly()->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12110                 }
12111
12112                 if (bmtGenericsInfo->fTypicalInstantiation)
12113                 {
12114                     // code:Module.m_GenericParamToDescMap maps generic parameter RIDs to TypeVarTypeDesc
12115                     // instances so that we do not leak by allocating them all over again, if the type
12116                     // repeatedly fails to load.
12117                     TypeVarTypeDesc* pTypeVarTypeDesc = pModule->LookupGenericParam(tkTyPar);
12118                     if (pTypeVarTypeDesc == NULL)
12119                     {
12120                         // Do NOT use the alloc tracker for this memory as we need it stay allocated even if the load fails.
12121                         void* mem = (void*)pModule->GetLoaderAllocator()->GetLowFrequencyHeap()->AllocMem(S_SIZE_T(sizeof(TypeVarTypeDesc)));
12122                         pTypeVarTypeDesc = new (mem) TypeVarTypeDesc(pModule, cl, i, tkTyPar);
12123
12124                         pModule->StoreGenericParamThrowing(tkTyPar, pTypeVarTypeDesc);
12125                     }
12126                     pDestInst[i] = TypeHandle(pTypeVarTypeDesc);
12127                 }
12128
12129                 DWORD varianceAnnotation = flags & gpVarianceMask;
12130                 bmtGenericsInfo->pVarianceInfo[i] = static_cast<BYTE>(varianceAnnotation);
12131                 if (varianceAnnotation != gpNonVariant)
12132                 {
12133                     if (varianceAnnotation != gpContravariant && varianceAnnotation != gpCovariant)
12134                     {
12135                         pModule->GetAssembly()->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADVARIANCE);
12136                     }
12137                     else
12138                     {
12139                         fHasVariance = TRUE;
12140                     }
12141                 }
12142             }
12143         }
12144
12145         if (!fHasVariance)
12146             bmtGenericsInfo->pVarianceInfo = NULL;
12147     }
12148     else
12149     {
12150         bmtGenericsInfo->fTypicalInstantiation = FALSE;
12151         bmtGenericsInfo->fSharedByGenericInstantiations = FALSE;
12152         bmtGenericsInfo->numDicts = 0;
12153     }
12154
12155     bmtGenericsInfo->fContainsGenericVariables = MethodTable::ComputeContainsGenericVariables(inst);
12156
12157     SigTypeContext typeContext(inst, Instantiation());
12158     bmtGenericsInfo->typeContext = typeContext;
12159 } // MethodTableBuilder::GatherGenericsInfo
12160
12161 //=======================================================================
12162 // This is invoked from the class loader while building the internal structures for a type
12163 // This function should check if explicit layout metadata exists.
12164 //
12165 // Returns:
12166 //  TRUE    - yes, there's layout metadata
12167 //  FALSE   - no, there's no layout.
12168 //  fail    - throws a typeload exception
12169 //
12170 // If TRUE,
12171 //   *pNLType            gets set to nltAnsi or nltUnicode
12172 //   *pPackingSize       declared packing size
12173 //   *pfExplicitoffsets  offsets explicit in metadata or computed?
12174 //=======================================================================
12175 BOOL HasLayoutMetadata(Assembly* pAssembly, IMDInternalImport* pInternalImport, mdTypeDef cl, MethodTable* pParentMT, BYTE* pPackingSize, BYTE* pNLTType, BOOL* pfExplicitOffsets)
12176 {
12177     CONTRACTL
12178     {
12179         THROWS;
12180         GC_TRIGGERS;
12181         MODE_ANY;
12182         PRECONDITION(CheckPointer(pInternalImport));
12183         PRECONDITION(CheckPointer(pPackingSize));
12184         PRECONDITION(CheckPointer(pNLTType));
12185         PRECONDITION(CheckPointer(pfExplicitOffsets));
12186     }
12187     CONTRACTL_END;
12188
12189     HRESULT hr;
12190     ULONG clFlags;
12191     if (FAILED(pInternalImport->GetTypeDefProps(cl, &clFlags, NULL)))
12192     {
12193         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12194     }
12195
12196     if (IsTdAutoLayout(clFlags))
12197     {
12198         return FALSE;
12199     }
12200     else if (IsTdSequentialLayout(clFlags))
12201     {
12202         *pfExplicitOffsets = FALSE;
12203     }
12204     else if (IsTdExplicitLayout(clFlags))
12205     {
12206         *pfExplicitOffsets = TRUE;
12207     }
12208     else
12209     {
12210         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12211     }
12212
12213     // We now know this class has seq. or explicit layout. Ensure the parent does too.
12214     if (pParentMT && !(pParentMT->IsObjectClass() || pParentMT->IsValueTypeClass()) && !(pParentMT->HasLayout()))
12215         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12216
12217     if (IsTdAnsiClass(clFlags))
12218     {
12219         *pNLTType = nltAnsi;
12220     }
12221     else if (IsTdUnicodeClass(clFlags))
12222     {
12223         *pNLTType = nltUnicode;
12224     }
12225     else if (IsTdAutoClass(clFlags))
12226     {
12227 #ifdef TARGET_WINDOWS
12228         *pNLTType = nltUnicode;
12229 #else
12230         *pNLTType = nltAnsi; // We don't have a utf8 charset in metadata yet, but ANSI == UTF-8 off-Windows
12231 #endif
12232     }
12233     else
12234     {
12235         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12236     }
12237
12238     DWORD dwPackSize;
12239     hr = pInternalImport->GetClassPackSize(cl, &dwPackSize);
12240     if (FAILED(hr) || dwPackSize == 0)
12241         dwPackSize = DEFAULT_PACKING_SIZE;
12242
12243     // This has to be reduced to a BYTE value, so we had better make sure it fits. If
12244     // not, we'll throw an exception instead of trying to munge the value to what we
12245     // think the user might want.
12246     if (!FitsInU1((UINT64)(dwPackSize)))
12247     {
12248         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12249     }
12250
12251     *pPackingSize = (BYTE)dwPackSize;
12252
12253     return TRUE;
12254 }
12255
12256 //---------------------------------------------------------------------------------------
12257 //
12258 // This service is called for normal classes -- and for the pseudo class we invent to
12259 // hold the module's public members.
12260 //
12261 //static
12262 TypeHandle
12263 ClassLoader::CreateTypeHandleForTypeDefThrowing(
12264     Module *          pModule,
12265     mdTypeDef         cl,
12266     Instantiation     inst,
12267     AllocMemTracker * pamTracker)
12268 {
12269     CONTRACT(TypeHandle)
12270     {
12271         STANDARD_VM_CHECK;
12272         PRECONDITION(GetThreadNULLOk() != NULL);
12273         PRECONDITION(CheckPointer(pModule));
12274         POSTCONDITION(!RETVAL.IsNull());
12275         POSTCONDITION(CheckPointer(RETVAL.GetMethodTable()));
12276     }
12277     CONTRACT_END;
12278
12279     MethodTable * pMT = NULL;
12280
12281     MethodTable * pParentMethodTable = NULL;
12282     SigPointer    parentInst;
12283     mdTypeDef     tdEnclosing = mdTypeDefNil;
12284     DWORD         cInterfaces;
12285     BuildingInterfaceInfo_t * pInterfaceBuildInfo = NULL;
12286     IMDInternalImport *       pInternalImport = NULL;
12287     LayoutRawFieldInfo *      pLayoutRawFieldInfos = NULL;
12288     MethodTableBuilder::bmtGenericsInfo genericsInfo;
12289
12290     Assembly * pAssembly = pModule->GetAssembly();
12291     pInternalImport = pModule->GetMDImport();
12292
12293     if (TypeFromToken(cl) != mdtTypeDef || !pInternalImport->IsValidToken(cl))
12294     {
12295         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12296     }
12297
12298     // GetCheckpoint for the thread-based allocator
12299     // This checkpoint provides a scope for all transient allocations of data structures
12300     // used during class loading.
12301     // <NICE> Ideally a debug/checked build should pass around tokens indicating the Checkpoint
12302     // being used and check these dynamically </NICE>
12303     ACQUIRE_STACKING_ALLOCATOR(pStackingAllocator);
12304
12305     // Gather up generics info
12306     MethodTableBuilder::GatherGenericsInfo(pModule, cl, inst, &genericsInfo, pStackingAllocator);
12307
12308     Module * pLoaderModule = pModule;
12309     if (!inst.IsEmpty())
12310     {
12311         pLoaderModule = ClassLoader::ComputeLoaderModuleWorker(
12312             pModule,
12313             cl,
12314             inst,
12315             Instantiation());
12316         pLoaderModule->GetLoaderAllocator()->EnsureInstantiation(pModule, inst);
12317     }
12318
12319     LoaderAllocator * pAllocator = pLoaderModule->GetLoaderAllocator();
12320
12321     {
12322         // As this is loading a parent type, we are allowed to override the load type limit.
12323         OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOAD_APPROXPARENTS);
12324         pParentMethodTable = LoadApproxParentThrowing(pModule, cl, &parentInst, &genericsInfo.typeContext);
12325     }
12326
12327     if (pParentMethodTable != NULL)
12328     {
12329         // Since methods on System.Array assume the layout of arrays, we can not allow
12330         // subclassing of arrays, it is sealed from the users point of view.
12331         // Value types and enums should be sealed - disable inheritting from them (we cannot require sealed
12332         // flag because of AppCompat)
12333         if (pParentMethodTable->IsSealed() ||
12334             (pParentMethodTable == g_pArrayClass) ||
12335             pParentMethodTable->IsValueType())
12336         {
12337             pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_SEALEDPARENT);
12338         }
12339
12340         DWORD dwTotalDicts = genericsInfo.numDicts + pParentMethodTable->GetNumDicts();
12341         if (!FitsIn<WORD>(dwTotalDicts))
12342         {
12343             pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_TOOMANYGENERICARGS);
12344         }
12345         genericsInfo.numDicts = static_cast<WORD>(dwTotalDicts);
12346     }
12347
12348     GetEnclosingClassThrowing(pInternalImport, pModule, cl, &tdEnclosing);
12349
12350     BYTE nstructPackingSize = 0, nstructNLT = 0;
12351     BOOL fExplicitOffsets = FALSE;
12352     // NOTE: HasLayoutMetadata does not load classes
12353     BOOL fHasLayout =
12354         !genericsInfo.fContainsGenericVariables &&
12355         HasLayoutMetadata(
12356             pModule->GetAssembly(),
12357             pInternalImport,
12358             cl,
12359             pParentMethodTable,
12360             &nstructPackingSize,
12361             &nstructNLT,
12362             &fExplicitOffsets);
12363
12364     BOOL fIsEnum = ((g_pEnumClass != NULL) && (pParentMethodTable == g_pEnumClass));
12365
12366     // enums may not have layout because they derive from g_pEnumClass and that has no layout
12367     // this is enforced by HasLayoutMetadata above
12368     _ASSERTE(!(fIsEnum && fHasLayout));
12369
12370     // This is a delegate class if it derives from MulticastDelegate (we do not allow single cast delegates)
12371     BOOL fIsDelegate = pParentMethodTable && pParentMethodTable == g_pMulticastDelegateClass;
12372
12373     // Create a EEClass entry for it, filling out a few fields, such as the parent class token
12374     // (and the generic type should we be creating an instantiation)
12375     EEClass * pClass = MethodTableBuilder::CreateClass(
12376         pModule,
12377         cl,
12378         fHasLayout,
12379         fIsDelegate,
12380         fIsEnum,
12381         &genericsInfo,
12382         pAllocator,
12383         pamTracker);
12384
12385     if ((pParentMethodTable != NULL) && (pParentMethodTable == g_pDelegateClass))
12386     {
12387         // Note we do not allow single cast delegates
12388         if (pModule->GetAssembly() != SystemDomain::SystemAssembly())
12389         {
12390             pAssembly->ThrowTypeLoadException(pInternalImport, cl, BFA_CANNOT_INHERIT_FROM_DELEGATE);
12391         }
12392
12393 #ifdef _DEBUG
12394         // Only MultiCastDelegate should inherit from Delegate
12395         LPCUTF8 className;
12396         LPCUTF8 nameSpace;
12397         if (FAILED(pInternalImport->GetNameOfTypeDef(cl, &className, &nameSpace)))
12398         {
12399             className = nameSpace = "Invalid TypeDef record";
12400         }
12401         BAD_FORMAT_NOTHROW_ASSERT(strcmp(className, "MulticastDelegate") == 0);
12402 #endif
12403     }
12404
12405     if (fIsDelegate)
12406     {
12407         if (!pClass->IsSealed())
12408         {
12409             pAssembly->ThrowTypeLoadException(pInternalImport, cl, BFA_DELEGATE_CLASS_NOTSEALED);
12410         }
12411
12412         pClass->SetIsDelegate();
12413     }
12414
12415     if (tdEnclosing != mdTypeDefNil)
12416     {
12417         pClass->SetIsNested();
12418         THROW_BAD_FORMAT_MAYBE(IsTdNested(pClass->GetProtection()), VLDTR_E_TD_ENCLNOTNESTED, pModule);
12419     }
12420     else if (IsTdNested(pClass->GetProtection()))
12421     {
12422         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12423     }
12424
12425     // We only permit generic interfaces and delegates to have variant type parameters
12426     if (genericsInfo.pVarianceInfo != NULL && !pClass->IsInterface() && !fIsDelegate)
12427     {
12428         pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_VARIANCE_CLASS);
12429     }
12430
12431     // Now load all the interfaces
12432     HENUMInternalHolder hEnumInterfaceImpl(pInternalImport);
12433     hEnumInterfaceImpl.EnumInit(mdtInterfaceImpl, cl);
12434
12435     cInterfaces = pInternalImport->EnumGetCount(&hEnumInterfaceImpl);
12436
12437     if (cInterfaces != 0)
12438     {
12439         DWORD i;
12440
12441         // Allocate the BuildingInterfaceList table
12442         pInterfaceBuildInfo = new (pStackingAllocator) BuildingInterfaceInfo_t[cInterfaces];
12443
12444         mdInterfaceImpl ii;
12445         for (i = 0; pInternalImport->EnumNext(&hEnumInterfaceImpl, &ii); i++)
12446         {
12447             // Get properties on this interface
12448             mdTypeRef crInterface;
12449             if (FAILED(pInternalImport->GetTypeOfInterfaceImpl(ii, &crInterface)))
12450             {
12451                 pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12452             }
12453             // validate the token
12454             mdToken crIntType =
12455                 (RidFromToken(crInterface) && pInternalImport->IsValidToken(crInterface)) ?
12456                 TypeFromToken(crInterface) :
12457                 0;
12458             switch (crIntType)
12459             {
12460                 case mdtTypeDef:
12461                 case mdtTypeRef:
12462                 case mdtTypeSpec:
12463                     break;
12464                 default:
12465                     pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_INTERFACENULL);
12466             }
12467
12468             TypeHandle intType;
12469
12470             {
12471                 OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOAD_APPROXPARENTS);
12472                 intType = LoadApproxTypeThrowing(pModule, crInterface, NULL, &genericsInfo.typeContext);
12473             }
12474
12475             pInterfaceBuildInfo[i].m_pMethodTable = intType.AsMethodTable();
12476             if (pInterfaceBuildInfo[i].m_pMethodTable == NULL)
12477             {
12478                 pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_INTERFACENULL);
12479             }
12480
12481             // Ensure this is an interface
12482             if (!pInterfaceBuildInfo[i].m_pMethodTable->IsInterface())
12483             {
12484                  pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_NOTINTERFACE);
12485             }
12486
12487             // Check interface for use of variant type parameters
12488             if ((genericsInfo.pVarianceInfo != NULL) && (TypeFromToken(crInterface) == mdtTypeSpec))
12489             {
12490                 ULONG cSig;
12491                 PCCOR_SIGNATURE pSig;
12492                 if (FAILED(pInternalImport->GetTypeSpecFromToken(crInterface, &pSig, &cSig)))
12493                 {
12494                     pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12495                 }
12496                 // Interfaces behave covariantly
12497                 if (!EEClass::CheckVarianceInSig(
12498                         genericsInfo.GetNumGenericArgs(),
12499                         genericsInfo.pVarianceInfo,
12500                         pModule,
12501                         SigPointer(pSig, cSig),
12502                         gpCovariant))
12503                 {
12504                     pAssembly->ThrowTypeLoadException(
12505                         pInternalImport,
12506                         cl,
12507                         IDS_CLASSLOAD_VARIANCE_IN_INTERFACE);
12508                 }
12509             }
12510         }
12511         _ASSERTE(i == cInterfaces);
12512     }
12513
12514     if (fHasLayout ||
12515         /* Variant delegates should not have any instance fields of the variant.
12516            type parameter. For now, we just completely disallow all fields even
12517            if they are non-variant or static, as it is not a useful scenario.
12518            @TODO: A more logical place for this check would be in
12519            MethodTableBuilder::EnumerateClassMembers() */
12520         (fIsDelegate && genericsInfo.pVarianceInfo))
12521     {
12522         // check for fields and variance
12523         ULONG               cFields;
12524         HENUMInternalHolder hEnumField(pInternalImport);
12525         hEnumField.EnumInit(mdtFieldDef, cl);
12526
12527         cFields = pInternalImport->EnumGetCount(&hEnumField);
12528
12529         if ((cFields != 0) && fIsDelegate && (genericsInfo.pVarianceInfo != NULL))
12530         {
12531             pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_VARIANCE_IN_DELEGATE);
12532         }
12533
12534         if (fHasLayout)
12535         {
12536             // Though we fail on this condition, we should never run into it.
12537             CONSISTENCY_CHECK(nstructPackingSize != 0);
12538             // MD Val check: PackingSize
12539             if((nstructPackingSize == 0)  ||
12540                (nstructPackingSize > 128) ||
12541                (nstructPackingSize & (nstructPackingSize-1)))
12542             {
12543                 THROW_BAD_FORMAT_MAYBE(!"ClassLayout:Invalid PackingSize", BFA_BAD_PACKING_SIZE, pModule);
12544                 pAssembly->ThrowTypeLoadException(pInternalImport, cl, IDS_CLASSLOAD_BADFORMAT);
12545             }
12546
12547             pLayoutRawFieldInfos = (LayoutRawFieldInfo *)pStackingAllocator->Alloc(
12548                 (S_UINT32(1) + S_UINT32(cFields)) * S_UINT32(sizeof(LayoutRawFieldInfo)));
12549
12550             {
12551                 // Warning: this can load classes
12552                 CONTRACT_VIOLATION(LoadsTypeViolation);
12553
12554                 // Set a flag that allows us to break dead-locks that are result of the LoadsTypeViolation
12555                 ThreadStateNCStackHolder tsNC(TRUE, Thread::TSNC_LoadsTypeViolation);
12556
12557                 EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing(
12558                     cl,
12559                     nstructPackingSize,
12560                     nstructNLT,
12561                     fExplicitOffsets,
12562                     pParentMethodTable,
12563                     cFields,
12564                     &hEnumField,
12565                     pModule,
12566                     &genericsInfo.typeContext,
12567                     &(((LayoutEEClass *)pClass)->m_LayoutInfo),
12568                     pLayoutRawFieldInfos,
12569                     pAllocator,
12570                     pamTracker);
12571             }
12572         }
12573     }
12574
12575     // Resolve this class, given that we know now that all of its dependencies are loaded and resolved.
12576     // !!! This must be the last thing in this TRY block: if MethodTableBuilder succeeds, it has published the class
12577     // and there is no going back.
12578     MethodTableBuilder builder(
12579         NULL,
12580         pClass,
12581         pStackingAllocator,
12582         pamTracker);
12583
12584     pMT = builder.BuildMethodTableThrowing(
12585         pAllocator,
12586         pLoaderModule,
12587         pModule,
12588         cl,
12589         pInterfaceBuildInfo,
12590         pLayoutRawFieldInfos,
12591         pParentMethodTable,
12592         &genericsInfo,
12593         parentInst,
12594         (WORD)cInterfaces);
12595
12596     RETURN(TypeHandle(pMT));
12597 } // ClassLoader::CreateTypeHandleForTypeDefThrowing