Merge pull request #14619 from briansull/emitter-cleanup
[platform/upstream/coreclr.git] / src / vm / methodtablebuilder.inl
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 //***************************************************************************************
18 inline MethodTableBuilder::DeclaredMethodIterator::DeclaredMethodIterator(
19             MethodTableBuilder &mtb) : m_mtb(mtb), m_idx(-1)
20 {
21     LIMITED_METHOD_CONTRACT;
22 }
23
24 //***************************************************************************************
25 inline 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 //***************************************************************************************
34 inline 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 //***************************************************************************************
45 inline 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 //***************************************************************************************
56 inline void MethodTableBuilder::DeclaredMethodIterator::ResetToEnd()
57 {
58     LIMITED_METHOD_CONTRACT;
59     m_idx = (int)m_mtb.NumDeclaredMethods();
60 }
61
62 //***************************************************************************************
63 inline 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 //***************************************************************************************
71 inline DWORD MethodTableBuilder::DeclaredMethodIterator::Attrs()
72 {
73     LIMITED_METHOD_CONTRACT;
74     return GetMDMethod()->GetDeclAttrs();
75 }
76
77 //***************************************************************************************
78 inline DWORD MethodTableBuilder::DeclaredMethodIterator::RVA()
79 {
80     LIMITED_METHOD_CONTRACT;
81     return GetMDMethod()->GetRVA();
82 }
83
84 //***************************************************************************************
85 inline DWORD MethodTableBuilder::DeclaredMethodIterator::ImplFlags()
86 {
87     LIMITED_METHOD_CONTRACT;
88     return GetMDMethod()->GetImplAttrs();
89 }
90
91 //***************************************************************************************
92 inline LPCSTR MethodTableBuilder::DeclaredMethodIterator::Name()
93 {
94     STANDARD_VM_CONTRACT;
95     return GetMDMethod()->GetMethodSignature().GetName();
96 }
97
98 //***************************************************************************************
99 inline 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 //***************************************************************************************
108 inline MethodTableBuilder::METHOD_IMPL_TYPE MethodTableBuilder::DeclaredMethodIterator::MethodImpl()
109 {
110     LIMITED_METHOD_CONTRACT;
111     return GetMDMethod()->GetMethodImplType();
112 }
113
114 //***************************************************************************************
115 inline BOOL  MethodTableBuilder::DeclaredMethodIterator::IsMethodImpl()
116 {
117     LIMITED_METHOD_CONTRACT;
118     return MethodImpl() == METHOD_IMPL;
119 }
120
121 //***************************************************************************************
122 inline MethodTableBuilder::METHOD_TYPE MethodTableBuilder::DeclaredMethodIterator::MethodType()
123 {
124     LIMITED_METHOD_CONTRACT;
125     return GetMDMethod()->GetMethodType();
126 }
127
128 //***************************************************************************************
129 inline MethodTableBuilder::bmtMDMethod *
130 MethodTableBuilder::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 //*******************************************************************************
138 inline class MethodDesc *
139 MethodTableBuilder::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 //***************************************************************************************
170 inline MethodTableBuilder::bmtMDMethod *
171 MethodTableBuilder::DeclaredMethodIterator::operator->()
172 {
173     return GetMDMethod();
174 }
175
176 //***************************************************************************************
177 inline bool
178 MethodTableBuilder::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
192 template <typename Data>
193 void
194 FixedCapacityStackingAllocatedUTF8StringHash<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
243 template <typename Data>
244 void
245 FixedCapacityStackingAllocatedUTF8StringHash<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
270 template <typename Data>
271 typename FixedCapacityStackingAllocatedUTF8StringHash<Data>::HashEntry *
272 FixedCapacityStackingAllocatedUTF8StringHash<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
296 template <typename Data>
297 typename FixedCapacityStackingAllocatedUTF8StringHash<Data>::HashEntry *
298 FixedCapacityStackingAllocatedUTF8StringHash<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 //***************************************************************************************
332 inline MethodTableBuilder::bmtTypeHandle
333 MethodTableBuilder::bmtTypeHandle::GetParentType() const
334 {
335     LIMITED_METHOD_CONTRACT;
336     return CALL_TYPE_HANDLE_METHOD(GetParentType);
337 }
338
339 //***************************************************************************************
340 inline bool
341 MethodTableBuilder::bmtTypeHandle::IsNested() const
342 {
343     LIMITED_METHOD_CONTRACT;
344     return CALL_TYPE_HANDLE_METHOD(IsNested);
345 }
346
347 //***************************************************************************************
348 inline mdTypeDef
349 MethodTableBuilder::bmtTypeHandle::GetEnclosingTypeToken() const
350 {
351     LIMITED_METHOD_CONTRACT;
352     return CALL_TYPE_HANDLE_METHOD(GetEnclosingTypeToken);
353 }
354
355 //***************************************************************************************
356 inline Module *
357 MethodTableBuilder::bmtTypeHandle::GetModule() const
358 {
359     LIMITED_METHOD_CONTRACT;
360     return CALL_TYPE_HANDLE_METHOD(GetModule);
361 }
362
363 //***************************************************************************************
364 inline mdTypeDef
365 MethodTableBuilder::bmtTypeHandle::GetTypeDefToken() const
366 {
367     LIMITED_METHOD_CONTRACT;
368     return CALL_TYPE_HANDLE_METHOD(GetTypeDefToken);
369 }
370
371 //***************************************************************************************
372 inline const Substitution &
373 MethodTableBuilder::bmtTypeHandle::GetSubstitution() const
374 {
375     LIMITED_METHOD_CONTRACT;
376     return CALL_TYPE_HANDLE_METHOD(GetSubstitution);
377 }
378
379 //***************************************************************************************
380 inline MethodTable *
381 MethodTableBuilder::bmtTypeHandle::GetMethodTable() const
382 {
383     LIMITED_METHOD_CONTRACT;
384     return CALL_TYPE_HANDLE_METHOD(GetMethodTable);
385 }
386
387 //***************************************************************************************
388 inline DWORD
389 MethodTableBuilder::bmtTypeHandle::GetAttrs() const
390 {
391     LIMITED_METHOD_CONTRACT;
392     return CALL_TYPE_HANDLE_METHOD(GetAttrs);
393 }
394
395 //***************************************************************************************
396 inline bool
397 MethodTableBuilder::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 //***************************************************************************************
410 inline MethodTableBuilder::bmtTypeHandle
411 MethodTableBuilder::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 //***************************************************************************************
421 inline DWORD
422 MethodTableBuilder::bmtMethodHandle::GetDeclAttrs() const
423 {
424     LIMITED_METHOD_CONTRACT;
425     return CALL_METHOD_HANDLE_METHOD(GetDeclAttrs);
426 }
427
428 //***************************************************************************************
429 inline DWORD
430 MethodTableBuilder::bmtMethodHandle::GetImplAttrs() const
431 {
432     LIMITED_METHOD_CONTRACT;
433     return CALL_METHOD_HANDLE_METHOD(GetImplAttrs);
434 }
435
436 //***************************************************************************************
437 inline MethodTableBuilder::SLOT_INDEX
438 MethodTableBuilder::bmtMethodHandle::GetSlotIndex() const
439 {
440     LIMITED_METHOD_CONTRACT;
441     return CALL_METHOD_HANDLE_METHOD(GetSlotIndex);
442 }
443
444 //***************************************************************************************
445 inline const MethodTableBuilder::MethodSignature &
446 MethodTableBuilder::bmtMethodHandle::GetMethodSignature() const
447 {
448     LIMITED_METHOD_CONTRACT;
449     return CALL_METHOD_HANDLE_METHOD(GetMethodSignature);
450 }
451
452 //***************************************************************************************
453 inline MethodDesc *
454 MethodTableBuilder::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 //***************************************************************************************
463 inline DWORD
464 MethodTableBuilder::bmtRTMethod::GetDeclAttrs() const
465 {
466     LIMITED_METHOD_CONTRACT;
467     return GetMethodDesc()->GetAttrs();
468 }
469
470 //***************************************************************************************
471 inline DWORD
472 MethodTableBuilder::bmtRTMethod::GetImplAttrs() const
473 {
474     LIMITED_METHOD_CONTRACT;
475     return GetMethodDesc()->GetImplAttrs();
476 }
477
478 //***************************************************************************************
479 inline MethodTableBuilder::SLOT_INDEX
480 MethodTableBuilder::bmtRTMethod::GetSlotIndex() const
481 {
482     LIMITED_METHOD_CONTRACT; 
483     return GetMethodDesc()->GetSlot();
484 }
485
486 //***************************************************************************************
487 inline void
488 MethodTableBuilder::bmtMDMethod::SetSlotIndex(SLOT_INDEX idx)
489 {
490     LIMITED_METHOD_CONTRACT;
491     CONSISTENCY_CHECK(m_pMD == NULL);
492     m_slotIndex = idx;
493 }
494
495 //***************************************************************************************
496 inline void
497 MethodTableBuilder::bmtMDMethod::SetUnboxedSlotIndex(SLOT_INDEX idx)
498 {
499     LIMITED_METHOD_CONTRACT;
500     CONSISTENCY_CHECK(m_pUnboxedMD == NULL);
501     m_unboxedSlotIndex = idx;
502 }
503
504 //***************************************************************************************
505 inline DWORD
506 MethodTableBuilder::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