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
28class ZapBlobWithRelocs;
29
30#ifdef REDHAWK
31typedef ZapNode ZapGCInfo;
32#else
33#if defined(WIN64EXCEPTIONS)
34class ZapGCInfo;
35#else
36typedef ZapBlob ZapGCInfo;
37#endif
38#endif // REDHAWK
39
40typedef ZapBlob ZapDebugInfo;
41typedef ZapBlob ZapFixupInfo;
42#ifdef REDHAWK
43typedef ZapBlobWithRelocs ZapExceptionInfo;
44#else
45typedef ZapBlob ZapExceptionInfo;
46#endif
47
48class ZapUnwindInfo;
49
50class ZapImport;
51
52class ZapInfo;
53
54class ZapGCRefMapTable;
55
56//---------------------------------------------------------------------------------------
57//
58// ZapMethodHeader is the main node that all information about the compiled code is hanging from
59//
60class ZapMethodHeader : 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 * m_pCode;
76 ZapBlobWithRelocs * m_pColdCode; // May be NULL
77
78 ZapUnwindInfo * m_pUnwindInfo;
79 ZapUnwindInfo * m_pColdUnwindInfo; // May be NULL
80
81#ifdef WIN64EXCEPTIONS
82 ZapUnwindInfo * m_pUnwindInfoFragments; // Linked list of all unwind info fragments
83#endif
84
85 ZapBlobWithRelocs * m_pROData; // May be NULL
86
87 ZapBlobWithRelocs * m_pProfileData; // May be NULL
88
89 ZapGCInfo * m_pGCInfo;
90 ZapDebugInfo * m_pDebugInfo;
91
92 union // May be NULL
93 {
94 ZapImport ** m_pFixupList; // Valid before place phase
95 ZapFixupInfo * m_pFixupInfo; // Valid after place phase
96 };
97
98 ZapExceptionInfo * m_pExceptionInfo; // May be NULL
99
100 unsigned m_ProfilingDataFlags;
101
102 unsigned m_compilationOrder;
103 unsigned m_cachedLayoutOrder;
104
105 DWORD m_methodIndex;
106
107 ZapMethodHeader()
108 {
109 }
110
111public:
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 GetMethodIndex()
123 {
124 return m_methodIndex;
125 }
126
127 ZapBlobWithRelocs * GetCode()
128 {
129 return m_pCode;
130 }
131
132 ZapBlobWithRelocs * GetColdCode()
133 {
134 return m_pColdCode;
135 }
136
137 BOOL HasFixups()
138 {
139 return m_pFixupList != NULL;
140 }
141
142 ZapNode * GetFixupList()
143 {
144 return m_pFixupInfo;
145 }
146
147 ZapDebugInfo * GetDebugInfo()
148 {
149 return m_pDebugInfo;
150 }
151
152 unsigned GetCompilationOrder()
153 {
154 return m_compilationOrder;
155 }
156
157 unsigned GetCachedLayoutOrder()
158 {
159 return m_cachedLayoutOrder;
160 }
161 virtual ZapNodeType GetType()
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 PartialTargetMethodIterator
172 {
173 public:
174 PartialTargetMethodIterator(ZapMethodHeader* pMethod)
175 : m_pMethod(pMethod)
176 {
177 ZapBlobWithRelocs * pCode = pMethod->GetCode();
178 m_pCurReloc = pCode ? pCode->GetRelocs() : NULL;
179 }
180
181 BOOL GetNext(CORINFO_METHOD_HANDLE *pHnd);
182
183 private:
184 ZapMethodHeader* m_pMethod;
185 ZapReloc* m_pCurReloc;
186 };
187
188};
189
190#if defined(_TARGET_X86_)
191class ZapCodeBlob : public ZapBlobWithRelocs
192{
193protected:
194 ZapCodeBlob(SIZE_T cbSize)
195 : ZapBlobWithRelocs(cbSize)
196 {
197 }
198
199public:
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
205typedef ZapBlobWithRelocs ZapCodeBlob;
206#endif
207
208class ZapCodeMethodDescs : public ZapNode
209{
210 COUNT_T m_iStartMethod;
211 COUNT_T m_iEndMethod;
212 COUNT_T m_nUnwindInfos;
213
214public:
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//
244class 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
252public:
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
286class 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
329public:
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//
351class 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
362public:
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//
443class ZapUnwindData : public ZapBlob
444{
445public:
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
471class ZapFilterFuncletUnwindData : public ZapUnwindData
472{
473public:
474 ZapFilterFuncletUnwindData(SIZE_T cbSize)
475 : ZapUnwindData(cbSize)
476 {
477 }
478
479 virtual ZapNodeType GetType()
480 {
481 return ZapNodeType_FilterFuncletUnwindData;
482 }
483};
484class 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
527public:
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
548class ZapGCInfo : public ZapUnwindData
549{
550 DWORD m_cbGCInfo;
551
552public:
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
605class 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
649public:
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
664class 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
672public:
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//
692class 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 LabelledEntry(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
732public:
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 PlaceDebugInfo(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//
772class ZapProfileData : public ZapNode
773{
774 ZapMethodHeader * m_pMethod;
775 ZapProfileData * m_pNext;
776
777public:
778 ZapProfileData(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.
810class ZapExceptionInfoLookupTable : public ZapNode
811{
812private:
813 typedef struct
814 {
815 ZapNode* m_pCode;
816 ZapExceptionInfo* m_pExceptionInfo;
817 } ExceptionInfoEntry;
818
819 SArray<ExceptionInfoEntry> m_exceptionInfoEntries;
820 ZapImage* m_pImage;
821public:
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
839class ZapUnwindInfoLookupTable : public ZapNode
840{
841
842public:
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
863private:
864 ZapVirtualSection * m_pRuntimeFunctionSection;
865 ZapNode * m_pCodeSection;
866 DWORD m_TotalCodeSize;
867};
868
869class ZapColdCodeMap : public ZapNode
870{
871public:
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
888private:
889 ZapVirtualSection * m_pRuntimeFunctionSection;
890};
891
892//
893//---------------------------------------------------------------------------------------
894//
895// Jump thunk for JIT helper
896//
897#ifdef _DEBUG
898const 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
905class ZapHelperThunk : public ZapNode
906{
907 DWORD m_dwHelper;
908
909public:
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
930class ZapLazyHelperThunk : public ZapNode
931{
932 CorInfoHelpFunc m_dwHelper;
933
934 ZapNode * m_pArg;
935 ZapNode * m_pTarget;
936
937 DWORD SaveWorker(ZapWriter * pZapWriter);
938
939public:
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