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.
#endif // !FEATURE_PAL
}
+
+DenseLightWeightMap<MethodContext::Agnostic_Environment>* 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<Agnostic_Environment>(*Environment);
+ return true;
+ }
+ return false;
+}
void dmpGetStringConfigValue(DWORD nameIndex, DWORD result);
const wchar_t* repGetStringConfigValue(const wchar_t* name);
+ bool wasEnviromentChanged();
+ static DenseLightWeightMap<Agnostic_Environment>* prevEnviroment;
+
CompileResult* cr;
CompileResult* originalCR;
int index;
MethodContextReader::~MethodContextReader()
{
+ if (MethodContext::prevEnviroment != nullptr)
+ {
+ delete MethodContext::prevEnviroment;
+ }
if (fileHandle != INVALID_HANDLE_VALUE)
{
CloseHandle(this->fileHandle);
#ifndef _JITHOST
#define _JITHOST
-class JitHost : public ICorJitHost
+class JitHost final: public ICorJitHost
{
public:
JitHost(JitInstance& jitInstance);
{
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);
+ jitHost = newHost;
+ return true;
+ }
+ return false;
+}
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);
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);
{
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;
}