Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update MulticoreJit #39996

Merged
merged 2 commits into from
Oct 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/coreclr/src/vm/compile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1168,6 +1168,8 @@ void CEECompileInfo::EncodeMethod(
STANDARD_VM_CONTRACT;

COOPERATIVE_TRANSITION_BEGIN();

_ASSERTE(referencingModule);
MethodDesc *pMethod = GetMethod(handle);

BOOL fSuccess;
Expand Down
205 changes: 177 additions & 28 deletions src/coreclr/src/vm/multicorejit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
#include "multicorejit.h"
#include "multicorejitimpl.h"


void MulticoreJitFireEtw(const WCHAR * pAction, const WCHAR * pTarget, int p1, int p2, int p3)
{
LIMITED_METHOD_CONTRACT
Expand Down Expand Up @@ -326,8 +325,6 @@ bool RecorderModuleInfo::SetModule(Module * pMod)
return moduleVersion.GetModuleVersion(pMod);
}



/////////////////////////////////////////////////////
//
// class MulticoreJitRecorder
Expand Down Expand Up @@ -381,14 +378,67 @@ HRESULT MulticoreJitRecorder::WriteOutput(IStream * pStream)
CONTRACTL
{
NOTHROW;
GC_NOTRIGGER;
GC_TRIGGERS;
MODE_PREEMPTIVE;
CAN_TAKE_LOCK;
}
CONTRACTL_END;

HRESULT hr = S_OK;

// Preprocessing Generic Methods
// - Add ModuleDependency to JITInfo
// - Increment MethodCount in Module
RecorderGenericInfo* genericInfoArray = new (nothrow) RecorderGenericInfo[m_GenericInfoCount]();
LONG skippedGeneric = 0;
if (genericInfoArray != nullptr)
{
for (LONG i = 0 ; i < m_GenericInfoCount; i++)
{
SigBuilder sigBuilder;
MethodDesc * pMethod = m_GenericInfoArray[i];
Module * pModule = pMethod->GetModule();
unsigned moduleIndex = FindModule(pModule);
_ASSERTE(moduleIndex < UINT_MAX);

BOOL fSuccess = false;
EX_TRY
{
fSuccess = ZapSig::EncodeMethod(pMethod, NULL, &sigBuilder, (LPVOID)this, (ENCODEMODULE_CALLBACK)MulticoreJitManager::EncodeModuleHelper, NULL);
}
EX_CATCH
{
}
EX_END_CATCH(SwallowAllExceptions);

if (!fSuccess)
{
skippedGeneric++;
continue;
}

DWORD dwLength;
BYTE * pBlob = (BYTE*)sigBuilder.GetSignature(&dwLength);
_ASSERTE(dwLength <= 0xFFFFFF);
BYTE * pSignature = new (nothrow) BYTE[dwLength];
if (pSignature == nullptr)
{
skippedGeneric++;
continue;
}

memcpy(pSignature, pBlob, dwLength);
unsigned info = Pack8_24(moduleIndex, dwLength & 0xFFFFFF);
genericInfoArray[i].genericInfo = info;
genericInfoArray[i].genericSignature = pSignature;
m_ModuleList[moduleIndex].methodCount ++;
}
}
else
{
skippedGeneric = m_GenericInfoCount;
}

{
HeaderRecord header;

Expand All @@ -397,7 +447,10 @@ HRESULT MulticoreJitRecorder::WriteOutput(IStream * pStream)
header.recordID = Pack8_24(MULTICOREJIT_HEADER_RECORD_ID, sizeof(HeaderRecord));
header.version = MULTICOREJIT_PROFILE_VERSION;
header.moduleCount = m_ModuleCount;
header.methodCount = m_JitInfoCount - m_ModuleDepCount;
header.methodCount = m_JitInfoCount
+ m_GenericInfoCount - skippedGeneric
- m_ModuleDepCount;

header.moduleDepCount = m_ModuleDepCount;

MulticoreJitCodeStorage & curStorage = m_pDomain->GetMulticoreJitManager().GetMulticoreJitCodeStorage();
Expand Down Expand Up @@ -462,6 +515,50 @@ HRESULT MulticoreJitRecorder::WriteOutput(IStream * pStream)
}
}

