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)
1349 if (m_zapper->m_pOpt->m_legacyMode)
1354 if (level <= LL_INFO10)
1357 ss.VPrintf(fmt,args);
1358 GetSvcLogger()->Log(ss.GetUnicode(), LogLevel_Success);
1364 if (LoggingOn(LF_JIT, level))
1366 LogSpewValist(LF_JIT, level, (char*) fmt, args);
1378 DWORD ZapInfo::getThreadTLSIndex(void **ppIndirection)
1380 _ASSERTE(ppIndirection != NULL);
1382 *ppIndirection = NULL;
1386 const void * ZapInfo::getInlinedCallFrameVptr(void **ppIndirection)
1388 _ASSERTE(ppIndirection != NULL);
1390 *ppIndirection = m_pImage->GetInnerPtr(m_pImage->m_pEEInfoTable,
1391 offsetof(CORCOMPILE_EE_INFO_TABLE, inlinedCallFrameVptr));
1395 LONG * ZapInfo::getAddrOfCaptureThreadGlobal(void **ppIndirection)
1397 _ASSERTE(ppIndirection != NULL);
1399 *ppIndirection = (LONG *) m_pImage->GetInnerPtr(m_pImage->m_pEEInfoTable,
1400 offsetof(CORCOMPILE_EE_INFO_TABLE, addrOfCaptureThreadGlobal));
1404 // Get slow lazy string literal helper to use (CORINFO_HELP_STRCNS*).
1405 // Returns CORINFO_HELP_UNDEF if lazy string literal helper cannot be used.
1406 CorInfoHelpFunc ZapInfo::getLazyStringLiteralHelper(CORINFO_MODULE_HANDLE handle)
1408 if (handle == m_pImage->m_hModule)
1409 return CORINFO_HELP_STRCNS_CURRENT_MODULE;
1411 return CORINFO_HELP_STRCNS;
1414 CORINFO_MODULE_HANDLE ZapInfo::embedModuleHandle(CORINFO_MODULE_HANDLE handle,
1415 void **ppIndirection)
1417 _ASSERTE(ppIndirection != NULL);
1419 if (IsReadyToRunCompilation())
1421 _ASSERTE(!"embedModuleHandle");
1425 BOOL fHardbound = m_pImage->m_pPreloader->CanEmbedModuleHandle(handle);
1428 if (handle == m_pImage->m_hModule)
1430 // If the handle is the module we are currently ngening, we will
1431 // assume that Module is the very first thing in the preload section
1432 *ppIndirection = NULL;
1433 return (CORINFO_MODULE_HANDLE)m_pImage->m_pPreloadSections[CORCOMPILE_SECTION_MODULE];
1436 *ppIndirection = m_pImage->GetImportTable()->GetModuleHandleImport(handle);
1440 ZapImport * pImport = m_pImage->GetImportTable()->GetModuleHandleImport(handle);
1441 AppendConditionalImport(pImport);
1443 *ppIndirection = pImport;
1449 // The following functions indicate whether a handle can be directly embedded into
1450 // the code being compiled, or if it needs to be accessed with a (fixable) indirection.
1451 // Embeddable handles are those that will be persisted in the zap image.
1453 // These functions are gradually being all moved across to ceeload.cpp and compile.cpp.
1456 CORINFO_CLASS_HANDLE ZapInfo::embedClassHandle(CORINFO_CLASS_HANDLE handle,
1457 void **ppIndirection)
1459 _ASSERTE(ppIndirection != NULL);
1461 if (IsReadyToRunCompilation())
1463 _ASSERTE(!"embedClassHandle");
1467 m_pImage->m_pPreloader->AddTypeToTransitiveClosureOfInstantiations(handle);
1469 BOOL fHardbound = m_pImage->m_pPreloader->CanEmbedClassHandle(handle);
1472 CORINFO_MODULE_HANDLE moduleHandle = m_pEECompileInfo->GetLoaderModuleForEmbeddableType(handle);
1474 if (moduleHandle == m_pImage->m_hModule)
1476 // If the handle is the module we are currently ngening, we can
1477 // embed it after its resolved. So use a deferred reloc
1479 *ppIndirection = NULL;
1480 return CORINFO_CLASS_HANDLE(m_pImage->GetWrappers()->GetClassHandle(handle));
1483 *ppIndirection = m_pImage->GetImportTable()->GetClassHandleImport(handle);
1487 ZapImport * pImport = m_pImage->GetImportTable()->GetClassHandleImport(handle);
1488 AppendConditionalImport(pImport);
1490 *ppIndirection = pImport;
1495 CORINFO_FIELD_HANDLE ZapInfo::embedFieldHandle(CORINFO_FIELD_HANDLE handle,
1496 void **ppIndirection)
1498 _ASSERTE(ppIndirection != NULL);
1500 if (IsReadyToRunCompilation())
1502 _ASSERTE(!"embedFieldHandle");
1506 m_pImage->m_pPreloader->AddTypeToTransitiveClosureOfInstantiations(m_pEEJitInfo->getFieldClass(handle));
1508 BOOL fHardbound = m_pImage->m_pPreloader->CanEmbedFieldHandle(handle);
1511 CORINFO_MODULE_HANDLE moduleHandle = m_pEECompileInfo->GetLoaderModuleForEmbeddableField(handle);
1513 if (moduleHandle == m_pImage->m_hModule)
1515 // If the handle is the module we are currently ngening, we can
1516 // embed it after its resolved. So use a deferred reloc
1518 *ppIndirection = NULL;
1519 return CORINFO_FIELD_HANDLE(m_pImage->GetWrappers()->GetFieldHandle(handle));
1524 ZapImport * pImport = m_pImage->GetImportTable()->GetFieldHandleImport(handle);
1525 AppendConditionalImport(pImport);
1527 *ppIndirection = pImport;
1531 CORINFO_METHOD_HANDLE ZapInfo::embedMethodHandle(CORINFO_METHOD_HANDLE handle,
1532 void **ppIndirection)
1534 _ASSERTE(ppIndirection != NULL);
1536 if (IsReadyToRunCompilation())
1538 // READYTORUN FUTURE: Handle this case correctly
1542 CORINFO_MODULE_HANDLE moduleHandle = m_pEECompileInfo->GetLoaderModuleForEmbeddableMethod(handle);
1543 if (moduleHandle == m_pImage->m_hModule
1544 && m_pImage->m_pPreloader->CanEmbedMethodHandle(handle, m_currentMethodHandle))
1546 // If the handle is the module we are currently ngening, we can
1547 // embed it after its resolved. So use a deferred reloc
1549 *ppIndirection = NULL;
1550 return CORINFO_METHOD_HANDLE(m_pImage->GetWrappers()->GetMethodHandle(handle));
1553 ZapImport * pImport = m_pImage->GetImportTable()->GetMethodHandleImport(handle);
1554 AppendConditionalImport(pImport);
1556 *ppIndirection = pImport;
1560 CORINFO_CLASS_HANDLE ZapInfo::getTokenTypeAsHandle(CORINFO_RESOLVED_TOKEN * pResolvedToken)
1562 return m_pEEJitInfo->getTokenTypeAsHandle(pResolvedToken);
1566 ZapInfo::getLocationOfThisType(CORINFO_METHOD_HANDLE context)
1568 return m_pEEJitInfo->getLocationOfThisType(context);
1572 ZapInfo::embedGenericHandle(CORINFO_RESOLVED_TOKEN * pResolvedToken,
1574 CORINFO_GENERICHANDLE_RESULT *pResult)
1578 m_pEEJitInfo->embedGenericHandle( pResolvedToken,
1582 _ASSERTE(pResult->compileTimeHandle);
1584 if (pResult->lookup.lookupKind.needsRuntimeLookup)
1586 if (!IsReadyToRunCompilation())
1587 embedGenericSignature(&pResult->lookup);
1589 if (pResult->handleType == CORINFO_HANDLETYPE_METHOD)
1591 // There is no easy way to detect method referenced via generic lookups in generated code.
1592 // Report this method reference unconditionally.
1593 m_pImage->m_pPreloader->MethodReferencedByCompiledCode((CORINFO_METHOD_HANDLE)pResult->compileTimeHandle);
1598 void *pIndirection = 0;
1599 CORINFO_GENERIC_HANDLE handle = 0;
1601 switch (pResult->handleType)
1603 case CORINFO_HANDLETYPE_CLASS:
1604 if (IsReadyToRunCompilation())
1606 ZapImport * pImport = m_pImage->GetImportTable()->GetClassImport(ENCODE_TYPE_HANDLE, pResolvedToken);
1607 AppendConditionalImport(pImport);
1608 pIndirection = pImport;
1613 CORINFO_CLASS_HANDLE clsHnd = (CORINFO_CLASS_HANDLE) pResult->compileTimeHandle;
1614 handle = CORINFO_GENERIC_HANDLE(embedClassHandle(clsHnd, &pIndirection));
1618 case CORINFO_HANDLETYPE_METHOD:
1619 if (IsReadyToRunCompilation())
1621 ZapImport * pImport = m_pImage->GetImportTable()->GetMethodImport(ENCODE_METHOD_HANDLE, (CORINFO_METHOD_HANDLE)pResult->compileTimeHandle, pResolvedToken);
1622 AppendConditionalImport(pImport);
1623 pIndirection = pImport;
1628 CORINFO_METHOD_HANDLE methHnd = (CORINFO_METHOD_HANDLE) pResult->compileTimeHandle;
1629 handle = CORINFO_GENERIC_HANDLE(embedMethodHandle(methHnd, &pIndirection));
1633 case CORINFO_HANDLETYPE_FIELD:
1634 if (IsReadyToRunCompilation())
1636 ZapImport * pImport = m_pImage->GetImportTable()->GetFieldImport(ENCODE_FIELD_HANDLE, (CORINFO_FIELD_HANDLE)pResult->compileTimeHandle, pResolvedToken);
1637 AppendConditionalImport(pImport);
1638 pIndirection = pImport;
1643 CORINFO_FIELD_HANDLE fldHnd = (CORINFO_FIELD_HANDLE) pResult->compileTimeHandle;
1644 handle = CORINFO_GENERIC_HANDLE(embedFieldHandle(fldHnd, &pIndirection));
1649 ThrowHR(COR_E_BADIMAGEFORMAT, BFA_INVALID_TOKEN_TYPE);
1654 pResult->lookup.constLookup.accessType = IAT_VALUE;
1655 pResult->lookup.constLookup.handle = CORINFO_GENERIC_HANDLE(handle);
1659 pResult->lookup.constLookup.accessType = IAT_PVALUE;
1660 pResult->lookup.constLookup.addr = pIndirection;
1665 void ZapInfo::embedGenericSignature(CORINFO_LOOKUP * pLookup)
1667 _ASSERTE(pLookup->lookupKind.needsRuntimeLookup);
1669 if (IsReadyToRunCompilation())
1671 UNREACHABLE_MSG("We should never get here for the ReadyToRun compilation.");
1675 if (pLookup->runtimeLookup.signature != NULL)
1677 pLookup->runtimeLookup.signature = m_pImage->GetImportTable()->GetGenericSignature(
1678 pLookup->runtimeLookup.signature, pLookup->lookupKind.runtimeLookupKind == CORINFO_LOOKUP_METHODPARAM);
1682 void* ZapInfo::getTailCallCopyArgsThunk (
1683 CORINFO_SIG_INFO *pSig,
1684 CorInfoHelperTailCallSpecialHandling flags)
1686 void * pStub = m_pEEJitInfo->getTailCallCopyArgsThunk(pSig, flags);
1689 return m_pImage->GetWrappers()->GetStub(pStub);
1692 #ifdef FEATURE_READYTORUN_COMPILER
1693 ReadyToRunHelper MapReadyToRunHelper(CorInfoHelpFunc func, bool * pfOptimizeForSize)
1697 #define OPTIMIZEFORSIZE *pfOptimizeForSize = true;
1698 #define HELPER(readyToRunHelper, corInfoHelpFunc, flags) \
1699 case corInfoHelpFunc: flags return readyToRunHelper;
1700 #include "readytorunhelpers.h"
1702 case CORINFO_HELP_STRCNS_CURRENT_MODULE:
1703 *pfOptimizeForSize = true;
1704 return READYTORUN_HELPER_GetString;
1707 return READYTORUN_HELPER_Invalid;
1710 #endif // FEATURE_READYTORUN_COMPILER
1712 void * ZapInfo::getHelperFtn (CorInfoHelpFunc ftnNum, void **ppIndirection)
1714 _ASSERTE(ppIndirection != NULL);
1715 *ppIndirection = NULL;
1717 #ifdef FEATURE_READYTORUN_COMPILER
1718 if (IsReadyToRunCompilation())
1720 bool fOptimizeForSize = false;
1721 ReadyToRunHelper helperNum = MapReadyToRunHelper(ftnNum, &fOptimizeForSize);
1723 if (helperNum == READYTORUN_HELPER_Invalid)
1725 m_zapper->Warning(W("ReadyToRun: JIT helper not supported: %S\n"), m_pEEJitInfo->getHelperName(ftnNum));
1729 if (fOptimizeForSize)
1731 *ppIndirection = NULL;
1732 return m_pImage->GetImportTable()->GetIndirectHelperThunk(helperNum);
1736 *ppIndirection = m_pImage->GetImportTable()->GetHelperImport(helperNum);
1742 DWORD dwHelper = ftnNum;
1746 case CORINFO_HELP_PROF_FCN_ENTER:
1747 *ppIndirection = m_pImage->GetInnerPtr(GetProfilingHandleImport(), kZapProfilingHandleImportValueIndexEnterAddr * sizeof(TADDR));
1749 case CORINFO_HELP_PROF_FCN_LEAVE:
1750 *ppIndirection = m_pImage->GetInnerPtr(GetProfilingHandleImport(), kZapProfilingHandleImportValueIndexLeaveAddr * sizeof(TADDR));
1752 case CORINFO_HELP_PROF_FCN_TAILCALL:
1753 *ppIndirection = m_pImage->GetInnerPtr(GetProfilingHandleImport(), kZapProfilingHandleImportValueIndexTailcallAddr * sizeof(TADDR));
1755 #ifdef _TARGET_AMD64_
1756 case CORINFO_HELP_STOP_FOR_GC:
1757 // Force all calls in ngen images for this helper to use an indirect call.
1758 // We cannot use a jump stub to reach this helper because
1759 // the RAX register can contain a return value.
1760 dwHelper |= CORCOMPILE_HELPER_PTR;
1767 if (m_pImage->m_pHelperThunks[ftnNum] == NULL)
1769 ZapNode * pHelperThunk;
1770 if (ftnNum == CORINFO_HELP_STRCNS_CURRENT_MODULE)
1772 pHelperThunk = new (m_pImage->GetHeap()) ZapLazyHelperThunk(CORINFO_HELP_STRCNS);
1776 pHelperThunk = new (m_pImage->GetHeap()) ZapHelperThunk(dwHelper);
1778 #if defined(_TARGET_ARM_)
1779 if ((dwHelper & CORCOMPILE_HELPER_PTR) == 0)
1780 pHelperThunk = m_pImage->GetInnerPtr(pHelperThunk, THUMB_CODE);
1782 m_pImage->m_pHelperThunks[ftnNum] = pHelperThunk;
1785 void * ptr = m_pImage->m_pHelperThunks[ftnNum];
1787 if (dwHelper & CORCOMPILE_HELPER_PTR)
1789 *ppIndirection = ptr;
1796 ULONG ZapInfo::GetNumFixups()
1798 return m_Imports.GetCount();
1801 void ZapInfo::AppendConditionalImport(ZapImport * pImport)
1803 if (m_ImportSet.LookupPtr(pImport) != NULL)
1807 entry.pImport = pImport;
1808 entry.fConditional = true;
1809 m_ImportSet.Add(entry);
1812 void ZapInfo::AppendImport(ZapImport * pImport)
1814 const ImportEntry * pExistingEntry = m_ImportSet.LookupPtr(pImport);
1815 if (pExistingEntry != NULL)
1817 if (!pExistingEntry->fConditional)
1819 const_cast<ImportEntry *>(pExistingEntry)->fConditional = false;
1824 entry.pImport = pImport;
1825 entry.fConditional = false;
1826 m_ImportSet.Add(entry);
1829 m_Imports.Append(pImport);
1833 // This function indicates whether a method entry point be directly embedded into
1834 // the code being compiled, or if we can use a (fixable) cross module thunk.
1835 // If we can't use either of these then we return NULL and we will use an
1836 // (fixable) indirection cell to perform the call.
1838 PVOID ZapInfo::embedDirectCall(CORINFO_METHOD_HANDLE ftn,
1839 CORINFO_ACCESS_FLAGS accessFlags,
1842 if (!m_pImage->m_pPreloader->CanEmbedFunctionEntryPoint(ftn, m_currentMethodHandle, accessFlags))
1847 ZapNode * pEntryPointOrThunkToEmbed = NULL;
1850 // If it's in the same module then we can call it directly
1852 CORINFO_MODULE_HANDLE moduleHandle = m_pEECompileInfo->GetLoaderModuleForEmbeddableMethod(ftn);
1853 if (moduleHandle == m_pImage->m_hModule
1854 && m_pImage->m_pPreloader->CanEmbedMethodHandle(ftn, m_currentMethodHandle))
1856 pEntryPointOrThunkToEmbed = m_pImage->m_pMethodEntryPoints->GetMethodEntryPoint(ftn, accessFlags);
1858 else // otherwise we are calling into an external module
1865 pEntryPointOrThunkToEmbed = m_pImage->GetImportTable()->GetExternalMethodThunk(ftn);
1869 pEntryPointOrThunkToEmbed = m_pImage->GetInnerPtr(pEntryPointOrThunkToEmbed, THUMB_CODE);
1872 return pEntryPointOrThunkToEmbed;
1875 void ZapInfo::getFunctionEntryPoint(
1876 CORINFO_METHOD_HANDLE ftn, /* IN */
1877 CORINFO_CONST_LOOKUP * pResult, /* OUT */
1878 CORINFO_ACCESS_FLAGS accessFlags/*=CORINFO_ACCESS_ANY*/)
1880 if (IsReadyToRunCompilation())
1882 // READYTORUN: FUTURE: JIT still calls this for tail. and jmp instructions
1883 m_zapper->Warning(W("ReadyToRun: Method entrypoint cannot be encoded\n"));
1887 // Must deal with methods that are methodImpl'd within their own type.
1888 ftn = mapMethodDeclToMethodImpl(ftn);
1890 m_pImage->m_pPreloader->AddMethodToTransitiveClosureOfInstantiations(ftn);
1892 void * entryPointOrThunkToEmbed = embedDirectCall(ftn, accessFlags, TRUE);
1893 if (entryPointOrThunkToEmbed != NULL)
1895 pResult->accessType = IAT_VALUE;
1896 pResult->addr = entryPointOrThunkToEmbed;
1900 ZapImport * pImport = m_pImage->GetImportTable()->GetFunctionEntryImport(ftn);
1901 AppendConditionalImport(pImport);
1903 // Tell the JIT to use an indirections
1904 pResult->accessType = IAT_PVALUE;
1905 pResult->addr = pImport;
1909 void ZapInfo::getFunctionFixedEntryPoint(CORINFO_METHOD_HANDLE ftn,
1910 CORINFO_CONST_LOOKUP * pResult)
1914 m_pImage->m_pPreloader->AddMethodToTransitiveClosureOfInstantiations(ftn);
1916 // We can only embed entrypoints from the module being NGened since we do not support mapping of external
1917 // import thunks to MethodDesc. It should be ok since the delegate targets are typically from the same module.
1918 void * entryPointToEmbed = embedDirectCall(ftn, CORINFO_ACCESS_ANY, FALSE);
1920 if (entryPointToEmbed != NULL)
1922 pResult->accessType = IAT_VALUE;
1923 pResult->addr = entryPointToEmbed;
1927 ZapImport * pImport = m_pImage->GetImportTable()->GetFunctionEntryImport(ftn);
1928 AppendConditionalImport(pImport);
1930 pResult->accessType = IAT_PVALUE;
1931 pResult->addr = pImport;
1935 void * ZapInfo::getMethodSync(CORINFO_METHOD_HANDLE ftn,
1936 void **ppIndirection)
1938 _ASSERTE(ppIndirection != NULL);
1940 CORINFO_CLASS_HANDLE classHandle = getMethodClass(ftn);
1942 ZapImport * pImport = m_pImage->GetImportTable()->GetSyncLockImport(classHandle);
1943 AppendConditionalImport(pImport);
1945 *ppIndirection = pImport;
1949 void * ZapInfo::getPInvokeUnmanagedTarget(CORINFO_METHOD_HANDLE method, void **ppIndirection)
1951 // We will never be able to return this directly in prejit mode.
1952 _ASSERTE(ppIndirection != NULL);
1954 *ppIndirection = NULL;
1958 void * ZapInfo::getAddressOfPInvokeFixup(CORINFO_METHOD_HANDLE method,void **ppIndirection)
1960 _ASSERTE(ppIndirection != NULL);
1962 m_pImage->m_pPreloader->AddMethodToTransitiveClosureOfInstantiations(method);
1964 CORINFO_MODULE_HANDLE moduleHandle = m_pEECompileInfo->GetLoaderModuleForEmbeddableMethod(method);
1965 if (moduleHandle == m_pImage->m_hModule
1966 && m_pImage->m_pPreloader->CanEmbedMethodHandle(method, m_currentMethodHandle))
1968 *ppIndirection = NULL;
1969 return PVOID(m_pImage->GetWrappers()->GetAddrOfPInvokeFixup(method));
1973 // Note we could a fixup to a direct call site, rather than to
1974 // the indirection. This would saves us an extra indirection, but changes the
1975 // semantics slightly (so that the pinvoke will be bound when the calling
1976 // method is first run, not at the exact moment of the first pinvoke.)
1979 ZapImport * pImport = m_pImage->GetImportTable()->GetIndirectPInvokeTargetImport(method);
1980 AppendConditionalImport(pImport);
1982 *ppIndirection = pImport;
1986 void ZapInfo::getAddressOfPInvokeTarget(CORINFO_METHOD_HANDLE method, CORINFO_CONST_LOOKUP *pLookup)
1988 _ASSERTE(pLookup != NULL);
1990 void * pIndirection;
1991 void * pResult = getAddressOfPInvokeFixup(method, &pIndirection);
1992 if (pResult != NULL)
1994 pLookup->accessType = IAT_PVALUE;
1995 pLookup->addr = pResult;
1999 pLookup->accessType = IAT_PPVALUE;
2000 pLookup->addr = pIndirection;
2003 CORINFO_JUST_MY_CODE_HANDLE ZapInfo::getJustMyCodeHandle(
2004 CORINFO_METHOD_HANDLE method,
2005 CORINFO_JUST_MY_CODE_HANDLE **ppIndirection)
2007 _ASSERTE(ppIndirection != NULL);
2009 if (IsReadyToRunCompilation())
2011 *ppIndirection = NULL;
2015 *ppIndirection = (CORINFO_JUST_MY_CODE_HANDLE *)m_pImage->GetInnerPtr(m_pImage->m_pEEInfoTable,
2016 offsetof(CORCOMPILE_EE_INFO_TABLE, addrOfJMCFlag));
2020 ZapImport * ZapInfo::GetProfilingHandleImport()
2022 if (m_pProfilingHandle == NULL)
2024 ZapImport * pImport = m_pImage->GetImportTable()->GetProfilingHandleImport(m_currentMethodHandle);
2025 AppendImport(pImport);
2027 m_pProfilingHandle = pImport;
2030 return m_pProfilingHandle;
2033 void ZapInfo::GetProfilingHandle(BOOL *pbHookFunction,
2034 void **pProfilerHandle,
2035 BOOL *pbIndirectedHandles)
2038 // Return the location within the fixup table
2040 // Profiling handle is opaque token. It does not have to be aligned thus we can not store it in the same location as token.
2042 *pProfilerHandle = m_pImage->GetInnerPtr(GetProfilingHandleImport(), kZapProfilingHandleImportValueIndexClientData * sizeof(TADDR));
2044 // All functions get hooked in ngen /Profile
2045 *pbHookFunction = TRUE;
2048 // This is the NGEN case, where we always do indirection on the handle so we can fix it up at load time.
2050 *pbIndirectedHandles = TRUE;
2053 //return a callable stub that will do the virtual or interface call
2056 void ZapInfo::getCallInfo(CORINFO_RESOLVED_TOKEN * pResolvedToken,
2057 CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken,
2058 CORINFO_METHOD_HANDLE callerHandle,
2059 CORINFO_CALLINFO_FLAGS flags,
2060 CORINFO_CALL_INFO *pResult)
2062 void * pTarget = NULL;
2066 // Fill in the kind of the virtual call.
2067 // We set kindOnly=true since we don't want the EE to actually give us
2068 // a call stub - instead we want to generate an indirection ourselves.
2069 m_pEEJitInfo->getCallInfo(pResolvedToken,
2070 pConstrainedResolvedToken,
2073 * Addition of this flag.
2075 (CORINFO_CALLINFO_FLAGS)(flags | CORINFO_CALLINFO_KINDONLY),
2078 #ifdef FEATURE_READYTORUN_COMPILER
2079 if (IsReadyToRunCompilation())
2081 if (pResult->sig.isVarArg())
2083 m_zapper->Warning(W("ReadyToRun: VarArg methods not supported\n"));
2087 if (pResult->accessAllowed != CORINFO_ACCESS_ALLOWED)
2089 m_zapper->Warning(W("ReadyToRun: Runtime method access checks not supported\n"));
2093 if (pResult->methodFlags & CORINFO_FLG_SECURITYCHECK)
2095 m_zapper->Warning(W("ReadyToRun: Methods with security checks not supported\n"));
2099 if (GetCompileInfo()->IsNativeCallableMethod(pResult->hMethod))
2101 m_zapper->Warning(W("ReadyToRun: References to methods with NativeCallableAttribute not supported\n"));
2107 if (flags & CORINFO_CALLINFO_KINDONLY)
2110 if (IsReadyToRunCompilation())
2112 if (pResult->thisTransform == CORINFO_BOX_THIS)
2114 // READYTORUN: FUTURE: Optionally create boxing stub at runtime
2119 // OK, if the EE said we're not doing a stub dispatch then just return the kind to
2120 // the caller. No other kinds of virtual calls have extra information attached.
2121 switch (pResult->kind)
2123 case CORINFO_VIRTUALCALL_STUB:
2125 if (pResult->stubLookup.lookupKind.needsRuntimeLookup)
2127 if (!IsReadyToRunCompilation())
2128 embedGenericSignature(&pResult->stubLookup);
2132 #ifdef FEATURE_READYTORUN_COMPILER
2133 if (IsReadyToRunCompilation())
2135 ZapImport * pImport = m_pImage->GetImportTable()->GetStubDispatchCell(pResolvedToken);
2137 pResult->stubLookup.constLookup.accessType = IAT_PVALUE;
2138 pResult->stubLookup.constLookup.addr = pImport;
2143 CORINFO_CLASS_HANDLE calleeOwner = pResolvedToken->hClass;
2144 CORINFO_METHOD_HANDLE callee = pResolvedToken->hMethod;
2145 _ASSERTE(callee == pResult->hMethod);
2148 // Create the indirection cell
2150 pTarget = m_pImage->GetImportTable()->GetStubDispatchCell(calleeOwner, callee);
2152 pResult->stubLookup.constLookup.accessType = IAT_PVALUE;
2154 pResult->stubLookup.constLookup.addr = pTarget;
2159 case CORINFO_CALL_CODE_POINTER:
2160 _ASSERTE(pResult->codePointerLookup.lookupKind.needsRuntimeLookup);
2161 if (!IsReadyToRunCompilation())
2162 embedGenericSignature(&pResult->codePointerLookup);
2164 // There is no easy way to detect method referenced via generic lookups in generated code.
2165 // Report this method reference unconditionally.
2166 m_pImage->m_pPreloader->MethodReferencedByCompiledCode(pResult->hMethod);
2170 #ifdef FEATURE_READYTORUN_COMPILER
2171 if (IsReadyToRunCompilation())
2173 // Constrained token is not interesting with this transforms
2174 if (pResult->thisTransform != CORINFO_NO_THIS_TRANSFORM)
2175 pConstrainedResolvedToken = NULL;
2177 ZapImport * pImport;
2179 if (flags & (CORINFO_CALLINFO_LDFTN | CORINFO_CALLINFO_ATYPICAL_CALLSITE))
2181 pImport = m_pImage->GetImportTable()->GetMethodImport(ENCODE_METHOD_ENTRY, pResult->hMethod, pResolvedToken, pConstrainedResolvedToken);
2183 AppendConditionalImport(pImport);
2187 pImport = m_pImage->GetImportTable()->GetExternalMethodCell(pResult->hMethod, pResolvedToken, pConstrainedResolvedToken);
2190 // READYTORUN: FUTURE: Direct calls if possible
2191 pResult->codePointerLookup.constLookup.accessType = IAT_PVALUE;
2192 pResult->codePointerLookup.constLookup.addr = pImport;
2197 case CORINFO_VIRTUALCALL_VTABLE:
2198 _ASSERTE(!IsReadyToRunCompilation());
2201 case CORINFO_VIRTUALCALL_LDVIRTFTN:
2202 #ifdef FEATURE_READYTORUN_COMPILER
2203 if (IsReadyToRunCompilation() && !pResult->exactContextNeedsRuntimeLookup)
2205 DWORD fAtypicalCallsite = (flags & CORINFO_CALLINFO_ATYPICAL_CALLSITE) ? CORINFO_HELP_READYTORUN_ATYPICAL_CALLSITE : 0;
2207 ZapImport * pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(
2208 (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_VIRTUAL_ENTRY | fAtypicalCallsite), pResult->hMethod, pResolvedToken);
2210 pResult->codePointerLookup.constLookup.accessType = IAT_PVALUE;
2211 pResult->codePointerLookup.constLookup.addr = pImport;
2213 _ASSERTE(!pResult->sig.hasTypeArg());
2217 // Include the declaring instantiation of virtual generic methods in the NGen image.
2218 m_pImage->m_pPreloader->AddMethodToTransitiveClosureOfInstantiations(pResult->hMethod);
2222 _ASSERTE(!"Unknown call type");
2226 #ifdef FEATURE_READYTORUN_COMPILER
2227 if (IsReadyToRunCompilation() && pResult->sig.hasTypeArg())
2229 if (pResult->exactContextNeedsRuntimeLookup)
2231 // Nothing to do... The generic handle lookup gets embedded in to the codegen
2232 // during the jitting of the call.
2233 // (Note: The generic lookup in R2R is performed by a call to a helper at runtime, not by
2234 // codegen emitted at crossgen time)
2238 ZapImport * pImport;
2239 if (((SIZE_T)pResult->contextHandle & CORINFO_CONTEXTFLAGS_MASK) == CORINFO_CONTEXTFLAGS_METHOD)
2241 CORINFO_METHOD_HANDLE exactMethodHandle = (CORINFO_METHOD_HANDLE)((SIZE_T)pResult->contextHandle & ~CORINFO_CONTEXTFLAGS_MASK);
2243 pImport = m_pImage->GetImportTable()->GetMethodImport(ENCODE_METHOD_DICTIONARY, exactMethodHandle,
2244 pResolvedToken, pConstrainedResolvedToken);
2248 pImport = m_pImage->GetImportTable()->GetClassImport(ENCODE_TYPE_DICTIONARY,
2249 (pConstrainedResolvedToken != NULL) ? pConstrainedResolvedToken : pResolvedToken);
2252 pResult->instParamLookup.accessType = IAT_PVALUE;
2253 pResult->instParamLookup.addr = pImport;
2255 AppendConditionalImport(pImport);
2260 BOOL ZapInfo::canAccessFamily(CORINFO_METHOD_HANDLE hCaller,
2261 CORINFO_CLASS_HANDLE hInstanceType)
2263 return m_pEEJitInfo->canAccessFamily(hCaller, hInstanceType);
2266 BOOL ZapInfo::isRIDClassDomainID (CORINFO_CLASS_HANDLE cls)
2268 return m_pEEJitInfo->isRIDClassDomainID(cls);
2272 unsigned ZapInfo::getClassDomainID (CORINFO_CLASS_HANDLE cls, void **ppIndirection)
2274 _ASSERTE(ppIndirection != NULL);
2276 m_pImage->m_pPreloader->AddTypeToTransitiveClosureOfInstantiations(cls);
2278 if (!m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE))
2280 if (isRIDClassDomainID(cls))
2282 // Token is invariant to loading order, so we can go ahead and use it
2284 // Ensure that 'cls' gets added to CORCOMPILE_LOAD_TABLE, unless
2285 // someone else adds some other type of fixup for 'cls'.
2286 m_ClassLoadTable.Load(cls, FALSE);
2288 return m_pEEJitInfo->getClassDomainID(cls, ppIndirection);
2291 if (m_pImage->m_pPreloader->CanEmbedClassID(cls))
2293 // Ensure that 'cls' gets added to CORCOMPILE_LOAD_TABLE, unless
2294 // someone else adds some other type of fixup for 'cls'.
2295 m_ClassLoadTable.Load(cls, FALSE);
2296 return m_pEEJitInfo->getClassDomainID(cls, ppIndirection);
2300 // We will have to insert a fixup
2301 ZapImport * pImport = m_pImage->GetImportTable()->GetClassDomainIdImport(cls);
2302 AppendConditionalImport(pImport);
2304 *ppIndirection = pImport;
2308 void * ZapInfo::getFieldAddress(CORINFO_FIELD_HANDLE field, void **ppIndirection)
2310 _ASSERTE(ppIndirection != NULL);
2312 CORINFO_CLASS_HANDLE hClass = m_pEEJitInfo->getFieldClass(field);
2314 m_pImage->m_pPreloader->AddTypeToTransitiveClosureOfInstantiations(hClass);
2316 ZapImport * pImport = m_pImage->GetImportTable()->GetStaticFieldAddressImport(field);
2317 AppendConditionalImport(pImport);
2319 // Field address is not aligned thus we can not store it in the same location as token.
2320 *ppIndirection = m_pImage->GetInnerPtr(pImport, sizeof(TADDR));
2325 DWORD ZapInfo::getFieldThreadLocalStoreID(CORINFO_FIELD_HANDLE field,
2326 void **ppIndirection)
2328 _ASSERTE(ppIndirection != NULL);
2330 *ppIndirection = m_pImage->GetInnerPtr(m_pImage->m_pEEInfoTable,
2331 offsetof(CORCOMPILE_EE_INFO_TABLE, rvaStaticTlsIndex));
2335 CORINFO_VARARGS_HANDLE ZapInfo::getVarArgsHandle(CORINFO_SIG_INFO *sig,
2336 void **ppIndirection)
2338 _ASSERTE(ppIndirection != NULL);
2340 // Zapper does not support embedding these as they are created dynamically
2342 if (sig->scope != m_pImage->m_hModule || sig->token == mdTokenNil)
2344 _ASSERTE(!"Don't have enough info to be able to create a sig token.");
2346 *ppIndirection = NULL;
2350 // @perf: If the sig cookie construction code actually will restore the value types in
2351 // the sig, we should call LoadClass on all of those types to avoid redundant
2354 ZapImport * pImport = m_pImage->GetImportTable()->GetVarArgImport(sig->scope, sig->token);
2355 AppendConditionalImport(pImport);
2357 *ppIndirection = pImport;
2361 bool ZapInfo::canGetVarArgsHandle(CORINFO_SIG_INFO *sig)
2363 // Zapper does not support embedding these as they are created dynamically
2364 if (sig->scope != m_pImage->m_hModule || sig->token == mdTokenNil)
2372 void ZapInfo::setOverride(ICorDynamicInfo *pOverride, CORINFO_METHOD_HANDLE currentMethod)
2377 void ZapInfo::addActiveDependency(CORINFO_MODULE_HANDLE moduleFrom, CORINFO_MODULE_HANDLE moduleTo)
2379 if (IsReadyToRunCompilation())
2382 _ASSERT(moduleFrom != moduleTo);
2384 if (m_pImage->m_pPreloader->CanSkipDependencyActivation(m_currentMethodHandle, moduleFrom, moduleTo))
2386 // No need to add dependency fixup since we will have an unconditional dependency
2389 else if (!GetCompileInfo()->IsInCurrentVersionBubble(moduleTo))
2394 ZapImport * pImport = m_pImage->GetImportTable()->GetActiveDependencyImport(moduleFrom, moduleTo);
2395 AppendImport(pImport);
2397 CORINFO_DEPENDENCY dep;
2398 dep.moduleFrom = moduleFrom;
2399 dep.moduleTo = moduleTo;
2405 ZapInfo::constructStringLiteral(CORINFO_MODULE_HANDLE tokenScope,
2406 unsigned metaTok, void **ppValue)
2408 if (m_pEECompileInfo->IsEmptyString(metaTok, tokenScope))
2410 return emptyStringLiteral(ppValue);
2413 ZapImport * pImport = m_pImage->GetImportTable()->GetStringHandleImport(tokenScope, metaTok);
2414 AppendConditionalImport(pImport);
2421 InfoAccessType ZapInfo::emptyStringLiteral(void **ppValue)
2423 #ifdef FEATURE_READYTORUN_COMPILER
2424 if (IsReadyToRunCompilation())
2426 ZapImport * pImport = m_pImage->GetImportTable()->GetStringHandleImport(m_pImage->m_hModule, mdtString);
2432 *ppValue = m_pImage->GetInnerPtr(m_pImage->m_pEEInfoTable,
2433 offsetof(CORCOMPILE_EE_INFO_TABLE, emptyString));
2438 void ZapInfo::recordCallSite(ULONG instrOffset, CORINFO_SIG_INFO *callSig, CORINFO_METHOD_HANDLE methodHandle)
2443 void ZapInfo::recordRelocation(void *location, void *target,
2444 WORD fRelocType, WORD slotNum, INT32 addlDelta)
2446 // Factor slotNum into the location address
2449 case IMAGE_REL_BASED_ABSOLUTE:
2450 case IMAGE_REL_BASED_PTR:
2451 #if defined(_TARGET_X86_) || defined(_TARGET_AMD64_)
2452 case IMAGE_REL_BASED_REL32:
2453 #endif // _TARGET_X86_ || _TARGET_AMD64_
2454 location = (PBYTE)location + slotNum;
2457 #if defined(_TARGET_ARM_)
2458 case IMAGE_REL_BASED_THUMB_MOV32:
2459 case IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL:
2460 case IMAGE_REL_BASED_THUMB_BRANCH24:
2464 CORJIT_FLAGS jitFlags = m_zapper->m_pOpt->m_compilerFlags;
2466 if (jitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_RELATIVE_CODE_RELOCS))
2468 _ASSERTE(fRelocType == IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL
2469 || fRelocType == IMAGE_REL_BASED_THUMB_BRANCH24);
2473 _ASSERTE(fRelocType == IMAGE_REL_BASED_THUMB_MOV32
2474 || fRelocType == IMAGE_REL_BASED_THUMB_BRANCH24);
2481 #if defined(_TARGET_ARM64_)
2482 case IMAGE_REL_ARM64_BRANCH26:
2483 case IMAGE_REL_ARM64_PAGEBASE_REL21:
2484 case IMAGE_REL_ARM64_PAGEOFFSET_12A:
2489 _ASSERTE(!"Unknown reloc type");
2493 ZapBlobWithRelocs * knownNodes[] =
2502 // The location of the relocation reported by the JIT has to fall into one of the code or data blobs
2507 ZapBlobWithRelocs * pSrcNode = NULL;
2508 for (size_t i = 0; i < _countof(knownNodes); i++)
2510 ZapBlobWithRelocs * pNode = knownNodes[i];
2514 if (pNode->GetData() <= location && location < pNode->GetData() + pNode->GetSize())
2520 PREFIX_ASSUME(pSrcNode != NULL);
2521 r.m_pNode = pSrcNode;
2522 r.m_offset = (DWORD)((PBYTE)location - (PBYTE)pSrcNode->GetData());
2525 // The target of the relocation reported by the JIT can be one of:
2526 // - Inner pointer into into one of the code or data blobs. We can detect this case by searching
2527 // through the blobs.
2528 // - Hardbound target. We can detect this case by searching through all hardbound assemblies.
2529 // - Otherwise, it has to be ZapNode *.
2532 ZapNode * pTargetNode = NULL;
2533 INT32 targetOffset = 0;
2534 for (size_t i = 0; i < _countof(knownNodes); i++)
2536 ZapBlobWithRelocs * pNode = knownNodes[i];
2540 if (pNode->GetData() <= target && target < pNode->GetData() + pNode->GetSize())
2542 pTargetNode = pNode;
2543 targetOffset = (INT32)((PBYTE)target - (PBYTE)pNode->GetData());
2548 if (pTargetNode != NULL)
2550 r.m_pTargetNode = pTargetNode;
2554 // Must be ZapNode otherwise
2555 pTargetNode = (ZapNode *)target;
2556 _ASSERTE(pTargetNode->GetType() != ZapNodeType_Unknown);
2557 r.m_pTargetNode = pTargetNode;
2560 r.m_type = (ZapRelocationType)fRelocType;
2564 case IMAGE_REL_BASED_ABSOLUTE:
2565 *(UNALIGNED DWORD *)location = (DWORD)targetOffset;
2568 case IMAGE_REL_BASED_PTR:
2569 *(UNALIGNED TADDR *)location = (TADDR)targetOffset;
2572 #if defined(_TARGET_X86_) || defined(_TARGET_AMD64_)
2573 case IMAGE_REL_BASED_REL32:
2574 *(UNALIGNED INT32 *)location = targetOffset + addlDelta;
2576 #endif // _TARGET_X86_ || _TARGET_AMD64_
2578 #if defined(_TARGET_ARM_)
2579 case IMAGE_REL_BASED_THUMB_MOV32:
2580 case IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL:
2581 PutThumb2Mov32((UINT16 *)location, targetOffset);
2584 case IMAGE_REL_BASED_THUMB_BRANCH24:
2585 if (!FitsInThumb2BlRel24(targetOffset))
2586 ThrowHR(COR_E_OVERFLOW);
2587 PutThumb2BlRel24((UINT16 *)location, targetOffset);
2591 #if defined(_TARGET_ARM64_)
2592 case IMAGE_REL_ARM64_BRANCH26:
2593 if (!FitsInRel28(targetOffset))
2594 ThrowHR(COR_E_OVERFLOW);
2595 PutArm64Rel28((UINT32 *)location, targetOffset);
2597 case IMAGE_REL_ARM64_PAGEBASE_REL21:
2598 if (!FitsInRel21(targetOffset))
2599 ThrowHR(COR_E_OVERFLOW);
2600 PutArm64Rel21((UINT32 *)location, targetOffset);
2603 case IMAGE_REL_ARM64_PAGEOFFSET_12A:
2604 if (!FitsInRel12(targetOffset))
2605 ThrowHR(COR_E_OVERFLOW);
2606 PutArm64Rel12((UINT32 *)location, targetOffset);
2611 _ASSERTE(!"Unknown reloc type");
2615 if (m_CodeRelocations.IsEmpty())
2617 SIZE_T totalCodeSize = m_pCode->GetSize() + ((m_pColdCode != NULL) ? m_pColdCode->GetSize() : 0);
2619 // Prealocate relocations (assume that every other pointer may need relocation)
2620 COUNT_T nEstimatedRelocations = (COUNT_T)(totalCodeSize / (2 * sizeof(TADDR)));
2621 if (nEstimatedRelocations > 1)
2622 m_CodeRelocations.Preallocate(nEstimatedRelocations);
2625 m_CodeRelocations.Append(r);
2628 WORD ZapInfo::getRelocTypeHint(void * target)
2630 #ifdef _TARGET_AMD64_
2631 // There should be no external pointers
2632 return IMAGE_REL_BASED_REL32;
2633 #elif defined(_TARGET_ARM_)
2634 // Use full 32-bit branch targets when retrying compilation on ARM
2635 if (m_zapper->m_pOpt->m_fNGenLastRetry)
2637 return IMAGE_REL_BASED_THUMB_BRANCH24;
2638 #elif defined(_TARGET_ARM64_)
2639 return IMAGE_REL_ARM64_BRANCH26;
2646 void ZapInfo::getModuleNativeEntryPointRange(void** pStart, void** pEnd)
2648 ULONG rvaStart, rvaEnd;
2650 // Initialize outparams to default range of (0,0).
2655 DWORD ZapInfo::getExpectedTargetArchitecture()
2657 return IMAGE_FILE_MACHINE_NATIVE;
2660 CORINFO_METHOD_HANDLE ZapInfo::GetDelegateCtor(CORINFO_METHOD_HANDLE methHnd,
2661 CORINFO_CLASS_HANDLE clsHnd,
2662 CORINFO_METHOD_HANDLE targetMethodHnd,
2663 DelegateCtorArgs * pCtorData)
2665 // For ReadyToRun, this optimization is done via ZapInfo::getReadyToRunDelegateCtorHelper
2666 if (IsReadyToRunCompilation())
2669 // forward the call to the standard GetDelegateCtor
2670 CORINFO_METHOD_HANDLE delegateCtor = m_pEEJitInfo->GetDelegateCtor(methHnd, clsHnd, targetMethodHnd, pCtorData);
2671 if (delegateCtor != methHnd)
2673 if (pCtorData->pArg4)
2675 // cannot optimize any secure delegate, give up
2676 delegateCtor = methHnd;
2678 else if (pCtorData->pArg3)
2680 pCtorData->pArg3 = m_pImage->GetWrappers()->GetStub(pCtorData->pArg3);
2683 return delegateCtor;
2686 void ZapInfo::MethodCompileComplete(
2687 CORINFO_METHOD_HANDLE methHnd)
2689 m_pEEJitInfo->MethodCompileComplete(methHnd);
2697 void ZapInfo::getEEInfo(CORINFO_EE_INFO *pEEInfoOut)
2699 m_pEEJitInfo->getEEInfo(pEEInfoOut);
2702 LPCWSTR ZapInfo::getJitTimeLogFilename()
2704 return m_pEEJitInfo->getJitTimeLogFilename();
2711 CORINFO_ARG_LIST_HANDLE ZapInfo::getArgNext(CORINFO_ARG_LIST_HANDLE args)
2713 return m_pEEJitInfo->getArgNext(args);
2716 CorInfoTypeWithMod ZapInfo::getArgType(CORINFO_SIG_INFO* sig,
2717 CORINFO_ARG_LIST_HANDLE args,
2718 CORINFO_CLASS_HANDLE *vcTypeRet)
2720 return m_pEEJitInfo->getArgType(sig, args, vcTypeRet);
2723 CORINFO_CLASS_HANDLE ZapInfo::getArgClass(CORINFO_SIG_INFO* sig,
2724 CORINFO_ARG_LIST_HANDLE args)
2726 return m_pEEJitInfo->getArgClass(sig, args);
2729 CorInfoType ZapInfo::getHFAType(CORINFO_CLASS_HANDLE hClass)
2731 return m_pEEJitInfo->getHFAType(hClass);
2738 void ZapInfo::getBoundaries(CORINFO_METHOD_HANDLE ftn, unsigned int *cILOffsets,
2739 DWORD **pILOffsets, ICorDebugInfo::BoundaryTypes *implicitBoundaries)
2741 m_pEEJitInfo->getBoundaries(ftn, cILOffsets, pILOffsets,
2742 implicitBoundaries);
2745 void ZapInfo::setBoundaries(CORINFO_METHOD_HANDLE ftn, ULONG32 cMap,
2746 ICorDebugInfo::OffsetMapping *pMap)
2748 _ASSERTE(ftn == m_currentMethodHandle);
2753 m_pOffsetMapping = pMap;
2754 m_iOffsetMapping = cMap;
2758 void ZapInfo::getVars(CORINFO_METHOD_HANDLE ftn,
2760 ICorDebugInfo::ILVarInfo **vars,
2763 m_pEEJitInfo->getVars(ftn, cVars, vars, extendOthers);
2766 void ZapInfo::setVars(CORINFO_METHOD_HANDLE ftn,
2768 ICorDebugInfo::NativeVarInfo * vars)
2770 _ASSERTE(ftn == m_currentMethodHandle);
2775 m_pNativeVarInfo = vars;
2776 m_iNativeVarInfo = cVars;
2781 void * ZapInfo::allocateArray(ULONG cBytes)
2783 return new BYTE[cBytes];
2786 void ZapInfo::freeArray(void *array)
2788 delete [] ((BYTE*) array);
2795 const char* ZapInfo::getFieldName(CORINFO_FIELD_HANDLE ftn, const char **moduleName)
2797 return m_pEEJitInfo->getFieldName(ftn, moduleName);
2800 CORINFO_CLASS_HANDLE ZapInfo::getFieldClass(CORINFO_FIELD_HANDLE field)
2802 return m_pEEJitInfo->getFieldClass(field);
2805 CorInfoType ZapInfo::getFieldType(CORINFO_FIELD_HANDLE field,
2806 CORINFO_CLASS_HANDLE *structType,
2807 CORINFO_CLASS_HANDLE memberParent)
2810 return m_pEEJitInfo->getFieldType(field, structType, memberParent);
2813 unsigned ZapInfo::getFieldOffset(CORINFO_FIELD_HANDLE field)
2815 return m_pEEJitInfo->getFieldOffset(field);
2818 bool ZapInfo::isWriteBarrierHelperRequired(
2819 CORINFO_FIELD_HANDLE field)
2821 return m_pEEJitInfo->isWriteBarrierHelperRequired(field);
2824 void ZapInfo::getFieldInfo (CORINFO_RESOLVED_TOKEN * pResolvedToken,
2825 CORINFO_METHOD_HANDLE callerHandle,
2826 CORINFO_ACCESS_FLAGS flags,
2827 CORINFO_FIELD_INFO *pResult)
2829 m_pEEJitInfo->getFieldInfo(pResolvedToken, callerHandle, flags, pResult);
2831 #ifdef FEATURE_READYTORUN_COMPILER
2832 CORINFO_EE_INFO eeInfo;
2833 m_pEEJitInfo->getEEInfo(&eeInfo);
2835 if (IsReadyToRunCompilation())
2837 if (pResult->accessAllowed != CORINFO_ACCESS_ALLOWED)
2839 m_zapper->Warning(W("ReadyToRun: Runtime field access checks not supported\n"));
2843 DWORD fAtypicalCallsite = (flags & CORINFO_ACCESS_ATYPICAL_CALLSITE) ? CORINFO_HELP_READYTORUN_ATYPICAL_CALLSITE : 0;
2845 switch (pResult->fieldAccessor)
2847 case CORINFO_FIELD_INSTANCE:
2849 DWORD dwBaseOffset = (DWORD)-1;
2850 CORCOMPILE_FIXUP_BLOB_KIND fixupKind = m_pImage->GetCompileInfo()->GetFieldBaseOffset(pResolvedToken->hClass, &dwBaseOffset);
2854 case ENCODE_FIELD_OFFSET:
2856 ZapImport * pImport = m_pImage->GetImportTable()->GetFieldImport(ENCODE_FIELD_OFFSET, pResolvedToken->hField, pResolvedToken);
2858 if (pResult->offset > eeInfo.maxUncheckedOffsetForNullObject / 2)
2860 m_zapper->Warning(W("ReadyToRun: Cross-module instance fields with large offsets not supported\n"));
2863 pResult->offset = 0;
2865 pResult->fieldAccessor = CORINFO_FIELD_INSTANCE_WITH_BASE;
2867 pResult->fieldLookup.accessType = IAT_PVALUE;
2868 pResult->fieldLookup.addr = pImport;
2870 AppendImport(pImport);
2874 case ENCODE_CHECK_FIELD_OFFSET:
2876 ZapImport * pImport = m_pImage->GetImportTable()->GetCheckFieldOffsetImport(pResolvedToken->hField, pResolvedToken, pResult->offset);
2877 AppendImport(pImport);
2881 case ENCODE_FIELD_BASE_OFFSET:
2883 ZapImport * pImport = m_pImage->GetImportTable()->GetClassImport(ENCODE_FIELD_BASE_OFFSET, pResolvedToken);
2885 if (pResult->offset > eeInfo.maxUncheckedOffsetForNullObject / 2)
2887 m_zapper->Warning(W("ReadyToRun: Large objects crossing module boundaries not supported\n"));
2890 _ASSERTE(pResult->offset >= dwBaseOffset);
2891 pResult->offset -= dwBaseOffset;
2893 pResult->fieldAccessor = CORINFO_FIELD_INSTANCE_WITH_BASE;
2895 pResult->fieldLookup.accessType = IAT_PVALUE;
2896 pResult->fieldLookup.addr = pImport;
2898 AppendImport(pImport);
2906 UNREACHABLE_MSG("Unexpected field base fixup");
2911 case CORINFO_FIELD_INSTANCE_HELPER:
2912 case CORINFO_FIELD_INSTANCE_ADDR_HELPER:
2913 m_zapper->Warning(W("ReadyToRun: Special instance fields not supported\n"));
2917 case CORINFO_FIELD_STATIC_SHARED_STATIC_HELPER:
2919 if (m_pImage->GetCompileInfo()->IsInCurrentVersionBubble(m_pEEJitInfo->getClassModule(pResolvedToken->hClass)))
2921 CORCOMPILE_FIXUP_BLOB_KIND kind;
2923 switch (pResult->helper)
2925 case CORINFO_HELP_GETSHARED_GCSTATIC_BASE:
2926 case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR:
2927 case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS:
2928 kind = ENCODE_STATIC_BASE_GC_HELPER;
2930 case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE:
2931 case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR:
2932 case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_DYNAMICCLASS:
2933 kind = ENCODE_STATIC_BASE_NONGC_HELPER;
2935 case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE:
2936 case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR:
2937 case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS:
2938 kind = ENCODE_THREAD_STATIC_BASE_GC_HELPER;
2940 case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE:
2941 case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR:
2942 case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_DYNAMICCLASS:
2943 kind = ENCODE_THREAD_STATIC_BASE_NONGC_HELPER;
2946 UNREACHABLE_MSG("Unexpected static helper");
2949 ZapImport * pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(
2950 (CORCOMPILE_FIXUP_BLOB_KIND)(kind | fAtypicalCallsite), pResolvedToken->hClass);
2952 pResult->fieldLookup.accessType = IAT_PVALUE;
2953 pResult->fieldLookup.addr = pImport;
2955 pResult->helper = CORINFO_HELP_READYTORUN_STATIC_BASE;
2959 ZapImport * pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(
2960 (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_FIELD_ADDRESS | fAtypicalCallsite), pResolvedToken->hField, pResolvedToken);
2962 pResult->fieldLookup.accessType = IAT_PVALUE;
2963 pResult->fieldLookup.addr = pImport;
2965 pResult->helper = CORINFO_HELP_READYTORUN_STATIC_BASE;
2967 pResult->offset = 0;
2968 pResult->fieldFlags &= ~CORINFO_FLG_FIELD_STATIC_IN_HEAP; // The dynamic helper takes care of the unboxing
2973 case CORINFO_FIELD_STATIC_GENERICS_STATIC_HELPER:
2975 // Nothing to do... The generic handle lookup gets embedded in to the codegen
2976 // during the jitting of the field lookup.
2977 // (Note: The generic lookup in R2R is performed by a call to a helper at runtime, not by
2978 // codegen emitted at crossgen time)
2979 // TODO: replace the call to the generic lookup helper and the call to the static helper function
2980 // with a single call to a R2R cell that performs:
2981 // 1) Generic handle lookup
2982 // 2) Computes the statics base address
2983 // 3) Generates a stub for subsequent lookups that includes dictionary access
2984 // (For perf reasons)
2988 case CORINFO_FIELD_STATIC_ADDRESS: // field at given address
2989 case CORINFO_FIELD_STATIC_RVA_ADDRESS: // RVA field at given address
2990 case CORINFO_FIELD_STATIC_ADDR_HELPER: // static field accessed using address-of helper (argument is FieldDesc *)
2991 case CORINFO_FIELD_STATIC_TLS:
2992 m_zapper->Warning(W("ReadyToRun: Rare kinds of static fields not supported\n"));
2996 case CORINFO_FIELD_INTRINSIC_ZERO:
2997 case CORINFO_FIELD_INTRINSIC_EMPTY_STRING:
2998 case CORINFO_FIELD_INTRINSIC_ISLITTLEENDIAN:
3002 UNREACHABLE_MSG("Unexpected field acccess type");
3005 #endif // FEATURE_READYTORUN_COMPILER
3008 bool ZapInfo::isFieldStatic(CORINFO_FIELD_HANDLE fldHnd)
3010 return m_pEEJitInfo->isFieldStatic(fldHnd);
3017 CorInfoType ZapInfo::asCorInfoType(CORINFO_CLASS_HANDLE cls)
3019 return m_pEEJitInfo->asCorInfoType(cls);
3022 const char* ZapInfo::getClassName(CORINFO_CLASS_HANDLE cls)
3024 return m_pEEJitInfo->getClassName(cls);
3027 const char* ZapInfo::getHelperName(CorInfoHelpFunc func)
3029 return m_pEEJitInfo->getHelperName(func);
3032 int ZapInfo::appendClassName(__deref_inout_ecount(*pnBufLen) WCHAR** ppBuf, int* pnBufLen,
3033 CORINFO_CLASS_HANDLE cls,
3038 return m_pEEJitInfo->appendClassName(ppBuf,pnBufLen,cls,fNamespace,fFullInst,fAssembly);
3041 BOOL ZapInfo::isValueClass(CORINFO_CLASS_HANDLE cls)
3043 return m_pEEJitInfo->isValueClass(cls);
3046 BOOL ZapInfo::canInlineTypeCheckWithObjectVTable (CORINFO_CLASS_HANDLE cls)
3048 return m_pEEJitInfo->canInlineTypeCheckWithObjectVTable(cls);
3051 DWORD ZapInfo::getClassAttribs(CORINFO_CLASS_HANDLE cls)
3053 return m_pEEJitInfo->getClassAttribs(cls);
3056 BOOL ZapInfo::isStructRequiringStackAllocRetBuf(CORINFO_CLASS_HANDLE cls)
3058 return m_pEEJitInfo->isStructRequiringStackAllocRetBuf(cls);
3061 CorInfoInitClassResult ZapInfo::initClass(
3062 CORINFO_FIELD_HANDLE field,
3063 CORINFO_METHOD_HANDLE method,
3064 CORINFO_CONTEXT_HANDLE context,
3067 return m_pEEJitInfo->initClass(field, method, context, speculative);
3070 void ZapInfo::classMustBeLoadedBeforeCodeIsRun(CORINFO_CLASS_HANDLE cls)
3072 // This adds an entry to the table of fixups. The table gets iterated later
3073 // to add entries to the delayed fixup list for the code being generated.
3074 m_ClassLoadTable.Load(cls, FALSE);
3077 CORINFO_METHOD_HANDLE ZapInfo::mapMethodDeclToMethodImpl(CORINFO_METHOD_HANDLE methHnd)
3079 return (CORINFO_METHOD_HANDLE)m_pEEJitInfo->mapMethodDeclToMethodImpl(methHnd);
3082 void ZapInfo::methodMustBeLoadedBeforeCodeIsRun(CORINFO_METHOD_HANDLE meth)
3084 // This adds an entry to the table of fixups. The table gets iterated later
3085 // to add entries to the delayed fixup list for the code being generated.
3086 m_MethodLoadTable.Load(meth, FALSE);
3089 CORINFO_CLASS_HANDLE ZapInfo::getBuiltinClass(CorInfoClassId classId)
3091 return m_pEEJitInfo->getBuiltinClass(classId);
3094 CorInfoType ZapInfo::getTypeForPrimitiveValueClass(CORINFO_CLASS_HANDLE cls)
3096 return m_pEEJitInfo->getTypeForPrimitiveValueClass(cls);
3099 BOOL ZapInfo::canCast(CORINFO_CLASS_HANDLE child,
3100 CORINFO_CLASS_HANDLE parent)
3102 return m_pEEJitInfo->canCast(child, parent);
3105 BOOL ZapInfo::areTypesEquivalent(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2)
3107 return m_pEEJitInfo->areTypesEquivalent(cls1, cls2);
3110 CORINFO_CLASS_HANDLE ZapInfo::mergeClasses(
3111 CORINFO_CLASS_HANDLE cls1,
3112 CORINFO_CLASS_HANDLE cls2)
3114 return m_pEEJitInfo->mergeClasses(cls1, cls2);
3117 BOOL ZapInfo::shouldEnforceCallvirtRestriction(
3118 CORINFO_MODULE_HANDLE scopeHnd)
3120 return m_zapper->m_pEEJitInfo->shouldEnforceCallvirtRestriction(scopeHnd);
3123 CORINFO_CLASS_HANDLE ZapInfo::getParentType (
3124 CORINFO_CLASS_HANDLE cls)
3126 return m_pEEJitInfo->getParentType(cls);
3129 CorInfoType ZapInfo::getChildType (
3130 CORINFO_CLASS_HANDLE clsHnd,
3131 CORINFO_CLASS_HANDLE *clsRet)
3133 return m_pEEJitInfo->getChildType(clsHnd, clsRet);
3136 BOOL ZapInfo::satisfiesClassConstraints(
3137 CORINFO_CLASS_HANDLE cls)
3139 return m_pEEJitInfo->satisfiesClassConstraints(cls);
3142 BOOL ZapInfo::isSDArray(CORINFO_CLASS_HANDLE cls)
3144 return m_pEEJitInfo->isSDArray(cls);
3147 unsigned ZapInfo::getArrayRank(CORINFO_CLASS_HANDLE cls)
3149 return m_pEEJitInfo->getArrayRank(cls);
3152 void * ZapInfo::getArrayInitializationData(CORINFO_FIELD_HANDLE field, DWORD size)
3154 if (m_pEEJitInfo->getClassModule(m_pEEJitInfo->getFieldClass(field)) != m_pImage->m_hModule)
3157 void * arrayData = m_pEEJitInfo->getArrayInitializationData(field, size);
3161 #ifdef FEATURE_READYTORUN_COMPILER
3162 if (IsReadyToRunCompilation())
3163 return m_pImage->m_pILMetaData->GetRVAField(arrayData);
3166 return (void *) m_pImage->GetWrappers()->GetGenericHandle(CORINFO_GENERIC_HANDLE(arrayData));
3169 CorInfoIsAccessAllowedResult ZapInfo::canAccessClass( CORINFO_RESOLVED_TOKEN * pResolvedToken,
3170 CORINFO_METHOD_HANDLE callerHandle,
3171 CORINFO_HELPER_DESC *throwHelper)
3173 CorInfoIsAccessAllowedResult ret = m_pEEJitInfo->canAccessClass(pResolvedToken, callerHandle, throwHelper);
3175 #ifdef FEATURE_READYTORUN_COMPILER
3176 if (ret != CORINFO_ACCESS_ALLOWED)
3178 m_zapper->Warning(W("ReadyToRun: Runtime access checks not supported\n"));
3187 CORINFO_MODULE_HANDLE ZapInfo::getClassModule(CORINFO_CLASS_HANDLE cls)
3189 return m_pEEJitInfo->getClassModule(cls);
3192 CORINFO_ASSEMBLY_HANDLE ZapInfo::getModuleAssembly(CORINFO_MODULE_HANDLE mod)
3194 return m_pEEJitInfo->getModuleAssembly(mod);
3197 const char* ZapInfo::getAssemblyName(CORINFO_ASSEMBLY_HANDLE assem)
3199 return m_pEEJitInfo->getAssemblyName(assem);
3202 void* ZapInfo::LongLifetimeMalloc(size_t sz)
3204 return m_pEEJitInfo->LongLifetimeMalloc(sz);
3207 void ZapInfo::LongLifetimeFree(void* obj)
3209 return m_pEEJitInfo->LongLifetimeFree(obj);
3212 size_t ZapInfo::getClassModuleIdForStatics(CORINFO_CLASS_HANDLE cls, CORINFO_MODULE_HANDLE *pModule, void **ppIndirection)
3214 if (IsReadyToRunCompilation())
3216 _ASSERTE(!"getClassModuleIdForStatics");
3220 _ASSERTE(ppIndirection != NULL);
3221 _ASSERTE(pModule == NULL);
3222 CORINFO_MODULE_HANDLE module;
3223 size_t moduleId = m_pEEJitInfo->getClassModuleIdForStatics(cls, &module, ppIndirection);
3224 CORINFO_MODULE_HANDLE pzmModule = m_pImage->m_pPreloader->GetPreferredZapModuleForClassHandle(cls);
3226 if (module == pzmModule)
3228 // Use the module for the moduleid lookup if we have to do so. This causes us to have fewer fixups than
3229 // if the fixups were exclusively based on the moduleforstatics lookup
3233 if (module == m_pImage->m_hModule)
3235 // If the handle is the module we are currently ngening, we use
3236 // an indirection to the slot where the module pointer gets
3237 // stored when the module gets reloaded.
3239 *ppIndirection = PVOID(m_pImage->GetWrappers()->GetModuleIDHandle(module));
3243 // Fall through to regular import
3247 // Use the class for the moduleid lookup. This causes us to generate a fixup for the ModuleForStatics explicitly.
3251 ZapImport * pImport = m_pImage->GetImportTable()->GetModuleDomainIdImport(module, cls);
3252 AppendConditionalImport(pImport);
3254 *ppIndirection = pImport;
3258 unsigned ZapInfo::getClassSize(CORINFO_CLASS_HANDLE cls)
3260 DWORD size = m_pEEJitInfo->getClassSize(cls);
3262 #ifdef FEATURE_READYTORUN_COMPILER
3263 if (IsReadyToRunCompilation())
3265 if (m_pEECompileInfo->NeedsTypeLayoutCheck(cls))
3267 ZapImport * pImport = m_pImage->GetImportTable()->GetCheckTypeLayoutImport(cls);
3268 AppendImport(pImport);
3270 m_ClassLoadTable.Load(cls, TRUE);
3278 unsigned ZapInfo::getClassAlignmentRequirement(CORINFO_CLASS_HANDLE cls, BOOL fDoubleAlignHint)
3280 return m_pEEJitInfo->getClassAlignmentRequirement(cls, fDoubleAlignHint);
3283 CORINFO_FIELD_HANDLE ZapInfo::getFieldInClass(CORINFO_CLASS_HANDLE clsHnd, INT num)
3285 return m_pEEJitInfo->getFieldInClass(clsHnd,num);
3288 mdMethodDef ZapInfo::getMethodDefFromMethod(CORINFO_METHOD_HANDLE hMethod)
3290 return m_pEEJitInfo->getMethodDefFromMethod(hMethod);
3293 BOOL ZapInfo::checkMethodModifier(CORINFO_METHOD_HANDLE hMethod, LPCSTR modifier, BOOL fOptional)
3295 return m_pEEJitInfo->checkMethodModifier(hMethod, modifier, fOptional);
3298 unsigned ZapInfo::getClassGClayout(CORINFO_CLASS_HANDLE cls, BYTE *gcPtrs)
3300 return m_pEEJitInfo->getClassGClayout(cls, gcPtrs);
3303 // returns the enregister info for a struct based on type of fields, alignment, etc..
3304 bool ZapInfo::getSystemVAmd64PassStructInRegisterDescriptor(
3305 /*IN*/ CORINFO_CLASS_HANDLE _structHnd,
3306 /*OUT*/ SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr)
3308 return m_pEEJitInfo->getSystemVAmd64PassStructInRegisterDescriptor(_structHnd, structPassInRegDescPtr);
3311 unsigned ZapInfo::getClassNumInstanceFields(CORINFO_CLASS_HANDLE cls)
3313 return m_pEEJitInfo->getClassNumInstanceFields(cls);
3317 CorInfoHelpFunc ZapInfo::getNewHelper(CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_METHOD_HANDLE callerHandle)
3319 if (IsReadyToRunCompilation())
3320 return CORINFO_HELP_NEWFAST;
3322 classMustBeLoadedBeforeCodeIsRun(pResolvedToken->hClass);
3323 return m_pEEJitInfo->getNewHelper(pResolvedToken, callerHandle);
3326 CorInfoHelpFunc ZapInfo::getSharedCCtorHelper(CORINFO_CLASS_HANDLE clsHnd)
3328 return m_pEEJitInfo->getSharedCCtorHelper(clsHnd);
3331 CorInfoHelpFunc ZapInfo::getSecurityPrologHelper(CORINFO_METHOD_HANDLE ftn)
3333 return m_pEEJitInfo->getSecurityPrologHelper(ftn);
3336 CORINFO_CLASS_HANDLE ZapInfo::getTypeForBox(CORINFO_CLASS_HANDLE cls)
3338 return m_pEEJitInfo->getTypeForBox(cls);
3341 CorInfoHelpFunc ZapInfo::getBoxHelper(CORINFO_CLASS_HANDLE cls)
3343 return m_pEEJitInfo->getBoxHelper(cls);
3346 CorInfoHelpFunc ZapInfo::getUnBoxHelper(CORINFO_CLASS_HANDLE cls)
3348 return m_pEEJitInfo->getUnBoxHelper(cls);
3351 CorInfoHelpFunc ZapInfo::getCastingHelper(CORINFO_RESOLVED_TOKEN * pResolvedToken, bool fThrowing)
3353 if (IsReadyToRunCompilation())
3354 return (fThrowing ? CORINFO_HELP_CHKCASTANY : CORINFO_HELP_ISINSTANCEOFANY);
3356 return m_pEEJitInfo->getCastingHelper(pResolvedToken, fThrowing);
3359 CorInfoHelpFunc ZapInfo::getNewArrHelper(CORINFO_CLASS_HANDLE arrayCls)
3361 if (IsReadyToRunCompilation())
3362 return CORINFO_HELP_NEWARR_1_R2R_DIRECT;
3364 return m_pEEJitInfo->getNewArrHelper(arrayCls);
3367 bool ZapInfo::getReadyToRunHelper(CORINFO_RESOLVED_TOKEN * pResolvedToken,
3368 CORINFO_LOOKUP_KIND * pGenericLookupKind,
3370 CORINFO_CONST_LOOKUP * pLookup)
3372 #ifdef FEATURE_READYTORUN_COMPILER
3373 _ASSERTE(IsReadyToRunCompilation());
3375 ZapImport * pImport = NULL;
3377 DWORD fAtypicalCallsite = (id & CORINFO_HELP_READYTORUN_ATYPICAL_CALLSITE);
3378 id = (CorInfoHelpFunc)(id & ~CORINFO_HELP_READYTORUN_ATYPICAL_CALLSITE);
3382 case CORINFO_HELP_READYTORUN_NEW:
3383 // Call CEEInfo::getNewHelper to validate the request (e.g., check for abstract class).
3384 m_pEEJitInfo->getNewHelper(pResolvedToken, m_currentMethodHandle);
3386 if ((getClassAttribs(pResolvedToken->hClass) & CORINFO_FLG_SHAREDINST) != 0)
3387 return false; // Requires runtime lookup.
3388 pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(
3389 (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_NEW_HELPER | fAtypicalCallsite), pResolvedToken->hClass);
3392 case CORINFO_HELP_READYTORUN_NEWARR_1:
3393 if ((getClassAttribs(pResolvedToken->hClass) & CORINFO_FLG_SHAREDINST) != 0)
3394 return false; // Requires runtime lookup.
3395 pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(
3396 (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_NEW_ARRAY_HELPER | fAtypicalCallsite), pResolvedToken->hClass);
3399 case CORINFO_HELP_READYTORUN_ISINSTANCEOF:
3400 if ((getClassAttribs(pResolvedToken->hClass) & CORINFO_FLG_SHAREDINST) != 0)
3401 return false; // Requires runtime lookup.
3402 pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(
3403 (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_ISINSTANCEOF_HELPER | fAtypicalCallsite), pResolvedToken->hClass);
3406 case CORINFO_HELP_READYTORUN_CHKCAST:
3407 if ((getClassAttribs(pResolvedToken->hClass) & CORINFO_FLG_SHAREDINST) != 0)
3408 return false; // Requires runtime lookup.
3409 pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(
3410 (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_CHKCAST_HELPER | fAtypicalCallsite), pResolvedToken->hClass);
3413 case CORINFO_HELP_READYTORUN_STATIC_BASE:
3414 if ((getClassAttribs(pResolvedToken->hClass) & CORINFO_FLG_SHAREDINST) != 0)
3415 return false; // Requires runtime lookup.
3416 if (m_pImage->GetCompileInfo()->IsInCurrentVersionBubble(m_pEEJitInfo->getClassModule(pResolvedToken->hClass)))
3418 pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(
3419 (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_CCTOR_TRIGGER | fAtypicalCallsite), pResolvedToken->hClass);
3423 // READYTORUN: FUTURE: Cross-module static cctor triggers
3424 m_zapper->Warning(W("ReadyToRun: Cross-module static cctor triggers not supported\n"));
3429 case CORINFO_HELP_READYTORUN_GENERIC_HANDLE:
3430 _ASSERTE(pGenericLookupKind != NULL && pGenericLookupKind->needsRuntimeLookup);
3431 if (pGenericLookupKind->runtimeLookupKind == CORINFO_LOOKUP_METHODPARAM)
3433 pImport = m_pImage->GetImportTable()->GetDictionaryLookupCell(
3434 (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_DICTIONARY_LOOKUP_METHOD | fAtypicalCallsite), pResolvedToken, pGenericLookupKind);
3436 else if (pGenericLookupKind->runtimeLookupKind == CORINFO_LOOKUP_THISOBJ)
3438 pImport = m_pImage->GetImportTable()->GetDictionaryLookupCell(
3439 (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_DICTIONARY_LOOKUP_THISOBJ | fAtypicalCallsite), pResolvedToken, pGenericLookupKind);
3443 _ASSERTE(pGenericLookupKind->runtimeLookupKind == CORINFO_LOOKUP_CLASSPARAM);
3444 pImport = m_pImage->GetImportTable()->GetDictionaryLookupCell(
3445 (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_DICTIONARY_LOOKUP_TYPE | fAtypicalCallsite), pResolvedToken, pGenericLookupKind);
3454 pLookup->accessType = IAT_PVALUE;
3455 pLookup->addr = pImport;
3462 void ZapInfo::getReadyToRunDelegateCtorHelper(
3463 CORINFO_RESOLVED_TOKEN * pTargetMethod,
3464 CORINFO_CLASS_HANDLE delegateType,
3465 CORINFO_LOOKUP * pLookup
3468 #ifdef FEATURE_READYTORUN_COMPILER
3469 _ASSERTE(IsReadyToRunCompilation());
3470 pLookup->lookupKind.needsRuntimeLookup = false;
3471 pLookup->constLookup.accessType = IAT_PVALUE;
3472 pLookup->constLookup.addr = m_pImage->GetImportTable()->GetDynamicHelperCell(
3473 (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_DELEGATE_CTOR), pTargetMethod->hMethod, pTargetMethod, delegateType);
3482 //-----------------------------------------------------------------------------
3483 void ZapInfo::resolveToken(CORINFO_RESOLVED_TOKEN * pResolvedToken)
3485 m_pEEJitInfo->resolveToken(pResolvedToken);
3488 //-----------------------------------------------------------------------------
3489 bool ZapInfo::tryResolveToken(CORINFO_RESOLVED_TOKEN * pResolvedToken)
3491 return m_pEEJitInfo->tryResolveToken(pResolvedToken);
3494 //-----------------------------------------------------------------------------
3495 void ZapInfo::findSig(CORINFO_MODULE_HANDLE tokenScope,
3497 CORINFO_CONTEXT_HANDLE tokenContext,
3498 CORINFO_SIG_INFO *sig)
3500 m_pEEJitInfo->findSig(tokenScope, sigTOK, tokenContext, sig);
3503 void ZapInfo::findCallSiteSig(CORINFO_MODULE_HANDLE tokenScope,
3505 CORINFO_CONTEXT_HANDLE tokenContext, CORINFO_SIG_INFO *sig)
3507 m_pEEJitInfo->findCallSiteSig(tokenScope, methTOK, tokenContext, sig);
3510 size_t ZapInfo::findNameOfToken(CORINFO_MODULE_HANDLE tokenScope,
3512 __out_ecount (FQNameCapacity) char * szFQName,
3513 size_t FQNameCapacity)
3515 return m_pEEJitInfo->findNameOfToken(tokenScope, token, szFQName, FQNameCapacity);
3518 CorInfoCanSkipVerificationResult ZapInfo::canSkipVerification (
3519 CORINFO_MODULE_HANDLE tokenScope)
3521 return m_pEEJitInfo->canSkipVerification(tokenScope);
3524 BOOL ZapInfo::isValidToken (
3525 CORINFO_MODULE_HANDLE tokenScope,
3528 return m_pEEJitInfo->isValidToken(tokenScope, token);
3531 BOOL ZapInfo::isValidStringRef (
3532 CORINFO_MODULE_HANDLE tokenScope,
3535 return m_pEEJitInfo->isValidStringRef(tokenScope, token);
3543 const char* ZapInfo::getMethodName(CORINFO_METHOD_HANDLE ftn, const char **moduleName)
3545 return m_pEEJitInfo->getMethodName(ftn, moduleName);
3548 unsigned ZapInfo::getMethodHash(CORINFO_METHOD_HANDLE ftn)
3550 return m_pEEJitInfo->getMethodHash(ftn);
3553 DWORD ZapInfo::getMethodAttribs(CORINFO_METHOD_HANDLE ftn)
3555 return m_pEEJitInfo->getMethodAttribs(ftn);
3558 void ZapInfo::setMethodAttribs(CORINFO_METHOD_HANDLE ftn, CorInfoMethodRuntimeFlags attribs)
3560 m_pEEJitInfo->setMethodAttribs(ftn, attribs);
3563 void ZapInfo::getMethodSig(CORINFO_METHOD_HANDLE ftn, CORINFO_SIG_INFO *sig,CORINFO_CLASS_HANDLE memberParent)
3565 m_pEEJitInfo->getMethodSig(ftn, sig, memberParent);
3568 bool ZapInfo::getMethodInfo(CORINFO_METHOD_HANDLE ftn,CORINFO_METHOD_INFO* info)
3570 bool result = m_pImage->m_pPreloader->GetMethodInfo(m_currentMethodToken, ftn, info);
3571 info->regionKind = m_pImage->GetCurrentRegionKind();
3575 CorInfoInline ZapInfo::canInline(CORINFO_METHOD_HANDLE caller,
3576 CORINFO_METHOD_HANDLE callee,
3577 DWORD* pRestrictions)
3579 return m_pEEJitInfo->canInline(caller, callee, pRestrictions);
3583 void ZapInfo::reportInliningDecision (CORINFO_METHOD_HANDLE inlinerHnd,
3584 CORINFO_METHOD_HANDLE inlineeHnd,
3585 CorInfoInline inlineResult,
3586 const char * reason)
3588 if (!dontInline(inlineResult) && inlineeHnd != NULL)
3590 // We deliberately report m_currentMethodHandle (not inlinerHnd) as inliner, because
3591 // if m_currentMethodHandle != inlinerHnd, it simply means that inlinerHnd is intermediate link
3592 // in inlining into m_currentMethodHandle, and we have no interest to track those intermediate links now.
3593 m_pImage->m_pPreloader->ReportInlining(m_currentMethodHandle, inlineeHnd);
3595 return m_pEEJitInfo->reportInliningDecision(inlinerHnd, inlineeHnd, inlineResult, reason);
3599 CorInfoInstantiationVerification ZapInfo::isInstantiationOfVerifiedGeneric(
3600 CORINFO_METHOD_HANDLE method)
3602 return m_pEEJitInfo->isInstantiationOfVerifiedGeneric(method);
3606 void ZapInfo::initConstraintsForVerification(CORINFO_METHOD_HANDLE method,
3607 BOOL *pfHasCircularClassConstraints,
3608 BOOL *pfHasCircularMethodConstraints)
3611 initConstraintsForVerification(method,pfHasCircularClassConstraints,pfHasCircularMethodConstraints);
3614 bool ZapInfo::canTailCall(CORINFO_METHOD_HANDLE caller,
3615 CORINFO_METHOD_HANDLE declaredCallee,
3616 CORINFO_METHOD_HANDLE exactCallee,
3619 #ifdef FEATURE_READYTORUN_COMPILER
3620 // READYTORUN: FUTURE: Delay load fixups for tailcalls
3621 if (IsReadyToRunCompilation())
3625 m_zapper->Warning(W("ReadyToRun: Explicit tailcalls not supported\n"));
3633 return m_pEEJitInfo->canTailCall(caller, declaredCallee, exactCallee, fIsTailPrefix);
3636 void ZapInfo::reportTailCallDecision(CORINFO_METHOD_HANDLE callerHnd,
3637 CORINFO_METHOD_HANDLE calleeHnd,
3639 CorInfoTailCall tailCallResult,
3640 const char * reason)
3642 return m_pEEJitInfo->reportTailCallDecision(callerHnd, calleeHnd, fIsTailPrefix, tailCallResult, reason);
3646 CorInfoCanSkipVerificationResult ZapInfo::canSkipMethodVerification (
3647 CORINFO_METHOD_HANDLE ftnHandle)
3649 // ILStubs are generated internally by the CLR. There is no need to
3650 // verify it, or any of its callees.
3651 if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB))
3652 return CORINFO_VERIFICATION_CAN_SKIP;
3654 CorInfoCanSkipVerificationResult canSkipVer =
3655 m_pEEJitInfo->canSkipMethodVerification(ftnHandle);
3657 if (canSkipVer == CORINFO_VERIFICATION_RUNTIME_CHECK)
3659 // Transparent code could be partial trust, but we don't know at NGEN time.
3660 // Since the JIT is not hardened against unverifiable/illegal code, tell it
3661 // to just not jit the method if it hits unverifiable code, rathern than
3662 // injecting a runtime callout and continuing trying to JIT the method.
3663 canSkipVer = CORINFO_VERIFICATION_DONT_JIT;
3669 void ZapInfo::getEHinfo(CORINFO_METHOD_HANDLE ftn,
3670 unsigned EHnumber, CORINFO_EH_CLAUSE* clause)
3672 m_pEEJitInfo->getEHinfo(ftn, EHnumber, clause);
3675 CORINFO_CLASS_HANDLE ZapInfo::getMethodClass(CORINFO_METHOD_HANDLE method)
3677 return m_pEEJitInfo->getMethodClass(method);
3680 CORINFO_MODULE_HANDLE ZapInfo::getMethodModule(CORINFO_METHOD_HANDLE method)
3682 return m_pEEJitInfo->getMethodModule(method);
3685 void ZapInfo::getMethodVTableOffset(CORINFO_METHOD_HANDLE method,
3686 unsigned * pOffsetOfIndirection,
3687 unsigned * pOffsetAfterIndirection,
3690 m_pEEJitInfo->getMethodVTableOffset(method, pOffsetOfIndirection, pOffsetAfterIndirection, isRelative);
3693 CORINFO_METHOD_HANDLE ZapInfo::resolveVirtualMethod(
3694 CORINFO_METHOD_HANDLE virtualMethod,
3695 CORINFO_CLASS_HANDLE implementingClass,
3696 CORINFO_CONTEXT_HANDLE ownerType
3699 return m_pEEJitInfo->resolveVirtualMethod(virtualMethod, implementingClass, ownerType);
3702 void ZapInfo::expandRawHandleIntrinsic(
3703 CORINFO_RESOLVED_TOKEN * pResolvedToken,
3704 CORINFO_GENERICHANDLE_RESULT * pResult)
3706 m_pEEJitInfo->expandRawHandleIntrinsic(pResolvedToken, pResult);
3709 CorInfoIntrinsics ZapInfo::getIntrinsicID(CORINFO_METHOD_HANDLE method,
3712 return m_pEEJitInfo->getIntrinsicID(method, pMustExpand);
3715 bool ZapInfo::isInSIMDModule(CORINFO_CLASS_HANDLE classHnd)
3717 return m_pEEJitInfo->isInSIMDModule(classHnd);
3720 CorInfoUnmanagedCallConv ZapInfo::getUnmanagedCallConv(CORINFO_METHOD_HANDLE method)
3722 return m_pEEJitInfo->getUnmanagedCallConv(method);
3725 BOOL ZapInfo::pInvokeMarshalingRequired(CORINFO_METHOD_HANDLE method,
3726 CORINFO_SIG_INFO* sig)
3728 // READYTORUN: FUTURE: P/Invoke
3729 if (IsReadyToRunCompilation())
3732 return m_pEEJitInfo->pInvokeMarshalingRequired(method, sig);
3735 LPVOID ZapInfo::GetCookieForPInvokeCalliSig(CORINFO_SIG_INFO* szMetaSig,
3736 void ** ppIndirection)
3738 return getVarArgsHandle(szMetaSig, ppIndirection);
3741 bool ZapInfo::canGetCookieForPInvokeCalliSig(CORINFO_SIG_INFO* szMetaSig)
3743 return canGetVarArgsHandle(szMetaSig);
3746 BOOL ZapInfo::satisfiesMethodConstraints(
3747 CORINFO_CLASS_HANDLE parent,
3748 CORINFO_METHOD_HANDLE method)
3750 return m_pEEJitInfo->satisfiesMethodConstraints(parent, method);
3754 BOOL ZapInfo::isCompatibleDelegate(
3755 CORINFO_CLASS_HANDLE objCls,
3756 CORINFO_CLASS_HANDLE methodParentCls,
3757 CORINFO_METHOD_HANDLE method,
3758 CORINFO_CLASS_HANDLE delegateCls,
3759 BOOL* pfIsOpenDelegate)
3761 return m_pEEJitInfo->isCompatibleDelegate(objCls, methodParentCls, method, delegateCls, pfIsOpenDelegate);
3768 HRESULT ZapInfo::GetErrorHRESULT(struct _EXCEPTION_POINTERS *pExceptionPointers)
3770 return m_pEEJitInfo->GetErrorHRESULT(pExceptionPointers);
3773 ULONG ZapInfo::GetErrorMessage(__in_ecount(bufferLength) LPWSTR buffer, ULONG bufferLength)
3775 return m_pEEJitInfo->GetErrorMessage(buffer, bufferLength);
3778 int ZapInfo::FilterException(struct _EXCEPTION_POINTERS *pExceptionPointers)
3780 // Continue unwinding if fatal error was hit.
3781 if (FAILED(g_hrFatalError))
3782 return EXCEPTION_CONTINUE_SEARCH;
3784 return m_pEEJitInfo->FilterException(pExceptionPointers);
3787 void ZapInfo::HandleException(struct _EXCEPTION_POINTERS *pExceptionPointers)
3789 m_pEEJitInfo->HandleException(pExceptionPointers);
3792 void ZapInfo::ThrowExceptionForJitResult(HRESULT result)
3794 m_pEEJitInfo->ThrowExceptionForJitResult(result);
3796 void ZapInfo::ThrowExceptionForHelper(const CORINFO_HELPER_DESC * throwHelper)
3798 m_pEEJitInfo->ThrowExceptionForHelper(throwHelper);
3801 template<> void LoadTable<CORINFO_CLASS_HANDLE>::EmitLoadFixups(CORINFO_METHOD_HANDLE currentMethodHandle, ZapInfo * pZapInfo)
3804 // Find all of our un-fixed entries, and emit a restore fixup for each of them.
3805 // Note that we don't need a restore fixups for prerestored classes.
3808 InlineSArray<LoadEntry, 4> unfixed;
3810 for (LoadEntryHashTable::Iterator i = m_entries.Begin(), end = m_entries.End(); i != end; i++)
3813 || m_pModule->m_pPreloader->CanPrerestoreEmbedClassHandle(i->handle)
3814 // @TODO: Skip transitive closure of currentMethodHandle (parents, instantiations, etc.)
3815 || m_pModule->GetJitInfo()->getMethodClass(currentMethodHandle) == i->handle)
3822 // Now clear the table.
3825 m_entries.RemoveAll();
3827 if (unfixed.IsEmpty())
3830 // Save the fixups in the order they got emited for determinism
3831 qsort(&unfixed[0], unfixed.GetCount(), sizeof(LoadEntry), LoadEntryCmp);
3833 for(COUNT_T j = 0; j < unfixed.GetCount(); j++)
3835 CORINFO_CLASS_HANDLE handle = unfixed[j].handle;
3836 m_pModule->m_pPreloader->AddTypeToTransitiveClosureOfInstantiations(handle);
3837 ZapImport * pImport = m_pModule->GetImportTable()->GetClassHandleImport(handle);
3838 pZapInfo->AppendImport(pImport);
3843 template<> void LoadTable<CORINFO_METHOD_HANDLE>::EmitLoadFixups(CORINFO_METHOD_HANDLE currentMethodHandle, ZapInfo * pZapInfo)
3846 // Find all of our un-fixed entries, and emit a restore fixup for each of them.
3847 // Note that we don't need a restore fixups for prerestored methods.
3850 InlineSArray<LoadEntry, 4> unfixed;
3852 for (LoadEntryHashTable::Iterator i = m_entries.Begin(), end = m_entries.End(); i != end; i++)
3855 || m_pModule->m_pPreloader->CanPrerestoreEmbedMethodHandle(i->handle)
3856 || currentMethodHandle == i->handle)
3863 // Now clear the table.
3866 m_entries.RemoveAll();
3868 if (unfixed.IsEmpty())
3871 // Save the fixups in the order they got emited for determinism
3872 qsort(&unfixed[0], unfixed.GetCount(), sizeof(LoadEntry), LoadEntryCmp);
3874 for(COUNT_T j = 0; j < unfixed.GetCount(); j++)
3876 CORINFO_METHOD_HANDLE handle = unfixed[j].handle;
3877 m_pModule->m_pPreloader->AddMethodToTransitiveClosureOfInstantiations(handle);
3878 ZapImport * pImport = m_pModule->GetImportTable()->GetMethodHandleImport(handle);
3879 pZapInfo->AppendImport(pImport);
3883 BOOL ZapInfo::CurrentMethodHasProfileData()
3885 WRAPPER_NO_CONTRACT;
3887 ICorJitInfo::ProfileBuffer * profileBuffer;
3888 return SUCCEEDED(getBBProfileData(m_currentMethodHandle, &size, &profileBuffer, NULL));