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 | // ZapCode.h |
6 | // |
7 | |
8 | // |
9 | // ZapNodes for everything directly related to zapping of native code |
10 | // |
11 | // code:ZapMethodHeader |
12 | // code:ZapMethodEntryPoint |
13 | // code:ZapMethodEntryPointTable |
14 | // code:ZapDebugInfo |
15 | // code:ZapProfileData |
16 | // code:ZapHelperTable |
17 | // code:ZapGCInfoTable |
18 | |
19 | |
20 | // |
21 | // ====================================================================================== |
22 | |
23 | #ifndef __ZAPCODE_H__ |
24 | #define __ZAPCODE_H__ |
25 | |
26 | // Forward declarations |
27 | |
28 | class ZapBlobWithRelocs; |
29 | |
30 | #ifdef REDHAWK |
31 | typedef ZapNode ZapGCInfo; |
32 | #else |
33 | #if defined(WIN64EXCEPTIONS) |
34 | class ZapGCInfo; |
35 | #else |
36 | typedef ZapBlob ZapGCInfo; |
37 | #endif |
38 | #endif // REDHAWK |
39 | |
40 | typedef ZapBlob ZapDebugInfo; |
41 | typedef ZapBlob ZapFixupInfo; |
42 | #ifdef REDHAWK |
43 | typedef ZapBlobWithRelocs ZapExceptionInfo; |
44 | #else |
45 | typedef ZapBlob ZapExceptionInfo; |
46 | #endif |
47 | |
48 | class ZapUnwindInfo; |
49 | |
50 | class ZapImport; |
51 | |
52 | class ZapInfo; |
53 | |
54 | class ZapGCRefMapTable; |
55 | |
56 | //--------------------------------------------------------------------------------------- |
57 | // |
58 | // ZapMethodHeader is the main node that all information about the compiled code is hanging from |
59 | // |
60 | class : public ZapNode |
61 | { |
62 | // All other kinds of method headers are tightly coupled with the main method header |
63 | friend class ZapProfileData; |
64 | friend class ZapCodeMethodDescs; |
65 | friend class ZapColdCodeMap; |
66 | |
67 | friend class MethodCodeComparer; |
68 | |
69 | friend class ZapImage; |
70 | friend class ZapInfo; |
71 | |
72 | CORINFO_METHOD_HANDLE m_handle; |
73 | CORINFO_CLASS_HANDLE m_classHandle; |
74 | |
75 | ZapBlobWithRelocs * ; |
76 | ZapBlobWithRelocs * ; // May be NULL |
77 | |
78 | ZapUnwindInfo * ; |
79 | ZapUnwindInfo * ; // May be NULL |
80 | |
81 | #ifdef WIN64EXCEPTIONS |
82 | ZapUnwindInfo * ; // Linked list of all unwind info fragments |
83 | #endif |
84 | |
85 | ZapBlobWithRelocs * ; // May be NULL |
86 | |
87 | ZapBlobWithRelocs * ; // May be NULL |
88 | |
89 | ZapGCInfo * ; |
90 | ZapDebugInfo * ; |
91 | |
92 | union // May be NULL |
93 | { |
94 | ZapImport ** ; // Valid before place phase |
95 | ZapFixupInfo * ; // Valid after place phase |
96 | }; |
97 | |
98 | ZapExceptionInfo * ; // May be NULL |
99 | |
100 | unsigned ; |
101 | |
102 | unsigned ; |
103 | unsigned ; |
104 | |
105 | DWORD ; |
106 | |
107 | () |
108 | { |
109 | } |
110 | |
111 | public: |
112 | CORINFO_METHOD_HANDLE GetHandle() |
113 | { |
114 | return m_handle; |
115 | } |
116 | |
117 | CORINFO_CLASS_HANDLE GetClassHandle() |
118 | { |
119 | return m_classHandle; |
120 | } |
121 | |
122 | DWORD () |
123 | { |
124 | return m_methodIndex; |
125 | } |
126 | |
127 | ZapBlobWithRelocs * () |
128 | { |
129 | return m_pCode; |
130 | } |
131 | |
132 | ZapBlobWithRelocs * () |
133 | { |
134 | return m_pColdCode; |
135 | } |
136 | |
137 | BOOL () |
138 | { |
139 | return m_pFixupList != NULL; |
140 | } |
141 | |
142 | ZapNode * () |
143 | { |
144 | return m_pFixupInfo; |
145 | } |
146 | |
147 | ZapDebugInfo * () |
148 | { |
149 | return m_pDebugInfo; |
150 | } |
151 | |
152 | unsigned () |
153 | { |
154 | return m_compilationOrder; |
155 | } |
156 | |
157 | unsigned () |
158 | { |
159 | return m_cachedLayoutOrder; |
160 | } |
161 | virtual ZapNodeType () |
162 | { |
163 | return ZapNodeType_MethodHeader; |
164 | } |
165 | |
166 | // Iterate over as many of the methods called by this method |
167 | // as are easy to determine. Currently this is implemented |
168 | // by walking the Reloc list and so is only as complete as |
169 | // the current state of the Relocs. Note that the implementation |
170 | // ignores virtual calls and calls in the cold code section. |
171 | class |
172 | { |
173 | public: |
174 | (ZapMethodHeader* pMethod) |
175 | : m_pMethod(pMethod) |
176 | { |
177 | ZapBlobWithRelocs * pCode = pMethod->GetCode(); |
178 | m_pCurReloc = pCode ? pCode->GetRelocs() : NULL; |
179 | } |
180 | |
181 | BOOL (CORINFO_METHOD_HANDLE *pHnd); |
182 | |
183 | private: |
184 | ZapMethodHeader* ; |
185 | ZapReloc* ; |
186 | }; |
187 | |
188 | }; |
189 | |
190 | #if defined(_TARGET_X86_) |
191 | class ZapCodeBlob : public ZapBlobWithRelocs |
192 | { |
193 | protected: |
194 | ZapCodeBlob(SIZE_T cbSize) |
195 | : ZapBlobWithRelocs(cbSize) |
196 | { |
197 | } |
198 | |
199 | public: |
200 | static ZapCodeBlob * NewAlignedBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize, SIZE_T cbAlignment); |
201 | |
202 | virtual DWORD ComputeRVA(ZapWriter * pZapWriter, DWORD dwPos); |
203 | }; |
204 | #else |
205 | typedef ZapBlobWithRelocs ZapCodeBlob; |
206 | #endif |
207 | |
208 | class ZapCodeMethodDescs : public ZapNode |
209 | { |
210 | COUNT_T m_iStartMethod; |
211 | COUNT_T m_iEndMethod; |
212 | COUNT_T m_nUnwindInfos; |
213 | |
214 | public: |
215 | ZapCodeMethodDescs(COUNT_T startMethod, COUNT_T endMethod, COUNT_T nUnwindInfos) |
216 | : m_iStartMethod(startMethod), m_iEndMethod(endMethod), m_nUnwindInfos(nUnwindInfos) |
217 | { |
218 | } |
219 | |
220 | virtual UINT GetAligment() |
221 | { |
222 | return sizeof(DWORD); |
223 | } |
224 | |
225 | virtual DWORD GetSize() |
226 | { |
227 | return m_nUnwindInfos * sizeof(DWORD); |
228 | } |
229 | |
230 | virtual ZapNodeType GetType() |
231 | { |
232 | return ZapNodeType_CodeManagerMap; |
233 | } |
234 | |
235 | virtual void Save(ZapWriter * pZapWriter); |
236 | }; |
237 | |
238 | //--------------------------------------------------------------------------------------- |
239 | // |
240 | // ZapMethodEntryPoint is special type of placeholder. Unlike normal placeholder, it |
241 | // carries extra CORINFO_ACCESS_FLAGS that is used to opt into the direct call even |
242 | // when it would not be otherwise possible. |
243 | // |
244 | class ZapMethodEntryPoint : public ZapNode |
245 | { |
246 | CORINFO_METHOD_HANDLE m_handle; // Target method being called |
247 | BYTE m_accessFlags; // CORINFO_ACCESS_FLAGS |
248 | BYTE m_fUsed; // Entrypoint is used - needs to be resolved |
249 | |
250 | ZapNode *m_pEntryPoint; // only used for abstract methods to remember the precode |
251 | |
252 | public: |
253 | ZapMethodEntryPoint(CORINFO_METHOD_HANDLE handle, CORINFO_ACCESS_FLAGS accessFlags) |
254 | : m_handle(handle), m_accessFlags(static_cast<BYTE>(accessFlags)) |
255 | { |
256 | } |
257 | |
258 | virtual ZapNodeType GetType() |
259 | { |
260 | return ZapNodeType_MethodEntryPoint; |
261 | } |
262 | |
263 | CORINFO_METHOD_HANDLE GetHandle() |
264 | { |
265 | return m_handle; |
266 | } |
267 | |
268 | CORINFO_ACCESS_FLAGS GetAccessFlags() |
269 | { |
270 | return (CORINFO_ACCESS_FLAGS)m_accessFlags; |
271 | } |
272 | |
273 | void SetIsUsed() |
274 | { |
275 | m_fUsed = true; |
276 | } |
277 | |
278 | BOOL IsUsed() |
279 | { |
280 | return m_fUsed; |
281 | } |
282 | |
283 | void Resolve(ZapImage * pImage); |
284 | }; |
285 | |
286 | class ZapMethodEntryPointTable |
287 | { |
288 | struct MethodEntryPointKey |
289 | { |
290 | MethodEntryPointKey(CORINFO_METHOD_HANDLE handle, CORINFO_ACCESS_FLAGS accessFlags) |
291 | : m_handle(handle), m_accessFlags(accessFlags) |
292 | { |
293 | } |
294 | |
295 | CORINFO_METHOD_HANDLE m_handle; // Target method being called |
296 | CORINFO_ACCESS_FLAGS m_accessFlags; |
297 | }; |
298 | |
299 | class MethodEntryPointTraits : public NoRemoveSHashTraits< DefaultSHashTraits<ZapMethodEntryPoint *> > |
300 | { |
301 | public: |
302 | typedef MethodEntryPointKey key_t; |
303 | |
304 | static key_t GetKey(element_t e) |
305 | { |
306 | LIMITED_METHOD_CONTRACT; |
307 | return MethodEntryPointKey(e->GetHandle(), e->GetAccessFlags()); |
308 | } |
309 | static BOOL Equals(key_t k1, key_t k2) |
310 | { |
311 | LIMITED_METHOD_CONTRACT; |
312 | return (k1.m_handle == k2.m_handle) && (k1.m_accessFlags == k2.m_accessFlags); |
313 | } |
314 | static count_t Hash(key_t k) |
315 | { |
316 | LIMITED_METHOD_CONTRACT; |
317 | return (count_t)(size_t)k.m_handle ^ (count_t)k.m_accessFlags; |
318 | } |
319 | |
320 | static element_t Null() { LIMITED_METHOD_CONTRACT; return NULL; } |
321 | static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; } |
322 | }; |
323 | |
324 | typedef SHash< MethodEntryPointTraits > MethodEntryPointTable; |
325 | |
326 | MethodEntryPointTable m_entries; |
327 | ZapImage * m_pImage; |
328 | |
329 | public: |
330 | ZapMethodEntryPointTable(ZapImage * pImage) |
331 | : m_pImage(pImage) |
332 | { |
333 | } |
334 | |
335 | void Preallocate(COUNT_T cbILImage) |
336 | { |
337 | PREALLOCATE_HASHTABLE(ZapMethodEntryPointTable::m_entries, 0.0018, cbILImage); |
338 | } |
339 | |
340 | ZapMethodEntryPoint * GetMethodEntryPoint(CORINFO_METHOD_HANDLE handle, CORINFO_ACCESS_FLAGS accessFlags); |
341 | |
342 | ZapNode * CanDirectCall(ZapMethodEntryPoint * pMethodEntryPoint, ZapMethodHeader * pCaller); |
343 | |
344 | void Resolve(); |
345 | }; |
346 | |
347 | //--------------------------------------------------------------------------------------- |
348 | // |
349 | // Zapping of unwind info |
350 | // |
351 | class ZapUnwindInfo : public ZapNode |
352 | { |
353 | ZapNode * m_pCode; |
354 | |
355 | DWORD m_dwStartOffset; |
356 | DWORD m_dwEndOffset; |
357 | |
358 | ZapNode * m_pUnwindData; |
359 | |
360 | ZapUnwindInfo * m_pNextFragment; |
361 | |
362 | public: |
363 | ZapUnwindInfo(ZapNode * pCode, DWORD dwStartOffset, DWORD dwEndOffset, ZapNode * pUnwindData = NULL) |
364 | : m_pCode(pCode), |
365 | m_dwStartOffset(dwStartOffset), |
366 | m_dwEndOffset(dwEndOffset), |
367 | m_pUnwindData(pUnwindData) |
368 | { |
369 | } |
370 | |
371 | ZapNode * GetCode() |
372 | { |
373 | return m_pCode; |
374 | } |
375 | |
376 | DWORD GetStartOffset() |
377 | { |
378 | return m_dwStartOffset; |
379 | } |
380 | |
381 | DWORD GetEndOffset() |
382 | { |
383 | return m_dwEndOffset; |
384 | } |
385 | |
386 | DWORD GetStartAddress() |
387 | { |
388 | return m_pCode->GetRVA() + GetStartOffset(); |
389 | } |
390 | |
391 | DWORD GetEndAddress() |
392 | { |
393 | return m_pCode->GetRVA() + GetEndOffset(); |
394 | } |
395 | // Used to set unwind data lazily |
396 | void SetUnwindData(ZapNode * pUnwindData) |
397 | { |
398 | _ASSERTE(m_pUnwindData == NULL); |
399 | m_pUnwindData = pUnwindData; |
400 | } |
401 | |
402 | ZapNode * GetUnwindData() |
403 | { |
404 | return m_pUnwindData; |
405 | } |
406 | |
407 | void SetNextFragment(ZapUnwindInfo * pFragment) |
408 | { |
409 | _ASSERTE(m_pNextFragment == NULL); |
410 | m_pNextFragment = pFragment; |
411 | } |
412 | |
413 | ZapUnwindInfo * GetNextFragment() |
414 | { |
415 | return m_pNextFragment; |
416 | } |
417 | |
418 | virtual UINT GetAlignment() |
419 | { |
420 | return sizeof(ULONG); |
421 | } |
422 | |
423 | virtual DWORD GetSize() |
424 | { |
425 | return sizeof(T_RUNTIME_FUNCTION); |
426 | } |
427 | |
428 | virtual ZapNodeType GetType() |
429 | { |
430 | return ZapNodeType_UnwindInfo; |
431 | } |
432 | |
433 | virtual void Save(ZapWriter * pZapWriter); |
434 | |
435 | static int __cdecl CompareUnwindInfo(const void * a, const void * b); |
436 | }; |
437 | |
438 | #ifdef WIN64EXCEPTIONS |
439 | //--------------------------------------------------------------------------------------- |
440 | // |
441 | // Zapping of unwind data |
442 | // |
443 | class ZapUnwindData : public ZapBlob |
444 | { |
445 | public: |
446 | ZapUnwindData(SIZE_T cbSize) |
447 | : ZapBlob(cbSize) |
448 | { |
449 | } |
450 | |
451 | virtual UINT GetAlignment(); |
452 | |
453 | virtual DWORD GetSize(); |
454 | |
455 | virtual ZapNodeType GetType() |
456 | { |
457 | return ZapNodeType_UnwindData; |
458 | } |
459 | |
460 | BOOL IsFilterFunclet() |
461 | { |
462 | return GetType() == ZapNodeType_FilterFuncletUnwindData; |
463 | } |
464 | |
465 | ZapNode * GetPersonalityRoutine(ZapImage * pImage); |
466 | virtual void Save(ZapWriter * pZapWriter); |
467 | |
468 | static ZapUnwindData * NewUnwindData(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize, BOOL fIsFilterFunclet); |
469 | }; |
470 | |
471 | class ZapFilterFuncletUnwindData : public ZapUnwindData |
472 | { |
473 | public: |
474 | ZapFilterFuncletUnwindData(SIZE_T cbSize) |
475 | : ZapUnwindData(cbSize) |
476 | { |
477 | } |
478 | |
479 | virtual ZapNodeType GetType() |
480 | { |
481 | return ZapNodeType_FilterFuncletUnwindData; |
482 | } |
483 | }; |
484 | class ZapUnwindDataTable |
485 | { |
486 | ZapImage * m_pImage; |
487 | |
488 | struct ZapUnwindDataKey |
489 | { |
490 | ZapUnwindDataKey(PVOID pUnwindData, SIZE_T cbUnwindData, BOOL fIsFilterFunclet) |
491 | : m_unwindData(pUnwindData, cbUnwindData), m_fIsFilterFunclet(fIsFilterFunclet) |
492 | { |
493 | } |
494 | |
495 | ZapBlob::SHashKey m_unwindData; |
496 | BOOL m_fIsFilterFunclet; |
497 | }; |
498 | |
499 | class ZapUnwindDataTraits : public NoRemoveSHashTraits< DefaultSHashTraits<ZapUnwindData *> > |
500 | { |
501 | public: |
502 | typedef ZapUnwindDataKey key_t; |
503 | |
504 | static key_t GetKey(element_t e) |
505 | { |
506 | LIMITED_METHOD_CONTRACT; |
507 | return ZapUnwindDataKey(e->GetData(), e->GetBlobSize(), e->IsFilterFunclet()); |
508 | } |
509 | static BOOL Equals(key_t k1, key_t k2) |
510 | { |
511 | LIMITED_METHOD_CONTRACT; |
512 | return ZapBlob::SHashTraits::Equals(k1.m_unwindData, k2.m_unwindData) && (k1.m_fIsFilterFunclet == k2.m_fIsFilterFunclet); |
513 | } |
514 | static count_t Hash(key_t k) |
515 | { |
516 | LIMITED_METHOD_CONTRACT; |
517 | return ZapBlob::SHashTraits::Hash(k.m_unwindData) ^ k.m_fIsFilterFunclet; |
518 | } |
519 | |
520 | static element_t Null() { LIMITED_METHOD_CONTRACT; return NULL; } |
521 | static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; } |
522 | }; |
523 | // Hashtable with all unwind data blobs. If two methods have unwind data |
524 | // we store it just once. |
525 | SHash< ZapUnwindDataTraits > m_blobs; |
526 | |
527 | public: |
528 | ZapUnwindDataTable(ZapImage * pImage) |
529 | : m_pImage(pImage) |
530 | { |
531 | } |
532 | |
533 | void Preallocate(COUNT_T cbILImage) |
534 | { |
535 | PREALLOCATE_HASHTABLE(ZapUnwindDataTable::m_blobs, 0.0003, cbILImage); |
536 | } |
537 | |
538 | ZapUnwindData * GetUnwindData(PVOID pBlob, SIZE_T cbBlob, BOOL fIsFilterFunclet); |
539 | }; |
540 | #endif // WIN64EXCEPTIONS |
541 | |
542 | |
543 | //--------------------------------------------------------------------------------------- |
544 | // |
545 | // Zapping of GC info |
546 | // |
547 | #ifdef WIN64EXCEPTIONS |
548 | class ZapGCInfo : public ZapUnwindData |
549 | { |
550 | DWORD m_cbGCInfo; |
551 | |
552 | public: |
553 | ZapGCInfo(SIZE_T cbGCInfo, SIZE_T cbUnwindInfo) |
554 | : ZapUnwindData(cbUnwindInfo), m_cbGCInfo((DWORD)cbGCInfo) |
555 | { |
556 | if (m_cbGCInfo > ZAPWRITER_MAX_SIZE) |
557 | ThrowHR(COR_E_OVERFLOW); |
558 | } |
559 | |
560 | virtual PBYTE GetData() |
561 | { |
562 | return (PBYTE)(this + 1); |
563 | } |
564 | |
565 | PBYTE GetGCInfo() |
566 | { |
567 | return GetData() + GetUnwindInfoSize(); |
568 | } |
569 | |
570 | DWORD GetGCInfoSize() |
571 | { |
572 | return m_cbGCInfo; |
573 | } |
574 | |
575 | PBYTE GetUnwindInfo() |
576 | { |
577 | return GetData(); |
578 | } |
579 | |
580 | DWORD GetUnwindInfoSize() |
581 | { |
582 | return GetBlobSize(); |
583 | } |
584 | |
585 | virtual ZapNodeType GetType() |
586 | { |
587 | return ZapNodeType_UnwindDataAndGCInfo; |
588 | } |
589 | |
590 | virtual DWORD GetSize() |
591 | { |
592 | return ZapUnwindData::GetSize() + m_cbGCInfo; |
593 | } |
594 | |
595 | virtual void Save(ZapWriter * pZapWriter) |
596 | { |
597 | ZapUnwindData::Save(pZapWriter); |
598 | |
599 | pZapWriter->Write(GetGCInfo(), GetGCInfoSize()); |
600 | } |
601 | |
602 | static ZapGCInfo * NewGCInfo(ZapWriter * pWriter, PVOID pGCInfo, SIZE_T cbGCInfo, PVOID pUnwindInfo, SIZE_T cbUnwindInfo); |
603 | }; |
604 | |
605 | class ZapGCInfoTable |
606 | { |
607 | ZapImage * m_pImage; |
608 | |
609 | struct GCInfoKey |
610 | { |
611 | GCInfoKey(PVOID pGCInfo, SIZE_T cbGCInfo, PVOID pUnwindInfo, SIZE_T cbUnwindInfo) |
612 | : m_gcInfo(pGCInfo, cbGCInfo), m_unwindInfo(pUnwindInfo, cbUnwindInfo) |
613 | { |
614 | } |
615 | |
616 | ZapBlob::SHashKey m_gcInfo; |
617 | ZapBlob::SHashKey m_unwindInfo; |
618 | }; |
619 | |
620 | class GCInfoTraits : public NoRemoveSHashTraits< DefaultSHashTraits<ZapGCInfo *> > |
621 | { |
622 | public: |
623 | typedef GCInfoKey key_t; |
624 | |
625 | static key_t GetKey(element_t e) |
626 | { |
627 | LIMITED_METHOD_CONTRACT; |
628 | return GCInfoKey(e->GetGCInfo(), e->GetGCInfoSize(), e->GetUnwindInfo(), e->GetUnwindInfoSize()); |
629 | } |
630 | static BOOL Equals(key_t k1, key_t k2) |
631 | { |
632 | LIMITED_METHOD_CONTRACT; |
633 | return ZapBlob::SHashTraits::Equals(k1.m_gcInfo, k2.m_gcInfo) && ZapBlob::SHashTraits::Equals(k1.m_unwindInfo, k2.m_unwindInfo); |
634 | } |
635 | static count_t Hash(key_t k) |
636 | { |
637 | LIMITED_METHOD_CONTRACT; |
638 | return ZapBlob::SHashTraits::Hash(k.m_gcInfo) ^ ZapBlob::SHashTraits::Hash(k.m_unwindInfo); |
639 | } |
640 | |
641 | static element_t Null() { LIMITED_METHOD_CONTRACT; return NULL; } |
642 | static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; } |
643 | }; |
644 | |
645 | // Hashtable with all GC info blobs. If two methods have same GC info |
646 | // we store it just once. |
647 | SHash< GCInfoTraits > m_blobs; |
648 | |
649 | public: |
650 | ZapGCInfoTable(ZapImage * pImage) |
651 | : m_pImage(pImage) |
652 | { |
653 | } |
654 | |
655 | void Preallocate(COUNT_T cbILImage) |
656 | { |
657 | PREALLOCATE_HASHTABLE(ZapGCInfoTable::m_blobs, 0.0021, cbILImage); |
658 | } |
659 | |
660 | // Returns interned instance of the GC info blob |
661 | ZapGCInfo * GetGCInfo(PVOID pGCInfo, SIZE_T cbGCInfo, PVOID pUnwindInfo, SIZE_T cbUnwindInfo); |
662 | }; |
663 | #else |
664 | class ZapGCInfoTable |
665 | { |
666 | ZapImage * m_pImage; |
667 | |
668 | // Hashtable with all GC info blobs. If two methods have same GC info |
669 | // we store it just once. |
670 | SHash< NoRemoveSHashTraits < ZapBlob::SHashTraits > > m_blobs; |
671 | |
672 | public: |
673 | ZapGCInfoTable(ZapImage * pImage) |
674 | : m_pImage(pImage) |
675 | { |
676 | } |
677 | |
678 | void Preallocate(COUNT_T cbILImage) |
679 | { |
680 | PREALLOCATE_HASHTABLE(ZapGCInfoTable::m_blobs, 0.0021, cbILImage); |
681 | } |
682 | |
683 | // Returns interned instance of the GC info blob |
684 | ZapGCInfo * GetGCInfo(PVOID pBlob, SIZE_T cbBlob); |
685 | }; |
686 | #endif |
687 | |
688 | //--------------------------------------------------------------------------------------- |
689 | // |
690 | // Zapping of debug info for native code |
691 | // |
692 | class ZapDebugInfoTable : public ZapNode |
693 | { |
694 | COUNT_T m_nCount; |
695 | ZapNode ** m_pTable; |
696 | |
697 | ZapImage * m_pImage; |
698 | |
699 | // Hashtable with all debug info blobs. If two methods have same debug info |
700 | // we store it just once. |
701 | SHash< NoRemoveSHashTraits < ZapBlob::SHashTraits > > m_blobs; |
702 | |
703 | class LabelledEntry : public ZapNode |
704 | { |
705 | public: |
706 | LabelledEntry * m_pNext; |
707 | ZapMethodHeader * m_pMethod; |
708 | |
709 | (ZapMethodHeader * pMethod) |
710 | : m_pMethod(pMethod) |
711 | { |
712 | } |
713 | |
714 | virtual DWORD GetSize() |
715 | { |
716 | return sizeof(CORCOMPILE_DEBUG_LABELLED_ENTRY); |
717 | } |
718 | |
719 | virtual UINT GetAlignment() |
720 | { |
721 | return sizeof(DWORD); |
722 | } |
723 | |
724 | virtual ZapNodeType GetType() |
725 | { |
726 | return ZapNodeType_DebugInfoLabelledEntry; |
727 | } |
728 | |
729 | virtual void Save(ZapWriter * pZapWriter); |
730 | }; |
731 | |
732 | public: |
733 | ZapDebugInfoTable(ZapImage * pImage) |
734 | : m_pImage(pImage) |
735 | { |
736 | } |
737 | |
738 | void Preallocate(COUNT_T cbILImage) |
739 | { |
740 | PREALLOCATE_HASHTABLE(ZapDebugInfoTable::m_blobs, 0.0024, cbILImage); |
741 | } |
742 | |
743 | // Returns interned instance of the debug info blob |
744 | ZapDebugInfo * GetDebugInfo(PVOID pBlob, SIZE_T cbBlob); |
745 | |
746 | void PrepareLayout(); |
747 | void (ZapMethodHeader * pMethod); |
748 | void FinishLayout(); |
749 | |
750 | virtual DWORD GetSize() |
751 | { |
752 | return m_nCount * sizeof(CORCOMPILE_DEBUG_RID_ENTRY); |
753 | } |
754 | |
755 | virtual UINT GetAlignment() |
756 | { |
757 | return sizeof(DWORD); |
758 | } |
759 | |
760 | virtual ZapNodeType GetType() |
761 | { |
762 | return ZapNodeType_DebugInfoTable; |
763 | } |
764 | |
765 | virtual void Save(ZapWriter * pZapWriter); |
766 | }; |
767 | |
768 | //--------------------------------------------------------------------------------------- |
769 | // |
770 | // Zapping of IBC profile data collection area |
771 | // |
772 | class ZapProfileData : public ZapNode |
773 | { |
774 | ZapMethodHeader * m_pMethod; |
775 | ZapProfileData * m_pNext; |
776 | |
777 | public: |
778 | (ZapMethodHeader * pMethod) |
779 | : m_pMethod(pMethod) |
780 | { |
781 | } |
782 | |
783 | void SetNext(ZapProfileData * pNext) |
784 | { |
785 | m_pNext = pNext; |
786 | } |
787 | |
788 | virtual DWORD GetSize() |
789 | { |
790 | return sizeof(CORCOMPILE_METHOD_PROFILE_LIST); |
791 | } |
792 | |
793 | virtual UINT GetAlignment() |
794 | { |
795 | return TARGET_POINTER_SIZE; |
796 | } |
797 | |
798 | virtual ZapNodeType GetType() |
799 | { |
800 | return ZapNodeType_ProfileData; |
801 | } |
802 | |
803 | virtual void Save(ZapWriter * pZapWriter); |
804 | }; |
805 | |
806 | // Zapping of ExceptionInfoTable |
807 | // ExceptionInfoTable is a lookup table that has 1 entry for each method with EH information. |
808 | // The table is sorted by method start address, so binary search is used during runtime to find |
809 | // the EH info for a given method given a method start address. |
810 | class ZapExceptionInfoLookupTable : public ZapNode |
811 | { |
812 | private: |
813 | typedef struct |
814 | { |
815 | ZapNode* m_pCode; |
816 | ZapExceptionInfo* m_pExceptionInfo; |
817 | } ExceptionInfoEntry; |
818 | |
819 | SArray<ExceptionInfoEntry> m_exceptionInfoEntries; |
820 | ZapImage* m_pImage; |
821 | public: |
822 | ZapExceptionInfoLookupTable(ZapImage *pImage); |
823 | |
824 | void PlaceExceptionInfoEntry(ZapNode* pCode, ZapExceptionInfo* pExceptionInfo); |
825 | |
826 | virtual ZapNodeType GetType() |
827 | { |
828 | return ZapNodeType_ExceptionInfoTable; |
829 | } |
830 | virtual UINT GetAlignment() |
831 | { |
832 | return TARGET_POINTER_SIZE; |
833 | } |
834 | virtual DWORD GetSize(); |
835 | virtual void Save(ZapWriter* pZapWriter); |
836 | }; |
837 | |
838 | |
839 | class ZapUnwindInfoLookupTable : public ZapNode |
840 | { |
841 | |
842 | public: |
843 | ZapUnwindInfoLookupTable(ZapVirtualSection * pRuntimeFunctionSection, ZapNode * pCodeSection, DWORD totalCodeSize): |
844 | m_pRuntimeFunctionSection(pRuntimeFunctionSection), m_pCodeSection(pCodeSection), m_TotalCodeSize(totalCodeSize) |
845 | { |
846 | } |
847 | |
848 | COUNT_T GetNumEntries() |
849 | { |
850 | return m_TotalCodeSize/RUNTIME_FUNCTION_LOOKUP_STRIDE + 1; |
851 | } |
852 | virtual ZapNodeType GetType() |
853 | { |
854 | return ZapNodeType_UnwindInfoLookupTable; |
855 | } |
856 | virtual UINT GetAlignment() |
857 | { |
858 | return sizeof(DWORD); |
859 | } |
860 | virtual DWORD GetSize(); |
861 | virtual void Save(ZapWriter* pZapWriter); |
862 | |
863 | private: |
864 | ZapVirtualSection * m_pRuntimeFunctionSection; |
865 | ZapNode * m_pCodeSection; |
866 | DWORD m_TotalCodeSize; |
867 | }; |
868 | |
869 | class ZapColdCodeMap : public ZapNode |
870 | { |
871 | public: |
872 | ZapColdCodeMap(ZapVirtualSection * pRuntimeFunctionSection): |
873 | m_pRuntimeFunctionSection (pRuntimeFunctionSection) |
874 | { |
875 | } |
876 | |
877 | virtual ZapNodeType GetType() |
878 | { |
879 | return ZapNodeType_ColdCodeMap; |
880 | } |
881 | virtual UINT GetAlignment() |
882 | { |
883 | return sizeof(DWORD); |
884 | } |
885 | virtual DWORD GetSize(); |
886 | virtual void Save(ZapWriter* pZapWriter); |
887 | |
888 | private: |
889 | ZapVirtualSection * m_pRuntimeFunctionSection; |
890 | }; |
891 | |
892 | // |
893 | //--------------------------------------------------------------------------------------- |
894 | // |
895 | // Jump thunk for JIT helper |
896 | // |
897 | #ifdef _DEBUG |
898 | const static PCSTR s_rgHelperNames[] = { |
899 | #define JITHELPER(code,pfnHelper,sig) #code , |
900 | #define DYNAMICJITHELPER(code,pfnHelper,sig) "<dynamic> " #code , |
901 | #include <jithelpers.h> |
902 | }; |
903 | #endif // _DEBUG |
904 | |
905 | class ZapHelperThunk : public ZapNode |
906 | { |
907 | DWORD m_dwHelper; |
908 | |
909 | public: |
910 | ZapHelperThunk(DWORD dwHelper) |
911 | : m_dwHelper(dwHelper) |
912 | { |
913 | #ifdef _DEBUG |
914 | static_assert_no_msg(COUNTOF(s_rgHelperNames) == CORINFO_HELP_COUNT); |
915 | LOG((LF_ZAP, LL_INFO1000000, "Created ZapHelperThunk for helper %3d (%s)\n" , |
916 | (USHORT)m_dwHelper, s_rgHelperNames[(USHORT)m_dwHelper])); |
917 | #endif // _DEBUG |
918 | } |
919 | |
920 | virtual DWORD GetSize(); |
921 | |
922 | virtual ZapNodeType GetType() |
923 | { |
924 | return ZapNodeType_HelperThunk; |
925 | } |
926 | |
927 | virtual void Save(ZapWriter * pZapWriter); |
928 | }; |
929 | |
930 | class ZapLazyHelperThunk : public ZapNode |
931 | { |
932 | CorInfoHelpFunc m_dwHelper; |
933 | |
934 | ZapNode * m_pArg; |
935 | ZapNode * m_pTarget; |
936 | |
937 | DWORD SaveWorker(ZapWriter * pZapWriter); |
938 | |
939 | public: |
940 | ZapLazyHelperThunk(CorInfoHelpFunc dwHelper) |
941 | : m_dwHelper(dwHelper) |
942 | { |
943 | } |
944 | |
945 | void Place(ZapImage * pImage); |
946 | |
947 | virtual DWORD GetSize(); |
948 | |
949 | virtual ZapNodeType GetType() |
950 | { |
951 | return ZapNodeType_LazyHelperThunk; |
952 | } |
953 | |
954 | virtual void Save(ZapWriter * pZapWriter); |
955 | }; |
956 | |
957 | #endif // __ZAPCODE_H__ |
958 | |