1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4// ===========================================================================
5// File: CLASS.H
6
7#ifndef CLASSCOMPAT_H
8#define CLASSCOMPAT_H
9
10#ifdef FEATURE_COMINTEROP
11
12/*
13 * Include Files
14 */
15#include "eecontract.h"
16#include "argslot.h"
17#include "vars.hpp"
18#include "cor.h"
19#include "clrex.h"
20#include "hash.h"
21#include "crst.h"
22#include "cgensys.h"
23#include "declsec.h"
24#include "stdinterfaces.h"
25#include "slist.h"
26#include "spinlock.h"
27#include "typehandle.h"
28#include "perfcounters.h"
29#include "methodtable.h"
30#include "eeconfig.h"
31#include "typectxt.h"
32#include "stackingallocator.h"
33#include "class.h"
34
35/*
36 * Forward declarations
37 */
38class AppDomain;
39class ArrayClass;
40class ArrayMethodDesc;
41class Assembly;
42class ClassLoader;
43class DomainLocalBlock;
44class FCallMethodDesc;
45class EEClass;
46class LayoutEEClass;
47class EnCFieldDesc;
48class FieldDesc;
49class FieldMarshaler;
50struct LayoutRawFieldInfo;
51class MetaSig;
52class MethodDesc;
53class MethodDescChunk;
54class MethodNameHash;
55class MethodTable;
56class Module;
57struct ModuleCtorInfo;
58class Object;
59class Stub;
60class Substitution;
61class SystemDomain;
62class TypeHandle;
63class AllocMemTracker;
64class ZapCodeMap;
65class InteropMethodTableSlotDataMap;
66class LoadingEntry_LockHolder;
67class DispatchMapBuilder;
68
69namespace ClassCompat
70{
71
72//*******************************************************************************
73// workaround: These classification bits need cleanup bad: for now, this gets around
74// IJW setting both mdUnmanagedExport & mdPinvokeImpl on expored methods.
75#define IsReallyMdPinvokeImpl(x) ( ((x) & mdPinvokeImpl) && !((x) & mdUnmanagedExport) )
76
77//*******************************************************************************
78//
79// The MethodNameHash is a temporary loader structure which may be allocated if there are a large number of
80// methods in a class, to quickly get from a method name to a MethodDesc (potentially a chain of MethodDescs).
81//
82
83//*******************************************************************************
84// Entry in the method hash table
85class MethodHashEntry
86{
87public:
88 MethodHashEntry * m_pNext; // Next item with same hash value
89 DWORD m_dwHashValue; // Hash value
90 MethodDesc * m_pDesc;
91 LPCUTF8 m_pKey; // Method name
92};
93
94//*******************************************************************************
95class MethodNameHash
96{
97public:
98
99 MethodHashEntry **m_pBuckets; // Pointer to first entry for each bucket
100 DWORD m_dwNumBuckets;
101 BYTE * m_pMemory; // Current pointer into preallocated memory for entries
102 BYTE * m_pMemoryStart; // Start pointer of pre-allocated memory fo entries
103 MethodNameHash *m_pNext; // Chain them for stub dispatch lookup
104 INDEBUG( BYTE * m_pDebugEndMemory; )
105
106 MethodNameHash()
107 {
108 LIMITED_METHOD_CONTRACT;
109 m_pMemoryStart = NULL;
110 m_pNext = NULL;
111 }
112
113 ~MethodNameHash()
114 {
115 LIMITED_METHOD_CONTRACT;
116 if (m_pMemoryStart != NULL)
117 delete(m_pMemoryStart);
118 }
119
120 // Throws on error
121 void Init(DWORD dwMaxEntries, StackingAllocator *pAllocator = NULL);
122
123 // Insert new entry at head of list
124 void Insert(
125 LPCUTF8 pszName,
126 MethodDesc *pDesc);
127
128 // Return the first MethodHashEntry with this name, or NULL if there is no such entry
129 MethodHashEntry *Lookup(
130 LPCUTF8 pszName,
131 DWORD dwHash);
132
133 void SetNext(MethodNameHash *pNext) { m_pNext = pNext; }
134 MethodNameHash *GetNext() { return m_pNext; }
135};
136
137
138//*******************************************************************************
139//
140// This structure is used only when the classloader is building the interface map. Before the class
141// is resolved, the EEClass contains an array of these, which are all interfaces *directly* declared
142// for this class/interface by the metadata - inherited interfaces will not be present if they are
143// not specifically declared.
144//
145// This structure is destroyed after resolving has completed.
146//
147typedef struct
148{
149 // The interface method table; for instantiated interfaces, this is the generic interface
150 MethodTable *m_pMethodTable;
151} BuildingInterfaceInfo_t;
152
153//*******************************************************************************
154struct InterfaceInfo_t
155{
156#ifdef DACCESS_COMPILE
157 friend class NativeImageDumper;
158#endif
159 enum {
160 interface_declared_on_class = 0x1,
161 interface_implemented_on_parent = 0x2,
162 };
163
164 MethodTable* m_pMethodTable; // Method table of the interface
165 WORD m_wFlags;
166
167private:
168 WORD m_wStartSlot; // starting slot of interface in vtable
169
170public:
171 WORD GetInteropStartSlot()
172 {
173 return m_wStartSlot;
174 }
175 void SetInteropStartSlot(WORD wStartSlot)
176 {
177 m_wStartSlot = wStartSlot;
178 }
179
180 BOOL IsDeclaredOnClass()
181 {
182 LIMITED_METHOD_CONTRACT;
183 return (m_wFlags & interface_declared_on_class);
184 }
185
186 BOOL IsImplementedByParent()
187 {
188 LIMITED_METHOD_CONTRACT;
189 return (m_wFlags & interface_implemented_on_parent);
190 }
191};
192
193//*******************************************************************************
194// MethodTableBuilder simply acts as a holder for the
195// large algorithm that "compiles" a type into
196// a MethodTable/EEClass/DispatchMap/VTable etc. etc.
197//
198// The user of this class (the ClassLoader) currently builds the EEClass
199// first, and does a couple of other things too, though all
200// that work should probably be folded into BuildMethodTableThrowing.
201//
202class MethodTableBuilder
203{
204public:
205 MethodTableBuilder(MethodTable * pMT)
206 {
207 LIMITED_METHOD_CONTRACT;
208 m_pHalfBakedMT = pMT;
209 m_pHalfBakedClass = pMT->GetClass();
210 NullBMTData();
211 }
212public:
213
214 // This method is purely for backward compatibility of COM Interop, and its
215 // implementation can be found in ClassCompat.cpp
216 InteropMethodTableData *BuildInteropVTable(AllocMemTracker *pamTracker);
217 InteropMethodTableData *BuildInteropVTableForArray(AllocMemTracker *pamTracker);
218
219 LPCWSTR GetPathForErrorMessages();
220
221private:
222 enum e_METHOD_IMPL
223 {
224 METHOD_IMPL_NOT,
225#ifndef STUB_DISPATCH_ALL
226 METHOD_IMPL,
227#endif
228 METHOD_IMPL_COUNT
229 };
230
231 enum e_METHOD_TYPE
232 {
233 METHOD_TYPE_NORMAL,
234 METHOD_TYPE_FCALL,
235 METHOD_TYPE_EEIMPL,
236 METHOD_TYPE_NDIRECT,
237 METHOD_TYPE_INTEROP,
238 METHOD_TYPE_INSTANTIATED,
239 METHOD_TYPE_COUNT
240 };
241
242private:
243 // <NICE> Get rid of this.</NICE>
244 EEClass *m_pHalfBakedClass;
245 MethodTable * m_pHalfBakedMT;
246
247 // GetHalfBakedClass: The EEClass you get back from this function may not have all its fields filled in yet.
248 // Thus you have to make sure that the relevant item which you are accessing has
249 // been correctly initialized in the EEClass/MethodTable construction sequence
250 // at the point at which you access it.
251 //
252 // Gradually we will move the code to a model where the process of constructing an EEClass/MethodTable
253 // is more obviously correct, e.g. by relying much less on reading information using GetHalfBakedClass
254 // and GetHalfBakedMethodTable.
255 //
256 // <NICE> Get rid of this.</NICE>
257 EEClass *GetHalfBakedClass() { LIMITED_METHOD_CONTRACT; return m_pHalfBakedClass; }
258 MethodTable *GetHalfBakedMethodTable() { WRAPPER_NO_CONTRACT; return m_pHalfBakedMT; }
259
260 mdTypeDef GetCl() { LIMITED_METHOD_CONTRACT; return bmtType->cl; }
261 BOOL IsGlobalClass() { WRAPPER_NO_CONTRACT; return GetCl() == COR_GLOBAL_PARENT_TOKEN; }
262 BOOL IsEnum() { LIMITED_METHOD_CONTRACT; return bmtProp->fIsEnum; }
263 DWORD GetAttrClass() { LIMITED_METHOD_CONTRACT; return bmtType->dwAttr; }
264 BOOL IsInterface() { WRAPPER_NO_CONTRACT; return IsTdInterface(GetAttrClass()); }
265 BOOL IsValueClass() { LIMITED_METHOD_CONTRACT; return bmtProp->fIsValueClass; }
266 BOOL IsAbstract() { LIMITED_METHOD_CONTRACT; return IsTdAbstract(bmtType->dwAttr); }
267 BOOL HasLayout() { LIMITED_METHOD_CONTRACT; return bmtProp->fHasLayout; }
268 BOOL IsDelegate() { LIMITED_METHOD_CONTRACT; return bmtProp->fIsDelegate; }
269 Module *GetModule() { LIMITED_METHOD_CONTRACT; return bmtType->pModule; }
270 Assembly *GetAssembly() { WRAPPER_NO_CONTRACT; return GetModule()->GetAssembly(); }
271 ClassLoader *GetClassLoader() { WRAPPER_NO_CONTRACT; return GetModule()->GetClassLoader(); }
272 IMDInternalImport* GetMDImport() { WRAPPER_NO_CONTRACT; return GetModule()->GetMDImport(); }
273#ifdef _DEBUG
274 LPCUTF8 GetDebugClassName() { LIMITED_METHOD_CONTRACT; return bmtProp->szDebugClassName; }
275#endif // _DEBUG
276 BOOL IsComImport() { WRAPPER_NO_CONTRACT; return IsTdImport(GetAttrClass()); }
277 BOOL IsComClassInterface() { LIMITED_METHOD_CONTRACT; return bmtProp->fIsComClassInterface; }
278
279 // <NOTE> The following functions are used during MethodTable construction to setup information
280 // about the type being constructedm in particular information stored in the EEClass.
281 // USE WITH CAUTION!! TRY NOT TO ADD MORE OF THESE!! </NOTE>
282 //
283 // <NICE> Get rid of all of these - we should be able to evaluate these conditions BEFORE
284 // we create the EEClass object, and thus set the flags immediately at the point
285 // we create that object.</NICE>
286 void SetIsValueClass() { LIMITED_METHOD_CONTRACT; bmtProp->fIsValueClass = TRUE; }
287 void SetEnum() { LIMITED_METHOD_CONTRACT; bmtProp->fIsEnum = TRUE; }
288 void SetHasLayout() { LIMITED_METHOD_CONTRACT; bmtProp->fHasLayout = TRUE; }
289 void SetIsDelegate() { LIMITED_METHOD_CONTRACT; bmtProp->fIsDelegate = TRUE; }
290#ifdef _DEBUG
291 void SetDebugClassName(LPUTF8 x) { LIMITED_METHOD_CONTRACT; bmtProp->szDebugClassName = x; }
292#endif
293 void SetIsComClassInterface() { LIMITED_METHOD_CONTRACT; bmtProp->fIsComClassInterface = TRUE; }
294
295 /************************************
296 * PRIVATE INTERNAL STRUCTS
297 ************************************/
298private:
299 struct bmtErrorInfo
300 {
301 UINT resIDWhy;
302 LPCUTF8 szMethodNameForError;
303 mdToken dMethodDefInError;
304 Module* pModule;
305 mdTypeDef cl;
306 OBJECTREF *pThrowable;
307
308 // Set the reason and the offending method def. If the method information
309 // is not from this class set the method name and it will override the method def.
310 inline bmtErrorInfo() : resIDWhy(0), szMethodNameForError(NULL), dMethodDefInError(mdMethodDefNil), pThrowable(NULL) {LIMITED_METHOD_CONTRACT; }
311 };
312
313 struct bmtProperties
314 {
315 BOOL fSparse; // Set to true if a sparse interface is being used.
316
317 // Com Interop, ComWrapper classes extend from ComObject
318 BOOL fIsComObjectType; // whether this class is an instance of ComObject class
319
320 BOOL fIsMngStandardItf; // Set to true if the interface is a manages standard interface.
321 BOOL fComEventItfType; // Set to true if the class is a special COM event interface.
322
323 BOOL fIsValueClass;
324 BOOL fIsEnum;
325 BOOL fIsComClassInterface;
326 BOOL fHasLayout;
327 BOOL fIsDelegate;
328
329 LPUTF8 szDebugClassName;
330
331 inline bmtProperties()
332 {
333 LIMITED_METHOD_CONTRACT;
334 memset((void *)this, NULL, sizeof(*this));
335 }
336 };
337
338 struct bmtVtable
339 {
340 WORD wCurrentVtableSlot;
341 WORD wCurrentNonVtableSlot;
342
343 // Temporary vtable - use GetMethodDescForSlot/SetMethodDescForSlot for access.
344 // pVtableMD is initialized lazily from pVtable
345 // pVtable is invalidated if the slot is overwritten.
346 PCODE* pVtable;
347 MethodDesc** pVtableMD;
348 MethodTable *pParentMethodTable;
349
350 MethodDesc** pNonVtableMD;
351 InteropMethodTableSlotData **ppSDVtable;
352 InteropMethodTableSlotData **ppSDNonVtable;
353 DWORD dwMaxVtableSize; // Upper bound on size of vtable
354 InteropMethodTableSlotDataMap *pInteropData;
355
356 DispatchMapBuilder *pDispatchMapBuilder;
357
358 MethodDesc* GetMethodDescForSlot(WORD slot)
359 {
360 CONTRACTL
361 {
362 NOTHROW;
363 GC_NOTRIGGER;
364 SO_TOLERANT;
365 MODE_ANY;
366 }
367 CONTRACTL_END;
368 if (pVtable[slot] != NULL && pVtableMD[slot] == NULL)
369 pVtableMD[slot] = pParentMethodTable->GetMethodDescForSlot(slot);
370 _ASSERTE((pVtable[slot] == NULL) ||
371 (MethodTable::GetMethodDescForSlotAddress(pVtable[slot]) == pVtableMD[slot]));
372 return pVtableMD[slot];
373 }
374
375 void SetMethodDescForSlot(WORD slot, MethodDesc* pMD)
376 {
377 WRAPPER_NO_CONTRACT;
378 pVtable[slot] = NULL;
379 pVtableMD[slot] = pMD;
380 }
381
382 inline bmtVtable() { LIMITED_METHOD_CONTRACT; memset((void *)this, NULL, sizeof(*this)); }
383 };
384
385 struct bmtParentInfo
386 {
387 WORD wNumParentInterfaces;
388 MethodDesc **ppParentMethodDescBuf; // Cache for declared methods
389 MethodDesc **ppParentMethodDescBufPtr; // Pointer for iterating over the cache
390
391 MethodNameHash *pParentMethodHash;
392 Substitution parentSubst;
393 MethodTable *pParentMethodTable;
394 mdToken token;
395
396 inline bmtParentInfo() { LIMITED_METHOD_CONTRACT; memset((void *)this, NULL, sizeof(*this)); }
397 };
398
399 struct bmtInterfaceInfo
400 {
401 DWORD dwTotalNewInterfaceMethods;
402 InterfaceInfo_t *pInterfaceMap; // Temporary interface map
403
404 // ppInterfaceSubstitutionChains[i][0] holds the primary substitution for each interface
405 // ppInterfaceSubstitutionChains[i][0..depth[i] ] is the chain of substitutions for each interface
406 Substitution **ppInterfaceSubstitutionChains;
407
408 DWORD *pdwOriginalStart; // If an interface is moved this is the original starting location.
409 WORD wInterfaceMapSize; // # members in interface map
410 DWORD dwLargestInterfaceSize; // # members in largest interface we implement
411 DWORD dwMaxExpandedInterfaces; // Upper bound on size of interface map
412 MethodDesc **ppInterfaceMethodDescList; // List of MethodDescs for current interface
413 MethodDesc **ppInterfaceDeclMethodDescList; // List of MethodDescs for the interface itself
414
415 MethodDesc ***pppInterfaceImplementingMD; // List of MethodDescs that implement interface methods
416 MethodDesc ***pppInterfaceDeclaringMD; // List of MethodDescs from the interface itself
417
418 inline bmtInterfaceInfo() { LIMITED_METHOD_CONTRACT; memset((void *)this, NULL, sizeof(*this)); }
419 };
420
421 struct bmtMethodInfo
422 {
423 DWORD cMethAndGaps; // # meta-data methods of this class ( including the gaps )
424
425 WORD cMethods; // # meta-data methods of this class
426 mdToken * rgMethodTokens; // Enumeration of metadata methods
427 DWORD * rgMethodAttrs; // Enumeration of the attributes of the methods
428 DWORD * rgMethodImplFlags; // Enumeration of the method implementation flags
429 ULONG * rgMethodRVA; // Enumeration of the method RVA's
430 DWORD * rgMethodClassifications; // Enumeration of the method classifications
431 LPCSTR * rgszMethodName; // Enumeration of the method names
432 BYTE * rgMethodImpl; // Enumeration of impl value
433 BYTE * rgMethodType; // Enumeration of type value
434
435 HENUMInternalHolder hEnumMethod;
436
437 MethodDesc ** ppUnboxMethodDescList; // Keep track unboxed entry points (for value classes)
438 MethodDesc ** ppMethodDescList; // MethodDesc pointer for each member
439
440 inline bmtMethodInfo(IMDInternalImport *pMDImport)
441 : cMethAndGaps(0),
442 cMethods(0),
443 rgMethodTokens(NULL),
444 rgMethodAttrs(NULL),
445 rgMethodImplFlags(NULL),
446 rgMethodRVA(NULL),
447 rgMethodClassifications(NULL),
448 rgszMethodName(NULL),
449 rgMethodImpl(NULL),
450 hEnumMethod(pMDImport),
451 ppUnboxMethodDescList(NULL),
452 ppMethodDescList(NULL)
453 {
454 WRAPPER_NO_CONTRACT;
455 }
456
457 inline void SetMethodData(int idx,
458 mdToken tok,
459 DWORD dwAttrs,
460 DWORD dwRVA,
461 DWORD dwImplFlags,
462 DWORD classification,
463 LPCSTR szMethodName,
464 BYTE impl,
465 BYTE type)
466 {
467 LIMITED_METHOD_CONTRACT;
468 rgMethodTokens[idx] = tok;
469 rgMethodAttrs[idx] = dwAttrs;
470 rgMethodRVA[idx] = dwRVA;
471 rgMethodImplFlags[idx] = dwImplFlags;
472 rgMethodClassifications[idx] = classification;
473 rgszMethodName[idx] = szMethodName;
474 rgMethodImpl[idx] = impl;
475 rgMethodType[idx] = type;
476 }
477 };
478
479 struct bmtTypeInfo
480 {
481 IMDInternalImport * pMDImport;
482 Module * pModule;
483 mdToken cl;
484 DWORD dwAttr;
485
486 inline bmtTypeInfo() { LIMITED_METHOD_CONTRACT; memset((void *)this, NULL, sizeof(*this)); }
487 };
488
489 struct bmtMethodImplInfo
490 {
491 DWORD dwNumberMethodImpls; // Number of method impls defined for this type
492 HENUMInternalMethodImplHolder hEnumMethodImpl;
493
494 struct MethodImplTokenPair
495 {
496 mdToken methodBody; // MethodDef's for the bodies of MethodImpls. Must be defined in this type.
497 mdToken methodDecl; // Method token that body implements. Is a MethodDef or MemberRef
498 static int __cdecl Compare(const void *elem1, const void *elem2);
499 static BOOL Equal(const MethodImplTokenPair *elem1, const MethodImplTokenPair *elem2);
500 };
501
502 MethodImplTokenPair * rgMethodImplTokens;
503 Substitution * pMethodDeclSubsts; // Used to interpret generic variables in the interface of the declaring type
504
505 DWORD pIndex; // Next open spot in array, we load the BodyDesc's up in order of appearance in the
506 // type's list of methods (a body can appear more then once in the list of MethodImpls)
507 struct Entry
508 {
509 mdToken declToken; // Either the token or the method desc is set for the declaration
510 Substitution declSubst; // Signature instantiations of parent types for Declaration (NULL if not instantiated)
511 MethodDesc* pDeclDesc; // Method descs for Declaration. If null then Declaration is in this type and use the token
512 MethodDesc* pBodyDesc; // Method descs created for Method impl bodies
513 DWORD dwFlags;
514 };
515
516 Entry *rgEntries;
517
518 void AddMethod(MethodDesc* pImplDesc, MethodDesc* pDeclDesc, mdToken mdDecl, Substitution *pDeclSubst);
519
520 MethodDesc* GetDeclarationMethodDesc(DWORD i)
521 {
522 LIMITED_METHOD_CONTRACT;
523 _ASSERTE(i < pIndex);
524 return rgEntries[i].pDeclDesc;
525 }
526
527 mdToken GetDeclarationToken(DWORD i)
528 {
529 LIMITED_METHOD_CONTRACT;
530 _ASSERTE(i < pIndex);
531 return rgEntries[i].declToken;
532 }
533
534 const Substitution *GetDeclarationSubst(DWORD i)
535 {
536 LIMITED_METHOD_CONTRACT;
537
538 _ASSERTE(i < pIndex);
539 return &rgEntries[i].declSubst;
540 }
541
542 MethodDesc* GetBodyMethodDesc(DWORD i)
543 {
544 LIMITED_METHOD_CONTRACT;
545 _ASSERTE(i < pIndex);
546 return rgEntries[i].pBodyDesc;
547 }
548
549 // Returns TRUE if tok acts as a body for any methodImpl entry. FALSE, otherwise.
550 BOOL IsBody(mdToken tok);
551
552 inline bmtMethodImplInfo(IMDInternalImport * pMDImport)
553 : dwNumberMethodImpls(0),
554 hEnumMethodImpl(pMDImport),
555 pIndex(0),
556 rgEntries(NULL)
557 {
558 LIMITED_METHOD_CONTRACT;
559 }
560 };
561
562 // The following structs, defined as private members of MethodTableBuilder, contain the necessary local
563 // parameters needed for BuildMethodTable
564
565 // Look at the struct definitions for a detailed list of all parameters available
566 // to BuildMethodTable.
567
568 bmtErrorInfo *bmtError;
569 bmtProperties *bmtProp;
570 bmtVtable *bmtVT;
571 bmtParentInfo *bmtParent;
572 bmtInterfaceInfo *bmtInterface;
573 bmtMethodInfo *bmtMethod;
574 bmtTypeInfo *bmtType;
575 bmtMethodImplInfo *bmtMethodImpl;
576
577 void SetBMTData(
578 bmtErrorInfo *bmtError,
579 bmtProperties *bmtProp,
580 bmtVtable *bmtVT,
581 bmtParentInfo *bmtParent,
582 bmtInterfaceInfo *bmtInterface,
583 bmtMethodInfo *bmtMethod,
584 bmtTypeInfo *bmtType,
585 bmtMethodImplInfo *bmtMethodImpl);
586
587 void NullBMTData();
588
589 class DeclaredMethodIterator
590 {
591 private:
592 MethodTableBuilder &m_mtb;
593 int m_idx;
594
595 public:
596 inline DeclaredMethodIterator(MethodTableBuilder &mtb);
597 inline int CurrentIndex();
598 inline BOOL Next();
599 inline mdToken Token();
600 inline DWORD Attrs();
601 inline DWORD RVA();
602 inline DWORD ImplFlags();
603 inline DWORD Classification();
604 inline LPCSTR Name();
605 inline PCCOR_SIGNATURE GetSig(DWORD *pcbSig);
606 inline BYTE MethodImpl();
607 inline BOOL IsMethodImpl();
608 inline BYTE MethodType();
609 inline MethodDesc *GetMethodDesc();
610 inline void SetMethodDesc(MethodDesc *pMD);
611 inline MethodDesc *GetParentMethodDesc();
612 inline void SetParentMethodDesc(MethodDesc *pMD);
613 inline MethodDesc *GetUnboxedMethodDesc();
614 };
615 friend class DeclaredMethodIterator;
616
617 inline WORD NumDeclaredMethods() { LIMITED_METHOD_CONTRACT; return bmtMethod->cMethods; }
618 inline void IncNumDeclaredMethods() { LIMITED_METHOD_CONTRACT; bmtMethod->cMethods++; }
619
620private:
621 static VOID DECLSPEC_NORETURN BuildMethodTableThrowException(HRESULT hr,
622 const bmtErrorInfo & bmtError);
623
624
625 inline VOID DECLSPEC_NORETURN BuildMethodTableThrowException(
626 HRESULT hr,
627 UINT idResWhy,
628 mdMethodDef tokMethodDef)
629 {
630 STANDARD_VM_CONTRACT;
631 bmtError->resIDWhy = idResWhy;
632 bmtError->dMethodDefInError = tokMethodDef;
633 bmtError->szMethodNameForError = NULL;
634 bmtError->cl = GetCl();
635 BuildMethodTableThrowException(hr, *bmtError);
636 }
637
638 inline VOID DECLSPEC_NORETURN BuildMethodTableThrowException(
639 HRESULT hr,
640 UINT idResWhy,
641 LPCUTF8 szMethodName)
642 {
643 STANDARD_VM_CONTRACT;
644 bmtError->resIDWhy = idResWhy;
645 bmtError->dMethodDefInError = mdMethodDefNil;
646 bmtError->szMethodNameForError = szMethodName;
647 bmtError->cl = GetCl();
648 BuildMethodTableThrowException(hr, *bmtError);
649 }
650
651 inline VOID DECLSPEC_NORETURN BuildMethodTableThrowException(
652 UINT idResWhy,
653 mdMethodDef tokMethodDef = mdMethodDefNil)
654 {
655 STANDARD_VM_CONTRACT;
656 BuildMethodTableThrowException(COR_E_TYPELOAD, idResWhy, tokMethodDef);
657 }
658
659 inline VOID DECLSPEC_NORETURN BuildMethodTableThrowException(
660 UINT idResWhy,
661 LPCUTF8 szMethodName)
662 {
663 STANDARD_VM_CONTRACT;
664 BuildMethodTableThrowException(COR_E_TYPELOAD, idResWhy, szMethodName);
665 }
666
667private:
668 MethodNameHash *CreateMethodChainHash(
669 MethodTable *pMT);
670
671 HRESULT LoaderFindMethodInClass(
672 LPCUTF8 pszMemberName,
673 Module* pModule,
674 mdMethodDef mdToken,
675 MethodDesc ** ppMethodDesc,
676 PCCOR_SIGNATURE * ppMemberSignature,
677 DWORD * pcMemberSignature,
678 DWORD dwHashName,
679 BOOL * pMethodConstraintsMatch);
680
681 // Finds a method declaration from a MemberRef or Def. It handles the case where
682 // the Ref or Def point back to this class even though it has not been fully
683 // laid out.
684 HRESULT FindMethodDeclarationForMethodImpl(
685 IMDInternalImport *pMDInternalImport, // Scope in which tkClass and tkMethod are defined.
686 mdTypeDef tkClass, // Type that the method def resides in
687 mdToken tkMethod, // Token that is being located (MemberRef or MethodDef)
688 mdToken* ptkMethodDef); // Method definition for Member
689
690 // Enumerates the method impl token pairs and resolves the impl tokens to mdtMethodDef
691 // tokens, since we currently have the limitation that all impls are in the current class.
692 VOID EnumerateMethodImpls();
693
694 VOID EnumerateClassMethods();
695
696 // Allocate temporary memory for tracking all information used in building the MethodTable
697 VOID AllocateMethodWorkingMemory();
698
699 VOID BuildInteropVTable_InterfaceList(
700 BuildingInterfaceInfo_t **ppBuildingInterfaceList,
701 WORD *pcBuildingInterfaceList);
702
703 VOID BuildInteropVTable_PlaceMembers(
704 bmtTypeInfo* bmtType,
705 DWORD numDeclaredInterfaces,
706 BuildingInterfaceInfo_t *pBuildingInterfaceList,
707 bmtMethodInfo* bmtMethod,
708 bmtErrorInfo* bmtError,
709 bmtProperties* bmtProp,
710 bmtParentInfo* bmtParent,
711 bmtInterfaceInfo* bmtInterface,
712 bmtMethodImplInfo* bmtMethodImpl,
713 bmtVtable* bmtVT);
714
715 VOID BuildInteropVTable_ResolveInterfaces(
716 BuildingInterfaceInfo_t *pBuildingInterfaceList,
717 bmtTypeInfo* bmtType,
718 bmtInterfaceInfo* bmtInterface,
719 bmtVtable* bmtVT,
720 bmtParentInfo* bmtParent,
721 const bmtErrorInfo & bmtError);
722
723 VOID BuildInteropVTable_CreateInterfaceMap(
724 BuildingInterfaceInfo_t *pBuildingInterfaceList,
725 bmtInterfaceInfo* bmtInterface,
726 WORD *pwInterfaceListSize,
727 DWORD *pdwMaxInterfaceMethods,
728 MethodTable *pParentMethodTable);
729
730 VOID BuildInteropVTable_ExpandInterface(
731 InterfaceInfo_t *pInterfaceMap,
732 MethodTable *pNewInterface,
733 WORD *pwInterfaceListSize,
734 DWORD *pdwMaxInterfaceMethods,
735 BOOL fDirect);
736
737 VOID BuildInteropVTable_PlaceVtableMethods(
738 bmtInterfaceInfo* bmtInterface,
739 DWORD numDeclaredInterfaces,
740 BuildingInterfaceInfo_t *pBuildingInterfaceList,
741 bmtVtable* bmtVT,
742 bmtMethodInfo* bmtMethod,
743 bmtTypeInfo* bmtType,
744 bmtErrorInfo* bmtError,
745 bmtProperties* bmtProp,
746 bmtParentInfo* bmtParent);
747
748 VOID BuildInteropVTable_PlaceMethodImpls(
749 bmtTypeInfo* bmtType,
750 bmtMethodImplInfo* bmtMethodImpl,
751 bmtErrorInfo* bmtError,
752 bmtInterfaceInfo* bmtInterface,
753 bmtVtable* bmtVT,
754 bmtParentInfo* bmtParent);
755
756 VOID BuildInteropVTable_PlaceLocalDeclaration(
757 mdMethodDef mdef,
758 MethodDesc* body,
759 bmtTypeInfo* bmtType,
760 bmtErrorInfo* bmtError,
761 bmtVtable* bmtVT,
762 DWORD* slots,
763 MethodDesc** replaced,
764 DWORD* pSlotIndex,
765 PCCOR_SIGNATURE* ppBodySignature,
766 DWORD* pcBodySignature);
767
768 VOID BuildInteropVTable_PlaceInterfaceDeclaration(
769 MethodDesc* pDecl,
770 MethodDesc* pImplBody,
771 const Substitution *pDeclSubst,
772 bmtTypeInfo* bmtType,
773 bmtInterfaceInfo* bmtInterface,
774 bmtErrorInfo* bmtError,
775 bmtVtable* bmtVT,
776 DWORD* slots,
777 MethodDesc** replaced,
778 DWORD* pSlotIndex,
779 PCCOR_SIGNATURE* ppBodySignature,
780 DWORD* pcBodySignature);
781
782 VOID BuildInteropVTable_PlaceParentDeclaration(
783 MethodDesc* pDecl,
784 MethodDesc* pImplBody,
785 const Substitution *pDeclSubst,
786 bmtTypeInfo* bmtType,
787 bmtErrorInfo* bmtError,
788 bmtVtable* bmtVT,
789 bmtParentInfo* bmtParent,
790 DWORD* slots,
791 MethodDesc** replaced,
792 DWORD* pSlotIndex,
793 PCCOR_SIGNATURE* ppBodySignature,
794 DWORD* pcBodySignature);
795
796 VOID BuildInteropVTable_PropagateInheritance(
797 bmtVtable *bmtVT);
798
799 VOID FinalizeInteropVTable(
800 AllocMemTracker *pamTracker,
801 LoaderAllocator*,
802 bmtVtable*,
803 bmtInterfaceInfo*,
804 bmtTypeInfo*,
805 bmtProperties*,
806 bmtMethodInfo*,
807 bmtErrorInfo*,
808 bmtParentInfo*,
809 InteropMethodTableData**);
810}; // MethodTableBuilder
811
812}; // Namespace ClassCompat
813
814#endif // FEATURE_COMINTEROP
815
816#endif // !CLASSCOMPAT_H
817