From: Brian Sullivan Date: Wed, 8 Mar 2017 02:58:11 +0000 (-0800) Subject: Work for IBC profiling with ReadyToRun images X-Git-Tag: submit/tizen/20210909.063632~11030^2~7747^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b05ff4ab41cb2816f43cf5789974a66a47f1fbe3;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Work for IBC profiling with ReadyToRun images Incremented ReadyToRun version to 2.2 Implemented caching for IsInstrumented using IS_INSTRUMENTED_UNSET Added method Module::InitializeForProfiling() Added full support for method profile counts in ReadyToRun image Commit migrated from https://github.com/dotnet/coreclr/commit/c67474bd34847bf5ceff3d49f29eb4b778848748 --- diff --git a/src/coreclr/src/inc/readytorun.h b/src/coreclr/src/inc/readytorun.h index 9084b92..0f5183f 100644 --- a/src/coreclr/src/inc/readytorun.h +++ b/src/coreclr/src/inc/readytorun.h @@ -16,8 +16,9 @@ #define READYTORUN_SIGNATURE 0x00525452 // 'RTR' #define READYTORUN_MAJOR_VERSION 0x0002 -#define READYTORUN_MINOR_VERSION 0x0001 +#define READYTORUN_MINOR_VERSION 0x0002 // R2R Version 2.1 adds the READYTORUN_SECTION_INLINING_INFO section +// R2R Version 2.2 adds the READYTORUN_SECTION_PROFILEDATA_INFO section struct READYTORUN_HEADER { @@ -58,7 +59,8 @@ enum ReadyToRunSectionType // 107 used by an older format of READYTORUN_SECTION_AVAILABLE_TYPES READYTORUN_SECTION_AVAILABLE_TYPES = 108, READYTORUN_SECTION_INSTANCE_METHOD_ENTRYPOINTS = 109, - READYTORUN_SECTION_INLINING_INFO = 110 // Added in V2.1 + READYTORUN_SECTION_INLINING_INFO = 110, // Added in V2.1 + READYTORUN_SECTION_PROFILEDATA_INFO = 111 // Added in V2.2 // If you add a new section consider whether it is a breaking or non-breaking change. // Usually it is non-breaking, but if it is preferable to have older runtimes fail @@ -228,6 +230,9 @@ enum ReadyToRunHelper // Get string handle lazily READYTORUN_HELPER_GetString = 0x50, + // Used by /Tuning for Profile optimizations + READYTORUN_HELPER_LogMethodEnter = 0x51, + // Reflection helpers READYTORUN_HELPER_GetRuntimeTypeHandle = 0x54, READYTORUN_HELPER_GetRuntimeMethodHandle = 0x55, diff --git a/src/coreclr/src/inc/readytorunhelpers.h b/src/coreclr/src/inc/readytorunhelpers.h index 4524e1a..9baf0e4 100644 --- a/src/coreclr/src/inc/readytorunhelpers.h +++ b/src/coreclr/src/inc/readytorunhelpers.h @@ -32,6 +32,8 @@ HELPER(READYTORUN_HELPER_Ldelema_Ref, CORINFO_HELP_LDELEMA_REF, HELPER(READYTORUN_HELPER_MemSet, CORINFO_HELP_MEMSET, ) HELPER(READYTORUN_HELPER_MemCpy, CORINFO_HELP_MEMCPY, ) +HELPER(READYTORUN_HELPER_LogMethodEnter, CORINFO_HELP_BBT_FCN_ENTER, ) + HELPER(READYTORUN_HELPER_GetRuntimeTypeHandle, CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE, ) HELPER(READYTORUN_HELPER_GetRuntimeMethodHandle, CORINFO_HELP_METHODDESC_TO_STUBRUNTIMEMETHOD, ) HELPER(READYTORUN_HELPER_GetRuntimeFieldHandle, CORINFO_HELP_FIELDDESC_TO_STUBRUNTIMEFIELD, ) diff --git a/src/coreclr/src/jit/flowgraph.cpp b/src/coreclr/src/jit/flowgraph.cpp index 3d6dba9..1c77572 100644 --- a/src/coreclr/src/jit/flowgraph.cpp +++ b/src/coreclr/src/jit/flowgraph.cpp @@ -330,14 +330,37 @@ void Compiler::fgInstrumentMethod() // Add the method entry callback node - GenTreeArgList* args = gtNewArgList(gtNewIconEmbMethHndNode(info.compMethodHnd)); + GenTreePtr arg; + +#ifdef FEATURE_READYTORUN_COMPILER + if (opts.IsReadyToRun()) + { + mdMethodDef currentMethodToken = info.compCompHnd->getMethodDefFromMethod(info.compMethodHnd); + + CORINFO_RESOLVED_TOKEN resolvedToken; + resolvedToken.tokenContext = MAKE_METHODCONTEXT(info.compMethodHnd); + resolvedToken.tokenScope = info.compScopeHnd; + resolvedToken.token = currentMethodToken; + resolvedToken.tokenType = CORINFO_TOKENKIND_Method; + + info.compCompHnd->resolveToken(&resolvedToken); + + arg = impTokenToHandle(&resolvedToken); + } + else +#endif + { + arg = gtNewIconEmbMethHndNode(info.compMethodHnd); + } + + GenTreeArgList* args = gtNewArgList(arg); GenTreePtr call = gtNewHelperCallNode(CORINFO_HELP_BBT_FCN_ENTER, TYP_VOID, 0, args); GenTreePtr handle = gtNewIconEmbHndNode((void*)&bbProfileBufferStart->ExecutionCount, nullptr, GTF_ICON_BBC_PTR); GenTreePtr value = gtNewOperNode(GT_IND, TYP_INT, handle); GenTreePtr relop = gtNewOperNode(GT_NE, TYP_INT, value, gtNewIconNode(0, TYP_INT)); - relop->gtFlags |= GTF_RELOP_QMARK; + relop->gtFlags |= GTF_RELOP_QMARK; // TODO-Cleanup: [Simple] Move this to gtNewQmarkNode GenTreePtr colon = new (this, GT_COLON) GenTreeColon(TYP_VOID, gtNewNothingNode(), call); GenTreePtr cond = gtNewQmarkNode(TYP_VOID, relop, colon); stmt = gtNewStmt(cond); diff --git a/src/coreclr/src/tools/crossgen/crossgen.cpp b/src/coreclr/src/tools/crossgen/crossgen.cpp index 6257896..df16e94 100644 --- a/src/coreclr/src/tools/crossgen/crossgen.cpp +++ b/src/coreclr/src/tools/crossgen/crossgen.cpp @@ -834,14 +834,6 @@ int _cdecl wmain(int argc, __in_ecount(argc) WCHAR **argv) exit(FAILURE_RESULT); } } - -#ifdef FEATURE_READYTORUN_COMPILER - if (((dwFlags & NGENWORKER_FLAGS_TUNING) != 0) && ((dwFlags & NGENWORKER_FLAGS_READYTORUN) != 0)) - { - Output(W("The /Tuning switch cannot be used with /ReadyToRun switch.\n")); - exit(FAILURE_RESULT); - } -#endif // All argument processing has happened by now. The only messages that should appear before here are errors // related to argument parsing, such as the Usage message. Afterwards, other messages can appear. diff --git a/src/coreclr/src/utilcode/pedecoder.cpp b/src/coreclr/src/utilcode/pedecoder.cpp index e4fc465..9b7a058 100644 --- a/src/coreclr/src/utilcode/pedecoder.cpp +++ b/src/coreclr/src/utilcode/pedecoder.cpp @@ -1075,8 +1075,8 @@ CHECK PEDecoder::CheckCorHeader() const if (IsStrongNameSigned()) CHECK(HasStrongNameSignature()); - // IL library files (really a misnomer - these are native images) only - // may have a native image header + // IL library files (really a misnomer - these are native images or ReadyToRun images) + // only they can have a native image header if ((pCor->Flags&VAL32(COMIMAGE_FLAGS_IL_LIBRARY)) == 0) { CHECK(VAL32(pCor->ManagedNativeHeader.Size) == 0); @@ -1828,7 +1828,7 @@ BOOL PEDecoder::HasNativeHeader() const CONTRACT_END; #ifdef FEATURE_PREJIT - // Pretend that ready-to-run images do not have native header + // Pretend that ready-to-run images do not have a native header RETURN (((GetCorHeader()->Flags & VAL32(COMIMAGE_FLAGS_IL_LIBRARY)) != 0) && !HasReadyToRunHeader()); #else RETURN FALSE; diff --git a/src/coreclr/src/vm/assembly.cpp b/src/coreclr/src/vm/assembly.cpp index 5f0e75d..d95eec0 100644 --- a/src/coreclr/src/vm/assembly.cpp +++ b/src/coreclr/src/vm/assembly.cpp @@ -141,6 +141,9 @@ Assembly::Assembly(BaseDomain *pDomain, PEAssembly* pFile, DebuggerAssemblyContr #ifdef FEATURE_COMINTEROP , m_InteropAttributeStatus(INTEROP_ATTRIBUTE_UNSET) #endif +#ifdef FEATURE_PREJIT + , m_isInstrumentedStatus(IS_INSTRUMENTED_UNSET) +#endif { STANDARD_VM_CONTRACT; } @@ -2329,21 +2332,37 @@ BOOL Assembly::IsInstrumented() STATIC_CONTRACT_GC_TRIGGERS; STATIC_CONTRACT_FAULT; - BOOL isInstrumented = false; - - EX_TRY + // This will set the value of m_isInstrumentedStatus by calling IsInstrumentedHelper() + // that method performs string pattern matching using the Config value of ZapBBInstr + // We cache the value returned from that method in m_isInstrumentedStatus + // + if (m_isInstrumentedStatus == IS_INSTRUMENTED_UNSET) { - FAULT_NOT_FATAL(); + EX_TRY + { + FAULT_NOT_FATAL(); - isInstrumented = IsInstrumentedHelper(); - } - EX_CATCH - { - isInstrumented = false; + if (IsInstrumentedHelper()) + { + m_isInstrumentedStatus = IS_INSTRUMENTED_TRUE; + } + else + { + m_isInstrumentedStatus = IS_INSTRUMENTED_FALSE; + } + } + + EX_CATCH + { + m_isInstrumentedStatus = IS_INSTRUMENTED_FALSE; + } + EX_END_CATCH(RethrowTerminalExceptions); } - EX_END_CATCH(RethrowTerminalExceptions); - return isInstrumented; + // At this point m_isInstrumentedStatus can't have the value of IS_INSTRUMENTED_UNSET + _ASSERTE(m_isInstrumentedStatus != IS_INSTRUMENTED_UNSET); + + return (m_isInstrumentedStatus == IS_INSTRUMENTED_TRUE); } BOOL Assembly::IsInstrumentedHelper() @@ -2357,7 +2376,7 @@ BOOL Assembly::IsInstrumentedHelper() return false; // We must have a native image in order to perform IBC instrumentation - if (!GetManifestFile()->HasNativeImage()) + if (!GetManifestFile()->HasNativeOrReadyToRunImage()) return false; // @Consider using the full name instead of the short form diff --git a/src/coreclr/src/vm/assembly.hpp b/src/coreclr/src/vm/assembly.hpp index 22b031b..0fdb9a2 100644 --- a/src/coreclr/src/vm/assembly.hpp +++ b/src/coreclr/src/vm/assembly.hpp @@ -551,7 +551,7 @@ public: BOOL IsSIMDVectorAssembly() { LIMITED_METHOD_DAC_CONTRACT; return m_fIsSIMDVectorAssembly; } -#ifdef FEATURE_PREJIT +#ifdef FEATURE_PREJIT BOOL IsInstrumented(); BOOL IsInstrumentedHelper(); #endif // FEATURE_PREJIT @@ -704,7 +704,6 @@ protected: // Keep track of the vars that need to be freed. short int m_FreeFlag; - private: //**************************************************************************************** @@ -775,6 +774,15 @@ private: DWORD m_dwReliabilityContract; +#ifdef FEATURE_PREJIT + enum IsInstrumentedStatus { + IS_INSTRUMENTED_UNSET = 0, + IS_INSTRUMENTED_FALSE = 1, + IS_INSTRUMENTED_TRUE = 2, + }; + IsInstrumentedStatus m_isInstrumentedStatus; +#endif // FEATURE_PREJIT + }; typedef Assembly::ModuleIterator ModuleIterator; diff --git a/src/coreclr/src/vm/ceeload.cpp b/src/coreclr/src/vm/ceeload.cpp index 61d8ae2..1979d69 100644 --- a/src/coreclr/src/vm/ceeload.cpp +++ b/src/coreclr/src/vm/ceeload.cpp @@ -437,6 +437,55 @@ Module::Module(Assembly *pAssembly, mdFile moduleRef, PEFile *file) file->AddRef(); } +void Module::InitializeForProfiling() +{ + CONTRACTL + { + INSTANCE_CHECK; + THROWS; + GC_TRIGGERS; + MODE_PREEMPTIVE; + PRECONDITION(HasNativeOrReadyToRunImage()); + } + CONTRACTL_END; + + COUNT_T cbProfileList = 0; + + m_nativeImageProfiling = FALSE; + + if (HasNativeImage()) + { + PEImageLayout * pNativeImage = GetNativeImage(); + CORCOMPILE_VERSION_INFO * pNativeVersionInfo = pNativeImage->GetNativeVersionInfoMaybeNull(); + if ((pNativeVersionInfo != NULL) && (pNativeVersionInfo->wConfigFlags & CORCOMPILE_CONFIG_INSTRUMENTATION)) + { + m_nativeImageProfiling = GetAssembly()->IsInstrumented(); + } + + // Link the module to the profile data list if available. + m_methodProfileList = pNativeImage->GetNativeProfileDataList(&cbProfileList); + } + else // ReadyToRun image + { + // We already setup the m_methodProfileList in the ReadyToRunInfo constructor + if (m_methodProfileList != nullptr) + { + ReadyToRunInfo * pInfo = GetReadyToRunInfo(); + PEImageLayout * pImage = pInfo->GetImage(); + + // Enable profiling if the ZapBBInstr value says to + m_nativeImageProfiling = GetAssembly()->IsInstrumented(); + } + } + +#ifdef FEATURE_LAZY_COW_PAGES + // When running a IBC tuning image to gather profile data + // we increment the block counts contained in this area. + // + if (cbProfileList) + EnsureWritablePages(m_methodProfileList, cbProfileList); +#endif +} #ifdef FEATURE_PREJIT @@ -461,20 +510,6 @@ void Module::InitializeNativeImage(AllocMemTracker* pamTracker) ExecutionManager::AddNativeImageRange(dac_cast(pNativeImage->GetBase()), pNativeImage->GetVirtualSize(), this); - CORCOMPILE_VERSION_INFO * pNativeVersionInfo = pNativeImage->GetNativeVersionInfoMaybeNull(); - if ((pNativeVersionInfo != NULL) && (pNativeVersionInfo->wConfigFlags & CORCOMPILE_CONFIG_INSTRUMENTATION)) - { - m_nativeImageProfiling = GetAssembly()->IsInstrumented(); - } - - // Link the module to the profile data list if available. - COUNT_T cbProfileList; - m_methodProfileList = pNativeImage->GetNativeProfileDataList(&cbProfileList); -#ifdef FEATURE_LAZY_COW_PAGES - if (cbProfileList) - EnsureWritablePages(m_methodProfileList, cbProfileList); -#endif - #ifndef CROSSGEN_COMPILE LoadTokenTables(); LoadHelperTable(); @@ -652,9 +687,15 @@ void Module::Initialize(AllocMemTracker *pamTracker, LPCWSTR szName) #ifdef FEATURE_PREJIT // Set up native image if (HasNativeImage()) + { InitializeNativeImage(pamTracker); + } #endif // FEATURE_PREJIT + if (HasNativeOrReadyToRunImage()) + { + InitializeForProfiling(); + } #ifdef FEATURE_NATIVE_IMAGE_GENERATION if (g_CorCompileVerboseLevel) @@ -4279,6 +4320,16 @@ BOOL Module::IsVisibleToDebugger() return TRUE; } +BOOL Module::HasNativeOrReadyToRunImage() +{ +#ifdef FEATURE_READYTORUN + if (IsReadyToRun()) + return TRUE; +#endif + + return HasNativeImage(); +} + PEImageLayout * Module::GetNativeOrReadyToRunImage() { LIMITED_METHOD_CONTRACT; diff --git a/src/coreclr/src/vm/ceeload.h b/src/coreclr/src/vm/ceeload.h index ba95b2d..2f3fe90 100644 --- a/src/coreclr/src/vm/ceeload.h +++ b/src/coreclr/src/vm/ceeload.h @@ -1790,6 +1790,7 @@ protected: protected: #ifndef DACCESS_COMPILE virtual void Initialize(AllocMemTracker *pamTracker, LPCWSTR szName = NULL); + void InitializeForProfiling(); #ifdef FEATURE_PREJIT void InitializeNativeImage(AllocMemTracker* pamTracker); #endif @@ -2734,6 +2735,8 @@ public: } #endif // FEATURE_PREJIT + + BOOL HasNativeOrReadyToRunImage(); PEImageLayout * GetNativeOrReadyToRunImage(); PTR_CORCOMPILE_IMPORT_SECTION GetImportSections(COUNT_T *pCount); PTR_CORCOMPILE_IMPORT_SECTION GetImportSectionFromIndex(COUNT_T index); @@ -3066,6 +3069,10 @@ public: static void ProfileDataAllocateTokenLists(ProfileEmitter * pEmitter, TokenProfileData* pTokenProfileData); HRESULT WriteMethodProfileDataLogFile(bool cleanup); static void WriteAllModuleProfileData(bool cleanup); + void SetMethodProfileList(CORCOMPILE_METHOD_PROFILE_LIST * value) + { + m_methodProfileList = value; + } void CreateProfilingData(); void DeleteProfilingData(); diff --git a/src/coreclr/src/vm/pefile.h b/src/coreclr/src/vm/pefile.h index d4f3755..b7c7bd3 100644 --- a/src/coreclr/src/vm/pefile.h +++ b/src/coreclr/src/vm/pefile.h @@ -378,6 +378,7 @@ public: PEImage *GetNativeImageWithRef(); PEImage *GetPersistentNativeImage(); #endif + BOOL HasNativeOrReadyToRunImage(); BOOL HasNativeImage(); PTR_PEImageLayout GetLoaded(); PTR_PEImageLayout GetLoadedNative(); diff --git a/src/coreclr/src/vm/pefile.inl b/src/coreclr/src/vm/pefile.inl index 9bd478e..44192ae 100644 --- a/src/coreclr/src/vm/pefile.inl +++ b/src/coreclr/src/vm/pefile.inl @@ -1338,6 +1338,23 @@ inline BOOL PEFile::HasNativeImage() #endif } +inline BOOL PEFile::HasNativeOrReadyToRunImage() +{ + CONTRACTL + { + INSTANCE_CHECK; + NOTHROW; + GC_NOTRIGGER; + MODE_ANY; + SO_TOLERANT; + CANNOT_TAKE_LOCK; + SUPPORTS_DAC; + } + CONTRACTL_END; + + return (HasNativeImage() || IsILImageReadyToRun()); +} + inline PTR_PEImageLayout PEFile::GetLoadedIL() { LIMITED_METHOD_CONTRACT; diff --git a/src/coreclr/src/vm/readytoruninfo.cpp b/src/coreclr/src/vm/readytoruninfo.cpp index 6a47aa8..623556d 100644 --- a/src/coreclr/src/vm/readytoruninfo.cpp +++ b/src/coreclr/src/vm/readytoruninfo.cpp @@ -590,17 +590,29 @@ ReadyToRunInfo::ReadyToRunInfo(Module * pModule, PEImageLayout * pLayout, READYT m_entryPointToMethodDescMap.Init(TRUE, &lock); } - //In format version >= 2.1 there is an optional inlining table - if (IsImageVersionAtLeast(2, 1)) - { - IMAGE_DATA_DIRECTORY * pInlineTrackingInfoDir = FindSection(READYTORUN_SECTION_INLINING_INFO); - if (pInlineTrackingInfoDir != NULL) - { - const BYTE* pInlineTrackingMapData = (const BYTE*)GetImage()->GetDirectoryData(pInlineTrackingInfoDir); - PersistentInlineTrackingMapR2R::TryLoad(pModule, pInlineTrackingMapData, pInlineTrackingInfoDir->Size, - pamTracker, &m_pPersistentInlineTrackingMap); - } - } + // For format version 2.1 and later, there is an optional inlining table + if (IsImageVersionAtLeast(2, 1)) + { + IMAGE_DATA_DIRECTORY * pInlineTrackingInfoDir = FindSection(READYTORUN_SECTION_INLINING_INFO); + if (pInlineTrackingInfoDir != NULL) + { + const BYTE* pInlineTrackingMapData = (const BYTE*)GetImage()->GetDirectoryData(pInlineTrackingInfoDir); + PersistentInlineTrackingMapR2R::TryLoad(pModule, pInlineTrackingMapData, pInlineTrackingInfoDir->Size, + pamTracker, &m_pPersistentInlineTrackingMap); + } + } + // Fpr format version 2.2 and later, there is an optional profile-data section + if (IsImageVersionAtLeast(2, 2)) + { + IMAGE_DATA_DIRECTORY * pProfileDataInfoDir = FindSection(READYTORUN_SECTION_PROFILEDATA_INFO); + if (pProfileDataInfoDir != NULL) + { + CORCOMPILE_METHOD_PROFILE_LIST * pMethodProfileList; + pMethodProfileList = (CORCOMPILE_METHOD_PROFILE_LIST *)GetImage()->GetDirectoryData(pProfileDataInfoDir); + + pModule->SetMethodProfileList(pMethodProfileList); + } + } } static bool SigMatchesMethodDesc(MethodDesc* pMD, SigPointer &sig, Module * pModule) diff --git a/src/coreclr/src/zap/zapheaders.cpp b/src/coreclr/src/zap/zapheaders.cpp index ecb32c0..acec36b 100644 --- a/src/coreclr/src/zap/zapheaders.cpp +++ b/src/coreclr/src/zap/zapheaders.cpp @@ -95,7 +95,7 @@ void ZapImage::SaveNativeHeader() // Pretend that ready-to-run images are IL-only nativeHeader.COR20Flags |= COMIMAGE_FLAGS_ILONLY; - // Pretend that ready-to-run images do not have native header + // Pretend that ready-to-run images do not have a native header nativeHeader.COR20Flags &= ~COMIMAGE_FLAGS_IL_LIBRARY; // Remember whether the source IL image had ReadyToRun header diff --git a/src/coreclr/src/zap/zapimage.cpp b/src/coreclr/src/zap/zapimage.cpp index 0267829..457b82e 100644 --- a/src/coreclr/src/zap/zapimage.cpp +++ b/src/coreclr/src/zap/zapimage.cpp @@ -1753,6 +1753,7 @@ void ZapImage::Compile() OutputDebugInfoForReadyToRun(); OutputTypesTableForReadyToRun(m_pMDImport); OutputInliningTableForReadyToRun(); + OutputProfileDataForReadyToRun(); } else #endif diff --git a/src/coreclr/src/zap/zapimage.h b/src/coreclr/src/zap/zapimage.h index 65347ff..f014fd2 100644 --- a/src/coreclr/src/zap/zapimage.h +++ b/src/coreclr/src/zap/zapimage.h @@ -558,6 +558,7 @@ private: void OutputDebugInfoForReadyToRun(); void OutputTypesTableForReadyToRun(IMDInternalImport * pMDImport); void OutputInliningTableForReadyToRun(); + void OutputProfileDataForReadyToRun(); void CopyDebugDirEntry(); void CopyWin32VersionResource(); diff --git a/src/coreclr/src/zap/zapper.cpp b/src/coreclr/src/zap/zapper.cpp index 904b9d1..50e86db 100644 --- a/src/coreclr/src/zap/zapper.cpp +++ b/src/coreclr/src/zap/zapper.cpp @@ -1657,19 +1657,16 @@ ZapImage * Zapper::CompileModule(CORINFO_MODULE_HANDLE hModule, module->Compile(); - if (IsReadyToRunCompilation()) + if (!IsReadyToRunCompilation()) { - return module.Extract(); - } - - // - // Link preloaded module. - // - - Info(W("Linking preloaded input file %s\n"), module->m_pModuleFileName); + // + // Link preloaded module. + // - module->LinkPreload(); + Info(W("Linking preloaded input file %s\n"), module->m_pModuleFileName); + module->LinkPreload(); + } return module.Extract(); } diff --git a/src/coreclr/src/zap/zapreadytorun.cpp b/src/coreclr/src/zap/zapreadytorun.cpp index 8ed3f55..e67f9d3 100644 --- a/src/coreclr/src/zap/zapreadytorun.cpp +++ b/src/coreclr/src/zap/zapreadytorun.cpp @@ -389,6 +389,14 @@ void ZapImage::OutputInliningTableForReadyToRun() GetReadyToRunHeader()->RegisterSection(READYTORUN_SECTION_INLINING_INFO, pBlob); } +void ZapImage::OutputProfileDataForReadyToRun() +{ + if (m_pInstrumentSection != nullptr) + { + GetReadyToRunHeader()->RegisterSection(READYTORUN_SECTION_PROFILEDATA_INFO, m_pInstrumentSection); + } +} + void ZapImage::OutputTypesTableForReadyToRun(IMDInternalImport * pMDImport) { NativeWriter writer;