JIT: Fix bug in finally cloning caused by unsound callfinally reordering
[platform/upstream/coreclr.git] / src / zap / zapcode.cpp
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.cpp
6 //
7
8 //
9 // Everything directly related to zapping of native code
10 //  - The code itself
11 //  - Code headers
12 //  - All XXX infos: GC Info, EH Info, Unwind Info, ...
13 //
14 // ======================================================================================
15
16 #include "common.h"
17
18 #include "zapcode.h"
19
20 #include "zapimport.h"
21
22 #include "zapinnerptr.h"
23
24 #ifdef FEATURE_READYTORUN_COMPILER
25 #include "zapreadytorun.h"
26 #endif
27
28 #ifdef REDHAWK
29 #include "rhcodeinfo.h"
30 #include "rhbinder.h"
31 #include "modulegcinfoencoder.h"
32 #endif // REDHAWK
33
34 //
35 // The image layout algorithm
36 //
37
38 ZapVirtualSection * ZapImage::GetCodeSection(CodeType codeType)
39 {
40     switch (codeType)
41     {
42     case ProfiledHot:
43         return m_pHotCodeSection;
44     case ProfiledCold:
45         return m_pColdCodeSection;
46     case Unprofiled:
47         return m_pCodeSection;
48     }
49
50     UNREACHABLE();
51 }
52
53 #if defined(WIN64EXCEPTIONS)
54 ZapVirtualSection * ZapImage::GetUnwindDataSection(CodeType codeType)
55 {
56 #ifdef REDHAWK
57     return m_pUnwindDataSection;
58 #else
59     switch (codeType)
60     {
61     case ProfiledHot:
62         return m_pHotUnwindDataSection;
63     case ProfiledCold:
64         return m_pColdUnwindDataSection;
65     case Unprofiled:
66         return m_pUnwindDataSection;
67     }
68
69 #endif // REDHAWK
70     UNREACHABLE();
71 }
72 #endif // defined(WIN64EXCEPTIONS)
73
74 ZapVirtualSection * ZapImage::GetRuntimeFunctionSection(CodeType codeType)
75 {
76     switch (codeType)
77     {
78     case ProfiledHot:
79         return m_pHotRuntimeFunctionSection;
80     case ProfiledCold:
81         return m_pColdRuntimeFunctionSection;
82     case Unprofiled:
83         return m_pRuntimeFunctionSection;
84     }
85
86     UNREACHABLE();
87 }
88
89 ZapVirtualSection * ZapImage::GetCodeMethodDescSection(CodeType codeType)
90 {
91     switch (codeType)
92     {
93     case ProfiledHot:
94         return m_pHotCodeMethodDescsSection;
95     case Unprofiled:
96         return m_pCodeMethodDescsSection;
97     default:
98         UNREACHABLE();
99     }
100 }
101
102 ZapVirtualSection* ZapImage::GetUnwindInfoLookupSection(CodeType codeType)
103 {
104     switch(codeType)
105     {
106     case ProfiledHot:
107         return m_pHotRuntimeFunctionLookupSection;
108     case Unprofiled:
109         return m_pRuntimeFunctionLookupSection;
110     default:
111         UNREACHABLE();
112     }
113 }
114
115 void ZapImage::GetCodeCompilationRange(CodeType codeType, COUNT_T * start, COUNT_T * end)
116 {
117     _ASSERTE(start && end);
118
119 #ifdef REDHAWK
120     *start = 0;
121     *end = m_MethodCompilationOrder.GetCount();
122 #else
123     switch (codeType)
124     {
125     case ProfiledHot:
126         *start = 0;
127         *end = m_iUntrainedMethod;
128         break;
129     case ProfiledCold:
130         *start = 0;
131         *end = m_MethodCompilationOrder.GetCount();
132         break;
133     case Unprofiled:
134         *start = m_iUntrainedMethod;
135         *end = m_MethodCompilationOrder.GetCount();
136         break;
137     }
138 #endif // REDHAWK
139 }
140
141 void ZapImage::OutputCode(CodeType codeType)
142 {
143     // Note there are three codeTypes: ProfiledHot, Unprofiled and ProfiledCold
144 #if defined(REDHAWK)
145     SectionMethodListGenerator map;
146 #endif 
147
148     bool fCold = (codeType == ProfiledCold);
149     CorInfoRegionKind regionKind = (codeType == ProfiledHot) ? CORINFO_REGION_HOT : CORINFO_REGION_COLD;
150     BeginRegion(regionKind);
151
152     ZapVirtualSection * pCodeSection = GetCodeSection(codeType);
153     ZapVirtualSection * pRuntimeFunctionSection = GetRuntimeFunctionSection(codeType);
154
155 #if defined (WIN64EXCEPTIONS)
156     ZapVirtualSection * pUnwindDataSection = GetUnwindDataSection(codeType);
157 #endif // defined (WIN64EXCEPTIONS)
158
159     DWORD codeSize = 0;
160
161     // We should start with empty code section
162     _ASSERTE(pRuntimeFunctionSection->GetNodeCount() == 0);
163     _ASSERTE(pCodeSection->GetNodeCount() == 0);
164
165     COUNT_T startMethod, endMethod;
166 #ifdef REDHAWK  // TritonTBD
167     DWORD currentOffset = 0;
168 #endif // REDHAWK
169
170     GetCodeCompilationRange(codeType, &startMethod, &endMethod);
171
172     DWORD dwStartMethodIndex = (codeType == Unprofiled) ? m_pHotRuntimeFunctionSection->GetNodeCount() : 0;
173
174     for (COUNT_T curMethod = startMethod; curMethod < endMethod; curMethod++)
175     {
176         ZapMethodHeader * pMethod = m_MethodCompilationOrder[curMethod];
177
178         ZapBlobWithRelocs * pCode = fCold ? pMethod->m_pColdCode : pMethod->m_pCode;
179         if (pCode == NULL)
180         {
181             continue;
182         }
183
184         if (!fCold)
185         {
186             pMethod->m_methodIndex = dwStartMethodIndex + pRuntimeFunctionSection->GetNodeCount();
187         }
188         else
189         {
190             pMethod->m_methodIndex = (DWORD)-1;
191         }
192
193         //Count the method size for use by ZapUnwindInfoLookupTable
194         codeSize  = AlignUp(codeSize, pCode->GetAlignment());
195         codeSize += pCode->GetSize();
196
197         pCodeSection->Place(pCode);
198
199 #ifdef  REDHAWK
200         DWORD codeOffset = AlignUp(currentOffset, pCode->GetAlignment());
201         codeOffset = map.AlignToMethodStartGranularity(codeOffset);
202         map.NoticeMethod(codeOffset, pCode->GetSize());
203         currentOffset = codeOffset + pCode->GetSize();
204 #endif
205
206         ZapReloc * pRelocs = pCode->GetRelocs();
207         if (pRelocs != NULL)
208         {
209             for (ZapReloc * pReloc = pRelocs; pReloc->m_type != IMAGE_REL_INVALID; pReloc++)
210             {
211                 ZapNode * pTarget = pReloc->m_pTargetNode;
212
213                 ZapNodeType type = pTarget->GetType();
214                 if (type == ZapNodeType_InnerPtr)
215                 {
216                     pTarget = ((ZapInnerPtr *)pTarget)->GetBase();
217                     type = pTarget->GetType();
218                 }
219
220                 switch (type)
221                 {
222                 case ZapNodeType_StubDispatchCell:
223                     // Optimizations may create redundant references to the StubDispatchCell
224                     if (!pTarget->IsPlaced())
225                     {
226                         m_pStubDispatchDataTable->PlaceStubDispatchCell((ZapImport *)pTarget);
227                     }
228                     break;
229                 case ZapNodeType_MethodEntryPoint:
230                     pTarget = m_pMethodEntryPoints->CanDirectCall((ZapMethodEntryPoint *)pTarget, pMethod);
231                     if (pTarget != NULL)
232                     {
233                         pReloc->m_pTargetNode = pTarget;
234                     }
235                     break;
236                 case ZapNodeType_Stub:
237                     if (!pTarget->IsPlaced())
238                     {
239                         m_pStubsSection->Place(pTarget);
240                     }
241                     break;
242                 case ZapNodeType_HelperThunk:
243                     if (!pTarget->IsPlaced())
244                     {
245                         // This should place the most frequently used JIT helpers first and together
246                         m_pHelperTableSection->Place(pTarget);
247                     }
248                     break;
249                 case ZapNodeType_LazyHelperThunk:
250                     if (!pTarget->IsPlaced())
251                     {
252                         ((ZapLazyHelperThunk *)pTarget)->Place(this);
253                     }
254                     break;
255                 case ZapNodeType_Import_ModuleHandle:
256                 case ZapNodeType_Import_ClassHandle:
257                 case ZapNodeType_Import_StringHandle:
258                 case ZapNodeType_Import_Helper:
259                     // Place all potentially eager imports
260                     if (!pTarget->IsPlaced())
261                         m_pImportTable->PlaceImport((ZapImport *)pTarget);
262                     break;
263
264                 case ZapNodeType_ExternalMethodThunk:
265                     if (!pTarget->IsPlaced())
266                         m_pExternalMethodDataTable->PlaceExternalMethodThunk((ZapImport *)pTarget);
267                     break;
268
269                 case ZapNodeType_ExternalMethodCell:
270                     if (!pTarget->IsPlaced())
271                         m_pExternalMethodDataTable->PlaceExternalMethodCell((ZapImport *)pTarget);
272                     break;
273
274 #ifdef FEATURE_READYTORUN_COMPILER
275                 case ZapNodeType_DynamicHelperCell:
276                     if (!pTarget->IsPlaced())
277                         m_pDynamicHelperDataTable->PlaceDynamicHelperCell((ZapImport *)pTarget);
278                     break;
279
280                 case ZapNodeType_IndirectHelperThunk:
281                     if (!pTarget->IsPlaced())
282                         m_pImportTable->PlaceIndirectHelperThunk(pTarget);
283                     break;
284
285                 case ZapNodeType_RVAFieldData:
286                     if (!pTarget->IsPlaced())
287                         m_pReadOnlyDataSection->Place(pTarget);
288                     break;
289 #endif
290
291                 case ZapNodeType_GenericSignature:
292                     if (!pTarget->IsPlaced())
293                         m_pImportTable->PlaceBlob((ZapBlob *)pTarget);
294                     break;
295                 default:
296                     break;
297                 }
298             }
299         }
300
301 #if defined (WIN64EXCEPTIONS)
302         //
303         // Place unwind data
304         //
305
306         InlineSArray<ZapUnwindInfo *, 8> unwindInfos;
307
308         ZapUnwindInfo * pFragment;
309
310         // Go over all fragments and append their unwind infos in this section
311         for (pFragment = pMethod->m_pUnwindInfoFragments;
312              pFragment != NULL;
313              pFragment = pFragment->GetNextFragment())
314         {
315             ZapNode * pFragmentCode = pFragment->GetCode();
316             _ASSERTE(pFragmentCode == pMethod->m_pCode || pFragmentCode == pMethod->m_pColdCode);
317
318             if (pFragmentCode == pCode)
319             {
320                 unwindInfos.Append(pFragment);
321             }
322         }
323
324         // The runtime function section must be ordered correctly relative to code layout
325         // in the image. Sort the unwind infos by their offset
326         _ASSERTE(unwindInfos.GetCount() > 0);
327         qsort(&unwindInfos[0], unwindInfos.GetCount(), sizeof(ZapUnwindInfo *), ZapUnwindInfo::CompareUnwindInfo);
328
329         // Set the initial unwind info for the hot and cold sections
330         if (fCold)
331         {
332             _ASSERTE(pMethod->m_pColdUnwindInfo == NULL);
333             pMethod->m_pColdUnwindInfo = unwindInfos[0];
334         }
335         else
336         {
337             _ASSERTE(pMethod->m_pUnwindInfo == NULL);
338             pMethod->m_pUnwindInfo = unwindInfos[0];
339         }
340
341         for (COUNT_T iUnwindInfo = 0; iUnwindInfo < unwindInfos.GetCount(); iUnwindInfo++)
342         {
343             ZapUnwindInfo * pUnwindInfo = unwindInfos[iUnwindInfo];
344             pRuntimeFunctionSection->Place(pUnwindInfo);
345
346             ZapNode * pUnwindData = pUnwindInfo->GetUnwindData();
347
348             if (!pUnwindData->IsPlaced())
349             {
350                 pUnwindDataSection->Place(pUnwindData);
351             }
352         }
353
354 #else // defined (WIN64EXCEPTIONS)
355
356         ZapUnwindInfo * pUnwindInfo;
357         if (fCold)
358         {
359             // Chained unwind info
360             pUnwindInfo = new (GetHeap()) ZapUnwindInfo(pCode, 0, 0, pMethod->m_pUnwindInfo);
361             pMethod->m_pColdUnwindInfo = pUnwindInfo;
362         }
363         else
364         {
365             pUnwindInfo = new (GetHeap()) ZapUnwindInfo(pCode, 0, 0, pMethod->m_pGCInfo);
366             pMethod->m_pUnwindInfo = pUnwindInfo;
367         }
368         pRuntimeFunctionSection->Place(pUnwindInfo);
369
370 #endif // defined (WIN64EXCEPTIONS)
371
372         if (m_stats != NULL)
373         {
374             CorInfoIndirectCallReason reason;
375             BOOL direct = m_pPreloader->CanSkipMethodPreparation(NULL, pMethod->GetHandle(), &reason);
376
377             if (direct && pMethod->m_pFixupList != NULL)
378             {
379                 reason = CORINFO_INDIRECT_CALL_FIXUPS;
380                 direct = FALSE;
381             }
382
383             if (direct)
384             {
385                 m_stats->m_directMethods++;
386             }
387             else
388             {
389                 m_stats->m_prestubMethods++;
390                 m_stats->m_indirectMethodReasons[reason]++;
391             }
392         }
393     }
394
395 #ifdef REDHAWK
396     // Redhawk needs any trailing padding to be 0xcc
397     DWORD cbPad = AlignUp(currentOffset, sizeof(DWORD)) - currentOffset;
398     if (cbPad != 0)
399     {
400         ZapBlob * pBlob = ZapBlob::NewBlob(this, NULL, cbPad);
401         memset(pBlob->GetData(), DEFAULT_CODE_BUFFER_INIT, cbPad);
402         pCodeSection->Place(pBlob);
403         currentOffset += cbPad;
404     }
405
406     map.Output(this, m_pCodeMgrSection, numMethods);
407 #else
408     COUNT_T nUnwindInfos = pRuntimeFunctionSection->GetNodeCount();
409
410     if (nUnwindInfos != 0)
411     {
412         if (IsReadyToRunCompilation())
413         {
414             // TODO: Implement
415         }
416         else
417         if (!fCold)
418         {
419             ZapVirtualSection * pCodeMethodDescSection = GetCodeMethodDescSection(codeType);
420             pCodeMethodDescSection->Place(new (GetHeap()) ZapCodeMethodDescs(startMethod, endMethod, nUnwindInfos));
421
422             ZapVirtualSection* pUnwindInfoLookupSection = GetUnwindInfoLookupSection(codeType);
423             pUnwindInfoLookupSection->Place(new (GetHeap()) ZapUnwindInfoLookupTable(pRuntimeFunctionSection, pCodeSection, codeSize));
424         }
425         else
426         {
427             m_pColdCodeMapSection->Place(new (GetHeap()) ZapColdCodeMap(pRuntimeFunctionSection));
428         }
429     }
430 #endif
431
432     EndRegion(regionKind);
433 }
434
435 void ZapImage::OutputCodeInfo(CodeType codeType)
436 {
437     CorInfoRegionKind regionKind = (codeType == ProfiledHot) ? CORINFO_REGION_HOT : CORINFO_REGION_COLD;
438     BeginRegion(regionKind);
439
440     for (COUNT_T i = 0; i < m_MethodCompilationOrder.GetCount(); i++)
441     {
442         ZapMethodHeader * pMethod = m_MethodCompilationOrder[i];
443
444         //
445         // We are either outputing the ProfiledHot methods
446         // or the unprofiled and cold methods
447         //
448         if ((pMethod->m_ProfilingDataFlags & (1 << ReadMethodCode)) != (codeType == ProfiledHot))
449         {
450             // Wrong kind so skip
451             continue;
452         }
453
454         if (pMethod->m_pROData != NULL)
455             m_pReadOnlyDataSection->Place(pMethod->m_pROData);
456
457 #ifndef REDHAWK
458         // Note: for Redhawk we place EH info via OutputEHInfo().
459         if (pMethod->m_pExceptionInfo != NULL)
460         {
461             ZapNode* pCode = pMethod->m_pCode;
462             m_pExceptionInfoLookupTable->PlaceExceptionInfoEntry(pCode, pMethod->m_pExceptionInfo);
463         }
464 #endif // REDHAWK
465
466         if (pMethod->m_pFixupList != NULL && !IsReadyToRunCompilation())
467             pMethod->m_pFixupInfo = m_pImportTable->PlaceFixups(pMethod->m_pFixupList);
468     }
469
470     EndRegion(regionKind);
471 }
472
473 void ZapImage::OutputProfileData()
474 {
475     if (m_pInstrumentSection == NULL)
476     {
477         return;
478     }
479
480     ZapProfileData * pPrevious = NULL;
481
482     for (COUNT_T i = 0; i < m_MethodCompilationOrder.GetCount(); i++)
483     {
484         ZapMethodHeader * pMethod = m_MethodCompilationOrder[i];
485
486         if (pMethod->m_pProfileData == NULL)
487         {
488             continue;
489         }
490
491         ZapProfileData * pHeader = new (GetHeap()) ZapProfileData(pMethod);
492
493         m_pInstrumentSection->Place(pHeader);
494         m_pInstrumentSection->Place(pMethod->m_pProfileData);
495
496         if (pPrevious != NULL)
497         {
498             pPrevious->SetNext(pHeader);
499         }
500
501         pPrevious = pHeader;
502     }
503 }
504
505 void ZapImage::OutputDebugInfo()
506 {
507     m_pDebugInfoTable->PrepareLayout();
508     for (COUNT_T i = 0; i < m_MethodCompilationOrder.GetCount(); i++)
509     {
510         m_pDebugInfoTable->PlaceDebugInfo(m_MethodCompilationOrder[i]);
511     }
512     m_pDebugInfoTable->FinishLayout();
513 }
514
515 void ZapImage::OutputGCInfo()
516 {
517 #ifndef REDHAWK
518     struct  MaskValue
519     {
520         DWORD   mask;
521         DWORD   value;
522     };
523
524     static const MaskValue gcInfoSequence[] =
525     {
526         {   (1 << CommonReadGCInfo)                  , (1 << CommonReadGCInfo) }, // c flag on, r flag don't care
527         {   (1 << CommonReadGCInfo)|(1 << ReadGCInfo), (1 << ReadGCInfo)       }, // r flag on, c flag off
528         {   (1 << CommonReadGCInfo)|(1 << ReadGCInfo), 0                       }, // both flags off
529         {   0, 0 }
530     };
531
532     // Make three passes over the gc infos, emitting them in order of decreasing hotness,
533     // and for stuff that wasn't touched by anyone we put it in the cold section
534     for (const MaskValue *pMaskValue = gcInfoSequence; pMaskValue->mask; pMaskValue++)
535     {
536         for (COUNT_T i = 0; i < m_MethodCompilationOrder.GetCount(); i++)
537         {
538             ZapMethodHeader * pMethod = m_MethodCompilationOrder[i];
539
540             if ((pMethod->m_ProfilingDataFlags & pMaskValue->mask) != pMaskValue->value)
541             {
542                 continue;
543             }
544
545             ZapGCInfo * pGCInfo = pMethod->m_pGCInfo;
546
547             // Given that GC Info can be interned it may have been placed already on
548             // this or a previous pass through the compiled methods. If it hasn't already
549             // been placed then we place it in the appropriate section.
550             if (!pGCInfo->IsPlaced())
551             {
552                 //  A) it was touched, and here they are placed in order of flags above
553                 if (pMaskValue->value)
554                 {
555                     m_pHotTouchedGCSection->Place(pGCInfo);
556                 }
557                 //  B) the method that it is attached to is in the trained section
558                 else if (i<m_iUntrainedMethod)
559                 {
560                     m_pHotGCSection->Place(pGCInfo);
561                 }
562                 // C) it wasn't touched _and_ it is related to untrained code
563                 else
564                 {
565                     m_pGCSection->Place(pGCInfo);
566                 }
567             }
568         }
569
570         // Just after placing those touched in an IBC scenario, place those that
571         // should be prioritized regardless of the corresponding method's IBC information.
572         // (Currently, this is used to pack the gc info of IL stubs that cannot be directly tracked by IBC.)
573         if (pMaskValue->value == (1 << ReadGCInfo))
574         {
575             for (COUNT_T i = 0; i < m_PrioritizedGCInfo.GetCount(); i++)
576             {
577                 ZapGCInfo * pGCInfo = m_PrioritizedGCInfo[i];
578                 if (!pGCInfo->IsPlaced())
579                 {
580                     m_pHotGCSection->Place(pGCInfo);
581                 }
582             }
583         }
584     }
585 #else // REDHAWK
586     //
587     ModuleGcInfoEncoder * pEncoder = GetGcInfoEncoder();
588
589     m_pUnwindInfoBlob   = pEncoder->ConstructUnwindInfoBlob(this);
590     m_pCallsiteInfoBlob = pEncoder->ConstructCallsiteInfoBlob(this);
591     ZapBlob * pShortcutMap   = pEncoder->ConstructDeltaShortcutMap(this);
592
593     // @TODO: we could fold this loop into ConstructMethodInfoBlob, but then we'd have to keep a separate
594     // list of method infos inside the ModuleGcInfoEncoder..
595     for (COUNT_T i = 0; i < m_MethodCompilationOrder.GetCount(); i++)
596     {
597         ZapMethodHeader * pMethod = m_MethodCompilationOrder[i];
598         pEncoder->EncodeMethodInfo(pMethod->m_pGCInfo);
599     }
600     ZapBlob * pMethodInfos   = pEncoder->ConstructMethodInfoBlob(this);
601
602     for (COUNT_T i = 0; i < m_MethodCompilationOrder.GetCount(); i++)
603     {
604         ZapMethodHeader * pMethod = m_MethodCompilationOrder[i];
605         // At this point pMethod->m_pGCInfo is really a pointer that the encoder owns.
606         // We must pass it back to the encoder so it can encode it and pass back a proper ZapBlob *
607         pMethod->m_pGCInfo = pEncoder->FindMethodInfo(this, pMethod->m_pGCInfo);
608     }
609
610     m_pGCSection->Place(pShortcutMap);
611     m_pGCSection->Place(pMethodInfos);
612     if (m_pUnwindInfoBlob)
613         m_pGCSection->Place(m_pUnwindInfoBlob);
614
615     if (m_pCallsiteInfoBlob)
616         m_pGCSection->Place(m_pCallsiteInfoBlob);
617
618     //
619     // Create the method-number-to-gc-info table
620     //
621     UINT32 methodInfoSize = pMethodInfos->GetSize();
622
623     COUNT_T nMethods = m_MethodCompilationOrder.GetCount();
624     UINT16 elemSize = 4;
625
626     if (methodInfoSize <= 0x10000)
627     {
628         elemSize = 2;
629
630         // Remember the element size for this map in the module header
631         m_moduleHeaderFlags |= ModuleHeader::SmallGCInfoListEntriesFlag;
632     }
633
634     // Create the table
635     SIZE_T tableSize = elemSize * nMethods;
636     ZapBlob * pMethodToGcInfoMap = ZapBlob::NewBlob(this, NULL, tableSize);
637
638     UINT16* pwTableEntries = (UINT16*) pMethodToGcInfoMap->GetData();
639     UINT32* pdwTableEntries = (UINT32*) pwTableEntries;
640
641     for (COUNT_T i = 0; i < nMethods; i++)
642     {
643         ZapMethodHeader * pMethod = m_MethodCompilationOrder[i];
644         ZapGCInfo * pGCInfo = pMethod->m_pGCInfo;
645
646         UINT32 uOffset = 0; 
647         if (pGCInfo->GetType() == ZapNodeType_InnerPtr)
648         {
649             uOffset = ((ZapInnerPtr*)pGCInfo)->GetOffset();
650         }
651         else
652         {
653             assert(ZapNodeType_Blob == pGCInfo->GetType());
654             assert(pGCInfo == pMethodInfos);
655         }
656
657         if (2 == elemSize)
658         {
659             assert(uOffset <= 0xFFFF);
660             pwTableEntries[i] = uOffset;
661         }
662         else
663         {
664             pdwTableEntries[i] = uOffset;
665         }
666     }
667
668     m_pMethodToGCInfoMap->Place(pMethodToGcInfoMap);
669 #endif // REDHAWK
670 }
671
672 #ifdef REDHAWK
673 // Place all ZapExceptionInfo blobs into the exception section, and form the lookup table that we'll
674 // use at runtime to find EH info for a given method.
675 void ZapImage::OutputEHInfo()
676 {
677     // For non-REDHAWK builds, we output EH info with the other per-method data in OutputCodeInfo().
678
679     // @TODO: consider emitting EH info in order of increasing hotness, like we do for GC info.
680
681     // Place EH info for every method that has EH.
682     for (COUNT_T i = 0; i < m_MethodCompilationOrder.GetCount(); i++)
683     {
684         ZapMethodHeader * pMethod = m_MethodCompilationOrder[i];
685         ZapExceptionInfo * pEHInfo = pMethod->m_pExceptionInfo;
686
687         if ((pEHInfo != NULL) && !pEHInfo->IsPlaced())
688         {
689             // We add relocs to the exception info here, at the last possible momement before placing
690             // them. That's because adding relocs changes the exception info, but prior to this we
691             // want to be able to use the data of the exception info as a hash key for interning.
692             AddRelocsForEHClauses(pEHInfo);
693             m_pExceptionSection->Place(pEHInfo);
694         }
695     }
696
697     // Get the offsets for each EH blob that we will emit.
698     MapSHash<ZapNode *, UINT32>   ehinfoOffsets;
699     UINT32                        ehinfoSize;
700
701     ehinfoSize = m_pExceptionSection->FillInNodeOffsetMap(&ehinfoOffsets);
702
703     // Chose a table entry size.
704     COUNT_T nMethods = m_MethodCompilationOrder.GetCount();
705     UINT16 elemSize = 4;
706
707     if (ehinfoSize <= 0x10000)
708     {
709         elemSize = 2;
710
711         // Remember the element size for this map in the module header
712         m_moduleHeaderFlags |= ModuleHeader::SmallEHInfoListEntriesFlag;
713     }
714
715     // Create the table.
716     SIZE_T tableSize = elemSize * nMethods;
717     SArray<BYTE> tableData(tableSize);
718
719     UINT16* pwTableEntries = (UINT16*)&tableData[0];
720     UINT32* pdwTableEntries = (UINT32*) pwTableEntries;
721
722     // Fill in the offset for each method that has EH info. For methods that have no
723     // EH info, we will use a sentinel offset of -1.
724     for (COUNT_T i = 0; i < nMethods; i++)
725     {
726         ZapMethodHeader * pMethod = m_MethodCompilationOrder[i];
727         ZapExceptionInfo * pEHInfo = pMethod->m_pExceptionInfo;
728
729         UINT32 uOffset = -1;
730
731         if (pEHInfo != NULL)
732         {
733             ehinfoOffsets.Lookup(pEHInfo, &uOffset);
734             assert(uOffset != -1); // Can't have a valid offset match the sentinel!
735             assert((4 == elemSize) || (uOffset <= 0xFFFF)); // Size must fit in 2 bytes if we're using hte small rep.
736         }
737
738         if (2 == elemSize)
739         {
740             pwTableEntries[i] = uOffset;
741         }
742         else
743         {
744             pdwTableEntries[i] = uOffset;
745         }
746     }
747
748     m_pMethodToEHInfoMap->Place(ZapBlob::NewBlob(this, &tableData[0], tableSize));
749 }
750 #endif // REDHAWK
751
752 #ifdef REDHAWK
753 // Add relocs for any EEType references in any typed EH clauses for the given EH Info.
754 void ZapImage::AddRelocsForEHClauses(ZapExceptionInfo * pExceptionInfo)
755 {
756     EE_ILEXCEPTION *pEHInfo = (EE_ILEXCEPTION *)pExceptionInfo->GetData();
757     _ASSERTE(pEHInfo != NULL);
758
759     // One set of relocs for the entire set of clauses. Size assuming that every clause has a token.
760     ZapReloc * pRelocs = (ZapReloc *)
761         new (GetHeap()) BYTE[sizeof(ZapReloc) * pEHInfo->EHCount() + sizeof(ZapRelocationType)];
762
763     DWORD relocIndex = 0;
764
765     // Add relocs for EEType references each typed clause.
766     for (int i = 0; i < pEHInfo->EHCount(); i++)
767     {
768         EE_ILEXCEPTION_CLAUSE *pClause = pEHInfo->EHClause(i);
769
770         if ((pClause->Flags == COR_ILEXCEPTION_CLAUSE_NONE) ||
771             (pClause->Flags == COR_ILEXCEPTION_CLAUSE_INDIRECT_TYPE_REFERENCE))
772         {
773             ZapNode *pEETypeNode = (ZapNode*)pClause->EETypeReference;
774
775             // @TODO: we're using a full pointer for each EEType reference in the EH clause. This will be 
776             // 64bits on a 64bit system, though, which is twice as large as it needs to be. We should make 
777             // these 32bit RVA's and compute the final address at runtime when we start supporting 64bit 
778             // systems. See comments in ZapInfo::setEHinfo() for more details.
779             //
780             // N.B! If we move to RVAs, then the runtime structure that matches the EE_ILEXCEPTION struct 
781             // needs to have a padding field removed.  (The C++ compiler introduced 4 bytes of padding between 
782             // 'DataSize' and 'Clauses' because 'Clauses' has a pointer field in it.  This padding will
783             // disappear when we change the pointers to RVAs.)
784             pRelocs[relocIndex].m_type = IMAGE_REL_BASED_PTR;
785             pRelocs[relocIndex].m_pTargetNode = pEETypeNode;
786             pRelocs[relocIndex].m_offset = (BYTE*)pClause - (BYTE*)pEHInfo + offsetof(EE_ILEXCEPTION_CLAUSE, EETypeReference);
787             pExceptionInfo->ZeroPointer(pRelocs[relocIndex].m_offset);
788             relocIndex++;
789         }
790     }
791
792     // Did we end up with any relocs? If so, then add them to the blob.
793     if (relocIndex > 0)
794     {
795         // Set sentinel
796         C_ASSERT(offsetof(ZapReloc, m_type) == 0);
797         pRelocs[relocIndex].m_type = IMAGE_REL_INVALID;
798
799         pExceptionInfo->SetRelocs(pRelocs);
800     }
801 }
802 #endif // REDHAWK
803
804 //
805 // ZapMethodHeader
806 //
807
808 #if defined(_TARGET_X86_)
809
810 DWORD ZapCodeBlob::ComputeRVA(ZapWriter * pZapWriter, DWORD dwPos)
811 {
812     void * pData = GetData();
813     SIZE_T size = GetSize();
814     DWORD dwAlignment = GetAlignment();
815
816     dwPos = AlignUp(dwPos, dwAlignment);
817
818 #ifdef _TARGET_X86_
819     //
820     // Padding for straddler relocations.
821     //
822
823     // The maximum size of padding
824     const DWORD cbAdjustForDynamicBaseMax = 256;
825
826     // Find padding that gives us minimum number of straddlers
827     DWORD nMinStraddlers = MAXDWORD;
828     DWORD bestPad = 0;
829     for (DWORD pad = 0; pad < cbAdjustForDynamicBaseMax; pad += dwAlignment)
830     {
831         COUNT_T nStraddlers = GetCountOfStraddlerRelocations(dwPos + pad);
832         if (nStraddlers < nMinStraddlers)
833         {
834             nMinStraddlers = nStraddlers;
835             bestPad = pad;
836
837             // It won't get better than this.
838             if (nMinStraddlers == 0)
839                 break;
840         }
841     }
842
843     DWORD dwPaddedPos = dwPos + bestPad;
844     SetRVA(dwPaddedPos);
845
846     return dwPaddedPos + size;
847 #endif // _TARGET_X86_
848 }
849
850 template <DWORD alignment>
851 class ZapCodeBlobConst : public ZapCodeBlob
852 {
853 protected:
854     ZapCodeBlobConst(SIZE_T cbSize)
855         : ZapCodeBlob(cbSize)
856     {
857     }
858
859 public:
860     virtual UINT GetAlignment()
861     {
862         return alignment;
863     }
864
865     static ZapCodeBlob * NewBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize)
866     {
867         S_SIZE_T cbAllocSize = S_SIZE_T(sizeof(ZapCodeBlobConst<alignment>)) + S_SIZE_T(cbSize);
868         if(cbAllocSize.IsOverflow())
869             ThrowHR(COR_E_OVERFLOW);
870         
871         void * pMemory = new (pWriter->GetHeap()) BYTE[cbAllocSize.Value()];
872
873         ZapCodeBlob * pZapCodeBlob = new (pMemory) ZapCodeBlobConst<alignment>(cbSize);
874
875         if (pData != NULL)
876             memcpy((void*)(pZapCodeBlob + 1), pData, cbSize);
877
878         return pZapCodeBlob;
879     }
880 };
881
882 ZapCodeBlob * ZapCodeBlob::NewAlignedBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize, SIZE_T cbAlignment)
883 {
884     switch (cbAlignment)
885     {
886     case 1:
887         return ZapCodeBlobConst<1>::NewBlob(pWriter, pData, cbSize);
888     case 2:
889         return ZapCodeBlobConst<2>::NewBlob(pWriter, pData, cbSize);
890     case 4:
891         return ZapCodeBlobConst<4>::NewBlob(pWriter, pData, cbSize);
892     case 8:
893         return ZapCodeBlobConst<8>::NewBlob(pWriter, pData, cbSize);
894     case 16:
895         return ZapCodeBlobConst<16>::NewBlob(pWriter, pData, cbSize);
896
897     default:
898         _ASSERTE(!"Requested alignment not supported");
899         return NULL;
900     }
901 }
902
903 #endif
904
905
906 // See function prototype for details on why this iterator is "partial"
907 BOOL ZapMethodHeader::PartialTargetMethodIterator::GetNext(CORINFO_METHOD_HANDLE *pHnd)
908 {
909     _ASSERTE(pHnd != NULL);
910
911     if (m_pCurReloc == NULL)
912     {
913         return FALSE;
914     }
915
916     while (m_pCurReloc->m_type != IMAGE_REL_INVALID)
917     {
918         ZapNode * pTarget = m_pCurReloc->m_pTargetNode;
919         ZapNodeType type = pTarget->GetType();
920
921         m_pCurReloc++;
922
923         if (type == ZapNodeType_InnerPtr)
924         {
925             pTarget = ((ZapInnerPtr *)pTarget)->GetBase();
926             type = pTarget->GetType();
927         }
928
929         if (type == ZapNodeType_MethodEntryPoint)
930         {
931             *pHnd = ((ZapMethodEntryPoint *)pTarget)->GetHandle();
932             return TRUE;
933         }
934     }
935
936     return FALSE;
937 }
938
939 void ZapCodeMethodDescs::Save(ZapWriter * pZapWriter)
940 {
941     ZapImage * pImage = ZapImage::GetImage(pZapWriter);
942
943     COUNT_T nUnwindInfos = 0;
944     
945     for (COUNT_T curMethod = m_iStartMethod; curMethod < m_iEndMethod; curMethod++)
946     {
947         ZapMethodHeader * pMethod = pImage->m_MethodCompilationOrder[curMethod];
948         DWORD dwRVA = pImage->m_pPreloader->MapMethodHandle(pMethod->GetHandle());
949
950         if (pMethod->m_pExceptionInfo != NULL)
951             dwRVA |= HAS_EXCEPTION_INFO_MASK;
952
953         pImage->Write(&dwRVA, sizeof(dwRVA));
954         nUnwindInfos++;
955
956 #ifdef WIN64EXCEPTIONS
957         ZapUnwindInfo * pFragment = pMethod->m_pUnwindInfoFragments;
958         while (pFragment != NULL)
959         {
960             if (pFragment != pMethod->m_pUnwindInfo && pFragment->GetCode() == pMethod->m_pCode)
961             {
962                 dwRVA = 0;
963                 pImage->Write(&dwRVA, sizeof(dwRVA));
964                 nUnwindInfos++;
965             }
966
967             pFragment = pFragment->GetNextFragment();
968         }
969 #endif
970     }
971     _ASSERTE(nUnwindInfos == m_nUnwindInfos);
972 }
973
974 //
975 // ZapMethodEntryPoint
976 //
977
978 void ZapMethodEntryPoint::Resolve(ZapImage * pImage)
979 {
980     DWORD rvaValue = pImage->m_pPreloader->MapMethodEntryPoint(GetHandle());
981 #ifdef _DEBUG
982     if (rvaValue == NULL)
983     {
984         mdMethodDef token;
985         pImage->GetCompileInfo()->GetMethodDef(GetHandle(), &token);
986         pImage->Error(token, S_OK, 0, W("MapMethodEntryPoint failed"));
987     }
988     else
989 #endif
990     {
991         SetRVA(rvaValue);
992     }
993 }
994
995 ZapMethodEntryPoint * ZapMethodEntryPointTable::GetMethodEntryPoint(CORINFO_METHOD_HANDLE handle, CORINFO_ACCESS_FLAGS accessFlags)
996 {
997     ZapMethodEntryPoint * pMethodEntryPoint = m_entries.Lookup(MethodEntryPointKey(handle, accessFlags));
998
999     if (pMethodEntryPoint != NULL)
1000         return pMethodEntryPoint;
1001
1002 #ifdef _DEBUG
1003     mdMethodDef token;
1004     m_pImage->GetCompileInfo()->GetMethodDef(handle, &token);
1005 #endif
1006
1007     pMethodEntryPoint = new (m_pImage->GetHeap()) ZapMethodEntryPoint(handle, accessFlags);
1008     m_entries.Add(pMethodEntryPoint);
1009     return pMethodEntryPoint;
1010 }
1011
1012 void ZapMethodEntryPointTable::Resolve()
1013 {
1014     for (MethodEntryPointTable::Iterator i = m_entries.Begin(), end = m_entries.End(); i != end; i++)
1015     {
1016         ZapMethodEntryPoint * pMethodEntryPoint = *i;
1017
1018         // Skip unused entrypoints - they may be omitted in the image
1019         if (!pMethodEntryPoint->IsUsed())
1020             continue;
1021
1022         pMethodEntryPoint->Resolve(m_pImage);
1023     }
1024 }
1025
1026 ZapNode * ZapMethodEntryPointTable::CanDirectCall(ZapMethodEntryPoint * pMethodEntryPoint, ZapMethodHeader * pCaller)
1027 {
1028     CORINFO_METHOD_HANDLE caller = pCaller->GetHandle();
1029     CORINFO_METHOD_HANDLE callee = pMethodEntryPoint->GetHandle();
1030
1031     CorInfoIndirectCallReason reason;
1032     if (m_pImage->canIntraModuleDirectCall(caller, callee, &reason, pMethodEntryPoint->GetAccessFlags()))
1033     {
1034         ZapNode * pCode = m_pImage->GetCompiledMethod(callee)->GetCode();
1035 #ifdef _TARGET_ARM_
1036         pCode = m_pImage->GetInnerPtr(pCode, THUMB_CODE);
1037 #endif // _TARGET_ARM_
1038         return pCode;
1039     }
1040     else
1041     {
1042         if (!pMethodEntryPoint->IsUsed())
1043         {
1044             // This method entry point is going to be used for indirect call.
1045             // Record this so that later we will assign it an RVA.
1046             pMethodEntryPoint->SetIsUsed();
1047         }
1048         return NULL;
1049     }
1050 }
1051
1052 #ifdef WIN64EXCEPTIONS
1053 ZapGCInfo * ZapGCInfoTable::GetGCInfo(PVOID pGCInfo, SIZE_T cbGCInfo, PVOID pUnwindInfo, SIZE_T cbUnwindInfo)
1054 {
1055     ZapGCInfo * pNode = m_blobs.Lookup(GCInfoKey(pGCInfo, cbGCInfo, pUnwindInfo, cbUnwindInfo));
1056
1057     if (pNode != NULL)
1058     {
1059         return pNode;
1060     }
1061
1062     pNode = ZapGCInfo::NewGCInfo(m_pImage, pGCInfo, cbGCInfo, pUnwindInfo, cbUnwindInfo);
1063     m_blobs.Add(pNode);
1064     return pNode;
1065 }
1066
1067 ZapGCInfo * ZapGCInfo::NewGCInfo(ZapWriter * pWriter, PVOID pGCInfo, SIZE_T cbGCInfo, PVOID pUnwindInfo, SIZE_T cbUnwindInfo)
1068 {
1069     S_SIZE_T cbAllocSize = S_SIZE_T(sizeof(ZapGCInfo)) + S_SIZE_T(cbGCInfo) + S_SIZE_T(cbUnwindInfo);
1070     if(cbAllocSize.IsOverflow())
1071         ThrowHR(COR_E_OVERFLOW);
1072
1073     void * pMemory = new (pWriter->GetHeap()) BYTE[cbAllocSize.Value()];
1074
1075     ZapGCInfo * pZapGCInfo = new (pMemory) ZapGCInfo(cbGCInfo, cbUnwindInfo);
1076     
1077     memcpy(pZapGCInfo->GetGCInfo(), pGCInfo, cbGCInfo);
1078     memcpy(pZapGCInfo->GetUnwindInfo(), pUnwindInfo, cbUnwindInfo);
1079
1080 #if !defined(_TARGET_X86_)
1081     // Make sure the personality routine thunk is created
1082     pZapGCInfo->GetPersonalityRoutine(ZapImage::GetImage(pWriter));
1083 #endif // !defined(_TARGET_X86_)
1084     return pZapGCInfo;
1085 }
1086 #else
1087 ZapGCInfo * ZapGCInfoTable::GetGCInfo(PVOID pBlob, SIZE_T cbBlob)
1088 {
1089     ZapGCInfo * pNode = m_blobs.Lookup(ZapBlob::SHashKey(pBlob, cbBlob));
1090
1091     if (pNode != NULL)
1092     {
1093         return pNode;
1094     }
1095
1096     pNode = ZapBlob::NewBlob(m_pImage, pBlob, cbBlob);
1097     m_blobs.Add(pNode);
1098     return pNode;
1099 }
1100 #endif
1101
1102 //
1103 // ZapUnwindInfo
1104 //
1105
1106 void ZapUnwindInfo::Save(ZapWriter * pZapWriter)
1107 {
1108     T_RUNTIME_FUNCTION runtimeFunction;
1109
1110 #if defined(_TARGET_ARM_) || defined(_TARGET_ARM64_)
1111     RUNTIME_FUNCTION__SetBeginAddress(&runtimeFunction, GetStartAddress());
1112     runtimeFunction.UnwindData = m_pUnwindData->GetRVA();
1113 #elif defined(_TARGET_AMD64_)
1114     runtimeFunction.BeginAddress = GetStartAddress();
1115     runtimeFunction.EndAddress = GetEndAddress();
1116     ULONG unwindData = m_pUnwindData->GetRVA();
1117     if (m_pUnwindData->GetType() == ZapNodeType_UnwindInfo) // Chained unwind info
1118         unwindData |= RUNTIME_FUNCTION_INDIRECT;
1119     runtimeFunction.UnwindData = unwindData;
1120 #elif defined(_TARGET_X86_)
1121     runtimeFunction.BeginAddress = GetStartAddress();
1122     ULONG unwindData = m_pUnwindData->GetRVA();
1123     if (m_pUnwindData->GetType() == ZapNodeType_UnwindInfo) // Chained unwind info
1124         unwindData |= RUNTIME_FUNCTION_INDIRECT;
1125     runtimeFunction.UnwindData = unwindData;
1126 #else
1127     PORTABILITY_ASSERT("ZapUnwindInfo");
1128 #endif
1129
1130     pZapWriter->Write(&runtimeFunction, sizeof(runtimeFunction));
1131 }
1132
1133 #if defined(WIN64EXCEPTIONS)
1134 // Compare the unwind infos by their offset
1135 int __cdecl ZapUnwindInfo::CompareUnwindInfo(const void* a_, const void* b_)
1136 {
1137     ZapUnwindInfo * a = *(ZapUnwindInfo **)a_;
1138     ZapUnwindInfo * b = *(ZapUnwindInfo **)b_;
1139
1140     if (a->GetStartOffset() > b->GetStartOffset())
1141     {
1142         _ASSERTE(a->GetStartOffset() >= b->GetEndOffset());
1143         return 1;
1144     }
1145
1146     if (a->GetStartOffset() < b->GetStartOffset())
1147     {
1148         _ASSERTE(a->GetEndOffset() <= b->GetEndOffset());
1149         return -1;
1150     }
1151
1152     _ASSERTE(a == b);
1153     return 0;
1154 }
1155
1156 #if defined(_TARGET_AMD64_)
1157
1158 UINT ZapUnwindData::GetAlignment()
1159 {
1160     return sizeof(ULONG);
1161 }
1162
1163 DWORD ZapUnwindData::GetSize()
1164 {
1165     DWORD dwSize = ZapBlob::GetSize();
1166
1167 #ifndef REDHAWK
1168     // Add space for personality routine, it must be 4-byte aligned.
1169     // Everything in the UNWIND_INFO has already had its size included in size
1170     dwSize = AlignUp(dwSize, sizeof(ULONG));
1171
1172     dwSize += sizeof(ULONG);
1173 #endif //REDHAWK
1174
1175     return dwSize;
1176 }
1177
1178 void ZapUnwindData::Save(ZapWriter * pZapWriter)
1179 {
1180     ZapImage * pImage = ZapImage::GetImage(pZapWriter);
1181
1182     PVOID pData = GetData();
1183     DWORD dwSize = GetBlobSize();
1184
1185     UNWIND_INFO * pUnwindInfo = (UNWIND_INFO *)pData;
1186
1187     // Check whether the size is what we expect it to be
1188     _ASSERTE(dwSize == offsetof(UNWIND_INFO, UnwindCode) + pUnwindInfo->CountOfUnwindCodes * sizeof(UNWIND_CODE));
1189 #ifndef REDHAWK
1190     pUnwindInfo->Flags = UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER;
1191 #endif //REDHAWK
1192
1193     pZapWriter->Write(pData, dwSize);
1194
1195 #ifndef REDHAWK
1196     DWORD dwPad = AlignmentPad(dwSize, sizeof(DWORD));
1197     if (dwPad != 0)
1198         pZapWriter->WritePad(dwPad);
1199
1200     ULONG personalityRoutine = GetPersonalityRoutine(pImage)->GetRVA();
1201     pZapWriter->Write(&personalityRoutine, sizeof(personalityRoutine));
1202 #endif //REDHAWK
1203 }
1204
1205 #elif defined(_TARGET_X86_)
1206
1207 UINT ZapUnwindData::GetAlignment()
1208 {
1209     return sizeof(BYTE);
1210 }
1211
1212 DWORD ZapUnwindData::GetSize()
1213 {
1214     return ZapBlob::GetSize();
1215 }
1216
1217 void ZapUnwindData::Save(ZapWriter * pZapWriter)
1218 {
1219     ZapImage * pImage = ZapImage::GetImage(pZapWriter);
1220
1221     PVOID pData = GetData();
1222     DWORD dwSize = GetBlobSize();
1223
1224     pZapWriter->Write(pData, dwSize);
1225 }
1226
1227 #elif defined(_TARGET_ARM_) || defined(_TARGET_ARM64_)
1228
1229 UINT ZapUnwindData::GetAlignment()
1230 {
1231     return sizeof(ULONG);
1232 }
1233
1234 DWORD ZapUnwindData::GetSize()
1235 {
1236     DWORD dwSize = ZapBlob::GetSize();
1237
1238     // Add space for personality routine, it must be 4-byte aligned.
1239     // Everything in the UNWIND_INFO has already had its size included in size
1240     dwSize = AlignUp(dwSize, sizeof(ULONG));
1241     dwSize += sizeof(ULONG);
1242
1243     return dwSize;
1244 }
1245
1246 void ZapUnwindData::Save(ZapWriter * pZapWriter)
1247 {
1248     ZapImage * pImage = ZapImage::GetImage(pZapWriter);
1249
1250     PVOID pData = GetData();
1251     DWORD dwSize = GetBlobSize();
1252
1253     UNWIND_INFO * pUnwindInfo = (UNWIND_INFO *)pData;
1254
1255     // Set the 'X' bit to indicate that there is a personality routine associated with this method
1256     *(LONG *)pUnwindInfo |= (1<<20);
1257
1258     pZapWriter->Write(pData, dwSize);
1259
1260     DWORD dwPad = AlignmentPad(dwSize, sizeof(DWORD));
1261     if (dwPad != 0)
1262         pZapWriter->WritePad(dwPad);
1263
1264     ULONG personalityRoutine = GetPersonalityRoutine(pImage)->GetRVA();
1265     pZapWriter->Write(&personalityRoutine, sizeof(personalityRoutine));
1266 }
1267
1268 #else
1269 UINT ZapUnwindData::GetAlignment()
1270 {
1271     PORTABILITY_ASSERT("ZapUnwindData::GetAlignment");
1272     return sizeof(ULONG);
1273 }
1274 DWORD ZapUnwindData::GetSize()
1275 {
1276     PORTABILITY_ASSERT("ZapUnwindData::GetSize");
1277     return -1;
1278 }
1279 void ZapUnwindData::Save(ZapWriter * pZapWriter)
1280 {
1281     PORTABILITY_ASSERT("ZapUnwindData::Save");
1282 }
1283
1284 #endif
1285
1286 ZapNode * ZapUnwindData::GetPersonalityRoutine(ZapImage * pImage)
1287 {
1288     // Use different personality routine pointer for filter funclets so that we can quickly tell at runtime
1289     // whether funclet is a filter.
1290 #ifdef FEATURE_READYTORUN_COMPILER
1291     if (IsReadyToRunCompilation())
1292     {
1293         ReadyToRunHelper helperNum = IsFilterFunclet() ? READYTORUN_HELPER_PersonalityRoutineFilterFunclet : READYTORUN_HELPER_PersonalityRoutine;
1294         return pImage->GetImportTable()->GetPlacedIndirectHelperThunk(helperNum);
1295     }
1296 #endif
1297     return pImage->GetHelperThunk(IsFilterFunclet() ? CORINFO_HELP_EE_PERSONALITY_ROUTINE_FILTER_FUNCLET : CORINFO_HELP_EE_PERSONALITY_ROUTINE);
1298 }
1299
1300 ZapUnwindData * ZapUnwindData::NewUnwindData(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize, BOOL fIsFilterFunclet)
1301 {
1302     SIZE_T cbAllocSize = sizeof(ZapUnwindData) + cbSize;
1303
1304     void * pMemory = new (pWriter->GetHeap()) BYTE[cbAllocSize];
1305
1306     ZapUnwindData * pZapUnwindData = fIsFilterFunclet ?
1307         (new (pMemory) ZapFilterFuncletUnwindData(cbSize)) : (new (pMemory) ZapUnwindData(cbSize));
1308
1309     memcpy((void*)(pZapUnwindData + 1), pData, cbSize);
1310
1311 #if !defined(_TARGET_X86_)
1312     // Make sure the personality routine thunk is created
1313     pZapUnwindData->GetPersonalityRoutine(ZapImage::GetImage(pWriter));
1314 #endif // !defined(_TARGET_X86_)
1315
1316     return pZapUnwindData;
1317 }
1318
1319 ZapUnwindData * ZapUnwindDataTable::GetUnwindData(PVOID pBlob, SIZE_T cbBlob, BOOL fIsFilterFunclet)
1320 {
1321     ZapUnwindData * pNode = (ZapUnwindData *)m_blobs.Lookup(ZapUnwindDataKey(pBlob, cbBlob, fIsFilterFunclet));
1322
1323     if (pNode != NULL)
1324     {
1325         return pNode;
1326     }
1327
1328     pNode = ZapUnwindData::NewUnwindData(m_pImage, pBlob, cbBlob, fIsFilterFunclet);
1329     m_blobs.Add(pNode);
1330     return pNode;
1331 }
1332 #endif // WIN64EXCEPTIONS
1333
1334 //
1335 // ZapDebugInfo
1336 //
1337
1338 ZapDebugInfo * ZapDebugInfoTable::GetDebugInfo(PVOID pBlob, SIZE_T cbBlob)
1339 {
1340     ZapDebugInfo * pNode = m_blobs.Lookup(ZapBlob::SHashKey(pBlob, cbBlob));
1341     m_nCount++;
1342
1343     if (pNode != NULL)
1344     {
1345         return pNode;
1346     }
1347
1348     pNode = ZapBlob::NewBlob(m_pImage, pBlob, cbBlob);
1349     m_blobs.Add(pNode);
1350     return pNode;
1351 }
1352
1353 void ZapDebugInfoTable::PrepareLayout()
1354 {
1355     if (m_nCount == 0)
1356         return;
1357
1358     // Make sure that the number of methods is odd number
1359     m_nCount |= 1;
1360
1361     m_pTable = new (m_pImage->GetHeap()) ZapNode * [m_nCount];
1362 }
1363
1364 void ZapDebugInfoTable::PlaceDebugInfo(ZapMethodHeader * pMethod)
1365 {
1366     // Place the debug info blob if it is not placed yet
1367     ZapBlob * pDebugInfo = pMethod->GetDebugInfo();
1368     if (pDebugInfo == NULL)
1369     {
1370         return;
1371     }
1372
1373     if (!pDebugInfo->IsPlaced())
1374     {
1375         m_pImage->m_pDebugSection->Place(pDebugInfo);
1376     }
1377
1378     mdMethodDef md;
1379     IfFailThrow(m_pImage->GetCompileInfo()->GetMethodDef(pMethod->GetHandle(), &md));
1380
1381     COUNT_T index = GetDebugRidEntryHash(md) % m_nCount;
1382
1383     ZapNode * pHead = m_pTable[index];
1384     if (pHead == NULL)
1385     {
1386         // The common case - single rid entry.
1387         m_pTable[index] = pMethod;
1388         return;
1389     }
1390
1391     // Create linked list of labelled entries if we do not have one yet
1392     if (pHead->GetType() != ZapNodeType_DebugInfoLabelledEntry)
1393     {
1394         m_pTable[index] = new (m_pImage->GetHeap()) LabelledEntry((ZapMethodHeader *)pHead);
1395     }
1396
1397     // Insert the method at the end of the linked list
1398     LabelledEntry * pEntry = (LabelledEntry *)m_pTable[index];
1399     while (pEntry->m_pNext != NULL)
1400         pEntry = pEntry->m_pNext;
1401
1402     pEntry->m_pNext = new (m_pImage->GetHeap()) LabelledEntry(pMethod);
1403 }
1404
1405 void ZapDebugInfoTable::FinishLayout()
1406 {
1407     // Go over the table again and place all labelled entries
1408     for (COUNT_T i = 0; i < m_nCount; i++)
1409     {
1410         ZapNode * pNode = m_pTable[i];
1411
1412         if (pNode == NULL || pNode->GetType() != ZapNodeType_DebugInfoLabelledEntry)
1413             continue;
1414
1415         LabelledEntry * pEntry = (LabelledEntry *)pNode;
1416
1417         while (pEntry != NULL)
1418         {
1419             m_pImage->m_pDebugSection->Place(pEntry);
1420             pEntry = pEntry->m_pNext;
1421         }
1422     }
1423 }
1424
1425 void ZapDebugInfoTable::Save(ZapWriter * pZapWriter)
1426 {
1427     for (COUNT_T i = 0; i < m_nCount; i++)
1428     {
1429         CORCOMPILE_DEBUG_ENTRY entry = 0;
1430
1431         ZapNode * pNode = m_pTable[i];
1432
1433         if (pNode != NULL)
1434         {
1435             if (pNode->GetType() == ZapNodeType_DebugInfoLabelledEntry)
1436                 entry |= pNode->GetRVA() | CORCOMPILE_DEBUG_MULTIPLE_ENTRIES;
1437             else
1438                 entry = ((ZapMethodHeader *)pNode)->GetDebugInfo()->GetRVA();
1439         }
1440
1441         pZapWriter->Write(&entry, sizeof(entry));
1442     }
1443 }
1444
1445 void ZapDebugInfoTable::LabelledEntry::Save(ZapWriter * pZapWriter)
1446 {
1447     CORCOMPILE_DEBUG_LABELLED_ENTRY entry;
1448
1449     entry.nativeCodeRVA = m_pMethod->GetCode()->GetRVA();
1450     entry.debugInfoOffset = m_pMethod->GetDebugInfo()->GetRVA();
1451
1452     if (m_pNext != NULL)
1453         entry.debugInfoOffset |= CORCOMPILE_DEBUG_MULTIPLE_ENTRIES;
1454
1455     pZapWriter->Write(&entry, sizeof(entry));
1456 }
1457
1458 //
1459 // ZapProfileData
1460 //
1461 void ZapProfileData::Save(ZapWriter * pZapWriter)
1462 {
1463     ZapImage * pImage = ZapImage::GetImage(pZapWriter);
1464
1465     CORCOMPILE_METHOD_PROFILE_LIST profileData;
1466
1467     ZeroMemory(&profileData, sizeof(CORCOMPILE_METHOD_PROFILE_LIST));
1468
1469     if (m_pNext != NULL)
1470         pImage->WriteReloc(&profileData,
1471                            offsetof(CORCOMPILE_METHOD_PROFILE_LIST, next),
1472                            m_pNext, 0, IMAGE_REL_BASED_PTR);
1473
1474     pZapWriter->Write(&profileData, sizeof(CORCOMPILE_METHOD_PROFILE_LIST));
1475 }
1476
1477
1478 // Zapping of ExeptionInfoTable
1479 ZapExceptionInfoLookupTable::ZapExceptionInfoLookupTable(ZapImage *pImage) : m_pImage(pImage)
1480 {
1481     _ASSERTE(m_pImage->m_pExceptionSection != NULL);
1482     m_pImage->m_pExceptionSection->Place(this);
1483 }
1484
1485 void ZapExceptionInfoLookupTable::PlaceExceptionInfoEntry(ZapNode* pCode, ZapExceptionInfo* pExceptionInfo)
1486 {
1487     ExceptionInfoEntry entry;
1488     entry.m_pCode = pCode;
1489     entry.m_pExceptionInfo = pExceptionInfo;
1490     m_exceptionInfoEntries.Append(entry);
1491     m_pImage->m_pExceptionSection->Place(pExceptionInfo);
1492 }
1493
1494 DWORD ZapExceptionInfoLookupTable::GetSize()
1495 {
1496     if (m_exceptionInfoEntries.GetCount() == 0)
1497         return 0;
1498
1499     DWORD numExceptionInfoEntries = m_exceptionInfoEntries.GetCount();
1500     // 1 sentential entry at the end of the table.
1501     return (numExceptionInfoEntries + 1) * sizeof(CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY);
1502 }
1503
1504 void ZapExceptionInfoLookupTable::Save(ZapWriter* pZapWriter) 
1505 {
1506
1507     if(m_exceptionInfoEntries.GetCount() == 0)
1508         return;
1509
1510     for(COUNT_T i = 0; i < m_exceptionInfoEntries.GetCount(); ++i)
1511     {
1512         DWORD methodStartRVA = m_exceptionInfoEntries[i].m_pCode->GetRVA();
1513
1514         ZapExceptionInfo* pExceptionInfo = m_exceptionInfoEntries[i].m_pExceptionInfo;
1515
1516         CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY lookupEntry;
1517
1518         lookupEntry.MethodStartRVA = methodStartRVA;
1519         lookupEntry.ExceptionInfoRVA = pExceptionInfo->GetRVA();
1520
1521         pZapWriter->Write(&lookupEntry, sizeof(CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY));
1522
1523 #ifdef _DEBUG
1524         // Make sure there are no gaps between 2 consecutive CORCOMPILE_EXCEPTION_CLAUSE
1525         // We use pointer arithmatic to calculate the number of EHClause for a method.
1526         if (i != 0)
1527         {
1528             ZapExceptionInfo* pPreviousExceptionInfo =  m_exceptionInfoEntries[i-1].m_pExceptionInfo;
1529             DWORD size = pExceptionInfo->GetRVA() - pPreviousExceptionInfo->GetRVA();
1530             DWORD ehClauseSize = size % sizeof(CORCOMPILE_EXCEPTION_CLAUSE);
1531             CONSISTENCY_CHECK_MSG(ehClauseSize == 0, "There must be no gaps between 2 successive clause arrays, please check ZapExceptionInfo alignment");
1532         }
1533 #endif 
1534     }
1535
1536     // write a sentinal entry.. this entry helps to find the number of EHClauses for the last entry
1537     CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY sentinalEntry;
1538
1539     ExceptionInfoEntry lastEntry = m_exceptionInfoEntries[m_exceptionInfoEntries.GetCount() -1];
1540
1541     ZapExceptionInfo* pLastExceptionInfo = lastEntry.m_pExceptionInfo;
1542
1543     sentinalEntry.MethodStartRVA = (DWORD)-1;
1544
1545     // points just after the end of the Exception table
1546     // the sentinal node m_pExceptionInfo pointer actually points to an invalid CORCOMPILE_EXCEPTION_CLAUSE 
1547     // area.  The lookup algorithm will never dereference the sentinal pointer, and hence this is safe
1548     sentinalEntry.ExceptionInfoRVA = pLastExceptionInfo->GetRVA() + pLastExceptionInfo->GetSize();
1549
1550     pZapWriter->Write(&sentinalEntry, sizeof(CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY));
1551 }
1552
1553
1554 DWORD ZapUnwindInfoLookupTable::GetSize()
1555 {
1556     // Sentinal entry at the end
1557     return (GetNumEntries() + 1) * sizeof (DWORD);
1558 }
1559
1560 void ZapUnwindInfoLookupTable::Save(ZapWriter* pZapWriter)
1561 {
1562     ZapVirtualSection * pRuntimeFunctionSection = m_pRuntimeFunctionSection;
1563
1564     // Create Lookup entries.
1565     // 1 lookup entry for each RUNTIME_FUNCTION_LOOKUP_STRIDE K of code.
1566     COUNT_T nUnwindInfos = pRuntimeFunctionSection->GetNodeCount();
1567
1568     DWORD dwCodeSectionStartAddress = m_pCodeSection->GetRVA();
1569
1570     DWORD nLookupEntries = 0;
1571     DWORD entry;
1572
1573     DWORD nTotalLookupEntries = GetNumEntries();
1574
1575     // write out the first entry
1576     entry = 0;
1577     pZapWriter->Write(&entry, sizeof(DWORD));
1578     nLookupEntries++;
1579     if (nLookupEntries == nTotalLookupEntries)
1580         goto WriteSentinel;
1581
1582     for (COUNT_T i = 1; i < nUnwindInfos; ++i)
1583     {
1584         ZapUnwindInfo* pUnwindInfo = (ZapUnwindInfo*)pRuntimeFunctionSection->GetNode(i);
1585         DWORD RelativePC = pUnwindInfo->GetStartAddress() - dwCodeSectionStartAddress;
1586
1587         COUNT_T iCurrentIndex = RelativePC / RUNTIME_FUNCTION_LOOKUP_STRIDE;
1588
1589         // Note that we should not be using pUnwindInfo->GetEndAddress() here. The binary search 
1590         // in the VM that's accelerated by this table does not look at the EndAddress either, and 
1591         // so not using EndAddress here assures consistency.
1592         COUNT_T iPreviousIndex = (RelativePC - 1)/ RUNTIME_FUNCTION_LOOKUP_STRIDE;
1593
1594         while(iPreviousIndex >= nLookupEntries)
1595         {
1596             entry = i - 1;
1597             pZapWriter->Write(&entry, sizeof(DWORD));
1598             nLookupEntries++;
1599             if (nLookupEntries == nTotalLookupEntries)
1600                 goto WriteSentinel;
1601         }
1602
1603         if (iCurrentIndex == nLookupEntries)
1604         {
1605             entry = i;
1606             pZapWriter->Write(&entry, sizeof(DWORD));
1607             nLookupEntries++;
1608             if (nLookupEntries == nTotalLookupEntries)
1609                 goto WriteSentinel;
1610         }
1611     }
1612
1613 WriteSentinel:
1614     // There should always be one sentinel entry at the end. The sentinel entry will
1615     // be good to cover the rest of the section to account for extra padding.
1616     _ASSERTE(nLookupEntries <= nTotalLookupEntries);
1617
1618     while (nLookupEntries <= nTotalLookupEntries)
1619     {
1620         entry = nUnwindInfos - 1;
1621         pZapWriter->Write(&entry, sizeof (DWORD));
1622         nLookupEntries ++;
1623     }
1624 }
1625
1626 DWORD ZapColdCodeMap::GetSize()
1627 {
1628     return m_pRuntimeFunctionSection->GetNodeCount() * sizeof(CORCOMPILE_COLD_METHOD_ENTRY);
1629 }
1630
1631 void ZapColdCodeMap::Save(ZapWriter* pZapWriter)
1632 {
1633     ZapImage * pImage = ZapImage::GetImage(pZapWriter);
1634
1635     ZapNode * pPendingCode = NULL;
1636     COUNT_T curMethod = 0;
1637
1638     COUNT_T nUnwindInfos = m_pRuntimeFunctionSection->GetNodeCount();
1639     for (COUNT_T i = 0; i < nUnwindInfos; ++i)
1640     {
1641         CORCOMPILE_COLD_METHOD_ENTRY entry;
1642
1643         ZapUnwindInfo* pUnwindInfo = (ZapUnwindInfo*)m_pRuntimeFunctionSection->GetNode(i);
1644
1645 #ifdef WIN64EXCEPTIONS
1646         if (pUnwindInfo->GetCode() == pPendingCode)
1647         {
1648             entry.mainFunctionEntryRVA = 0;
1649             entry.hotCodeSize = 0;
1650         }
1651         else
1652 #endif
1653         {
1654             pPendingCode = pUnwindInfo->GetCode();
1655
1656             ZapMethodHeader * pMethod;
1657
1658             for (;;)
1659             {
1660                 pMethod = pImage->m_MethodCompilationOrder[curMethod];
1661                 if (pMethod->m_pColdCode == pPendingCode)
1662                     break;
1663                 curMethod++;
1664             }
1665
1666 #ifdef WIN64EXCEPTIONS
1667             entry.mainFunctionEntryRVA = pMethod->m_pUnwindInfo->GetRVA();
1668 #endif
1669
1670             entry.hotCodeSize = pMethod->m_pCode->GetSize();
1671         }
1672
1673         pZapWriter->Write(&entry, sizeof(entry));
1674     }
1675 }
1676
1677 DWORD ZapHelperThunk::GetSize()
1678 {
1679     return (m_dwHelper & CORCOMPILE_HELPER_PTR) ? sizeof(TADDR) : HELPER_TABLE_ENTRY_LEN;
1680 }
1681
1682 void ZapHelperThunk::Save(ZapWriter * pZapWriter)
1683 {
1684 #ifdef _DEBUG
1685     LOG((LF_ZAP, LL_INFO1000000, "Emitting JIT helper table entry for helper %3d (%s)\n",
1686         (USHORT) m_dwHelper, s_rgHelperNames[(USHORT) m_dwHelper]));
1687 #endif // _DEBUG
1688
1689     // Save the index of the helper, the actual code for the thunk will be generated at runtime
1690     pZapWriter->Write(&m_dwHelper, sizeof(DWORD));
1691
1692     DWORD pad = GetSize() - sizeof(DWORD);
1693     if (pad > 0)
1694     {
1695         void * pPad = _alloca(pad);
1696         memset(pPad, DEFAULT_CODE_BUFFER_INIT, pad);
1697         pZapWriter->Write(pPad, pad);
1698     }
1699 }
1700
1701 void ZapLazyHelperThunk::Place(ZapImage * pImage)
1702 {
1703     m_pArg = pImage->m_pPreloadSections[CORCOMPILE_SECTION_MODULE];
1704
1705     m_pTarget = pImage->GetHelperThunk(m_dwHelper);
1706
1707     pImage->m_pLazyHelperSection->Place(this);
1708 }
1709
1710 DWORD ZapLazyHelperThunk::GetSize()
1711 {
1712     return SaveWorker(NULL);
1713 }
1714
1715 void ZapLazyHelperThunk::Save(ZapWriter * pZapWriter)
1716 {
1717     SaveWorker(pZapWriter);
1718 }
1719
1720 DWORD ZapLazyHelperThunk::SaveWorker(ZapWriter * pZapWriter)
1721 {
1722     ZapImage * pImage = ZapImage::GetImage(pZapWriter);
1723
1724     BYTE buffer[42]; // Buffer big enough to hold any reasonable helper thunk sequence
1725     BYTE * p = buffer;
1726
1727 #if defined(_TARGET_X86_)
1728     // mov edx, module
1729     *p++ = 0xBA;
1730     if (pImage != NULL)
1731         pImage->WriteReloc(buffer, (int)(p - buffer), m_pArg, 0, IMAGE_REL_BASED_PTR);
1732     p += 4;
1733
1734     // jmp JIT_StrCns
1735     *p++ = 0xE9;
1736     if (pImage != NULL)
1737         pImage->WriteReloc(buffer, (int)(p - buffer), m_pTarget, 0, IMAGE_REL_BASED_REL32);
1738     p += 4;
1739 #elif defined(_TARGET_AMD64_)
1740     *p++ = 0x48;
1741     *p++ = 0x8D;
1742 #ifdef UNIX_AMD64_ABI
1743     // lea rsi, module
1744     *p++ = 0x35;
1745 #else
1746     // lea rdx, module
1747     *p++ = 0x15;
1748 #endif
1749     if (pImage != NULL)
1750         pImage->WriteReloc(buffer, (int)(p - buffer), m_pArg, 0, IMAGE_REL_BASED_REL32);
1751     p += 4;
1752
1753     // jmp JIT_StrCns
1754     *p++ = 0xE9;
1755     if (pImage != NULL)
1756         pImage->WriteReloc(buffer, (int)(p - buffer), m_pTarget, 0, IMAGE_REL_BASED_REL32);
1757     p += 4;
1758 #elif defined(_TARGET_ARM_)
1759     // movw r1, module
1760     *(WORD *)(p + 0) = 0xf240;
1761     *(WORD *)(p + 2) = 1 << 8;
1762     // movt r1, module
1763     *(WORD *)(p + 4) = 0xf2c0;
1764     *(WORD *)(p + 6) = 1 << 8;
1765     if (pImage != NULL)
1766         pImage->WriteReloc(buffer, (int)(p - buffer), m_pArg, 0, IMAGE_REL_BASED_THUMB_MOV32);
1767     p += 8;
1768
1769     // b JIT_StrCns
1770     *(WORD *)(p + 0) = 0xf000;
1771     *(WORD *)(p + 2) = 0xb800;
1772     if (pImage != NULL)
1773         pImage->WriteReloc(buffer, (int)(p - buffer), m_pTarget, 0, IMAGE_REL_BASED_THUMB_BRANCH24);
1774     p += 4;
1775 #elif defined(_TARGET_ARM64_)
1776     // ldr x1, [PC+8]
1777     *(DWORD *)(p) =0x58000041;
1778     p += 4;
1779     // b JIT_StrCns
1780     *(DWORD *)(p) = 0x14000000;
1781     if (pImage != NULL)
1782         pImage->WriteReloc(buffer, (int)(p - buffer), m_pTarget, 0, IMAGE_REL_ARM64_BRANCH26);
1783     p += 4;
1784     if (pImage != NULL)
1785         pImage->WriteReloc(buffer, (int)(p - buffer), m_pArg, 0, IMAGE_REL_BASED_PTR);
1786     p += 8;
1787 #else
1788     PORTABILITY_ASSERT("ZapLazyHelperThunk::Save");
1789 #endif
1790
1791     _ASSERTE(p - buffer <= sizeof(buffer));
1792
1793     if (pZapWriter != NULL)
1794         pZapWriter->Write(&buffer, (int)(p - buffer));
1795
1796     return (DWORD) (p - buffer);
1797 }