LWM(EmbedMethodHandle, DWORDLONG, DLDL)
LWM(EmbedModuleHandle, DWORDLONG, DLDL)
DENSELWM(EmptyStringLiteral, DLD)
-DENSELWM(Environment, Agnostic_Environment)
DENSELWM(ErrorList, DWORD)
LWM(FilterException, DWORD, DWORD)
LWM(FindCallSiteSig, Agnostic_FindCallSiteSig, Agnostic_CORINFO_SIG_INFO)
#include "spmirecordhelper.h"
#include "spmidumphelper.h"
-struct
-{
- int packetID;
- const char* message;
-} retiredPackets[] = {
- {6, "CanEmbedModuleHandleForHelper id 6 superseded by GetLazyStringLiteralHelper id 147 on 12/20/2013"},
- {13, "CheckMethodModifier id 13 superseded by id 142 on 2013/07/04. Re-record input with newer shim."},
- {14, "CompileMethod id 14 superseded by id 141 on 2013/07/03. Re-record input with newer shim."},
- {24, "FindNameOfToken id 24 superseded by id 145 on 2013/07/19. Re-record input with newer shim. Adjusted members "
- "to be proper."},
- {28, "GetArgClass id 28 superseded by id 139 on 2013/07/03. Re-record input with newer shim."},
- {30, "GetArgType id 30 superseded by id 140 on 2013/07/03. Re-record input with newer shim."},
- {93, "GetUnBoxHelper2 id 93 unused. 2016/02/19. Re-record input with newer shim."},
- {104, "IsValidToken id 104 superseded by id 144 on 2013/07/19. Re-record input with newer shim. Adjusted members "
- "to be proper."},
- {141, "CompileMethod id 141 superseded by id 142 on 2013/07/09. Re-record input with newer shim. We basically "
- "reset lots of other stuff too. :-)"},
-};
-int retiredPacketCount = 7;
-
#define sparseMC // Support filling in details where guesses are okay and will still generate good code. (i.e. helper
// function addresses)
while (buffIndex < totalLen)
{
- unsigned char packetType = buff2[buffIndex++];
+ mcPackets packetType = (mcPackets)buff2[buffIndex++];
memcpy(&localsize, &buff2[buffIndex], sizeof(unsigned int));
buffIndex += 4;
#include "crlwmlist.h"
default:
- for (int i = 0; i < retiredPacketCount; i++)
- {
- AssertCodeMsg(retiredPackets[i].packetID != packetType, EXCEPTIONCODE_MC,
- "Ran into retired packet %u '%s'", packetType, retiredPackets[i].message);
- }
LogException(EXCEPTIONCODE_MC, "Read ran into unknown packet type %u. Are you using a newer recorder?",
packetType);
// break;
}
}
-void MethodContext::dmpEnvironment(DWORD key, const Agnostic_Environment& value)
-{
-}
-
void MethodContext::dumpToConsole(int mcNumber)
{
printf("*****************************************");
#endif // !FEATURE_PAL
}
-DenseLightWeightMap<MethodContext::Agnostic_Environment>* MethodContext::prevEnviroment = nullptr;
+MethodContext::Environment MethodContext::cloneEnvironment()
+{
+ MethodContext::Environment env;
+ if (GetIntConfigValue != nullptr)
+ {
+ env.getIntConfigValue = new LightWeightMap<MethodContext::Agnostic_ConfigIntInfo, DWORD>(*GetIntConfigValue);
+ }
+ if (GetStringConfigValue != nullptr)
+ {
+ env.getStingConfigValue = new LightWeightMap<DWORD, DWORD>(*GetStringConfigValue);
+ }
+ return env;
+}
-bool MethodContext::wasEnviromentChanged()
+// Check that there is a difference between the current enviroment variables maps and the prevEnv.
+bool MethodContext::WasEnvironmentChanged(const Environment& prevEnv)
{
- bool changed = false;
- if (prevEnviroment == nullptr)
+ if (!IsEnvironmentHeaderEqual(prevEnv))
{
- changed = true;
+ return true;
}
- else if (Environment->GetCount() != prevEnviroment->GetCount())
+ if (!IsEnvironmentContentEqual(prevEnv))
{
- changed = true;
+ return true;
}
- else
+ return false;
+}
+
+// Check that environment maps headers are equal to the prevEnv maps headers.
+bool MethodContext::IsEnvironmentHeaderEqual(const Environment& prevEnv)
+{
+ if (!AreLWMHeadersEqual(prevEnv.getIntConfigValue, GetIntConfigValue))
+ {
+ return false;
+ }
+ if (!AreLWMHeadersEqual(prevEnv.getStingConfigValue, GetStringConfigValue))
+ {
+ return false;
+ }
+ return true;
+}
+
+// Check that environment maps content is equal to the prevEnv content.
+bool MethodContext::IsEnvironmentContentEqual(const Environment& prevEnv)
+{
+ if (!IsIntConfigContentEqual(prevEnv.getIntConfigValue, GetIntConfigValue))
+ {
+ return false;
+ }
+ if (!IsStringContentEqual(prevEnv.getStingConfigValue, GetStringConfigValue))
+ {
+ return false;
+ }
+ return true;
+}
+
+// Check pointers to be both initizlized or null and number of keys to be equal.
+template <typename key, typename value>
+bool MethodContext::AreLWMHeadersEqual(LightWeightMap<key, value>* prev, LightWeightMap<key, value>* curr)
+{
+ if (prev == nullptr && curr == nullptr)
+ {
+ return true;
+ }
+ if (prev != nullptr && curr != nullptr)
{
- for (unsigned int i = 0; i < Environment->GetCount(); i++)
+ if (prev->GetCount() == curr->GetCount())
{
- 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;
- }
+ return true;
}
}
- if (changed)
+ return false;
+}
+
+bool MethodContext::IsIntConfigContentEqual(LightWeightMap<Agnostic_ConfigIntInfo, DWORD>* prev,
+ LightWeightMap<Agnostic_ConfigIntInfo, DWORD>* curr)
+{
+ if (prev != nullptr && curr != nullptr)
{
- if (prevEnviroment != nullptr)
+ if (prev->GetCount() != curr->GetCount())
{
- delete prevEnviroment;
+ return false;
}
- if (Environment != nullptr)
+
+ for (unsigned i = 0; i < prev->GetCount(); ++i)
{
- prevEnviroment = new DenseLightWeightMap<Agnostic_Environment>(*Environment);
+ DWORD currValue = curr->GetItem(i);
+ DWORD prevValue = prev->GetItem(i);
+ if (currValue != prevValue)
+ {
+ return false;
+ }
+
+ Agnostic_ConfigIntInfo currKey = curr->GetKey(i);
+ Agnostic_ConfigIntInfo prevKey = prev->GetKey(i);
+
+ if (currKey.defaultValue != prevKey.defaultValue)
+ {
+ return false;
+ }
+
+ DWORD currNameIndex = currKey.nameIndex;
+ LPCSTR currName = (LPCSTR)curr->GetBuffer(currNameIndex);
+ DWORD prevNameIndex = prevKey.nameIndex;
+ LPCSTR prevName = (LPCSTR)prev->GetBuffer(currNameIndex);
+ if (strcmp(currName, prevName) != 0)
+ {
+ return false;
+ }
}
- else
+ return true;
+ }
+ else
+ {
+ return (prev == curr);
+ }
+}
+
+bool MethodContext::IsStringContentEqual(LightWeightMap<DWORD, DWORD>* prev, LightWeightMap<DWORD, DWORD>* curr)
+{
+ if (prev != nullptr && curr != nullptr)
+ {
+ if (prev->GetCount() != curr->GetCount())
+ {
+ return false;
+ }
+
+ for (unsigned i = 0; i < curr->GetCount(); ++i)
{
- prevEnviroment = nullptr;
+ DWORD currKeyIndex = curr->GetKey(i);
+ LPCSTR currKey = (LPCSTR)curr->GetBuffer(currKeyIndex);
+ DWORD prevKeyIndex = prev->GetKey(i);
+ LPCSTR prevKey = (LPCSTR)prev->GetBuffer(prevKeyIndex);
+ if (strcmp(currKey, prevKey) != 0)
+ {
+ return false;
+ }
+
+ DWORD currValueIndex = curr->GetItem(i);
+ LPCSTR currValue = (LPCSTR)curr->GetBuffer(currValueIndex);
+ DWORD prevValueIndex = prev->GetItem(i);
+ LPCSTR prevValue = (LPCSTR)prev->GetBuffer(prevValueIndex);
+ if (strcmp(currValue, prevValue) != 0)
+ {
+ return false;
+ }
}
return true;
}
- return false;
+ else
+ {
+ return (prev == curr);
+ }
}
void dmpGetStringConfigValue(DWORD nameIndex, DWORD result);
const wchar_t* repGetStringConfigValue(const wchar_t* name);
- bool wasEnviromentChanged();
- static DenseLightWeightMap<Agnostic_Environment>* prevEnviroment;
+ struct Environment
+ {
+ Environment() : getIntConfigValue(nullptr), getStingConfigValue(nullptr)
+ {
+ }
+
+ LightWeightMap<MethodContext::Agnostic_ConfigIntInfo, DWORD>* getIntConfigValue;
+ LightWeightMap<DWORD, DWORD>* getStingConfigValue;
+ };
+
+ Environment cloneEnvironment();
+
+ bool WasEnvironmentChanged(const Environment& prevEnv);
CompileResult* cr;
CompileResult* originalCR;
int index;
private:
+ bool IsEnvironmentHeaderEqual(const Environment& prevEnv);
+ bool IsEnvironmentContentEqual(const Environment& prevEnv);
+
+ template <typename key, typename value>
+ static bool AreLWMHeadersEqual(LightWeightMap<key, value>* prev, LightWeightMap<key, value>* curr);
+ static bool IsIntConfigContentEqual(LightWeightMap<Agnostic_ConfigIntInfo, DWORD>* prev,
+ LightWeightMap<Agnostic_ConfigIntInfo, DWORD>* curr);
+ static bool IsStringContentEqual(LightWeightMap<DWORD, DWORD>* prev, LightWeightMap<DWORD, DWORD>* curr);
+
#define LWM(map, key, value) LightWeightMap<key, value>* map;
#define DENSELWM(map, value) DenseLightWeightMap<value>* map;
#include "lwmlist.h"
Packet_EmbedMethodHandle = 19,
Packet_EmbedModuleHandle = 20,
Packet_EmptyStringLiteral = 21,
- Packet_Environment = 136, // Deprecated 7/29/2017
+ Retired9 = 136,
Packet_ErrorList = 22,
Packet_FilterException = 134,
Packet_FindCallSiteSig = 23,
MethodContextReader::~MethodContextReader()
{
- if (MethodContext::prevEnviroment != nullptr)
- {
- delete MethodContext::prevEnviroment;
- }
if (fileHandle != INVALID_HANDLE_VALUE)
{
CloseHandle(this->fileHandle);
#endif // USE_COREDISTOOLS
printf("\n");
printf(" -jitoption [force] key=value\n");
- printf(" Set the JIT option named \"key\" to \"value\" for JIT 1 if the option was not set.");
- printf(" With optional force flag overwrites the existing value if it was already set. NOTE: do not use a "
- "\"COMPlus_\" prefix!\n");
+ printf(" Set the JIT option named \"key\" to \"value\" for JIT 1 if the option was not set.\n");
+ printf(" With optional force flag overwrites the existing value if it was already set.\n");
+ printf(" NOTE: do not use a \"COMPlus_\" prefix, \"key\" and \"value\" are case sensitive!\n");
printf("\n");
printf(" -jit2option [force] key=value\n");
- printf(" Set the JIT option named \"key\" to \"value\" for JIT 2 if the option was not set.");
- printf(" With optional force flag overwrites the existing value if it was already set. NOTE: do not use a "
- "\"COMPlus_\" prefix!\n");
+ printf(" Set the JIT option named \"key\" to \"value\" for JIT 2 if the option was not set.\n");
+ printf(" With optional force flag overwrites the existing value if it was already set.\n");
+ printf(" NOTE: do not use a \"COMPlus_\" prefix, \"key\" and \"value\" are case sensitive!\n");
printf("\n");
printf("Inputs are case sensitive.\n");
printf("\n");
InitIEEMemoryManager(&jitInstance)->ClrVirtualFree(block, 0, 0);
}
+bool JitHost::convertStringValueToInt(const wchar_t* key, const wchar_t* stringValue, int& result)
+{
+ if (stringValue == nullptr)
+ {
+ return false;
+ }
+
+ wchar_t* endPtr;
+ unsigned long longResult = wcstoul(stringValue, &endPtr, 16);
+ bool succeeded = (errno != ERANGE) && (endPtr != stringValue) && (longResult <= INT_MAX);
+ if (!succeeded)
+ {
+ LogWarning("Can't convert int config value from string, key: %ws, string value: %ws\n", key, stringValue);
+ return false;
+ }
+
+ result = static_cast<int>(longResult);
+ return true;
+}
+
int JitHost::getIntConfigValue(const wchar_t* key, int defaultValue)
{
jitInstance.mc->cr->AddCall("getIntConfigValue");
+ // First check the force options, then the mc value. If value is not presented there, probe the JIT options, then
+ // check
+ // the special cases and then the environment.
+
int result = defaultValue;
- const wchar_t* forceValue = jitInstance.getForceOption(key);
+ bool valueFound;
- if (forceValue != nullptr)
+ valueFound = convertStringValueToInt(key, jitInstance.getForceOption(key), result);
+
+ if (!valueFound)
{
- wchar_t* endPtr;
- result = static_cast<int>(wcstoul(forceValue, &endPtr, 16));
- bool succeeded = (errno != ERANGE) && (endPtr != forceValue);
- if (succeeded)
+ // Right now we can't distinguish between the default value that was set explicitly and the default value
+ // from the key that was not set. See comments in CLRConfig::GetConfigValue.
+ result = jitInstance.mc->repGetIntConfigValue(key, defaultValue);
+ if (result != defaultValue)
{
- return result;
+ valueFound = true;
}
}
- result = jitInstance.mc->repGetIntConfigValue(key, defaultValue);
-
- if (result != defaultValue)
+ if (!valueFound)
{
- return result;
+ // Look for special case keys.
+ if (wcscmp(key, W("SuperPMIMethodContextNumber")) == 0)
+ {
+ result = jitInstance.mc->index;
+ valueFound = true;
+ }
}
- // Look for special case keys.
- if (wcscmp(key, W("SuperPMIMethodContextNumber")) == 0)
+ if (!valueFound)
{
- return jitInstance.mc->index;
+ valueFound = convertStringValueToInt(key, jitInstance.getOption(key), result);
}
- // If the result is the default value, probe the JIT options and then the environment. If a value is found, parse
- // it as a hex integer.
-
- const wchar_t* value = jitInstance.getOption(key);
-
- bool succeeded;
- if (value != nullptr)
+ if (!valueFound)
{
- wchar_t* endPtr;
- result = static_cast<int>(wcstoul(value, &endPtr, 16));
- succeeded = (errno != ERANGE) && (endPtr != value);
- }
- else
- {
- wchar_t* complus = GetCOMPlusVariable(key, jitInstance);
- if (complus == nullptr)
+ wchar_t* complusVar = GetCOMPlusVariable(key, jitInstance);
+ valueFound = convertStringValueToInt(key, complusVar, result);
+ if (complusVar != nullptr)
{
- return defaultValue;
+ jitInstance.freeLongLivedArray(complusVar);
}
- wchar_t* endPtr;
- result = static_cast<int>(wcstoul(complus, &endPtr, 16));
- succeeded = (errno != ERANGE) && (endPtr != complus);
- jitInstance.freeLongLivedArray(complus);
}
- return succeeded ? result : defaultValue;
+ if (valueFound)
+ {
+ LogDebug("Environment variable %ws=%d", key, result);
+ }
+
+ return valueFound ? result : defaultValue;
}
const wchar_t* JitHost::getStringConfigValue(const wchar_t* key)
{
jitInstance.mc->cr->AddCall("getStringConfigValue");
- const wchar_t* result = nullptr;
+ bool needToDup = true;
+ const wchar_t* result = nullptr;
// First check the force options, then mc value. If value is not presented there, probe the JIT options and then the
// environment.
if (result == nullptr)
{
result = jitInstance.getOption(key);
- if (result == nullptr)
- {
- return GetCOMPlusVariable(key, jitInstance);
- }
}
- // Now we need to dup it, so you can call freeStringConfigValue() on what we return.
- size_t resultLenInChars = wcslen(result) + 1;
- wchar_t* dupResult = (wchar_t*)jitInstance.allocateLongLivedArray((ULONG)(sizeof(wchar_t) * resultLenInChars));
- wcscpy_s(dupResult, resultLenInChars, result);
+ if (result == nullptr)
+ {
+ result = GetCOMPlusVariable(key, jitInstance);
+ needToDup = false;
+ }
- return dupResult;
+ if (result != nullptr && needToDup)
+ {
+ // Now we need to dup it, so you can call freeStringConfigValue() on what we return.
+ size_t resultLenInChars = wcslen(result) + 1;
+ wchar_t* dupResult = (wchar_t*)jitInstance.allocateLongLivedArray((ULONG)(sizeof(wchar_t) * resultLenInChars));
+ wcscpy_s(dupResult, resultLenInChars, result);
+ result = dupResult;
+ }
+
+ if (result != nullptr)
+ {
+ LogDebug("Environment variable %ws=%ws", key, result);
+ }
+ return result;
}
void JitHost::freeStringConfigValue(const wchar_t* value)
#include "icorjithostimpl.h"
private:
+ bool convertStringValueToInt(const wchar_t* key, const wchar_t* stringValue, int& result);
+
JitInstance& jitInstance;
};
jit->options = options;
+ jit->environment.getIntConfigValue = nullptr;
+ jit->environment.getStingConfigValue = nullptr;
+
if (st1 != nullptr)
st1->Start();
HRESULT hr = jit->StartUp(nameOfJit, false, breakOnAssert, firstContext);
}
PAL_ENDTRY
+ Assert(environment.getIntConfigValue == nullptr && environment.getStingConfigValue == nullptr);
+ environment = mc->cloneEnvironment();
+
return param.result;
}
return false;
}
+ if (environment.getIntConfigValue != nullptr)
+ {
+ delete environment.getIntConfigValue;
+ environment.getIntConfigValue = nullptr;
+ }
+
+ if (environment.getStingConfigValue != nullptr)
+ {
+ delete environment.getStingConfigValue;
+ environment.getStingConfigValue = nullptr;
+ }
+
mc = firstContext;
ICorJitHost* newHost = new JitHost(*this);
jitHost = newHost;
return true;
}
+
+const MethodContext::Environment& JitInstance::getEnvironment()
+{
+ return environment;
+}
LightWeightMap<DWORD, DWORD>* forceOptions;
LightWeightMap<DWORD, DWORD>* options;
+ MethodContext::Environment environment;
+
JitInstance(){};
void timeResult(CORINFO_METHOD_INFO info, unsigned flags);
const wchar_t* getOption(const wchar_t* key);
const wchar_t* getOption(const wchar_t* key, LightWeightMap<DWORD, DWORD>* options);
+ const MethodContext::Environment& getEnvironment();
+
void* allocateArray(ULONG size);
void* allocateLongLivedArray(ULONG size);
void freeArray(void* array);
mc->cr = new CompileResult();
mc->originalCR = crl;
- if (mc->wasEnviromentChanged())
+ if (mc->WasEnvironmentChanged(jit->getEnvironment()))
{
if (!jit->resetConfig(mc))
{