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