From: Sergey Andreenko Date: Tue, 3 Jul 2018 00:32:59 +0000 (-0700) Subject: SuperPMI: add ability to exclude failing method contexts from replays (dotnet/coreclr... X-Git-Tag: submit/tizen/20210909.063632~11030^2~4458 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a4dd2e67e3026598c8b6b32134672b98f41c2f2f;p=platform%2Fupstream%2Fdotnet%2Fruntime.git SuperPMI: add ability to exclude failing method contexts from replays (dotnet/coreclr#18721) * format spmi * rename mchFile to mchFileName * refactor ProcessChildStdOut * add a stub to exclude methods Commit migrated from https://github.com/dotnet/coreclr/commit/15a6beb33de6f243d59f6b61ec90cfcb336f45af --- diff --git a/src/coreclr/src/ToolBox/superpmi/mcs/verbremovedup.cpp b/src/coreclr/src/ToolBox/superpmi/mcs/verbremovedup.cpp index cd2ead06327..64d5fa435b7 100644 --- a/src/coreclr/src/ToolBox/superpmi/mcs/verbremovedup.cpp +++ b/src/coreclr/src/ToolBox/superpmi/mcs/verbremovedup.cpp @@ -11,8 +11,8 @@ #include "methodcontextiterator.h" // We use a hash to limit the number of comparisons we need to do. - //The first level key to our hash map is ILCodeSize and the second - //level map key is just an index and the value is an existing MC Hash. +// The first level key to our hash map is ILCodeSize and the second +// level map key is just an index and the value is an existing MC Hash. LightWeightMap*>* inFile = nullptr; diff --git a/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp index b5de52feaf1..97be26fc8d8 100644 --- a/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp @@ -2436,7 +2436,7 @@ InfoAccessType MethodContext::repConstructStringLiteral(CORINFO_MODULE_HANDLE mo return (InfoAccessType)temp2.B; } -void MethodContext::recConvertPInvokeCalliToCall(CORINFO_RESOLVED_TOKEN * pResolvedToken, bool fMustConvert, bool result) +void MethodContext::recConvertPInvokeCalliToCall(CORINFO_RESOLVED_TOKEN* pResolvedToken, bool fMustConvert, bool result) { if (ConvertPInvokeCalliToCall == nullptr) ConvertPInvokeCalliToCall = new LightWeightMap(); @@ -2456,7 +2456,7 @@ void MethodContext::dmpConvertPInvokeCalliToCall(DLD key, DWORDLONG value) { printf("ConvertPInvokeCalliToCall key mod-%016llX tok-%08X, value %016llX", key.A, key.B, value); } -bool MethodContext::repConvertPInvokeCalliToCall(CORINFO_RESOLVED_TOKEN * pResolvedToken, bool fMustConvert) +bool MethodContext::repConvertPInvokeCalliToCall(CORINFO_RESOLVED_TOKEN* pResolvedToken, bool fMustConvert) { DLD key; ZeroMemory(&key, sizeof(DLD)); // We use the input structs as a key and use memcmp to compare.. so we need to zero @@ -4362,7 +4362,8 @@ void MethodContext::dmpCanInlineTypeCheckWithObjectVTable(DWORDLONG key, DWORD v } BOOL MethodContext::repCanInlineTypeCheckWithObjectVTable(CORINFO_CLASS_HANDLE cls) { - AssertCodeMsg(CanInlineTypeCheckWithObjectVTable != nullptr, EXCEPTIONCODE_MC, "No map for CanInlineTypeCheckWithObjectVTable"); + AssertCodeMsg(CanInlineTypeCheckWithObjectVTable != nullptr, EXCEPTIONCODE_MC, + "No map for CanInlineTypeCheckWithObjectVTable"); return (BOOL)CanInlineTypeCheckWithObjectVTable->Get((DWORDLONG)cls); } diff --git a/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.h b/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.h index ac7acf1ea15..739c1b2c024 100644 --- a/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.h +++ b/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.h @@ -805,9 +805,9 @@ public: void dmpConstructStringLiteral(DLD key, DLD value); InfoAccessType repConstructStringLiteral(CORINFO_MODULE_HANDLE module, mdToken metaTok, void** ppValue); - void recConvertPInvokeCalliToCall(CORINFO_RESOLVED_TOKEN * pResolvedToken, bool fMustConvert, bool result); + void recConvertPInvokeCalliToCall(CORINFO_RESOLVED_TOKEN* pResolvedToken, bool fMustConvert, bool result); void dmpConvertPInvokeCalliToCall(DLD key, DWORDLONG value); - bool repConvertPInvokeCalliToCall(CORINFO_RESOLVED_TOKEN * pResolvedToken, bool fMustConvert); + bool repConvertPInvokeCalliToCall(CORINFO_RESOLVED_TOKEN* pResolvedToken, bool fMustConvert); void recEmptyStringLiteral(void** ppValue, InfoAccessType result); void dmpEmptyStringLiteral(DWORD key, DLD value); diff --git a/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontextreader.cpp b/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontextreader.cpp index beadcffc251..a978fa2c2e3 100644 --- a/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontextreader.cpp +++ b/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontextreader.cpp @@ -83,26 +83,26 @@ MethodContextReader::MethodContextReader( { this->mutex = CreateMutexA(NULL, FALSE, nullptr); - std::string tocFileName, mchFile; + std::string tocFileName, mchFileName; // First, check to see if they passed an MCH file (look for a paired MCT file) tocFileName = MethodContextReader::CheckForPairedFile(inputFileName, ".mch", ".mct"); if (!tocFileName.empty()) { - mchFile = inputFileName; + mchFileName = inputFileName; } else { // Okay, it wasn't an MCH file, let's check to see if it was an MCT file // so check for a paired MCH file instead - mchFile = MethodContextReader::CheckForPairedFile(inputFileName, ".mct", ".mch"); - if (!mchFile.empty()) + mchFileName = MethodContextReader::CheckForPairedFile(inputFileName, ".mct", ".mch"); + if (!mchFileName.empty()) { tocFileName = inputFileName; } else { - mchFile = inputFileName; + mchFileName = inputFileName; } } @@ -110,8 +110,8 @@ MethodContextReader::MethodContextReader( this->tocFile.LoadToc(tocFileName.c_str()); // we'll get here even if we don't have a valid index file - this->fileHandle = OpenFile(mchFile.c_str(), (this->hasTOC() && this->hasIndex()) ? FILE_ATTRIBUTE_NORMAL - : FILE_FLAG_SEQUENTIAL_SCAN); + this->fileHandle = OpenFile(mchFileName.c_str(), (this->hasTOC() && this->hasIndex()) ? FILE_ATTRIBUTE_NORMAL + : FILE_FLAG_SEQUENTIAL_SCAN); if (this->fileHandle != INVALID_HANDLE_VALUE) { GetFileSizeEx(this->fileHandle, (PLARGE_INTEGER) & this->fileSize); diff --git a/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontextreader.h b/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontextreader.h index e9ee4511154..ab1c6932199 100644 --- a/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontextreader.h +++ b/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontextreader.h @@ -135,6 +135,13 @@ public: { return curMCIndex; } + + // Return should this method context be excluded from the replay or not. + bool IsMethodExcluded(MethodContext* mc) + { + // Right now it is just a stub. + return false; + } }; #pragma pack(pop) diff --git a/src/coreclr/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/coreclr/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp index 5d70a5488f5..32cc072d683 100644 --- a/src/coreclr/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/coreclr/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -1825,7 +1825,7 @@ InfoAccessType interceptor_ICJI::constructStringLiteral(CORINFO_MODULE_HANDLE mo return temp; } -bool interceptor_ICJI::convertPInvokeCalliToCall(CORINFO_RESOLVED_TOKEN * pResolvedToken, bool fMustConvert) +bool interceptor_ICJI::convertPInvokeCalliToCall(CORINFO_RESOLVED_TOKEN* pResolvedToken, bool fMustConvert) { mc->cr->AddCall("convertPInvokeCalliToCall"); bool result = original_ICorJitInfo->convertPInvokeCalliToCall(pResolvedToken, fMustConvert); diff --git a/src/coreclr/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp b/src/coreclr/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp index 316fd8c1ede..8a3e80ca4c1 100644 --- a/src/coreclr/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp +++ b/src/coreclr/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp @@ -1412,7 +1412,7 @@ InfoAccessType interceptor_ICJI::constructStringLiteral(CORINFO_MODULE_HANDLE mo return original_ICorJitInfo->constructStringLiteral(module, metaTok, ppValue); } -bool interceptor_ICJI::convertPInvokeCalliToCall(CORINFO_RESOLVED_TOKEN * pResolvedToken, bool fMustConvert) +bool interceptor_ICJI::convertPInvokeCalliToCall(CORINFO_RESOLVED_TOKEN* pResolvedToken, bool fMustConvert) { mcs->AddCall("convertPInvokeCalliToCall"); return original_ICorJitInfo->convertPInvokeCalliToCall(pResolvedToken, fMustConvert); diff --git a/src/coreclr/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp b/src/coreclr/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp index 97c434755e7..90b2fdb6287 100644 --- a/src/coreclr/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp +++ b/src/coreclr/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp @@ -1266,7 +1266,7 @@ InfoAccessType interceptor_ICJI::constructStringLiteral(CORINFO_MODULE_HANDLE mo return original_ICorJitInfo->constructStringLiteral(module, metaTok, ppValue); } -bool interceptor_ICJI::convertPInvokeCalliToCall(CORINFO_RESOLVED_TOKEN * pResolvedToken, bool fMustConvert) +bool interceptor_ICJI::convertPInvokeCalliToCall(CORINFO_RESOLVED_TOKEN* pResolvedToken, bool fMustConvert) { return original_ICorJitInfo->convertPInvokeCalliToCall(pResolvedToken, fMustConvert); } diff --git a/src/coreclr/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp index 43ac5a8502a..31be0883aae 100644 --- a/src/coreclr/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp +++ b/src/coreclr/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp @@ -1580,7 +1580,7 @@ void* MyICJI::getTailCallCopyArgsThunk(CORINFO_SIG_INFO* pSig, CorInfoHelperTail return jitInstance->mc->repGetTailCallCopyArgsThunk(pSig, flags); } -bool MyICJI::convertPInvokeCalliToCall(CORINFO_RESOLVED_TOKEN * pResolvedToken, bool fMustConvert) +bool MyICJI::convertPInvokeCalliToCall(CORINFO_RESOLVED_TOKEN* pResolvedToken, bool fMustConvert) { jitInstance->mc->cr->AddCall("convertPInvokeCalliToCall"); return jitInstance->mc->repConvertPInvokeCalliToCall(pResolvedToken, fMustConvert); diff --git a/src/coreclr/src/ToolBox/superpmi/superpmi/parallelsuperpmi.cpp b/src/coreclr/src/ToolBox/superpmi/superpmi/parallelsuperpmi.cpp index 70afb5ce20e..f58ec663808 100644 --- a/src/coreclr/src/ToolBox/superpmi/superpmi/parallelsuperpmi.cpp +++ b/src/coreclr/src/ToolBox/superpmi/superpmi/parallelsuperpmi.cpp @@ -195,6 +195,7 @@ void ProcessChildStdOut(const CommandLine::Options& o, int* loaded, int* jitted, int* failed, + int* excluded, int* diffs, bool* usageError) { @@ -238,44 +239,42 @@ void ProcessChildStdOut(const CommandLine::Options& o, } else if (strncmp(buff, g_AllFormatStringFixedPrefix, strlen(g_AllFormatStringFixedPrefix)) == 0) { + int childLoaded = 0, childJitted = 0, childFailed = 0, childExcluded = 0; if (o.applyDiff) { - int temp1 = 0, temp2 = 0, temp3 = 0, temp4 = 0; - int converted = sscanf_s(buff, g_AsmDiffsSummaryFormatString, &temp1, &temp2, &temp3, &temp4); - if (converted != 4) + int childDiffs = 0; + int converted = sscanf_s(buff, g_AsmDiffsSummaryFormatString, &childLoaded, &childJitted, &childFailed, + &childExcluded, &childDiffs); + if (converted != 5) { LogError("Couldn't parse status message: \"%s\"", buff); + continue; } - else - { - *loaded += temp1; - *jitted += temp2; - *failed += temp3; - *diffs += temp4; - } + *diffs += childDiffs; } else { - int temp1 = 0, temp2 = 0, temp3 = 0; - int converted = sscanf_s(buff, g_SummaryFormatString, &temp1, &temp2, &temp3); - if (converted != 3) + int converted = + sscanf_s(buff, g_SummaryFormatString, &childLoaded, &childJitted, &childFailed, &childExcluded); + if (converted != 4) { LogError("Couldn't parse status message: \"%s\"", buff); + continue; } - else - { - *loaded += temp1; - *jitted += temp2; - *failed += temp3; - *diffs = -1; - } + *diffs = -1; } + *loaded += childLoaded; + *jitted += childJitted; + *failed += childFailed; + *excluded += childExcluded; } } Cleanup: if (fp != NULL) + { fclose(fp); + } } #ifndef FEATURE_PAL // TODO-Porting: handle Ctrl-C signals gracefully on Unix @@ -604,14 +603,14 @@ int doParallelSuperPMI(CommandLine::Options& o) bool usageError = false; // variable to flag if we hit a usage error in SuperPMI - int loaded = 0, jitted = 0, failed = 0, diffs = 0; + int loaded = 0, jitted = 0, failed = 0, excluded = 0, diffs = 0; // Read the stderr files and log them as errors // Read the stdout files and parse them for counts and log any MISSING or ISSUE errors for (int i = 0; i < o.workerCount; i++) { ProcessChildStdErr(arrStdErrorPath[i]); - ProcessChildStdOut(o, arrStdOutputPath[i], &loaded, &jitted, &failed, &diffs, &usageError); + ProcessChildStdOut(o, arrStdOutputPath[i], &loaded, &jitted, &failed, &excluded, &diffs, &usageError); if (usageError) break; } diff --git a/src/coreclr/src/ToolBox/superpmi/superpmi/superpmi.cpp b/src/coreclr/src/ToolBox/superpmi/superpmi/superpmi.cpp index be5476e8c38..5e80854fa86 100644 --- a/src/coreclr/src/ToolBox/superpmi/superpmi/superpmi.cpp +++ b/src/coreclr/src/ToolBox/superpmi/superpmi/superpmi.cpp @@ -26,8 +26,8 @@ extern int doParallelSuperPMI(CommandLine::Options& o); // There must be a single, fixed prefix common to all strings, to ease the determination of when // to parse the string fully. const char* const g_AllFormatStringFixedPrefix = "Loaded "; -const char* const g_SummaryFormatString = "Loaded %d Jitted %d FailedCompile %d"; -const char* const g_AsmDiffsSummaryFormatString = "Loaded %d Jitted %d FailedCompile %d Diffs %d"; +const char* const g_SummaryFormatString = "Loaded %d Jitted %d FailedCompile %d Excluded %d"; +const char* const g_AsmDiffsSummaryFormatString = "Loaded %d Jitted %d FailedCompile %d Excluded %d Diffs %d"; //#define SuperPMI_ChewMemory 0x7FFFFFFF //Amount of address space to consume on startup @@ -238,6 +238,7 @@ int __cdecl main(int argc, char* argv[]) int errorCount = 0; int missingCount = 0; int index = 0; + int excludedCount = 0; st1.Start(); NearDiffer nearDiffer(o.targetArchitecture, o.useCoreDisTools); @@ -284,7 +285,17 @@ int __cdecl main(int argc, char* argv[]) loadedCount++; if (!MethodContext::Initialize(loadedCount, mcb.buff, mcb.size, &mc)) + { return (int)SpmiResult::GeneralFailure; + } + + if (reader->IsMethodExcluded(mc)) + { + excludedCount++; + LogInfo("main method %d of size %d with was excluded from the compilation.", + reader->GetMethodContextIndex(), mc->methodSize); + continue; + } if (jit == nullptr) { @@ -552,12 +563,12 @@ int __cdecl main(int argc, char* argv[]) // NOTE: these output status strings are parsed by parallelsuperpmi.cpp::ProcessChildStdOut(). if (o.applyDiff) { - LogInfo(g_AsmDiffsSummaryFormatString, loadedCount, jittedCount, failToReplayCount, + LogInfo(g_AsmDiffsSummaryFormatString, loadedCount, jittedCount, failToReplayCount, excludedCount, jittedCount - failToReplayCount - matchCount); } else { - LogInfo(g_SummaryFormatString, loadedCount, jittedCount, failToReplayCount); + LogInfo(g_SummaryFormatString, loadedCount, jittedCount, failToReplayCount, excludedCount); } st2.Stop();