Skip to content

Commit

Permalink
Update MulticoreJit (#39996)
Browse files Browse the repository at this point in the history
- Enable Generic Methods in MulticoreJit
- Enable NDirect Stub in MulticoreJit
  • Loading branch information
clamp03 authored Oct 20, 2020
1 parent 7664a9a commit 781077f
Show file tree
Hide file tree
Showing 10 changed files with 429 additions and 79 deletions.
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())
{
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

0 comments on commit 781077f

Please sign in to comment.