summaryrefslogtreecommitdiff
path: root/src/ToolBox/superpmi/superpmi-shared/compileresult.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ToolBox/superpmi/superpmi-shared/compileresult.cpp')
-rw-r--r--src/ToolBox/superpmi/superpmi-shared/compileresult.cpp1080
1 files changed, 1080 insertions, 0 deletions
diff --git a/src/ToolBox/superpmi/superpmi-shared/compileresult.cpp b/src/ToolBox/superpmi/superpmi-shared/compileresult.cpp
new file mode 100644
index 0000000000..b15c51f28a
--- /dev/null
+++ b/src/ToolBox/superpmi/superpmi-shared/compileresult.cpp
@@ -0,0 +1,1080 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+//----------------------------------------------------------
+// CompileResult.cpp - CompileResult contains the stuff generated by a compilation
+//----------------------------------------------------------
+
+#include "standardpch.h"
+#include "compileresult.h"
+#include "methodcontext.h"
+
+CompileResult::CompileResult()
+{
+ #define LWM(map,key,value) map = nullptr;
+ #include "crlwmlist.h"
+
+ //Not persisted to disk. though should it be?
+ CallTargetTypes = new LightWeightMap<DWORDLONG, DWORD>();
+
+ allocMemDets.hotCodeSize = 0;
+ allocMemDets.coldCodeSize = 0;
+ allocMemDets.roDataSize = 0;
+ allocMemDets.xcptnsCount = 0;
+ allocMemDets.flag = (CorJitAllocMemFlag)0;
+ allocMemDets.hotCodeBlock = 0;
+ allocMemDets.coldCodeBlock = 0;
+ allocMemDets.roDataBlock = 0;
+
+ allocGCInfoDets.retval = 0;
+ allocGCInfoDets.size = 0;
+
+ codeHeap = nullptr;
+}
+
+CompileResult::~CompileResult()
+{
+ #define LWM(map,key,value) if (map != nullptr) delete map;
+ #include "crlwmlist.h"
+
+ if (CallTargetTypes != nullptr) delete CallTargetTypes;
+
+#ifndef FEATURE_PAL // PAL doesn't have HeapDestroy()
+ if(codeHeap != nullptr)
+ ::HeapDestroy(codeHeap);
+#endif // !FEATURE_PAL
+}
+
+// Is the CompileResult empty? Define this as whether all the maps that store information given by the JIT are empty.
+// This is useful when determining if a function won't apply after a "mcs -removeDump -thin" operation has been run.
+bool CompileResult::IsEmpty()
+{
+ bool isEmpty = true;
+
+ #define LWM(map,key,value) if (map != nullptr) isEmpty = false;
+ #include "crlwmlist.h"
+
+ return isEmpty;
+}
+
+HANDLE CompileResult::getCodeHeap()
+{
+ if(codeHeap == nullptr)
+ codeHeap = ::HeapCreate(0,0,0);
+ if(codeHeap == nullptr)
+ {
+ LogError("CompileResult::codeHeap() failed to acquire a heap.");
+ __debugbreak();
+ }
+ return codeHeap;
+}
+
+void CompileResult::recAssert(const char *assertText)
+{
+ if(AssertLog == nullptr)
+ AssertLog = new DenseLightWeightMap<DWORD>();
+
+ AssertLog->Append(AssertLog->AddBuffer((const unsigned char*)assertText, (DWORD)strlen(assertText)+1));
+}
+void CompileResult::dmpAssertLog(DWORD key, DWORD value)
+{
+ const char *assert = (const char *)AssertLog->GetBuffer(value);
+ printf("AssertLog key %u, value '%s'", key, assert);
+ AssertLog->Unlock();
+}
+const char *CompileResult::repAssert()
+{
+ if((AssertLog==nullptr)||(AssertLog->GetCount()==0))
+ return nullptr;
+ return (const char *)AssertLog->GetBuffer(AssertLog->Get((DWORD)0));
+}
+
+void CompileResult::AddCall(const char *name)
+{
+ if(CallLog == nullptr)
+ CallLog = new DenseLightWeightMap<DWORD>();
+ //if(name[0] != '+')
+ //CallLog->Append(CallLog->AddBuffer((const unsigned char *)name, (DWORD)strlen(name)+1));
+}
+unsigned int CompileResult::CallLog_GetCount()
+{
+ return CallLog->GetCount();
+}
+
+bool CompileResult::CallLog_Contains(const char *str)
+{
+ return (CallLog->Contains((unsigned char *)str, (unsigned int)strlen(str))>0);
+}
+void CompileResult::dmpCallLog(DWORD key, DWORD value)
+{
+ const char* temp = (const char*)CallLog->GetBuffer(value);
+ printf("CallLog %u '%s'", key, temp);
+ CallLog->Unlock();
+}
+
+void CompileResult::dumpToConsole()
+{
+ printf("***************************************** CompileResult\n");
+
+ #define LWM(map,key,value) dumpLWM(this,map)
+ #define DENSELWM(map,value) dumpLWMDense(this,map)
+ #include "crlwmlist.h"
+
+ printf("-----------------------------------------\n");
+}
+
+//Note - EE allocates these blocks (and the exception blocks) in a single linear region.
+//Note - EE assures that RoBlock is 8 byte aligned
+void CompileResult::recAllocMem(ULONG hotCodeSize, ULONG coldCodeSize, ULONG roDataSize, ULONG xcptnsCount, CorJitAllocMemFlag flag,
+ void **hotCodeBlock, void **coldCodeBlock, void **roDataBlock)
+{
+ //Grab the values, so we can scrape the real answers in the capture method
+ allocMemDets.hotCodeSize = hotCodeSize;
+ allocMemDets.coldCodeSize = coldCodeSize;
+ allocMemDets.roDataSize = roDataSize;
+ allocMemDets.xcptnsCount = xcptnsCount;
+ allocMemDets.flag = flag;
+ allocMemDets.hotCodeBlock = *hotCodeBlock;
+ allocMemDets.coldCodeBlock = *coldCodeBlock;
+ allocMemDets.roDataBlock = *roDataBlock;
+}
+void CompileResult::recAllocMemCapture()
+{
+ if(AllocMem == nullptr)
+ AllocMem = new LightWeightMap<DWORD, Agnostic_AllocMemDetails>();
+
+ Agnostic_AllocMemDetails value;
+
+ value.hotCodeSize = (DWORD)allocMemDets.hotCodeSize;
+ value.coldCodeSize = (DWORD)allocMemDets.coldCodeSize;
+ value.roDataSize = (DWORD)allocMemDets.roDataSize;
+ value.xcptnsCount = (DWORD)allocMemDets.xcptnsCount;
+ value.flag = (DWORD)allocMemDets.flag;
+ value.hotCodeBlock_offset = (DWORD)AllocMem->AddBuffer((const unsigned char*)allocMemDets.hotCodeBlock, allocMemDets.hotCodeSize);
+ value.coldCodeBlock_offset = (DWORD)AllocMem->AddBuffer((const unsigned char*)allocMemDets.coldCodeBlock, allocMemDets.coldCodeSize);
+ value.roDataBlock_offset = (DWORD)AllocMem->AddBuffer((const unsigned char*)allocMemDets.roDataBlock, allocMemDets.roDataSize);
+ value.hotCodeBlock = (DWORDLONG)allocMemDets.hotCodeBlock;
+ value.coldCodeBlock = (DWORDLONG)allocMemDets.coldCodeBlock;
+ value.roDataBlock = (DWORDLONG)allocMemDets.roDataBlock;
+
+ AllocMem->Add(0, value);
+}
+void CompileResult::dmpAllocMem(DWORD key, const Agnostic_AllocMemDetails& value)
+{
+ printf("AllocMem key 0, value hotCodeSize-%u coldCodeSize-%u roDataSize-%u xcptnsCount-%u flag-%08X hotCodeBlock_offset-%u coldCodeBlock_offset-%u roDataBlock_offset-%u hotCodeBlock-%016llX coldCodeBlock-%016llX roDataBlock-%016llX",
+ value.hotCodeSize,
+ value.coldCodeSize,
+ value.roDataSize,
+ value.xcptnsCount,
+ value.flag,
+ value.hotCodeBlock_offset,
+ value.coldCodeBlock_offset,
+ value.roDataBlock_offset,
+ value.hotCodeBlock,
+ value.coldCodeBlock,
+ value.roDataBlock);
+}
+
+// We can't allocate memory in the same place is was during recording, so we pass back code/data block pointers
+// that point into the AllocMem LightWeightMap, but also return what the original addresses were during recording.
+void CompileResult::repAllocMem(
+ ULONG *hotCodeSize,
+ ULONG *coldCodeSize,
+ ULONG *roDataSize,
+ ULONG *xcptnsCount,
+ CorJitAllocMemFlag *flag,
+ unsigned char **hotCodeBlock,
+ unsigned char **coldCodeBlock,
+ unsigned char **roDataBlock,
+ void **orig_hotCodeBlock,
+ void **orig_coldCodeBlock,
+ void **orig_roDataBlock)
+{
+ Agnostic_AllocMemDetails value;
+
+ value = AllocMem->Get(0);
+
+ *hotCodeSize = (ULONG)value.hotCodeSize;
+ *coldCodeSize = (ULONG)value.coldCodeSize;
+ *roDataSize = (ULONG)value.roDataSize;
+ *xcptnsCount = (ULONG)value.xcptnsCount;
+ *flag = (CorJitAllocMemFlag)value.flag;
+
+ if(*hotCodeSize>0)
+ *hotCodeBlock = AllocMem->GetBuffer(value.hotCodeBlock_offset);
+ else
+ *hotCodeBlock = nullptr;
+
+ if(*coldCodeSize>0)
+ *coldCodeBlock = AllocMem->GetBuffer(value.coldCodeBlock_offset);
+ else
+ *coldCodeBlock = nullptr;
+
+ if(*roDataSize>0)
+ *roDataBlock = AllocMem->GetBuffer(value.roDataBlock_offset);
+ else
+ *roDataBlock = nullptr;
+
+ *orig_hotCodeBlock = (void *)value.hotCodeBlock;
+ *orig_coldCodeBlock = (void *)value.coldCodeBlock;
+ *orig_roDataBlock = (void *)value.roDataBlock;
+}
+
+//Note - Ownership of pMap is transfered with this call. In replay icorjitinfo we should free it.
+void CompileResult::recSetBoundaries(CORINFO_METHOD_HANDLE ftn, ULONG32 cMap, ICorDebugInfo::OffsetMapping *pMap)
+{
+ if(SetBoundaries == nullptr)
+ SetBoundaries = new LightWeightMap<DWORD, Agnostic_SetBoundaries>();
+
+ Agnostic_SetBoundaries value;
+
+ value.ftn = (DWORDLONG)ftn;
+ value.cMap = (DWORD)cMap;
+ value.pMap_offset = (DWORD)SetBoundaries->AddBuffer((const unsigned char*)pMap, sizeof(ICorDebugInfo::OffsetMapping)*cMap);
+
+ SetBoundaries->Add(0, value);
+}
+void CompileResult::dmpSetBoundaries(DWORD key, const Agnostic_SetBoundaries& value)
+{
+ ICorDebugInfo::OffsetMapping *om = (ICorDebugInfo::OffsetMapping *)SetBoundaries->GetBuffer(value.pMap_offset);
+ printf("SetBoundaries key 0, value ftn-%016llX cMap-%u %u{",
+ value.ftn,
+ value.cMap,
+ value.pMap_offset);
+ for(unsigned int i=0;i<value.cMap;i++)
+ {
+ if (i != 0)
+ printf(", ");
+ printf("%u %u %u", om[i].ilOffset, om[i].nativeOffset, om[i].source);
+ }
+ printf("}");
+ SetBoundaries->Unlock();
+}
+bool CompileResult::repSetBoundaries(CORINFO_METHOD_HANDLE *ftn, ULONG32 *cMap, ICorDebugInfo::OffsetMapping **pMap)
+{
+ if((SetBoundaries == nullptr)||(SetBoundaries->GetCount()==0))
+ {
+ *ftn = (CORINFO_METHOD_HANDLE)-1;
+ *cMap = -1;
+ *pMap = nullptr;
+ return false;
+ }
+ Agnostic_SetBoundaries value;
+
+ value = SetBoundaries->Get(0);
+
+ *ftn = (CORINFO_METHOD_HANDLE)value.ftn;
+ *cMap = (ULONG32)value.cMap;
+ *pMap = (ICorDebugInfo::OffsetMapping *)SetBoundaries->GetBuffer(value.pMap_offset);
+ return true;
+}
+
+//Note - Ownership of vars is transfered with this call. In replay icorjitinfo we should free it.
+void CompileResult::recSetVars(CORINFO_METHOD_HANDLE ftn, ULONG32 cVars, ICorDebugInfo::NativeVarInfo *vars)
+{
+ if(SetVars == nullptr)
+ SetVars = new LightWeightMap<DWORD, Agnostic_SetVars>();
+
+ Agnostic_SetVars value;
+
+ value.ftn = (DWORDLONG)ftn;
+ value.cVars = (DWORD)cVars;
+ value.vars_offset = (DWORD)SetVars->AddBuffer((const unsigned char*)vars, sizeof(ICorDebugInfo::NativeVarInfo)*cVars); //not deep enough.. vlt memory is pointer sized.
+
+ SetVars->Add(0, value);
+}
+void CompileResult::dmpSetVars(DWORD key, const Agnostic_SetVars& value)
+{
+ ICorDebugInfo::NativeVarInfo *om = (ICorDebugInfo::NativeVarInfo *)SetVars->GetBuffer(value.vars_offset);
+ printf("SetVars key %u, value ftn-%016llX cVars-%u %u{",
+ key,
+ value.ftn,
+ value.cVars,
+ value.vars_offset);
+ for (unsigned int i = 0; i < value.cVars; i++)
+ {
+ if (i != 0)
+ printf(", ");
+ printf("so-%u eo-%u var-%u", om[i].startOffset, om[i].endOffset, om[i].varNumber);
+ }
+ printf("}");
+ SetVars->Unlock();
+}
+bool CompileResult::repSetVars(CORINFO_METHOD_HANDLE *ftn, ULONG32 *cVars, ICorDebugInfo::NativeVarInfo **vars)
+{
+ if((SetVars == nullptr)||(SetVars->GetCount()==0))
+ {
+ *ftn = (CORINFO_METHOD_HANDLE)-1;
+ *cVars = -1;
+ *vars = nullptr;
+ return false;
+ }
+
+ Agnostic_SetVars value;
+
+ value = SetVars->Get(0);
+
+ *ftn = (CORINFO_METHOD_HANDLE)value.ftn;
+ *cVars = (ULONG32)value.cVars;
+ *vars = (ICorDebugInfo::NativeVarInfo*)SetVars->GetBuffer(value.vars_offset);
+
+ return true;
+}
+
+void CompileResult::recAllocGCInfo(size_t size, void* retval)
+{
+ allocGCInfoDets.size = size;
+ allocGCInfoDets.retval = retval;
+}
+void CompileResult::recAllocGCInfoCapture()
+{
+ if(AllocGCInfo == nullptr)
+ AllocGCInfo = new LightWeightMap<DWORD, Agnostic_AllocGCInfo>();
+
+ Agnostic_AllocGCInfo value;
+
+ value.size = allocGCInfoDets.size;
+ value.retval_offset = (DWORD)AllocGCInfo->AddBuffer((const unsigned char *)allocGCInfoDets.retval, (DWORD)allocGCInfoDets.size);
+
+ AllocGCInfo->Add(0, value);
+}
+void CompileResult::dmpAllocGCInfo(DWORD key, const Agnostic_AllocGCInfo& value)
+{
+ const unsigned char *buff = AllocGCInfo->GetBuffer(value.retval_offset);
+ printf("AllocGCInfo key 0, ");
+ printf("sz-%llu %p{ ", value.size, buff);
+ for(unsigned int i=0; i<value.size; i++)
+ printf("%02X ", *(buff+i));
+ printf("}");
+ AllocGCInfo->Unlock();
+}
+void CompileResult::repAllocGCInfo(size_t *size, void **retval)
+{
+ Agnostic_AllocGCInfo value;
+
+ value = AllocGCInfo->Get(0);
+
+ *size = (size_t)value.size;
+ if(*size>0)
+ *retval = (void *)AllocGCInfo->GetBuffer(value.retval_offset);
+}
+
+void CompileResult::recCompileMethod(BYTE **nativeEntry, ULONG *nativeSizeOfCode, CorJitResult result)
+{
+ if(CompileMethod == nullptr)
+ CompileMethod = new LightWeightMap<DWORD, Agnostic_CompileMethodResults>();
+
+ Agnostic_CompileMethodResults value;
+ value.nativeEntry = (DWORDLONG)*nativeEntry;
+ value.nativeSizeOfCode = (DWORD)*nativeSizeOfCode;
+ value.CorJitResult = (DWORD)result;
+
+ CompileMethod->Add(0, value);
+}
+void CompileResult::dmpCompileMethod(DWORD key, const Agnostic_CompileMethodResults& value)
+{
+ printf("CompileMethod key %u, value nativeEntry-%016llX nativeSizeOfCode-%u CorJitResult-%u",
+ key, value.nativeEntry, value.nativeSizeOfCode, value.CorJitResult);
+}
+void CompileResult::repCompileMethod(BYTE **nativeEntry, ULONG *nativeSizeOfCode, CorJitResult *result)
+{
+ Agnostic_CompileMethodResults value;
+ value = CompileMethod->Get(0);
+ *nativeEntry = (BYTE *)value.nativeEntry;
+ *nativeSizeOfCode = (ULONG)value.nativeSizeOfCode;
+ *result = (CorJitResult)value.CorJitResult;
+}
+
+void CompileResult::recMessageLog(const char* fmt, ...)
+{
+ // TODO-Cleanup: ???
+ return;
+ if(MessageLog == nullptr)
+ MessageLog = new DenseLightWeightMap<DWORD>();
+
+ va_list args;
+
+ // retrieve the variable arguments
+ va_start( args, fmt );
+
+ size_t len = _vscprintf(fmt, args) + 1; //space for the terminator
+
+ unsigned char *messageLogBuffer = new unsigned char[len];
+ vsprintf_s((char*)messageLogBuffer, len, fmt, args);
+ messageLogBuffer[len-1] = 0;
+ MessageLog->Append(MessageLog->AddBuffer(messageLogBuffer, (DWORD)len));
+ delete []messageLogBuffer;
+}
+void CompileResult::dmpMessageLog(DWORD key, DWORD value)
+{
+ printf("MessageLog NYI");
+}
+
+void CompileResult::recClassMustBeLoadedBeforeCodeIsRun(CORINFO_CLASS_HANDLE cls)
+{
+ if(ClassMustBeLoadedBeforeCodeIsRun == nullptr)
+ ClassMustBeLoadedBeforeCodeIsRun = new DenseLightWeightMap<DWORDLONG>();
+
+ ClassMustBeLoadedBeforeCodeIsRun->Append((DWORDLONG)cls);
+}
+void CompileResult::dmpClassMustBeLoadedBeforeCodeIsRun(DWORD key, DWORDLONG value)
+{
+ printf("ClassMustBeLoadedBeforeCodeIsRun key %u, value cls-%016llX",
+ key, value);
+}
+
+void CompileResult::recReportInliningDecision(CORINFO_METHOD_HANDLE inlinerHnd, CORINFO_METHOD_HANDLE inlineeHnd,
+ CorInfoInline inlineResult, const char * reason)
+{
+ if(ReportInliningDecision == nullptr)
+ ReportInliningDecision = new DenseLightWeightMap<Agnostic_ReportInliningDecision>();
+
+ Agnostic_ReportInliningDecision value;
+
+ value.inlinerHnd = (DWORDLONG)inlinerHnd;
+ value.inlineeHnd = (DWORDLONG)inlineeHnd;
+ value.inlineResult = (DWORD)inlineResult;
+ if(reason!=nullptr)
+ value.reason_offset = (DWORD)ReportInliningDecision->AddBuffer((unsigned char*)reason, (DWORD)strlen(reason)+1);
+ else
+ value.reason_offset = -1;
+
+ ReportInliningDecision->Append(value);
+}
+void CompileResult::dmpReportInliningDecision(DWORD key, const Agnostic_ReportInliningDecision& value)
+{
+ const char *reason = (const char*)ReportInliningDecision->GetBuffer(value.reason_offset);
+ printf("ReportInliningDecision key %u, value inliner-%016llX inlinee-%016llX res-%u reason-'%s'",
+ key,
+ value.inlinerHnd,
+ value.inlineeHnd,
+ value.inlineResult,
+ reason);
+ ReportInliningDecision->Unlock();
+}
+CorInfoInline CompileResult::repReportInliningDecision(CORINFO_METHOD_HANDLE inlinerHnd, CORINFO_METHOD_HANDLE inlineeHnd)
+{
+ CorInfoInline result = INLINE_FAIL;
+ if(ReportInliningDecision!=nullptr)
+ {
+ Agnostic_ReportInliningDecision *items = ReportInliningDecision->GetRawItems();
+ unsigned int cnt = ReportInliningDecision->GetCount();
+ for(unsigned int i=0;i<cnt;i++)
+ {
+ if((items[i].inlinerHnd == (DWORDLONG)inlinerHnd)&&(items[i].inlineeHnd == (DWORDLONG)inlineeHnd)&&
+ (items[i].inlineResult == INLINE_PASS))
+ result = INLINE_PASS;
+ }
+ }
+ return result;
+}
+
+void CompileResult::recSetEHcount(unsigned cEH)
+{
+ if(SetEHcount == nullptr)
+ SetEHcount = new LightWeightMap<DWORD, DWORD>();
+
+ SetEHcount->Add((DWORD)0, (DWORD)cEH);
+}
+void CompileResult::dmpSetEHcount(DWORD key, DWORD value)
+{
+ printf("SetEHcount key %u, value %u", key, value);
+}
+ULONG CompileResult::repSetEHcount()
+{
+ if(SetEHcount==nullptr)
+ SetEHcount = new LightWeightMap<DWORD, DWORD>();
+
+ ULONG ehCount;
+ int index = SetEHcount->GetIndex(0);
+ if(index < 0)
+ ehCount = 0;
+ else
+ ehCount = (ULONG)SetEHcount->Get(index);
+ return ehCount;
+}
+
+void CompileResult::recSetEHinfo(unsigned EHnumber, const CORINFO_EH_CLAUSE *clause)
+{
+ if(SetEHinfo == nullptr)
+ SetEHinfo = new LightWeightMap<DWORD, Agnostic_CORINFO_EH_CLAUSE2>();
+
+ Agnostic_CORINFO_EH_CLAUSE2 value;
+ value.Flags = (DWORD)clause->Flags;
+ value.TryOffset = (DWORD)clause->TryOffset;
+ value.TryLength = (DWORD)clause->TryLength;
+ value.HandlerOffset = (DWORD)clause->HandlerOffset;
+ value.HandlerLength = (DWORD)clause->HandlerLength;
+ value.ClassToken = (DWORD)clause->ClassToken;
+
+ SetEHinfo->Add((DWORD)EHnumber, value);
+}
+void CompileResult::dmpSetEHinfo(DWORD key, const Agnostic_CORINFO_EH_CLAUSE2& value)
+{
+ printf("SetEHinfo key %u, value flg-%u to-%u tl-%u ho-%u hl-%u",
+ key,
+ value.Flags,
+ value.TryOffset,
+ value.TryLength,
+ value.HandlerOffset,
+ value.HandlerLength);
+ if ((CORINFO_EH_CLAUSE_FLAGS)value.Flags == CORINFO_EH_CLAUSE_FILTER)
+ {
+ printf(" fo-%u", value.ClassToken); // FilterOffset
+ }
+ else if ((CORINFO_EH_CLAUSE_FLAGS)value.Flags == CORINFO_EH_CLAUSE_NONE)
+ {
+ printf(" cls-%08X", value.ClassToken);
+ }
+ // else, no need to print for finally/fault handlers
+}
+void CompileResult::repSetEHinfo(unsigned EHnumber, ULONG *flags, ULONG *tryOffset, ULONG *tryLength, ULONG *handlerOffset, ULONG *handlerLength, ULONG *classToken)
+{
+ Agnostic_CORINFO_EH_CLAUSE2 value;
+ value = SetEHinfo->Get(EHnumber);
+
+ *flags=(ULONG)value.Flags;
+ *tryOffset=(ULONG)value.TryOffset;
+ *tryLength=(ULONG)value.TryLength;
+ *handlerOffset=(ULONG)value.HandlerOffset;
+ *handlerLength=(ULONG)value.HandlerLength;
+ *classToken=(ULONG)value.ClassToken;
+}
+
+void CompileResult::recSetMethodAttribs(CORINFO_METHOD_HANDLE ftn, CorInfoMethodRuntimeFlags attribs)
+{
+ if(SetMethodAttribs == nullptr)
+ SetMethodAttribs = new LightWeightMap<DWORDLONG, DWORD>();
+
+ SetMethodAttribs->Add((DWORDLONG)ftn, (DWORD)attribs);
+}
+void CompileResult::dmpSetMethodAttribs(DWORDLONG key, DWORD value)
+{
+ printf("SetMethodAttribs key ftn-%016llX, value attr-%08X", key, value);
+}
+CorInfoMethodRuntimeFlags CompileResult::repSetMethodAttribs (CORINFO_METHOD_HANDLE ftn)
+{
+ if((SetMethodAttribs==nullptr)||(SetMethodAttribs->GetIndex((DWORDLONG)ftn)==-1))
+ return (CorInfoMethodRuntimeFlags)0;
+ CorInfoMethodRuntimeFlags result = (CorInfoMethodRuntimeFlags)SetMethodAttribs->Get((DWORDLONG)ftn);
+ return result;
+}
+
+void CompileResult::recMethodMustBeLoadedBeforeCodeIsRun(CORINFO_METHOD_HANDLE method)
+{
+ if(MethodMustBeLoadedBeforeCodeIsRun == nullptr)
+ MethodMustBeLoadedBeforeCodeIsRun = new DenseLightWeightMap<DWORDLONG>();
+
+ MethodMustBeLoadedBeforeCodeIsRun->Append((DWORDLONG)method);
+}
+void CompileResult::dmpMethodMustBeLoadedBeforeCodeIsRun(DWORD key, DWORDLONG value)
+{
+ printf("MethodMustBeLoadedBeforeCodeIsRun key %u, value ftn-%016llX", key, value);
+}
+
+void CompileResult::recReportTailCallDecision(CORINFO_METHOD_HANDLE callerHnd, CORINFO_METHOD_HANDLE calleeHnd, bool fIsTailPrefix,
+ CorInfoTailCall tailCallResult, const char * reason)
+{
+ if(ReportTailCallDecision == nullptr)
+ ReportTailCallDecision = new DenseLightWeightMap<Agnostic_ReportTailCallDecision>();
+
+ Agnostic_ReportTailCallDecision value;
+
+ value.callerHnd = (DWORDLONG)callerHnd;
+ value.calleeHnd = (DWORDLONG)calleeHnd;
+ value.fIsTailPrefix = (DWORD)fIsTailPrefix;
+ value.tailCallResult = (DWORD)tailCallResult;
+ if(reason!=nullptr) //protect strlen
+ value.reason_index = (DWORD)ReportTailCallDecision->AddBuffer((unsigned char*)reason, (DWORD)strlen(reason)+1);
+ else
+ value.reason_index = (DWORD)-1;
+
+ ReportTailCallDecision->Append(value);
+}
+void CompileResult::dmpReportTailCallDecision(DWORD key, const Agnostic_ReportTailCallDecision& value)
+{
+ const char *reason = (const char*)ReportTailCallDecision->GetBuffer(value.reason_index);
+ printf("ReportTailCallDecision key-%u, value cr-%016llX ce-%016llX tail-%u call-%u -%s",
+ key, value.callerHnd, value.calleeHnd, value.tailCallResult, value.tailCallResult, reason);
+ ReportTailCallDecision->Unlock();
+}
+
+void CompileResult::recReportFatalError(CorJitResult result)
+{
+ if(ReportFatalError == nullptr)
+ ReportFatalError = new DenseLightWeightMap<DWORD>();
+
+ ReportFatalError->Append((DWORD)result);
+}
+void CompileResult::dmpReportFatalError(DWORD key, DWORD value)
+{
+ printf("ReportFatalError key Count-%u, value result-%08X", key, value);
+}
+
+void CompileResult::recRecordRelocation(void *location, void *target, WORD fRelocType, WORD slotNum, INT32 addlDelta)
+{
+ repRecordRelocation(location, target, fRelocType, slotNum, addlDelta);
+}
+
+const char* relocationTypeToString(WORD fRelocType)
+{
+ switch (fRelocType)
+ {
+ // From winnt.h
+ case IMAGE_REL_BASED_ABSOLUTE : return "absolute";
+ case IMAGE_REL_BASED_HIGH : return "high";
+ case IMAGE_REL_BASED_LOW : return "low";
+ case IMAGE_REL_BASED_HIGHLOW : return "highlow";
+ case IMAGE_REL_BASED_HIGHADJ : return "highadj";
+ case IMAGE_REL_BASED_DIR64 : return "dir64";
+
+ // From corinfo.h
+ case IMAGE_REL_BASED_REL32 : return "rel32";
+ case IMAGE_REL_BASED_THUMB_BRANCH24 : return "thumb_branch24";
+ default : return "UNKNOWN";
+ }
+}
+void CompileResult::dmpRecordRelocation(DWORD key, const Agnostic_RecordRelocation& value)
+{
+ printf("RecordRelocation key %u, value loc-%016llX tgt-%016llX fRelocType-%u(%s) slotNum-%u addlDelta-%d",
+ key,
+ value.location,
+ value.target,
+ value.fRelocType,
+ relocationTypeToString((WORD)value.fRelocType),
+ value.slotNum,
+ (INT32)value.addlDelta);
+}
+void CompileResult::repRecordRelocation(void *location, void *target, WORD fRelocType, WORD slotNum, INT32 addlDelta)
+{
+ if(RecordRelocation == nullptr)
+ RecordRelocation = new DenseLightWeightMap<Agnostic_RecordRelocation>();
+
+ Agnostic_RecordRelocation value;
+
+ value.location = (DWORDLONG)location;
+ value.target = (DWORDLONG)target;
+ value.fRelocType = (DWORD)fRelocType;
+ value.slotNum = (DWORD)slotNum;
+ value.addlDelta = (DWORD)addlDelta;
+
+ RecordRelocation->Append(value);
+}
+
+// When we do a replay, we replace the CompileResult that was originally recorded. In most cases,
+// though, as part of our collection process we do a "thinning" operation, using "mcs -removeDup -thin",
+// which removes the CompileResult from the stored file. Because of this, we lose access to the original
+// addresses.
+//
+// Unfortunately, we may have generated code based on the original relative addresses. For example,
+// we might have generated a relocation based on the results of a call to GetFunctionEntryPoint, and
+// the delta from the generated code to that address fit in a rel32 reloc. Or, it didn't fit, but the
+// VM constructed a jump stub in the JIT code section that would fit, and returned that.
+//
+// Ideally, we would just keep all the original addresses and relocations, even if we delete the CompileResult.
+// If a new relocation has the same target as an original relocation, then simply substitute the original
+// delta and use that instead of the newly computed delta.
+//
+// For now, for rel32 relocations, if it doesn't fit, then simply pick an address immediately after the
+// current section (using originalAddr), assuming we needed a jump stub. We'll let multiple calls to potentially
+// different functions use the same address because even if they used different ones, and diffs were generated,
+// no textual diffs would appear because most of the textual call names are "hackishMethodName".
+void CompileResult::applyRelocs(unsigned char *block1, ULONG blocksize1, void *originalAddr)
+{
+ if(RecordRelocation == nullptr)
+ return;
+ if(blocksize1 == 0)
+ return;
+
+ size_t section_begin = (size_t)block1;
+ size_t section_end = (size_t)block1 + (size_t)blocksize1; // address is exclusive
+
+ LogDebug("applyRelocs block [%p,%p) block size %u, orig addr %p",
+ block1,
+ block1 + blocksize1,
+ blocksize1,
+ originalAddr);
+
+ for(unsigned int i=0;i<RecordRelocation->GetCount();i++)
+ {
+ Agnostic_RecordRelocation tmp = RecordRelocation->GetRawItems()[i];
+
+ if (Logger::IsLogLevelEnabled(LOGLEVEL_DEBUG))
+ {
+ printf(" ");
+ dmpRecordRelocation(i, tmp);
+ printf("\n");
+ }
+
+ switch (tmp.fRelocType)
+ {
+ #if defined(_TARGET_X86_)
+ case IMAGE_REL_BASED_HIGHLOW:
+ {
+ DWORDLONG fixupLocation = tmp.location;
+
+ size_t address = section_begin + (size_t)fixupLocation - (size_t)originalAddr;
+ if ( (section_begin <= address) && (address < section_end) ) //A reloc for our section?
+ {
+ LogDebug(" fixupLoc-%016llX (@%p) : %08X => %08X", fixupLocation, address, *(DWORD*)address, (DWORD)tmp.target);
+ *(DWORD*)address = (DWORD)tmp.target;
+ }
+ if (tmp.addlDelta != 0)
+ __debugbreak();
+ if (tmp.slotNum != 0)
+ __debugbreak();
+ }
+ break;
+ #endif // _TARGET_X86_
+
+ #if defined(_TARGET_X86_) || defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_) || defined(_TARGET_ARM_)
+ case IMAGE_REL_BASED_REL32:
+ {
+ DWORDLONG target = tmp.target + tmp.addlDelta;
+ DWORDLONG fixupLocation = tmp.location + tmp.slotNum;
+ DWORDLONG baseAddr = fixupLocation + sizeof(INT32);
+ INT64 delta = (INT64)((BYTE *)target - baseAddr);
+
+ #if defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_)
+ if (delta != (INT64)(int)delta)
+ {
+ // This isn't going to fit in a signed 32-bit address. Use something that will fit,
+ // since we assume that original compilation fit fine. This is only an issue for
+ // 32-bit offsets on 64-bit targets.
+ target = (DWORDLONG)originalAddr + (DWORDLONG)blocksize1;
+ INT64 newdelta = (INT64)((BYTE *)target - baseAddr);
+
+ LogDebug(" REL32 overflow. Mapping target to %016llX. Mapping delta: %016llX => %016llX", target, delta, newdelta);
+
+ delta = newdelta;
+ }
+ #endif // defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_)
+
+ if (delta != (INT64)(int)delta)
+ {
+ #if defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_)
+ LogError("REL32 relocation overflows field! delta=0x%016llX", delta);
+ #else
+ LogError("REL32 relocation overflows field! delta=0x%08X", delta);
+ #endif
+ }
+
+ // Write 32-bits into location
+ size_t address = section_begin + (size_t)fixupLocation - (size_t)originalAddr;
+ if ( (section_begin <= address) && (address < section_end) ) //A reloc for our section?
+ {
+ LogDebug(" fixupLoc-%016llX (@%p) : %08X => %08X", fixupLocation, address, *(DWORD*)address, delta);
+ *(DWORD*)address = (DWORD)delta;
+ }
+ }
+ break;
+ #endif // defined(_TARGET_X86_) || defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_) || defined(_TARGET_ARM_)
+
+ #if defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_)
+ case IMAGE_REL_BASED_DIR64:
+ {
+ DWORDLONG fixupLocation = tmp.location + tmp.slotNum;
+
+ // Write 64-bits into location
+ size_t address = section_begin + (size_t)fixupLocation - (size_t)originalAddr;
+ if ( (section_begin <= address) && (address < section_end) ) //A reloc for our section?
+ {
+ LogDebug(" fixupLoc-%016llX (@%p) %016llX => %016llX", fixupLocation, address, *(DWORDLONG*)address, tmp.target);
+ *(DWORDLONG*)address = tmp.target;
+ }
+ }
+ break;
+ #endif // defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_)
+
+ #ifdef _TARGET_ARM64_
+ case IMAGE_REL_ARM64_BRANCH26: // 26 bit offset << 2 & sign ext, for B and BL
+ case IMAGE_REL_ARM64_PAGEBASE_REL21:
+ case IMAGE_REL_ARM64_PAGEOFFSET_12A:
+ LogError("Unimplemented reloc type %u", tmp.fRelocType);
+ break;
+ #endif // _TARGET_ARM64_
+
+ default:
+ LogError("Unknown reloc type %u", tmp.fRelocType);
+ break;
+ }
+ }
+}
+
+void CompileResult::recProcessName(const char* name)
+{
+ if(ProcessName == nullptr)
+ ProcessName = new DenseLightWeightMap<DWORD>();
+
+ DWORD index = (DWORD)-1;
+ if(name != nullptr)
+ index = (DWORD)ProcessName->AddBuffer((unsigned char*)name, (DWORD)strlen(name)+1);
+
+ ProcessName->Append(index);
+}
+void CompileResult::dmpProcessName(DWORD key, DWORD value)
+{
+ const char *procName = (const char *)ProcessName->GetBuffer(value);
+ printf("ProcessName key %u, value '%s'", key, procName);
+ ProcessName->Unlock();
+}
+const char *CompileResult::repProcessName()
+{
+ if(ProcessName == nullptr)
+ return "hackishProcessName";
+
+ if(ProcessName->GetCount()>0)
+ {
+ return (const char*)ProcessName->GetBuffer(ProcessName->Get((DWORD)0));
+ }
+ return nullptr;
+}
+
+void CompileResult::recAddressMap(void *originalAddress, void *replayAddress, unsigned int size)
+{
+ if(AddressMap == nullptr)
+ AddressMap = new LightWeightMap<DWORDLONG, Agnostic_AddressMap>();
+
+ Agnostic_AddressMap value;
+
+ value.Address = (DWORDLONG)originalAddress;
+ value.size = (DWORD)size;
+
+ AddressMap->Add((DWORDLONG)replayAddress, value);
+}
+void CompileResult::dmpAddressMap(DWORDLONG key, const Agnostic_AddressMap& value)
+{
+ printf("AddressMap key %016llX, value addr-%016llX, size-%u",
+ key,
+ value.Address,
+ value.size);
+}
+void* CompileResult::repAddressMap(void *replayAddress)
+{
+ if (AddressMap == nullptr)
+ return nullptr;
+ Agnostic_AddressMap value;
+ value = AddressMap->Get((DWORDLONG)replayAddress);
+ return (void*)value.Address;
+}
+void *CompileResult::searchAddressMap(void *newAddress)
+{
+ if(AddressMap==nullptr)
+ return (void*)-1;
+ for(unsigned int i=0;i<AddressMap->GetCount();i++)
+ {
+ DWORDLONG replayAddress = AddressMap->GetRawKeys()[i];
+ Agnostic_AddressMap value = AddressMap->Get(replayAddress);
+ if((replayAddress<=(DWORDLONG)newAddress)&&((DWORDLONG)newAddress<(replayAddress+value.size)))
+ return (void *)(value.Address+((DWORDLONG)newAddress-replayAddress));
+ }
+ return (void*)-1;
+}
+
+void CompileResult::recReserveUnwindInfo(BOOL isFunclet, BOOL isColdCode, ULONG unwindSize)
+{
+ if(ReserveUnwindInfo == nullptr)
+ ReserveUnwindInfo = new DenseLightWeightMap<Agnostic_ReserveUnwindInfo>();
+
+ Agnostic_ReserveUnwindInfo value;
+
+ value.isFunclet = (DWORD)isFunclet;
+ value.isColdCode = (DWORD)isColdCode;
+ value.unwindSize = (DWORD)unwindSize;
+
+ ReserveUnwindInfo->Append(value);
+}
+void CompileResult::dmpReserveUnwindInfo(DWORD key, const Agnostic_ReserveUnwindInfo& value)
+{
+ printf("ReserveUnwindInfo key %u, value isFun-%u isCold-%u usz-%u",
+ key, value.isFunclet, value.isColdCode, value.unwindSize);
+}
+
+void CompileResult::recAllocUnwindInfo(BYTE *pHotCode, BYTE *pColdCode, ULONG startOffset, ULONG endOffset, ULONG unwindSize, BYTE *pUnwindBlock,
+ CorJitFuncKind funcKind)
+{
+ if(AllocUnwindInfo == nullptr)
+ AllocUnwindInfo = new DenseLightWeightMap<Agnostic_AllocUnwindInfo>();
+
+ Agnostic_AllocUnwindInfo value;
+ value.pHotCode = (DWORDLONG)pHotCode;
+ value.pColdCode = (DWORDLONG)pColdCode;
+ value.startOffset = (DWORD)startOffset;
+ value.endOffset = (DWORD)endOffset;
+ value.unwindSize = (DWORD)unwindSize;
+ value.pUnwindBlock_index = AllocUnwindInfo->AddBuffer((unsigned char*)pUnwindBlock, unwindSize);
+ value.funcKind = funcKind;
+
+ AllocUnwindInfo->Append(value);
+}
+void CompileResult::dmpAllocUnwindInfo(DWORD key, const Agnostic_AllocUnwindInfo& value)
+{
+ printf("AllocUnwindInfo key %u, value pHot-%016llX pCold-%016llX startOff-%u endOff-%u unwindSz-%u blki-%u funcKind-%u",
+ key,
+ value.pHotCode,
+ value.pColdCode,
+ value.startOffset,
+ value.endOffset,
+ value.unwindSize,
+ value.pUnwindBlock_index,
+ value.funcKind);
+}
+
+void CompileResult::recAllocBBProfileBuffer(ULONG count, ICorJitInfo::ProfileBuffer **profileBuffer, HRESULT result)
+{
+ if(AllocBBProfileBuffer == nullptr)
+ AllocBBProfileBuffer=new LightWeightMap<DWORD, Agnostic_AllocBBProfileBuffer>();
+
+ Agnostic_AllocBBProfileBuffer value;
+
+ value.count = (DWORD)count;
+ value.result = (DWORD)result;
+ value.profileBuffer_index = AllocBBProfileBuffer->AddBuffer((unsigned char*)*profileBuffer, count * sizeof(ICorJitInfo::ProfileBuffer));
+
+ AllocBBProfileBuffer->Add((DWORD)0, value);
+}
+void CompileResult::dmpAllocBBProfileBuffer(DWORD key, const Agnostic_AllocBBProfileBuffer& value)
+{
+ printf("AllocBBProfileBuffer key %u, value cnt-%u ind-%u res-%08X",
+ key,
+ value.count,
+ value.profileBuffer_index,
+ value.result);
+}
+HRESULT CompileResult::repAllocBBProfileBuffer(ULONG count, ICorJitInfo::ProfileBuffer **profileBuffer)
+{
+ Agnostic_AllocBBProfileBuffer value;
+ value = AllocBBProfileBuffer->Get((DWORD)0);
+
+ if(count != value.count)
+ __debugbreak();
+
+ HRESULT result = (HRESULT)value.result;
+ *profileBuffer = (ICorJitInfo::ProfileBuffer *)AllocBBProfileBuffer->GetBuffer(value.profileBuffer_index);
+ recAddressMap((void*)0x4242, (void*)*profileBuffer, count *(sizeof(ICorJitInfo::ProfileBuffer)));
+ return result;
+}
+
+void CompileResult::recRecordCallSite(ULONG instrOffset, CORINFO_SIG_INFO *callSig, CORINFO_METHOD_HANDLE methodHandle)
+{
+ repRecordCallSite(instrOffset, callSig, methodHandle);
+}
+
+void CompileResult::dmpRecordCallSite(DWORD key, const Agnostic_RecordCallSite& value)
+{
+ printf("RecordCallSite key %u, callSig{cc-%u rtc-%016llX rts-%016llX rt-%u flg-%u na-%u cc-%u ci-%u mc-%u mi-%u sig-%u pSig-%u scp-%016llX tok-%08X} ftn-%016llX",
+ key,
+ value.callSig.callConv,
+ value.callSig.retTypeClass,
+ value.callSig.retTypeSigClass,
+ value.callSig.retType,
+ value.callSig.flags,
+ value.callSig.numArgs,
+ value.callSig.sigInst_classInstCount,
+ value.callSig.sigInst_classInst_Index,
+ value.callSig.sigInst_methInstCount,
+ value.callSig.sigInst_methInst_Index,
+ value.callSig.cbSig,
+ value.callSig.pSig,
+ value.callSig.scope,
+ value.callSig.token,
+ value.methodHandle);
+}
+
+void CompileResult::repRecordCallSite(ULONG instrOffset, CORINFO_SIG_INFO *callSig, CORINFO_METHOD_HANDLE methodHandle)
+{
+ if (RecordCallSite == nullptr)
+ RecordCallSite = new LightWeightMap<DWORD, Agnostic_RecordCallSite>();
+
+ Agnostic_RecordCallSite value;
+ ZeroMemory(&value, sizeof(Agnostic_RecordCallSite));
+
+ if (callSig != nullptr)
+ {
+ value.callSig.callConv = (DWORD)callSig->callConv;
+ value.callSig.retTypeClass = (DWORDLONG)callSig->retTypeClass;
+ value.callSig.retTypeSigClass = (DWORDLONG)callSig->retTypeSigClass;
+ value.callSig.retType = (DWORD)callSig->retType;
+ value.callSig.flags = (DWORD)callSig->flags;
+ value.callSig.numArgs = (DWORD)callSig->numArgs;
+ value.callSig.sigInst_classInstCount = (DWORD)callSig->sigInst.classInstCount;
+ value.callSig.sigInst_classInst_Index = RecordCallSite->AddBuffer((unsigned char*)callSig->sigInst.classInst, callSig->sigInst.classInstCount*8); // porting issue
+ value.callSig.sigInst_methInstCount = (DWORD)callSig->sigInst.methInstCount;
+ value.callSig.sigInst_methInst_Index = RecordCallSite->AddBuffer((unsigned char*)callSig->sigInst.methInst, callSig->sigInst.methInstCount*8); // porting issue
+ value.callSig.args = (DWORDLONG)callSig->args;
+ value.callSig.cbSig = (DWORD)callSig->cbSig;
+ value.callSig.pSig = (DWORD)RecordCallSite->AddBuffer((unsigned char *)callSig->pSig, callSig->cbSig);
+ value.callSig.scope = (DWORDLONG)callSig->scope;
+ value.callSig.token = (DWORD)callSig->token;
+ }
+ else
+ {
+ value.callSig.callConv = (DWORD)-1;
+ value.callSig.retTypeClass = (DWORDLONG)-1;
+ value.callSig.retTypeSigClass = (DWORDLONG)-1;
+ value.callSig.retType = (DWORD)-1;
+ value.callSig.flags = (DWORD)-1;
+ value.callSig.numArgs = (DWORD)-1;
+ value.callSig.sigInst_classInstCount = (DWORD)-1;
+ value.callSig.sigInst_classInst_Index = (DWORD)-1;
+ value.callSig.sigInst_methInstCount = (DWORD)-1;
+ value.callSig.sigInst_methInst_Index = (DWORD)-1;
+ value.callSig.args = (DWORDLONG)-1;
+ value.callSig.cbSig = (DWORD)-1;
+ value.callSig.pSig = (DWORD)-1;
+ value.callSig.scope = (DWORDLONG)-1;
+ value.callSig.token = (DWORD)-1;
+ }
+
+ value.methodHandle = (DWORDLONG)methodHandle;
+
+ RecordCallSite->Add(instrOffset, value);
+}
+
+bool CompileResult::fndRecordCallSiteSigInfo(ULONG instrOffset, CORINFO_SIG_INFO *pCallSig)
+{
+ if (RecordCallSite == nullptr)
+ return false;
+
+ if (RecordCallSite->GetIndex(instrOffset) == -1)
+ return false;
+
+ Agnostic_RecordCallSite value = RecordCallSite->Get(instrOffset);
+
+ if (value.callSig.callConv == -1)
+ return false;
+
+ pCallSig->callConv = (CorInfoCallConv)value.callSig.callConv;
+ pCallSig->retTypeClass = (CORINFO_CLASS_HANDLE)value.callSig.retTypeClass;
+ pCallSig->retTypeSigClass = (CORINFO_CLASS_HANDLE)value.callSig.retTypeSigClass;
+ pCallSig->retType = (CorInfoType)value.callSig.retType;
+ pCallSig->flags = (unsigned)value.callSig.flags;
+ pCallSig->numArgs = (unsigned)value.callSig.numArgs;
+ pCallSig->sigInst.classInstCount = (unsigned)value.callSig.sigInst_classInstCount;
+ pCallSig->sigInst.classInst = (CORINFO_CLASS_HANDLE*)RecordCallSite->GetBuffer(value.callSig.sigInst_classInst_Index);
+ pCallSig->sigInst.methInstCount = (unsigned)value.callSig.sigInst_methInstCount;
+ pCallSig->sigInst.methInst = (CORINFO_CLASS_HANDLE*)RecordCallSite->GetBuffer(value.callSig.sigInst_methInst_Index);
+ pCallSig->args = (CORINFO_ARG_LIST_HANDLE)value.callSig.args;
+ pCallSig->cbSig = (unsigned int)value.callSig.cbSig;
+ pCallSig->pSig = (PCCOR_SIGNATURE)RecordCallSite->GetBuffer(value.callSig.pSig);
+ pCallSig->scope = (CORINFO_MODULE_HANDLE)value.callSig.scope;
+ pCallSig->token = (mdToken)value.callSig.token;
+
+ return true;
+}
+
+bool CompileResult::fndRecordCallSiteMethodHandle(ULONG instrOffset, CORINFO_METHOD_HANDLE *pMethodHandle)
+{
+ if (RecordCallSite == nullptr)
+ return false;
+
+ if (RecordCallSite->GetIndex(instrOffset) == -1)
+ return false;
+
+ Agnostic_RecordCallSite value = RecordCallSite->Get(instrOffset);
+ *pMethodHandle = (CORINFO_METHOD_HANDLE)value.methodHandle;
+
+ return true;
+}