summaryrefslogtreecommitdiff
path: root/src/ToolBox
diff options
context:
space:
mode:
authorPat Gavlin <pagavlin@microsoft.com>2017-07-29 15:42:39 -0700
committerPat Gavlin <pagavlin@microsoft.com>2017-09-07 16:17:21 -0700
commita6f64213881c8ebbd3035c694d4c7193846e3893 (patch)
tree3a0e09c818e7f9c3c0b35305e6531b09bd443956 /src/ToolBox
parente390d7202605f3e5c9eb123f37c67ec5685c3fee (diff)
downloadcoreclr-a6f64213881c8ebbd3035c694d4c7193846e3893.tar.gz
coreclr-a6f64213881c8ebbd3035c694d4c7193846e3893.tar.bz2
coreclr-a6f64213881c8ebbd3035c694d4c7193846e3893.zip
Add the capability to specify JIT options on the SPMI command line.
This change adds two new flags, `-jitoption` and `-jit2option`, to the SuperPMI command line. These flags are cumulative, and are used to specify JIT config options (e.g. `COMPlus_JitDisasm`, albeit without the `COMPlus_` prefix) to the base and diff JITs, respectively. This change also removes Smarty-specific code and support for capturing and replaying environment variables. The former is no longer terribly useful and the latter has been obviated by the JIT host interface.
Diffstat (limited to 'src/ToolBox')
-rw-r--r--src/ToolBox/superpmi/mcs/CMakeLists.txt1
-rw-r--r--src/ToolBox/superpmi/mcs/commandline.cpp22
-rw-r--r--src/ToolBox/superpmi/mcs/commandline.h2
-rw-r--r--src/ToolBox/superpmi/mcs/mcs.cpp5
-rw-r--r--src/ToolBox/superpmi/mcs/verbsmarty.cpp97
-rw-r--r--src/ToolBox/superpmi/mcs/verbsmarty.h22
-rw-r--r--src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp171
-rw-r--r--src/ToolBox/superpmi/superpmi-shared/methodcontext.h7
-rw-r--r--src/ToolBox/superpmi/superpmi-shim-collector/icorjitcompiler.cpp3
-rw-r--r--src/ToolBox/superpmi/superpmi/commandline.cpp89
-rw-r--r--src/ToolBox/superpmi/superpmi/commandline.h4
-rw-r--r--src/ToolBox/superpmi/superpmi/jithost.cpp56
-rw-r--r--src/ToolBox/superpmi/superpmi/jitinstance.cpp24
-rw-r--r--src/ToolBox/superpmi/superpmi/jitinstance.h6
-rw-r--r--src/ToolBox/superpmi/superpmi/parallelsuperpmi.cpp21
-rw-r--r--src/ToolBox/superpmi/superpmi/superpmi.cpp17
16 files changed, 185 insertions, 362 deletions
diff --git a/src/ToolBox/superpmi/mcs/CMakeLists.txt b/src/ToolBox/superpmi/mcs/CMakeLists.txt
index 6ad1ff35ed..ebacd0761c 100644
--- a/src/ToolBox/superpmi/mcs/CMakeLists.txt
+++ b/src/ToolBox/superpmi/mcs/CMakeLists.txt
@@ -24,7 +24,6 @@ set(MCS_SOURCES
verbinteg.cpp
verbmerge.cpp
verbremovedup.cpp
- verbsmarty.cpp
verbstat.cpp
verbstrip.cpp
verbtoc.cpp
diff --git a/src/ToolBox/superpmi/mcs/commandline.cpp b/src/ToolBox/superpmi/mcs/commandline.cpp
index cc2244d870..161122815a 100644
--- a/src/ToolBox/superpmi/mcs/commandline.cpp
+++ b/src/ToolBox/superpmi/mcs/commandline.cpp
@@ -107,10 +107,6 @@ void CommandLine::DumpHelp(const char* program)
printf(" e.g. -removeDup -thin a.mc b.mc\n");
printf(" e.g. -removeDup -legacy -thin a.mc b.mc\n");
printf("\n");
- printf(" -smarty range inputfile outputfile\n");
- printf(" Write smarty Test IDs of the range from inputfile to outputfile.\n");
- printf(" e.g. -smarty 2 a.mc b.mc\n");
- printf("\n");
printf(" -stat {optional range} inputfile outputfile\n");
printf(" Report various statistics per method context.\n");
printf(" inputfile is read and statistics are written into outputfile\n");
@@ -344,14 +340,6 @@ bool CommandLine::Parse(int argc, char* argv[], /* OUT */ Options* o)
{
o->legacyCompare = true;
}
- else if ((_strnicmp(&argv[i][1], "smarty", argLen) == 0))
- {
- tempLen = strlen(argv[i]);
- o->actionSmarty = true;
- foundVerb = true;
- if (i + 1 < argc) // Peek to see if we have an mcl file or an integer next
- goto processMCL;
- }
else if ((_strnicmp(&argv[i][1], "verbosity", argLen) == 0))
{
if (++i >= argc)
@@ -564,16 +552,6 @@ bool CommandLine::Parse(int argc, char* argv[], /* OUT */ Options* o)
}
return true;
}
- if (o->actionSmarty)
- {
- if ((!foundFile1) || (!foundFile2))
- {
- LogError("CommandLine::Parse() '-smarty' needs one input file and one output file.");
- DumpHelp(argv[0]);
- return false;
- }
- return true;
- }
DumpHelp(argv[0]);
return false;
diff --git a/src/ToolBox/superpmi/mcs/commandline.h b/src/ToolBox/superpmi/mcs/commandline.h
index 442f2a4098..4e594934d2 100644
--- a/src/ToolBox/superpmi/mcs/commandline.h
+++ b/src/ToolBox/superpmi/mcs/commandline.h
@@ -27,7 +27,6 @@ public:
, actionInteg(false)
, actionMerge(false)
, actionRemoveDup(false)
- , actionSmarty(false)
, actionStat(false)
, actionStrip(false)
, actionTOC(false)
@@ -53,7 +52,6 @@ public:
bool actionInteg;
bool actionMerge;
bool actionRemoveDup;
- bool actionSmarty;
bool actionStat;
bool actionStrip;
bool actionTOC;
diff --git a/src/ToolBox/superpmi/mcs/mcs.cpp b/src/ToolBox/superpmi/mcs/mcs.cpp
index 7026ff55a3..4ed72cac27 100644
--- a/src/ToolBox/superpmi/mcs/mcs.cpp
+++ b/src/ToolBox/superpmi/mcs/mcs.cpp
@@ -19,7 +19,6 @@
#include "verbconcat.h"
#include "verbmerge.h"
#include "verbstrip.h"
-#include "verbsmarty.h"
#include "logging.h"
int __cdecl main(int argc, char* argv[])
@@ -98,10 +97,6 @@ int __cdecl main(int argc, char* argv[])
{
exitCode = verbTOC::DoWork(o.nameOfFile1);
}
- if (o.actionSmarty)
- {
- exitCode = verbSmarty::DoWork(o.nameOfFile1, o.nameOfFile2, o.indexCount, o.indexes);
- }
Logger::Shutdown();
return exitCode;
diff --git a/src/ToolBox/superpmi/mcs/verbsmarty.cpp b/src/ToolBox/superpmi/mcs/verbsmarty.cpp
deleted file mode 100644
index a9425bd11c..0000000000
--- a/src/ToolBox/superpmi/mcs/verbsmarty.cpp
+++ /dev/null
@@ -1,97 +0,0 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-#include "standardpch.h"
-#include "verbsmarty.h"
-#include "simpletimer.h"
-#include "methodcontext.h"
-#include "methodcontextiterator.h"
-
-//
-// Constructs a new verbSmarty.
-//
-// Arguments:
-// hFile - A handle to the output file that we are writing the Smarty Test IDs
-//
-// Assumptions:
-// hFile refers to an open and writeable file handle.
-//
-verbSmarty::verbSmarty(HANDLE hFile)
-{
- m_hFile = hFile;
-}
-
-//
-// Dumps the Smarty TestID to file
-//
-// Arguments:
-// testID - Smarty Test ID
-//
-void verbSmarty::DumpTestInfo(int testID)
-{
-#define bufflen 4096
- DWORD bytesWritten;
-
- char buff[bufflen];
- int buff_offset = 0;
- ZeroMemory(buff, bufflen * sizeof(char));
-
- buff_offset += sprintf_s(&buff[buff_offset], bufflen - buff_offset, "%i\r\n", testID);
- WriteFile(m_hFile, buff, buff_offset * sizeof(char), &bytesWritten, nullptr);
-}
-
-int verbSmarty::DoWork(const char* nameOfInput, const char* nameOfOutput, int indexCount, const int* indexes)
-{
- LogVerbose("Reading from '%s' reading Smarty ID for the Mc Indexes and writing into '%s'", nameOfInput,
- nameOfOutput);
-
- MethodContextIterator mci(indexCount, indexes);
- if (!mci.Initialize(nameOfInput))
- return -1;
-
- int savedCount = 0;
-
- HANDLE hFileOut = CreateFileA(nameOfOutput, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
- if (hFileOut == INVALID_HANDLE_VALUE)
- {
- LogError("Failed to open input 1 '%s'. GetLastError()=%u", nameOfOutput, GetLastError());
- return -1;
- }
-
- verbSmarty* verbList = new verbSmarty(hFileOut);
-
- // TODO-Cleanup: look to use toc for this
- while (mci.MoveNext())
- {
- MethodContext* mc = mci.Current();
-
- int testID = mc->repGetTestID();
- if (testID != -1)
- {
- // write to the file
- verbList->DumpTestInfo(testID);
- }
- else
- {
- LogError("Smarty ID not found for '%s'", mc->cr->repProcessName());
- }
- }
-
- delete verbList;
-
- if (!CloseHandle(hFileOut))
- {
- LogError("2nd CloseHandle failed. GetLastError()=%u", GetLastError());
- return -1;
- }
-
- LogInfo("Loaded %d, Saved %d", mci.MethodContextNumber(), savedCount);
-
- if (!mci.Destroy())
- return -1;
-
- return 0;
-}
diff --git a/src/ToolBox/superpmi/mcs/verbsmarty.h b/src/ToolBox/superpmi/mcs/verbsmarty.h
deleted file mode 100644
index c595ecbf4e..0000000000
--- a/src/ToolBox/superpmi/mcs/verbsmarty.h
+++ /dev/null
@@ -1,22 +0,0 @@
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-//----------------------------------------------------------
-// verbSmarty.h - verb that outputs Smarty test ID for mc
-//----------------------------------------------------------
-#ifndef _verbSmarty
-#define _verbSmarty
-
-class verbSmarty
-{
-public:
- verbSmarty(HANDLE hFile);
- void DumpTestInfo(int testID);
- static int DoWork(const char* nameOfInput, const char* nameofOutput, int indexCount, const int* indexes);
-
-private:
- HANDLE m_hFile;
-};
-#endif
diff --git a/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp b/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp
index 154505632b..7696560034 100644
--- a/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp
+++ b/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp
@@ -481,7 +481,7 @@ bool MethodContext::Equal(MethodContext* other)
// `ICJI::compileMethod`).
//
// This method is intended to be called as part of initializing a method
-// during collection, similar to `methodContext::recEnvironment`.
+// during collection.
void MethodContext::recGlobalContext(const MethodContext& other)
{
Assert(GetIntConfigValue == nullptr);
@@ -498,128 +498,8 @@ void MethodContext::recGlobalContext(const MethodContext& other)
}
}
-void MethodContext::recEnvironment()
-{
- if (Environment == nullptr)
- Environment = new DenseLightWeightMap<Agnostic_Environment>();
-
- char* l_EnvStr;
- char* l_val;
-
-#ifdef FEATURE_PAL
- l_EnvStr = GetEnvironmentStringsA();
-#else // !FEATURE_PAL
- l_EnvStr = GetEnvironmentStrings();
-#endif // !FEATURE_PAL
-
- l_val = l_EnvStr;
-
- char* l_str = l_EnvStr;
-
- int count = 0;
- while (true)
- {
- if (*l_str == 0)
- break;
- while (*l_str != 0)
- l_str++;
- l_str++;
- count++;
- }
-
- for (int i = 0; i < count; i++)
- {
- if ((_strnicmp(l_EnvStr, "complus_", 8) == 0) || (_strnicmp(l_EnvStr, "dbflag", 6) == 0) ||
- (_strnicmp(l_EnvStr, "BVT_TEST_ID", 11) == 0))
- {
- char* val = l_EnvStr;
- while (*val != '=')
- val++;
- *val++ = 0;
- int nameind = Environment->AddBuffer((unsigned char*)l_EnvStr, (int)strlen(l_EnvStr) + 1);
- int valind = Environment->AddBuffer((unsigned char*)val, (int)strlen(val) + 1);
- Agnostic_Environment value;
- value.name_index = nameind;
- value.val_index = valind;
- DWORD key = (DWORD)Environment->GetCount();
- Environment->Append(value);
- DEBUG_REC(dmpEnvironment(key, value));
- l_EnvStr = val;
- }
- while (*l_EnvStr != '\0')
- l_EnvStr++;
- l_EnvStr++;
- }
- FreeEnvironmentStringsA(l_val);
-}
void MethodContext::dmpEnvironment(DWORD key, const Agnostic_Environment& value)
{
- printf("Environment key %u, value '%s' '%s'", key, (LPCSTR)Environment->GetBuffer(value.name_index),
- (LPCSTR)Environment->GetBuffer(value.val_index));
- Environment->Unlock();
-}
-void MethodContext::repEnvironmentSet()
-{
- if (Environment == nullptr)
- return;
- Agnostic_Environment val;
- for (unsigned int i = 0; i < Environment->GetCount(); i++)
- {
- val = Environment->Get((DWORD)i);
- DEBUG_REP(dmpEnvironment(i, val));
-
- SetEnvironmentVariableA((LPCSTR)Environment->GetBuffer(val.name_index),
- (LPCSTR)Environment->GetBuffer(val.val_index));
- }
-}
-
-int MethodContext::repGetTestID()
-{
- // CLR Test asset only - we capture the testID via smarty-environnent (BVT_TEST_ID) during record time
- // This procedure returns the test id if found and -1 otherwise
-
- if (Environment == nullptr)
- return -1;
- Agnostic_Environment val;
- LPCSTR key;
- int value = -1;
- for (unsigned int i = 0; i < Environment->GetCount(); i++)
- {
- val = Environment->Get((DWORD)i);
- key = (LPCSTR)Environment->GetBuffer(val.name_index);
-
- if (_strnicmp(key, "BVT_TEST_ID", 11) == 0)
- {
- value = atoi((LPCSTR)Environment->GetBuffer(val.val_index));
- break;
- }
- }
-
- if (value == -1)
- {
- LogError("Couldn't find Smarty test ID");
- }
-
- return value;
-}
-
-void MethodContext::repEnvironmentUnset()
-{
- if (Environment == nullptr)
- return;
- Agnostic_Environment val;
- for (unsigned int i = 0; i < Environment->GetCount(); i++)
- {
- val = Environment->Get((DWORD)i);
- SetEnvironmentVariableA((LPCSTR)Environment->GetBuffer(val.name_index), nullptr);
- }
-}
-int MethodContext::repEnvironmentGetCount()
-{
- int result = 0;
- if (Environment != nullptr)
- result = Environment->GetCount();
- return result;
}
void MethodContext::dumpToConsole(int mcNumber)
@@ -5974,15 +5854,6 @@ const wchar_t* MethodContext::repGetStringConfigValue(const wchar_t* name)
return value;
}
-struct EnvironmentVariable
-{
- char* name;
- DWORD val_index;
-};
-int __cdecl compareEnvironmentVariable(const void* arg1, const void* arg2)
-{
- return _stricmp(((EnvironmentVariable*)arg1)->name, ((EnvironmentVariable*)arg2)->name);
-}
int MethodContext::dumpMethodIdentityInfoToBuffer(char* buff, int len)
{
char* obuff = buff;
@@ -6007,46 +5878,6 @@ int MethodContext::dumpMethodIdentityInfoToBuffer(char* buff, int len)
buff += t;
len -= t;
- // Add COMPLUS_* & dbflag environment variables to method Identity
- // except complus_version and complus_defaultversion
- // since they change the compilation behaviour of JIT
- // we also need to sort them to ensure we don't produce a different
- // hash based on the order of these variables
- if (Environment != nullptr)
- {
- Agnostic_Environment val;
- EnvironmentVariable* envValues = new EnvironmentVariable[Environment->GetCount()];
- int envValCount = 0;
-
- for (unsigned int i = 0; i < Environment->GetCount(); i++)
- {
- val = Environment->Get((DWORD)i);
- char* envVariable = (char*)Environment->GetBuffer(val.name_index);
- if ((_strnicmp(envVariable, "complus_", 8) == 0 || _strnicmp(envVariable, "dbflag", 6) == 0) &&
- (_stricmp(envVariable, "complus_version") != 0) &&
- (_stricmp(envVariable, "complus_defaultversion") != 0))
- {
- envValues[envValCount].name = envVariable;
- envValues[envValCount++].val_index = val.val_index;
- }
- }
-
- // Do a quick sort on envValues if needed
- if (envValCount > 1)
- qsort(envValues, envValCount, sizeof(EnvironmentVariable), compareEnvironmentVariable);
-
- // Append these values to the IdentityInfobuffer
- for (int i = 0; i < envValCount; i++)
- {
- t = sprintf_s(buff, len, "%s=%s ", _strlwr(envValues[i].name),
- _strlwr((char*)Environment->GetBuffer(envValues[i].val_index)));
- buff += t;
- len -= t;
- }
-
- delete[] envValues;
- }
-
// Hash the IL Code for this method and append it to the ID info
char ilHash[MD5_HASH_BUFFER_SIZE];
dumpMD5HashToBuffer(info.ILCode, info.ILCodeSize, ilHash, MD5_HASH_BUFFER_SIZE);
diff --git a/src/ToolBox/superpmi/superpmi-shared/methodcontext.h b/src/ToolBox/superpmi/superpmi-shared/methodcontext.h
index eec403196b..7f79b2b9f6 100644
--- a/src/ToolBox/superpmi/superpmi-shared/methodcontext.h
+++ b/src/ToolBox/superpmi/superpmi-shared/methodcontext.h
@@ -570,12 +570,7 @@ public:
void recGlobalContext(const MethodContext& other);
- void recEnvironment();
void dmpEnvironment(DWORD key, const Agnostic_Environment& value);
- void repEnvironmentSet();
- void repEnvironmentUnset();
- int repEnvironmentGetCount();
- int repGetTestID();
void recCompileMethod(CORINFO_METHOD_INFO* info, unsigned flags);
void dmpCompileMethod(DWORD key, const Agnostic_CompileMethod& value);
@@ -1287,7 +1282,7 @@ enum mcPackets
Packet_EmbedMethodHandle = 19,
Packet_EmbedModuleHandle = 20,
Packet_EmptyStringLiteral = 21,
- Packet_Environment = 136, // Added 4/3/2013
+ Packet_Environment = 136, // Deprecated 7/29/2017
Packet_ErrorList = 22,
Packet_FilterException = 134,
Packet_FindCallSiteSig = 23,
diff --git a/src/ToolBox/superpmi/superpmi-shim-collector/icorjitcompiler.cpp b/src/ToolBox/superpmi/superpmi-shim-collector/icorjitcompiler.cpp
index eaa6b8cfb7..19f96385e4 100644
--- a/src/ToolBox/superpmi/superpmi-shim-collector/icorjitcompiler.cpp
+++ b/src/ToolBox/superpmi/superpmi-shim-collector/icorjitcompiler.cpp
@@ -63,9 +63,6 @@ CorJitResult __stdcall interceptor_ICJC::compileMethod(ICorJitInfo*
our_ICorJitInfo.mc->recGlobalContext(*g_globalContext);
}
- // Record a simple view of the environment
- our_ICorJitInfo.mc->recEnvironment();
-
CorJitResult temp =
original_ICorJitCompiler->compileMethod(&our_ICorJitInfo, info, flags, nativeEntry, nativeSizeOfCode);
diff --git a/src/ToolBox/superpmi/superpmi/commandline.cpp b/src/ToolBox/superpmi/superpmi/commandline.cpp
index c77337f6be..47ba0940c2 100644
--- a/src/ToolBox/superpmi/superpmi/commandline.cpp
+++ b/src/ToolBox/superpmi/superpmi/commandline.cpp
@@ -8,6 +8,7 @@
//----------------------------------------------------------
#include "standardpch.h"
+#include "lightweightmap.h"
#include "commandline.h"
#include "superpmi.h"
#include "mclist.h"
@@ -116,7 +117,13 @@ void CommandLine::DumpHelp(const char* program)
printf(" Ignored: MSVCDIS is not available, so CoreDisTools will be used.\n");
#else
printf(" Ignored: neither MSVCDIS nor CoreDisTools is available.\n");
-#endif
+#endif // USE_COREDISTOOLS
+ printf("\n");
+ printf(" -jitoption key=value\n");
+ printf(" Set the JIT option named \"key\" to \"value\" for JIT 1. NOTE: do not use a \"COMPlus_\" prefix!\n");
+ printf("\n");
+ printf(" -jit2option key=value\n");
+ printf(" Set the JIT option named \"key\" to \"value\" for JIT 2. NOTE: do not use a \"COMPlus_\" prefix!\n");
printf("\n");
printf("Inputs are case sensitive.\n");
printf("\n");
@@ -140,6 +147,40 @@ void CommandLine::DumpHelp(const char* program)
printf(" ; if there are any failures, record their MC numbers in the file fail.mcl\n");
}
+static bool ParseJitOption(const char* optionString, wchar_t** key, wchar_t **value)
+{
+ char tempKey[1024];
+
+ unsigned i;
+ for (i = 0; optionString[i] != '='; i++)
+ {
+ if ((i >= 1023) || (optionString[i] == '\0'))
+ {
+ return false;
+ }
+ tempKey[i] = optionString[i];
+ }
+ tempKey[i] = '\0';
+
+ const char* tempVal = &optionString[i + 1];
+ if (tempVal[0] == '\0')
+ {
+ return false;
+ }
+
+ const unsigned keyLen = i;
+ wchar_t* keyBuf = new wchar_t[keyLen + 1];
+ MultiByteToWideChar(CP_UTF8, 0, tempKey, keyLen + 1, keyBuf, keyLen + 1);
+
+ const unsigned valLen = (unsigned)strlen(tempVal);
+ wchar_t* valBuf = new wchar_t[valLen + 1];
+ MultiByteToWideChar(CP_UTF8, 0, tempVal, valLen + 1, valBuf, valLen + 1);
+
+ *key = keyBuf;
+ *value = valBuf;
+ return true;
+}
+
// Assumption: All inputs are initialized to default or real value. we'll just set the stuff we see on the command
// line. Assumption: Single byte names are passed in.. mb stuff doesnt cause an obvious problem... but it might have
// issues... Assumption: Values larger than 2^31 aren't expressible from the commandline.... (atoi) Unless you pass in
@@ -481,6 +522,52 @@ bool CommandLine::Parse(int argc, char* argv[], /* OUT */ Options* o)
return false;
}
}
+ else if ((_strnicmp(&argv[i][1], "jitoption", argLen) == 0))
+ {
+ i++;
+
+ wchar_t *key, *value;
+ if ((i >= argc) || !ParseJitOption(argv[i], &key, &value))
+ {
+ DumpHelp(argv[0]);
+ return false;
+ }
+
+ if (o->jitOptions == nullptr)
+ {
+ o->jitOptions = new LightWeightMap<DWORD, DWORD>();
+ }
+
+ DWORD keyIndex = (DWORD)o->jitOptions->AddBuffer((unsigned char*)key, sizeof(wchar_t) * ((unsigned int)wcslen(key) + 1));
+ DWORD valueIndex = (DWORD)o->jitOptions->AddBuffer((unsigned char*)value, sizeof(wchar_t) * ((unsigned int)wcslen(value) + 1));
+ o->jitOptions->Add(keyIndex, valueIndex);
+
+ delete[] key;
+ delete[] value;
+ }
+ else if ((_strnicmp(&argv[i][1], "jit2option", argLen) == 0))
+ {
+ i++;
+
+ wchar_t *key, *value;
+ if ((i >= argc) || !ParseJitOption(argv[i], &key, &value))
+ {
+ DumpHelp(argv[0]);
+ return false;
+ }
+
+ if (o->jit2Options == nullptr)
+ {
+ o->jit2Options = new LightWeightMap<DWORD, DWORD>();
+ }
+
+ DWORD keyIndex = (DWORD)o->jit2Options->AddBuffer((unsigned char*)key, sizeof(wchar_t) * ((unsigned int)wcslen(key) + 1));
+ DWORD valueIndex = (DWORD)o->jit2Options->AddBuffer((unsigned char*)value, sizeof(wchar_t) * ((unsigned int)wcslen(value) + 1));
+ o->jit2Options->Add(keyIndex, valueIndex);
+
+ delete[] key;
+ delete[] value;
+ }
else
{
LogError("Unknown switch '%s' passed as argument.", argv[i]);
diff --git a/src/ToolBox/superpmi/superpmi/commandline.h b/src/ToolBox/superpmi/superpmi/commandline.h
index 87034476d6..0881f088b0 100644
--- a/src/ToolBox/superpmi/superpmi/commandline.h
+++ b/src/ToolBox/superpmi/superpmi/commandline.h
@@ -42,6 +42,8 @@ public:
, compileList(nullptr)
, offset(-1)
, increment(-1)
+ , jitOptions(nullptr)
+ , jit2Options(nullptr)
{
}
@@ -67,6 +69,8 @@ public:
char* compileList;
int offset;
int increment;
+ LightWeightMap<DWORD, DWORD>* jitOptions;
+ LightWeightMap<DWORD, DWORD>* jit2Options;
};
static bool Parse(int argc, char* argv[], /* OUT */ Options* o);
diff --git a/src/ToolBox/superpmi/superpmi/jithost.cpp b/src/ToolBox/superpmi/superpmi/jithost.cpp
index d14909bae1..a515d51cf1 100644
--- a/src/ToolBox/superpmi/superpmi/jithost.cpp
+++ b/src/ToolBox/superpmi/superpmi/jithost.cpp
@@ -77,19 +77,30 @@ int JitHost::getIntConfigValue(const wchar_t* key, int defaultValue)
return jitInstance.mc->index;
}
- // If the result is the default value, probe the environment for
- // a COMPlus variable with the same name.
- wchar_t* complus = GetCOMPlusVariable(key, jitInstance);
- if (complus == nullptr)
- {
- return defaultValue;
- }
+ // 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.
- // Parse the value as a hex integer.
wchar_t* endPtr;
- result = static_cast<int>(wcstoul(complus, &endPtr, 16));
- bool succeeded = (errno != ERANGE) && (endPtr != complus);
- jitInstance.freeLongLivedArray(complus);
+ bool succeeded;
+
+ const wchar_t* value = jitInstance.getOption(key);
+ if (value != nullptr)
+ {
+ result = static_cast<int>(wcstoul(value, &endPtr, 16));
+ succeeded = (errno != ERANGE) && (endPtr != value);
+ }
+ else
+ {
+ wchar_t* complus = GetCOMPlusVariable(key, jitInstance);
+ if (complus == nullptr)
+ {
+ return defaultValue;
+ }
+
+ result = static_cast<int>(wcstoul(complus, &endPtr, 16));
+ succeeded = (errno != ERANGE) && (endPtr != complus);
+ jitInstance.freeLongLivedArray(complus);
+ }
return succeeded ? result : defaultValue;
}
@@ -99,19 +110,22 @@ const wchar_t* JitHost::getStringConfigValue(const wchar_t* key)
jitInstance.mc->cr->AddCall("getStringConfigValue");
const wchar_t* result = jitInstance.mc->repGetStringConfigValue(key);
- if (result != nullptr)
+ // If the result is the default value, probe the JIT options and then the environment.
+ if (result == nullptr)
{
- // 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);
-
- return dupResult;
+ result = jitInstance.getOption(key);
+ if (result == nullptr)
+ {
+ return GetCOMPlusVariable(key, jitInstance);
+ }
}
- // If the result is the default value, probe the environment for
- // a COMPlus variable with the same name.
- 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);
+
+ return dupResult;
}
void JitHost::freeStringConfigValue(const wchar_t* value)
diff --git a/src/ToolBox/superpmi/superpmi/jitinstance.cpp b/src/ToolBox/superpmi/superpmi/jitinstance.cpp
index 7902c392bb..2d84cfd658 100644
--- a/src/ToolBox/superpmi/superpmi/jitinstance.cpp
+++ b/src/ToolBox/superpmi/superpmi/jitinstance.cpp
@@ -12,7 +12,7 @@
#include "errorhandling.h"
#include "spmiutil.h"
-JitInstance* JitInstance::InitJit(char* nameOfJit, bool breakOnAssert, SimpleTimer* st1, MethodContext* firstContext)
+JitInstance* JitInstance::InitJit(char* nameOfJit, bool breakOnAssert, SimpleTimer* st1, MethodContext* firstContext, LightWeightMap<DWORD, DWORD>* options)
{
JitInstance* jit = new JitInstance();
if (jit == nullptr)
@@ -21,6 +21,8 @@ JitInstance* JitInstance::InitJit(char* nameOfJit, bool breakOnAssert, SimpleTim
return nullptr;
}
+ jit->options = options;
+
if (st1 != nullptr)
st1->Start();
HRESULT hr = jit->StartUp(nameOfJit, false, breakOnAssert, firstContext);
@@ -33,6 +35,7 @@ JitInstance* JitInstance::InitJit(char* nameOfJit, bool breakOnAssert, SimpleTim
}
if (st1 != nullptr)
LogVerbose("Jit startup took %fms", st1->GetMilliseconds());
+
return jit;
}
@@ -284,7 +287,6 @@ JitInstance::Result JitInstance::CompileMethod(MethodContext* MethodToCompile, i
times[0] = 0;
times[1] = 0;
- mc->repEnvironmentSet(); // Sets envvars
stj.Start();
PAL_TRY(Param*, pParam, &param)
@@ -349,7 +351,6 @@ JitInstance::Result JitInstance::CompileMethod(MethodContext* MethodToCompile, i
// If we get here, we know it compiles
timeResult(param.info, param.flags);
}
- mc->repEnvironmentUnset(); // Unsets envvars
mc->cr->secondsToCompile = stj.GetSeconds();
@@ -398,6 +399,23 @@ void JitInstance::timeResult(CORINFO_METHOD_INFO info, unsigned flags)
/*-------------------------- Misc ---------------------------------------*/
+const wchar_t* JitInstance::getOption(const wchar_t* key)
+{
+ if (options == nullptr)
+ {
+ return nullptr;
+ }
+
+ size_t keyLenInBytes = sizeof(wchar_t) * (wcslen(key) + 1);
+ int keyIndex = options->Contains((unsigned char*)key, (unsigned int)keyLenInBytes);
+ if (keyIndex == -1)
+ {
+ return nullptr;
+ }
+
+ return (const wchar_t*)options->GetBuffer(options->Get(keyIndex));
+}
+
// Used to allocate memory that needs to handed to the EE.
// For eg, use this to allocated memory for reporting debug info,
// which will be handed to the EE by setVars() and setBoundaries()
diff --git a/src/ToolBox/superpmi/superpmi/jitinstance.h b/src/ToolBox/superpmi/superpmi/jitinstance.h
index 3b4d22c081..0baf401803 100644
--- a/src/ToolBox/superpmi/superpmi/jitinstance.h
+++ b/src/ToolBox/superpmi/superpmi/jitinstance.h
@@ -25,6 +25,8 @@ private:
ICorJitInfo* icji;
SimpleTimer stj;
+ LightWeightMap<DWORD, DWORD>* options;
+
JitInstance(){};
void timeResult(CORINFO_METHOD_INFO info, unsigned flags);
@@ -41,7 +43,7 @@ public:
ICorJitCompiler* pJitInstance;
// Allocate and initialize the jit provided
- static JitInstance* InitJit(char* nameOfJit, bool breakOnAssert, SimpleTimer* st1, MethodContext* firstContext);
+ static JitInstance* InitJit(char* nameOfJit, bool breakOnAssert, SimpleTimer* st1, MethodContext* firstContext, LightWeightMap<DWORD, DWORD>* options);
HRESULT StartUp(char* PathToJit, bool copyJit, bool breakOnDebugBreakorAV, MethodContext* firstContext);
bool reLoad(MethodContext* firstContext);
@@ -50,6 +52,8 @@ public:
Result CompileMethod(MethodContext* MethodToCompile, int mcIndex, bool collectThroughput);
+ const wchar_t* getOption(const wchar_t* key);
+
void* allocateArray(ULONG size);
void* allocateLongLivedArray(ULONG size);
void freeArray(void* array);
diff --git a/src/ToolBox/superpmi/superpmi/parallelsuperpmi.cpp b/src/ToolBox/superpmi/superpmi/parallelsuperpmi.cpp
index 0f2d31d3e5..41b27deebc 100644
--- a/src/ToolBox/superpmi/superpmi/parallelsuperpmi.cpp
+++ b/src/ToolBox/superpmi/superpmi/parallelsuperpmi.cpp
@@ -7,6 +7,7 @@
#include "superpmi.h"
#include "simpletimer.h"
#include "mclist.h"
+#include "lightweightmap.h"
#include "commandline.h"
#include "errorhandling.h"
@@ -360,6 +361,26 @@ char* ConstructChildProcessArgs(const CommandLine::Options& o)
ADDARG_STRING(o.targetArchitecture, "-target");
ADDARG_STRING(o.compileList, "-compile");
+ if (o.jitOptions != nullptr)
+ {
+ for (unsigned i = 0; i < o.jitOptions->GetCount(); i++)
+ {
+ wchar_t* key = (wchar_t*)o.jitOptions->GetBuffer(o.jitOptions->GetKey(i));
+ wchar_t* value = (wchar_t*)o.jitOptions->GetBuffer(o.jitOptions->GetItem(i));
+ bytesWritten += sprintf_s(spmiArgs + bytesWritten, MAX_CMDLINE_SIZE - bytesWritten, " -jitoption %S=%S", key, value);
+ }
+ }
+
+ if (o.jit2Options != nullptr)
+ {
+ for (unsigned i = 0; i < o.jit2Options->GetCount(); i++)
+ {
+ wchar_t* key = (wchar_t*)o.jit2Options->GetBuffer(o.jit2Options->GetKey(i));
+ wchar_t* value = (wchar_t*)o.jit2Options->GetBuffer(o.jit2Options->GetItem(i));
+ bytesWritten += sprintf_s(spmiArgs + bytesWritten, MAX_CMDLINE_SIZE - bytesWritten, " -jit2option %S=%S", key, value);
+ }
+ }
+
ADDSTRING(o.nameOfJit);
ADDSTRING(o.nameOfJit2);
ADDSTRING(o.nameOfInputMethodContextFile);
diff --git a/src/ToolBox/superpmi/superpmi/superpmi.cpp b/src/ToolBox/superpmi/superpmi/superpmi.cpp
index c98c0538e7..a8363a608d 100644
--- a/src/ToolBox/superpmi/superpmi/superpmi.cpp
+++ b/src/ToolBox/superpmi/superpmi/superpmi.cpp
@@ -9,6 +9,7 @@
#include "coredistools.h"
#endif // USE_COREDISTOOLS
+#include "lightweightmap.h"
#include "commandline.h"
#include "superpmi.h"
#include "jitinstance.h"
@@ -106,8 +107,8 @@ void InvokeNearDiffer(NearDiffer* nearDiffer,
{
SpmiException e(&param.exceptionPointers);
- LogError("main method %d of size %d failed to load and compile correctly. EnvCnt=%d",
- (*reader)->GetMethodContextIndex(), (*mc)->methodSize, (*mc)->repEnvironmentGetCount());
+ LogError("main method %d of size %d failed to load and compile correctly.",
+ (*reader)->GetMethodContextIndex(), (*mc)->methodSize);
e.ShowAndDeleteMessage();
if ((*o).mclFilename != nullptr)
(*failingMCL).AddMethodToMCL((*reader)->GetMethodContextIndex());
@@ -286,7 +287,7 @@ int __cdecl main(int argc, char* argv[])
{
SimpleTimer st4;
- jit = JitInstance::InitJit(o.nameOfJit, o.breakOnAssert, &st4, mc);
+ jit = JitInstance::InitJit(o.nameOfJit, o.breakOnAssert, &st4, mc, o.jitOptions);
if (jit == nullptr)
{
// InitJit already printed a failure message
@@ -295,7 +296,7 @@ int __cdecl main(int argc, char* argv[])
if (o.nameOfJit2 != nullptr)
{
- jit2 = JitInstance::InitJit(o.nameOfJit2, o.breakOnAssert, &st4, mc);
+ jit2 = JitInstance::InitJit(o.nameOfJit2, o.breakOnAssert, &st4, mc, o.jit2Options);
if (jit2 == nullptr)
{
// InitJit already printed a failure message
@@ -360,8 +361,8 @@ int __cdecl main(int argc, char* argv[])
if (res2 == JitInstance::RESULT_ERROR)
{
- LogError("JIT2 main method %d of size %d failed to load and compile correctly. EnvCnt=%d",
- reader->GetMethodContextIndex(), mc->methodSize, mc->repEnvironmentGetCount());
+ LogError("JIT2 main method %d of size %d failed to load and compile correctly.",
+ reader->GetMethodContextIndex(), mc->methodSize);
}
// Methods that don't compile due to missing JIT-EE information
@@ -503,8 +504,8 @@ int __cdecl main(int argc, char* argv[])
// to, for instance, failures caused by missing JIT-EE details).
if (res == JitInstance::RESULT_ERROR)
{
- LogError("main method %d of size %d failed to load and compile correctly. EnvCnt=%d",
- reader->GetMethodContextIndex(), mc->methodSize, mc->repEnvironmentGetCount());
+ LogError("main method %d of size %d failed to load and compile correctly.",
+ reader->GetMethodContextIndex(), mc->methodSize);
if ((o.reproName != nullptr) && (o.indexCount == -1))
{
char buff[500];