From 64694c2301605594d9a1d5b5b7fa4165302d4e78 Mon Sep 17 00:00:00 2001 From: Sergey Andreenko Date: Mon, 28 Aug 2017 18:14:50 -0700 Subject: [PATCH] SuperPMI replay: fix enviroment variables initialization. (#13596) SuperPMI replay: fix enviroment variables initialization. If we have mch with mc files with different ENV_variables, we ran them with the set for the first mc. --- .../superpmi/superpmi-shared/methodcontext.cpp | 43 ++++++++++++++++++++++ .../superpmi/superpmi-shared/methodcontext.h | 3 ++ .../superpmi-shared/methodcontextreader.cpp | 4 ++ src/ToolBox/superpmi/superpmi/jithost.h | 2 +- src/ToolBox/superpmi/superpmi/jitinstance.cpp | 15 ++++++++ src/ToolBox/superpmi/superpmi/jitinstance.h | 2 + src/ToolBox/superpmi/superpmi/superpmi.cpp | 15 ++++++++ src/jit/ee_il_dll.cpp | 14 +++++++ 8 files changed, 97 insertions(+), 1 deletion(-) diff --git a/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp b/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp index b33e031..eb3b189 100644 --- a/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp @@ -6061,3 +6061,46 @@ OnError: #endif // !FEATURE_PAL } + +DenseLightWeightMap* MethodContext::prevEnviroment = nullptr; + +bool MethodContext::wasEnviromentChanged() +{ + bool changed = false; + if (prevEnviroment == nullptr) + { + changed = true; + } + else if (Environment->GetCount() != prevEnviroment->GetCount()) + { + changed = true; + } + else + { + for (unsigned int i = 0; i < Environment->GetCount(); i++) + { + Agnostic_Environment currEnvValue = Environment->Get(i); + LPCSTR currKey = (LPCSTR)Environment->GetBuffer(currEnvValue.name_index); + LPCSTR currVal = (LPCSTR)Environment->GetBuffer(currEnvValue.val_index); + + Agnostic_Environment prevEnvValue = prevEnviroment->Get(i); + LPCSTR prevKey = (LPCSTR)prevEnviroment->GetBuffer(prevEnvValue.name_index); + LPCSTR prevVal = (LPCSTR)prevEnviroment->GetBuffer(prevEnvValue.val_index); + if (strcmp(currKey, prevKey) != 0 || strcmp(currVal, prevVal) != 0) + { + changed = true; + break; + } + } + } + if (changed) + { + if (prevEnviroment == nullptr) + { + delete prevEnviroment; + } + prevEnviroment = new DenseLightWeightMap(*Environment); + return true; + } + return false; +} diff --git a/src/ToolBox/superpmi/superpmi-shared/methodcontext.h b/src/ToolBox/superpmi/superpmi-shared/methodcontext.h index d2f43b4..83c1677 100644 --- a/src/ToolBox/superpmi/superpmi-shared/methodcontext.h +++ b/src/ToolBox/superpmi/superpmi-shared/methodcontext.h @@ -1233,6 +1233,9 @@ public: void dmpGetStringConfigValue(DWORD nameIndex, DWORD result); const wchar_t* repGetStringConfigValue(const wchar_t* name); + bool wasEnviromentChanged(); + static DenseLightWeightMap* prevEnviroment; + CompileResult* cr; CompileResult* originalCR; int index; diff --git a/src/ToolBox/superpmi/superpmi-shared/methodcontextreader.cpp b/src/ToolBox/superpmi/superpmi-shared/methodcontextreader.cpp index 6b40839..8d1930f 100644 --- a/src/ToolBox/superpmi/superpmi-shared/methodcontextreader.cpp +++ b/src/ToolBox/superpmi/superpmi-shared/methodcontextreader.cpp @@ -121,6 +121,10 @@ MethodContextReader::MethodContextReader( MethodContextReader::~MethodContextReader() { + if (MethodContext::prevEnviroment != nullptr) + { + delete MethodContext::prevEnviroment; + } if (fileHandle != INVALID_HANDLE_VALUE) { CloseHandle(this->fileHandle); diff --git a/src/ToolBox/superpmi/superpmi/jithost.h b/src/ToolBox/superpmi/superpmi/jithost.h index 60181cd..9e31e43 100644 --- a/src/ToolBox/superpmi/superpmi/jithost.h +++ b/src/ToolBox/superpmi/superpmi/jithost.h @@ -6,7 +6,7 @@ #ifndef _JITHOST #define _JITHOST -class JitHost : public ICorJitHost +class JitHost final: public ICorJitHost { public: JitHost(JitInstance& jitInstance); diff --git a/src/ToolBox/superpmi/superpmi/jitinstance.cpp b/src/ToolBox/superpmi/superpmi/jitinstance.cpp index e463f82..7902c39 100644 --- a/src/ToolBox/superpmi/superpmi/jitinstance.cpp +++ b/src/ToolBox/superpmi/superpmi/jitinstance.cpp @@ -429,3 +429,18 @@ void JitInstance::freeLongLivedArray(void* array) { HeapFree(ourHeap, 0, array); } + +// Reset JitConfig, that stores Enviroment variables. +bool JitInstance::resetConfig(MethodContext* firstContext) +{ + if (pnjitStartup != nullptr) + { + mc = firstContext; + ICorJitHost* newHost = new JitHost(*this); + pnjitStartup(newHost); + delete static_cast(jitHost); + jitHost = newHost; + return true; + } + return false; +} diff --git a/src/ToolBox/superpmi/superpmi/jitinstance.h b/src/ToolBox/superpmi/superpmi/jitinstance.h index 9db17dc..3b4d22c 100644 --- a/src/ToolBox/superpmi/superpmi/jitinstance.h +++ b/src/ToolBox/superpmi/superpmi/jitinstance.h @@ -46,6 +46,8 @@ public: HRESULT StartUp(char* PathToJit, bool copyJit, bool breakOnDebugBreakorAV, MethodContext* firstContext); bool reLoad(MethodContext* firstContext); + bool resetConfig(MethodContext* firstContext); + Result CompileMethod(MethodContext* MethodToCompile, int mcIndex, bool collectThroughput); void* allocateArray(ULONG size); diff --git a/src/ToolBox/superpmi/superpmi/superpmi.cpp b/src/ToolBox/superpmi/superpmi/superpmi.cpp index 58d7787..c98c053 100644 --- a/src/ToolBox/superpmi/superpmi/superpmi.cpp +++ b/src/ToolBox/superpmi/superpmi/superpmi.cpp @@ -313,6 +313,21 @@ int __cdecl main(int argc, char* argv[]) mc->cr = new CompileResult(); mc->originalCR = crl; + if (mc->wasEnviromentChanged()) + { + if (!jit->resetConfig(mc)) + { + LogError("JIT can't reset enviroment"); + } + if (o.nameOfJit2 != nullptr) + { + if (!jit2->resetConfig(mc)) + { + LogError("JIT2 can't reset enviroment"); + } + } + } + jittedCount++; st3.Start(); res = jit->CompileMethod(mc, reader->GetMethodContextIndex(), collectThroughput); diff --git a/src/jit/ee_il_dll.cpp b/src/jit/ee_il_dll.cpp index 553a9b8..b32d59f 100644 --- a/src/jit/ee_il_dll.cpp +++ b/src/jit/ee_il_dll.cpp @@ -58,6 +58,20 @@ extern "C" void __stdcall jitStartup(ICorJitHost* jitHost) { if (g_jitInitialized) { + if (jitHost != g_jitHost) + { + // We normally don't expect jitStartup() to be invoked more than once. + // (We check whether it has been called once due to an abundance of caution.) + // However, during SuperPMI playback of MCH file, we need to JIT many different methods. + // Each one carries its own environment configuration state. + // So, we need the JIT to reload the JitConfig state for each change in the environment state of the + // replayed compilations. + // We do this by calling jitStartup with a different ICorJitHost, + // and have the JIT re-initialize its JitConfig state when this happens. + JitConfig.destroy(g_jitHost); + JitConfig.initialize(jitHost); + g_jitHost = jitHost; + } return; } -- 2.7.4