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.
9 // JIT-EE interface for zapping
11 // ======================================================================================
16 #include "zapimport.h"
17 #include "zapwrapper.h"
18 #include "zapinnerptr.h"
19 #include "zapmetadata.h"
21 #ifdef FEATURE_READYTORUN_COMPILER
22 #include "zapreadytorun.h"
25 ZapInfo::ZapInfo(ZapImage * pImage, mdMethodDef md, CORINFO_METHOD_HANDLE handle, CORINFO_MODULE_HANDLE module, unsigned methodProfilingDataFlags)
27 m_currentMethodToken(md),
28 m_currentMethodHandle(handle),
29 m_currentMethodModule(module),
30 m_currentMethodProfilingDataFlags(methodProfilingDataFlags),
32 m_pNativeVarInfo(NULL),
34 m_pOffsetMapping(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),
47 m_pUnwindInfoFragments(NULL),
48 #if defined(_TARGET_AMD64_)
49 m_pChainedColdUnwindInfo(NULL),
51 #endif // WIN64EXCEPTIONS
52 m_pExceptionInfo(NULL),
54 m_pProfilingHandle(NULL),
56 m_ClassLoadTable(pImage),
57 m_MethodLoadTable(pImage)
59 m_zapper = m_pImage->m_zapper;
61 m_pEEJitInfo = m_zapper->m_pEEJitInfo;
62 m_pEEJitInfo->setOverride(this, handle);
64 m_pEECompileInfo = m_zapper->m_pEECompileInfo;
69 m_pEEJitInfo->setOverride(NULL, NULL);
71 delete [] m_pNativeVarInfo;
72 delete [] m_pOffsetMapping;
75 #ifdef WIN64EXCEPTIONS
76 delete [] m_pMainUnwindInfo;
80 #ifdef ALLOW_SXS_JIT_NGEN
81 // The AltJit failed and we're going to retry. Forget everything the JIT told us and prepare to JIT again.
82 void ZapInfo::ResetForJitRetry()
84 delete [] m_pNativeVarInfo;
85 m_pNativeVarInfo = NULL;
89 delete [] m_pOffsetMapping;
90 m_pOffsetMapping = NULL;
99 #ifdef WIN64EXCEPTIONS
100 delete [] m_pMainUnwindInfo;
101 m_pMainUnwindInfo = NULL;
103 m_cbMainUnwindInfo = 0;
104 #endif // WIN64EXCEPTIONS
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.
114 #ifdef WIN64EXCEPTIONS
115 m_pUnwindInfoFragments = NULL;
116 m_pUnwindInfo = NULL;
117 #if defined(_TARGET_AMD64_)
118 m_pChainedColdUnwindInfo = NULL;
120 #endif // WIN64EXCEPTIONS
122 m_pExceptionInfo = NULL;
123 m_pProfileData = NULL;
124 m_pProfilingHandle = NULL;
126 m_ImportSet.RemoveAll();
128 m_CodeRelocations.Clear();
130 #endif // ALLOW_SXS_JIT_NGEN
132 void ZapInfo::InitMethodName()
134 const char* szClsName;
135 const char* szMethodName = m_pEEJitInfo->getMethodName(
136 m_currentMethodHandle,
139 m_currentMethodName.SetUTF8(szClsName);
140 m_currentMethodName.AppendUTF8(NAMESPACE_SEPARATOR_STR);
141 m_currentMethodName.AppendUTF8(szMethodName);
144 CORJIT_FLAGS ZapInfo::ComputeJitFlags(CORINFO_METHOD_HANDLE handle)
146 CORJIT_FLAGS jitFlags = m_zapper->m_pOpt->m_compilerFlags;
149 IfFailThrow(m_pEECompileInfo->GetBaseJitFlags(handle, &flags));
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)
158 // NGened code should enable fpo
159 jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_FRAMED);
161 else if (dwNGenFramed == 1)
163 // NGened code should disable fpo
164 jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_FRAMED);
167 if (canSkipMethodVerification(m_currentMethodHandle) == CORINFO_VERIFICATION_CAN_SKIP)
169 jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_SKIP_VERIFICATION);
172 if (m_pImage->m_profileDataSections[MethodBlockCounts].pData &&
173 !m_zapper->m_pOpt->m_ignoreProfileData)
175 jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_BBOPT);
179 // By default we always enable Hot/Cold procedure splitting
181 jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_PROCSPLIT);
183 if (m_zapper->m_pOpt->m_noProcedureSplitting)
184 jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_PROCSPLIT);
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))
189 jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_GCPOLL_INLINE);
190 jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_GCPOLL_CALLS);
193 // If the method is specified for min-opts then turn everything off
194 if (jitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_MIN_OPT))
196 jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_BBINSTR);
197 jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_BBOPT);
198 jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_PROCSPLIT);
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);
206 #ifdef FEATURE_READYTORUN_COMPILER
207 if (IsReadyToRunCompilation())
208 jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_READYTORUN);
214 ZapDebugInfo * ZapInfo::EmitDebugInfo()
216 if (m_iNativeVarInfo == 0 && m_iOffsetMapping == 0)
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.
224 StackSBuffer debugInfoBuffer;
225 m_pEECompileInfo->CompressDebugInfo(
226 m_pOffsetMapping, m_iOffsetMapping,
227 m_pNativeVarInfo, m_iNativeVarInfo,
230 if (IsReadyToRunCompilation())
231 return ZapBlob::NewBlob(m_pImage, &debugInfoBuffer[0], debugInfoBuffer.GetSize());
233 return m_pImage->m_pDebugInfoTable->GetDebugInfo(&debugInfoBuffer[0], debugInfoBuffer.GetSize());
236 ZapGCInfo * ZapInfo::EmitGCInfo()
238 _ASSERTE(m_pGCInfo != NULL);
240 #ifdef WIN64EXCEPTIONS
241 return m_pImage->m_pGCInfoTable->GetGCInfo(m_pGCInfo, m_cbGCInfo, m_pMainUnwindInfo, m_cbMainUnwindInfo);
243 return m_pImage->m_pGCInfoTable->GetGCInfo(m_pGCInfo, m_cbGCInfo);
244 #endif // WIN64EXCEPTIONS
247 ZapImport ** ZapInfo::EmitFixupList()
249 ZapImport ** pFixupList = NULL;
251 if (m_Imports.GetCount() != 0)
253 pFixupList = new (m_pImage->GetHeap()) ZapImport * [m_Imports.GetCount() + 1];
254 memcpy(pFixupList, &(m_Imports[0]), m_Imports.GetCount() * sizeof(ZapImport *));
261 int __cdecl ZapInfo::CompareCodeRelocation(const void * a_, const void * b_)
263 ZapInfo::CodeRelocation * a = (ZapInfo::CodeRelocation *)a_;
264 ZapInfo::CodeRelocation * b = (ZapInfo::CodeRelocation *)b_;
266 if (a->m_pNode != b->m_pNode)
268 return (a->m_pNode > b->m_pNode) ? 1 : -1;
271 return a->m_offset - b->m_offset;
274 void ZapInfo::EmitCodeRelocations()
276 if (m_CodeRelocations.IsEmpty())
279 qsort(&m_CodeRelocations[0], m_CodeRelocations.GetCount(), sizeof(CodeRelocation), CompareCodeRelocation);
281 COUNT_T startIndex = 0;
282 while (startIndex < m_CodeRelocations.GetCount())
284 ZapBlobWithRelocs * pNode = m_CodeRelocations[startIndex].m_pNode;
286 COUNT_T endIndex = startIndex + 1;
287 for ( ; endIndex < m_CodeRelocations.GetCount(); endIndex++)
289 if (m_CodeRelocations[endIndex].m_pNode != pNode)
293 ZapReloc * pRelocs = (ZapReloc *)
294 new (m_pImage->GetHeap()) BYTE[sizeof(ZapReloc) * (endIndex - startIndex) + sizeof(ZapRelocationType)];
296 for (COUNT_T i = 0; i < endIndex - startIndex; i++)
297 pRelocs[i] = m_CodeRelocations[startIndex + i];
300 static_assert_no_msg(offsetof(ZapReloc, m_type) == 0);
301 *(ZapRelocationType *)(pRelocs + (endIndex - startIndex)) = IMAGE_REL_INVALID;
303 pNode->SetRelocs(pRelocs);
305 startIndex = endIndex;
309 void ZapInfo::ProcessReferences()
311 COUNT_T count = m_CodeRelocations.GetCount();
312 for (COUNT_T i = 0; i < count; i++)
314 CORINFO_METHOD_HANDLE hMethod = NULL;
315 CORINFO_CLASS_HANDLE hClass = NULL;
316 bool fMaybeConditionalImport = false;
318 ZapNode * pTarget = m_CodeRelocations[i].m_pTargetNode;
320 ZapNodeType type = pTarget->GetType();
321 if (type == ZapNodeType_InnerPtr)
323 pTarget = ((ZapInnerPtr *)pTarget)->GetBase();
324 type = pTarget->GetType();
329 case ZapNodeType_MethodEntryPoint:
330 hMethod = ((ZapMethodEntryPoint*)pTarget)->GetHandle();
332 if (m_pImage->m_pPreloader->DoesMethodNeedRestoringBeforePrestubIsRun(hMethod))
334 methodMustBeLoadedBeforeCodeIsRun(hMethod);
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;
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;
350 case ZapNodeType_Import_FieldHandle:
351 case ZapNodeType_Import_StaticFieldAddress:
352 hClass = m_pEEJitInfo->getFieldClass((CORINFO_FIELD_HANDLE)(((ZapImport *)pTarget)->GetHandle()));
353 fMaybeConditionalImport = true;
355 case ZapNodeType_Import_StringHandle:
356 case ZapNodeType_Import_ModuleHandle:
357 case ZapNodeType_Import_ModuleDomainId:
358 case ZapNodeType_Import_VarArg:
359 fMaybeConditionalImport = true;
362 case ZapNodeType_MethodHandle:
363 hMethod = (CORINFO_METHOD_HANDLE)(((ZapWrapper *)pTarget)->GetHandle());
366 case ZapNodeType_ExternalMethodThunk:
367 case ZapNodeType_ExternalMethodCell:
368 hMethod = (CORINFO_METHOD_HANDLE)((ZapImport*)pTarget)->GetHandle();
375 if (fMaybeConditionalImport)
377 const ImportEntry * pExistingEntry = m_ImportSet.LookupPtr((ZapImport *)pTarget);
378 if (pExistingEntry != NULL && pExistingEntry->fConditional)
380 const_cast<ImportEntry *>(pExistingEntry)->fConditional = false;
381 m_Imports.Append((ZapImport *)pTarget);
383 // 'handle' does not have to be added to CORCOMPILE_LOAD_TABLE since we adding
384 // it to CORCOMPILE_HANDLE_TABLE
386 m_MethodLoadTable.Load(hMethod, TRUE);
389 m_ClassLoadTable.Load(hClass, TRUE);
395 m_pImage->m_pPreloader->MethodReferencedByCompiledCode(hMethod);
400 // Compile a method using the JIT or Module compiler, and emit fixups
402 void ZapInfo::CompileMethod()
404 PRECONDITION(m_zapper->m_pJitCompiler != NULL);
408 if (m_zapper->m_pOpt->m_verbose)
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());
415 m_currentMethodInfo = CORINFO_METHOD_INFO();
416 if (!getMethodInfo(m_currentMethodHandle, &m_currentMethodInfo))
421 // Method does not have IL (e.g. an abstract method)
422 if (m_currentMethodInfo.ILCodeSize == 0)
425 // During ngen we look for a hint attribute on the method that indicates
426 // the method should be preprocessed for early
427 // preparation. This normally happens automatically, but for methods that
428 // are prepared explicitly at runtime the needed
429 // information is missing from the ngen image, causing costly overheads
430 // at runtime. When the author of the method knows about
431 // this they can add the hint and reduce the perf cost at runtime.
432 m_pImage->m_pPreloader->PrePrepareMethodIfNecessary(m_currentMethodHandle);
434 m_jitFlags = ComputeJitFlags(m_currentMethodHandle);
436 #ifdef FEATURE_READYTORUN_COMPILER
437 if (IsReadyToRunCompilation())
439 // READYTORUN: FUTURE: Producedure spliting
440 m_jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_PROCSPLIT);
442 DWORD methodAttribs = getMethodAttribs(m_currentMethodHandle);
443 if (!(methodAttribs & CORINFO_FLG_NOSECURITYWRAP) || (methodAttribs & CORINFO_FLG_SECURITYCHECK))
445 m_zapper->Warning(W("ReadyToRun: Methods with security checks not supported\n"));
451 if (m_pImage->m_stats)
453 m_pImage->m_stats->m_methods++;
454 m_pImage->m_stats->m_ilCodeSize += m_currentMethodInfo.ILCodeSize;
457 CorJitResult res = CORJIT_SKIPPED;
462 #ifdef ALLOW_SXS_JIT_NGEN
463 if (m_zapper->m_alternateJit)
467 res = m_zapper->m_alternateJit->compileMethod( this,
468 &m_currentMethodInfo,
469 CORJIT_FLAGS::CORJIT_FLAG_CALL_GETJITFLAGS,
474 // We will fall back to the "main" JIT on failure.
478 #endif // ALLOW_SXS_JIT_NGEN
484 ICorJitCompiler * pCompiler = m_zapper->m_pJitCompiler;
485 res = pCompiler->compileMethod(this,
486 &m_currentMethodInfo,
487 CORJIT_FLAGS::CORJIT_FLAG_CALL_GETJITFLAGS,
493 ThrowExceptionForJitResult(res);
497 MethodCompileComplete(m_currentMethodInfo.ftn);
500 // The x86 JIT over estimates the code size. Trim the blob size down to
502 // We can do this only for non-split code. Adjusting the code size for split
503 // methods would hose offsets in GC info.
504 if (m_pColdCode == NULL)
506 m_pCode->AdjustBlobSize(cCode);
510 PublishCompiledMethod();
513 #ifndef FEATURE_FULL_NGEN
514 class MethodCodeComparer
516 static BOOL NodeEquals(ZapNode * k1, ZapNode * k2)
521 static BOOL BlobEquals(ZapBlob * k1, ZapBlob * k2)
523 if (k1 == NULL && k2 == NULL)
525 if (k1 == NULL || k2 == NULL)
528 if (k1->GetBlobSize() != k2->GetBlobSize())
530 if (memcmp(k1->GetData(), k2->GetData(), k1->GetBlobSize()) != 0)
536 typedef ZapNode * EquivalentNodes[4][2];
538 static BOOL EquivalentNode(ZapNode * k1, ZapNode * k2, EquivalentNodes & equivalentNodes)
543 for (int i = 0; i < _countof(equivalentNodes); i++)
545 if (k1 == equivalentNodes[i][0] && k2 == equivalentNodes[i][1])
552 static BOOL BlobWithRelocsEquals(ZapBlobWithRelocs * k1, ZapBlobWithRelocs * k2, EquivalentNodes & equivalentNodes)
554 if (k1 == NULL && k2 == NULL)
556 if (k1 == NULL || k2 == NULL)
559 if (k1->GetBlobSize() != k2->GetBlobSize())
561 if (memcmp(k1->GetData(), k2->GetData(), k1->GetBlobSize()) != 0)
564 ZapReloc * pRelocs1 = k1->GetRelocs();
565 ZapReloc * pRelocs2 = k2->GetRelocs();
567 if (pRelocs1 == NULL && pRelocs2 == NULL)
569 if (pRelocs1 == NULL || pRelocs2 == NULL)
572 while (pRelocs1->m_type != IMAGE_REL_INVALID || pRelocs2->m_type != IMAGE_REL_INVALID)
574 if (pRelocs1->m_type != pRelocs2->m_type || pRelocs1->m_offset != pRelocs2->m_offset)
577 if (!EquivalentNode(pRelocs1->m_pTargetNode, pRelocs2->m_pTargetNode, equivalentNodes))
580 pRelocs1++; pRelocs2++;
586 static BOOL UnwindInfoEquals(ZapUnwindInfo * k1, ZapUnwindInfo * k2, EquivalentNodes & equivalentNodes)
588 if (k1 == NULL && k2 == NULL)
590 if (k1 == NULL || k2 == NULL)
593 return (k1->GetStartOffset() == k2->GetStartOffset()) &&
594 (k1->GetEndOffset() == k2->GetEndOffset()) &&
595 (k1->GetUnwindData() == k2->GetUnwindData()) &&
596 EquivalentNode(k1->GetCode(), k2->GetCode(), equivalentNodes);
599 static BOOL UnwindInfoFragmentsEquals(ZapUnwindInfo * k1, ZapUnwindInfo * k2, EquivalentNodes & equivalentNodes)
601 if (k1 == NULL && k2 == NULL)
603 if (k1 == NULL || k2 == NULL)
606 while (k1 != NULL || k2 != NULL)
608 if (!UnwindInfoEquals(k1, k2, equivalentNodes))
611 k1 = k1->GetNextFragment(); k2 = k2->GetNextFragment();
617 static BOOL FixupListEquals(ZapImport ** k1, ZapImport ** k2)
619 if (k1 == NULL && k2 == NULL)
621 if (k1 == NULL || k2 == NULL)
624 while (*k1 != NULL || *k2 != NULL)
635 static BOOL MethodCodeEquals(ZapMethodHeader * k1, ZapMethodHeader * k2)
637 LIMITED_METHOD_CONTRACT;
639 EquivalentNodes equivalentNodes =
641 { k1->m_pCode, k2->m_pCode },
642 { k1->m_pColdCode, k2->m_pColdCode },
643 { k1->m_pROData, k2->m_pROData },
644 { k1->m_pProfileData, k2->m_pProfileData }
647 if (!BlobWithRelocsEquals(k1->m_pCode, k2->m_pCode, equivalentNodes))
650 if (!BlobWithRelocsEquals(k1->m_pColdCode, k2->m_pColdCode, equivalentNodes))
653 if (!UnwindInfoEquals(k1->m_pUnwindInfo, k2->m_pUnwindInfo, equivalentNodes))
656 if (!UnwindInfoEquals(k1->m_pColdUnwindInfo, k2->m_pColdUnwindInfo, equivalentNodes))
659 #ifdef WIN64EXCEPTIONS
660 if (!UnwindInfoFragmentsEquals(k1->m_pUnwindInfoFragments, k2->m_pUnwindInfoFragments, equivalentNodes))
664 if (!BlobWithRelocsEquals(k1->m_pROData, k2->m_pROData, equivalentNodes))
667 if (!BlobWithRelocsEquals(k1->m_pProfileData, k2->m_pProfileData, equivalentNodes))
670 if (!NodeEquals(k1->m_pGCInfo, k2->m_pGCInfo)) // interned
673 if (!NodeEquals(k1->m_pDebugInfo, k2->m_pDebugInfo)) // interned
676 if (!FixupListEquals(k1->m_pFixupList, k2->m_pFixupList))
679 if (!BlobEquals(k1->m_pExceptionInfo, k2->m_pExceptionInfo))
686 extern BOOL CanDeduplicateCode(CORINFO_METHOD_HANDLE method, CORINFO_METHOD_HANDLE duplicateMethod);
688 BOOL ZapImage::MethodCodeTraits::Equals(key_t k1, key_t k2)
690 if (!MethodCodeComparer::MethodCodeEquals(k1, k2))
693 // Check additional VM conditions that has to be satisfied for deduplication
694 if (!CanDeduplicateCode(k1->GetHandle(), k2->GetHandle()))
700 COUNT_T ZapImage::MethodCodeTraits::Hash(key_t k)
702 COUNT_T hash = ZapBlob::SHashTraits::Hash(ZapBlob::SHashTraits::GetKey(k->m_pCode));
704 ZapReloc * pRelocs = k->m_pCode->GetRelocs();
707 while (pRelocs->m_type != IMAGE_REL_INVALID)
709 ZapNode * pTarget = pRelocs->m_pTargetNode;
710 ZapNodeType type = pTarget->GetType();
712 if (type == ZapNodeType_InnerPtr)
714 pTarget = ((ZapInnerPtr *)pTarget)->GetBase();
715 type = pTarget->GetType();
718 // The IL stubs code often differs by just a method call or class handle. Include
719 // these in the hash code.
722 case ZapNodeType_MethodEntryPoint:
723 case ZapNodeType_ExternalMethodThunk:
724 case ZapNodeType_ClassHandle:
725 case ZapNodeType_Import_ClassHandle:
726 case ZapNodeType_MethodHandle:
727 case ZapNodeType_Import_MethodHandle:
728 hash = ((hash << 5) + hash) ^ (COUNT_T)(pTarget);
742 void ZapInfo::PublishCompiledMethod()
744 EmitCodeRelocations();
746 // Go through all references in the code, make sure that we have fixups for them,
747 // and ensure that they will be otherwise present in the image if necessary
750 // See if there are load fixups to emit.
751 m_ClassLoadTable.EmitLoadFixups(m_currentMethodHandle, this);
753 if (!IsReadyToRunCompilation())
754 m_MethodLoadTable.EmitLoadFixups(m_currentMethodHandle, this);
756 ZapMethodHeader * pMethod = new (m_pImage->GetHeap()) ZapMethodHeader();
758 pMethod->m_handle = m_currentMethodHandle;
759 pMethod->m_classHandle = getMethodClass(m_currentMethodHandle);
761 pMethod->m_pCode = m_pCode;
762 pMethod->m_pColdCode = m_pColdCode;
763 pMethod->m_pROData = m_pROData;
765 pMethod->m_pProfileData = m_pProfileData;
767 pMethod->m_pExceptionInfo = m_pExceptionInfo;
769 pMethod->m_pFixupList = EmitFixupList();
771 pMethod->m_pDebugInfo = EmitDebugInfo();
772 pMethod->m_pGCInfo = EmitGCInfo();
774 #ifdef WIN64EXCEPTIONS
775 pMethod->m_pUnwindInfoFragments = m_pUnwindInfoFragments;
777 // Set the combined GCInfo + UnwindInfo blob
778 m_pUnwindInfo->SetUnwindData(pMethod->m_pGCInfo);
780 #if defined(_TARGET_AMD64_)
781 if (m_pChainedColdUnwindInfo != NULL)
783 // Chain the cold unwind info with the hot unwind info
784 m_pChainedColdUnwindInfo->SetUnwindData(m_pUnwindInfo);
786 #endif // _TARGET_AMD64_
788 #endif // WIN64EXCEPTIONS
790 #ifndef FEATURE_FULL_NGEN
792 // Method code deduplication
794 // For now, the only methods eligible for de-duplication are IL stubs
796 if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB))
798 ZapMethodHeader * pDuplicateMethod = m_pImage->m_CodeDeduplicator.Lookup(pMethod);
799 if (pDuplicateMethod != NULL)
801 m_pImage->m_pPreloader->NoteDeduplicatedCode(pMethod->m_handle, pDuplicateMethod->m_handle);
805 m_pImage->m_CodeDeduplicator.Add(pMethod);
809 // Remember the gc info for IL stubs associated with hot methods so they can be packed well.
810 // Stubs that have no metadata token cannot be tracked by IBC data.
811 if (m_currentMethodProfilingDataFlags & (1 << ReadMethodCode))
813 if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB))
814 m_pImage->m_PrioritizedGCInfo.Append(pMethod->m_pGCInfo);
817 pMethod->m_ProfilingDataFlags = m_currentMethodProfilingDataFlags;
819 COUNT_T methodCompilationOrder = m_pImage->m_MethodCompilationOrder.GetCount();
820 pMethod->m_compilationOrder = methodCompilationOrder;
822 // We need to remember the first index into m_MethodCompilationOrder where we saw a method from this class
823 m_pImage->InitializeClassLayoutOrder(pMethod->m_classHandle, methodCompilationOrder);
825 m_pImage->m_CompiledMethods.Add(pMethod);
826 m_pImage->m_MethodCompilationOrder.Append(pMethod);
829 void ZapInfo::getGSCookie(GSCookie * pCookieVal, GSCookie ** ppCookieVal)
833 #ifdef FEATURE_READYTORUN_COMPILER
834 if (IsReadyToRunCompilation())
836 *ppCookieVal = (GSCookie *)m_pImage->GetImportTable()->GetHelperImport(READYTORUN_HELPER_GSCookie);
841 *ppCookieVal = (GSCookie *)m_pImage->GetInnerPtr(m_pImage->m_pEEInfoTable,
842 offsetof(CORCOMPILE_EE_INFO_TABLE, gsCookie));
845 DWORD ZapInfo::getJitFlags(CORJIT_FLAGS* jitFlags, DWORD sizeInBytes)
847 _ASSERTE(jitFlags != NULL);
848 _ASSERTE(sizeInBytes >= sizeof(m_jitFlags));
850 *jitFlags = m_jitFlags;
851 return sizeof(m_jitFlags);
854 IEEMemoryManager* ZapInfo::getMemoryManager()
856 return GetEEMemoryManager();
859 bool ZapInfo::runWithErrorTrap(void (*function)(void*), void* param)
861 return m_pEEJitInfo->runWithErrorTrap(function, param);
864 HRESULT ZapInfo::allocBBProfileBuffer (
866 ICorJitInfo::ProfileBuffer ** ppBlock
871 if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB))
877 // @TODO: support generic methods from other assemblies
878 if (m_currentMethodModule != m_pImage->m_hModule)
884 mdMethodDef md = m_currentMethodToken;
888 // This must be the non-System.Object instantiation of a generic type/method.
889 IfFailRet(m_zapper->m_pEECompileInfo->GetMethodDef(m_currentMethodHandle, &md));
895 IfFailRet(m_zapper->m_pEECompileInfo->GetMethodDef(m_currentMethodHandle, &mdTemp));
896 _ASSERTE(md == mdTemp);
904 // If the JIT retries the compilation (especially during JIT stress), it can
905 // try to allocate the profiling data multiple times. We will just keep track
906 // of the latest copy in this case.
907 // _ASSERTE(m_pProfileData == NULL);
909 DWORD totalSize = (DWORD) (cBlock * sizeof(ICorJitInfo::ProfileBuffer)) + sizeof(CORBBTPROF_METHOD_HEADER);
910 m_pProfileData = ZapBlobWithRelocs::NewAlignedBlob(m_pImage, NULL, totalSize, sizeof(DWORD));
911 CORBBTPROF_METHOD_HEADER * profileData = (CORBBTPROF_METHOD_HEADER *) m_pProfileData->GetData();
912 profileData->size = totalSize;
913 profileData->cDetail = 0;
914 profileData->method.token = md;
915 profileData->method.ILSize = m_currentMethodInfo.ILCodeSize;
916 profileData->method.cBlock = cBlock;
918 *ppBlock = (ICorJitInfo::ProfileBuffer *)(&profileData->method.block[0]);
923 HRESULT ZapInfo::getBBProfileData (
924 CORINFO_METHOD_HANDLE ftnHnd,
926 ICorJitInfo::ProfileBuffer ** ppBlock,
932 _ASSERTE(ftnHnd == m_currentMethodHandle);
936 // Initialize outputs in case we return E_FAIL
944 // For generic instantiations whose IL is in another module,
945 // the profile data is in that module
946 // @TODO: Fetch the profile data from the other module.
947 if ((m_currentMethodModule != m_pImage->m_hModule) ||
948 m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB))
953 ZapImage::ProfileDataSection * DataSection_MethodBlockCounts = & m_pImage->m_profileDataSections[MethodBlockCounts];
955 if (!DataSection_MethodBlockCounts->pData)
960 mdMethodDef md = m_currentMethodToken;
964 // This must be the non-System.Object instantiation of a generic type/method.
965 IfFailRet(m_zapper->m_pEECompileInfo->GetMethodDef(ftnHnd, &md));
971 IfFailRet(m_zapper->m_pEECompileInfo->GetMethodDef(ftnHnd, &mdTemp));
972 _ASSERTE(md == mdTemp);
982 *numRuns = m_pImage->m_profileDataNumRuns;
985 const ZapImage::ProfileDataHashEntry * foundEntry = m_pImage->profileDataHashTable.LookupPtr(md);
987 if (foundEntry == NULL)
992 // The md must match.
993 _ASSERTE(foundEntry->md == md);
995 if (foundEntry->pos == 0)
997 // We might not have profile data and instead only have CompileStatus and flags
998 assert(foundEntry->size == 0);
1004 // We found the md. Let's retrieve the profile data.
1006 _ASSERTE(foundEntry->size >= sizeof(CORBBTPROF_METHOD_HEADER)); // The size must at least this
1008 ProfileReader profileReader(DataSection_MethodBlockCounts->pData, DataSection_MethodBlockCounts->dataSize);
1010 // Locate the method in interest.
1011 SEEK(foundEntry->pos);
1012 CORBBTPROF_METHOD_HEADER * profileData;
1013 READ_SIZE(profileData, CORBBTPROF_METHOD_HEADER, foundEntry->size);
1014 _ASSERTE(profileData->method.token == foundEntry->md); // We should be looking at the right method
1015 _ASSERTE(profileData->size == foundEntry->size); // and the cached size must match
1017 *ppBlock = (ICorJitInfo::ProfileBuffer *) &profileData->method.block[0];
1018 *pCount = profileData->method.cBlock;
1020 // If the ILSize is non-zero the the ILCodeSize also must match
1022 if ((profileData->method.ILSize != 0) && (profileData->method.ILSize != m_currentMethodInfo.ILCodeSize))
1024 // IL code for this method does not match the IL code for the method when it was profiled
1025 // in such cases we tell the JIT to discard the profile data by returning E_FAIL
1033 void ZapInfo::allocMem(
1034 ULONG hotCodeSize, /* IN */
1035 ULONG coldCodeSize, /* IN */
1036 ULONG roDataSize, /* IN */
1037 ULONG xcptnsCount, /* IN */
1038 CorJitAllocMemFlag flag, /* IN */
1039 void ** hotCodeBlock, /* OUT */
1040 void ** coldCodeBlock, /* OUT */
1041 void ** roDataBlock /* OUT */
1044 bool optForSize = m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_SIZE_OPT);
1046 UINT align = DEFAULT_CODE_ALIGN;
1048 if ((flag & CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN) && !IsReadyToRunCompilation()) align = max(align, 16);
1050 m_pCode = ZapCodeBlob::NewAlignedBlob(m_pImage, NULL, hotCodeSize, align);
1051 *hotCodeBlock = m_pCode->GetData();
1053 if (coldCodeSize != 0)
1055 align = sizeof(DWORD);
1057 m_pColdCode = ZapCodeBlob::NewAlignedBlob(m_pImage, NULL, coldCodeSize, align);
1058 *coldCodeBlock = m_pColdCode->GetData();
1067 if (flag & CORJIT_ALLOCMEM_FLG_RODATA_16BYTE_ALIGN)
1071 else if (optForSize || (roDataSize < 8))
1073 align = sizeof(TADDR);
1079 m_pROData = ZapBlobWithRelocs::NewAlignedBlob(m_pImage, NULL, roDataSize, align);
1080 *roDataBlock = m_pROData->GetData();
1083 if (m_pImage->m_stats)
1085 m_pImage->m_stats->m_nativeCodeSize += hotCodeSize;
1086 m_pImage->m_stats->m_nativeColdCodeSize += coldCodeSize;
1087 m_pImage->m_stats->m_nativeRODataSize += roDataSize;
1089 BOOL haveProfileData = CurrentMethodHasProfileData();
1091 if (haveProfileData)
1093 m_pImage->m_stats->m_nativeCodeSizeInProfiledMethods += hotCodeSize;
1094 m_pImage->m_stats->m_nativeColdCodeSizeInProfiledMethods += coldCodeSize;
1099 m_pImage->m_stats->m_NumHotColdAllocations++;
1101 m_pImage->m_stats->m_nativeCodeSizeInSplitMethods += hotCodeSize;
1102 m_pImage->m_stats->m_nativeColdCodeSizeInSplitMethods += coldCodeSize;
1104 if (haveProfileData)
1106 m_pImage->m_stats->m_nativeCodeSizeInSplitProfiledMethods += hotCodeSize;
1107 m_pImage->m_stats->m_nativeColdCodeSizeInSplitProfiledMethods += coldCodeSize;
1112 m_pImage->m_stats->m_NumHotAllocations++;
1117 void * ZapInfo::allocGCInfo(size_t size)
1119 _ASSERTE(m_pGCInfo == NULL);
1122 if (size & 0xFFFFFFFF80000000LL)
1124 IfFailThrow(CORJIT_OUTOFMEM);
1128 m_pGCInfo = new BYTE[size];
1134 void ZapInfo::yieldExecution()
1136 // nothing necessary here
1140 void ZapInfo::setEHcount(unsigned cEH)
1143 // Must call after header has been allocated
1148 _ASSERTE(!"Should not be called");
1152 ULONG size = (sizeof(CORCOMPILE_EXCEPTION_CLAUSE) * cEH);
1154 _ASSERTE(m_pExceptionInfo == NULL);
1155 m_pExceptionInfo = ZapBlob::NewAlignedBlob(m_pImage, NULL, size, sizeof(DWORD));
1158 void ZapInfo::setEHinfo(unsigned EHnumber,
1159 const CORINFO_EH_CLAUSE *clause)
1162 // Must call after EH info has been allocated
1165 _ASSERTE(m_pExceptionInfo != NULL);
1167 CORCOMPILE_EXCEPTION_CLAUSE *ehClauseArray = (CORCOMPILE_EXCEPTION_CLAUSE *)m_pExceptionInfo->GetData();
1168 CORCOMPILE_EXCEPTION_CLAUSE *ilClause = &ehClauseArray[EHnumber];
1170 ilClause->TryStartPC = clause->TryOffset;
1171 ilClause->TryEndPC = clause->TryLength;
1172 ilClause->HandlerStartPC= clause->HandlerOffset;
1173 ilClause->HandlerEndPC = clause->HandlerLength;
1174 ilClause->Flags = (CorExceptionFlag) clause->Flags;
1176 if (clause->Flags & CORINFO_EH_CLAUSE_FILTER)
1178 ilClause->FilterOffset = clause->FilterOffset;
1182 ilClause->ClassToken = clause->ClassToken;
1184 if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB) && (clause->ClassToken != 0))
1186 // IL stub tokens are 'private' and do not resolve correctly in their parent module's metadata.
1188 // Currently, the only place we are using a token here is for a COM-to-CLR exception-to-HRESULT
1189 // mapping catch clause. We want this catch clause to catch all exceptions, so we override the
1190 // token to be mdTypeRefNil, which used by the EH system to mean catch(...)
1193 // The proper way to do this, should we ever want to support arbitrary types here, is to "pre-
1194 // resolve" the token and store the TypeHandle in the clause. But this requires additional
1195 // infrastructure to ensure the TypeHandle is saved and fixed-up properly. For now, we will
1196 // simply assert that the original type was System.Object.
1198 CORINFO_RESOLVED_TOKEN resolvedToken = { 0 };
1199 resolvedToken.tokenContext = MAKE_METHODCONTEXT(m_currentMethodInfo.ftn);
1200 resolvedToken.tokenScope = m_currentMethodInfo.scope;
1201 resolvedToken.token = ilClause->ClassToken;
1202 resolvedToken.tokenType = CORINFO_TOKENKIND_Class;
1204 resolveToken(&resolvedToken);
1206 CORINFO_CLASS_HANDLE systemObjectHandle = getBuiltinClass(CLASSID_SYSTEM_OBJECT);
1207 _ASSERTE(systemObjectHandle == resolvedToken.hClass);
1210 ilClause->ClassToken = mdTypeRefNil;
1215 // @TODO: this does not support DynamicMethods
1219 int ZapInfo::canHandleException(struct _EXCEPTION_POINTERS *pExceptionPointers)
1221 return (EXCEPTION_EXECUTE_HANDLER);
1224 int ZapInfo::doAssert(const char* szFile, int iLine, const char* szExpr)
1228 return(_DbgBreakCheck(szFile, iLine, szExpr));
1230 return(true); // break into debugger
1234 void ZapInfo::reportFatalError(CorJitResult result)
1236 m_zapper->Info(W("Jit reported error 0x%x while compiling %s\n"), (int)result,
1237 m_currentMethodName.GetUnicode());
1240 // Reserve memory for the method/funclet's unwind information
1241 // Note that this must be called before allocMem, it should be
1242 // called once for the main method, once for every funclet region, and
1243 // once for every non-funclet cold region for which we will call
1246 // For prejitted code we need to count how many funclet regions
1247 // we have so that we can allocate and sort a contiguous .rdata block.
1249 void ZapInfo::reserveUnwindInfo(BOOL isFunclet, BOOL isColdCode, ULONG unwindSize)
1256 // Allocate and initialize the .xdata and .pdata for this method or
1257 // funclet region and get the block of memory needed for the machine-specific
1258 // unwind information (the info for crawling the stack frame).
1259 // Note that allocMem must be called first.
1261 // The pHotCode parameter points at the first byte of the code of the method.
1262 // The startOffset and endOffset are the region (main or funclet) that
1263 // we are to allocate and create .xdata and .pdata for.
1264 // The pUnwindBlock is copied and contains the .xdata unwind info.
1268 // pHotCode main method code buffer, always filled in
1269 // pColdCode cold code buffer, only filled in if this is cold code,
1271 // startOffset start of code block, relative to appropriate code buffer
1272 // (e.g. pColdCode if cold, pHotCode if hot).
1273 // endOffset end of code block, relative to appropriate code buffer
1274 // unwindSize size of unwind info pointed to by pUnwindBlock
1275 // pUnwindBlock pointer to unwind info
1276 // funcKind type of funclet (main method code, handler, filter)
1278 void ZapInfo::allocUnwindInfo (
1279 BYTE * pHotCode, /* IN */
1280 BYTE * pColdCode, /* IN */
1281 ULONG startOffset, /* IN */
1282 ULONG endOffset, /* IN */
1283 ULONG unwindSize, /* IN */
1284 BYTE * pUnwindBlock, /* IN */
1285 CorJitFuncKind funcKind /* IN */
1288 #ifdef WIN64EXCEPTIONS
1289 _ASSERTE(pHotCode == m_pCode->GetData());
1290 _ASSERTE(pColdCode == NULL || pColdCode == m_pColdCode->GetData());
1292 ZapNode * pCode = (pColdCode != NULL) ? m_pColdCode : m_pCode;
1294 ZapUnwindInfo * pUnwindInfo = new (m_pImage->GetHeap()) ZapUnwindInfo(pCode, startOffset, endOffset);
1296 // Prepend the new unwind info to the linked list of all fragments
1297 pUnwindInfo->SetNextFragment(m_pUnwindInfoFragments);
1298 m_pUnwindInfoFragments = pUnwindInfo;
1300 if (funcKind == CORJIT_FUNC_ROOT && pColdCode == NULL && startOffset == 0)
1303 // Main method unwind data
1306 _ASSERTE(m_pMainUnwindInfo == NULL);
1308 m_pMainUnwindInfo = new BYTE[unwindSize];
1309 m_cbMainUnwindInfo = unwindSize;
1311 memcpy(m_pMainUnwindInfo, pUnwindBlock, unwindSize);
1313 // UnwindData Will be set to the combined GCInfo + UnwindInfo blob later as the compiled method is published
1315 _ASSERTE(m_pUnwindInfo == NULL);
1316 m_pUnwindInfo = pUnwindInfo;
1318 #if defined(_TARGET_AMD64_)
1320 if (funcKind == CORJIT_FUNC_ROOT && pColdCode != NULL)
1323 // Chained cold code unwind data
1326 _ASSERTE(unwindSize == 0);
1328 // UnwindData Will be chained to the parent unwind info later as the compiled method is published
1330 _ASSERTE(m_pChainedColdUnwindInfo == NULL);
1331 m_pChainedColdUnwindInfo = pUnwindInfo;
1338 // Normal unwind data
1341 ZapUnwindData * pUnwindData = m_pImage->m_pUnwindDataTable->GetUnwindData(pUnwindBlock, unwindSize, funcKind == CORJIT_FUNC_FILTER);
1342 pUnwindInfo->SetUnwindData(pUnwindData);
1344 #endif // WIN64EXCEPTIONS
1347 BOOL ZapInfo::logMsg(unsigned level, const char *fmt, va_list args)
1351 if (level <= LL_INFO10)
1354 ss.VPrintf(fmt,args);
1355 GetSvcLogger()->Log(ss.GetUnicode(), LogLevel_Success);
1361 if (LoggingOn(LF_JIT, level))
1363 LogSpewValist(LF_JIT, level, (char*) fmt, args);
1375 DWORD ZapInfo::getThreadTLSIndex(void **ppIndirection)
1377 _ASSERTE(ppIndirection != NULL);
1379 *ppIndirection = NULL;
1383 const void * ZapInfo::getInlinedCallFrameVptr(void **ppIndirection)
1385 _ASSERTE(ppIndirection != NULL);
1387 *ppIndirection = m_pImage->GetInnerPtr(m_pImage->m_pEEInfoTable,
1388 offsetof(CORCOMPILE_EE_INFO_TABLE, inlinedCallFrameVptr));
1392 LONG * ZapInfo::getAddrOfCaptureThreadGlobal(void **ppIndirection)
1394 _ASSERTE(ppIndirection != NULL);
1396 *ppIndirection = (LONG *) m_pImage->GetInnerPtr(m_pImage->m_pEEInfoTable,
1397 offsetof(CORCOMPILE_EE_INFO_TABLE, addrOfCaptureThreadGlobal));
1401 // Get slow lazy string literal helper to use (CORINFO_HELP_STRCNS*).
1402 // Returns CORINFO_HELP_UNDEF if lazy string literal helper cannot be used.
1403 CorInfoHelpFunc ZapInfo::getLazyStringLiteralHelper(CORINFO_MODULE_HANDLE handle)
1405 if (handle == m_pImage->m_hModule)
1406 return CORINFO_HELP_STRCNS_CURRENT_MODULE;
1408 return CORINFO_HELP_STRCNS;
1411 CORINFO_MODULE_HANDLE ZapInfo::embedModuleHandle(CORINFO_MODULE_HANDLE handle,
1412 void **ppIndirection)
1414 _ASSERTE(ppIndirection != NULL);
1416 if (IsReadyToRunCompilation())
1418 _ASSERTE(!"embedModuleHandle");
1422 BOOL fHardbound = m_pImage->m_pPreloader->CanEmbedModuleHandle(handle);
1425 if (handle == m_pImage->m_hModule)
1427 // If the handle is the module we are currently ngening, we will
1428 // assume that Module is the very first thing in the preload section
1429 *ppIndirection = NULL;
1430 return (CORINFO_MODULE_HANDLE)m_pImage->m_pPreloadSections[CORCOMPILE_SECTION_MODULE];
1433 *ppIndirection = m_pImage->GetImportTable()->GetModuleHandleImport(handle);
1437 ZapImport * pImport = m_pImage->GetImportTable()->GetModuleHandleImport(handle);
1438 AppendConditionalImport(pImport);
1440 *ppIndirection = pImport;
1446 // The following functions indicate whether a handle can be directly embedded into
1447 // the code being compiled, or if it needs to be accessed with a (fixable) indirection.
1448 // Embeddable handles are those that will be persisted in the zap image.
1450 // These functions are gradually being all moved across to ceeload.cpp and compile.cpp.
1453 CORINFO_CLASS_HANDLE ZapInfo::embedClassHandle(CORINFO_CLASS_HANDLE handle,
1454 void **ppIndirection)
1456 _ASSERTE(ppIndirection != NULL);
1458 if (IsReadyToRunCompilation())
1460 _ASSERTE(!"embedClassHandle");
1464 m_pImage->m_pPreloader->AddTypeToTransitiveClosureOfInstantiations(handle);
1466 BOOL fHardbound = m_pImage->m_pPreloader->CanEmbedClassHandle(handle);
1469 CORINFO_MODULE_HANDLE moduleHandle = m_pEECompileInfo->GetLoaderModuleForEmbeddableType(handle);
1471 if (moduleHandle == m_pImage->m_hModule)
1473 // If the handle is the module we are currently ngening, we can
1474 // embed it after its resolved. So use a deferred reloc
1476 *ppIndirection = NULL;
1477 return CORINFO_CLASS_HANDLE(m_pImage->GetWrappers()->GetClassHandle(handle));
1480 *ppIndirection = m_pImage->GetImportTable()->GetClassHandleImport(handle);
1484 ZapImport * pImport = m_pImage->GetImportTable()->GetClassHandleImport(handle);
1485 AppendConditionalImport(pImport);
1487 *ppIndirection = pImport;
1492 CORINFO_FIELD_HANDLE ZapInfo::embedFieldHandle(CORINFO_FIELD_HANDLE handle,
1493 void **ppIndirection)
1495 _ASSERTE(ppIndirection != NULL);
1497 if (IsReadyToRunCompilation())
1499 _ASSERTE(!"embedFieldHandle");
1503 m_pImage->m_pPreloader->AddTypeToTransitiveClosureOfInstantiations(m_pEEJitInfo->getFieldClass(handle));
1505 BOOL fHardbound = m_pImage->m_pPreloader->CanEmbedFieldHandle(handle);
1508 CORINFO_MODULE_HANDLE moduleHandle = m_pEECompileInfo->GetLoaderModuleForEmbeddableField(handle);
1510 if (moduleHandle == m_pImage->m_hModule)
1512 // If the handle is the module we are currently ngening, we can
1513 // embed it after its resolved. So use a deferred reloc
1515 *ppIndirection = NULL;
1516 return CORINFO_FIELD_HANDLE(m_pImage->GetWrappers()->GetFieldHandle(handle));
1521 ZapImport * pImport = m_pImage->GetImportTable()->GetFieldHandleImport(handle);
1522 AppendConditionalImport(pImport);
1524 *ppIndirection = pImport;
1528 CORINFO_METHOD_HANDLE ZapInfo::embedMethodHandle(CORINFO_METHOD_HANDLE handle,
1529 void **ppIndirection)
1531 _ASSERTE(ppIndirection != NULL);
1533 if (IsReadyToRunCompilation())
1535 // READYTORUN FUTURE: Handle this case correctly
1539 CORINFO_MODULE_HANDLE moduleHandle = m_pEECompileInfo->GetLoaderModuleForEmbeddableMethod(handle);
1540 if (moduleHandle == m_pImage->m_hModule
1541 && m_pImage->m_pPreloader->CanEmbedMethodHandle(handle, m_currentMethodHandle))
1543 // If the handle is the module we are currently ngening, we can
1544 // embed it after its resolved. So use a deferred reloc
1546 *ppIndirection = NULL;
1547 return CORINFO_METHOD_HANDLE(m_pImage->GetWrappers()->GetMethodHandle(handle));
1550 ZapImport * pImport = m_pImage->GetImportTable()->GetMethodHandleImport(handle);
1551 AppendConditionalImport(pImport);
1553 *ppIndirection = pImport;
1557 CORINFO_CLASS_HANDLE ZapInfo::getTokenTypeAsHandle(CORINFO_RESOLVED_TOKEN * pResolvedToken)
1559 return m_pEEJitInfo->getTokenTypeAsHandle(pResolvedToken);
1563 ZapInfo::getLocationOfThisType(CORINFO_METHOD_HANDLE context)
1565 return m_pEEJitInfo->getLocationOfThisType(context);
1569 ZapInfo::embedGenericHandle(CORINFO_RESOLVED_TOKEN * pResolvedToken,
1571 CORINFO_GENERICHANDLE_RESULT *pResult)
1575 m_pEEJitInfo->embedGenericHandle( pResolvedToken,
1579 _ASSERTE(pResult->compileTimeHandle);
1581 if (pResult->lookup.lookupKind.needsRuntimeLookup)
1583 if (!IsReadyToRunCompilation())
1584 embedGenericSignature(&pResult->lookup);
1586 if (pResult->handleType == CORINFO_HANDLETYPE_METHOD)
1588 // There is no easy way to detect method referenced via generic lookups in generated code.
1589 // Report this method reference unconditionally.
1590 m_pImage->m_pPreloader->MethodReferencedByCompiledCode((CORINFO_METHOD_HANDLE)pResult->compileTimeHandle);
1595 void *pIndirection = 0;
1596 CORINFO_GENERIC_HANDLE handle = 0;
1598 switch (pResult->handleType)
1600 case CORINFO_HANDLETYPE_CLASS:
1601 if (IsReadyToRunCompilation())
1603 ZapImport * pImport = m_pImage->GetImportTable()->GetClassImport(ENCODE_TYPE_HANDLE, pResolvedToken);
1604 AppendConditionalImport(pImport);
1605 pIndirection = pImport;
1610 CORINFO_CLASS_HANDLE clsHnd = (CORINFO_CLASS_HANDLE) pResult->compileTimeHandle;
1611 handle = CORINFO_GENERIC_HANDLE(embedClassHandle(clsHnd, &pIndirection));
1615 case CORINFO_HANDLETYPE_METHOD:
1616 if (IsReadyToRunCompilation())
1618 ZapImport * pImport = m_pImage->GetImportTable()->GetMethodImport(ENCODE_METHOD_HANDLE, (CORINFO_METHOD_HANDLE)pResult->compileTimeHandle, pResolvedToken);
1619 AppendConditionalImport(pImport);
1620 pIndirection = pImport;
1625 CORINFO_METHOD_HANDLE methHnd = (CORINFO_METHOD_HANDLE) pResult->compileTimeHandle;
1626 handle = CORINFO_GENERIC_HANDLE(embedMethodHandle(methHnd, &pIndirection));
1630 case CORINFO_HANDLETYPE_FIELD:
1631 if (IsReadyToRunCompilation())
1633 ZapImport * pImport = m_pImage->GetImportTable()->GetFieldImport(ENCODE_FIELD_HANDLE, (CORINFO_FIELD_HANDLE)pResult->compileTimeHandle, pResolvedToken);
1634 AppendConditionalImport(pImport);
1635 pIndirection = pImport;
1640 CORINFO_FIELD_HANDLE fldHnd = (CORINFO_FIELD_HANDLE) pResult->compileTimeHandle;
1641 handle = CORINFO_GENERIC_HANDLE(embedFieldHandle(fldHnd, &pIndirection));
1646 ThrowHR(COR_E_BADIMAGEFORMAT, BFA_INVALID_TOKEN_TYPE);
1651 pResult->lookup.constLookup.accessType = IAT_VALUE;
1652 pResult->lookup.constLookup.handle = CORINFO_GENERIC_HANDLE(handle);
1656 pResult->lookup.constLookup.accessType = IAT_PVALUE;
1657 pResult->lookup.constLookup.addr = pIndirection;
1662 void ZapInfo::embedGenericSignature(CORINFO_LOOKUP * pLookup)
1664 _ASSERTE(pLookup->lookupKind.needsRuntimeLookup);
1666 if (IsReadyToRunCompilation())
1668 UNREACHABLE_MSG("We should never get here for the ReadyToRun compilation.");
1672 if (pLookup->runtimeLookup.signature != NULL)
1674 pLookup->runtimeLookup.signature = m_pImage->GetImportTable()->GetGenericSignature(
1675 pLookup->runtimeLookup.signature, pLookup->lookupKind.runtimeLookupKind == CORINFO_LOOKUP_METHODPARAM);
1679 void* ZapInfo::getTailCallCopyArgsThunk (
1680 CORINFO_SIG_INFO *pSig,
1681 CorInfoHelperTailCallSpecialHandling flags)
1683 void * pStub = m_pEEJitInfo->getTailCallCopyArgsThunk(pSig, flags);
1686 return m_pImage->GetWrappers()->GetStub(pStub);
1689 #ifdef FEATURE_READYTORUN_COMPILER
1690 ReadyToRunHelper MapReadyToRunHelper(CorInfoHelpFunc func, bool * pfOptimizeForSize)
1694 #define OPTIMIZEFORSIZE *pfOptimizeForSize = true;
1695 #define HELPER(readyToRunHelper, corInfoHelpFunc, flags) \
1696 case corInfoHelpFunc: flags return readyToRunHelper;
1697 #include "readytorunhelpers.h"
1699 case CORINFO_HELP_STRCNS_CURRENT_MODULE:
1700 *pfOptimizeForSize = true;
1701 return READYTORUN_HELPER_GetString;
1704 return READYTORUN_HELPER_Invalid;
1707 #endif // FEATURE_READYTORUN_COMPILER
1709 void * ZapInfo::getHelperFtn (CorInfoHelpFunc ftnNum, void **ppIndirection)
1711 _ASSERTE(ppIndirection != NULL);
1712 *ppIndirection = NULL;
1714 #ifdef FEATURE_READYTORUN_COMPILER
1715 if (IsReadyToRunCompilation())
1717 bool fOptimizeForSize = false;
1718 ReadyToRunHelper helperNum = MapReadyToRunHelper(ftnNum, &fOptimizeForSize);
1720 if (helperNum == READYTORUN_HELPER_Invalid)
1722 m_zapper->Warning(W("ReadyToRun: JIT helper not supported: %S\n"), m_pEEJitInfo->getHelperName(ftnNum));
1726 if (fOptimizeForSize)
1728 *ppIndirection = NULL;
1729 return m_pImage->GetImportTable()->GetIndirectHelperThunk(helperNum);
1733 *ppIndirection = m_pImage->GetImportTable()->GetHelperImport(helperNum);
1739 DWORD dwHelper = ftnNum;
1743 case CORINFO_HELP_PROF_FCN_ENTER:
1744 *ppIndirection = m_pImage->GetInnerPtr(GetProfilingHandleImport(), kZapProfilingHandleImportValueIndexEnterAddr * sizeof(TADDR));
1746 case CORINFO_HELP_PROF_FCN_LEAVE:
1747 *ppIndirection = m_pImage->GetInnerPtr(GetProfilingHandleImport(), kZapProfilingHandleImportValueIndexLeaveAddr * sizeof(TADDR));
1749 case CORINFO_HELP_PROF_FCN_TAILCALL:
1750 *ppIndirection = m_pImage->GetInnerPtr(GetProfilingHandleImport(), kZapProfilingHandleImportValueIndexTailcallAddr * sizeof(TADDR));
1752 #ifdef _TARGET_AMD64_
1753 case CORINFO_HELP_STOP_FOR_GC:
1754 // Force all calls in ngen images for this helper to use an indirect call.
1755 // We cannot use a jump stub to reach this helper because
1756 // the RAX register can contain a return value.
1757 dwHelper |= CORCOMPILE_HELPER_PTR;
1764 if (m_pImage->m_pHelperThunks[ftnNum] == NULL)
1766 ZapNode * pHelperThunk;
1767 if (ftnNum == CORINFO_HELP_STRCNS_CURRENT_MODULE)
1769 pHelperThunk = new (m_pImage->GetHeap()) ZapLazyHelperThunk(CORINFO_HELP_STRCNS);
1773 pHelperThunk = new (m_pImage->GetHeap()) ZapHelperThunk(dwHelper);
1775 #if defined(_TARGET_ARM_)
1776 if ((dwHelper & CORCOMPILE_HELPER_PTR) == 0)
1777 pHelperThunk = m_pImage->GetInnerPtr(pHelperThunk, THUMB_CODE);
1779 m_pImage->m_pHelperThunks[ftnNum] = pHelperThunk;
1782 void * ptr = m_pImage->m_pHelperThunks[ftnNum];
1784 if (dwHelper & CORCOMPILE_HELPER_PTR)
1786 *ppIndirection = ptr;
1793 ULONG ZapInfo::GetNumFixups()
1795 return m_Imports.GetCount();
1798 void ZapInfo::AppendConditionalImport(ZapImport * pImport)
1800 if (m_ImportSet.LookupPtr(pImport) != NULL)
1804 entry.pImport = pImport;
1805 entry.fConditional = true;
1806 m_ImportSet.Add(entry);
1809 void ZapInfo::AppendImport(ZapImport * pImport)
1811 const ImportEntry * pExistingEntry = m_ImportSet.LookupPtr(pImport);
1812 if (pExistingEntry != NULL)
1814 if (!pExistingEntry->fConditional)
1816 const_cast<ImportEntry *>(pExistingEntry)->fConditional = false;
1821 entry.pImport = pImport;
1822 entry.fConditional = false;
1823 m_ImportSet.Add(entry);
1826 m_Imports.Append(pImport);
1830 // This function indicates whether a method entry point be directly embedded into
1831 // the code being compiled, or if we can use a (fixable) cross module thunk.
1832 // If we can't use either of these then we return NULL and we will use an
1833 // (fixable) indirection cell to perform the call.
1835 PVOID ZapInfo::embedDirectCall(CORINFO_METHOD_HANDLE ftn,
1836 CORINFO_ACCESS_FLAGS accessFlags,
1839 if (!m_pImage->m_pPreloader->CanEmbedFunctionEntryPoint(ftn, m_currentMethodHandle, accessFlags))
1844 ZapNode * pEntryPointOrThunkToEmbed = NULL;
1847 // If it's in the same module then we can call it directly
1849 CORINFO_MODULE_HANDLE moduleHandle = m_pEECompileInfo->GetLoaderModuleForEmbeddableMethod(ftn);
1850 if (moduleHandle == m_pImage->m_hModule
1851 && m_pImage->m_pPreloader->CanEmbedMethodHandle(ftn, m_currentMethodHandle))
1853 pEntryPointOrThunkToEmbed = m_pImage->m_pMethodEntryPoints->GetMethodEntryPoint(ftn, accessFlags);
1855 else // otherwise we are calling into an external module
1862 pEntryPointOrThunkToEmbed = m_pImage->GetImportTable()->GetExternalMethodThunk(ftn);
1866 pEntryPointOrThunkToEmbed = m_pImage->GetInnerPtr(pEntryPointOrThunkToEmbed, THUMB_CODE);
1869 return pEntryPointOrThunkToEmbed;
1872 void ZapInfo::getFunctionEntryPoint(
1873 CORINFO_METHOD_HANDLE ftn, /* IN */
1874 CORINFO_CONST_LOOKUP * pResult, /* OUT */
1875 CORINFO_ACCESS_FLAGS accessFlags/*=CORINFO_ACCESS_ANY*/)
1877 if (IsReadyToRunCompilation())
1879 // READYTORUN: FUTURE: JIT still calls this for tail. and jmp instructions
1880 m_zapper->Warning(W("ReadyToRun: Method entrypoint cannot be encoded\n"));
1884 // Must deal with methods that are methodImpl'd within their own type.
1885 ftn = mapMethodDeclToMethodImpl(ftn);
1887 m_pImage->m_pPreloader->AddMethodToTransitiveClosureOfInstantiations(ftn);
1889 void * entryPointOrThunkToEmbed = embedDirectCall(ftn, accessFlags, TRUE);
1890 if (entryPointOrThunkToEmbed != NULL)
1892 pResult->accessType = IAT_VALUE;
1893 pResult->addr = entryPointOrThunkToEmbed;
1897 ZapImport * pImport = m_pImage->GetImportTable()->GetFunctionEntryImport(ftn);
1898 AppendConditionalImport(pImport);
1900 // Tell the JIT to use an indirections
1901 pResult->accessType = IAT_PVALUE;
1902 pResult->addr = pImport;
1906 void ZapInfo::getFunctionFixedEntryPoint(CORINFO_METHOD_HANDLE ftn,
1907 CORINFO_CONST_LOOKUP * pResult)
1911 m_pImage->m_pPreloader->AddMethodToTransitiveClosureOfInstantiations(ftn);
1913 // We can only embed entrypoints from the module being NGened since we do not support mapping of external
1914 // import thunks to MethodDesc. It should be ok since the delegate targets are typically from the same module.
1915 void * entryPointToEmbed = embedDirectCall(ftn, CORINFO_ACCESS_ANY, FALSE);
1917 if (entryPointToEmbed != NULL)
1919 pResult->accessType = IAT_VALUE;
1920 pResult->addr = entryPointToEmbed;
1924 ZapImport * pImport = m_pImage->GetImportTable()->GetFunctionEntryImport(ftn);
1925 AppendConditionalImport(pImport);
1927 pResult->accessType = IAT_PVALUE;
1928 pResult->addr = pImport;
1932 void * ZapInfo::getMethodSync(CORINFO_METHOD_HANDLE ftn,
1933 void **ppIndirection)
1935 _ASSERTE(ppIndirection != NULL);
1937 CORINFO_CLASS_HANDLE classHandle = getMethodClass(ftn);
1939 ZapImport * pImport = m_pImage->GetImportTable()->GetSyncLockImport(classHandle);
1940 AppendConditionalImport(pImport);
1942 *ppIndirection = pImport;
1946 void * ZapInfo::getPInvokeUnmanagedTarget(CORINFO_METHOD_HANDLE method, void **ppIndirection)
1948 // We will never be able to return this directly in prejit mode.
1949 _ASSERTE(ppIndirection != NULL);
1951 *ppIndirection = NULL;
1955 void * ZapInfo::getAddressOfPInvokeFixup(CORINFO_METHOD_HANDLE method,void **ppIndirection)
1957 _ASSERTE(ppIndirection != NULL);
1959 m_pImage->m_pPreloader->AddMethodToTransitiveClosureOfInstantiations(method);
1961 CORINFO_MODULE_HANDLE moduleHandle = m_pEECompileInfo->GetLoaderModuleForEmbeddableMethod(method);
1962 if (moduleHandle == m_pImage->m_hModule
1963 && m_pImage->m_pPreloader->CanEmbedMethodHandle(method, m_currentMethodHandle))
1965 *ppIndirection = NULL;
1966 return PVOID(m_pImage->GetWrappers()->GetAddrOfPInvokeFixup(method));
1970 // Note we could a fixup to a direct call site, rather than to
1971 // the indirection. This would saves us an extra indirection, but changes the
1972 // semantics slightly (so that the pinvoke will be bound when the calling
1973 // method is first run, not at the exact moment of the first pinvoke.)
1976 ZapImport * pImport = m_pImage->GetImportTable()->GetIndirectPInvokeTargetImport(method);
1977 AppendConditionalImport(pImport);
1979 *ppIndirection = pImport;
1983 void ZapInfo::getAddressOfPInvokeTarget(CORINFO_METHOD_HANDLE method, CORINFO_CONST_LOOKUP *pLookup)
1985 _ASSERTE(pLookup != NULL);
1987 void * pIndirection;
1988 void * pResult = getAddressOfPInvokeFixup(method, &pIndirection);
1989 if (pResult != NULL)
1991 pLookup->accessType = IAT_PVALUE;
1992 pLookup->addr = pResult;
1996 pLookup->accessType = IAT_PPVALUE;
1997 pLookup->addr = pIndirection;
2000 CORINFO_JUST_MY_CODE_HANDLE ZapInfo::getJustMyCodeHandle(
2001 CORINFO_METHOD_HANDLE method,
2002 CORINFO_JUST_MY_CODE_HANDLE **ppIndirection)
2004 _ASSERTE(ppIndirection != NULL);
2006 if (IsReadyToRunCompilation())
2008 *ppIndirection = NULL;
2012 *ppIndirection = (CORINFO_JUST_MY_CODE_HANDLE *)m_pImage->GetInnerPtr(m_pImage->m_pEEInfoTable,
2013 offsetof(CORCOMPILE_EE_INFO_TABLE, addrOfJMCFlag));
2017 ZapImport * ZapInfo::GetProfilingHandleImport()
2019 if (m_pProfilingHandle == NULL)
2021 ZapImport * pImport = m_pImage->GetImportTable()->GetProfilingHandleImport(m_currentMethodHandle);
2022 AppendImport(pImport);
2024 m_pProfilingHandle = pImport;
2027 return m_pProfilingHandle;
2030 void ZapInfo::GetProfilingHandle(BOOL *pbHookFunction,
2031 void **pProfilerHandle,
2032 BOOL *pbIndirectedHandles)
2035 // Return the location within the fixup table
2037 // Profiling handle is opaque token. It does not have to be aligned thus we can not store it in the same location as token.
2039 *pProfilerHandle = m_pImage->GetInnerPtr(GetProfilingHandleImport(), kZapProfilingHandleImportValueIndexClientData * sizeof(TADDR));
2041 // All functions get hooked in ngen /Profile
2042 *pbHookFunction = TRUE;
2045 // This is the NGEN case, where we always do indirection on the handle so we can fix it up at load time.
2047 *pbIndirectedHandles = TRUE;
2050 //return a callable stub that will do the virtual or interface call
2053 void ZapInfo::getCallInfo(CORINFO_RESOLVED_TOKEN * pResolvedToken,
2054 CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken,
2055 CORINFO_METHOD_HANDLE callerHandle,
2056 CORINFO_CALLINFO_FLAGS flags,
2057 CORINFO_CALL_INFO *pResult)
2059 void * pTarget = NULL;
2063 // Fill in the kind of the virtual call.
2064 // We set kindOnly=true since we don't want the EE to actually give us
2065 // a call stub - instead we want to generate an indirection ourselves.
2066 m_pEEJitInfo->getCallInfo(pResolvedToken,
2067 pConstrainedResolvedToken,
2070 * Addition of this flag.
2072 (CORINFO_CALLINFO_FLAGS)(flags | CORINFO_CALLINFO_KINDONLY),
2075 #ifdef FEATURE_READYTORUN_COMPILER
2076 if (IsReadyToRunCompilation())
2078 if (pResult->sig.isVarArg())
2080 m_zapper->Warning(W("ReadyToRun: VarArg methods not supported\n"));
2084 if (pResult->accessAllowed != CORINFO_ACCESS_ALLOWED)
2086 m_zapper->Warning(W("ReadyToRun: Runtime method access checks not supported\n"));
2090 if (pResult->methodFlags & CORINFO_FLG_SECURITYCHECK)
2092 m_zapper->Warning(W("ReadyToRun: Methods with security checks not supported\n"));
2096 if (GetCompileInfo()->IsNativeCallableMethod(pResult->hMethod))
2098 m_zapper->Warning(W("ReadyToRun: References to methods with NativeCallableAttribute not supported\n"));
2104 if (flags & CORINFO_CALLINFO_KINDONLY)
2107 if (IsReadyToRunCompilation())
2109 if (pResult->thisTransform == CORINFO_BOX_THIS)
2111 // READYTORUN: FUTURE: Optionally create boxing stub at runtime
2116 // OK, if the EE said we're not doing a stub dispatch then just return the kind to
2117 // the caller. No other kinds of virtual calls have extra information attached.
2118 switch (pResult->kind)
2120 case CORINFO_VIRTUALCALL_STUB:
2122 if (pResult->stubLookup.lookupKind.needsRuntimeLookup)
2124 if (!IsReadyToRunCompilation())
2125 embedGenericSignature(&pResult->stubLookup);
2129 #ifdef FEATURE_READYTORUN_COMPILER
2130 if (IsReadyToRunCompilation())
2132 ZapImport * pImport = m_pImage->GetImportTable()->GetStubDispatchCell(pResolvedToken);
2134 pResult->stubLookup.constLookup.accessType = IAT_PVALUE;
2135 pResult->stubLookup.constLookup.addr = pImport;
2140 CORINFO_CLASS_HANDLE calleeOwner = pResolvedToken->hClass;
2141 CORINFO_METHOD_HANDLE callee = pResolvedToken->hMethod;
2142 _ASSERTE(callee == pResult->hMethod);
2145 // Create the indirection cell
2147 pTarget = m_pImage->GetImportTable()->GetStubDispatchCell(calleeOwner, callee);
2149 pResult->stubLookup.constLookup.accessType = IAT_PVALUE;
2151 pResult->stubLookup.constLookup.addr = pTarget;
2156 case CORINFO_CALL_CODE_POINTER:
2157 _ASSERTE(pResult->codePointerLookup.lookupKind.needsRuntimeLookup);
2158 if (!IsReadyToRunCompilation())
2159 embedGenericSignature(&pResult->codePointerLookup);
2161 // There is no easy way to detect method referenced via generic lookups in generated code.
2162 // Report this method reference unconditionally.
2163 m_pImage->m_pPreloader->MethodReferencedByCompiledCode(pResult->hMethod);
2167 #ifdef FEATURE_READYTORUN_COMPILER
2168 if (IsReadyToRunCompilation())
2170 // Constrained token is not interesting with this transforms
2171 if (pResult->thisTransform != CORINFO_NO_THIS_TRANSFORM)
2172 pConstrainedResolvedToken = NULL;
2174 ZapImport * pImport;
2176 if (flags & (CORINFO_CALLINFO_LDFTN | CORINFO_CALLINFO_ATYPICAL_CALLSITE))
2178 pImport = m_pImage->GetImportTable()->GetMethodImport(ENCODE_METHOD_ENTRY, pResult->hMethod, pResolvedToken, pConstrainedResolvedToken);
2180 AppendConditionalImport(pImport);
2184 pImport = m_pImage->GetImportTable()->GetExternalMethodCell(pResult->hMethod, pResolvedToken, pConstrainedResolvedToken);
2187 // READYTORUN: FUTURE: Direct calls if possible
2188 pResult->codePointerLookup.constLookup.accessType = IAT_PVALUE;
2189 pResult->codePointerLookup.constLookup.addr = pImport;
2194 case CORINFO_VIRTUALCALL_VTABLE:
2195 _ASSERTE(!IsReadyToRunCompilation());
2198 case CORINFO_VIRTUALCALL_LDVIRTFTN:
2199 #ifdef FEATURE_READYTORUN_COMPILER
2200 if (IsReadyToRunCompilation() && !pResult->exactContextNeedsRuntimeLookup)
2202 DWORD fAtypicalCallsite = (flags & CORINFO_CALLINFO_ATYPICAL_CALLSITE) ? CORINFO_HELP_READYTORUN_ATYPICAL_CALLSITE : 0;
2204 ZapImport * pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(
2205 (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_VIRTUAL_ENTRY | fAtypicalCallsite), pResult->hMethod, pResolvedToken);
2207 pResult->codePointerLookup.constLookup.accessType = IAT_PVALUE;
2208 pResult->codePointerLookup.constLookup.addr = pImport;
2210 _ASSERTE(!pResult->sig.hasTypeArg());
2214 // Include the declaring instantiation of virtual generic methods in the NGen image.
2215 m_pImage->m_pPreloader->AddMethodToTransitiveClosureOfInstantiations(pResult->hMethod);
2219 _ASSERTE(!"Unknown call type");
2223 #ifdef FEATURE_READYTORUN_COMPILER
2224 if (IsReadyToRunCompilation() && pResult->sig.hasTypeArg())
2226 if (pResult->exactContextNeedsRuntimeLookup)
2228 // Nothing to do... The generic handle lookup gets embedded in to the codegen
2229 // during the jitting of the call.
2230 // (Note: The generic lookup in R2R is performed by a call to a helper at runtime, not by
2231 // codegen emitted at crossgen time)
2235 ZapImport * pImport;
2236 if (((SIZE_T)pResult->contextHandle & CORINFO_CONTEXTFLAGS_MASK) == CORINFO_CONTEXTFLAGS_METHOD)
2238 CORINFO_METHOD_HANDLE exactMethodHandle = (CORINFO_METHOD_HANDLE)((SIZE_T)pResult->contextHandle & ~CORINFO_CONTEXTFLAGS_MASK);
2240 pImport = m_pImage->GetImportTable()->GetMethodImport(ENCODE_METHOD_DICTIONARY, exactMethodHandle,
2241 pResolvedToken, pConstrainedResolvedToken);
2245 pImport = m_pImage->GetImportTable()->GetClassImport(ENCODE_TYPE_DICTIONARY,
2246 (pConstrainedResolvedToken != NULL) ? pConstrainedResolvedToken : pResolvedToken);
2249 pResult->instParamLookup.accessType = IAT_PVALUE;
2250 pResult->instParamLookup.addr = pImport;
2252 AppendConditionalImport(pImport);
2257 BOOL ZapInfo::canAccessFamily(CORINFO_METHOD_HANDLE hCaller,
2258 CORINFO_CLASS_HANDLE hInstanceType)
2260 return m_pEEJitInfo->canAccessFamily(hCaller, hInstanceType);
2263 BOOL ZapInfo::isRIDClassDomainID (CORINFO_CLASS_HANDLE cls)
2265 return m_pEEJitInfo->isRIDClassDomainID(cls);
2269 unsigned ZapInfo::getClassDomainID (CORINFO_CLASS_HANDLE cls, void **ppIndirection)
2271 _ASSERTE(ppIndirection != NULL);
2273 m_pImage->m_pPreloader->AddTypeToTransitiveClosureOfInstantiations(cls);
2275 if (!m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE))
2277 if (isRIDClassDomainID(cls))
2279 // Token is invariant to loading order, so we can go ahead and use it
2281 // Ensure that 'cls' gets added to CORCOMPILE_LOAD_TABLE, unless
2282 // someone else adds some other type of fixup for 'cls'.
2283 m_ClassLoadTable.Load(cls, FALSE);
2285 return m_pEEJitInfo->getClassDomainID(cls, ppIndirection);
2288 if (m_pImage->m_pPreloader->CanEmbedClassID(cls))
2290 // Ensure that 'cls' gets added to CORCOMPILE_LOAD_TABLE, unless
2291 // someone else adds some other type of fixup for 'cls'.
2292 m_ClassLoadTable.Load(cls, FALSE);
2293 return m_pEEJitInfo->getClassDomainID(cls, ppIndirection);
2297 // We will have to insert a fixup
2298 ZapImport * pImport = m_pImage->GetImportTable()->GetClassDomainIdImport(cls);
2299 AppendConditionalImport(pImport);
2301 *ppIndirection = pImport;
2305 void * ZapInfo::getFieldAddress(CORINFO_FIELD_HANDLE field, void **ppIndirection)
2307 _ASSERTE(ppIndirection != NULL);
2309 CORINFO_CLASS_HANDLE hClass = m_pEEJitInfo->getFieldClass(field);
2311 m_pImage->m_pPreloader->AddTypeToTransitiveClosureOfInstantiations(hClass);
2313 ZapImport * pImport = m_pImage->GetImportTable()->GetStaticFieldAddressImport(field);
2314 AppendConditionalImport(pImport);
2316 // Field address is not aligned thus we can not store it in the same location as token.
2317 *ppIndirection = m_pImage->GetInnerPtr(pImport, sizeof(TADDR));
2322 DWORD ZapInfo::getFieldThreadLocalStoreID(CORINFO_FIELD_HANDLE field,
2323 void **ppIndirection)
2325 _ASSERTE(ppIndirection != NULL);
2327 *ppIndirection = m_pImage->GetInnerPtr(m_pImage->m_pEEInfoTable,
2328 offsetof(CORCOMPILE_EE_INFO_TABLE, rvaStaticTlsIndex));
2332 CORINFO_VARARGS_HANDLE ZapInfo::getVarArgsHandle(CORINFO_SIG_INFO *sig,
2333 void **ppIndirection)
2335 _ASSERTE(ppIndirection != NULL);
2337 // Zapper does not support embedding these as they are created dynamically
2339 if (sig->scope != m_pImage->m_hModule || sig->token == mdTokenNil)
2341 _ASSERTE(!"Don't have enough info to be able to create a sig token.");
2343 *ppIndirection = NULL;
2347 // @perf: If the sig cookie construction code actually will restore the value types in
2348 // the sig, we should call LoadClass on all of those types to avoid redundant
2351 ZapImport * pImport = m_pImage->GetImportTable()->GetVarArgImport(sig->scope, sig->token);
2352 AppendConditionalImport(pImport);
2354 *ppIndirection = pImport;
2358 bool ZapInfo::canGetVarArgsHandle(CORINFO_SIG_INFO *sig)
2360 // Zapper does not support embedding these as they are created dynamically
2361 if (sig->scope != m_pImage->m_hModule || sig->token == mdTokenNil)
2369 void ZapInfo::setOverride(ICorDynamicInfo *pOverride, CORINFO_METHOD_HANDLE currentMethod)
2374 void ZapInfo::addActiveDependency(CORINFO_MODULE_HANDLE moduleFrom, CORINFO_MODULE_HANDLE moduleTo)
2376 if (IsReadyToRunCompilation())
2379 _ASSERT(moduleFrom != moduleTo);
2381 if (m_pImage->m_pPreloader->CanSkipDependencyActivation(m_currentMethodHandle, moduleFrom, moduleTo))
2383 // No need to add dependency fixup since we will have an unconditional dependency
2386 else if (!GetCompileInfo()->IsInCurrentVersionBubble(moduleTo))
2391 ZapImport * pImport = m_pImage->GetImportTable()->GetActiveDependencyImport(moduleFrom, moduleTo);
2392 AppendImport(pImport);
2394 CORINFO_DEPENDENCY dep;
2395 dep.moduleFrom = moduleFrom;
2396 dep.moduleTo = moduleTo;
2402 ZapInfo::constructStringLiteral(CORINFO_MODULE_HANDLE tokenScope,
2403 unsigned metaTok, void **ppValue)
2405 if (m_pEECompileInfo->IsEmptyString(metaTok, tokenScope))
2407 return emptyStringLiteral(ppValue);
2410 ZapImport * pImport = m_pImage->GetImportTable()->GetStringHandleImport(tokenScope, metaTok);
2411 AppendConditionalImport(pImport);
2418 InfoAccessType ZapInfo::emptyStringLiteral(void **ppValue)
2420 #ifdef FEATURE_READYTORUN_COMPILER
2421 if (IsReadyToRunCompilation())
2423 ZapImport * pImport = m_pImage->GetImportTable()->GetStringHandleImport(m_pImage->m_hModule, mdtString);
2429 *ppValue = m_pImage->GetInnerPtr(m_pImage->m_pEEInfoTable,
2430 offsetof(CORCOMPILE_EE_INFO_TABLE, emptyString));
2435 void ZapInfo::recordCallSite(ULONG instrOffset, CORINFO_SIG_INFO *callSig, CORINFO_METHOD_HANDLE methodHandle)
2440 void ZapInfo::recordRelocation(void *location, void *target,
2441 WORD fRelocType, WORD slotNum, INT32 addlDelta)
2443 // Factor slotNum into the location address
2446 case IMAGE_REL_BASED_ABSOLUTE:
2447 case IMAGE_REL_BASED_PTR:
2448 #if defined(_TARGET_X86_) || defined(_TARGET_AMD64_)
2449 case IMAGE_REL_BASED_REL32:
2450 #endif // _TARGET_X86_ || _TARGET_AMD64_
2451 location = (PBYTE)location + slotNum;
2454 #if defined(_TARGET_ARM_)
2455 case IMAGE_REL_BASED_THUMB_MOV32:
2456 case IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL:
2457 case IMAGE_REL_BASED_THUMB_BRANCH24:
2461 CORJIT_FLAGS jitFlags = m_zapper->m_pOpt->m_compilerFlags;
2463 if (jitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_RELATIVE_CODE_RELOCS))
2465 _ASSERTE(fRelocType == IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL
2466 || fRelocType == IMAGE_REL_BASED_THUMB_BRANCH24);
2470 _ASSERTE(fRelocType == IMAGE_REL_BASED_THUMB_MOV32
2471 || fRelocType == IMAGE_REL_BASED_THUMB_BRANCH24);
2478 #if defined(_TARGET_ARM64_)
2479 case IMAGE_REL_ARM64_BRANCH26:
2480 case IMAGE_REL_ARM64_PAGEBASE_REL21:
2481 case IMAGE_REL_ARM64_PAGEOFFSET_12A:
2486 _ASSERTE(!"Unknown reloc type");
2490 ZapBlobWithRelocs * knownNodes[] =
2499 // The location of the relocation reported by the JIT has to fall into one of the code or data blobs
2504 ZapBlobWithRelocs * pSrcNode = NULL;
2505 for (size_t i = 0; i < _countof(knownNodes); i++)
2507 ZapBlobWithRelocs * pNode = knownNodes[i];
2511 if (pNode->GetData() <= location && location < pNode->GetData() + pNode->GetSize())
2517 PREFIX_ASSUME(pSrcNode != NULL);
2518 r.m_pNode = pSrcNode;
2519 r.m_offset = (DWORD)((PBYTE)location - (PBYTE)pSrcNode->GetData());
2522 // The target of the relocation reported by the JIT can be one of:
2523 // - Inner pointer into into one of the code or data blobs. We can detect this case by searching
2524 // through the blobs.
2525 // - Hardbound target. We can detect this case by searching through all hardbound assemblies.
2526 // - Otherwise, it has to be ZapNode *.
2529 ZapNode * pTargetNode = NULL;
2530 INT32 targetOffset = 0;
2531 for (size_t i = 0; i < _countof(knownNodes); i++)
2533 ZapBlobWithRelocs * pNode = knownNodes[i];
2537 if (pNode->GetData() <= target && target < pNode->GetData() + pNode->GetSize())
2539 pTargetNode = pNode;
2540 targetOffset = (INT32)((PBYTE)target - (PBYTE)pNode->GetData());
2545 if (pTargetNode != NULL)
2547 r.m_pTargetNode = pTargetNode;
2551 // Must be ZapNode otherwise
2552 pTargetNode = (ZapNode *)target;
2553 _ASSERTE(pTargetNode->GetType() != ZapNodeType_Unknown);
2554 r.m_pTargetNode = pTargetNode;
2557 r.m_type = (ZapRelocationType)fRelocType;
2561 case IMAGE_REL_BASED_ABSOLUTE:
2562 *(UNALIGNED DWORD *)location = (DWORD)targetOffset;
2565 case IMAGE_REL_BASED_PTR:
2566 *(UNALIGNED TADDR *)location = (TADDR)targetOffset;
2569 #if defined(_TARGET_X86_) || defined(_TARGET_AMD64_)
2570 case IMAGE_REL_BASED_REL32:
2571 *(UNALIGNED INT32 *)location = targetOffset + addlDelta;
2573 #endif // _TARGET_X86_ || _TARGET_AMD64_
2575 #if defined(_TARGET_ARM_)
2576 case IMAGE_REL_BASED_THUMB_MOV32:
2577 case IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL:
2578 PutThumb2Mov32((UINT16 *)location, targetOffset);
2581 case IMAGE_REL_BASED_THUMB_BRANCH24:
2582 if (!FitsInThumb2BlRel24(targetOffset))
2583 ThrowHR(COR_E_OVERFLOW);
2584 PutThumb2BlRel24((UINT16 *)location, targetOffset);
2588 #if defined(_TARGET_ARM64_)
2589 case IMAGE_REL_ARM64_BRANCH26:
2590 if (!FitsInRel28(targetOffset))
2591 ThrowHR(COR_E_OVERFLOW);
2592 PutArm64Rel28((UINT32 *)location, targetOffset);
2594 case IMAGE_REL_ARM64_PAGEBASE_REL21:
2595 if (!FitsInRel21(targetOffset))
2596 ThrowHR(COR_E_OVERFLOW);
2597 PutArm64Rel21((UINT32 *)location, targetOffset);
2600 case IMAGE_REL_ARM64_PAGEOFFSET_12A:
2601 if (!FitsInRel12(targetOffset))
2602 ThrowHR(COR_E_OVERFLOW);
2603 PutArm64Rel12((UINT32 *)location, targetOffset);
2608 _ASSERTE(!"Unknown reloc type");
2612 if (m_CodeRelocations.IsEmpty())
2614 SIZE_T totalCodeSize = m_pCode->GetSize() + ((m_pColdCode != NULL) ? m_pColdCode->GetSize() : 0);
2616 // Prealocate relocations (assume that every other pointer may need relocation)
2617 COUNT_T nEstimatedRelocations = (COUNT_T)(totalCodeSize / (2 * sizeof(TADDR)));
2618 if (nEstimatedRelocations > 1)
2619 m_CodeRelocations.Preallocate(nEstimatedRelocations);
2622 m_CodeRelocations.Append(r);
2625 WORD ZapInfo::getRelocTypeHint(void * target)
2627 #ifdef _TARGET_AMD64_
2628 // There should be no external pointers
2629 return IMAGE_REL_BASED_REL32;
2630 #elif defined(_TARGET_ARM_)
2631 // Use full 32-bit branch targets when retrying compilation on ARM
2632 if (m_zapper->m_pOpt->m_fNGenLastRetry)
2634 return IMAGE_REL_BASED_THUMB_BRANCH24;
2635 #elif defined(_TARGET_ARM64_)
2636 return IMAGE_REL_ARM64_BRANCH26;
2643 void ZapInfo::getModuleNativeEntryPointRange(void** pStart, void** pEnd)
2645 ULONG rvaStart, rvaEnd;
2647 // Initialize outparams to default range of (0,0).
2652 DWORD ZapInfo::getExpectedTargetArchitecture()
2654 return IMAGE_FILE_MACHINE_NATIVE;
2657 CORINFO_METHOD_HANDLE ZapInfo::GetDelegateCtor(CORINFO_METHOD_HANDLE methHnd,
2658 CORINFO_CLASS_HANDLE clsHnd,
2659 CORINFO_METHOD_HANDLE targetMethodHnd,
2660 DelegateCtorArgs * pCtorData)
2662 // For ReadyToRun, this optimization is done via ZapInfo::getReadyToRunDelegateCtorHelper
2663 if (IsReadyToRunCompilation())
2666 // forward the call to the standard GetDelegateCtor
2667 CORINFO_METHOD_HANDLE delegateCtor = m_pEEJitInfo->GetDelegateCtor(methHnd, clsHnd, targetMethodHnd, pCtorData);
2668 if (delegateCtor != methHnd)
2670 if (pCtorData->pArg4)
2672 // cannot optimize any secure delegate, give up
2673 delegateCtor = methHnd;
2675 else if (pCtorData->pArg3)
2677 pCtorData->pArg3 = m_pImage->GetWrappers()->GetStub(pCtorData->pArg3);
2680 return delegateCtor;
2683 void ZapInfo::MethodCompileComplete(
2684 CORINFO_METHOD_HANDLE methHnd)
2686 m_pEEJitInfo->MethodCompileComplete(methHnd);
2694 void ZapInfo::getEEInfo(CORINFO_EE_INFO *pEEInfoOut)
2696 m_pEEJitInfo->getEEInfo(pEEInfoOut);
2699 LPCWSTR ZapInfo::getJitTimeLogFilename()
2701 return m_pEEJitInfo->getJitTimeLogFilename();
2708 CORINFO_ARG_LIST_HANDLE ZapInfo::getArgNext(CORINFO_ARG_LIST_HANDLE args)
2710 return m_pEEJitInfo->getArgNext(args);
2713 CorInfoTypeWithMod ZapInfo::getArgType(CORINFO_SIG_INFO* sig,
2714 CORINFO_ARG_LIST_HANDLE args,
2715 CORINFO_CLASS_HANDLE *vcTypeRet)
2717 return m_pEEJitInfo->getArgType(sig, args, vcTypeRet);
2720 CORINFO_CLASS_HANDLE ZapInfo::getArgClass(CORINFO_SIG_INFO* sig,
2721 CORINFO_ARG_LIST_HANDLE args)
2723 return m_pEEJitInfo->getArgClass(sig, args);
2726 CorInfoType ZapInfo::getHFAType(CORINFO_CLASS_HANDLE hClass)
2728 return m_pEEJitInfo->getHFAType(hClass);
2735 void ZapInfo::getBoundaries(CORINFO_METHOD_HANDLE ftn, unsigned int *cILOffsets,
2736 DWORD **pILOffsets, ICorDebugInfo::BoundaryTypes *implicitBoundaries)
2738 m_pEEJitInfo->getBoundaries(ftn, cILOffsets, pILOffsets,
2739 implicitBoundaries);
2742 void ZapInfo::setBoundaries(CORINFO_METHOD_HANDLE ftn, ULONG32 cMap,
2743 ICorDebugInfo::OffsetMapping *pMap)
2745 _ASSERTE(ftn == m_currentMethodHandle);
2750 m_pOffsetMapping = pMap;
2751 m_iOffsetMapping = cMap;
2755 void ZapInfo::getVars(CORINFO_METHOD_HANDLE ftn,
2757 ICorDebugInfo::ILVarInfo **vars,
2760 m_pEEJitInfo->getVars(ftn, cVars, vars, extendOthers);
2763 void ZapInfo::setVars(CORINFO_METHOD_HANDLE ftn,
2765 ICorDebugInfo::NativeVarInfo * vars)
2767 _ASSERTE(ftn == m_currentMethodHandle);
2772 m_pNativeVarInfo = vars;
2773 m_iNativeVarInfo = cVars;
2778 void * ZapInfo::allocateArray(ULONG cBytes)
2780 return new BYTE[cBytes];
2783 void ZapInfo::freeArray(void *array)
2785 delete [] ((BYTE*) array);
2792 const char* ZapInfo::getFieldName(CORINFO_FIELD_HANDLE ftn, const char **moduleName)
2794 return m_pEEJitInfo->getFieldName(ftn, moduleName);
2797 CORINFO_CLASS_HANDLE ZapInfo::getFieldClass(CORINFO_FIELD_HANDLE field)
2799 return m_pEEJitInfo->getFieldClass(field);
2802 CorInfoType ZapInfo::getFieldType(CORINFO_FIELD_HANDLE field,
2803 CORINFO_CLASS_HANDLE *structType,
2804 CORINFO_CLASS_HANDLE memberParent)
2807 return m_pEEJitInfo->getFieldType(field, structType, memberParent);
2810 unsigned ZapInfo::getFieldOffset(CORINFO_FIELD_HANDLE field)
2812 return m_pEEJitInfo->getFieldOffset(field);
2815 bool ZapInfo::isWriteBarrierHelperRequired(
2816 CORINFO_FIELD_HANDLE field)
2818 return m_pEEJitInfo->isWriteBarrierHelperRequired(field);
2821 void ZapInfo::getFieldInfo (CORINFO_RESOLVED_TOKEN * pResolvedToken,
2822 CORINFO_METHOD_HANDLE callerHandle,
2823 CORINFO_ACCESS_FLAGS flags,
2824 CORINFO_FIELD_INFO *pResult)
2826 m_pEEJitInfo->getFieldInfo(pResolvedToken, callerHandle, flags, pResult);
2828 #ifdef FEATURE_READYTORUN_COMPILER
2829 CORINFO_EE_INFO eeInfo;
2830 m_pEEJitInfo->getEEInfo(&eeInfo);
2832 if (IsReadyToRunCompilation())
2834 if (pResult->accessAllowed != CORINFO_ACCESS_ALLOWED)
2836 m_zapper->Warning(W("ReadyToRun: Runtime field access checks not supported\n"));
2840 DWORD fAtypicalCallsite = (flags & CORINFO_ACCESS_ATYPICAL_CALLSITE) ? CORINFO_HELP_READYTORUN_ATYPICAL_CALLSITE : 0;
2842 switch (pResult->fieldAccessor)
2844 case CORINFO_FIELD_INSTANCE:
2846 DWORD dwBaseOffset = (DWORD)-1;
2847 CORCOMPILE_FIXUP_BLOB_KIND fixupKind = m_pImage->GetCompileInfo()->GetFieldBaseOffset(pResolvedToken->hClass, &dwBaseOffset);
2851 case ENCODE_FIELD_OFFSET:
2853 ZapImport * pImport = m_pImage->GetImportTable()->GetFieldImport(ENCODE_FIELD_OFFSET, pResolvedToken->hField, pResolvedToken);
2855 if (pResult->offset > eeInfo.maxUncheckedOffsetForNullObject / 2)
2857 m_zapper->Warning(W("ReadyToRun: Cross-module instance fields with large offsets not supported\n"));
2860 pResult->offset = 0;
2862 pResult->fieldAccessor = CORINFO_FIELD_INSTANCE_WITH_BASE;
2864 pResult->fieldLookup.accessType = IAT_PVALUE;
2865 pResult->fieldLookup.addr = pImport;
2867 AppendImport(pImport);
2871 case ENCODE_CHECK_FIELD_OFFSET:
2873 ZapImport * pImport = m_pImage->GetImportTable()->GetCheckFieldOffsetImport(pResolvedToken->hField, pResolvedToken, pResult->offset);
2874 AppendImport(pImport);
2878 case ENCODE_FIELD_BASE_OFFSET:
2880 ZapImport * pImport = m_pImage->GetImportTable()->GetClassImport(ENCODE_FIELD_BASE_OFFSET, pResolvedToken);
2882 if (pResult->offset > eeInfo.maxUncheckedOffsetForNullObject / 2)
2884 m_zapper->Warning(W("ReadyToRun: Large objects crossing module boundaries not supported\n"));
2887 _ASSERTE(pResult->offset >= dwBaseOffset);
2888 pResult->offset -= dwBaseOffset;
2890 pResult->fieldAccessor = CORINFO_FIELD_INSTANCE_WITH_BASE;
2892 pResult->fieldLookup.accessType = IAT_PVALUE;
2893 pResult->fieldLookup.addr = pImport;
2895 AppendImport(pImport);
2903 UNREACHABLE_MSG("Unexpected field base fixup");
2908 case CORINFO_FIELD_INSTANCE_HELPER:
2909 case CORINFO_FIELD_INSTANCE_ADDR_HELPER:
2910 m_zapper->Warning(W("ReadyToRun: Special instance fields not supported\n"));
2914 case CORINFO_FIELD_STATIC_SHARED_STATIC_HELPER:
2916 if (m_pImage->GetCompileInfo()->IsInCurrentVersionBubble(m_pEEJitInfo->getClassModule(pResolvedToken->hClass)))
2918 CORCOMPILE_FIXUP_BLOB_KIND kind;
2920 switch (pResult->helper)
2922 case CORINFO_HELP_GETSHARED_GCSTATIC_BASE:
2923 case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR:
2924 case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS:
2925 kind = ENCODE_STATIC_BASE_GC_HELPER;
2927 case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE:
2928 case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR:
2929 case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_DYNAMICCLASS:
2930 kind = ENCODE_STATIC_BASE_NONGC_HELPER;
2932 case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE:
2933 case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR:
2934 case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS:
2935 kind = ENCODE_THREAD_STATIC_BASE_GC_HELPER;
2937 case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE:
2938 case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR:
2939 case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_DYNAMICCLASS:
2940 kind = ENCODE_THREAD_STATIC_BASE_NONGC_HELPER;
2943 UNREACHABLE_MSG("Unexpected static helper");
2946 ZapImport * pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(
2947 (CORCOMPILE_FIXUP_BLOB_KIND)(kind | fAtypicalCallsite), pResolvedToken->hClass);
2949 pResult->fieldLookup.accessType = IAT_PVALUE;
2950 pResult->fieldLookup.addr = pImport;
2952 pResult->helper = CORINFO_HELP_READYTORUN_STATIC_BASE;
2956 ZapImport * pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(
2957 (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_FIELD_ADDRESS | fAtypicalCallsite), pResolvedToken->hField, pResolvedToken);
2959 pResult->fieldLookup.accessType = IAT_PVALUE;
2960 pResult->fieldLookup.addr = pImport;
2962 pResult->helper = CORINFO_HELP_READYTORUN_STATIC_BASE;
2964 pResult->offset = 0;
2965 pResult->fieldFlags &= ~CORINFO_FLG_FIELD_STATIC_IN_HEAP; // The dynamic helper takes care of the unboxing
2970 case CORINFO_FIELD_STATIC_GENERICS_STATIC_HELPER:
2972 // Nothing to do... The generic handle lookup gets embedded in to the codegen
2973 // during the jitting of the field lookup.
2974 // (Note: The generic lookup in R2R is performed by a call to a helper at runtime, not by
2975 // codegen emitted at crossgen time)
2976 // TODO: replace the call to the generic lookup helper and the call to the static helper function
2977 // with a single call to a R2R cell that performs:
2978 // 1) Generic handle lookup
2979 // 2) Computes the statics base address
2980 // 3) Generates a stub for subsequent lookups that includes dictionary access
2981 // (For perf reasons)
2985 case CORINFO_FIELD_STATIC_ADDRESS: // field at given address
2986 case CORINFO_FIELD_STATIC_RVA_ADDRESS: // RVA field at given address
2987 case CORINFO_FIELD_STATIC_ADDR_HELPER: // static field accessed using address-of helper (argument is FieldDesc *)
2988 case CORINFO_FIELD_STATIC_TLS:
2989 m_zapper->Warning(W("ReadyToRun: Rare kinds of static fields not supported\n"));
2993 case CORINFO_FIELD_INTRINSIC_ZERO:
2994 case CORINFO_FIELD_INTRINSIC_EMPTY_STRING:
2995 case CORINFO_FIELD_INTRINSIC_ISLITTLEENDIAN:
2999 UNREACHABLE_MSG("Unexpected field acccess type");
3002 #endif // FEATURE_READYTORUN_COMPILER
3005 bool ZapInfo::isFieldStatic(CORINFO_FIELD_HANDLE fldHnd)
3007 return m_pEEJitInfo->isFieldStatic(fldHnd);
3014 CorInfoType ZapInfo::asCorInfoType(CORINFO_CLASS_HANDLE cls)
3016 return m_pEEJitInfo->asCorInfoType(cls);
3019 const char* ZapInfo::getClassName(CORINFO_CLASS_HANDLE cls)
3021 return m_pEEJitInfo->getClassName(cls);
3024 const char* ZapInfo::getClassNameFromMetadata(CORINFO_CLASS_HANDLE cls, const char** namespaceName)
3026 return m_pEEJitInfo->getClassNameFromMetadata(cls, namespaceName);
3029 CORINFO_CLASS_HANDLE ZapInfo::getTypeInstantiationArgument(CORINFO_CLASS_HANDLE cls, unsigned index)
3031 return m_pEEJitInfo->getTypeInstantiationArgument(cls, index);
3034 const char* ZapInfo::getHelperName(CorInfoHelpFunc func)
3036 return m_pEEJitInfo->getHelperName(func);
3039 int ZapInfo::appendClassName(__deref_inout_ecount(*pnBufLen) WCHAR** ppBuf, int* pnBufLen,
3040 CORINFO_CLASS_HANDLE cls,
3045 return m_pEEJitInfo->appendClassName(ppBuf,pnBufLen,cls,fNamespace,fFullInst,fAssembly);
3048 BOOL ZapInfo::isValueClass(CORINFO_CLASS_HANDLE cls)
3050 return m_pEEJitInfo->isValueClass(cls);
3053 BOOL ZapInfo::canInlineTypeCheckWithObjectVTable (CORINFO_CLASS_HANDLE cls)
3055 return m_pEEJitInfo->canInlineTypeCheckWithObjectVTable(cls);
3058 DWORD ZapInfo::getClassAttribs(CORINFO_CLASS_HANDLE cls)
3060 return m_pEEJitInfo->getClassAttribs(cls);
3063 BOOL ZapInfo::isStructRequiringStackAllocRetBuf(CORINFO_CLASS_HANDLE cls)
3065 return m_pEEJitInfo->isStructRequiringStackAllocRetBuf(cls);
3068 CorInfoInitClassResult ZapInfo::initClass(
3069 CORINFO_FIELD_HANDLE field,
3070 CORINFO_METHOD_HANDLE method,
3071 CORINFO_CONTEXT_HANDLE context,
3074 return m_pEEJitInfo->initClass(field, method, context, speculative);
3077 void ZapInfo::classMustBeLoadedBeforeCodeIsRun(CORINFO_CLASS_HANDLE cls)
3079 // This adds an entry to the table of fixups. The table gets iterated later
3080 // to add entries to the delayed fixup list for the code being generated.
3081 m_ClassLoadTable.Load(cls, FALSE);
3084 CORINFO_METHOD_HANDLE ZapInfo::mapMethodDeclToMethodImpl(CORINFO_METHOD_HANDLE methHnd)
3086 return (CORINFO_METHOD_HANDLE)m_pEEJitInfo->mapMethodDeclToMethodImpl(methHnd);
3089 void ZapInfo::methodMustBeLoadedBeforeCodeIsRun(CORINFO_METHOD_HANDLE meth)
3091 // This adds an entry to the table of fixups. The table gets iterated later
3092 // to add entries to the delayed fixup list for the code being generated.
3093 m_MethodLoadTable.Load(meth, FALSE);
3096 CORINFO_CLASS_HANDLE ZapInfo::getBuiltinClass(CorInfoClassId classId)
3098 return m_pEEJitInfo->getBuiltinClass(classId);
3101 CorInfoType ZapInfo::getTypeForPrimitiveValueClass(CORINFO_CLASS_HANDLE cls)
3103 return m_pEEJitInfo->getTypeForPrimitiveValueClass(cls);
3106 CorInfoType ZapInfo::getTypeForPrimitiveNumericClass(CORINFO_CLASS_HANDLE cls)
3108 return m_pEEJitInfo->getTypeForPrimitiveNumericClass(cls);
3111 BOOL ZapInfo::canCast(CORINFO_CLASS_HANDLE child,
3112 CORINFO_CLASS_HANDLE parent)
3114 return m_pEEJitInfo->canCast(child, parent);
3117 BOOL ZapInfo::areTypesEquivalent(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2)
3119 return m_pEEJitInfo->areTypesEquivalent(cls1, cls2);
3122 TypeCompareState ZapInfo::compareTypesForCast(CORINFO_CLASS_HANDLE fromClass, CORINFO_CLASS_HANDLE toClass)
3124 return m_pEEJitInfo->compareTypesForCast(fromClass, toClass);
3127 TypeCompareState ZapInfo::compareTypesForEquality(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2)
3129 return m_pEEJitInfo->compareTypesForEquality(cls1, cls2);
3132 CORINFO_CLASS_HANDLE ZapInfo::mergeClasses(
3133 CORINFO_CLASS_HANDLE cls1,
3134 CORINFO_CLASS_HANDLE cls2)
3136 return m_pEEJitInfo->mergeClasses(cls1, cls2);
3139 BOOL ZapInfo::shouldEnforceCallvirtRestriction(
3140 CORINFO_MODULE_HANDLE scopeHnd)
3142 return m_zapper->m_pEEJitInfo->shouldEnforceCallvirtRestriction(scopeHnd);
3145 CORINFO_CLASS_HANDLE ZapInfo::getParentType (
3146 CORINFO_CLASS_HANDLE cls)
3148 return m_pEEJitInfo->getParentType(cls);
3151 CorInfoType ZapInfo::getChildType (
3152 CORINFO_CLASS_HANDLE clsHnd,
3153 CORINFO_CLASS_HANDLE *clsRet)
3155 return m_pEEJitInfo->getChildType(clsHnd, clsRet);
3158 BOOL ZapInfo::satisfiesClassConstraints(
3159 CORINFO_CLASS_HANDLE cls)
3161 return m_pEEJitInfo->satisfiesClassConstraints(cls);
3164 BOOL ZapInfo::isSDArray(CORINFO_CLASS_HANDLE cls)
3166 return m_pEEJitInfo->isSDArray(cls);
3169 unsigned ZapInfo::getArrayRank(CORINFO_CLASS_HANDLE cls)
3171 return m_pEEJitInfo->getArrayRank(cls);
3174 void * ZapInfo::getArrayInitializationData(CORINFO_FIELD_HANDLE field, DWORD size)
3176 if (m_pEEJitInfo->getClassModule(m_pEEJitInfo->getFieldClass(field)) != m_pImage->m_hModule)
3179 void * arrayData = m_pEEJitInfo->getArrayInitializationData(field, size);
3183 #ifdef FEATURE_READYTORUN_COMPILER
3184 if (IsReadyToRunCompilation())
3185 return m_pImage->m_pILMetaData->GetRVAField(arrayData);
3188 return (void *) m_pImage->GetWrappers()->GetGenericHandle(CORINFO_GENERIC_HANDLE(arrayData));
3191 CorInfoIsAccessAllowedResult ZapInfo::canAccessClass( CORINFO_RESOLVED_TOKEN * pResolvedToken,
3192 CORINFO_METHOD_HANDLE callerHandle,
3193 CORINFO_HELPER_DESC *throwHelper)
3195 CorInfoIsAccessAllowedResult ret = m_pEEJitInfo->canAccessClass(pResolvedToken, callerHandle, throwHelper);
3197 #ifdef FEATURE_READYTORUN_COMPILER
3198 if (ret != CORINFO_ACCESS_ALLOWED)
3200 m_zapper->Warning(W("ReadyToRun: Runtime access checks not supported\n"));
3209 CORINFO_MODULE_HANDLE ZapInfo::getClassModule(CORINFO_CLASS_HANDLE cls)
3211 return m_pEEJitInfo->getClassModule(cls);
3214 CORINFO_ASSEMBLY_HANDLE ZapInfo::getModuleAssembly(CORINFO_MODULE_HANDLE mod)
3216 return m_pEEJitInfo->getModuleAssembly(mod);
3219 const char* ZapInfo::getAssemblyName(CORINFO_ASSEMBLY_HANDLE assem)
3221 return m_pEEJitInfo->getAssemblyName(assem);
3224 void* ZapInfo::LongLifetimeMalloc(size_t sz)
3226 return m_pEEJitInfo->LongLifetimeMalloc(sz);
3229 void ZapInfo::LongLifetimeFree(void* obj)
3231 return m_pEEJitInfo->LongLifetimeFree(obj);
3234 size_t ZapInfo::getClassModuleIdForStatics(CORINFO_CLASS_HANDLE cls, CORINFO_MODULE_HANDLE *pModule, void **ppIndirection)
3236 if (IsReadyToRunCompilation())
3238 _ASSERTE(!"getClassModuleIdForStatics");
3242 _ASSERTE(ppIndirection != NULL);
3243 _ASSERTE(pModule == NULL);
3244 CORINFO_MODULE_HANDLE module;
3245 size_t moduleId = m_pEEJitInfo->getClassModuleIdForStatics(cls, &module, ppIndirection);
3246 CORINFO_MODULE_HANDLE pzmModule = m_pImage->m_pPreloader->GetPreferredZapModuleForClassHandle(cls);
3248 if (module == pzmModule)
3250 // Use the module for the moduleid lookup if we have to do so. This causes us to have fewer fixups than
3251 // if the fixups were exclusively based on the moduleforstatics lookup
3255 if (module == m_pImage->m_hModule)
3257 // If the handle is the module we are currently ngening, we use
3258 // an indirection to the slot where the module pointer gets
3259 // stored when the module gets reloaded.
3261 *ppIndirection = PVOID(m_pImage->GetWrappers()->GetModuleIDHandle(module));
3265 // Fall through to regular import
3269 // Use the class for the moduleid lookup. This causes us to generate a fixup for the ModuleForStatics explicitly.
3273 ZapImport * pImport = m_pImage->GetImportTable()->GetModuleDomainIdImport(module, cls);
3274 AppendConditionalImport(pImport);
3276 *ppIndirection = pImport;
3280 unsigned ZapInfo::getClassSize(CORINFO_CLASS_HANDLE cls)
3282 DWORD size = m_pEEJitInfo->getClassSize(cls);
3284 #ifdef FEATURE_READYTORUN_COMPILER
3285 if (IsReadyToRunCompilation())
3287 if (m_pEECompileInfo->NeedsTypeLayoutCheck(cls))
3289 ZapImport * pImport = m_pImage->GetImportTable()->GetCheckTypeLayoutImport(cls);
3290 AppendImport(pImport);
3292 m_ClassLoadTable.Load(cls, TRUE);
3300 unsigned ZapInfo::getClassAlignmentRequirement(CORINFO_CLASS_HANDLE cls, BOOL fDoubleAlignHint)
3302 return m_pEEJitInfo->getClassAlignmentRequirement(cls, fDoubleAlignHint);
3305 CORINFO_FIELD_HANDLE ZapInfo::getFieldInClass(CORINFO_CLASS_HANDLE clsHnd, INT num)
3307 return m_pEEJitInfo->getFieldInClass(clsHnd,num);
3310 mdMethodDef ZapInfo::getMethodDefFromMethod(CORINFO_METHOD_HANDLE hMethod)
3312 return m_pEEJitInfo->getMethodDefFromMethod(hMethod);
3315 BOOL ZapInfo::checkMethodModifier(CORINFO_METHOD_HANDLE hMethod, LPCSTR modifier, BOOL fOptional)
3317 return m_pEEJitInfo->checkMethodModifier(hMethod, modifier, fOptional);
3320 unsigned ZapInfo::getClassGClayout(CORINFO_CLASS_HANDLE cls, BYTE *gcPtrs)
3322 return m_pEEJitInfo->getClassGClayout(cls, gcPtrs);
3325 // returns the enregister info for a struct based on type of fields, alignment, etc..
3326 bool ZapInfo::getSystemVAmd64PassStructInRegisterDescriptor(
3327 /*IN*/ CORINFO_CLASS_HANDLE _structHnd,
3328 /*OUT*/ SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr)
3330 return m_pEEJitInfo->getSystemVAmd64PassStructInRegisterDescriptor(_structHnd, structPassInRegDescPtr);
3333 unsigned ZapInfo::getClassNumInstanceFields(CORINFO_CLASS_HANDLE cls)
3335 return m_pEEJitInfo->getClassNumInstanceFields(cls);
3339 CorInfoHelpFunc ZapInfo::getNewHelper(CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_METHOD_HANDLE callerHandle)
3341 if (IsReadyToRunCompilation())
3342 return CORINFO_HELP_NEWFAST;
3344 classMustBeLoadedBeforeCodeIsRun(pResolvedToken->hClass);
3345 return m_pEEJitInfo->getNewHelper(pResolvedToken, callerHandle);
3348 CorInfoHelpFunc ZapInfo::getSharedCCtorHelper(CORINFO_CLASS_HANDLE clsHnd)
3350 return m_pEEJitInfo->getSharedCCtorHelper(clsHnd);
3353 CorInfoHelpFunc ZapInfo::getSecurityPrologHelper(CORINFO_METHOD_HANDLE ftn)
3355 return m_pEEJitInfo->getSecurityPrologHelper(ftn);
3358 CORINFO_CLASS_HANDLE ZapInfo::getTypeForBox(CORINFO_CLASS_HANDLE cls)
3360 return m_pEEJitInfo->getTypeForBox(cls);
3363 CorInfoHelpFunc ZapInfo::getBoxHelper(CORINFO_CLASS_HANDLE cls)
3365 return m_pEEJitInfo->getBoxHelper(cls);
3368 CorInfoHelpFunc ZapInfo::getUnBoxHelper(CORINFO_CLASS_HANDLE cls)
3370 return m_pEEJitInfo->getUnBoxHelper(cls);
3373 CorInfoHelpFunc ZapInfo::getCastingHelper(CORINFO_RESOLVED_TOKEN * pResolvedToken, bool fThrowing)
3375 if (IsReadyToRunCompilation())
3376 return (fThrowing ? CORINFO_HELP_CHKCASTANY : CORINFO_HELP_ISINSTANCEOFANY);
3378 return m_pEEJitInfo->getCastingHelper(pResolvedToken, fThrowing);
3381 CorInfoHelpFunc ZapInfo::getNewArrHelper(CORINFO_CLASS_HANDLE arrayCls)
3383 if (IsReadyToRunCompilation())
3384 return CORINFO_HELP_NEWARR_1_R2R_DIRECT;
3386 return m_pEEJitInfo->getNewArrHelper(arrayCls);
3389 bool ZapInfo::getReadyToRunHelper(CORINFO_RESOLVED_TOKEN * pResolvedToken,
3390 CORINFO_LOOKUP_KIND * pGenericLookupKind,
3392 CORINFO_CONST_LOOKUP * pLookup)
3394 #ifdef FEATURE_READYTORUN_COMPILER
3395 _ASSERTE(IsReadyToRunCompilation());
3397 ZapImport * pImport = NULL;
3399 DWORD fAtypicalCallsite = (id & CORINFO_HELP_READYTORUN_ATYPICAL_CALLSITE);
3400 id = (CorInfoHelpFunc)(id & ~CORINFO_HELP_READYTORUN_ATYPICAL_CALLSITE);
3404 case CORINFO_HELP_READYTORUN_NEW:
3405 // Call CEEInfo::getNewHelper to validate the request (e.g., check for abstract class).
3406 m_pEEJitInfo->getNewHelper(pResolvedToken, m_currentMethodHandle);
3408 if ((getClassAttribs(pResolvedToken->hClass) & CORINFO_FLG_SHAREDINST) != 0)
3409 return false; // Requires runtime lookup.
3410 pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(
3411 (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_NEW_HELPER | fAtypicalCallsite), pResolvedToken->hClass);
3414 case CORINFO_HELP_READYTORUN_NEWARR_1:
3415 if ((getClassAttribs(pResolvedToken->hClass) & CORINFO_FLG_SHAREDINST) != 0)
3416 return false; // Requires runtime lookup.
3417 pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(
3418 (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_NEW_ARRAY_HELPER | fAtypicalCallsite), pResolvedToken->hClass);
3421 case CORINFO_HELP_READYTORUN_ISINSTANCEOF:
3422 if ((getClassAttribs(pResolvedToken->hClass) & CORINFO_FLG_SHAREDINST) != 0)
3423 return false; // Requires runtime lookup.
3424 pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(
3425 (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_ISINSTANCEOF_HELPER | fAtypicalCallsite), pResolvedToken->hClass);
3428 case CORINFO_HELP_READYTORUN_CHKCAST:
3429 if ((getClassAttribs(pResolvedToken->hClass) & CORINFO_FLG_SHAREDINST) != 0)
3430 return false; // Requires runtime lookup.
3431 pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(
3432 (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_CHKCAST_HELPER | fAtypicalCallsite), pResolvedToken->hClass);
3435 case CORINFO_HELP_READYTORUN_STATIC_BASE:
3436 if ((getClassAttribs(pResolvedToken->hClass) & CORINFO_FLG_SHAREDINST) != 0)
3437 return false; // Requires runtime lookup.
3438 if (m_pImage->GetCompileInfo()->IsInCurrentVersionBubble(m_pEEJitInfo->getClassModule(pResolvedToken->hClass)))
3440 pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(
3441 (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_CCTOR_TRIGGER | fAtypicalCallsite), pResolvedToken->hClass);
3445 // READYTORUN: FUTURE: Cross-module static cctor triggers
3446 m_zapper->Warning(W("ReadyToRun: Cross-module static cctor triggers not supported\n"));
3451 case CORINFO_HELP_READYTORUN_GENERIC_HANDLE:
3452 _ASSERTE(pGenericLookupKind != NULL && pGenericLookupKind->needsRuntimeLookup);
3453 if (pGenericLookupKind->runtimeLookupKind == CORINFO_LOOKUP_METHODPARAM)
3455 pImport = m_pImage->GetImportTable()->GetDictionaryLookupCell(
3456 (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_DICTIONARY_LOOKUP_METHOD | fAtypicalCallsite), pResolvedToken, pGenericLookupKind);
3458 else if (pGenericLookupKind->runtimeLookupKind == CORINFO_LOOKUP_THISOBJ)
3460 pImport = m_pImage->GetImportTable()->GetDictionaryLookupCell(
3461 (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_DICTIONARY_LOOKUP_THISOBJ | fAtypicalCallsite), pResolvedToken, pGenericLookupKind);
3465 _ASSERTE(pGenericLookupKind->runtimeLookupKind == CORINFO_LOOKUP_CLASSPARAM);
3466 pImport = m_pImage->GetImportTable()->GetDictionaryLookupCell(
3467 (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_DICTIONARY_LOOKUP_TYPE | fAtypicalCallsite), pResolvedToken, pGenericLookupKind);
3476 pLookup->accessType = IAT_PVALUE;
3477 pLookup->addr = pImport;
3484 void ZapInfo::getReadyToRunDelegateCtorHelper(
3485 CORINFO_RESOLVED_TOKEN * pTargetMethod,
3486 CORINFO_CLASS_HANDLE delegateType,
3487 CORINFO_LOOKUP * pLookup
3490 #ifdef FEATURE_READYTORUN_COMPILER
3491 _ASSERTE(IsReadyToRunCompilation());
3492 pLookup->lookupKind.needsRuntimeLookup = false;
3493 pLookup->constLookup.accessType = IAT_PVALUE;
3494 pLookup->constLookup.addr = m_pImage->GetImportTable()->GetDynamicHelperCell(
3495 (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_DELEGATE_CTOR), pTargetMethod->hMethod, pTargetMethod, delegateType);
3504 //-----------------------------------------------------------------------------
3505 void ZapInfo::resolveToken(CORINFO_RESOLVED_TOKEN * pResolvedToken)
3507 m_pEEJitInfo->resolveToken(pResolvedToken);
3510 //-----------------------------------------------------------------------------
3511 bool ZapInfo::tryResolveToken(CORINFO_RESOLVED_TOKEN * pResolvedToken)
3513 return m_pEEJitInfo->tryResolveToken(pResolvedToken);
3516 //-----------------------------------------------------------------------------
3517 void ZapInfo::findSig(CORINFO_MODULE_HANDLE tokenScope,
3519 CORINFO_CONTEXT_HANDLE tokenContext,
3520 CORINFO_SIG_INFO *sig)
3522 m_pEEJitInfo->findSig(tokenScope, sigTOK, tokenContext, sig);
3525 void ZapInfo::findCallSiteSig(CORINFO_MODULE_HANDLE tokenScope,
3527 CORINFO_CONTEXT_HANDLE tokenContext, CORINFO_SIG_INFO *sig)
3529 m_pEEJitInfo->findCallSiteSig(tokenScope, methTOK, tokenContext, sig);
3532 size_t ZapInfo::findNameOfToken(CORINFO_MODULE_HANDLE tokenScope,
3534 __out_ecount (FQNameCapacity) char * szFQName,
3535 size_t FQNameCapacity)
3537 return m_pEEJitInfo->findNameOfToken(tokenScope, token, szFQName, FQNameCapacity);
3540 CorInfoCanSkipVerificationResult ZapInfo::canSkipVerification (
3541 CORINFO_MODULE_HANDLE tokenScope)
3543 return m_pEEJitInfo->canSkipVerification(tokenScope);
3546 BOOL ZapInfo::isValidToken (
3547 CORINFO_MODULE_HANDLE tokenScope,
3550 return m_pEEJitInfo->isValidToken(tokenScope, token);
3553 BOOL ZapInfo::isValidStringRef (
3554 CORINFO_MODULE_HANDLE tokenScope,
3557 return m_pEEJitInfo->isValidStringRef(tokenScope, token);
3565 const char* ZapInfo::getMethodName(CORINFO_METHOD_HANDLE ftn, const char **moduleName)
3567 return m_pEEJitInfo->getMethodName(ftn, moduleName);
3570 const char* ZapInfo::getMethodNameFromMetadata(CORINFO_METHOD_HANDLE ftn, const char **className, const char** namespaceName)
3572 return m_pEEJitInfo->getMethodNameFromMetadata(ftn, className, namespaceName);
3575 unsigned ZapInfo::getMethodHash(CORINFO_METHOD_HANDLE ftn)
3577 return m_pEEJitInfo->getMethodHash(ftn);
3580 DWORD ZapInfo::getMethodAttribs(CORINFO_METHOD_HANDLE ftn)
3582 return m_pEEJitInfo->getMethodAttribs(ftn);
3585 void ZapInfo::setMethodAttribs(CORINFO_METHOD_HANDLE ftn, CorInfoMethodRuntimeFlags attribs)
3587 m_pEEJitInfo->setMethodAttribs(ftn, attribs);
3590 void ZapInfo::getMethodSig(CORINFO_METHOD_HANDLE ftn, CORINFO_SIG_INFO *sig,CORINFO_CLASS_HANDLE memberParent)
3592 m_pEEJitInfo->getMethodSig(ftn, sig, memberParent);
3595 bool ZapInfo::getMethodInfo(CORINFO_METHOD_HANDLE ftn,CORINFO_METHOD_INFO* info)
3597 bool result = m_pImage->m_pPreloader->GetMethodInfo(m_currentMethodToken, ftn, info);
3598 info->regionKind = m_pImage->GetCurrentRegionKind();
3602 CorInfoInline ZapInfo::canInline(CORINFO_METHOD_HANDLE caller,
3603 CORINFO_METHOD_HANDLE callee,
3604 DWORD* pRestrictions)
3606 return m_pEEJitInfo->canInline(caller, callee, pRestrictions);
3610 void ZapInfo::reportInliningDecision (CORINFO_METHOD_HANDLE inlinerHnd,
3611 CORINFO_METHOD_HANDLE inlineeHnd,
3612 CorInfoInline inlineResult,
3613 const char * reason)
3615 if (!dontInline(inlineResult) && inlineeHnd != NULL)
3617 // We deliberately report m_currentMethodHandle (not inlinerHnd) as inliner, because
3618 // if m_currentMethodHandle != inlinerHnd, it simply means that inlinerHnd is intermediate link
3619 // in inlining into m_currentMethodHandle, and we have no interest to track those intermediate links now.
3620 m_pImage->m_pPreloader->ReportInlining(m_currentMethodHandle, inlineeHnd);
3622 return m_pEEJitInfo->reportInliningDecision(inlinerHnd, inlineeHnd, inlineResult, reason);
3626 CorInfoInstantiationVerification ZapInfo::isInstantiationOfVerifiedGeneric(
3627 CORINFO_METHOD_HANDLE method)
3629 return m_pEEJitInfo->isInstantiationOfVerifiedGeneric(method);
3633 void ZapInfo::initConstraintsForVerification(CORINFO_METHOD_HANDLE method,
3634 BOOL *pfHasCircularClassConstraints,
3635 BOOL *pfHasCircularMethodConstraints)
3638 initConstraintsForVerification(method,pfHasCircularClassConstraints,pfHasCircularMethodConstraints);
3641 bool ZapInfo::canTailCall(CORINFO_METHOD_HANDLE caller,
3642 CORINFO_METHOD_HANDLE declaredCallee,
3643 CORINFO_METHOD_HANDLE exactCallee,
3646 #ifdef FEATURE_READYTORUN_COMPILER
3647 // READYTORUN: FUTURE: Delay load fixups for tailcalls
3648 if (IsReadyToRunCompilation())
3652 m_zapper->Warning(W("ReadyToRun: Explicit tailcalls not supported\n"));
3660 return m_pEEJitInfo->canTailCall(caller, declaredCallee, exactCallee, fIsTailPrefix);
3663 void ZapInfo::reportTailCallDecision(CORINFO_METHOD_HANDLE callerHnd,
3664 CORINFO_METHOD_HANDLE calleeHnd,
3666 CorInfoTailCall tailCallResult,
3667 const char * reason)
3669 return m_pEEJitInfo->reportTailCallDecision(callerHnd, calleeHnd, fIsTailPrefix, tailCallResult, reason);
3673 CorInfoCanSkipVerificationResult ZapInfo::canSkipMethodVerification (
3674 CORINFO_METHOD_HANDLE ftnHandle)
3676 // ILStubs are generated internally by the CLR. There is no need to
3677 // verify it, or any of its callees.
3678 if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB))
3679 return CORINFO_VERIFICATION_CAN_SKIP;
3681 CorInfoCanSkipVerificationResult canSkipVer =
3682 m_pEEJitInfo->canSkipMethodVerification(ftnHandle);
3684 if (canSkipVer == CORINFO_VERIFICATION_RUNTIME_CHECK)
3686 // Transparent code could be partial trust, but we don't know at NGEN time.
3687 // Since the JIT is not hardened against unverifiable/illegal code, tell it
3688 // to just not jit the method if it hits unverifiable code, rathern than
3689 // injecting a runtime callout and continuing trying to JIT the method.
3690 canSkipVer = CORINFO_VERIFICATION_DONT_JIT;
3696 void ZapInfo::getEHinfo(CORINFO_METHOD_HANDLE ftn,
3697 unsigned EHnumber, CORINFO_EH_CLAUSE* clause)
3699 m_pEEJitInfo->getEHinfo(ftn, EHnumber, clause);
3702 CORINFO_CLASS_HANDLE ZapInfo::getMethodClass(CORINFO_METHOD_HANDLE method)
3704 return m_pEEJitInfo->getMethodClass(method);
3707 CORINFO_MODULE_HANDLE ZapInfo::getMethodModule(CORINFO_METHOD_HANDLE method)
3709 return m_pEEJitInfo->getMethodModule(method);
3712 void ZapInfo::getMethodVTableOffset(CORINFO_METHOD_HANDLE method,
3713 unsigned * pOffsetOfIndirection,
3714 unsigned * pOffsetAfterIndirection,
3717 m_pEEJitInfo->getMethodVTableOffset(method, pOffsetOfIndirection, pOffsetAfterIndirection, isRelative);
3720 CORINFO_METHOD_HANDLE ZapInfo::resolveVirtualMethod(
3721 CORINFO_METHOD_HANDLE virtualMethod,
3722 CORINFO_CLASS_HANDLE implementingClass,
3723 CORINFO_CONTEXT_HANDLE ownerType)
3725 return m_pEEJitInfo->resolveVirtualMethod(virtualMethod, implementingClass, ownerType);
3728 CORINFO_METHOD_HANDLE ZapInfo::getUnboxedEntry(
3729 CORINFO_METHOD_HANDLE ftn,
3730 bool* requiresInstMethodTableArg)
3732 return m_pEEJitInfo->getUnboxedEntry(ftn, requiresInstMethodTableArg);
3735 CORINFO_CLASS_HANDLE ZapInfo::getDefaultEqualityComparerClass(
3736 CORINFO_CLASS_HANDLE elemType)
3738 return m_pEEJitInfo->getDefaultEqualityComparerClass(elemType);
3741 void ZapInfo::expandRawHandleIntrinsic(
3742 CORINFO_RESOLVED_TOKEN * pResolvedToken,
3743 CORINFO_GENERICHANDLE_RESULT * pResult)
3745 m_pEEJitInfo->expandRawHandleIntrinsic(pResolvedToken, pResult);
3748 CorInfoIntrinsics ZapInfo::getIntrinsicID(CORINFO_METHOD_HANDLE method,
3751 return m_pEEJitInfo->getIntrinsicID(method, pMustExpand);
3754 bool ZapInfo::isInSIMDModule(CORINFO_CLASS_HANDLE classHnd)
3756 return m_pEEJitInfo->isInSIMDModule(classHnd);
3759 CorInfoUnmanagedCallConv ZapInfo::getUnmanagedCallConv(CORINFO_METHOD_HANDLE method)
3761 return m_pEEJitInfo->getUnmanagedCallConv(method);
3764 BOOL ZapInfo::pInvokeMarshalingRequired(CORINFO_METHOD_HANDLE method,
3765 CORINFO_SIG_INFO* sig)
3767 // READYTORUN: FUTURE: P/Invoke
3768 if (IsReadyToRunCompilation())
3771 return m_pEEJitInfo->pInvokeMarshalingRequired(method, sig);
3774 LPVOID ZapInfo::GetCookieForPInvokeCalliSig(CORINFO_SIG_INFO* szMetaSig,
3775 void ** ppIndirection)
3777 return getVarArgsHandle(szMetaSig, ppIndirection);
3780 bool ZapInfo::canGetCookieForPInvokeCalliSig(CORINFO_SIG_INFO* szMetaSig)
3782 return canGetVarArgsHandle(szMetaSig);
3785 BOOL ZapInfo::satisfiesMethodConstraints(
3786 CORINFO_CLASS_HANDLE parent,
3787 CORINFO_METHOD_HANDLE method)
3789 return m_pEEJitInfo->satisfiesMethodConstraints(parent, method);
3793 BOOL ZapInfo::isCompatibleDelegate(
3794 CORINFO_CLASS_HANDLE objCls,
3795 CORINFO_CLASS_HANDLE methodParentCls,
3796 CORINFO_METHOD_HANDLE method,
3797 CORINFO_CLASS_HANDLE delegateCls,
3798 BOOL* pfIsOpenDelegate)
3800 return m_pEEJitInfo->isCompatibleDelegate(objCls, methodParentCls, method, delegateCls, pfIsOpenDelegate);
3807 HRESULT ZapInfo::GetErrorHRESULT(struct _EXCEPTION_POINTERS *pExceptionPointers)
3809 return m_pEEJitInfo->GetErrorHRESULT(pExceptionPointers);
3812 ULONG ZapInfo::GetErrorMessage(__in_ecount(bufferLength) LPWSTR buffer, ULONG bufferLength)
3814 return m_pEEJitInfo->GetErrorMessage(buffer, bufferLength);
3817 int ZapInfo::FilterException(struct _EXCEPTION_POINTERS *pExceptionPointers)
3819 // Continue unwinding if fatal error was hit.
3820 if (FAILED(g_hrFatalError))
3821 return EXCEPTION_CONTINUE_SEARCH;
3823 return m_pEEJitInfo->FilterException(pExceptionPointers);
3826 void ZapInfo::HandleException(struct _EXCEPTION_POINTERS *pExceptionPointers)
3828 m_pEEJitInfo->HandleException(pExceptionPointers);
3831 void ZapInfo::ThrowExceptionForJitResult(HRESULT result)
3833 m_pEEJitInfo->ThrowExceptionForJitResult(result);
3835 void ZapInfo::ThrowExceptionForHelper(const CORINFO_HELPER_DESC * throwHelper)
3837 m_pEEJitInfo->ThrowExceptionForHelper(throwHelper);
3840 template<> void LoadTable<CORINFO_CLASS_HANDLE>::EmitLoadFixups(CORINFO_METHOD_HANDLE currentMethodHandle, ZapInfo * pZapInfo)
3843 // Find all of our un-fixed entries, and emit a restore fixup for each of them.
3844 // Note that we don't need a restore fixups for prerestored classes.
3847 InlineSArray<LoadEntry, 4> unfixed;
3849 for (LoadEntryHashTable::Iterator i = m_entries.Begin(), end = m_entries.End(); i != end; i++)
3852 || m_pModule->m_pPreloader->CanPrerestoreEmbedClassHandle(i->handle)
3853 // @TODO: Skip transitive closure of currentMethodHandle (parents, instantiations, etc.)
3854 || m_pModule->GetJitInfo()->getMethodClass(currentMethodHandle) == i->handle)
3861 // Now clear the table.
3864 m_entries.RemoveAll();
3866 if (unfixed.IsEmpty())
3869 // Save the fixups in the order they got emited for determinism
3870 qsort(&unfixed[0], unfixed.GetCount(), sizeof(LoadEntry), LoadEntryCmp);
3872 for(COUNT_T j = 0; j < unfixed.GetCount(); j++)
3874 CORINFO_CLASS_HANDLE handle = unfixed[j].handle;
3875 m_pModule->m_pPreloader->AddTypeToTransitiveClosureOfInstantiations(handle);
3876 ZapImport * pImport = m_pModule->GetImportTable()->GetClassHandleImport(handle);
3877 pZapInfo->AppendImport(pImport);
3882 template<> void LoadTable<CORINFO_METHOD_HANDLE>::EmitLoadFixups(CORINFO_METHOD_HANDLE currentMethodHandle, ZapInfo * pZapInfo)
3885 // Find all of our un-fixed entries, and emit a restore fixup for each of them.
3886 // Note that we don't need a restore fixups for prerestored methods.
3889 InlineSArray<LoadEntry, 4> unfixed;
3891 for (LoadEntryHashTable::Iterator i = m_entries.Begin(), end = m_entries.End(); i != end; i++)
3894 || m_pModule->m_pPreloader->CanPrerestoreEmbedMethodHandle(i->handle)
3895 || currentMethodHandle == i->handle)
3902 // Now clear the table.
3905 m_entries.RemoveAll();
3907 if (unfixed.IsEmpty())
3910 // Save the fixups in the order they got emited for determinism
3911 qsort(&unfixed[0], unfixed.GetCount(), sizeof(LoadEntry), LoadEntryCmp);
3913 for(COUNT_T j = 0; j < unfixed.GetCount(); j++)
3915 CORINFO_METHOD_HANDLE handle = unfixed[j].handle;
3916 m_pModule->m_pPreloader->AddMethodToTransitiveClosureOfInstantiations(handle);
3917 ZapImport * pImport = m_pModule->GetImportTable()->GetMethodHandleImport(handle);
3918 pZapInfo->AppendImport(pImport);
3922 BOOL ZapInfo::CurrentMethodHasProfileData()
3924 WRAPPER_NO_CONTRACT;
3926 ICorJitInfo::ProfileBuffer * profileBuffer;
3927 return SUCCEEDED(getBBProfileData(m_currentMethodHandle, &size, &profileBuffer, NULL));