1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4//
5// File: METHODTABLEBUILDER.INL
6//
7
8
9//
10
11//
12// ============================================================================
13
14#ifndef _METHODTABLEBUILDER_INL_
15#define _METHODTABLEBUILDER_INL_
16
17//***************************************************************************************
18inline MethodTableBuilder::DeclaredMethodIterator::DeclaredMethodIterator(
19 MethodTableBuilder &mtb) : m_mtb(mtb), m_idx(-1)
20{
21 LIMITED_METHOD_CONTRACT;
22}
23
24//***************************************************************************************
25inline int MethodTableBuilder::DeclaredMethodIterator::CurrentIndex()
26{
27 LIMITED_METHOD_CONTRACT;
28 CONSISTENCY_CHECK_MSG(0 <= m_idx && m_idx < (int)m_mtb.NumDeclaredMethods(),
29 "Invalid iterator state.");
30 return m_idx;
31}
32
33//***************************************************************************************
34inline BOOL MethodTableBuilder::DeclaredMethodIterator::Next()
35{
36 LIMITED_METHOD_CONTRACT;
37 if (m_idx + 1 >= (int)m_mtb.NumDeclaredMethods())
38 return FALSE;
39 m_idx++;
40 INDEBUG(m_debug_pMethod = GetMDMethod();)
41 return TRUE;
42}
43
44//***************************************************************************************
45inline BOOL MethodTableBuilder::DeclaredMethodIterator::Prev()
46{
47 LIMITED_METHOD_CONTRACT;
48 if (m_idx - 1 <= -1)
49 return FALSE;
50 m_idx--;
51 INDEBUG(m_debug_pMethod = GetMDMethod();)
52 return TRUE;
53}
54
55//***************************************************************************************
56inline void MethodTableBuilder::DeclaredMethodIterator::ResetToEnd()
57{
58 LIMITED_METHOD_CONTRACT;
59 m_idx = (int)m_mtb.NumDeclaredMethods();
60}
61
62//***************************************************************************************
63inline mdMethodDef MethodTableBuilder::DeclaredMethodIterator::Token()
64{
65 STANDARD_VM_CONTRACT;
66 CONSISTENCY_CHECK(TypeFromToken(GetMDMethod()->GetMethodSignature().GetToken()) == mdtMethodDef);
67 return GetMDMethod()->GetMethodSignature().GetToken();
68}
69
70//***************************************************************************************
71inline DWORD MethodTableBuilder::DeclaredMethodIterator::Attrs()
72{
73 LIMITED_METHOD_CONTRACT;
74 return GetMDMethod()->GetDeclAttrs();
75}
76
77//***************************************************************************************
78inline DWORD MethodTableBuilder::DeclaredMethodIterator::RVA()
79{
80 LIMITED_METHOD_CONTRACT;
81 return GetMDMethod()->GetRVA();
82}
83
84//***************************************************************************************
85inline DWORD MethodTableBuilder::DeclaredMethodIterator::ImplFlags()
86{
87 LIMITED_METHOD_CONTRACT;
88 return GetMDMethod()->GetImplAttrs();
89}
90
91//***************************************************************************************
92inline LPCSTR MethodTableBuilder::DeclaredMethodIterator::Name()
93{
94 STANDARD_VM_CONTRACT;
95 return GetMDMethod()->GetMethodSignature().GetName();
96}
97
98//***************************************************************************************
99inline PCCOR_SIGNATURE MethodTableBuilder::DeclaredMethodIterator::GetSig(DWORD *pcbSig)
100{
101 STANDARD_VM_CONTRACT;
102 *pcbSig = static_cast<DWORD>
103 (GetMDMethod()->GetMethodSignature().GetSignatureLength());
104 return GetMDMethod()->GetMethodSignature().GetSignature();
105}
106
107//***************************************************************************************
108inline MethodTableBuilder::METHOD_IMPL_TYPE MethodTableBuilder::DeclaredMethodIterator::MethodImpl()
109{
110 LIMITED_METHOD_CONTRACT;
111 return GetMDMethod()->GetMethodImplType();
112}
113
114//***************************************************************************************
115inline BOOL MethodTableBuilder::DeclaredMethodIterator::IsMethodImpl()
116{
117 LIMITED_METHOD_CONTRACT;
118 return MethodImpl() == METHOD_IMPL;
119}
120
121//***************************************************************************************
122inline MethodTableBuilder::METHOD_TYPE MethodTableBuilder::DeclaredMethodIterator::MethodType()
123{
124 LIMITED_METHOD_CONTRACT;
125 return GetMDMethod()->GetMethodType();
126}
127
128//***************************************************************************************
129inline MethodTableBuilder::bmtMDMethod *
130MethodTableBuilder::DeclaredMethodIterator::GetMDMethod()
131{
132 LIMITED_METHOD_CONTRACT;
133 _ASSERTE(FitsIn<SLOT_INDEX>(m_idx)); // Review: m_idx should probably _be_ a SLOT_INDEX, but that asserts.
134 return (*m_mtb.bmtMethod)[static_cast<SLOT_INDEX>(m_idx)];
135}
136
137//*******************************************************************************
138inline class MethodDesc *
139MethodTableBuilder::DeclaredMethodIterator::GetIntroducingMethodDesc()
140{
141 STANDARD_VM_CONTRACT;
142
143 bmtMDMethod *pCurrentMD = GetMDMethod();
144 DWORD dwSlot = pCurrentMD->GetSlotIndex();
145 MethodDesc *pIntroducingMD = NULL;
146
147 bmtRTType *pParentType = pCurrentMD->GetOwningType()->GetParentType();
148 bmtRTType *pPrevParentType = NULL;
149
150 // Find this method in the parent.
151 // If it does exist in the parent, it would be at the same vtable slot.
152 while (pParentType != NULL &&
153 dwSlot < pParentType->GetMethodTable()->GetNumVirtuals())
154 {
155 pPrevParentType = pParentType;
156 pParentType = pParentType->GetParentType();
157 }
158
159 if (pPrevParentType != NULL)
160 {
161 pIntroducingMD =
162 pPrevParentType->GetMethodTable()->GetMethodDescForSlot(dwSlot);
163 }
164
165 return pIntroducingMD;
166}
167
168
169//***************************************************************************************
170inline MethodTableBuilder::bmtMDMethod *
171MethodTableBuilder::DeclaredMethodIterator::operator->()
172{
173 return GetMDMethod();
174}
175
176//***************************************************************************************
177inline bool
178MethodTableBuilder::bmtMethodHandle::operator==(
179 const bmtMethodHandle &rhs) const
180{
181 return m_handle == rhs.m_handle;
182}
183
184//***************************************************************************************
185//
186// The MethodNameHash is a temporary loader structure which may be allocated if there are a large number of
187// methods in a class, to quickly get from a method name to a MethodDesc (potentially a chain of MethodDescs).
188//
189
190//***************************************************************************************
191// Returns TRUE for success, FALSE for failure
192template <typename Data>
193void
194FixedCapacityStackingAllocatedUTF8StringHash<Data>::Init(
195 DWORD dwMaxEntries,
196 StackingAllocator * pAllocator)
197{
198 CONTRACTL
199 {
200 THROWS;
201 GC_NOTRIGGER;
202 PRECONDITION(CheckPointer(this));
203 }
204 CONTRACTL_END;
205
206 // Given dwMaxEntries, determine a good value for the number of hash buckets
207 m_dwNumBuckets = (dwMaxEntries / 10);
208
209 if (m_dwNumBuckets < 5)
210 m_dwNumBuckets = 5;
211
212 S_UINT32 scbMemory = (S_UINT32(m_dwNumBuckets) * S_UINT32(sizeof(HashEntry*))) +
213 (S_UINT32(dwMaxEntries) * S_UINT32(sizeof(HashEntry)));
214
215 if(scbMemory.IsOverflow())
216 ThrowHR(E_INVALIDARG);
217
218 if (pAllocator)
219 {
220 m_pMemoryStart = (BYTE*)pAllocator->Alloc(scbMemory);
221 }
222 else
223 { // We're given the number of hash table entries we're going to insert,
224 // so we can allocate the appropriate size
225 m_pMemoryStart = new BYTE[scbMemory.Value()];
226 }
227
228 INDEBUG(m_pDebugEndMemory = m_pMemoryStart + scbMemory.Value();)
229
230 // Current alloc ptr
231 m_pMemory = m_pMemoryStart;
232
233 // Allocate the buckets out of the alloc ptr
234 m_pBuckets = (HashEntry**) m_pMemory;
235 m_pMemory += sizeof(HashEntry*)*m_dwNumBuckets;
236
237 // Buckets all point to empty lists to begin with
238 memset(m_pBuckets, 0, scbMemory.Value());
239}
240
241//***************************************************************************************
242// Insert new entry at head of list
243template <typename Data>
244void
245FixedCapacityStackingAllocatedUTF8StringHash<Data>::Insert(
246 LPCUTF8 pszName,
247 const Data & data)
248{
249 LIMITED_METHOD_CONTRACT;
250 DWORD dwHash = GetHashCode(pszName);
251 DWORD dwBucket = dwHash % m_dwNumBuckets;
252 HashEntry * pNewEntry;
253
254 pNewEntry = (HashEntry *) m_pMemory;
255 m_pMemory += sizeof(HashEntry);
256
257 _ASSERTE(m_pMemory <= m_pDebugEndMemory);
258
259 // Insert at head of bucket chain
260 pNewEntry->m_pNext = m_pBuckets[dwBucket];
261 pNewEntry->m_data = data;
262 pNewEntry->m_dwHashValue = dwHash;
263 pNewEntry->m_pKey = pszName;
264
265 m_pBuckets[dwBucket] = pNewEntry;
266}
267
268//***************************************************************************************
269// Return the first HashEntry with this name, or NULL if there is no such entry
270template <typename Data>
271typename FixedCapacityStackingAllocatedUTF8StringHash<Data>::HashEntry *
272FixedCapacityStackingAllocatedUTF8StringHash<Data>::Lookup(
273 LPCUTF8 pszName)
274{
275 STATIC_CONTRACT_NOTHROW;
276 STATIC_CONTRACT_GC_NOTRIGGER;
277 STATIC_CONTRACT_FORBID_FAULT;
278
279 DWORD dwHash = GetHashCode(pszName);
280 DWORD dwBucket = dwHash % m_dwNumBuckets;
281 HashEntry * pSearch;
282
283 for (pSearch = m_pBuckets[dwBucket]; pSearch; pSearch = pSearch->m_pNext)
284 {
285 if (pSearch->m_dwHashValue == dwHash && !strcmp(pSearch->m_pKey, pszName))
286 {
287 return pSearch;
288 }
289 }
290
291 return NULL;
292}
293
294//***************************************************************************************
295// Return the first HashEntry with this name, or NULL if there is no such entry
296template <typename Data>
297typename FixedCapacityStackingAllocatedUTF8StringHash<Data>::HashEntry *
298FixedCapacityStackingAllocatedUTF8StringHash<Data>::FindNext(
299 HashEntry * pEntry)
300{
301 STATIC_CONTRACT_NOTHROW;
302 STATIC_CONTRACT_GC_NOTRIGGER;
303 STATIC_CONTRACT_FORBID_FAULT;
304 CONSISTENCY_CHECK(CheckPointer(pEntry));
305
306 LPCUTF8 key = pEntry->m_pKey;
307 DWORD hash = pEntry->m_dwHashValue;
308
309 pEntry = pEntry->m_pNext;
310 while (pEntry != NULL)
311 {
312 if (pEntry->m_dwHashValue == hash &&
313 strcmp(pEntry->m_pKey, key) == 0)
314 {
315 break;
316 }
317 pEntry = pEntry->m_pNext;
318 }
319
320 return pEntry;
321}
322
323#endif // DACCESS_COMPILE
324
325#ifndef DACCESS_COMPILE
326
327//***************************************************************************************
328#define CALL_TYPE_HANDLE_METHOD(m) \
329 ((IsRTType()) ? (AsRTType()->m()) : (AsMDType()->m()))
330
331//***************************************************************************************
332inline MethodTableBuilder::bmtTypeHandle
333MethodTableBuilder::bmtTypeHandle::GetParentType() const
334{
335 LIMITED_METHOD_CONTRACT;
336 return CALL_TYPE_HANDLE_METHOD(GetParentType);
337}
338
339//***************************************************************************************
340inline bool
341MethodTableBuilder::bmtTypeHandle::IsNested() const
342{
343 LIMITED_METHOD_CONTRACT;
344 return CALL_TYPE_HANDLE_METHOD(IsNested);
345}
346
347//***************************************************************************************
348inline mdTypeDef
349MethodTableBuilder::bmtTypeHandle::GetEnclosingTypeToken() const
350{
351 LIMITED_METHOD_CONTRACT;
352 return CALL_TYPE_HANDLE_METHOD(GetEnclosingTypeToken);
353}
354
355//***************************************************************************************
356inline Module *
357MethodTableBuilder::bmtTypeHandle::GetModule() const
358{
359 LIMITED_METHOD_CONTRACT;
360 return CALL_TYPE_HANDLE_METHOD(GetModule);
361}
362
363//***************************************************************************************
364inline mdTypeDef
365MethodTableBuilder::bmtTypeHandle::GetTypeDefToken() const
366{
367 LIMITED_METHOD_CONTRACT;
368 return CALL_TYPE_HANDLE_METHOD(GetTypeDefToken);
369}
370
371//***************************************************************************************
372inline const Substitution &
373MethodTableBuilder::bmtTypeHandle::GetSubstitution() const
374{
375 LIMITED_METHOD_CONTRACT;
376 return CALL_TYPE_HANDLE_METHOD(GetSubstitution);
377}
378
379//***************************************************************************************
380inline MethodTable *
381MethodTableBuilder::bmtTypeHandle::GetMethodTable() const
382{
383 LIMITED_METHOD_CONTRACT;
384 return CALL_TYPE_HANDLE_METHOD(GetMethodTable);
385}
386
387//***************************************************************************************
388inline DWORD
389MethodTableBuilder::bmtTypeHandle::GetAttrs() const
390{
391 LIMITED_METHOD_CONTRACT;
392 return CALL_TYPE_HANDLE_METHOD(GetAttrs);
393}
394
395//***************************************************************************************
396inline bool
397MethodTableBuilder::bmtTypeHandle::IsInterface() const
398{
399 LIMITED_METHOD_CONTRACT;
400 return CALL_TYPE_HANDLE_METHOD(IsInterface);
401}
402
403#undef CALL_TYPE_HANDLE_METHOD
404
405//***************************************************************************************
406#define CALL_METHOD_HANDLE_METHOD(m) \
407 ((IsRTMethod()) ? (AsRTMethod()->m()) : (AsMDMethod()->m()))
408
409//***************************************************************************************
410inline MethodTableBuilder::bmtTypeHandle
411MethodTableBuilder::bmtMethodHandle::GetOwningType() const
412{
413 LIMITED_METHOD_CONTRACT;
414 if (IsRTMethod())
415 return bmtTypeHandle(AsRTMethod()->GetOwningType());
416 else
417 return bmtTypeHandle(AsMDMethod()->GetOwningType());
418}
419
420//***************************************************************************************
421inline DWORD
422MethodTableBuilder::bmtMethodHandle::GetDeclAttrs() const
423{
424 LIMITED_METHOD_CONTRACT;
425 return CALL_METHOD_HANDLE_METHOD(GetDeclAttrs);
426}
427
428//***************************************************************************************
429inline DWORD
430MethodTableBuilder::bmtMethodHandle::GetImplAttrs() const
431{
432 LIMITED_METHOD_CONTRACT;
433 return CALL_METHOD_HANDLE_METHOD(GetImplAttrs);
434}
435
436//***************************************************************************************
437inline MethodTableBuilder::SLOT_INDEX
438MethodTableBuilder::bmtMethodHandle::GetSlotIndex() const
439{
440 LIMITED_METHOD_CONTRACT;
441 return CALL_METHOD_HANDLE_METHOD(GetSlotIndex);
442}
443
444//***************************************************************************************
445inline const MethodTableBuilder::MethodSignature &
446MethodTableBuilder::bmtMethodHandle::GetMethodSignature() const
447{
448 LIMITED_METHOD_CONTRACT;
449 return CALL_METHOD_HANDLE_METHOD(GetMethodSignature);
450}
451
452//***************************************************************************************
453inline MethodDesc *
454MethodTableBuilder::bmtMethodHandle::GetMethodDesc() const
455{
456 LIMITED_METHOD_CONTRACT;
457 return CALL_METHOD_HANDLE_METHOD(GetMethodDesc);
458}
459
460#undef CALL_METHOD_HANDLE_METHOD
461
462//***************************************************************************************
463inline DWORD
464MethodTableBuilder::bmtRTMethod::GetDeclAttrs() const
465{
466 LIMITED_METHOD_CONTRACT;
467 return GetMethodDesc()->GetAttrs();
468}
469
470//***************************************************************************************
471inline DWORD
472MethodTableBuilder::bmtRTMethod::GetImplAttrs() const
473{
474 LIMITED_METHOD_CONTRACT;
475 return GetMethodDesc()->GetImplAttrs();
476}
477
478//***************************************************************************************
479inline MethodTableBuilder::SLOT_INDEX
480MethodTableBuilder::bmtRTMethod::GetSlotIndex() const
481{
482 LIMITED_METHOD_CONTRACT;
483 return GetMethodDesc()->GetSlot();
484}
485
486//***************************************************************************************
487inline void
488MethodTableBuilder::bmtMDMethod::SetSlotIndex(SLOT_INDEX idx)
489{
490 LIMITED_METHOD_CONTRACT;
491 CONSISTENCY_CHECK(m_pMD == NULL);
492 m_slotIndex = idx;
493}
494
495//***************************************************************************************
496inline void
497MethodTableBuilder::bmtMDMethod::SetUnboxedSlotIndex(SLOT_INDEX idx)
498{
499 LIMITED_METHOD_CONTRACT;
500 CONSISTENCY_CHECK(m_pUnboxedMD == NULL);
501 m_unboxedSlotIndex = idx;
502}
503
504//***************************************************************************************
505inline DWORD
506MethodTableBuilder::GetMethodClassification(MethodTableBuilder::METHOD_TYPE type)
507{
508 LIMITED_METHOD_CONTRACT;
509 // Verify that the enums are in sync, so we can do the conversion by simple cast.
510 C_ASSERT((DWORD)METHOD_TYPE_NORMAL == (DWORD)mcIL);
511 C_ASSERT((DWORD)METHOD_TYPE_FCALL == (DWORD)mcFCall);
512 C_ASSERT((DWORD)METHOD_TYPE_NDIRECT == (DWORD)mcNDirect);
513 C_ASSERT((DWORD)METHOD_TYPE_EEIMPL == (DWORD)mcEEImpl);
514 C_ASSERT((DWORD)METHOD_TYPE_INSTANTIATED == (DWORD)mcInstantiated);
515#ifdef FEATURE_COMINTEROP
516 C_ASSERT((DWORD)METHOD_TYPE_COMINTEROP == (DWORD)mcComInterop);
517#endif
518
519 return (DWORD)type;
520}
521
522#endif // _METHODTABLEBUILDER_INL_
523
524