if (SUCCEEDED(hr) && genericInfoArray != nullptr)
{
for (LONG i = 0 ; i < m_GenericInfoCount && SUCCEEDED(hr); i++)
{
unsigned info = genericInfoArray[i].genericInfo;
BYTE * pSignature = genericInfoArray[i].genericSignature;
if (info == 0 && pSignature == nullptr)
{
continue;
}

DWORD sigSize = info & 0xFFFFFF;
DWORD dataSize = sigSize * sizeof(BYTE) + sizeof(DWORD) * 2;
DWORD dwSize = ((DWORD)(dataSize + sizeof(DWORD) - 1) / sizeof(DWORD)) * sizeof(DWORD);
_ASSERTE(dwSize <= 0xFFFFFF);
dwData = Pack8_24(MULTICOREJIT_GENERICINF_RECORD_ID, dwSize);
hr = WriteData(pStream, &dwData, sizeof(dwData));
if (SUCCEEDED(hr))
{
hr = WriteData(pStream, &info, sizeof(unsigned));
}

if (SUCCEEDED(hr))
{
hr = WriteData(pStream, pSignature, sizeof(BYTE) * sigSize);
}

if (SUCCEEDED(hr))
{
DWORD init = 0;
hr = WriteData(pStream, &init, dwSize - dataSize);
}
}
}

if (genericInfoArray != nullptr)
{
for (LONG i = 0; i < m_GenericInfoCount; i++)
{
delete [] genericInfoArray[i].genericSignature;
}
delete [] genericInfoArray;
}

MulticoreJitTrace(("New profile: %d modules, %d methods", m_ModuleCount, m_JitInfoCount));

_FireEtwMulticoreJit(W("WRITEPROFILE"), m_fullFileName.GetUnicode(), m_ModuleCount, m_JitInfoCount, 0);
Expand All @@ -488,7 +585,7 @@ unsigned MulticoreJitRecorder::FindModule(Module * pModule)

// Find known module index, or add to module table
// Return UINT_MAX when table is full, or SetModule fails
unsigned MulticoreJitRecorder::GetModuleIndex(Module * pModule)
unsigned MulticoreJitRecorder::GetOrAddModuleIndex(Module * pModule)
{
STANDARD_VM_CONTRACT;

Expand Down Expand Up @@ -548,6 +645,18 @@ void MulticoreJitRecorder::RecordJitInfo(unsigned module, unsigned method)
}
}

void MulticoreJitRecorder::RecordGenericInfo(MethodDesc * pMethod)
{
LIMITED_METHOD_CONTRACT;

// To avoid recording overhead, records only method desc.
if (m_GenericInfoCount < (LONG) MAX_GENERIC_ARRAY)
{
m_GenericInfoArray[m_GenericInfoCount] = pMethod;
m_GenericInfoCount++;
}
}

