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 | |
524 | |