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: CEELOAD.INL |
6 | // |
7 | |
8 | // |
9 | // CEELOAD.INL has inline methods from CEELOAD.H. |
10 | // =========================================================================== |
11 | |
12 | #ifndef CEELOAD_INL_ |
13 | #define CEELOAD_INL_ |
14 | |
15 | template<typename TYPE> |
16 | inline |
17 | TYPE LookupMap<TYPE>::GetValueAt(PTR_TADDR pValue, TADDR* pFlags, TADDR supportedFlags) |
18 | { |
19 | WRAPPER_NO_CONTRACT; |
20 | SUPPORTS_DAC; |
21 | TYPE value = RelativePointer<TYPE>::GetValueMaybeNullAtPtr(dac_cast<TADDR>(pValue)); |
22 | |
23 | if (pFlags) |
24 | *pFlags = dac_cast<TADDR>(value) & supportedFlags; |
25 | |
26 | return (TYPE)(dac_cast<TADDR>(value) & ~supportedFlags); |
27 | } |
28 | |
29 | #ifndef DACCESS_COMPILE |
30 | |
31 | template<typename TYPE> |
32 | inline |
33 | void LookupMap<TYPE>::SetValueAt(PTR_TADDR pValue, TYPE value, TADDR flags) |
34 | { |
35 | WRAPPER_NO_CONTRACT; |
36 | |
37 | value = (TYPE)(dac_cast<TADDR>(value) | flags); |
38 | |
39 | RelativePointer<TYPE> *pRelPtr = (RelativePointer<TYPE> *)pValue; |
40 | pRelPtr->SetValue(value); |
41 | } |
42 | |
43 | // |
44 | // Specialization of Get/SetValueAt methods to support maps of pointer-sized value types |
45 | // |
46 | template<> |
47 | inline |
48 | SIZE_T LookupMap<SIZE_T>::GetValueAt(PTR_TADDR pValue, TADDR* pFlags, TADDR supportedFlags) |
49 | { |
50 | WRAPPER_NO_CONTRACT; |
51 | |
52 | TADDR value = *pValue; |
53 | |
54 | if (pFlags) |
55 | *pFlags = value & supportedFlags; |
56 | |
57 | return (value & ~supportedFlags); |
58 | } |
59 | |
60 | template<> |
61 | inline |
62 | void LookupMap<SIZE_T>::SetValueAt(PTR_TADDR pValue, SIZE_T value, TADDR flags) |
63 | { |
64 | WRAPPER_NO_CONTRACT; |
65 | *pValue = value | flags; |
66 | } |
67 | #endif // DACCESS_COMPILE |
68 | |
69 | // |
70 | // Specialization of GetValueAt methods for tables with cross-module references |
71 | // |
72 | template<> |
73 | inline |
74 | PTR_TypeRef LookupMap<PTR_TypeRef>::GetValueAt(PTR_TADDR pValue, TADDR* pFlags, TADDR supportedFlags) |
75 | { |
76 | WRAPPER_NO_CONTRACT; |
77 | SUPPORTS_DAC; |
78 | |
79 | // Strip flags before RelativeFixupPointer dereference |
80 | TADDR value = *pValue; |
81 | |
82 | TADDR flags = (value & supportedFlags); |
83 | value -= flags; |
84 | value = ((RelativeFixupPointer<TADDR>&)(value)).GetValueMaybeNull(dac_cast<TADDR>(pValue)); |
85 | |
86 | if (pFlags) |
87 | *pFlags = flags; |
88 | |
89 | return dac_cast<PTR_TypeRef>(value); |
90 | } |
91 | |
92 | template<> |
93 | inline |
94 | PTR_Module LookupMap<PTR_Module>::GetValueAt(PTR_TADDR pValue, TADDR* pFlags, TADDR supportedFlags) |
95 | { |
96 | WRAPPER_NO_CONTRACT; |
97 | SUPPORTS_DAC; |
98 | |
99 | // Strip flags before RelativeFixupPointer dereference |
100 | TADDR value = *pValue; |
101 | |
102 | TADDR flags = (value & supportedFlags); |
103 | value -= flags; |
104 | value = ((RelativeFixupPointer<TADDR>&)(value)).GetValueMaybeNull(dac_cast<TADDR>(pValue)); |
105 | |
106 | if (pFlags) |
107 | *pFlags = flags; |
108 | |
109 | return dac_cast<PTR_Module>(value); |
110 | } |
111 | |
112 | template<> |
113 | inline |
114 | PTR_MemberRef LookupMap<PTR_MemberRef>::GetValueAt(PTR_TADDR pValue, TADDR* pFlags, TADDR supportedFlags) |
115 | { |
116 | WRAPPER_NO_CONTRACT; |
117 | SUPPORTS_DAC; |
118 | |
119 | // Strip flags before RelativeFixupPointer dereference |
120 | TADDR value = *pValue; |
121 | |
122 | TADDR flags = (value & supportedFlags); |
123 | value -= flags; |
124 | value = ((RelativeFixupPointer<TADDR>&)(value)).GetValueMaybeNull(dac_cast<TADDR>(pValue)); |
125 | |
126 | if (pFlags) |
127 | *pFlags = flags; |
128 | |
129 | return dac_cast<PTR_MemberRef>(value); |
130 | |
131 | } |
132 | |
133 | // Retrieve the value associated with a rid |
134 | template<typename TYPE> |
135 | TYPE LookupMap<TYPE>::GetElement(DWORD rid, TADDR* pFlags) |
136 | { |
137 | WRAPPER_NO_CONTRACT; |
138 | SUPPORTS_DAC; |
139 | |
140 | #ifdef FEATURE_PREJIT |
141 | if (MapIsCompressed()) |
142 | { |
143 | // Can't access compressed entries directly: we need to go through the special helper. However we |
144 | // must still check the hot cache first (this would normally be done by GetElementPtr() below, but |
145 | // we can't integrate compressed support there since compressed entries don't have addresses, at |
146 | // least not byte-aligned ones). |
147 | PTR_TADDR pHotItemValue = FindHotItemValuePtr(rid); |
148 | if (pHotItemValue) |
149 | return GetValueAt(pHotItemValue, pFlags, supportedFlags); |
150 | |
151 | TADDR value = GetValueFromCompressedMap(rid); |
152 | |
153 | if (value == NULL) |
154 | { |
155 | if ((pNext == NULL) || (rid < dwCount)) |
156 | { |
157 | if (pFlags) |
158 | *pFlags = NULL; |
159 | return NULL; |
160 | } |
161 | |
162 | return dac_cast<DPTR(LookupMap)>(pNext)->GetElement(rid - dwCount, pFlags); |
163 | } |
164 | |
165 | if (pFlags) |
166 | *pFlags = (value & supportedFlags); |
167 | |
168 | return (TYPE)(value & ~supportedFlags); |
169 | } |
170 | #endif // FEATURE_PREJIT |
171 | |
172 | PTR_TADDR pElement = GetElementPtr(rid); |
173 | return (pElement != NULL) ? GetValueAt(pElement, pFlags, supportedFlags) : NULL; |
174 | } |
175 | |
176 | // Stores an association in a map that has been previously grown to |
177 | // the required size. Will never throw or fail. |
178 | template<typename TYPE> |
179 | void LookupMap<TYPE>::SetElement(DWORD rid, TYPE value, TADDR flags) |
180 | { |
181 | WRAPPER_NO_CONTRACT; |
182 | SUPPORTS_DAC; |
183 | BOOL fSuccess; |
184 | fSuccess = TrySetElement(rid, value, flags); |
185 | _ASSERTE(fSuccess); |
186 | } |
187 | |
188 | |
189 | #ifndef DACCESS_COMPILE |
190 | |
191 | // Try to store an association in a map. Will never throw or fail. |
192 | template<typename TYPE> |
193 | BOOL LookupMap<TYPE>::TrySetElement(DWORD rid, TYPE value, TADDR flags) |
194 | { |
195 | CONTRACTL |
196 | { |
197 | INSTANCE_CHECK; |
198 | NOTHROW; |
199 | GC_NOTRIGGER; |
200 | MODE_ANY; |
201 | } |
202 | CONTRACTL_END; |
203 | |
204 | PTR_TADDR pElement = GetElementPtr(rid); |
205 | if (pElement == NULL) |
206 | return FALSE; |
207 | #ifdef _DEBUG |
208 | // Once set, the values in LookupMap should be immutable. |
209 | TADDR oldFlags; |
210 | TYPE oldValue = GetValueAt(pElement, &oldFlags, supportedFlags); |
211 | _ASSERTE(oldValue == NULL || (oldValue == value && oldFlags == flags)); |
212 | #endif |
213 | // Avoid unnecessary writes - do not overwrite existing value |
214 | if (*pElement == NULL) |
215 | { |
216 | if (!EnsureWritablePagesNoThrow(pElement, sizeof (TYPE))) |
217 | return FALSE; |
218 | SetValueAt(pElement, value, flags); |
219 | } |
220 | return TRUE; |
221 | } |
222 | |
223 | // Stores an association in a map. Grows the map as necessary. |
224 | template<typename TYPE> |
225 | void LookupMap<TYPE>::AddElement(Module * pModule, DWORD rid, TYPE value, TADDR flags) |
226 | { |
227 | CONTRACTL |
228 | { |
229 | INSTANCE_CHECK; |
230 | PRECONDITION(CheckPointer(pModule)); |
231 | THROWS; |
232 | GC_NOTRIGGER; |
233 | MODE_ANY; |
234 | INJECT_FAULT(ThrowOutOfMemory();); |
235 | } |
236 | CONTRACTL_END; |
237 | |
238 | PTR_TADDR pElement = GetElementPtr(rid); |
239 | if (pElement == NULL) |
240 | pElement = GrowMap(pModule, rid); |
241 | #ifdef _DEBUG |
242 | // Once set, the values in LookupMap should be immutable. |
243 | TADDR oldFlags; |
244 | TYPE oldValue = GetValueAt(pElement, &oldFlags, supportedFlags); |
245 | _ASSERTE(oldValue == NULL || (oldValue == value && oldFlags == flags)); |
246 | #endif |
247 | // Avoid unnecessary writes - do not overwrite existing value |
248 | if (*pElement == NULL) |
249 | { |
250 | EnsureWritablePages(pElement, sizeof (TYPE)); |
251 | SetValueAt(pElement, value, flags); |
252 | } |
253 | } |
254 | |
255 | |
256 | // Ensures that the map has space for this element |
257 | template<typename TYPE> |
258 | inline |
259 | void LookupMap<TYPE>::EnsureElementCanBeStored(Module * pModule, DWORD rid) |
260 | { |
261 | CONTRACTL |
262 | { |
263 | INSTANCE_CHECK; |
264 | PRECONDITION(CheckPointer(pModule)); |
265 | THROWS; |
266 | GC_NOTRIGGER; |
267 | MODE_ANY; |
268 | INJECT_FAULT(ThrowOutOfMemory();); |
269 | } |
270 | CONTRACTL_END; |
271 | |
272 | #ifdef FEATURE_PREJIT |
273 | // don't attempt to call GetElementPtr for rids inside the compressed portion of |
274 | // a multi-node map |
275 | if (MapIsCompressed() && rid < dwCount) |
276 | return; |
277 | #endif |
278 | PTR_TADDR pElement = GetElementPtr(rid); |
279 | if (pElement == NULL) |
280 | GrowMap(pModule, rid); |
281 | |
282 | EnsureWritablePages(pElement, sizeof (TYPE)); |
283 | } |
284 | |
285 | #endif // DACCESS_COMPILE |
286 | |
287 | // Find the given value in the table and return its RID |
288 | template<typename TYPE> |
289 | DWORD LookupMap<TYPE>::Find(TYPE value, TADDR* pFlags) |
290 | { |
291 | CONTRACTL |
292 | { |
293 | INSTANCE_CHECK; |
294 | NOTHROW; |
295 | GC_NOTRIGGER; |
296 | MODE_ANY; |
297 | } |
298 | CONTRACTL_END; |
299 | |
300 | Iterator it(this); |
301 | |
302 | DWORD rid = 0; |
303 | while (it.Next()) |
304 | { |
305 | TADDR flags; |
306 | if (it.GetElementAndFlags(&flags) == value && (!pFlags || *pFlags == flags)) |
307 | return rid; |
308 | rid++; |
309 | } |
310 | |
311 | return 0; |
312 | } |
313 | |
314 | template<typename TYPE> |
315 | inline |
316 | LookupMap<TYPE>::Iterator::Iterator(LookupMap* map) |
317 | { |
318 | LIMITED_METHOD_DAC_CONTRACT; |
319 | |
320 | m_map = map; |
321 | m_index = (DWORD) -1; |
322 | #ifdef FEATURE_PREJIT |
323 | // Compressed map support |
324 | m_currentEntry = 0; |
325 | if (map->pTable != NULL) |
326 | m_tableStream = BitStreamReader(dac_cast<PTR_CBYTE>(map->pTable)); |
327 | #endif // FEATURE_PREJIT |
328 | } |
329 | |
330 | template<typename TYPE> |
331 | inline BOOL |
332 | LookupMap<TYPE>::Iterator::Next() |
333 | { |
334 | LIMITED_METHOD_DAC_CONTRACT; |
335 | |
336 | if (!m_map || !m_map->pTable) |
337 | { |
338 | return FALSE; |
339 | } |
340 | |
341 | m_index++; |
342 | if (m_index == m_map->dwCount) |
343 | { |
344 | m_map = dac_cast<DPTR(LookupMap)>(m_map->pNext); |
345 | if (!m_map || !m_map->pTable) |
346 | { |
347 | return FALSE; |
348 | } |
349 | m_index = 0; |
350 | } |
351 | |
352 | #ifdef FEATURE_PREJIT |
353 | // For a compressed map we need to read the encoded delta for the next entry and apply it to our previous |
354 | // value to obtain the new current value. |
355 | if (m_map->MapIsCompressed()) |
356 | m_currentEntry = m_map->GetNextCompressedEntry(&m_tableStream, m_currentEntry); |
357 | #endif // FEATURE_PREJIT |
358 | |
359 | return TRUE; |
360 | } |
361 | |
362 | template<typename TYPE> |
363 | inline TYPE |
364 | LookupMap<TYPE>::Iterator::GetElement(TADDR* pFlags) |
365 | { |
366 | SUPPORTS_DAC; |
367 | WRAPPER_NO_CONTRACT; |
368 | |
369 | #ifdef FEATURE_PREJIT |
370 | // The current value for a compressed map is actually a map-based RVA. A zero RVA indicates a NULL pointer |
371 | // but otherwise we can recover the full pointer by adding the address of the map we're iterating. |
372 | // Note that most LookupMaps are embedded structures (in Module) so we can't directly dac_cast<TADDR> our |
373 | // "this" pointer for DAC builds. Instead we have to use the slightly slower (in DAC) but more flexible |
374 | // PTR_HOST_INT_TO_TADDR() which copes with interior host pointers. |
375 | if (m_map->MapIsCompressed()) |
376 | { |
377 | TADDR value = m_currentEntry ? PTR_HOST_INT_TO_TADDR(m_map) + m_currentEntry : 0; |
378 | |
379 | if (pFlags) |
380 | *pFlags = (value & m_map->supportedFlags); |
381 | |
382 | return (TYPE)(value & ~m_map->supportedFlags); |
383 | } |
384 | else |
385 | #endif // FEATURE_PREJIT |
386 | return GetValueAt(m_map->GetIndexPtr(m_index), pFlags, m_map->supportedFlags); |
387 | } |
388 | |
389 | inline PTR_Assembly Module::GetAssembly() const |
390 | { |
391 | LIMITED_METHOD_CONTRACT; |
392 | SUPPORTS_DAC; |
393 | |
394 | return m_pAssembly; |
395 | } |
396 | |
397 | inline MethodDesc *Module::LookupMethodDef(mdMethodDef token) |
398 | { |
399 | CONTRACTL |
400 | { |
401 | NOTHROW; |
402 | GC_NOTRIGGER; |
403 | SO_TOLERANT; |
404 | MODE_ANY; |
405 | SUPPORTS_DAC; |
406 | } |
407 | CONTRACTL_END |
408 | |
409 | _ASSERTE(TypeFromToken(token) == mdtMethodDef); |
410 | g_IBCLogger.LogRidMapAccess( MakePair( this, token ) ); |
411 | |
412 | return m_MethodDefToDescMap.GetElement(RidFromToken(token)); |
413 | } |
414 | |
415 | inline MethodDesc *Module::LookupMemberRefAsMethod(mdMemberRef token) |
416 | { |
417 | LIMITED_METHOD_DAC_CONTRACT; |
418 | |
419 | _ASSERTE(TypeFromToken(token) == mdtMemberRef); |
420 | g_IBCLogger.LogRidMapAccess( MakePair( this, token ) ); |
421 | BOOL flags = FALSE; |
422 | PTR_MemberRef pMemberRef = m_pMemberRefToDescHashTable->GetValue(token, &flags); |
423 | return flags ? dac_cast<PTR_MethodDesc>(pMemberRef) : NULL; |
424 | } |
425 | |
426 | inline Assembly *Module::LookupAssemblyRef(mdAssemblyRef token) |
427 | { |
428 | WRAPPER_NO_CONTRACT; |
429 | SUPPORTS_DAC; |
430 | |
431 | _ASSERTE(TypeFromToken(token) == mdtAssemblyRef); |
432 | PTR_Module module= m_ManifestModuleReferencesMap.GetElement(RidFromToken(token)); |
433 | return module?module->GetAssembly():NULL; |
434 | } |
435 | |
436 | #ifndef DACCESS_COMPILE |
437 | inline void Module::ForceStoreAssemblyRef(mdAssemblyRef token, Assembly *value) |
438 | { |
439 | WRAPPER_NO_CONTRACT; // THROWS/GC_NOTRIGGER/INJECT_FAULT()/MODE_ANY |
440 | _ASSERTE(value->GetManifestModule()); |
441 | _ASSERTE(TypeFromToken(token) == mdtAssemblyRef); |
442 | |
443 | m_ManifestModuleReferencesMap.AddElement(this, RidFromToken(token), value->GetManifestModule()); |
444 | } |
445 | |
446 | inline void Module::StoreAssemblyRef(mdAssemblyRef token, Assembly *value) |
447 | { |
448 | WRAPPER_NO_CONTRACT; |
449 | _ASSERTE(value->GetManifestModule()); |
450 | _ASSERTE(TypeFromToken(token) == mdtAssemblyRef); |
451 | m_ManifestModuleReferencesMap.TrySetElement(RidFromToken(token), value->GetManifestModule()); |
452 | } |
453 | |
454 | inline mdAssemblyRef Module::FindAssemblyRef(Assembly *targetAssembly) |
455 | { |
456 | WRAPPER_NO_CONTRACT; |
457 | |
458 | return m_ManifestModuleReferencesMap.Find(targetAssembly->GetManifestModule()) | mdtAssemblyRef; |
459 | } |
460 | |
461 | #endif //DACCESS_COMPILE |
462 | |
463 | inline BOOL Module::IsEditAndContinueCapable() |
464 | { |
465 | WRAPPER_NO_CONTRACT; |
466 | SUPPORTS_DAC; |
467 | |
468 | BOOL isEnCCapable = IsEditAndContinueCapable(m_pAssembly, m_file); |
469 | |
470 | // for now, Module::IsReflection is equivalent to m_file->IsDynamic, |
471 | // which is checked by IsEditAndContinueCapable(m_pAssembly, m_file) |
472 | _ASSERTE(!isEnCCapable || (!this->IsReflection())); |
473 | |
474 | return isEnCCapable; |
475 | } |
476 | |
477 | FORCEINLINE PTR_DomainLocalModule Module::GetDomainLocalModule(AppDomain *pDomain) |
478 | { |
479 | WRAPPER_NO_CONTRACT; |
480 | SUPPORTS_DAC; |
481 | |
482 | if (!Module::IsEncodedModuleIndex(GetModuleID())) |
483 | { |
484 | return m_ModuleID; |
485 | } |
486 | |
487 | #if !defined(DACCESS_COMPILE) |
488 | if (pDomain == NULL) |
489 | { |
490 | pDomain = GetAppDomain(); |
491 | } |
492 | #endif // DACCESS_COMPILE |
493 | |
494 | // If the module is domain neutral, then you must supply an AppDomain argument. |
495 | // Use GetDomainLocalModule() if you want to rely on the current AppDomain |
496 | _ASSERTE(pDomain != NULL); |
497 | |
498 | return pDomain->GetDomainLocalBlock()->GetModuleSlot(GetModuleIndex()); |
499 | } |
500 | |
501 | #ifdef FEATURE_PREJIT |
502 | |
503 | #include "nibblestream.h" |
504 | |
505 | FORCEINLINE BOOL Module::FixupDelayList(TADDR pFixupList) |
506 | { |
507 | WRAPPER_NO_CONTRACT; |
508 | |
509 | COUNT_T nImportSections; |
510 | PTR_CORCOMPILE_IMPORT_SECTION pImportSections = GetImportSections(&nImportSections); |
511 | |
512 | return FixupDelayListAux(pFixupList, this, &Module::FixupNativeEntry, pImportSections, nImportSections, GetNativeOrReadyToRunImage()); |
513 | } |
514 | |
515 | template<typename Ptr, typename FixupNativeEntryCallback> |
516 | BOOL Module::FixupDelayListAux(TADDR pFixupList, |
517 | Ptr pThis, FixupNativeEntryCallback pfnCB, |
518 | PTR_CORCOMPILE_IMPORT_SECTION pImportSections, COUNT_T nImportSections, |
519 | PEDecoder * pNativeImage) |
520 | { |
521 | CONTRACTL |
522 | { |
523 | INSTANCE_CHECK; |
524 | THROWS; |
525 | GC_TRIGGERS; |
526 | MODE_ANY; |
527 | PRECONDITION(pFixupList != NULL); |
528 | } |
529 | CONTRACTL_END; |
530 | |
531 | // Fixup Encoding: |
532 | // ============== |
533 | // |
534 | // The fixup list is sorted in tables. Within each table, the fixups are a |
535 | // sorted list of INDEXes. The first INDEX in each table is encoded entirely, |
536 | // but the remaining INDEXes store only the delta increment from the previous INDEX. |
537 | // The encoding/compression is done by ZapperModule::CompressFixupList(). |
538 | // |
539 | //------------------------------------------------------------------------- |
540 | // Here is the detailed description : |
541 | // |
542 | // The first entry stores the m_pFixupBlob table index. |
543 | // |
544 | // The next entry stores the INDEX into the particular table. |
545 | // An "entry" can be one or more nibbles. 3 bits of a nibble are used |
546 | // to store the value, and the top bit indicates if the following nibble |
547 | // contains rest of the value. If the top bit is not set, then this |
548 | // nibble is the last part of the value. |
549 | // |
550 | // If the next entry is non-0, it is another (delta-encoded relative to the |
551 | // previous INDEX) INDEX belonging to the same table. If the next entry is 0, |
552 | // it indicates that all INDEXes in this table are done. |
553 | // |
554 | // When the fixups for the previous table is done, there is entry to |
555 | // indicate the next table (delta-encoded relative to the previous table). |
556 | // If the entry is 0, then it is the end of the entire fixup list. |
557 | // |
558 | //------------------------------------------------------------------------- |
559 | // This is what the fixup list looks like: |
560 | // |
561 | // CorCompileTokenTable index |
562 | // absolute INDEX |
563 | // INDEX delta |
564 | // ... |
565 | // INDEX delta |
566 | // 0 |
567 | // CorCompileTokenTable index delta |
568 | // absolute INDEX |
569 | // INDEX delta |
570 | // ... |
571 | // INDEX delta |
572 | // 0 |
573 | // CorCompileTokenTable index delta |
574 | // absolute INDEX |
575 | // INDEX delta |
576 | // ... |
577 | // INDEX delta |
578 | // 0 |
579 | // 0 |
580 | // |
581 | // |
582 | |
583 | NibbleReader reader(PTR_BYTE(pFixupList), (SIZE_T)-1); |
584 | |
585 | // |
586 | // The fixups are sorted by the sections they point to. |
587 | // Walk the set of fixups in every sections |
588 | // |
589 | |
590 | DWORD curTableIndex = reader.ReadEncodedU32(); |
591 | |
592 | while (TRUE) |
593 | { |
594 | // Get the correct section to work with. This is stored in the first two nibbles (first byte) |
595 | |
596 | _ASSERTE(curTableIndex < nImportSections); |
597 | PTR_CORCOMPILE_IMPORT_SECTION pImportSection = pImportSections + curTableIndex; |
598 | |
599 | COUNT_T cbData; |
600 | TADDR pData = pNativeImage->GetDirectoryData(&pImportSection->Section, &cbData); |
601 | |
602 | // Now iterate thru the fixup entries |
603 | SIZE_T fixupIndex = reader.ReadEncodedU32(); // Accumulate the real rva from the delta encoded rva |
604 | |
605 | while (TRUE) |
606 | { |
607 | CONSISTENCY_CHECK(fixupIndex * sizeof(TADDR) < cbData); |
608 | |
609 | if (!(pThis->*pfnCB)(pImportSection, fixupIndex, dac_cast<PTR_SIZE_T>(pData + fixupIndex * sizeof(TADDR)))) |
610 | return FALSE; |
611 | |
612 | int delta = reader.ReadEncodedU32(); |
613 | |
614 | // Delta of 0 means end of entries in this table |
615 | if (delta == 0) |
616 | break; |
617 | |
618 | fixupIndex += delta; |
619 | } |
620 | |
621 | unsigned tableIndex = reader.ReadEncodedU32(); |
622 | |
623 | if (tableIndex == 0) |
624 | break; |
625 | |
626 | curTableIndex = curTableIndex + tableIndex; |
627 | |
628 | } // Done with all entries in this table |
629 | |
630 | return TRUE; |
631 | } |
632 | |
633 | #endif //FEATURE_PREJIT |
634 | |
635 | inline PTR_LoaderAllocator Module::GetLoaderAllocator() |
636 | { |
637 | LIMITED_METHOD_DAC_CONTRACT; |
638 | return GetAssembly()->GetLoaderAllocator(); |
639 | } |
640 | |
641 | inline MethodTable* Module::GetDynamicClassMT(DWORD dynamicClassID) |
642 | { |
643 | LIMITED_METHOD_CONTRACT; |
644 | _ASSERTE(m_cDynamicEntries > dynamicClassID); |
645 | return m_pDynamicStaticsInfo[dynamicClassID].pEnclosingMT; |
646 | } |
647 | |
648 | #ifdef FEATURE_CODE_VERSIONING |
649 | inline CodeVersionManager * Module::GetCodeVersionManager() |
650 | { |
651 | LIMITED_METHOD_CONTRACT; |
652 | return GetDomain()->GetCodeVersionManager(); |
653 | } |
654 | #endif // FEATURE_CODE_VERSIONING |
655 | |
656 | #ifdef FEATURE_TIERED_COMPILATION |
657 | inline CallCounter * Module::GetCallCounter() |
658 | { |
659 | LIMITED_METHOD_CONTRACT; |
660 | return GetDomain()->GetCallCounter(); |
661 | } |
662 | #endif // FEATURE_TIERED_COMPILATION |
663 | |
664 | #endif // CEELOAD_INL_ |
665 | |