class MulticoreJitRecorderModuleEnumerator : public MulticoreJitModuleEnumerator
{
MulticoreJitRecorder * m_pRecorder;
Expand Down Expand Up @@ -590,7 +699,7 @@ void MulticoreJitRecorder::AddModuleDependency(Module * pModule, FileLoadLevel l

_FireEtwMulticoreJitA(W("ADDMODULEDEPENDENCY"), pModule->GetSimpleName(), loadLevel, 0, 0);

unsigned moduleTo = GetModuleIndex(pModule);
unsigned moduleTo = GetOrAddModuleIndex(pModule);

if (moduleTo != UINT_MAX)
{
Expand All @@ -604,6 +713,27 @@ void MulticoreJitRecorder::AddModuleDependency(Module * pModule, FileLoadLevel l
}
}

DWORD MulticoreJitRecorder::EncodeModule(Module * pReferencedModule)
{
STANDARD_VM_CONTRACT;

unsigned slot = GetOrAddModuleIndex(pReferencedModule);
FileLoadLevel loadLevel = MulticoreJitManager::GetModuleFileLoadLevel(pReferencedModule);

if (slot != UINT_MAX)
{
if (m_ModuleList[slot].loadLevel < loadLevel)
{
m_ModuleList[slot].loadLevel = loadLevel;

// Update load level
RecordJitInfo(0, ((unsigned) loadLevel << 8) | slot | MODULE_DEPENDENCY);
}
m_ModuleList[slot].methodCount++;
return (DWORD)slot;
}
return ENCODE_MODULE_FAILED;
}

// Enumerate all modules within an assembly, call OnModule virtual method
HRESULT MulticoreJitModuleEnumerator::HandleAssembly(DomainAssembly * pAssembly)
Expand Down Expand Up @@ -740,29 +870,39 @@ void MulticoreJitRecorder::RecordMethodJit(MethodDesc * pMethod, bool applicatio
}

// pModule could be unknown at this point (modules not enumerated, no event received yet)
unsigned moduleIndex = GetModuleIndex(pModule);
unsigned moduleIndex = GetOrAddModuleIndex(pModule);

if (moduleIndex < UINT_MAX)
if (moduleIndex >= UINT_MAX)
{
if (m_fFirstMethod)
{
PreRecordFirstMethod();
}
return;
}

// Make sure level for current module is recorded properly
if (m_ModuleList[moduleIndex].loadLevel != FILE_ACTIVE)
{
FileLoadLevel needLevel = MulticoreJitManager::GetModuleFileLoadLevel(pModule);
if (m_fFirstMethod)
{
PreRecordFirstMethod();
}

if (m_ModuleList[moduleIndex].loadLevel < needLevel)
{
m_ModuleList[moduleIndex].loadLevel = needLevel;
// Make sure level for current module is recorded properly
// Module dependency for generic and stub as well as regular method are handled in JitInfo.
// Any module dependencies for all types of methods would be handled with JitInfo before they are attempted to be multicorejitted.
if (m_ModuleList[moduleIndex].loadLevel != FILE_ACTIVE)
{
FileLoadLevel needLevel = MulticoreJitManager::GetModuleFileLoadLevel(pModule);

// Update load level
RecordJitInfo(0, ((unsigned) needLevel << 8) | moduleIndex | MODULE_DEPENDENCY);
}
}
if (m_ModuleList[moduleIndex].loadLevel < needLevel)
{
m_ModuleList[moduleIndex].loadLevel = needLevel;

// Update load level
RecordJitInfo(0, ((unsigned) needLevel << 8) | moduleIndex | MODULE_DEPENDENCY);
}
}
if (!pMethod->IsTypicalSharedInstantiation())
kouvel marked this conversation as resolved.
Show resolved Hide resolved
{
RecordGenericInfo(pMethod);
}
else
{
unsigned methodIndex = pMethod->GetMemberDef_NoLogging() & 0xFFFFFF;

if (methodIndex <= METHODINDEX_MASK)
Expand Down Expand Up @@ -994,7 +1134,6 @@ MulticoreJitCodeInfo MulticoreJitRecorder::RequestMethodCode(MethodDesc * pMetho
return codeInfo;
}


//////////////////////////////////////////////////////////
//
// class MulticoreJitManager: attachment to AppDomain
Expand Down Expand Up @@ -1339,9 +1478,8 @@ bool MulticoreJitManager::IsMethodSupported(MethodDesc * pMethod)
}
CONTRACTL_END;

return pMethod->HasILHeader() &&
pMethod->IsTypicalSharedInstantiation() &&
! pMethod->IsDynamicMethod();
return !pMethod->IsDynamicMethod() &&
!pMethod->GetLoaderAllocator()->IsCollectible();
}


Expand Down Expand Up @@ -1397,6 +1535,17 @@ void MulticoreJitManager::DisableMulticoreJit()
#endif
}

// static
DWORD MulticoreJitManager::EncodeModuleHelper(void * pModuleContext, Module * pReferencedModule)
{
STANDARD_VM_CONTRACT

if (pModuleContext == NULL || pReferencedModule == NULL)
{
return ENCODE_MODULE_FAILED;
}
return ((MulticoreJitRecorder*)pModuleContext)->EncodeModule(pReferencedModule);
}

//---------------------------------------------------------------------------------------
//
Expand Down
5 changes: 5 additions & 0 deletions src/coreclr/src/vm/multicorejit.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#define __MULTICORE_JIT_H__

class MulticoreJitRecorder;
class MulticoreJitProfilePlayer;


class MulticoreJitCounter
Expand Down Expand Up @@ -300,7 +301,11 @@ class MulticoreJitManager

static bool ModuleHasNoCode(Module * pModule);

static DWORD EncodeModuleHelper(void * pModuleContext,
Module * pReferencedModule);

static Module * DecodeModuleFromIndex(void * pModuleContext,
DWORD ix);
};


Expand Down
Loading