Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Commit

Permalink
Work for IBC profiling with ReadyToRun images
Browse files Browse the repository at this point in the history
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
  • Loading branch information
briansull committed Mar 13, 2017
1 parent a7bed22 commit c67474b
Show file tree
Hide file tree
Showing 17 changed files with 209 additions and 65 deletions.
9 changes: 7 additions & 2 deletions src/inc/readytorun.h
Expand Up @@ -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
{
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 2 additions & 0 deletions src/inc/readytorunhelpers.h
Expand Up @@ -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, )
Expand Down
27 changes: 25 additions & 2 deletions src/jit/flowgraph.cpp
Expand Up @@ -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);
Expand Down
8 changes: 0 additions & 8 deletions src/tools/crossgen/crossgen.cpp
Expand Up @@ -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.
Expand Down
6 changes: 3 additions & 3 deletions src/utilcode/pedecoder.cpp
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
43 changes: 31 additions & 12 deletions src/vm/assembly.cpp
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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()
Expand All @@ -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
Expand Down
12 changes: 10 additions & 2 deletions src/vm/assembly.hpp
Expand Up @@ -551,7 +551,7 @@ class Assembly

BOOL IsSIMDVectorAssembly() { LIMITED_METHOD_DAC_CONTRACT; return m_fIsSIMDVectorAssembly; }

#ifdef FEATURE_PREJIT
#ifdef FEATURE_PREJIT
BOOL IsInstrumented();
BOOL IsInstrumentedHelper();
#endif // FEATURE_PREJIT
Expand Down Expand Up @@ -704,7 +704,6 @@ class Assembly
// Keep track of the vars that need to be freed.
short int m_FreeFlag;


private:

//****************************************************************************************
Expand Down Expand Up @@ -775,6 +774,15 @@ class Assembly

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;
Expand Down
79 changes: 65 additions & 14 deletions src/vm/ceeload.cpp
Expand Up @@ -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

Expand All @@ -461,20 +510,6 @@ void Module::InitializeNativeImage(AllocMemTracker* pamTracker)

ExecutionManager::AddNativeImageRange(dac_cast<TADDR>(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();
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down
7 changes: 7 additions & 0 deletions src/vm/ceeload.h
Expand Up @@ -1790,6 +1790,7 @@ class Module
protected:
#ifndef DACCESS_COMPILE
virtual void Initialize(AllocMemTracker *pamTracker, LPCWSTR szName = NULL);
void InitializeForProfiling();
#ifdef FEATURE_PREJIT
void InitializeNativeImage(AllocMemTracker* pamTracker);
#endif
Expand Down Expand Up @@ -2734,6 +2735,8 @@ class Module
}
#endif // FEATURE_PREJIT


BOOL HasNativeOrReadyToRunImage();
PEImageLayout * GetNativeOrReadyToRunImage();
PTR_CORCOMPILE_IMPORT_SECTION GetImportSections(COUNT_T *pCount);
PTR_CORCOMPILE_IMPORT_SECTION GetImportSectionFromIndex(COUNT_T index);
Expand Down Expand Up @@ -3066,6 +3069,10 @@ class Module
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();
Expand Down
1 change: 1 addition & 0 deletions src/vm/pefile.h
Expand Up @@ -378,6 +378,7 @@ class PEFile
PEImage *GetNativeImageWithRef();
PEImage *GetPersistentNativeImage();
#endif
BOOL HasNativeOrReadyToRunImage();
BOOL HasNativeImage();
PTR_PEImageLayout GetLoaded();
PTR_PEImageLayout GetLoadedNative();
Expand Down
17 changes: 17 additions & 0 deletions src/vm/pefile.inl
Expand Up @@ -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;
Expand Down

0 comments on commit c67474b

Please sign in to comment.