1e78051a1342f69c4880cd4e99ceaadee3c772a2
[platform/upstream/coreclr.git] / src / zap / zapcode.h
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 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
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 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_)
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 const 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 const 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 const 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         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
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 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 //
772 class ZapProfileData : public ZapNode
773 {
774     ZapMethodHeader *          m_pMethod;
775     ZapProfileData *           m_pNext;
776
777 public:
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.
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__