5683f4f3e12460a9377e22de99fc60204dad18d9
[platform/upstream/coreclr.git] / src / zap / zapinfo.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 // ZapInfo.cpp
6 //
7
8 //
9 // JIT-EE interface for zapping
10 // 
11 // ======================================================================================
12
13 #include "common.h"
14
15 #include "zapcode.h"
16 #include "zapimport.h"
17 #include "zapwrapper.h"
18 #include "zapinnerptr.h"
19 #include "zapmetadata.h"
20
21 #ifdef FEATURE_READYTORUN_COMPILER
22 #include "zapreadytorun.h"
23 #endif
24
25 ZapInfo::ZapInfo(ZapImage * pImage, mdMethodDef md, CORINFO_METHOD_HANDLE handle, CORINFO_MODULE_HANDLE module, unsigned methodProfilingDataFlags)
26     : m_pImage(pImage),
27     m_currentMethodToken(md),
28     m_currentMethodHandle(handle),
29     m_currentMethodModule(module),
30     m_currentMethodProfilingDataFlags(methodProfilingDataFlags),
31
32     m_pNativeVarInfo(NULL),
33     m_iNativeVarInfo(0),
34     m_pOffsetMapping(NULL),
35     m_iOffsetMapping(0),
36     m_pGCInfo(NULL),
37     m_cbGCInfo(0),
38     m_pCode(NULL),
39     m_pColdCode(NULL),
40     m_pROData(NULL),
41 #ifdef WIN64EXCEPTIONS
42     // Unwind info of the main method body. It will get merged with GC info.
43     m_pMainUnwindInfo(NULL),
44     m_cbMainUnwindInfo(0),
45
46     m_pUnwindInfo(NULL),
47     m_pUnwindInfoFragments(NULL),
48 #if defined(_TARGET_AMD64_)
49     m_pChainedColdUnwindInfo(NULL),
50 #endif
51 #endif // WIN64EXCEPTIONS
52     m_pExceptionInfo(NULL),
53     m_pProfileData(NULL),
54     m_pProfilingHandle(NULL),
55
56     m_ClassLoadTable(pImage),
57     m_MethodLoadTable(pImage)
58 {
59     m_zapper = m_pImage->m_zapper;
60
61     m_pEEJitInfo = m_zapper->m_pEEJitInfo;
62     m_pEEJitInfo->setOverride(this, handle);
63
64     m_pEECompileInfo = m_zapper->m_pEECompileInfo;
65 }
66
67 ZapInfo::~ZapInfo()
68 {
69     m_pEEJitInfo->setOverride(NULL, NULL);
70
71     delete [] m_pNativeVarInfo;
72     delete [] m_pOffsetMapping;
73
74     delete [] m_pGCInfo;
75 #ifdef WIN64EXCEPTIONS
76     delete [] m_pMainUnwindInfo;
77 #endif
78 }
79
80 #ifdef ALLOW_SXS_JIT_NGEN
81 // The AltJit failed and we're going to retry. Forget everything the JIT told us and prepare to JIT again.
82 void ZapInfo::ResetForJitRetry()
83 {
84     delete [] m_pNativeVarInfo;
85     m_pNativeVarInfo = NULL;
86
87     m_iNativeVarInfo = 0;
88
89     delete [] m_pOffsetMapping;
90     m_pOffsetMapping = NULL;
91
92     m_iOffsetMapping = 0;
93
94     delete [] m_pGCInfo;
95     m_pGCInfo = NULL;
96
97     m_cbGCInfo = 0;
98
99 #ifdef WIN64EXCEPTIONS
100     delete [] m_pMainUnwindInfo;
101     m_pMainUnwindInfo = NULL;
102
103     m_cbMainUnwindInfo = 0;
104 #endif // WIN64EXCEPTIONS
105
106     // The rest of these pointers are in the ZapWriter's ZapHeap, and will go away when the ZapWriter
107     // goes away. That's ok for altjit fallback; we'll use extra memory until the ZapWriter goes away,
108     // but we won't write anything to the image. We just zero out the pointers and constants, and we're good.
109
110     m_pCode = NULL;
111     m_pColdCode = NULL;
112     m_pROData = NULL;
113
114 #ifdef WIN64EXCEPTIONS
115     m_pUnwindInfoFragments = NULL;
116     m_pUnwindInfo = NULL;
117 #if defined(_TARGET_AMD64_)
118     m_pChainedColdUnwindInfo = NULL;
119 #endif
120 #endif // WIN64EXCEPTIONS
121
122     m_pExceptionInfo = NULL;
123     m_pProfileData = NULL;
124     m_pProfilingHandle = NULL;
125
126     m_ImportSet.RemoveAll();
127     m_Imports.Clear();
128     m_CodeRelocations.Clear();
129 }
130 #endif // ALLOW_SXS_JIT_NGEN
131
132 void ZapInfo::InitMethodName()
133 {
134     const char* szClsName;
135     const char* szMethodName = m_pEEJitInfo->getMethodName(
136                                         m_currentMethodHandle,
137                                         &szClsName);
138
139     m_currentMethodName.SetUTF8(szClsName);
140     m_currentMethodName.AppendUTF8(NAMESPACE_SEPARATOR_STR);
141     m_currentMethodName.AppendUTF8(szMethodName);
142 }
143
144 CORJIT_FLAGS ZapInfo::ComputeJitFlags(CORINFO_METHOD_HANDLE handle)
145 {
146     CORJIT_FLAGS jitFlags = m_zapper->m_pOpt->m_compilerFlags;
147
148     CORJIT_FLAGS flags;
149     IfFailThrow(m_pEECompileInfo->GetBaseJitFlags(handle, &flags));
150     jitFlags.Add(flags);
151
152     // COMPlus_JitFramed specifies the default fpo setting for jitted and NGened code.
153     // You can override the behavior for NGened code using COMPlus_NGenFramed.
154     static ConfigDWORD g_NGenFramed;
155     DWORD dwNGenFramed = g_NGenFramed.val(CLRConfig::UNSUPPORTED_NGenFramed);
156     if (dwNGenFramed == 0) 
157     {
158         // NGened code should enable fpo
159         jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_FRAMED);
160     } 
161     else if (dwNGenFramed == 1) 
162     {
163         // NGened code should disable fpo
164         jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_FRAMED);
165     }
166
167     if (canSkipMethodVerification(m_currentMethodHandle) == CORINFO_VERIFICATION_CAN_SKIP)
168     {
169         jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_SKIP_VERIFICATION);
170     }
171
172     if (m_pImage->m_profileDataSections[MethodBlockCounts].pData && 
173         !m_zapper->m_pOpt->m_ignoreProfileData)
174     {
175         jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_BBOPT);
176     }
177
178     // 
179     // By default we always enable Hot/Cold procedure splitting
180     //
181     jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_PROCSPLIT);
182
183     if (m_zapper->m_pOpt->m_noProcedureSplitting)
184         jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_PROCSPLIT);
185
186     //never emit inlined polls for NGen'd code.  The extra indirection is not optimal.
187     if (jitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_GCPOLL_INLINE))
188     {
189         jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_GCPOLL_INLINE);
190         jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_GCPOLL_CALLS);
191     }
192
193     // If the method is specified for min-opts then turn everything off
194     if (jitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_MIN_OPT))
195     {
196         jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_BBINSTR);
197         jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_BBOPT);
198         jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_PROCSPLIT);
199     }
200
201     // Rejit is now enabled by default for NGEN'ed code. This costs us
202     // some size in exchange for diagnostic functionality, but we've got
203     // further work planned that should mitigate the size increase.
204     jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_PROF_REJIT_NOPS);
205
206 #ifdef FEATURE_READYTORUN_COMPILER
207     if (IsReadyToRunCompilation())
208         jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_READYTORUN);
209 #endif
210
211     return jitFlags;
212 }
213
214 ZapDebugInfo * ZapInfo::EmitDebugInfo()
215 {
216     if (m_iNativeVarInfo == 0 && m_iOffsetMapping == 0)
217     {
218         return NULL;
219     }
220
221     // We create a temporary buffer which is conservatily estimated to be
222     // bigger than we need. We then copy the used portion into the ngen image.
223
224     StackSBuffer debugInfoBuffer;
225     m_pEECompileInfo->CompressDebugInfo( 
226             m_pOffsetMapping, m_iOffsetMapping,
227             m_pNativeVarInfo, m_iNativeVarInfo,
228             &debugInfoBuffer);
229
230     if (IsReadyToRunCompilation())
231         return ZapBlob::NewBlob(m_pImage, &debugInfoBuffer[0], debugInfoBuffer.GetSize());
232
233     return m_pImage->m_pDebugInfoTable->GetDebugInfo(&debugInfoBuffer[0], debugInfoBuffer.GetSize());
234 }
235
236 ZapGCInfo * ZapInfo::EmitGCInfo()
237 {    
238     _ASSERTE(m_pGCInfo != NULL);
239
240 #ifdef WIN64EXCEPTIONS
241     return m_pImage->m_pGCInfoTable->GetGCInfo(m_pGCInfo, m_cbGCInfo, m_pMainUnwindInfo, m_cbMainUnwindInfo);
242 #else
243     return m_pImage->m_pGCInfoTable->GetGCInfo(m_pGCInfo, m_cbGCInfo);
244 #endif // WIN64EXCEPTIONS
245 }
246
247 ZapImport ** ZapInfo::EmitFixupList()
248 {
249     ZapImport ** pFixupList = NULL;
250
251     if (m_Imports.GetCount() != 0)
252     {
253         pFixupList = new (m_pImage->GetHeap()) ZapImport * [m_Imports.GetCount() + 1];
254         memcpy(pFixupList, &(m_Imports[0]), m_Imports.GetCount() * sizeof(ZapImport *));
255     }
256
257     return pFixupList;
258 }
259
260 // Used by qsort
261 int __cdecl ZapInfo::CompareCodeRelocation(const void * a_, const void * b_)
262 {
263     ZapInfo::CodeRelocation * a = (ZapInfo::CodeRelocation *)a_;
264     ZapInfo::CodeRelocation * b = (ZapInfo::CodeRelocation *)b_;
265
266     if (a->m_pNode != b->m_pNode)
267     {
268         return (a->m_pNode > b->m_pNode) ? 1 : -1;
269     }
270
271     return a->m_offset - b->m_offset;
272 }
273
274 void ZapInfo::EmitCodeRelocations()
275 {
276     if (m_CodeRelocations.IsEmpty())
277         return;
278
279     qsort(&m_CodeRelocations[0], m_CodeRelocations.GetCount(), sizeof(CodeRelocation), CompareCodeRelocation);
280
281     COUNT_T startIndex = 0;
282     while (startIndex < m_CodeRelocations.GetCount())
283     {
284         ZapBlobWithRelocs * pNode = m_CodeRelocations[startIndex].m_pNode;
285
286         COUNT_T endIndex = startIndex + 1;
287         for ( ; endIndex < m_CodeRelocations.GetCount(); endIndex++)
288         {
289             if (m_CodeRelocations[endIndex].m_pNode != pNode)
290                 break;
291         }
292
293         ZapReloc * pRelocs = (ZapReloc *)
294             new (m_pImage->GetHeap()) BYTE[sizeof(ZapReloc) * (endIndex - startIndex) + sizeof(ZapRelocationType)];
295
296         for (COUNT_T i = 0; i < endIndex - startIndex; i++)
297             pRelocs[i] = m_CodeRelocations[startIndex + i];
298
299         // Set sentinel
300         static_assert_no_msg(offsetof(ZapReloc, m_type) == 0);
301         *(ZapRelocationType *)(pRelocs + (endIndex - startIndex)) = IMAGE_REL_INVALID;
302
303         pNode->SetRelocs(pRelocs);
304
305         startIndex = endIndex;
306     }
307 }
308
309 void ZapInfo::ProcessReferences()
310 {
311     COUNT_T count = m_CodeRelocations.GetCount();
312     for (COUNT_T i = 0; i < count; i++)
313     {
314         CORINFO_METHOD_HANDLE hMethod = NULL;
315         CORINFO_CLASS_HANDLE hClass = NULL;
316         bool fMaybeConditionalImport = false;
317
318         ZapNode * pTarget = m_CodeRelocations[i].m_pTargetNode;
319
320         ZapNodeType type = pTarget->GetType();
321         if (type == ZapNodeType_InnerPtr)
322         {
323             pTarget = ((ZapInnerPtr *)pTarget)->GetBase();
324             type = pTarget->GetType();
325         }
326
327         switch (type)
328         {
329         case ZapNodeType_MethodEntryPoint:
330             hMethod = ((ZapMethodEntryPoint*)pTarget)->GetHandle();
331
332             if (m_pImage->m_pPreloader->DoesMethodNeedRestoringBeforePrestubIsRun(hMethod))
333             {
334                 methodMustBeLoadedBeforeCodeIsRun(hMethod);
335             }
336             break;
337
338         case ZapNodeType_Import_MethodHandle:
339         case ZapNodeType_Import_FunctionEntry:
340         case ZapNodeType_Import_IndirectPInvokeTarget:
341             hMethod = (CORINFO_METHOD_HANDLE)(((ZapImport *)pTarget)->GetHandle());
342             fMaybeConditionalImport = true;
343             break;
344         case ZapNodeType_Import_ClassHandle:
345         case ZapNodeType_Import_ClassDomainId:
346         case ZapNodeType_Import_SyncLock:
347             hClass = (CORINFO_CLASS_HANDLE)((ZapImport *)pTarget)->GetHandle();
348             fMaybeConditionalImport = true;
349             break;
350         case ZapNodeType_Import_FieldHandle:
351         case ZapNodeType_Import_StaticFieldAddress:
352             hClass = m_pEEJitInfo->getFieldClass((CORINFO_FIELD_HANDLE)(((ZapImport *)pTarget)->GetHandle()));
353             fMaybeConditionalImport = true;
354             break;
355         case ZapNodeType_Import_StringHandle:
356         case ZapNodeType_Import_ModuleHandle:
357         case ZapNodeType_Import_ModuleDomainId:
358         case ZapNodeType_Import_VarArg:
359             fMaybeConditionalImport = true;
360             break;
361
362         case ZapNodeType_MethodHandle:
363             hMethod = (CORINFO_METHOD_HANDLE)(((ZapWrapper *)pTarget)->GetHandle());
364             break;
365
366         case ZapNodeType_ExternalMethodThunk:
367         case ZapNodeType_ExternalMethodCell:
368             hMethod = (CORINFO_METHOD_HANDLE)((ZapImport*)pTarget)->GetHandle();
369             break;
370
371         default:
372             break;
373         }
374
375         if (fMaybeConditionalImport)
376         {
377             const ImportEntry * pExistingEntry = m_ImportSet.LookupPtr((ZapImport *)pTarget);
378             if (pExistingEntry != NULL && pExistingEntry->fConditional)
379             {
380                 const_cast<ImportEntry *>(pExistingEntry)->fConditional = false;
381                 m_Imports.Append((ZapImport *)pTarget);
382
383                 // 'handle' does not have to be added to CORCOMPILE_LOAD_TABLE since we adding
384                 // it to CORCOMPILE_HANDLE_TABLE
385                 if (hMethod != NULL)
386                     m_MethodLoadTable.Load(hMethod, TRUE);
387                 else
388                 if (hClass != NULL)
389                     m_ClassLoadTable.Load(hClass, TRUE);
390             }
391         }
392
393         if (hMethod != NULL)
394         {
395             m_pImage->m_pPreloader->MethodReferencedByCompiledCode(hMethod);
396         }
397     }
398 }
399
400 // Compile a method using the JIT or Module compiler, and emit fixups
401
402 void ZapInfo::CompileMethod()
403 {
404     PRECONDITION(m_zapper->m_pJitCompiler != NULL);
405
406     InitMethodName();
407
408     if (m_zapper->m_pOpt->m_verbose)
409     {
410         // The evaluation of m_currentMethodName.GetUnicode() is expensive
411         // only do it when we are truely logging
412         m_zapper->Info(W("Compiling method %s\n"), m_currentMethodName.GetUnicode());
413     }
414
415     m_currentMethodInfo = CORINFO_METHOD_INFO();
416     if (!getMethodInfo(m_currentMethodHandle, &m_currentMethodInfo))
417     {
418         return;
419     }
420
421     // Method does not have IL (e.g. an abstract method)
422     if (m_currentMethodInfo.ILCodeSize == 0)
423         return;
424
425     // During ngen we look for a hint attribute on the method that indicates
426     // the method should be preprocessed for early
427     // preparation. This normally happens automatically, but for methods that
428     // are prepared explicitly at runtime the needed
429     // information is missing from the ngen image, causing costly overheads
430     // at runtime. When the author of the method knows about
431     // this they can add the hint and reduce the perf cost at runtime.
432     m_pImage->m_pPreloader->PrePrepareMethodIfNecessary(m_currentMethodHandle);
433
434     m_jitFlags = ComputeJitFlags(m_currentMethodHandle);
435
436 #ifdef FEATURE_READYTORUN_COMPILER
437     if (IsReadyToRunCompilation())
438     {
439         // READYTORUN: FUTURE: Producedure spliting
440         m_jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_PROCSPLIT);
441
442         DWORD methodAttribs = getMethodAttribs(m_currentMethodHandle);
443         if (!(methodAttribs & CORINFO_FLG_NOSECURITYWRAP) || (methodAttribs & CORINFO_FLG_SECURITYCHECK))
444         {
445             m_zapper->Warning(W("ReadyToRun: Methods with security checks not supported\n"));
446             ThrowHR(E_NOTIMPL);
447         }
448     }
449 #endif
450
451     if (m_pImage->m_stats)
452     {
453         m_pImage->m_stats->m_methods++;
454         m_pImage->m_stats->m_ilCodeSize += m_currentMethodInfo.ILCodeSize;
455     }
456
457     CorJitResult res = CORJIT_SKIPPED;
458     
459     BYTE *pCode;
460     ULONG cCode;
461
462 #ifdef ALLOW_SXS_JIT_NGEN
463     if (m_zapper->m_alternateJit)
464     {
465         REMOVE_STACK_GUARD;
466
467         res = m_zapper->m_alternateJit->compileMethod( this,
468                                                      &m_currentMethodInfo,
469                                                      CORJIT_FLAGS::CORJIT_FLAG_CALL_GETJITFLAGS,
470                                                      &pCode,
471                                                      &cCode );
472         if (FAILED(res))
473         {
474             // We will fall back to the "main" JIT on failure.
475             ResetForJitRetry();
476         }
477     }
478 #endif // ALLOW_SXS_JIT_NGEN
479
480     if (FAILED(res))
481     {
482         REMOVE_STACK_GUARD;
483
484         ICorJitCompiler * pCompiler = m_zapper->m_pJitCompiler;
485         res = pCompiler->compileMethod(this,
486                                     &m_currentMethodInfo,
487                                     CORJIT_FLAGS::CORJIT_FLAG_CALL_GETJITFLAGS,
488                                     &pCode,
489                                     &cCode);
490
491         if (FAILED(res))
492         {
493             ThrowExceptionForJitResult(res);
494         }
495     }
496     
497     MethodCompileComplete(m_currentMethodInfo.ftn);
498
499 #ifdef _TARGET_X86_
500     // The x86 JIT over estimates the code size. Trim the blob size down to 
501     // the actual size. 
502     // We can do this only for non-split code. Adjusting the code size for split
503     // methods would hose offsets in GC info.
504     if (m_pColdCode == NULL)
505     {
506         m_pCode->AdjustBlobSize(cCode);
507     }
508 #endif
509
510     PublishCompiledMethod();
511 }
512
513 #ifndef FEATURE_FULL_NGEN
514 class MethodCodeComparer
515 {
516     static BOOL NodeEquals(ZapNode * k1, ZapNode * k2)
517     {
518         return k1 == k2;
519     }
520
521     static BOOL BlobEquals(ZapBlob * k1, ZapBlob * k2)
522     {
523         if (k1 == NULL && k2 == NULL)
524             return TRUE;
525         if (k1 == NULL || k2 == NULL)
526             return FALSE;
527
528         if (k1->GetBlobSize() != k2->GetBlobSize())
529             return FALSE;
530         if (memcmp(k1->GetData(), k2->GetData(), k1->GetBlobSize()) != 0)
531             return FALSE;
532
533         return TRUE;
534     }
535
536     typedef ZapNode * EquivalentNodes[4][2];
537
538     static BOOL EquivalentNode(ZapNode * k1, ZapNode * k2, EquivalentNodes & equivalentNodes)
539     {
540         if (k1 == k2)
541             return TRUE;
542
543         for (int i = 0; i < _countof(equivalentNodes); i++)
544         {
545             if (k1 == equivalentNodes[i][0] && k2 == equivalentNodes[i][1])
546                 return TRUE;
547         }
548
549         return FALSE;
550     }
551
552     static BOOL BlobWithRelocsEquals(ZapBlobWithRelocs * k1, ZapBlobWithRelocs * k2, EquivalentNodes & equivalentNodes)
553     {
554         if (k1 == NULL && k2 == NULL)
555             return TRUE;
556         if (k1 == NULL || k2 == NULL)
557             return FALSE;
558
559         if (k1->GetBlobSize() != k2->GetBlobSize())
560             return FALSE;
561         if (memcmp(k1->GetData(), k2->GetData(), k1->GetBlobSize()) != 0)
562             return FALSE;
563
564         ZapReloc * pRelocs1 = k1->GetRelocs();
565         ZapReloc * pRelocs2 = k2->GetRelocs();
566
567         if (pRelocs1 == NULL && pRelocs2 == NULL)
568             return TRUE;
569         if (pRelocs1 == NULL || pRelocs2 == NULL)
570             return FALSE;
571
572         while (pRelocs1->m_type != IMAGE_REL_INVALID || pRelocs2->m_type != IMAGE_REL_INVALID)
573         {
574             if (pRelocs1->m_type != pRelocs2->m_type || pRelocs1->m_offset != pRelocs2->m_offset)
575                 return FALSE;
576
577             if (!EquivalentNode(pRelocs1->m_pTargetNode, pRelocs2->m_pTargetNode, equivalentNodes))
578                 return FALSE;
579
580             pRelocs1++; pRelocs2++;
581         }
582
583         return TRUE;
584     }
585
586     static BOOL UnwindInfoEquals(ZapUnwindInfo * k1, ZapUnwindInfo * k2, EquivalentNodes & equivalentNodes)
587     {
588         if (k1 == NULL && k2 == NULL)
589             return TRUE;
590         if (k1 == NULL || k2 == NULL)
591             return FALSE;
592
593         return (k1->GetStartOffset() == k2->GetStartOffset()) && 
594                (k1->GetEndOffset() == k2->GetEndOffset()) &&
595                (k1->GetUnwindData() == k2->GetUnwindData()) && 
596                EquivalentNode(k1->GetCode(), k2->GetCode(), equivalentNodes);
597     }
598
599     static BOOL UnwindInfoFragmentsEquals(ZapUnwindInfo * k1, ZapUnwindInfo * k2, EquivalentNodes & equivalentNodes)
600     {
601         if (k1 == NULL && k2 == NULL)
602             return TRUE;
603         if (k1 == NULL || k2 == NULL)
604             return FALSE;
605
606         while (k1 != NULL || k2 != NULL)
607         {
608             if (!UnwindInfoEquals(k1, k2, equivalentNodes))
609                 return FALSE;
610
611             k1 = k1->GetNextFragment(); k2 = k2->GetNextFragment();
612         }
613
614         return TRUE;
615     }
616
617     static BOOL FixupListEquals(ZapImport ** k1, ZapImport ** k2)
618     {
619         if (k1 == NULL && k2 == NULL)
620             return TRUE;
621         if (k1 == NULL || k2 == NULL)
622             return FALSE;
623
624         while (*k1 != NULL || *k2 != NULL)
625         {
626             if (*k1 != *k2)
627                 return FALSE;
628             k1++; k2++;
629         }
630
631         return TRUE;
632     }
633
634 public:
635     static BOOL MethodCodeEquals(ZapMethodHeader * k1, ZapMethodHeader * k2)
636     {
637         LIMITED_METHOD_CONTRACT;
638
639         EquivalentNodes equivalentNodes =
640         {
641             { k1->m_pCode, k2->m_pCode },
642             { k1->m_pColdCode, k2->m_pColdCode },
643             { k1->m_pROData, k2->m_pROData },
644             { k1->m_pProfileData, k2->m_pProfileData }
645         };
646
647         if (!BlobWithRelocsEquals(k1->m_pCode, k2->m_pCode, equivalentNodes))
648             return FALSE;
649
650         if (!BlobWithRelocsEquals(k1->m_pColdCode, k2->m_pColdCode, equivalentNodes))
651             return FALSE;
652
653         if (!UnwindInfoEquals(k1->m_pUnwindInfo, k2->m_pUnwindInfo, equivalentNodes))
654             return FALSE;
655
656         if (!UnwindInfoEquals(k1->m_pColdUnwindInfo, k2->m_pColdUnwindInfo, equivalentNodes))
657             return FALSE;
658
659 #ifdef WIN64EXCEPTIONS
660         if (!UnwindInfoFragmentsEquals(k1->m_pUnwindInfoFragments, k2->m_pUnwindInfoFragments, equivalentNodes))
661             return FALSE;
662 #endif
663
664         if (!BlobWithRelocsEquals(k1->m_pROData, k2->m_pROData, equivalentNodes))
665             return FALSE;
666
667         if (!BlobWithRelocsEquals(k1->m_pProfileData, k2->m_pProfileData, equivalentNodes))
668             return FALSE;
669
670         if (!NodeEquals(k1->m_pGCInfo, k2->m_pGCInfo)) // interned
671             return FALSE;
672
673         if (!NodeEquals(k1->m_pDebugInfo, k2->m_pDebugInfo)) // interned
674             return FALSE;
675
676         if (!FixupListEquals(k1->m_pFixupList, k2->m_pFixupList))
677             return FALSE;
678
679         if (!BlobEquals(k1->m_pExceptionInfo, k2->m_pExceptionInfo))
680             return FALSE;
681
682         return TRUE;
683     }
684 };
685
686 extern BOOL CanDeduplicateCode(CORINFO_METHOD_HANDLE method, CORINFO_METHOD_HANDLE duplicateMethod);
687
688 BOOL ZapImage::MethodCodeTraits::Equals(key_t k1, key_t k2)
689 {
690     if (!MethodCodeComparer::MethodCodeEquals(k1, k2))
691         return FALSE;
692
693     // Check additional VM conditions that has to be satisfied for deduplication
694     if (!CanDeduplicateCode(k1->GetHandle(), k2->GetHandle()))
695         return FALSE;
696
697     return TRUE;
698 }
699
700 COUNT_T ZapImage::MethodCodeTraits::Hash(key_t k)
701 {
702     COUNT_T hash = ZapBlob::SHashTraits::Hash(ZapBlob::SHashTraits::GetKey(k->m_pCode));
703
704     ZapReloc * pRelocs = k->m_pCode->GetRelocs();
705     if (pRelocs != NULL)
706     {
707         while (pRelocs->m_type != IMAGE_REL_INVALID)
708         {
709             ZapNode * pTarget = pRelocs->m_pTargetNode;
710             ZapNodeType type = pTarget->GetType();
711
712             if (type == ZapNodeType_InnerPtr)
713             {
714                 pTarget = ((ZapInnerPtr *)pTarget)->GetBase();
715                 type = pTarget->GetType();
716             }
717
718             // The IL stubs code often differs by just a method call or class handle. Include 
719             // these in the hash code.
720             switch (type)
721             {
722             case ZapNodeType_MethodEntryPoint:
723             case ZapNodeType_ExternalMethodThunk:
724             case ZapNodeType_ClassHandle:
725             case ZapNodeType_Import_ClassHandle:
726             case ZapNodeType_MethodHandle:
727             case ZapNodeType_Import_MethodHandle:
728                 hash = ((hash << 5) + hash) ^ (COUNT_T)(pTarget);
729                 break;
730             default:
731                 break;
732             }
733
734             pRelocs++;
735         }
736     }
737
738     return hash;
739 }
740 #endif
741
742 void ZapInfo::PublishCompiledMethod()
743 {
744     EmitCodeRelocations();
745
746     // Go through all references in the code, make sure that we have fixups for them, 
747     // and ensure that they will be otherwise present in the image if necessary
748     ProcessReferences();
749
750     // See if there are load fixups to emit.
751     m_ClassLoadTable.EmitLoadFixups(m_currentMethodHandle, this);
752
753     if (!IsReadyToRunCompilation())
754         m_MethodLoadTable.EmitLoadFixups(m_currentMethodHandle, this);
755
756     ZapMethodHeader * pMethod = new (m_pImage->GetHeap()) ZapMethodHeader();
757
758     pMethod->m_handle = m_currentMethodHandle;
759     pMethod->m_classHandle = getMethodClass(m_currentMethodHandle);
760
761     pMethod->m_pCode = m_pCode;
762     pMethod->m_pColdCode = m_pColdCode;
763     pMethod->m_pROData = m_pROData;
764
765     pMethod->m_pProfileData = m_pProfileData;
766
767     pMethod->m_pExceptionInfo = m_pExceptionInfo;
768
769     pMethod->m_pFixupList = EmitFixupList();
770
771     pMethod->m_pDebugInfo = EmitDebugInfo();
772     pMethod->m_pGCInfo = EmitGCInfo();
773
774 #ifdef WIN64EXCEPTIONS
775     pMethod->m_pUnwindInfoFragments = m_pUnwindInfoFragments;
776
777     // Set the combined GCInfo + UnwindInfo blob
778     m_pUnwindInfo->SetUnwindData(pMethod->m_pGCInfo);
779
780 #if defined(_TARGET_AMD64_)
781     if (m_pChainedColdUnwindInfo != NULL)
782     {
783         // Chain the cold unwind info with the hot unwind info
784         m_pChainedColdUnwindInfo->SetUnwindData(m_pUnwindInfo);
785     }
786 #endif // _TARGET_AMD64_
787
788 #endif // WIN64EXCEPTIONS
789
790 #ifndef FEATURE_FULL_NGEN
791     //
792     // Method code deduplication
793     //
794     // For now, the only methods eligible for de-duplication are IL stubs
795     //
796     if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB))
797     {
798         ZapMethodHeader * pDuplicateMethod = m_pImage->m_CodeDeduplicator.Lookup(pMethod);
799         if (pDuplicateMethod != NULL)
800         {
801             m_pImage->m_pPreloader->NoteDeduplicatedCode(pMethod->m_handle, pDuplicateMethod->m_handle);
802             return;
803         }
804
805         m_pImage->m_CodeDeduplicator.Add(pMethod);
806     }
807 #endif
808
809     // Remember the gc info for IL stubs associated with hot methods so they can be packed well.
810     // Stubs that have no metadata token cannot be tracked by IBC data.
811     if (m_currentMethodProfilingDataFlags & (1 << ReadMethodCode))
812     {
813         if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB))
814             m_pImage->m_PrioritizedGCInfo.Append(pMethod->m_pGCInfo);
815     }
816
817     pMethod->m_ProfilingDataFlags = m_currentMethodProfilingDataFlags;
818
819     COUNT_T methodCompilationOrder = m_pImage->m_MethodCompilationOrder.GetCount();
820     pMethod->m_compilationOrder = methodCompilationOrder;
821
822     // We need to remember the first index into m_MethodCompilationOrder where we saw a method from this class
823     m_pImage->InitializeClassLayoutOrder(pMethod->m_classHandle, methodCompilationOrder);
824
825     m_pImage->m_CompiledMethods.Add(pMethod);
826     m_pImage->m_MethodCompilationOrder.Append(pMethod);
827 }
828
829 void ZapInfo::getGSCookie(GSCookie * pCookieVal, GSCookie ** ppCookieVal)
830 {
831     *pCookieVal = 0;
832
833 #ifdef FEATURE_READYTORUN_COMPILER
834     if (IsReadyToRunCompilation())
835     {
836         *ppCookieVal = (GSCookie *)m_pImage->GetImportTable()->GetHelperImport(READYTORUN_HELPER_GSCookie);
837         return;
838     }
839 #endif
840
841     *ppCookieVal = (GSCookie *)m_pImage->GetInnerPtr(m_pImage->m_pEEInfoTable,
842         offsetof(CORCOMPILE_EE_INFO_TABLE, gsCookie));
843 }
844
845 DWORD ZapInfo::getJitFlags(CORJIT_FLAGS* jitFlags, DWORD sizeInBytes)
846 {
847     _ASSERTE(jitFlags != NULL);
848     _ASSERTE(sizeInBytes >= sizeof(m_jitFlags));
849
850     *jitFlags = m_jitFlags;
851     return sizeof(m_jitFlags);
852 }
853
854 IEEMemoryManager* ZapInfo::getMemoryManager()
855 {
856     return GetEEMemoryManager();
857 }
858     
859 bool ZapInfo::runWithErrorTrap(void (*function)(void*), void* param)
860 {
861     return m_pEEJitInfo->runWithErrorTrap(function, param);
862 }
863
864 HRESULT ZapInfo::allocBBProfileBuffer (
865     ULONG                         cBlock,
866     ICorJitInfo::ProfileBuffer ** ppBlock
867     )
868 {
869     HRESULT hr;
870
871     if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB))
872     {
873         *ppBlock = NULL;
874         return E_NOTIMPL;
875     }
876
877     // @TODO: support generic methods from other assemblies
878     if (m_currentMethodModule != m_pImage->m_hModule)
879     {
880         *ppBlock = NULL;
881         return E_NOTIMPL;
882     }
883
884     mdMethodDef md = m_currentMethodToken;
885
886     if (IsNilToken(md))
887     {
888         // This must be the non-System.Object instantiation of a generic type/method.
889         IfFailRet(m_zapper->m_pEECompileInfo->GetMethodDef(m_currentMethodHandle, &md));
890     }
891 #ifdef _DEBUG
892     else
893     {
894         mdMethodDef mdTemp;
895         IfFailRet(m_zapper->m_pEECompileInfo->GetMethodDef(m_currentMethodHandle, &mdTemp));
896         _ASSERTE(md == mdTemp);
897     }
898 #endif
899     if (IsNilToken(md))
900     {
901         return E_FAIL;
902     }
903
904     // If the JIT retries the compilation (especially during JIT stress), it can
905     // try to allocate the profiling data multiple times. We will just keep track
906     // of the latest copy in this case.
907     // _ASSERTE(m_pProfileData == NULL);
908
909     DWORD totalSize = (DWORD) (cBlock * sizeof(ICorJitInfo::ProfileBuffer)) + sizeof(CORBBTPROF_METHOD_HEADER);
910     m_pProfileData = ZapBlobWithRelocs::NewAlignedBlob(m_pImage, NULL, totalSize, sizeof(DWORD));
911     CORBBTPROF_METHOD_HEADER * profileData = (CORBBTPROF_METHOD_HEADER *) m_pProfileData->GetData();
912     profileData->size           = totalSize;
913     profileData->cDetail        = 0;
914     profileData->method.token   = md;
915     profileData->method.ILSize  = m_currentMethodInfo.ILCodeSize;
916     profileData->method.cBlock  = cBlock;
917
918     *ppBlock = (ICorJitInfo::ProfileBuffer *)(&profileData->method.block[0]);
919
920     return S_OK;
921 }
922
923 HRESULT ZapInfo::getBBProfileData (
924     CORINFO_METHOD_HANDLE         ftnHnd,
925     ULONG *                       pCount,
926     ICorJitInfo::ProfileBuffer ** ppBlock,
927     ULONG *                       numRuns
928     )
929 {
930     _ASSERTE(ppBlock);
931     _ASSERTE(pCount);
932     _ASSERTE(ftnHnd == m_currentMethodHandle);
933
934     HRESULT hr;
935
936     // Initialize outputs in case we return E_FAIL
937     *ppBlock = NULL;
938     *pCount = 0;
939     if (numRuns)
940     {
941         *numRuns = 0;
942     }
943
944     // For generic instantiations whose IL is in another module,
945     // the profile data is in that module
946     // @TODO: Fetch the profile data from the other module.
947     if ((m_currentMethodModule != m_pImage->m_hModule) ||
948         m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB))
949     {
950         return E_FAIL;
951     }
952
953     ZapImage::ProfileDataSection * DataSection_MethodBlockCounts = & m_pImage->m_profileDataSections[MethodBlockCounts];
954
955     if (!DataSection_MethodBlockCounts->pData)
956     {
957         return E_FAIL;
958     }
959
960     mdMethodDef md = m_currentMethodToken;
961
962     if (IsNilToken(md))
963     {
964         // This must be the non-System.Object instantiation of a generic type/method.
965         IfFailRet(m_zapper->m_pEECompileInfo->GetMethodDef(ftnHnd, &md));
966     }
967 #ifdef _DEBUG
968     else
969     {
970         mdMethodDef mdTemp;
971         IfFailRet(m_zapper->m_pEECompileInfo->GetMethodDef(ftnHnd, &mdTemp));
972         _ASSERTE(md == mdTemp);
973     }
974 #endif
975     if (IsNilToken(md))
976     {
977         return E_FAIL;
978     }
979
980     if (numRuns)
981     {
982         *numRuns =  m_pImage->m_profileDataNumRuns;
983     }
984
985     const ZapImage::ProfileDataHashEntry * foundEntry = m_pImage->profileDataHashTable.LookupPtr(md);
986
987     if (foundEntry == NULL)
988     {
989         return E_FAIL;
990     }
991
992     // The md must match.
993     _ASSERTE(foundEntry->md == md);
994
995     if (foundEntry->pos == 0)
996     {
997         // We might not have profile data and instead only have CompileStatus and flags
998         assert(foundEntry->size == 0);
999         return E_FAIL;
1000     }
1001
1002     //
1003     //
1004     // We found the md. Let's retrieve the profile data.
1005     //
1006     _ASSERTE(foundEntry->size >= sizeof(CORBBTPROF_METHOD_HEADER));   // The size must at least this
1007
1008     ProfileReader profileReader(DataSection_MethodBlockCounts->pData, DataSection_MethodBlockCounts->dataSize);
1009
1010     // Locate the method in interest.
1011     SEEK(foundEntry->pos);     
1012     CORBBTPROF_METHOD_HEADER *  profileData;
1013     READ_SIZE(profileData, CORBBTPROF_METHOD_HEADER, foundEntry->size);
1014     _ASSERTE(profileData->method.token == foundEntry->md);  // We should be looking at the right method
1015     _ASSERTE(profileData->size == foundEntry->size);        // and the cached size must match
1016
1017     *ppBlock = (ICorJitInfo::ProfileBuffer *) &profileData->method.block[0];
1018     *pCount  = profileData->method.cBlock;
1019
1020     // If the ILSize is non-zero the the ILCodeSize also must match
1021     // 
1022     if ((profileData->method.ILSize != 0) && (profileData->method.ILSize != m_currentMethodInfo.ILCodeSize))
1023     {
1024         // IL code for this method does not match the IL code for the method when it was profiled
1025         // in such cases we tell the JIT to discard the profile data by returning E_FAIL
1026         //
1027         return E_FAIL;
1028     }
1029
1030     return S_OK;
1031 }
1032
1033 void ZapInfo::allocMem(
1034     ULONG               hotCodeSize,    /* IN */
1035     ULONG               coldCodeSize,   /* IN */
1036     ULONG               roDataSize,     /* IN */
1037     ULONG               xcptnsCount,    /* IN */    
1038     CorJitAllocMemFlag  flag,           /* IN */
1039     void **             hotCodeBlock,   /* OUT */
1040     void **             coldCodeBlock,  /* OUT */
1041     void **             roDataBlock     /* OUT */
1042     )
1043 {
1044     bool optForSize = m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_SIZE_OPT);
1045
1046     UINT align = DEFAULT_CODE_ALIGN;
1047
1048     if ((flag & CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN) && !IsReadyToRunCompilation()) align = max(align, 16);
1049
1050     m_pCode = ZapCodeBlob::NewAlignedBlob(m_pImage, NULL, hotCodeSize, align);
1051     *hotCodeBlock = m_pCode->GetData();
1052
1053     if (coldCodeSize != 0)
1054     {
1055         align = sizeof(DWORD);
1056
1057         m_pColdCode = ZapCodeBlob::NewAlignedBlob(m_pImage, NULL, coldCodeSize, align);
1058         *coldCodeBlock = m_pColdCode->GetData();
1059     }
1060
1061     //
1062     // Allocate data
1063     //
1064
1065     if (roDataSize > 0)
1066     {
1067         if (flag & CORJIT_ALLOCMEM_FLG_RODATA_16BYTE_ALIGN)
1068         {
1069             align = 16;
1070         }
1071         else if (optForSize || (roDataSize < 8))
1072         {
1073             align = sizeof(TADDR);
1074         }
1075         else
1076         {
1077             align = 8;
1078         }
1079         m_pROData = ZapBlobWithRelocs::NewAlignedBlob(m_pImage, NULL, roDataSize, align);
1080         *roDataBlock = m_pROData->GetData();
1081     }
1082
1083     if (m_pImage->m_stats)
1084     {
1085         m_pImage->m_stats->m_nativeCodeSize     += hotCodeSize;
1086         m_pImage->m_stats->m_nativeColdCodeSize += coldCodeSize;
1087         m_pImage->m_stats->m_nativeRODataSize   += roDataSize;
1088
1089         BOOL haveProfileData = CurrentMethodHasProfileData();
1090
1091         if (haveProfileData)
1092         {
1093             m_pImage->m_stats->m_nativeCodeSizeInProfiledMethods     += hotCodeSize;
1094             m_pImage->m_stats->m_nativeColdCodeSizeInProfiledMethods += coldCodeSize;
1095         }
1096
1097         if (coldCodeSize)
1098         {
1099             m_pImage->m_stats->m_NumHotColdAllocations++;
1100
1101             m_pImage->m_stats->m_nativeCodeSizeInSplitMethods     += hotCodeSize;
1102             m_pImage->m_stats->m_nativeColdCodeSizeInSplitMethods += coldCodeSize;
1103
1104             if (haveProfileData)
1105             {
1106                 m_pImage->m_stats->m_nativeCodeSizeInSplitProfiledMethods     += hotCodeSize;
1107                 m_pImage->m_stats->m_nativeColdCodeSizeInSplitProfiledMethods += coldCodeSize;
1108             }
1109         }
1110         else
1111         {
1112             m_pImage->m_stats->m_NumHotAllocations++;
1113         }
1114     }
1115 }
1116
1117 void * ZapInfo::allocGCInfo(size_t size)
1118 {
1119     _ASSERTE(m_pGCInfo == NULL);
1120
1121 #ifdef _WIN64
1122     if (size & 0xFFFFFFFF80000000LL)
1123     {
1124         IfFailThrow(CORJIT_OUTOFMEM);
1125     }
1126 #endif // _WIN64
1127
1128     m_pGCInfo = new BYTE[size];
1129     m_cbGCInfo = size;
1130
1131     return m_pGCInfo;
1132 }
1133
1134 void ZapInfo::yieldExecution()
1135 {
1136     // nothing necessary here
1137 }
1138
1139
1140 void ZapInfo::setEHcount(unsigned cEH)
1141 {
1142     //
1143     // Must call after header has been allocated
1144     //
1145
1146     if (cEH == 0)
1147     {
1148         _ASSERTE(!"Should not be called");
1149         return;
1150     }    
1151
1152     ULONG size = (sizeof(CORCOMPILE_EXCEPTION_CLAUSE) * cEH);
1153
1154     _ASSERTE(m_pExceptionInfo == NULL);
1155     m_pExceptionInfo = ZapBlob::NewAlignedBlob(m_pImage, NULL, size, sizeof(DWORD));
1156 }
1157
1158 void ZapInfo::setEHinfo(unsigned EHnumber,
1159                         const CORINFO_EH_CLAUSE *clause)
1160 {
1161     //
1162     // Must call after EH info has been allocated
1163     //
1164
1165     _ASSERTE(m_pExceptionInfo != NULL);
1166
1167     CORCOMPILE_EXCEPTION_CLAUSE *ehClauseArray = (CORCOMPILE_EXCEPTION_CLAUSE *)m_pExceptionInfo->GetData();
1168     CORCOMPILE_EXCEPTION_CLAUSE *ilClause = &ehClauseArray[EHnumber];
1169
1170     ilClause->TryStartPC    = clause->TryOffset;
1171     ilClause->TryEndPC      = clause->TryLength;
1172     ilClause->HandlerStartPC= clause->HandlerOffset;
1173     ilClause->HandlerEndPC  = clause->HandlerLength;
1174     ilClause->Flags         = (CorExceptionFlag) clause->Flags;
1175
1176     if (clause->Flags & CORINFO_EH_CLAUSE_FILTER)
1177     {
1178         ilClause->FilterOffset = clause->FilterOffset;
1179     }
1180     else
1181     {
1182         ilClause->ClassToken = clause->ClassToken;
1183
1184         if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB) && (clause->ClassToken != 0))
1185         {
1186             // IL stub tokens are 'private' and do not resolve correctly in their parent module's metadata.
1187
1188             // Currently, the only place we are using a token here is for a COM-to-CLR exception-to-HRESULT
1189             // mapping catch clause.  We want this catch clause to catch all exceptions, so we override the
1190             // token to be mdTypeRefNil, which used by the EH system to mean catch(...)
1191
1192 #ifdef _DEBUG
1193             // The proper way to do this, should we ever want to support arbitrary types here, is to "pre-
1194             // resolve" the token and store the TypeHandle in the clause.  But this requires additional 
1195             // infrastructure to ensure the TypeHandle is saved and fixed-up properly.  For now, we will
1196             // simply assert that the original type was System.Object.
1197
1198             CORINFO_RESOLVED_TOKEN resolvedToken = { 0 };
1199             resolvedToken.tokenContext = MAKE_METHODCONTEXT(m_currentMethodInfo.ftn);
1200             resolvedToken.tokenScope = m_currentMethodInfo.scope;
1201             resolvedToken.token = ilClause->ClassToken;
1202             resolvedToken.tokenType = CORINFO_TOKENKIND_Class;
1203
1204             resolveToken(&resolvedToken);
1205
1206             CORINFO_CLASS_HANDLE systemObjectHandle = getBuiltinClass(CLASSID_SYSTEM_OBJECT);
1207             _ASSERTE(systemObjectHandle == resolvedToken.hClass);
1208 #endif // _DEBUG
1209
1210             ilClause->ClassToken = mdTypeRefNil; 
1211         }
1212     }
1213
1214     //
1215     // @TODO: this does not support DynamicMethods
1216     //
1217 }
1218
1219 int ZapInfo::canHandleException(struct _EXCEPTION_POINTERS *pExceptionPointers)
1220 {
1221     return (EXCEPTION_EXECUTE_HANDLER);
1222 }
1223
1224 int ZapInfo::doAssert(const char* szFile, int iLine, const char* szExpr)
1225 {
1226
1227 #if defined(_DEBUG)
1228     return(_DbgBreakCheck(szFile, iLine, szExpr));
1229 #else
1230     return(true);       // break into debugger
1231 #endif
1232
1233 }
1234 void ZapInfo::reportFatalError(CorJitResult result)
1235 {
1236     m_zapper->Info(W("Jit reported error 0x%x while compiling %s\n"), (int)result,
1237                    m_currentMethodName.GetUnicode());
1238 }
1239
1240 // Reserve memory for the method/funclet's unwind information
1241 // Note that this must be called before allocMem, it should be
1242 // called once for the main method, once for every funclet region, and 
1243 // once for every non-funclet cold region for which we will call 
1244 // allocUnwindinfo. 
1245 //
1246 // For prejitted code we need to count how many funclet regions
1247 // we have so that we can allocate and sort a contiguous .rdata block.
1248 //
1249 void ZapInfo::reserveUnwindInfo(BOOL isFunclet, BOOL isColdCode, ULONG unwindSize)
1250 {
1251     // Nothing to do
1252 }
1253
1254
1255 //
1256 // Allocate and initialize the .xdata and .pdata for this method or
1257 // funclet region and get the block of memory needed for the machine-specific
1258 // unwind information (the info for crawling the stack frame).
1259 // Note that allocMem must be called first.
1260 //
1261 // The pHotCode parameter points at the first byte of the code of the method.
1262 // The startOffset and endOffset are the region (main or funclet) that
1263 // we are to allocate and create .xdata and .pdata for.
1264 // The pUnwindBlock is copied and contains the .xdata unwind info.
1265 //
1266 // Parameters:
1267 //
1268 //    pHotCode        main method code buffer, always filled in
1269 //    pColdCode       cold code buffer, only filled in if this is cold code, 
1270 //                      null otherwise
1271 //    startOffset     start of code block, relative to appropriate code buffer
1272 //                      (e.g. pColdCode if cold, pHotCode if hot).
1273 //    endOffset       end of code block, relative to appropriate code buffer
1274 //    unwindSize      size of unwind info pointed to by pUnwindBlock
1275 //    pUnwindBlock    pointer to unwind info
1276 //    funcKind        type of funclet (main method code, handler, filter)
1277 //
1278 void ZapInfo::allocUnwindInfo (
1279         BYTE *              pHotCode,              /* IN */
1280         BYTE *              pColdCode,             /* IN */
1281         ULONG               startOffset,           /* IN */
1282         ULONG               endOffset,             /* IN */
1283         ULONG               unwindSize,            /* IN */
1284         BYTE *              pUnwindBlock,          /* IN */
1285         CorJitFuncKind      funcKind               /* IN */
1286         )
1287 {
1288 #ifdef WIN64EXCEPTIONS
1289     _ASSERTE(pHotCode == m_pCode->GetData());
1290     _ASSERTE(pColdCode == NULL || pColdCode == m_pColdCode->GetData());
1291
1292     ZapNode * pCode = (pColdCode != NULL) ? m_pColdCode : m_pCode;
1293
1294     ZapUnwindInfo * pUnwindInfo = new (m_pImage->GetHeap()) ZapUnwindInfo(pCode, startOffset, endOffset);    
1295
1296     // Prepend the new unwind info to the linked list of all fragments
1297     pUnwindInfo->SetNextFragment(m_pUnwindInfoFragments);
1298     m_pUnwindInfoFragments = pUnwindInfo;
1299
1300     if (funcKind == CORJIT_FUNC_ROOT && pColdCode == NULL && startOffset == 0)
1301     {
1302         //
1303         // Main method unwind data
1304         //
1305
1306         _ASSERTE(m_pMainUnwindInfo == NULL);
1307
1308         m_pMainUnwindInfo = new BYTE[unwindSize];
1309         m_cbMainUnwindInfo = unwindSize;
1310
1311         memcpy(m_pMainUnwindInfo, pUnwindBlock, unwindSize);
1312
1313         // UnwindData Will be set to the combined GCInfo + UnwindInfo blob later as the compiled method is published
1314
1315         _ASSERTE(m_pUnwindInfo == NULL);
1316         m_pUnwindInfo = pUnwindInfo;
1317     }
1318 #if defined(_TARGET_AMD64_)
1319     else
1320     if (funcKind == CORJIT_FUNC_ROOT && pColdCode != NULL)
1321     {
1322         //
1323         // Chained cold code unwind data
1324         //
1325
1326         _ASSERTE(unwindSize == 0);        
1327
1328         // UnwindData Will be chained to the parent unwind info later as the compiled method is published
1329
1330         _ASSERTE(m_pChainedColdUnwindInfo == NULL);
1331         m_pChainedColdUnwindInfo = pUnwindInfo;
1332     }
1333 #endif
1334     else
1335     {
1336
1337         //
1338         // Normal unwind data
1339         //
1340
1341         ZapUnwindData * pUnwindData = m_pImage->m_pUnwindDataTable->GetUnwindData(pUnwindBlock, unwindSize, funcKind == CORJIT_FUNC_FILTER);
1342         pUnwindInfo->SetUnwindData(pUnwindData);
1343     }     
1344 #endif // WIN64EXCEPTIONS
1345 }
1346
1347 BOOL ZapInfo::logMsg(unsigned level, const char *fmt, va_list args)
1348 {
1349     if (m_zapper->m_pOpt->m_legacyMode)
1350         return FALSE;
1351
1352     if (HasSvcLogger())
1353     {
1354         if (level <= LL_INFO10)
1355         {
1356             StackSString ss;
1357             ss.VPrintf(fmt,args);
1358             GetSvcLogger()->Log(ss.GetUnicode(), LogLevel_Success);
1359             return TRUE;
1360         }
1361     }
1362
1363 #ifdef LOGGING
1364     if (LoggingOn(LF_JIT, level))
1365     {
1366         LogSpewValist(LF_JIT, level, (char*) fmt, args);
1367         return TRUE;
1368     }
1369 #endif // LOGGING
1370
1371     return FALSE;
1372 }
1373
1374 //
1375 // ICorDynamicInfo
1376 //
1377
1378 DWORD ZapInfo::getThreadTLSIndex(void **ppIndirection)
1379 {
1380     _ASSERTE(ppIndirection != NULL);
1381
1382     *ppIndirection = NULL;
1383     return (DWORD)-1;
1384 }
1385
1386 const void * ZapInfo::getInlinedCallFrameVptr(void **ppIndirection)
1387 {
1388     _ASSERTE(ppIndirection != NULL);
1389
1390     *ppIndirection = m_pImage->GetInnerPtr(m_pImage->m_pEEInfoTable,
1391         offsetof(CORCOMPILE_EE_INFO_TABLE, inlinedCallFrameVptr));
1392     return NULL;
1393 }
1394
1395 LONG * ZapInfo::getAddrOfCaptureThreadGlobal(void **ppIndirection)
1396 {
1397     _ASSERTE(ppIndirection != NULL);
1398
1399     *ppIndirection = (LONG *) m_pImage->GetInnerPtr(m_pImage->m_pEEInfoTable,
1400         offsetof(CORCOMPILE_EE_INFO_TABLE, addrOfCaptureThreadGlobal));
1401     return NULL;
1402 }
1403
1404 // Get slow lazy string literal helper to use (CORINFO_HELP_STRCNS*).
1405 // Returns CORINFO_HELP_UNDEF if lazy string literal helper cannot be used.
1406 CorInfoHelpFunc ZapInfo::getLazyStringLiteralHelper(CORINFO_MODULE_HANDLE handle)
1407 {
1408     if (handle == m_pImage->m_hModule)
1409         return CORINFO_HELP_STRCNS_CURRENT_MODULE;
1410
1411     return CORINFO_HELP_STRCNS;
1412 }
1413
1414 CORINFO_MODULE_HANDLE ZapInfo::embedModuleHandle(CORINFO_MODULE_HANDLE handle,
1415                                                                 void **ppIndirection)
1416 {
1417     _ASSERTE(ppIndirection != NULL);
1418
1419     if (IsReadyToRunCompilation())
1420     {
1421         _ASSERTE(!"embedModuleHandle");
1422         ThrowHR(E_NOTIMPL);
1423     }
1424
1425     BOOL fHardbound = m_pImage->m_pPreloader->CanEmbedModuleHandle(handle);
1426     if (fHardbound)
1427     {
1428         if (handle == m_pImage->m_hModule)
1429         {
1430             // If the handle is the module we are currently ngening, we will
1431             // assume that Module is the very first thing in the preload section
1432             *ppIndirection = NULL;
1433             return (CORINFO_MODULE_HANDLE)m_pImage->m_pPreloadSections[CORCOMPILE_SECTION_MODULE];
1434         }
1435
1436         *ppIndirection = m_pImage->GetImportTable()->GetModuleHandleImport(handle);
1437     }
1438     else
1439     {
1440         ZapImport * pImport = m_pImage->GetImportTable()->GetModuleHandleImport(handle);
1441         AppendConditionalImport(pImport);
1442         
1443         *ppIndirection = pImport;
1444     }
1445     return NULL;
1446 }
1447
1448 //
1449 // The following functions indicate whether a handle can be directly embedded into
1450 // the code being compiled, or if it needs to be accessed with a (fixable) indirection.
1451 // Embeddable handles are those that will be persisted in the zap image.
1452 //
1453 // These functions are gradually being all moved across to ceeload.cpp and compile.cpp.
1454 //
1455
1456 CORINFO_CLASS_HANDLE ZapInfo::embedClassHandle(CORINFO_CLASS_HANDLE handle,
1457                                                          void **ppIndirection)
1458 {
1459     _ASSERTE(ppIndirection != NULL);
1460
1461     if (IsReadyToRunCompilation())
1462     {
1463         _ASSERTE(!"embedClassHandle");
1464         ThrowHR(E_NOTIMPL);
1465     }
1466
1467     m_pImage->m_pPreloader->AddTypeToTransitiveClosureOfInstantiations(handle);
1468
1469     BOOL fHardbound = m_pImage->m_pPreloader->CanEmbedClassHandle(handle); 
1470     if (fHardbound)
1471     {
1472         CORINFO_MODULE_HANDLE moduleHandle = m_pEECompileInfo->GetLoaderModuleForEmbeddableType(handle);
1473
1474         if (moduleHandle == m_pImage->m_hModule)
1475         {
1476             // If the handle is the module we are currently ngening, we can
1477             // embed it after its resolved. So use a deferred reloc
1478
1479             *ppIndirection = NULL;
1480             return CORINFO_CLASS_HANDLE(m_pImage->GetWrappers()->GetClassHandle(handle));
1481         }
1482
1483         *ppIndirection = m_pImage->GetImportTable()->GetClassHandleImport(handle);
1484     }
1485     else
1486     {
1487         ZapImport * pImport = m_pImage->GetImportTable()->GetClassHandleImport(handle);
1488         AppendConditionalImport(pImport);
1489
1490         *ppIndirection = pImport;
1491     }
1492     return NULL;
1493 }
1494
1495 CORINFO_FIELD_HANDLE ZapInfo::embedFieldHandle(CORINFO_FIELD_HANDLE handle,
1496                                                void **ppIndirection)
1497 {
1498     _ASSERTE(ppIndirection != NULL);
1499
1500     if (IsReadyToRunCompilation())
1501     {
1502         _ASSERTE(!"embedFieldHandle");
1503         ThrowHR(E_NOTIMPL);
1504     }
1505
1506     m_pImage->m_pPreloader->AddTypeToTransitiveClosureOfInstantiations(m_pEEJitInfo->getFieldClass(handle));
1507
1508     BOOL fHardbound = m_pImage->m_pPreloader->CanEmbedFieldHandle(handle); 
1509     if (fHardbound)
1510     {
1511         CORINFO_MODULE_HANDLE moduleHandle = m_pEECompileInfo->GetLoaderModuleForEmbeddableField(handle);
1512
1513         if (moduleHandle == m_pImage->m_hModule)
1514         {
1515             // If the handle is the module we are currently ngening, we can
1516             // embed it after its resolved. So use a deferred reloc
1517
1518             *ppIndirection = NULL;
1519             return CORINFO_FIELD_HANDLE(m_pImage->GetWrappers()->GetFieldHandle(handle));
1520         }
1521     }
1522
1523
1524     ZapImport * pImport = m_pImage->GetImportTable()->GetFieldHandleImport(handle);
1525     AppendConditionalImport(pImport);
1526
1527     *ppIndirection = pImport;
1528     return NULL;
1529 }
1530
1531 CORINFO_METHOD_HANDLE ZapInfo::embedMethodHandle(CORINFO_METHOD_HANDLE handle,
1532                                                  void **ppIndirection)
1533 {
1534     _ASSERTE(ppIndirection != NULL);
1535
1536     if (IsReadyToRunCompilation())
1537     {
1538         // READYTORUN FUTURE: Handle this case correctly
1539         ThrowHR(E_NOTIMPL);
1540     }
1541
1542     CORINFO_MODULE_HANDLE moduleHandle = m_pEECompileInfo->GetLoaderModuleForEmbeddableMethod(handle);
1543     if (moduleHandle == m_pImage->m_hModule 
1544         && m_pImage->m_pPreloader->CanEmbedMethodHandle(handle, m_currentMethodHandle))
1545     {
1546         // If the handle is the module we are currently ngening, we can
1547         // embed it after its resolved. So use a deferred reloc
1548
1549         *ppIndirection = NULL;
1550         return CORINFO_METHOD_HANDLE(m_pImage->GetWrappers()->GetMethodHandle(handle));
1551     }
1552
1553     ZapImport * pImport = m_pImage->GetImportTable()->GetMethodHandleImport(handle);
1554     AppendConditionalImport(pImport);
1555     
1556     *ppIndirection = pImport;
1557     return NULL;
1558 }
1559
1560 CORINFO_CLASS_HANDLE ZapInfo::getTokenTypeAsHandle(CORINFO_RESOLVED_TOKEN * pResolvedToken)
1561 {
1562     return m_pEEJitInfo->getTokenTypeAsHandle(pResolvedToken);
1563 }
1564
1565 CORINFO_LOOKUP_KIND
1566 ZapInfo::getLocationOfThisType(CORINFO_METHOD_HANDLE   context)
1567 {
1568     return m_pEEJitInfo->getLocationOfThisType(context);
1569 }
1570
1571 void
1572 ZapInfo::embedGenericHandle(CORINFO_RESOLVED_TOKEN * pResolvedToken,
1573                             BOOL                     fEmbedParent,
1574                             CORINFO_GENERICHANDLE_RESULT *pResult)
1575 {
1576     _ASSERTE(pResult);
1577
1578     m_pEEJitInfo->embedGenericHandle( pResolvedToken,
1579                                       fEmbedParent,
1580                                       pResult);
1581
1582     _ASSERTE(pResult->compileTimeHandle);
1583
1584     if (pResult->lookup.lookupKind.needsRuntimeLookup)
1585     {
1586         if (!IsReadyToRunCompilation())
1587             embedGenericSignature(&pResult->lookup);
1588
1589         if (pResult->handleType == CORINFO_HANDLETYPE_METHOD)
1590         {
1591             // There is no easy way to detect method referenced via generic lookups in generated code.
1592             // Report this method reference unconditionally.
1593             m_pImage->m_pPreloader->MethodReferencedByCompiledCode((CORINFO_METHOD_HANDLE)pResult->compileTimeHandle);
1594         }
1595     }
1596     else
1597     {
1598         void *pIndirection = 0;
1599         CORINFO_GENERIC_HANDLE handle = 0;
1600
1601         switch (pResult->handleType)
1602         {
1603         case CORINFO_HANDLETYPE_CLASS:
1604             if (IsReadyToRunCompilation())
1605             {
1606                 ZapImport * pImport = m_pImage->GetImportTable()->GetClassImport(ENCODE_TYPE_HANDLE, pResolvedToken);
1607                 AppendConditionalImport(pImport);
1608                 pIndirection = pImport;
1609                 handle = NULL;
1610             }
1611             else
1612             {
1613                 CORINFO_CLASS_HANDLE clsHnd = (CORINFO_CLASS_HANDLE) pResult->compileTimeHandle;
1614                 handle = CORINFO_GENERIC_HANDLE(embedClassHandle(clsHnd, &pIndirection));
1615             }
1616             break;
1617
1618         case CORINFO_HANDLETYPE_METHOD:
1619             if (IsReadyToRunCompilation())
1620             {
1621                 ZapImport * pImport = m_pImage->GetImportTable()->GetMethodImport(ENCODE_METHOD_HANDLE, (CORINFO_METHOD_HANDLE)pResult->compileTimeHandle, pResolvedToken);
1622                 AppendConditionalImport(pImport);
1623                 pIndirection = pImport;
1624                 handle = NULL;
1625             }
1626             else
1627             {
1628                 CORINFO_METHOD_HANDLE methHnd = (CORINFO_METHOD_HANDLE) pResult->compileTimeHandle;
1629                 handle =  CORINFO_GENERIC_HANDLE(embedMethodHandle(methHnd, &pIndirection));
1630             }
1631             break;
1632
1633         case CORINFO_HANDLETYPE_FIELD:
1634             if (IsReadyToRunCompilation())
1635             {
1636                 ZapImport * pImport = m_pImage->GetImportTable()->GetFieldImport(ENCODE_FIELD_HANDLE, (CORINFO_FIELD_HANDLE)pResult->compileTimeHandle, pResolvedToken);
1637                 AppendConditionalImport(pImport);
1638                 pIndirection = pImport;
1639                 handle = NULL;
1640             }
1641             else
1642             {
1643                 CORINFO_FIELD_HANDLE fldHnd = (CORINFO_FIELD_HANDLE) pResult->compileTimeHandle;
1644                 handle = CORINFO_GENERIC_HANDLE(embedFieldHandle(fldHnd, &pIndirection));
1645             }
1646             break;
1647
1648         default:
1649             ThrowHR(COR_E_BADIMAGEFORMAT, BFA_INVALID_TOKEN_TYPE);
1650         }
1651
1652         if (handle)
1653         {
1654             pResult->lookup.constLookup.accessType   = IAT_VALUE;
1655             pResult->lookup.constLookup.handle       = CORINFO_GENERIC_HANDLE(handle);
1656         }
1657         else
1658         {
1659             pResult->lookup.constLookup.accessType   = IAT_PVALUE;
1660             pResult->lookup.constLookup.addr         = pIndirection;
1661         }
1662     }
1663 }
1664
1665 void ZapInfo::embedGenericSignature(CORINFO_LOOKUP * pLookup)
1666 {
1667     _ASSERTE(pLookup->lookupKind.needsRuntimeLookup);
1668
1669     if (IsReadyToRunCompilation())
1670     {
1671                 UNREACHABLE_MSG("We should never get here for the ReadyToRun compilation.");
1672         ThrowHR(E_NOTIMPL);
1673     }
1674
1675     if (pLookup->runtimeLookup.signature != NULL)
1676     {
1677         pLookup->runtimeLookup.signature = m_pImage->GetImportTable()->GetGenericSignature(
1678             pLookup->runtimeLookup.signature, pLookup->lookupKind.runtimeLookupKind == CORINFO_LOOKUP_METHODPARAM);
1679     }
1680 }
1681
1682 void* ZapInfo::getTailCallCopyArgsThunk (
1683                     CORINFO_SIG_INFO       *pSig,
1684                     CorInfoHelperTailCallSpecialHandling flags)
1685 {
1686     void * pStub = m_pEEJitInfo->getTailCallCopyArgsThunk(pSig, flags);
1687     if (pStub == NULL)
1688         return NULL;
1689     return m_pImage->GetWrappers()->GetStub(pStub);
1690 }
1691
1692 #ifdef FEATURE_READYTORUN_COMPILER
1693 ReadyToRunHelper MapReadyToRunHelper(CorInfoHelpFunc func, bool * pfOptimizeForSize)
1694 {
1695     switch (func)
1696     {
1697 #define OPTIMIZEFORSIZE *pfOptimizeForSize = true;
1698 #define HELPER(readyToRunHelper, corInfoHelpFunc, flags) \
1699     case corInfoHelpFunc: flags return readyToRunHelper;
1700 #include "readytorunhelpers.h"
1701
1702     case CORINFO_HELP_STRCNS_CURRENT_MODULE:
1703         *pfOptimizeForSize = true;
1704         return READYTORUN_HELPER_GetString;
1705
1706     default:
1707         return READYTORUN_HELPER_Invalid;
1708     }
1709 }
1710 #endif // FEATURE_READYTORUN_COMPILER
1711
1712 void * ZapInfo::getHelperFtn (CorInfoHelpFunc ftnNum, void **ppIndirection)
1713 {
1714     _ASSERTE(ppIndirection != NULL);
1715     *ppIndirection = NULL;
1716
1717 #ifdef FEATURE_READYTORUN_COMPILER
1718     if (IsReadyToRunCompilation())
1719     {
1720         bool fOptimizeForSize = false;
1721         ReadyToRunHelper helperNum = MapReadyToRunHelper(ftnNum, &fOptimizeForSize);
1722
1723         if (helperNum == READYTORUN_HELPER_Invalid)
1724         {
1725             m_zapper->Warning(W("ReadyToRun: JIT helper not supported: %S\n"), m_pEEJitInfo->getHelperName(ftnNum));
1726             ThrowHR(E_NOTIMPL);
1727         }
1728
1729         if (fOptimizeForSize)
1730         {
1731             *ppIndirection = NULL;
1732             return m_pImage->GetImportTable()->GetIndirectHelperThunk(helperNum);
1733         }
1734         else
1735         {
1736             *ppIndirection = m_pImage->GetImportTable()->GetHelperImport(helperNum);
1737             return NULL;
1738         }
1739     }
1740 #endif
1741
1742     DWORD dwHelper = ftnNum;
1743
1744     switch (ftnNum)
1745     {
1746     case CORINFO_HELP_PROF_FCN_ENTER:
1747         *ppIndirection = m_pImage->GetInnerPtr(GetProfilingHandleImport(), kZapProfilingHandleImportValueIndexEnterAddr * sizeof(TADDR));
1748         return NULL;
1749     case CORINFO_HELP_PROF_FCN_LEAVE:
1750         *ppIndirection = m_pImage->GetInnerPtr(GetProfilingHandleImport(), kZapProfilingHandleImportValueIndexLeaveAddr * sizeof(TADDR));
1751         return NULL;
1752     case CORINFO_HELP_PROF_FCN_TAILCALL:
1753         *ppIndirection = m_pImage->GetInnerPtr(GetProfilingHandleImport(), kZapProfilingHandleImportValueIndexTailcallAddr * sizeof(TADDR));
1754         return NULL;
1755 #ifdef _TARGET_AMD64_
1756     case CORINFO_HELP_STOP_FOR_GC:
1757         // Force all calls in ngen images for this helper to use an indirect call.
1758         // We cannot use a jump stub to reach this helper because 
1759         // the RAX register can contain a return value.
1760         dwHelper |= CORCOMPILE_HELPER_PTR;
1761    break;
1762 #endif
1763     default:
1764         break;
1765     }
1766
1767     if (m_pImage->m_pHelperThunks[ftnNum] == NULL)
1768     {
1769         ZapNode * pHelperThunk;
1770         if (ftnNum == CORINFO_HELP_STRCNS_CURRENT_MODULE)
1771         {
1772             pHelperThunk = new (m_pImage->GetHeap()) ZapLazyHelperThunk(CORINFO_HELP_STRCNS);
1773         }            
1774         else
1775         {
1776             pHelperThunk = new (m_pImage->GetHeap()) ZapHelperThunk(dwHelper);
1777         }
1778 #if defined(_TARGET_ARM_)
1779         if ((dwHelper & CORCOMPILE_HELPER_PTR) == 0)
1780             pHelperThunk = m_pImage->GetInnerPtr(pHelperThunk, THUMB_CODE);
1781 #endif
1782         m_pImage->m_pHelperThunks[ftnNum] = pHelperThunk;
1783     }
1784
1785     void * ptr = m_pImage->m_pHelperThunks[ftnNum];
1786
1787     if (dwHelper & CORCOMPILE_HELPER_PTR)
1788     {
1789         *ppIndirection = ptr;
1790         return NULL;
1791     }
1792
1793     return ptr;
1794 }
1795
1796 ULONG ZapInfo::GetNumFixups()
1797 {
1798     return m_Imports.GetCount();
1799 }
1800
1801 void ZapInfo::AppendConditionalImport(ZapImport * pImport)
1802 {
1803     if (m_ImportSet.LookupPtr(pImport) != NULL)
1804         return;
1805
1806     ImportEntry entry;
1807     entry.pImport = pImport;
1808     entry.fConditional = true;
1809     m_ImportSet.Add(entry);
1810 }
1811
1812 void ZapInfo::AppendImport(ZapImport * pImport)
1813 {
1814     const ImportEntry * pExistingEntry = m_ImportSet.LookupPtr(pImport);
1815     if (pExistingEntry != NULL)
1816     {
1817         if (!pExistingEntry->fConditional)
1818             return;
1819         const_cast<ImportEntry *>(pExistingEntry)->fConditional = false;
1820     }
1821     else
1822     {
1823         ImportEntry entry;
1824         entry.pImport = pImport;
1825         entry.fConditional = false;
1826         m_ImportSet.Add(entry);
1827     }
1828
1829     m_Imports.Append(pImport);  
1830 }
1831
1832 //
1833 // This function indicates whether a method entry point be directly embedded into
1834 // the code being compiled, or if we can use a (fixable) cross module thunk.
1835 // If we can't use either of these then we return NULL and we will use an 
1836 // (fixable) indirection cell to perform the call.
1837 // 
1838 PVOID ZapInfo::embedDirectCall(CORINFO_METHOD_HANDLE ftn,
1839                                CORINFO_ACCESS_FLAGS accessFlags, 
1840                                BOOL fAllowThunk)
1841 {
1842     if (!m_pImage->m_pPreloader->CanEmbedFunctionEntryPoint(ftn, m_currentMethodHandle, accessFlags))
1843     {
1844         return NULL;
1845     }
1846
1847     ZapNode * pEntryPointOrThunkToEmbed = NULL;
1848
1849     //
1850     // If it's in the same module then we can call it directly
1851     //
1852     CORINFO_MODULE_HANDLE moduleHandle = m_pEECompileInfo->GetLoaderModuleForEmbeddableMethod(ftn);
1853     if (moduleHandle == m_pImage->m_hModule 
1854         && m_pImage->m_pPreloader->CanEmbedMethodHandle(ftn, m_currentMethodHandle))
1855     {
1856         pEntryPointOrThunkToEmbed = m_pImage->m_pMethodEntryPoints->GetMethodEntryPoint(ftn, accessFlags);
1857     }
1858     else  // otherwise we are calling into an external module
1859     {
1860         if (!fAllowThunk)
1861         {
1862             return NULL;
1863         }
1864
1865         pEntryPointOrThunkToEmbed = m_pImage->GetImportTable()->GetExternalMethodThunk(ftn);
1866     }
1867
1868 #ifdef _TARGET_ARM_
1869     pEntryPointOrThunkToEmbed = m_pImage->GetInnerPtr(pEntryPointOrThunkToEmbed, THUMB_CODE);
1870 #endif
1871
1872     return pEntryPointOrThunkToEmbed;
1873 }
1874
1875 void ZapInfo::getFunctionEntryPoint(
1876                                 CORINFO_METHOD_HANDLE   ftn,                 /* IN  */
1877                                 CORINFO_CONST_LOOKUP *  pResult,             /* OUT */
1878                                 CORINFO_ACCESS_FLAGS    accessFlags/*=CORINFO_ACCESS_ANY*/)
1879 {
1880     if (IsReadyToRunCompilation())
1881     {
1882         // READYTORUN: FUTURE: JIT still calls this for tail. and jmp instructions
1883         m_zapper->Warning(W("ReadyToRun: Method entrypoint cannot be encoded\n"));
1884         ThrowHR(E_NOTIMPL);
1885     }
1886
1887     // Must deal with methods that are methodImpl'd within their own type.
1888     ftn = mapMethodDeclToMethodImpl(ftn);
1889
1890     m_pImage->m_pPreloader->AddMethodToTransitiveClosureOfInstantiations(ftn);
1891
1892     void * entryPointOrThunkToEmbed = embedDirectCall(ftn, accessFlags, TRUE);
1893     if (entryPointOrThunkToEmbed != NULL)
1894     {
1895         pResult->accessType = IAT_VALUE;
1896         pResult->addr       = entryPointOrThunkToEmbed;
1897     }
1898     else
1899     {
1900         ZapImport * pImport = m_pImage->GetImportTable()->GetFunctionEntryImport(ftn);
1901         AppendConditionalImport(pImport);
1902
1903         // Tell the JIT to use an indirections
1904         pResult->accessType   = IAT_PVALUE;
1905         pResult->addr         = pImport;
1906     }
1907 }
1908
1909 void ZapInfo::getFunctionFixedEntryPoint(CORINFO_METHOD_HANDLE   ftn,
1910                                          CORINFO_CONST_LOOKUP *  pResult)
1911 {
1912     _ASSERTE(pResult);
1913
1914     m_pImage->m_pPreloader->AddMethodToTransitiveClosureOfInstantiations(ftn);
1915
1916     // We can only embed entrypoints from the module being NGened since we do not support mapping of external 
1917     // import thunks to MethodDesc. It should be ok since the delegate targets are typically from the same module.
1918     void * entryPointToEmbed = embedDirectCall(ftn, CORINFO_ACCESS_ANY, FALSE);
1919
1920     if (entryPointToEmbed != NULL)
1921     {
1922         pResult->accessType   = IAT_VALUE;
1923         pResult->addr         = entryPointToEmbed;
1924     }
1925     else
1926     {
1927         ZapImport * pImport = m_pImage->GetImportTable()->GetFunctionEntryImport(ftn);
1928         AppendConditionalImport(pImport);
1929         
1930         pResult->accessType   = IAT_PVALUE;
1931         pResult->addr         = pImport;
1932     }
1933 }
1934
1935 void * ZapInfo::getMethodSync(CORINFO_METHOD_HANDLE ftn,
1936                                             void **ppIndirection)
1937 {
1938     _ASSERTE(ppIndirection != NULL);
1939
1940     CORINFO_CLASS_HANDLE classHandle = getMethodClass(ftn);
1941
1942     ZapImport * pImport = m_pImage->GetImportTable()->GetSyncLockImport(classHandle);
1943     AppendConditionalImport(pImport);
1944
1945     *ppIndirection = pImport;
1946     return NULL;
1947 }
1948
1949 void * ZapInfo::getPInvokeUnmanagedTarget(CORINFO_METHOD_HANDLE method, void **ppIndirection)
1950 {
1951     // We will never be able to return this directly in prejit mode.
1952     _ASSERTE(ppIndirection != NULL);
1953
1954     *ppIndirection = NULL;
1955     return NULL;
1956 }
1957
1958 void * ZapInfo::getAddressOfPInvokeFixup(CORINFO_METHOD_HANDLE method,void **ppIndirection)
1959 {
1960     _ASSERTE(ppIndirection != NULL);
1961
1962     m_pImage->m_pPreloader->AddMethodToTransitiveClosureOfInstantiations(method);
1963
1964     CORINFO_MODULE_HANDLE moduleHandle = m_pEECompileInfo->GetLoaderModuleForEmbeddableMethod(method);
1965     if (moduleHandle == m_pImage->m_hModule 
1966         && m_pImage->m_pPreloader->CanEmbedMethodHandle(method, m_currentMethodHandle))
1967     {
1968         *ppIndirection = NULL;
1969         return PVOID(m_pImage->GetWrappers()->GetAddrOfPInvokeFixup(method));
1970     }
1971
1972     //
1973     // Note we could a fixup to a direct call site, rather than to
1974     // the indirection.  This would saves us an extra indirection, but changes the
1975     // semantics slightly (so that the pinvoke will be bound when the calling
1976     // method is first run, not at the exact moment of the first pinvoke.)
1977     //
1978
1979     ZapImport * pImport = m_pImage->GetImportTable()->GetIndirectPInvokeTargetImport(method);
1980     AppendConditionalImport(pImport);
1981
1982     *ppIndirection = pImport;
1983     return NULL;
1984 }
1985
1986 void ZapInfo::getAddressOfPInvokeTarget(CORINFO_METHOD_HANDLE method, CORINFO_CONST_LOOKUP *pLookup)
1987 {
1988     _ASSERTE(pLookup != NULL);
1989
1990     void * pIndirection;
1991     void * pResult = getAddressOfPInvokeFixup(method, &pIndirection);
1992     if (pResult != NULL)
1993     {
1994         pLookup->accessType = IAT_PVALUE;
1995         pLookup->addr = pResult;
1996         return;
1997     }
1998
1999     pLookup->accessType = IAT_PPVALUE;
2000     pLookup->addr = pIndirection;
2001 }
2002
2003 CORINFO_JUST_MY_CODE_HANDLE ZapInfo::getJustMyCodeHandle(
2004     CORINFO_METHOD_HANDLE method,
2005     CORINFO_JUST_MY_CODE_HANDLE **ppIndirection)
2006 {
2007     _ASSERTE(ppIndirection != NULL);
2008
2009     if (IsReadyToRunCompilation())
2010     {
2011         *ppIndirection = NULL;
2012         return NULL;
2013     }
2014
2015     *ppIndirection = (CORINFO_JUST_MY_CODE_HANDLE *)m_pImage->GetInnerPtr(m_pImage->m_pEEInfoTable,
2016         offsetof(CORCOMPILE_EE_INFO_TABLE, addrOfJMCFlag));
2017     return NULL;
2018 }
2019
2020 ZapImport * ZapInfo::GetProfilingHandleImport()
2021 {
2022     if (m_pProfilingHandle == NULL)
2023     {
2024         ZapImport * pImport = m_pImage->GetImportTable()->GetProfilingHandleImport(m_currentMethodHandle);
2025         AppendImport(pImport);
2026
2027         m_pProfilingHandle = pImport;
2028     }
2029
2030     return m_pProfilingHandle;
2031 }
2032
2033 void ZapInfo::GetProfilingHandle(BOOL                      *pbHookFunction,
2034                                  void                     **pProfilerHandle,
2035                                  BOOL                      *pbIndirectedHandles)
2036 {
2037     //
2038     // Return the location within the fixup table
2039     //
2040     // Profiling handle is opaque token. It does not have to be aligned thus we can not store it in the same location as token.
2041     //
2042     *pProfilerHandle = m_pImage->GetInnerPtr(GetProfilingHandleImport(), kZapProfilingHandleImportValueIndexClientData * sizeof(TADDR));
2043
2044     // All functions get hooked in ngen /Profile
2045     *pbHookFunction = TRUE;
2046
2047     //
2048     // This is the NGEN case, where we always do indirection on the handle so we can fix it up at load time.
2049     //
2050     *pbIndirectedHandles = TRUE;
2051 }
2052
2053 //return a callable stub that will do the virtual or interface call
2054
2055
2056 void ZapInfo::getCallInfo(CORINFO_RESOLVED_TOKEN * pResolvedToken,
2057                           CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken,
2058                           CORINFO_METHOD_HANDLE   callerHandle,
2059                           CORINFO_CALLINFO_FLAGS  flags,
2060                           CORINFO_CALL_INFO       *pResult)
2061 {
2062     void * pTarget = NULL;
2063
2064     _ASSERTE(pResult);
2065
2066     // Fill in the kind of the virtual call.
2067     // We set kindOnly=true since we don't want the EE to actually give us
2068     // a call stub - instead we want to generate an indirection ourselves.
2069     m_pEEJitInfo->getCallInfo(pResolvedToken,
2070                               pConstrainedResolvedToken,
2071                               callerHandle,
2072                               /* REVISIT_TODO
2073                                * Addition of this flag.
2074                                */
2075                               (CORINFO_CALLINFO_FLAGS)(flags | CORINFO_CALLINFO_KINDONLY),
2076                               pResult);
2077
2078 #ifdef FEATURE_READYTORUN_COMPILER
2079     if (IsReadyToRunCompilation())
2080     {
2081         if (pResult->sig.isVarArg())
2082         {
2083             m_zapper->Warning(W("ReadyToRun: VarArg methods not supported\n"));
2084             ThrowHR(E_NOTIMPL);
2085         }
2086
2087         if (pResult->accessAllowed != CORINFO_ACCESS_ALLOWED)
2088         {
2089             m_zapper->Warning(W("ReadyToRun: Runtime method access checks not supported\n"));
2090             ThrowHR(E_NOTIMPL);
2091         }
2092
2093         if (pResult->methodFlags & CORINFO_FLG_SECURITYCHECK)
2094         {
2095             m_zapper->Warning(W("ReadyToRun: Methods with security checks not supported\n"));
2096             ThrowHR(E_NOTIMPL);
2097         }
2098
2099         if (GetCompileInfo()->IsNativeCallableMethod(pResult->hMethod))
2100         {
2101             m_zapper->Warning(W("ReadyToRun: References to methods with NativeCallableAttribute not supported\n"));
2102             ThrowHR(E_NOTIMPL);
2103         }
2104     }
2105 #endif
2106
2107     if (flags & CORINFO_CALLINFO_KINDONLY)
2108         return;
2109
2110     if (IsReadyToRunCompilation())
2111     {
2112         if (pResult->thisTransform == CORINFO_BOX_THIS)
2113         {
2114             // READYTORUN: FUTURE: Optionally create boxing stub at runtime
2115             ThrowHR(E_NOTIMPL);
2116         }
2117     }
2118
2119     // OK, if the EE said we're not doing a stub dispatch then just return the kind to
2120     // the caller.  No other kinds of virtual calls have extra information attached.
2121     switch (pResult->kind)
2122     {
2123     case CORINFO_VIRTUALCALL_STUB:
2124         {
2125             if (pResult->stubLookup.lookupKind.needsRuntimeLookup)
2126             {
2127                                 if (!IsReadyToRunCompilation())
2128                                         embedGenericSignature(&pResult->stubLookup);
2129                 return;
2130             }
2131
2132 #ifdef FEATURE_READYTORUN_COMPILER
2133             if (IsReadyToRunCompilation())
2134             {
2135                 ZapImport * pImport = m_pImage->GetImportTable()->GetStubDispatchCell(pResolvedToken);
2136
2137                 pResult->stubLookup.constLookup.accessType   = IAT_PVALUE;
2138                 pResult->stubLookup.constLookup.addr         = pImport;
2139                 break;
2140             }
2141 #endif
2142
2143             CORINFO_CLASS_HANDLE calleeOwner = pResolvedToken->hClass;
2144             CORINFO_METHOD_HANDLE callee = pResolvedToken->hMethod;
2145             _ASSERTE(callee == pResult->hMethod);
2146
2147             //
2148             // Create the indirection cell
2149             //
2150             pTarget = m_pImage->GetImportTable()->GetStubDispatchCell(calleeOwner, callee);
2151
2152             pResult->stubLookup.constLookup.accessType = IAT_PVALUE;
2153
2154             pResult->stubLookup.constLookup.addr = pTarget;
2155         }
2156         break;
2157
2158
2159     case CORINFO_CALL_CODE_POINTER:
2160         _ASSERTE(pResult->codePointerLookup.lookupKind.needsRuntimeLookup);
2161                 if (!IsReadyToRunCompilation())
2162                         embedGenericSignature(&pResult->codePointerLookup);
2163
2164         // There is no easy way to detect method referenced via generic lookups in generated code.
2165         // Report this method reference unconditionally.
2166         m_pImage->m_pPreloader->MethodReferencedByCompiledCode(pResult->hMethod);
2167         return;
2168
2169     case CORINFO_CALL:
2170 #ifdef FEATURE_READYTORUN_COMPILER
2171         if (IsReadyToRunCompilation())
2172         {
2173             // Constrained token is not interesting with this transforms
2174             if (pResult->thisTransform != CORINFO_NO_THIS_TRANSFORM)
2175                 pConstrainedResolvedToken = NULL;
2176
2177             ZapImport * pImport;
2178
2179             if (flags & (CORINFO_CALLINFO_LDFTN | CORINFO_CALLINFO_ATYPICAL_CALLSITE))
2180             {
2181                 pImport = m_pImage->GetImportTable()->GetMethodImport(ENCODE_METHOD_ENTRY, pResult->hMethod, pResolvedToken, pConstrainedResolvedToken);
2182
2183                 AppendConditionalImport(pImport);
2184             }
2185             else
2186             {
2187                 pImport = m_pImage->GetImportTable()->GetExternalMethodCell(pResult->hMethod, pResolvedToken, pConstrainedResolvedToken);
2188             }
2189
2190             // READYTORUN: FUTURE: Direct calls if possible
2191             pResult->codePointerLookup.constLookup.accessType   = IAT_PVALUE;
2192             pResult->codePointerLookup.constLookup.addr         = pImport;
2193         }
2194 #endif
2195         break;
2196
2197     case CORINFO_VIRTUALCALL_VTABLE:
2198         _ASSERTE(!IsReadyToRunCompilation());
2199         break;
2200
2201     case CORINFO_VIRTUALCALL_LDVIRTFTN:
2202 #ifdef FEATURE_READYTORUN_COMPILER
2203                 if (IsReadyToRunCompilation() && !pResult->exactContextNeedsRuntimeLookup)
2204                 {
2205                         DWORD fAtypicalCallsite = (flags & CORINFO_CALLINFO_ATYPICAL_CALLSITE) ? CORINFO_HELP_READYTORUN_ATYPICAL_CALLSITE : 0;
2206
2207                         ZapImport * pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(
2208                                 (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_VIRTUAL_ENTRY | fAtypicalCallsite), pResult->hMethod, pResolvedToken);
2209
2210                         pResult->codePointerLookup.constLookup.accessType = IAT_PVALUE;
2211                         pResult->codePointerLookup.constLookup.addr = pImport;
2212
2213                         _ASSERTE(!pResult->sig.hasTypeArg());
2214                 }
2215 #endif
2216
2217         // Include the declaring instantiation of virtual generic methods in the NGen image.
2218         m_pImage->m_pPreloader->AddMethodToTransitiveClosureOfInstantiations(pResult->hMethod);
2219         break;
2220
2221     default:
2222         _ASSERTE(!"Unknown call type");
2223         break;
2224     }
2225
2226 #ifdef FEATURE_READYTORUN_COMPILER
2227     if (IsReadyToRunCompilation() && pResult->sig.hasTypeArg())
2228     {
2229         if (pResult->exactContextNeedsRuntimeLookup)
2230         {
2231                         // Nothing to do... The generic handle lookup gets embedded in to the codegen
2232                         // during the jitting of the call.
2233                         // (Note: The generic lookup in R2R is performed by a call to a helper at runtime, not by
2234                         // codegen emitted at crossgen time)
2235         }
2236         else
2237         {
2238             ZapImport * pImport;
2239             if (((SIZE_T)pResult->contextHandle & CORINFO_CONTEXTFLAGS_MASK) == CORINFO_CONTEXTFLAGS_METHOD)
2240             {
2241                 CORINFO_METHOD_HANDLE exactMethodHandle = (CORINFO_METHOD_HANDLE)((SIZE_T)pResult->contextHandle & ~CORINFO_CONTEXTFLAGS_MASK);
2242
2243                 pImport = m_pImage->GetImportTable()->GetMethodImport(ENCODE_METHOD_DICTIONARY, exactMethodHandle, 
2244                     pResolvedToken, pConstrainedResolvedToken);
2245             }
2246             else
2247             {
2248                 pImport = m_pImage->GetImportTable()->GetClassImport(ENCODE_TYPE_DICTIONARY,
2249                     (pConstrainedResolvedToken != NULL) ? pConstrainedResolvedToken : pResolvedToken);
2250             }
2251
2252             pResult->instParamLookup.accessType   = IAT_PVALUE;
2253             pResult->instParamLookup.addr         = pImport;
2254
2255             AppendConditionalImport(pImport);
2256         }
2257     }
2258 #endif
2259 }
2260 BOOL ZapInfo::canAccessFamily(CORINFO_METHOD_HANDLE hCaller,
2261                               CORINFO_CLASS_HANDLE hInstanceType)
2262 {
2263     return m_pEEJitInfo->canAccessFamily(hCaller, hInstanceType);
2264 }
2265
2266 BOOL ZapInfo::isRIDClassDomainID (CORINFO_CLASS_HANDLE cls)
2267 {
2268     return m_pEEJitInfo->isRIDClassDomainID(cls);
2269 }
2270
2271
2272 unsigned ZapInfo::getClassDomainID (CORINFO_CLASS_HANDLE cls, void **ppIndirection)
2273 {
2274     _ASSERTE(ppIndirection != NULL);
2275
2276     m_pImage->m_pPreloader->AddTypeToTransitiveClosureOfInstantiations(cls);
2277
2278     if (!m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE))
2279     {
2280         if (isRIDClassDomainID(cls))
2281         {
2282             // Token is invariant to loading order, so we can go ahead and use it
2283             
2284             // Ensure that 'cls' gets added to CORCOMPILE_LOAD_TABLE, unless
2285             // someone else adds some other type of fixup for 'cls'.
2286             m_ClassLoadTable.Load(cls, FALSE);
2287             
2288             return m_pEEJitInfo->getClassDomainID(cls, ppIndirection);
2289         }
2290
2291         if (m_pImage->m_pPreloader->CanEmbedClassID(cls))
2292         {
2293             // Ensure that 'cls' gets added to CORCOMPILE_LOAD_TABLE, unless
2294             // someone else adds some other type of fixup for 'cls'.
2295             m_ClassLoadTable.Load(cls, FALSE);
2296             return m_pEEJitInfo->getClassDomainID(cls, ppIndirection);
2297         }
2298     }
2299     
2300     // We will have to insert a fixup
2301     ZapImport * pImport = m_pImage->GetImportTable()->GetClassDomainIdImport(cls);
2302     AppendConditionalImport(pImport);
2303
2304     *ppIndirection = pImport;
2305     return NULL;
2306 }
2307
2308 void * ZapInfo::getFieldAddress(CORINFO_FIELD_HANDLE field, void **ppIndirection)
2309 {
2310     _ASSERTE(ppIndirection != NULL);
2311
2312     CORINFO_CLASS_HANDLE hClass = m_pEEJitInfo->getFieldClass(field);
2313
2314     m_pImage->m_pPreloader->AddTypeToTransitiveClosureOfInstantiations(hClass);
2315
2316     ZapImport * pImport = m_pImage->GetImportTable()->GetStaticFieldAddressImport(field);
2317     AppendConditionalImport(pImport);
2318
2319     // Field address is not aligned thus we can not store it in the same location as token.
2320     *ppIndirection = m_pImage->GetInnerPtr(pImport, sizeof(TADDR));
2321
2322     return NULL;
2323 }
2324
2325 DWORD ZapInfo::getFieldThreadLocalStoreID(CORINFO_FIELD_HANDLE field,
2326                                           void **ppIndirection)
2327 {
2328     _ASSERTE(ppIndirection != NULL);
2329
2330     *ppIndirection = m_pImage->GetInnerPtr(m_pImage->m_pEEInfoTable,
2331         offsetof(CORCOMPILE_EE_INFO_TABLE, rvaStaticTlsIndex));
2332     return NULL;
2333 }
2334
2335 CORINFO_VARARGS_HANDLE ZapInfo::getVarArgsHandle(CORINFO_SIG_INFO *sig,
2336                                                  void **ppIndirection)
2337 {
2338     _ASSERTE(ppIndirection != NULL);
2339
2340     // Zapper does not support embedding these as they are created dynamically
2341
2342     if (sig->scope != m_pImage->m_hModule || sig->token == mdTokenNil)
2343     {
2344         _ASSERTE(!"Don't have enough info to be able to create a sig token.");
2345
2346         *ppIndirection = NULL;
2347         return NULL;
2348     }
2349
2350     // @perf: If the sig cookie construction code actually will restore the value types in
2351     // the sig, we should call LoadClass on all of those types to avoid redundant
2352     // restore cookies.
2353
2354     ZapImport * pImport = m_pImage->GetImportTable()->GetVarArgImport(sig->scope, sig->token);
2355     AppendConditionalImport(pImport);
2356
2357     *ppIndirection = pImport;
2358     return NULL;
2359 }
2360
2361 bool ZapInfo::canGetVarArgsHandle(CORINFO_SIG_INFO *sig)
2362 {
2363     // Zapper does not support embedding these as they are created dynamically
2364     if (sig->scope != m_pImage->m_hModule || sig->token == mdTokenNil)
2365     {
2366         return false;
2367     }
2368
2369     return true;
2370 }
2371
2372 void ZapInfo::setOverride(ICorDynamicInfo *pOverride, CORINFO_METHOD_HANDLE currentMethod)
2373 {
2374     UNREACHABLE();
2375 }
2376
2377 void ZapInfo::addActiveDependency(CORINFO_MODULE_HANDLE moduleFrom, CORINFO_MODULE_HANDLE moduleTo)
2378 {
2379     if (IsReadyToRunCompilation())
2380         return;
2381
2382     _ASSERT(moduleFrom != moduleTo);
2383
2384     if (m_pImage->m_pPreloader->CanSkipDependencyActivation(m_currentMethodHandle, moduleFrom, moduleTo))
2385     {
2386         // No need to add dependency fixup since we will have an unconditional dependency
2387         // already
2388     }
2389     else if (!GetCompileInfo()->IsInCurrentVersionBubble(moduleTo))
2390     {
2391     }
2392     else
2393     {
2394         ZapImport * pImport = m_pImage->GetImportTable()->GetActiveDependencyImport(moduleFrom, moduleTo);
2395         AppendImport(pImport);
2396
2397         CORINFO_DEPENDENCY dep;
2398         dep.moduleFrom = moduleFrom;
2399         dep.moduleTo   = moduleTo;
2400     }
2401 }
2402
2403
2404 InfoAccessType
2405     ZapInfo::constructStringLiteral(CORINFO_MODULE_HANDLE tokenScope,
2406                                          unsigned metaTok, void **ppValue)
2407 {
2408     if (m_pEECompileInfo->IsEmptyString(metaTok, tokenScope))
2409     {
2410         return emptyStringLiteral(ppValue);
2411     }
2412
2413     ZapImport * pImport = m_pImage->GetImportTable()->GetStringHandleImport(tokenScope, metaTok);
2414     AppendConditionalImport(pImport);
2415
2416     *ppValue = pImport;
2417
2418     return IAT_PPVALUE;
2419 }
2420
2421 InfoAccessType ZapInfo::emptyStringLiteral(void **ppValue)
2422 {
2423 #ifdef FEATURE_READYTORUN_COMPILER
2424     if (IsReadyToRunCompilation())
2425     {
2426         ZapImport * pImport = m_pImage->GetImportTable()->GetStringHandleImport(m_pImage->m_hModule, mdtString);
2427         *ppValue = pImport;
2428         return IAT_PPVALUE;
2429     }
2430 #endif
2431
2432     *ppValue = m_pImage->GetInnerPtr(m_pImage->m_pEEInfoTable,
2433         offsetof(CORCOMPILE_EE_INFO_TABLE, emptyString));
2434
2435     return IAT_PPVALUE;
2436 }
2437
2438 void ZapInfo::recordCallSite(ULONG instrOffset, CORINFO_SIG_INFO *callSig, CORINFO_METHOD_HANDLE methodHandle)
2439 {
2440     return;
2441 }
2442
2443 void ZapInfo::recordRelocation(void *location, void *target,
2444                                WORD fRelocType, WORD slotNum, INT32 addlDelta)
2445 {
2446     // Factor slotNum into the location address
2447     switch (fRelocType)
2448     {
2449     case IMAGE_REL_BASED_ABSOLUTE:
2450     case IMAGE_REL_BASED_PTR:
2451 #if defined(_TARGET_X86_) || defined(_TARGET_AMD64_)
2452     case IMAGE_REL_BASED_REL32:
2453 #endif // _TARGET_X86_ || _TARGET_AMD64_
2454         location = (PBYTE)location + slotNum;
2455         break;
2456
2457 #if defined(_TARGET_ARM_)
2458     case IMAGE_REL_BASED_THUMB_MOV32:
2459     case IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL:
2460     case IMAGE_REL_BASED_THUMB_BRANCH24:
2461
2462 # ifdef _DEBUG
2463     {
2464         CORJIT_FLAGS jitFlags = m_zapper->m_pOpt->m_compilerFlags;
2465
2466         if (jitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_RELATIVE_CODE_RELOCS))
2467         {
2468             _ASSERTE(fRelocType == IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL
2469                      || fRelocType == IMAGE_REL_BASED_THUMB_BRANCH24);
2470         }
2471         else
2472         {
2473             _ASSERTE(fRelocType == IMAGE_REL_BASED_THUMB_MOV32
2474                      || fRelocType == IMAGE_REL_BASED_THUMB_BRANCH24);
2475         }
2476     }
2477 # endif // _DEBUG
2478         break;
2479 #endif
2480
2481 #if defined(_TARGET_ARM64_)
2482     case IMAGE_REL_ARM64_BRANCH26:
2483     case IMAGE_REL_ARM64_PAGEBASE_REL21:
2484     case IMAGE_REL_ARM64_PAGEOFFSET_12A:
2485         break;
2486 #endif
2487
2488     default:
2489         _ASSERTE(!"Unknown reloc type");
2490         break;
2491     }
2492
2493     ZapBlobWithRelocs * knownNodes[] =
2494     {
2495         m_pCode,
2496         m_pColdCode,
2497         m_pROData,
2498         m_pProfileData
2499     };
2500
2501     //
2502     // The location of the relocation reported by the JIT has to fall into one of the code or data blobs
2503     //
2504
2505     CodeRelocation r;
2506
2507     ZapBlobWithRelocs * pSrcNode = NULL;
2508     for (size_t i = 0; i < _countof(knownNodes); i++)
2509     {
2510         ZapBlobWithRelocs * pNode = knownNodes[i];
2511         if (pNode == NULL)
2512             continue;
2513
2514         if (pNode->GetData() <= location && location < pNode->GetData() + pNode->GetSize())
2515         {
2516             pSrcNode = pNode;
2517             break;
2518         }
2519     }
2520     PREFIX_ASSUME(pSrcNode != NULL);
2521     r.m_pNode = pSrcNode;
2522     r.m_offset = (DWORD)((PBYTE)location - (PBYTE)pSrcNode->GetData());
2523
2524     //
2525     // The target of the relocation reported by the JIT can be one of:
2526     //  - Inner pointer into into one of the code or data blobs. We can detect this case by searching
2527     //    through the blobs.
2528     //  - Hardbound target. We can detect this case by searching through all hardbound assemblies.
2529     //  - Otherwise, it has to be ZapNode *.
2530     //
2531
2532     ZapNode * pTargetNode = NULL;
2533     INT32 targetOffset = 0;
2534     for (size_t i = 0; i < _countof(knownNodes); i++)
2535     {
2536         ZapBlobWithRelocs * pNode = knownNodes[i];
2537         if (pNode == NULL)
2538             continue;
2539
2540         if (pNode->GetData() <= target && target < pNode->GetData() + pNode->GetSize())
2541         {
2542             pTargetNode = pNode;
2543             targetOffset = (INT32)((PBYTE)target - (PBYTE)pNode->GetData());
2544             break;
2545         }
2546     }
2547
2548     if (pTargetNode != NULL)
2549     {
2550         r.m_pTargetNode = pTargetNode;
2551     }
2552     else
2553     {
2554         // Must be ZapNode otherwise
2555         pTargetNode = (ZapNode *)target;
2556         _ASSERTE(pTargetNode->GetType() != ZapNodeType_Unknown);
2557         r.m_pTargetNode = pTargetNode;
2558     }
2559
2560     r.m_type = (ZapRelocationType)fRelocType;
2561
2562     switch (fRelocType)
2563     {
2564     case IMAGE_REL_BASED_ABSOLUTE:
2565         *(UNALIGNED DWORD *)location = (DWORD)targetOffset;
2566         break;
2567
2568     case IMAGE_REL_BASED_PTR:
2569         *(UNALIGNED TADDR *)location = (TADDR)targetOffset;
2570         break;
2571
2572 #if defined(_TARGET_X86_) || defined(_TARGET_AMD64_)
2573     case IMAGE_REL_BASED_REL32:
2574         *(UNALIGNED INT32 *)location = targetOffset + addlDelta;
2575         break;
2576 #endif // _TARGET_X86_ || _TARGET_AMD64_
2577
2578 #if defined(_TARGET_ARM_)
2579     case IMAGE_REL_BASED_THUMB_MOV32:
2580     case IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL:
2581         PutThumb2Mov32((UINT16 *)location, targetOffset);
2582         break;
2583
2584     case IMAGE_REL_BASED_THUMB_BRANCH24:
2585         if (!FitsInThumb2BlRel24(targetOffset))
2586             ThrowHR(COR_E_OVERFLOW);
2587         PutThumb2BlRel24((UINT16 *)location, targetOffset);
2588         break;
2589 #endif
2590
2591 #if defined(_TARGET_ARM64_)
2592     case IMAGE_REL_ARM64_BRANCH26:
2593         if (!FitsInRel28(targetOffset))
2594             ThrowHR(COR_E_OVERFLOW);
2595         PutArm64Rel28((UINT32 *)location, targetOffset);
2596         break;
2597     case IMAGE_REL_ARM64_PAGEBASE_REL21:
2598         if (!FitsInRel21(targetOffset))
2599             ThrowHR(COR_E_OVERFLOW);
2600         PutArm64Rel21((UINT32 *)location, targetOffset);
2601         break;
2602
2603     case IMAGE_REL_ARM64_PAGEOFFSET_12A:
2604         if (!FitsInRel12(targetOffset))
2605             ThrowHR(COR_E_OVERFLOW);
2606         PutArm64Rel12((UINT32 *)location, targetOffset);
2607         break;
2608 #endif
2609
2610     default:
2611         _ASSERTE(!"Unknown reloc type");
2612         break;
2613     }
2614
2615     if (m_CodeRelocations.IsEmpty())
2616     {
2617         SIZE_T totalCodeSize = m_pCode->GetSize() + ((m_pColdCode != NULL) ? m_pColdCode->GetSize() : 0);
2618
2619         // Prealocate relocations (assume that every other pointer may need relocation)
2620         COUNT_T nEstimatedRelocations = (COUNT_T)(totalCodeSize / (2 * sizeof(TADDR)));
2621         if (nEstimatedRelocations > 1)
2622             m_CodeRelocations.Preallocate(nEstimatedRelocations);
2623     }
2624
2625     m_CodeRelocations.Append(r);
2626 }
2627
2628 WORD ZapInfo::getRelocTypeHint(void * target)
2629 {
2630 #ifdef _TARGET_AMD64_
2631     // There should be no external pointers
2632     return IMAGE_REL_BASED_REL32;
2633 #elif defined(_TARGET_ARM_)
2634     // Use full 32-bit branch targets when retrying compilation on ARM
2635     if (m_zapper->m_pOpt->m_fNGenLastRetry)
2636         return (WORD)-1;
2637     return IMAGE_REL_BASED_THUMB_BRANCH24;
2638 #elif defined(_TARGET_ARM64_)
2639     return IMAGE_REL_ARM64_BRANCH26;
2640 #else
2641     // No hints
2642     return (WORD)-1;
2643 #endif
2644 }
2645
2646 void ZapInfo::getModuleNativeEntryPointRange(void** pStart, void** pEnd)
2647 {
2648     ULONG rvaStart, rvaEnd;
2649
2650     // Initialize outparams to default range of (0,0).
2651     *pStart = 0;
2652     *pEnd = 0;
2653 }
2654
2655 DWORD ZapInfo::getExpectedTargetArchitecture()
2656 {
2657     return IMAGE_FILE_MACHINE_NATIVE;
2658 }
2659
2660 CORINFO_METHOD_HANDLE ZapInfo::GetDelegateCtor(CORINFO_METHOD_HANDLE   methHnd,
2661                                                CORINFO_CLASS_HANDLE    clsHnd,
2662                                                CORINFO_METHOD_HANDLE   targetMethodHnd,
2663                                                DelegateCtorArgs *      pCtorData)
2664 {
2665     // For ReadyToRun, this optimization is done via ZapInfo::getReadyToRunDelegateCtorHelper
2666     if (IsReadyToRunCompilation())
2667         return methHnd;
2668
2669     // forward the call to the standard GetDelegateCtor
2670     CORINFO_METHOD_HANDLE delegateCtor = m_pEEJitInfo->GetDelegateCtor(methHnd, clsHnd, targetMethodHnd, pCtorData);
2671     if (delegateCtor != methHnd)
2672     {
2673         if (pCtorData->pArg4)
2674         {
2675             // cannot optimize any secure delegate, give up
2676             delegateCtor = methHnd;
2677         }
2678         else if (pCtorData->pArg3)
2679         {
2680             pCtorData->pArg3 = m_pImage->GetWrappers()->GetStub(pCtorData->pArg3);
2681         }
2682     }
2683     return delegateCtor;
2684 }
2685
2686 void ZapInfo::MethodCompileComplete(
2687             CORINFO_METHOD_HANDLE methHnd)
2688 {
2689     m_pEEJitInfo->MethodCompileComplete(methHnd);
2690 }
2691
2692
2693 //
2694 // ICorStaticInfo
2695 //
2696
2697 void ZapInfo::getEEInfo(CORINFO_EE_INFO *pEEInfoOut)
2698 {
2699     m_pEEJitInfo->getEEInfo(pEEInfoOut);
2700 }
2701
2702 LPCWSTR ZapInfo::getJitTimeLogFilename()
2703 {
2704     return m_pEEJitInfo->getJitTimeLogFilename();
2705 }
2706
2707 //
2708 // ICorArgInfo
2709 //
2710
2711 CORINFO_ARG_LIST_HANDLE ZapInfo::getArgNext(CORINFO_ARG_LIST_HANDLE args)
2712 {
2713     return m_pEEJitInfo->getArgNext(args);
2714 }
2715
2716 CorInfoTypeWithMod ZapInfo::getArgType(CORINFO_SIG_INFO* sig,
2717                                                CORINFO_ARG_LIST_HANDLE args,
2718                                                 CORINFO_CLASS_HANDLE *vcTypeRet)
2719 {
2720     return m_pEEJitInfo->getArgType(sig, args, vcTypeRet);
2721 }
2722
2723 CORINFO_CLASS_HANDLE ZapInfo::getArgClass(CORINFO_SIG_INFO* sig,
2724                                            CORINFO_ARG_LIST_HANDLE args)
2725 {
2726     return m_pEEJitInfo->getArgClass(sig, args);
2727 }
2728
2729 CorInfoType ZapInfo::getHFAType(CORINFO_CLASS_HANDLE hClass)
2730 {
2731     return m_pEEJitInfo->getHFAType(hClass);
2732 }
2733
2734 //
2735 // ICorDebugInfo
2736 //
2737
2738 void ZapInfo::getBoundaries(CORINFO_METHOD_HANDLE ftn, unsigned int *cILOffsets,
2739                              DWORD **pILOffsets, ICorDebugInfo::BoundaryTypes *implicitBoundaries)
2740 {
2741     m_pEEJitInfo->getBoundaries(ftn, cILOffsets, pILOffsets,
2742                                               implicitBoundaries);
2743 }
2744
2745 void ZapInfo::setBoundaries(CORINFO_METHOD_HANDLE ftn, ULONG32 cMap,
2746                                            ICorDebugInfo::OffsetMapping *pMap)
2747 {
2748     _ASSERTE(ftn == m_currentMethodHandle);
2749
2750     if (cMap == 0)
2751         return;
2752
2753     m_pOffsetMapping = pMap;
2754     m_iOffsetMapping = cMap;
2755     return;
2756 }
2757
2758 void ZapInfo::getVars(CORINFO_METHOD_HANDLE ftn,
2759                                     ULONG32 *cVars,
2760                                     ICorDebugInfo::ILVarInfo **vars,
2761                                     bool *extendOthers)
2762 {
2763     m_pEEJitInfo->getVars(ftn, cVars, vars, extendOthers);
2764 }
2765
2766 void ZapInfo::setVars(CORINFO_METHOD_HANDLE ftn,
2767                                     ULONG32 cVars,
2768                                     ICorDebugInfo::NativeVarInfo * vars)
2769 {
2770     _ASSERTE(ftn == m_currentMethodHandle);
2771
2772     if (cVars == 0)
2773         return;
2774
2775     m_pNativeVarInfo = vars;
2776     m_iNativeVarInfo = cVars;
2777
2778     return;
2779 }
2780
2781 void * ZapInfo::allocateArray(ULONG cBytes)
2782 {
2783     return new BYTE[cBytes];
2784 }
2785
2786 void ZapInfo::freeArray(void *array)
2787 {
2788     delete [] ((BYTE*) array);
2789 }
2790
2791 //
2792 // ICorFieldInfo
2793 //
2794
2795 const char* ZapInfo::getFieldName(CORINFO_FIELD_HANDLE ftn, const char **moduleName)
2796 {
2797     return m_pEEJitInfo->getFieldName(ftn, moduleName);
2798 }
2799
2800 CORINFO_CLASS_HANDLE ZapInfo::getFieldClass(CORINFO_FIELD_HANDLE field)
2801 {
2802     return m_pEEJitInfo->getFieldClass(field);
2803 }
2804
2805 CorInfoType ZapInfo::getFieldType(CORINFO_FIELD_HANDLE field,
2806                                   CORINFO_CLASS_HANDLE *structType,
2807                                   CORINFO_CLASS_HANDLE memberParent)
2808
2809 {
2810     return m_pEEJitInfo->getFieldType(field, structType, memberParent);
2811 }
2812
2813 unsigned ZapInfo::getFieldOffset(CORINFO_FIELD_HANDLE field)
2814 {
2815     return m_pEEJitInfo->getFieldOffset(field);
2816 }
2817
2818 bool ZapInfo::isWriteBarrierHelperRequired(
2819                         CORINFO_FIELD_HANDLE    field)
2820 {
2821     return m_pEEJitInfo->isWriteBarrierHelperRequired(field);
2822 }
2823
2824 void ZapInfo::getFieldInfo (CORINFO_RESOLVED_TOKEN * pResolvedToken,
2825                             CORINFO_METHOD_HANDLE  callerHandle,
2826                             CORINFO_ACCESS_FLAGS   flags,
2827                             CORINFO_FIELD_INFO    *pResult)
2828 {
2829     m_pEEJitInfo->getFieldInfo(pResolvedToken, callerHandle, flags, pResult);
2830
2831 #ifdef FEATURE_READYTORUN_COMPILER
2832     CORINFO_EE_INFO eeInfo;
2833     m_pEEJitInfo->getEEInfo(&eeInfo);
2834
2835     if (IsReadyToRunCompilation())
2836     {
2837         if (pResult->accessAllowed != CORINFO_ACCESS_ALLOWED)
2838         {
2839             m_zapper->Warning(W("ReadyToRun: Runtime field access checks not supported\n"));
2840             ThrowHR(E_NOTIMPL);
2841         }
2842
2843         DWORD fAtypicalCallsite = (flags & CORINFO_ACCESS_ATYPICAL_CALLSITE) ? CORINFO_HELP_READYTORUN_ATYPICAL_CALLSITE : 0;
2844
2845         switch (pResult->fieldAccessor)
2846         {
2847         case CORINFO_FIELD_INSTANCE:
2848             {
2849                 DWORD dwBaseOffset = (DWORD)-1;
2850                 CORCOMPILE_FIXUP_BLOB_KIND fixupKind = m_pImage->GetCompileInfo()->GetFieldBaseOffset(pResolvedToken->hClass, &dwBaseOffset);
2851
2852                 switch (fixupKind)
2853                 {
2854                 case ENCODE_FIELD_OFFSET:
2855                     {
2856                         ZapImport * pImport = m_pImage->GetImportTable()->GetFieldImport(ENCODE_FIELD_OFFSET, pResolvedToken->hField, pResolvedToken);
2857
2858                         if (pResult->offset > eeInfo.maxUncheckedOffsetForNullObject / 2)
2859                         {
2860                             m_zapper->Warning(W("ReadyToRun: Cross-module instance fields with large offsets not supported\n"));
2861                             ThrowHR(E_NOTIMPL);
2862                         }
2863                         pResult->offset = 0;
2864
2865                         pResult->fieldAccessor = CORINFO_FIELD_INSTANCE_WITH_BASE;
2866
2867                         pResult->fieldLookup.accessType = IAT_PVALUE;
2868                         pResult->fieldLookup.addr = pImport;
2869
2870                         AppendImport(pImport);
2871                     }
2872                     break;
2873
2874                 case ENCODE_CHECK_FIELD_OFFSET:
2875                     {
2876                         ZapImport * pImport = m_pImage->GetImportTable()->GetCheckFieldOffsetImport(pResolvedToken->hField, pResolvedToken, pResult->offset);
2877                         AppendImport(pImport);
2878                     }
2879                     break;
2880
2881                 case ENCODE_FIELD_BASE_OFFSET:
2882                     {
2883                         ZapImport * pImport = m_pImage->GetImportTable()->GetClassImport(ENCODE_FIELD_BASE_OFFSET, pResolvedToken);
2884
2885                         if (pResult->offset > eeInfo.maxUncheckedOffsetForNullObject / 2)
2886                         {
2887                             m_zapper->Warning(W("ReadyToRun: Large objects crossing module boundaries not supported\n"));
2888                             ThrowHR(E_NOTIMPL);
2889                         }
2890                         _ASSERTE(pResult->offset >= dwBaseOffset);
2891                         pResult->offset -= dwBaseOffset;
2892
2893                         pResult->fieldAccessor = CORINFO_FIELD_INSTANCE_WITH_BASE;
2894
2895                         pResult->fieldLookup.accessType = IAT_PVALUE;
2896                         pResult->fieldLookup.addr = pImport;
2897
2898                         AppendImport(pImport);
2899                     }
2900                     break;
2901
2902                 case ENCODE_NONE:
2903                     break;
2904
2905                 default:
2906                     UNREACHABLE_MSG("Unexpected field base fixup");
2907                 }
2908             }
2909             break;
2910
2911         case CORINFO_FIELD_INSTANCE_HELPER:
2912         case CORINFO_FIELD_INSTANCE_ADDR_HELPER:
2913             m_zapper->Warning(W("ReadyToRun: Special instance fields not supported\n"));
2914             ThrowHR(E_NOTIMPL);
2915             break;
2916
2917         case CORINFO_FIELD_STATIC_SHARED_STATIC_HELPER:
2918             {
2919                 if (m_pImage->GetCompileInfo()->IsInCurrentVersionBubble(m_pEEJitInfo->getClassModule(pResolvedToken->hClass)))
2920                 {
2921                     CORCOMPILE_FIXUP_BLOB_KIND kind;
2922
2923                     switch (pResult->helper)
2924                     {
2925                     case CORINFO_HELP_GETSHARED_GCSTATIC_BASE:
2926                     case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR:
2927                     case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS:
2928                         kind = ENCODE_STATIC_BASE_GC_HELPER;
2929                         break;
2930                     case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE:
2931                     case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR:
2932                     case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_DYNAMICCLASS:
2933                         kind = ENCODE_STATIC_BASE_NONGC_HELPER;
2934                         break;
2935                     case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE:
2936                     case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR:
2937                     case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS:
2938                         kind = ENCODE_THREAD_STATIC_BASE_GC_HELPER;
2939                         break;
2940                     case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE:
2941                     case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR:
2942                     case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_DYNAMICCLASS:
2943                         kind = ENCODE_THREAD_STATIC_BASE_NONGC_HELPER;
2944                         break;
2945                     default:
2946                         UNREACHABLE_MSG("Unexpected static helper");
2947                     }
2948
2949                     ZapImport * pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(
2950                         (CORCOMPILE_FIXUP_BLOB_KIND)(kind | fAtypicalCallsite), pResolvedToken->hClass);
2951
2952                     pResult->fieldLookup.accessType = IAT_PVALUE;
2953                     pResult->fieldLookup.addr = pImport;
2954
2955                     pResult->helper = CORINFO_HELP_READYTORUN_STATIC_BASE;
2956                 }
2957                 else
2958                 {
2959                     ZapImport * pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(
2960                         (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_FIELD_ADDRESS | fAtypicalCallsite), pResolvedToken->hField, pResolvedToken);
2961
2962                     pResult->fieldLookup.accessType = IAT_PVALUE;
2963                     pResult->fieldLookup.addr = pImport;
2964
2965                     pResult->helper = CORINFO_HELP_READYTORUN_STATIC_BASE;
2966
2967                     pResult->offset = 0;
2968                     pResult->fieldFlags &= ~CORINFO_FLG_FIELD_STATIC_IN_HEAP; // The dynamic helper takes care of the unboxing
2969                 }
2970             }
2971             break;
2972
2973         case CORINFO_FIELD_STATIC_GENERICS_STATIC_HELPER:
2974                 {
2975                         // Nothing to do... The generic handle lookup gets embedded in to the codegen
2976                         // during the jitting of the field lookup.
2977                         // (Note: The generic lookup in R2R is performed by a call to a helper at runtime, not by
2978                         // codegen emitted at crossgen time)
2979                         // TODO: replace the call to the generic lookup helper and the call to the static helper function
2980                         // with a single call to a R2R cell that performs:
2981                         //      1) Generic handle lookup
2982                         //      2) Computes the statics base address
2983                         //      3) Generates a stub for subsequent lookups that includes dictionary access
2984                         // (For perf reasons)
2985                 }
2986             break;
2987
2988         case CORINFO_FIELD_STATIC_ADDRESS:           // field at given address
2989         case CORINFO_FIELD_STATIC_RVA_ADDRESS:       // RVA field at given address
2990         case CORINFO_FIELD_STATIC_ADDR_HELPER:       // static field accessed using address-of helper (argument is FieldDesc *)
2991         case CORINFO_FIELD_STATIC_TLS:
2992             m_zapper->Warning(W("ReadyToRun: Rare kinds of static fields not supported\n"));
2993             ThrowHR(E_NOTIMPL);
2994             break;
2995
2996         case CORINFO_FIELD_INTRINSIC_ZERO:
2997         case CORINFO_FIELD_INTRINSIC_EMPTY_STRING:
2998         case CORINFO_FIELD_INTRINSIC_ISLITTLEENDIAN:
2999             break;
3000
3001         default:
3002             UNREACHABLE_MSG("Unexpected field acccess type");
3003         }
3004     }
3005 #endif // FEATURE_READYTORUN_COMPILER
3006 }
3007
3008 bool ZapInfo::isFieldStatic(CORINFO_FIELD_HANDLE fldHnd)
3009 {
3010     return m_pEEJitInfo->isFieldStatic(fldHnd);
3011 }
3012
3013 //
3014 // ICorClassInfo
3015 //
3016
3017 CorInfoType ZapInfo::asCorInfoType(CORINFO_CLASS_HANDLE cls)
3018 {
3019     return m_pEEJitInfo->asCorInfoType(cls);
3020 }
3021
3022 const char* ZapInfo::getClassName(CORINFO_CLASS_HANDLE cls)
3023 {
3024     return m_pEEJitInfo->getClassName(cls);
3025 }
3026
3027 const char* ZapInfo::getHelperName(CorInfoHelpFunc func)
3028 {
3029     return m_pEEJitInfo->getHelperName(func);
3030 }
3031
3032 int ZapInfo::appendClassName(__deref_inout_ecount(*pnBufLen) WCHAR** ppBuf, int* pnBufLen,
3033                              CORINFO_CLASS_HANDLE    cls,
3034                              BOOL fNamespace,
3035                              BOOL fFullInst,
3036                              BOOL fAssembly)
3037 {
3038     return m_pEEJitInfo->appendClassName(ppBuf,pnBufLen,cls,fNamespace,fFullInst,fAssembly);
3039 }
3040
3041 BOOL ZapInfo::isValueClass(CORINFO_CLASS_HANDLE cls)
3042 {
3043     return m_pEEJitInfo->isValueClass(cls);
3044 }
3045
3046 BOOL ZapInfo::canInlineTypeCheckWithObjectVTable (CORINFO_CLASS_HANDLE cls)
3047 {
3048     return m_pEEJitInfo->canInlineTypeCheckWithObjectVTable(cls);
3049 }
3050
3051 DWORD ZapInfo::getClassAttribs(CORINFO_CLASS_HANDLE cls)
3052 {
3053     return m_pEEJitInfo->getClassAttribs(cls);
3054 }
3055
3056 BOOL ZapInfo::isStructRequiringStackAllocRetBuf(CORINFO_CLASS_HANDLE cls)
3057 {
3058     return m_pEEJitInfo->isStructRequiringStackAllocRetBuf(cls);
3059 }
3060
3061 CorInfoInitClassResult ZapInfo::initClass(
3062             CORINFO_FIELD_HANDLE    field,
3063             CORINFO_METHOD_HANDLE   method,
3064             CORINFO_CONTEXT_HANDLE  context,
3065             BOOL                    speculative)
3066 {
3067     return m_pEEJitInfo->initClass(field, method, context, speculative);
3068 }
3069
3070 void ZapInfo::classMustBeLoadedBeforeCodeIsRun(CORINFO_CLASS_HANDLE cls)
3071 {
3072     // This adds an entry to the table of fixups.  The table gets iterated later
3073     // to add entries to the delayed fixup list for the code being generated.
3074     m_ClassLoadTable.Load(cls, FALSE);
3075 }
3076
3077 CORINFO_METHOD_HANDLE ZapInfo::mapMethodDeclToMethodImpl(CORINFO_METHOD_HANDLE methHnd)
3078 {
3079     return (CORINFO_METHOD_HANDLE)m_pEEJitInfo->mapMethodDeclToMethodImpl(methHnd);
3080 }
3081
3082 void ZapInfo::methodMustBeLoadedBeforeCodeIsRun(CORINFO_METHOD_HANDLE meth)
3083 {
3084     // This adds an entry to the table of fixups.  The table gets iterated later
3085     // to add entries to the delayed fixup list for the code being generated.
3086     m_MethodLoadTable.Load(meth, FALSE);
3087 }
3088
3089 CORINFO_CLASS_HANDLE ZapInfo::getBuiltinClass(CorInfoClassId classId)
3090 {
3091     return m_pEEJitInfo->getBuiltinClass(classId);
3092 }
3093
3094 CorInfoType ZapInfo::getTypeForPrimitiveValueClass(CORINFO_CLASS_HANDLE cls)
3095 {
3096     return m_pEEJitInfo->getTypeForPrimitiveValueClass(cls);
3097 }
3098
3099 BOOL ZapInfo::canCast(CORINFO_CLASS_HANDLE child,
3100                                 CORINFO_CLASS_HANDLE parent)
3101 {
3102     return m_pEEJitInfo->canCast(child, parent);
3103 }
3104
3105 BOOL ZapInfo::areTypesEquivalent(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2)
3106 {
3107     return m_pEEJitInfo->areTypesEquivalent(cls1, cls2);
3108 }
3109
3110 CORINFO_CLASS_HANDLE ZapInfo::mergeClasses(
3111                                 CORINFO_CLASS_HANDLE cls1,
3112                                 CORINFO_CLASS_HANDLE cls2)
3113 {
3114     return m_pEEJitInfo->mergeClasses(cls1, cls2);
3115 }
3116
3117 BOOL ZapInfo::shouldEnforceCallvirtRestriction(
3118         CORINFO_MODULE_HANDLE scopeHnd)
3119 {
3120     return m_zapper->m_pEEJitInfo->shouldEnforceCallvirtRestriction(scopeHnd);
3121 }
3122
3123 CORINFO_CLASS_HANDLE ZapInfo::getParentType (
3124                                 CORINFO_CLASS_HANDLE       cls)
3125 {
3126     return m_pEEJitInfo->getParentType(cls);
3127 }
3128
3129 CorInfoType ZapInfo::getChildType (
3130             CORINFO_CLASS_HANDLE       clsHnd,
3131             CORINFO_CLASS_HANDLE       *clsRet)
3132 {
3133     return m_pEEJitInfo->getChildType(clsHnd, clsRet);
3134 }
3135
3136 BOOL ZapInfo::satisfiesClassConstraints(
3137             CORINFO_CLASS_HANDLE cls)
3138 {
3139     return m_pEEJitInfo->satisfiesClassConstraints(cls);
3140 }
3141
3142 BOOL ZapInfo::isSDArray(CORINFO_CLASS_HANDLE cls)
3143 {
3144     return m_pEEJitInfo->isSDArray(cls);
3145 }
3146
3147 unsigned ZapInfo::getArrayRank(CORINFO_CLASS_HANDLE cls)
3148 {
3149     return m_pEEJitInfo->getArrayRank(cls);
3150 }
3151
3152 void * ZapInfo::getArrayInitializationData(CORINFO_FIELD_HANDLE field, DWORD size)
3153 {
3154     if (m_pEEJitInfo->getClassModule(m_pEEJitInfo->getFieldClass(field)) != m_pImage->m_hModule)
3155         return NULL;
3156
3157     void * arrayData = m_pEEJitInfo->getArrayInitializationData(field, size);
3158     if (!arrayData)
3159         return NULL;
3160
3161 #ifdef FEATURE_READYTORUN_COMPILER
3162     if (IsReadyToRunCompilation())
3163         return m_pImage->m_pILMetaData->GetRVAField(arrayData);
3164 #endif
3165
3166     return (void *) m_pImage->GetWrappers()->GetGenericHandle(CORINFO_GENERIC_HANDLE(arrayData));
3167 }
3168
3169 CorInfoIsAccessAllowedResult ZapInfo::canAccessClass( CORINFO_RESOLVED_TOKEN * pResolvedToken,
3170                                                       CORINFO_METHOD_HANDLE   callerHandle,
3171                                                       CORINFO_HELPER_DESC    *throwHelper)
3172 {
3173     CorInfoIsAccessAllowedResult ret = m_pEEJitInfo->canAccessClass(pResolvedToken, callerHandle, throwHelper);
3174
3175 #ifdef FEATURE_READYTORUN_COMPILER
3176     if (ret != CORINFO_ACCESS_ALLOWED)
3177     {
3178         m_zapper->Warning(W("ReadyToRun: Runtime access checks not supported\n"));
3179         ThrowHR(E_NOTIMPL);
3180     }
3181 #endif
3182
3183     return ret;
3184 }
3185
3186
3187 CORINFO_MODULE_HANDLE ZapInfo::getClassModule(CORINFO_CLASS_HANDLE cls)
3188 {
3189     return m_pEEJitInfo->getClassModule(cls);
3190 }
3191
3192 CORINFO_ASSEMBLY_HANDLE ZapInfo::getModuleAssembly(CORINFO_MODULE_HANDLE mod)
3193 {
3194     return m_pEEJitInfo->getModuleAssembly(mod);
3195 }
3196
3197 const char* ZapInfo::getAssemblyName(CORINFO_ASSEMBLY_HANDLE assem)
3198 {
3199     return m_pEEJitInfo->getAssemblyName(assem);
3200 }
3201
3202 void* ZapInfo::LongLifetimeMalloc(size_t sz)
3203 {
3204     return m_pEEJitInfo->LongLifetimeMalloc(sz);
3205 }
3206
3207 void ZapInfo::LongLifetimeFree(void* obj)
3208 {
3209     return m_pEEJitInfo->LongLifetimeFree(obj);
3210 }
3211
3212 size_t ZapInfo::getClassModuleIdForStatics(CORINFO_CLASS_HANDLE cls, CORINFO_MODULE_HANDLE *pModule, void **ppIndirection)
3213 {
3214     if (IsReadyToRunCompilation())
3215     {
3216         _ASSERTE(!"getClassModuleIdForStatics");
3217         ThrowHR(E_NOTIMPL);
3218     }
3219
3220     _ASSERTE(ppIndirection != NULL);
3221     _ASSERTE(pModule == NULL);
3222     CORINFO_MODULE_HANDLE module;
3223     size_t moduleId = m_pEEJitInfo->getClassModuleIdForStatics(cls, &module, ppIndirection);
3224     CORINFO_MODULE_HANDLE pzmModule = m_pImage->m_pPreloader->GetPreferredZapModuleForClassHandle(cls);
3225
3226     if (module == pzmModule)
3227     {
3228         // Use the module for the moduleid lookup if we have to do so. This causes us to have fewer fixups than
3229         // if the fixups were exclusively based on the moduleforstatics lookup
3230         cls = NULL;
3231
3232
3233         if (module == m_pImage->m_hModule)
3234         {
3235             // If the handle is the module we are currently ngening, we use
3236             // an indirection to the slot where the module pointer gets
3237             // stored when the module gets reloaded.
3238
3239             *ppIndirection = PVOID(m_pImage->GetWrappers()->GetModuleIDHandle(module));
3240             return NULL;
3241         }
3242
3243         // Fall through to regular import
3244     }
3245     else
3246     {
3247         // Use the class for the moduleid lookup. This causes us to generate a fixup for the ModuleForStatics explicitly.
3248         module = NULL;
3249     }
3250
3251     ZapImport * pImport = m_pImage->GetImportTable()->GetModuleDomainIdImport(module, cls);
3252     AppendConditionalImport(pImport);
3253
3254     *ppIndirection = pImport;
3255     return NULL;
3256 }
3257
3258 unsigned ZapInfo::getClassSize(CORINFO_CLASS_HANDLE cls)
3259 {
3260     DWORD size = m_pEEJitInfo->getClassSize(cls);
3261
3262 #ifdef FEATURE_READYTORUN_COMPILER
3263     if (IsReadyToRunCompilation())
3264     {
3265         if (m_pEECompileInfo->NeedsTypeLayoutCheck(cls))
3266         {
3267             ZapImport * pImport = m_pImage->GetImportTable()->GetCheckTypeLayoutImport(cls);
3268             AppendImport(pImport);
3269
3270             m_ClassLoadTable.Load(cls, TRUE);
3271         }
3272     }
3273 #endif
3274
3275     return size;
3276 }
3277
3278 unsigned ZapInfo::getClassAlignmentRequirement(CORINFO_CLASS_HANDLE cls, BOOL fDoubleAlignHint)
3279 {
3280     return m_pEEJitInfo->getClassAlignmentRequirement(cls, fDoubleAlignHint);
3281 }
3282
3283 CORINFO_FIELD_HANDLE ZapInfo::getFieldInClass(CORINFO_CLASS_HANDLE clsHnd, INT num)
3284 {
3285     return m_pEEJitInfo->getFieldInClass(clsHnd,num);
3286 }
3287
3288 mdMethodDef ZapInfo::getMethodDefFromMethod(CORINFO_METHOD_HANDLE hMethod)
3289 {
3290     return m_pEEJitInfo->getMethodDefFromMethod(hMethod);
3291 }
3292
3293 BOOL ZapInfo::checkMethodModifier(CORINFO_METHOD_HANDLE hMethod, LPCSTR modifier, BOOL fOptional)
3294 {
3295     return m_pEEJitInfo->checkMethodModifier(hMethod, modifier, fOptional);
3296 }
3297
3298 unsigned ZapInfo::getClassGClayout(CORINFO_CLASS_HANDLE cls, BYTE *gcPtrs)
3299 {
3300     return m_pEEJitInfo->getClassGClayout(cls, gcPtrs);
3301 }
3302
3303 // returns the enregister info for a struct based on type of fields, alignment, etc..
3304 bool ZapInfo::getSystemVAmd64PassStructInRegisterDescriptor(
3305     /*IN*/  CORINFO_CLASS_HANDLE _structHnd,
3306     /*OUT*/ SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr)
3307 {
3308     return m_pEEJitInfo->getSystemVAmd64PassStructInRegisterDescriptor(_structHnd, structPassInRegDescPtr);
3309 }
3310
3311 unsigned ZapInfo::getClassNumInstanceFields(CORINFO_CLASS_HANDLE cls)
3312 {
3313     return m_pEEJitInfo->getClassNumInstanceFields(cls);
3314 }
3315
3316
3317 CorInfoHelpFunc ZapInfo::getNewHelper(CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_METHOD_HANDLE callerHandle)
3318 {
3319         if (IsReadyToRunCompilation())
3320                 return CORINFO_HELP_NEWFAST;
3321
3322         classMustBeLoadedBeforeCodeIsRun(pResolvedToken->hClass);
3323         return m_pEEJitInfo->getNewHelper(pResolvedToken, callerHandle);
3324 }
3325
3326 CorInfoHelpFunc ZapInfo::getSharedCCtorHelper(CORINFO_CLASS_HANDLE clsHnd)
3327 {
3328         return m_pEEJitInfo->getSharedCCtorHelper(clsHnd);
3329 }
3330
3331 CorInfoHelpFunc ZapInfo::getSecurityPrologHelper(CORINFO_METHOD_HANDLE ftn)
3332 {
3333         return m_pEEJitInfo->getSecurityPrologHelper(ftn);
3334 }
3335
3336 CORINFO_CLASS_HANDLE  ZapInfo::getTypeForBox(CORINFO_CLASS_HANDLE  cls)
3337 {
3338         return m_pEEJitInfo->getTypeForBox(cls);
3339 }
3340
3341 CorInfoHelpFunc ZapInfo::getBoxHelper(CORINFO_CLASS_HANDLE cls)
3342 {
3343         return m_pEEJitInfo->getBoxHelper(cls);
3344 }
3345
3346 CorInfoHelpFunc ZapInfo::getUnBoxHelper(CORINFO_CLASS_HANDLE cls)
3347 {
3348         return m_pEEJitInfo->getUnBoxHelper(cls);
3349 }
3350
3351 CorInfoHelpFunc ZapInfo::getCastingHelper(CORINFO_RESOLVED_TOKEN * pResolvedToken, bool fThrowing)
3352 {
3353         if (IsReadyToRunCompilation())
3354                 return (fThrowing ? CORINFO_HELP_CHKCASTANY : CORINFO_HELP_ISINSTANCEOFANY);
3355
3356         return m_pEEJitInfo->getCastingHelper(pResolvedToken, fThrowing);
3357 }
3358
3359 CorInfoHelpFunc ZapInfo::getNewArrHelper(CORINFO_CLASS_HANDLE arrayCls)
3360 {
3361         if (IsReadyToRunCompilation())
3362                 return CORINFO_HELP_NEWARR_1_R2R_DIRECT;
3363
3364         return m_pEEJitInfo->getNewArrHelper(arrayCls);
3365 }
3366
3367 bool ZapInfo::getReadyToRunHelper(CORINFO_RESOLVED_TOKEN * pResolvedToken,
3368         CORINFO_LOOKUP_KIND * pGenericLookupKind,
3369         CorInfoHelpFunc id,
3370         CORINFO_CONST_LOOKUP * pLookup)
3371 {
3372 #ifdef FEATURE_READYTORUN_COMPILER
3373         _ASSERTE(IsReadyToRunCompilation());
3374
3375         ZapImport * pImport = NULL;
3376
3377         DWORD fAtypicalCallsite = (id & CORINFO_HELP_READYTORUN_ATYPICAL_CALLSITE);
3378         id = (CorInfoHelpFunc)(id & ~CORINFO_HELP_READYTORUN_ATYPICAL_CALLSITE);
3379
3380         switch (id)
3381         {
3382         case CORINFO_HELP_READYTORUN_NEW:
3383         // Call CEEInfo::getNewHelper to validate the request (e.g., check for abstract class).
3384         m_pEEJitInfo->getNewHelper(pResolvedToken, m_currentMethodHandle);
3385
3386                 if ((getClassAttribs(pResolvedToken->hClass) & CORINFO_FLG_SHAREDINST) != 0)
3387                         return false;   // Requires runtime lookup.
3388                 pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(
3389                         (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_NEW_HELPER | fAtypicalCallsite), pResolvedToken->hClass);
3390                 break;
3391
3392         case CORINFO_HELP_READYTORUN_NEWARR_1:
3393                 if ((getClassAttribs(pResolvedToken->hClass) & CORINFO_FLG_SHAREDINST) != 0)
3394                         return false;   // Requires runtime lookup.
3395                 pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(
3396                         (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_NEW_ARRAY_HELPER | fAtypicalCallsite), pResolvedToken->hClass);
3397                 break;
3398
3399         case CORINFO_HELP_READYTORUN_ISINSTANCEOF:
3400                 if ((getClassAttribs(pResolvedToken->hClass) & CORINFO_FLG_SHAREDINST) != 0)
3401                         return false;   // Requires runtime lookup.
3402                 pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(
3403                         (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_ISINSTANCEOF_HELPER | fAtypicalCallsite), pResolvedToken->hClass);
3404                 break;
3405
3406         case CORINFO_HELP_READYTORUN_CHKCAST:
3407                 if ((getClassAttribs(pResolvedToken->hClass) & CORINFO_FLG_SHAREDINST) != 0)
3408                         return false;   // Requires runtime lookup.
3409                 pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(
3410                         (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_CHKCAST_HELPER | fAtypicalCallsite), pResolvedToken->hClass);
3411                 break;
3412
3413         case CORINFO_HELP_READYTORUN_STATIC_BASE:
3414                 if ((getClassAttribs(pResolvedToken->hClass) & CORINFO_FLG_SHAREDINST) != 0)
3415                         return false;   // Requires runtime lookup.
3416                 if (m_pImage->GetCompileInfo()->IsInCurrentVersionBubble(m_pEEJitInfo->getClassModule(pResolvedToken->hClass)))
3417                 {
3418                         pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(
3419                                 (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_CCTOR_TRIGGER | fAtypicalCallsite), pResolvedToken->hClass);
3420                 }
3421                 else
3422                 {
3423                         // READYTORUN: FUTURE: Cross-module static cctor triggers
3424                         m_zapper->Warning(W("ReadyToRun: Cross-module static cctor triggers not supported\n"));
3425                         ThrowHR(E_NOTIMPL);
3426                 }
3427                 break;
3428
3429         case CORINFO_HELP_READYTORUN_GENERIC_HANDLE:
3430                 _ASSERTE(pGenericLookupKind != NULL && pGenericLookupKind->needsRuntimeLookup);
3431                 if (pGenericLookupKind->runtimeLookupKind == CORINFO_LOOKUP_METHODPARAM)
3432                 {
3433                         pImport = m_pImage->GetImportTable()->GetDictionaryLookupCell(
3434                                 (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_DICTIONARY_LOOKUP_METHOD | fAtypicalCallsite), pResolvedToken, pGenericLookupKind);
3435                 }
3436         else if (pGenericLookupKind->runtimeLookupKind == CORINFO_LOOKUP_THISOBJ)
3437         {
3438             pImport = m_pImage->GetImportTable()->GetDictionaryLookupCell(
3439                 (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_DICTIONARY_LOOKUP_THISOBJ | fAtypicalCallsite), pResolvedToken, pGenericLookupKind);
3440         }
3441                 else
3442                 {
3443                         _ASSERTE(pGenericLookupKind->runtimeLookupKind == CORINFO_LOOKUP_CLASSPARAM);
3444                         pImport = m_pImage->GetImportTable()->GetDictionaryLookupCell(
3445                                 (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_DICTIONARY_LOOKUP_TYPE | fAtypicalCallsite), pResolvedToken, pGenericLookupKind);
3446                 }
3447                 break;
3448
3449         default:
3450                 _ASSERTE(false);
3451                 ThrowHR(E_NOTIMPL);
3452         }
3453
3454         pLookup->accessType = IAT_PVALUE;
3455         pLookup->addr = pImport;
3456         return true;
3457 #else
3458         return false;
3459 #endif
3460 }
3461
3462 void ZapInfo::getReadyToRunDelegateCtorHelper(
3463         CORINFO_RESOLVED_TOKEN * pTargetMethod,
3464         CORINFO_CLASS_HANDLE     delegateType,
3465         CORINFO_LOOKUP *   pLookup
3466         )
3467 {
3468 #ifdef FEATURE_READYTORUN_COMPILER
3469     _ASSERTE(IsReadyToRunCompilation());
3470     pLookup->lookupKind.needsRuntimeLookup = false;
3471     pLookup->constLookup.accessType = IAT_PVALUE;
3472     pLookup->constLookup.addr = m_pImage->GetImportTable()->GetDynamicHelperCell(
3473             (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_DELEGATE_CTOR), pTargetMethod->hMethod, pTargetMethod, delegateType);
3474 #endif
3475 }
3476
3477
3478 //
3479 // ICorModuleInfo
3480 //
3481
3482 //-----------------------------------------------------------------------------
3483 void ZapInfo::resolveToken(CORINFO_RESOLVED_TOKEN * pResolvedToken)
3484 {
3485     m_pEEJitInfo->resolveToken(pResolvedToken);
3486 }
3487
3488 //-----------------------------------------------------------------------------
3489 bool ZapInfo::tryResolveToken(CORINFO_RESOLVED_TOKEN * pResolvedToken)
3490 {
3491     return m_pEEJitInfo->tryResolveToken(pResolvedToken);
3492 }
3493
3494 //-----------------------------------------------------------------------------
3495 void ZapInfo::findSig(CORINFO_MODULE_HANDLE tokenScope,
3496                       unsigned sigTOK,
3497                       CORINFO_CONTEXT_HANDLE tokenContext,
3498                       CORINFO_SIG_INFO *sig)
3499 {
3500     m_pEEJitInfo->findSig(tokenScope, sigTOK, tokenContext, sig);
3501 }
3502
3503 void ZapInfo::findCallSiteSig(CORINFO_MODULE_HANDLE tokenScope,
3504                                            unsigned methTOK,
3505                                            CORINFO_CONTEXT_HANDLE tokenContext, CORINFO_SIG_INFO *sig)
3506 {
3507     m_pEEJitInfo->findCallSiteSig(tokenScope, methTOK, tokenContext, sig);
3508 }
3509
3510 size_t ZapInfo::findNameOfToken(CORINFO_MODULE_HANDLE tokenScope,
3511                                        unsigned token,
3512                                        __out_ecount (FQNameCapacity) char * szFQName,
3513                                        size_t FQNameCapacity)
3514 {
3515     return m_pEEJitInfo->findNameOfToken(tokenScope, token, szFQName, FQNameCapacity);
3516 }
3517
3518 CorInfoCanSkipVerificationResult ZapInfo::canSkipVerification (
3519         CORINFO_MODULE_HANDLE tokenScope)
3520 {
3521     return m_pEEJitInfo->canSkipVerification(tokenScope);
3522 }
3523
3524 BOOL ZapInfo::isValidToken (
3525             CORINFO_MODULE_HANDLE       tokenScope,
3526             unsigned                    token)
3527 {
3528     return m_pEEJitInfo->isValidToken(tokenScope, token);
3529 }
3530
3531 BOOL ZapInfo::isValidStringRef (
3532             CORINFO_MODULE_HANDLE       tokenScope,
3533             unsigned                    token)
3534 {
3535     return m_pEEJitInfo->isValidStringRef(tokenScope, token);
3536 }
3537
3538
3539 //
3540 // ICorMethodInfo
3541 //
3542
3543 const char* ZapInfo::getMethodName(CORINFO_METHOD_HANDLE ftn, const char **moduleName)
3544 {
3545     return m_pEEJitInfo->getMethodName(ftn, moduleName);
3546 }
3547
3548 unsigned ZapInfo::getMethodHash(CORINFO_METHOD_HANDLE ftn)
3549 {
3550     return m_pEEJitInfo->getMethodHash(ftn);
3551 }
3552
3553 DWORD ZapInfo::getMethodAttribs(CORINFO_METHOD_HANDLE ftn)
3554 {
3555     return m_pEEJitInfo->getMethodAttribs(ftn);
3556 }
3557
3558 void ZapInfo::setMethodAttribs(CORINFO_METHOD_HANDLE ftn, CorInfoMethodRuntimeFlags attribs)
3559 {
3560     m_pEEJitInfo->setMethodAttribs(ftn, attribs);
3561 }
3562
3563 void ZapInfo::getMethodSig(CORINFO_METHOD_HANDLE ftn, CORINFO_SIG_INFO *sig,CORINFO_CLASS_HANDLE memberParent)
3564 {
3565     m_pEEJitInfo->getMethodSig(ftn, sig, memberParent);
3566 }
3567
3568 bool ZapInfo::getMethodInfo(CORINFO_METHOD_HANDLE ftn,CORINFO_METHOD_INFO* info)
3569 {
3570     bool result = m_pImage->m_pPreloader->GetMethodInfo(m_currentMethodToken, ftn, info);
3571     info->regionKind = m_pImage->GetCurrentRegionKind();
3572     return result;
3573 }
3574
3575 CorInfoInline ZapInfo::canInline(CORINFO_METHOD_HANDLE caller,
3576                                            CORINFO_METHOD_HANDLE callee,
3577                                            DWORD* pRestrictions)
3578 {
3579     return m_pEEJitInfo->canInline(caller, callee, pRestrictions);
3580
3581 }
3582
3583 void ZapInfo::reportInliningDecision (CORINFO_METHOD_HANDLE inlinerHnd,
3584                                                 CORINFO_METHOD_HANDLE inlineeHnd,
3585                                                 CorInfoInline inlineResult,
3586                                                 const char * reason)
3587 {
3588     if (!dontInline(inlineResult) && inlineeHnd != NULL)
3589     {
3590         // We deliberately report  m_currentMethodHandle (not inlinerHnd) as inliner, because
3591         // if m_currentMethodHandle != inlinerHnd, it simply means that inlinerHnd is intermediate link 
3592         // in inlining into m_currentMethodHandle, and we have no interest to track those intermediate links now.
3593         m_pImage->m_pPreloader->ReportInlining(m_currentMethodHandle, inlineeHnd);
3594     }
3595     return m_pEEJitInfo->reportInliningDecision(inlinerHnd, inlineeHnd, inlineResult, reason);
3596 }
3597
3598
3599 CorInfoInstantiationVerification ZapInfo::isInstantiationOfVerifiedGeneric(
3600         CORINFO_METHOD_HANDLE method)
3601 {
3602     return m_pEEJitInfo->isInstantiationOfVerifiedGeneric(method);
3603 }
3604
3605
3606 void ZapInfo::initConstraintsForVerification(CORINFO_METHOD_HANDLE method,
3607                                                             BOOL *pfHasCircularClassConstraints,
3608                                                             BOOL *pfHasCircularMethodConstraints)
3609 {
3610      m_pEEJitInfo->
3611               initConstraintsForVerification(method,pfHasCircularClassConstraints,pfHasCircularMethodConstraints);
3612 }
3613
3614 bool ZapInfo::canTailCall(CORINFO_METHOD_HANDLE caller,
3615                                          CORINFO_METHOD_HANDLE declaredCallee,
3616                                          CORINFO_METHOD_HANDLE exactCallee,
3617                                          bool fIsTailPrefix)
3618 {
3619 #ifdef FEATURE_READYTORUN_COMPILER
3620     // READYTORUN: FUTURE: Delay load fixups for tailcalls
3621     if (IsReadyToRunCompilation())
3622     {
3623         if (fIsTailPrefix)
3624         {
3625             m_zapper->Warning(W("ReadyToRun: Explicit tailcalls not supported\n"));
3626             ThrowHR(E_NOTIMPL);
3627         }
3628
3629         return false;
3630     }
3631 #endif
3632
3633     return m_pEEJitInfo->canTailCall(caller, declaredCallee, exactCallee, fIsTailPrefix);
3634 }
3635
3636 void ZapInfo::reportTailCallDecision(CORINFO_METHOD_HANDLE callerHnd,
3637                                                CORINFO_METHOD_HANDLE calleeHnd,
3638                                                bool fIsTailPrefix,
3639                                                CorInfoTailCall tailCallResult,
3640                                                const char * reason)
3641 {
3642     return m_pEEJitInfo->reportTailCallDecision(callerHnd, calleeHnd, fIsTailPrefix, tailCallResult, reason);
3643 }
3644
3645
3646 CorInfoCanSkipVerificationResult ZapInfo::canSkipMethodVerification (
3647         CORINFO_METHOD_HANDLE ftnHandle)
3648 {
3649     // ILStubs are generated internally by the CLR. There is no need to
3650     // verify it, or any of its callees.
3651     if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB))
3652         return CORINFO_VERIFICATION_CAN_SKIP;
3653
3654     CorInfoCanSkipVerificationResult canSkipVer =
3655         m_pEEJitInfo->canSkipMethodVerification(ftnHandle);
3656
3657     if (canSkipVer == CORINFO_VERIFICATION_RUNTIME_CHECK)
3658     {
3659         // Transparent code could be partial trust, but we don't know at NGEN time.
3660         // Since the JIT is not hardened against unverifiable/illegal code, tell it
3661         // to just not jit the method if it hits unverifiable code, rathern than
3662         // injecting a runtime callout and continuing trying to JIT the method.
3663         canSkipVer = CORINFO_VERIFICATION_DONT_JIT;
3664     }
3665
3666     return canSkipVer;
3667 }
3668
3669 void ZapInfo::getEHinfo(CORINFO_METHOD_HANDLE ftn,
3670                          unsigned EHnumber, CORINFO_EH_CLAUSE* clause)
3671 {
3672     m_pEEJitInfo->getEHinfo(ftn, EHnumber, clause);
3673 }
3674
3675 CORINFO_CLASS_HANDLE ZapInfo::getMethodClass(CORINFO_METHOD_HANDLE method)
3676 {
3677     return m_pEEJitInfo->getMethodClass(method);
3678 }
3679
3680 CORINFO_MODULE_HANDLE ZapInfo::getMethodModule(CORINFO_METHOD_HANDLE method)
3681 {
3682     return m_pEEJitInfo->getMethodModule(method);
3683 }
3684
3685 void ZapInfo::getMethodVTableOffset(CORINFO_METHOD_HANDLE method,
3686                                     unsigned * pOffsetOfIndirection,
3687                                     unsigned * pOffsetAfterIndirection,
3688                                     bool * isRelative)
3689 {
3690     m_pEEJitInfo->getMethodVTableOffset(method, pOffsetOfIndirection, pOffsetAfterIndirection, isRelative);
3691 }
3692
3693 CORINFO_METHOD_HANDLE ZapInfo::resolveVirtualMethod(
3694         CORINFO_METHOD_HANDLE virtualMethod,
3695         CORINFO_CLASS_HANDLE implementingClass,
3696         CORINFO_CONTEXT_HANDLE ownerType
3697         )
3698 {
3699     return m_pEEJitInfo->resolveVirtualMethod(virtualMethod, implementingClass, ownerType);
3700 }
3701
3702 void ZapInfo::expandRawHandleIntrinsic(
3703     CORINFO_RESOLVED_TOKEN *        pResolvedToken,
3704     CORINFO_GENERICHANDLE_RESULT *  pResult)
3705 {
3706     m_pEEJitInfo->expandRawHandleIntrinsic(pResolvedToken, pResult);
3707 }
3708
3709 CorInfoIntrinsics ZapInfo::getIntrinsicID(CORINFO_METHOD_HANDLE method,
3710                                           bool * pMustExpand)
3711 {
3712     return m_pEEJitInfo->getIntrinsicID(method, pMustExpand);
3713 }
3714
3715 bool ZapInfo::isInSIMDModule(CORINFO_CLASS_HANDLE classHnd)
3716 {
3717     return m_pEEJitInfo->isInSIMDModule(classHnd);
3718 }
3719
3720 CorInfoUnmanagedCallConv ZapInfo::getUnmanagedCallConv(CORINFO_METHOD_HANDLE method)
3721 {
3722     return m_pEEJitInfo->getUnmanagedCallConv(method);
3723 }
3724
3725 BOOL ZapInfo::pInvokeMarshalingRequired(CORINFO_METHOD_HANDLE method,
3726                                                        CORINFO_SIG_INFO* sig)
3727 {
3728     // READYTORUN: FUTURE: P/Invoke
3729     if (IsReadyToRunCompilation())
3730         return TRUE;
3731
3732     return m_pEEJitInfo->pInvokeMarshalingRequired(method, sig);
3733 }
3734
3735 LPVOID ZapInfo::GetCookieForPInvokeCalliSig(CORINFO_SIG_INFO* szMetaSig,
3736                                                  void ** ppIndirection)
3737 {
3738     return getVarArgsHandle(szMetaSig, ppIndirection);
3739 }
3740
3741 bool ZapInfo::canGetCookieForPInvokeCalliSig(CORINFO_SIG_INFO* szMetaSig)
3742 {
3743     return canGetVarArgsHandle(szMetaSig);
3744 }
3745
3746 BOOL ZapInfo::satisfiesMethodConstraints(
3747             CORINFO_CLASS_HANDLE        parent,
3748             CORINFO_METHOD_HANDLE       method)
3749 {
3750     return m_pEEJitInfo->satisfiesMethodConstraints(parent, method);
3751 }
3752
3753
3754 BOOL ZapInfo::isCompatibleDelegate(
3755             CORINFO_CLASS_HANDLE objCls,
3756             CORINFO_CLASS_HANDLE methodParentCls,
3757             CORINFO_METHOD_HANDLE method,
3758             CORINFO_CLASS_HANDLE delegateCls,
3759             BOOL* pfIsOpenDelegate)
3760 {
3761     return m_pEEJitInfo->isCompatibleDelegate(objCls, methodParentCls, method, delegateCls, pfIsOpenDelegate);
3762 }
3763
3764 //
3765 // ICorErrorInfo
3766 //
3767
3768 HRESULT ZapInfo::GetErrorHRESULT(struct _EXCEPTION_POINTERS *pExceptionPointers)
3769 {
3770     return m_pEEJitInfo->GetErrorHRESULT(pExceptionPointers);
3771 }
3772
3773 ULONG ZapInfo::GetErrorMessage(__in_ecount(bufferLength) LPWSTR buffer, ULONG bufferLength)
3774 {
3775     return m_pEEJitInfo->GetErrorMessage(buffer, bufferLength);
3776 }
3777
3778 int ZapInfo::FilterException(struct _EXCEPTION_POINTERS *pExceptionPointers)
3779 {
3780     // Continue unwinding if fatal error was hit.
3781     if (FAILED(g_hrFatalError))
3782         return EXCEPTION_CONTINUE_SEARCH;
3783
3784     return m_pEEJitInfo->FilterException(pExceptionPointers);
3785 }
3786
3787 void ZapInfo::HandleException(struct _EXCEPTION_POINTERS *pExceptionPointers)
3788 {
3789     m_pEEJitInfo->HandleException(pExceptionPointers);
3790 }
3791
3792 void ZapInfo::ThrowExceptionForJitResult(HRESULT result)
3793 {
3794     m_pEEJitInfo->ThrowExceptionForJitResult(result);
3795 }
3796 void ZapInfo::ThrowExceptionForHelper(const CORINFO_HELPER_DESC * throwHelper)
3797 {
3798     m_pEEJitInfo->ThrowExceptionForHelper(throwHelper);
3799 }
3800
3801 template<> void LoadTable<CORINFO_CLASS_HANDLE>::EmitLoadFixups(CORINFO_METHOD_HANDLE currentMethodHandle, ZapInfo * pZapInfo)
3802 {
3803     //
3804     // Find all of our un-fixed entries, and emit a restore fixup for each of them.
3805     // Note that we don't need a restore fixups for prerestored classes.
3806     //
3807
3808     InlineSArray<LoadEntry, 4> unfixed;
3809
3810     for (LoadEntryHashTable::Iterator i = m_entries.Begin(), end = m_entries.End(); i != end; i++)
3811     {
3812         if (i->order == -1
3813             || m_pModule->m_pPreloader->CanPrerestoreEmbedClassHandle(i->handle)
3814             // @TODO: Skip transitive closure of currentMethodHandle (parents, instantiations, etc.)
3815             || m_pModule->GetJitInfo()->getMethodClass(currentMethodHandle) == i->handle)
3816             continue;
3817
3818         unfixed.Append(*i);
3819     }
3820
3821     //
3822     // Now clear the table.
3823     //
3824
3825     m_entries.RemoveAll();
3826
3827     if (unfixed.IsEmpty())
3828         return;
3829
3830     // Save the fixups in the order they got emited for determinism
3831     qsort(&unfixed[0], unfixed.GetCount(), sizeof(LoadEntry), LoadEntryCmp);
3832
3833     for(COUNT_T j = 0; j < unfixed.GetCount(); j++)
3834     {
3835         CORINFO_CLASS_HANDLE handle = unfixed[j].handle;
3836         m_pModule->m_pPreloader->AddTypeToTransitiveClosureOfInstantiations(handle);
3837         ZapImport * pImport = m_pModule->GetImportTable()->GetClassHandleImport(handle);
3838         pZapInfo->AppendImport(pImport);
3839     }
3840 }
3841
3842
3843 template<> void LoadTable<CORINFO_METHOD_HANDLE>::EmitLoadFixups(CORINFO_METHOD_HANDLE currentMethodHandle, ZapInfo * pZapInfo)
3844 {
3845     //
3846     // Find all of our un-fixed entries, and emit a restore fixup for each of them.
3847     // Note that we don't need a restore fixups for prerestored methods.
3848     //
3849
3850     InlineSArray<LoadEntry, 4> unfixed;
3851
3852     for (LoadEntryHashTable::Iterator i = m_entries.Begin(), end = m_entries.End(); i != end; i++)
3853     {
3854         if (i->order == -1
3855             || m_pModule->m_pPreloader->CanPrerestoreEmbedMethodHandle(i->handle)
3856             || currentMethodHandle == i->handle)
3857             continue;
3858
3859         unfixed.Append(*i);
3860     }
3861
3862     //
3863     // Now clear the table.
3864     //
3865
3866     m_entries.RemoveAll();
3867
3868     if (unfixed.IsEmpty())
3869         return;
3870
3871     // Save the fixups in the order they got emited for determinism
3872     qsort(&unfixed[0], unfixed.GetCount(), sizeof(LoadEntry), LoadEntryCmp);
3873
3874     for(COUNT_T j = 0; j < unfixed.GetCount(); j++)
3875     {
3876         CORINFO_METHOD_HANDLE handle = unfixed[j].handle;
3877         m_pModule->m_pPreloader->AddMethodToTransitiveClosureOfInstantiations(handle);
3878         ZapImport * pImport = m_pModule->GetImportTable()->GetMethodHandleImport(handle);
3879         pZapInfo->AppendImport(pImport);
3880     }
3881 }
3882
3883 BOOL ZapInfo::CurrentMethodHasProfileData()
3884 {
3885     WRAPPER_NO_CONTRACT;
3886     ULONG size;
3887     ICorJitInfo::ProfileBuffer * profileBuffer;
3888     return SUCCEEDED(getBBProfileData(m_currentMethodHandle, &size, &profileBuffer, NULL));
3889 }
3890