summaryrefslogtreecommitdiff
path: root/src/vm/proftoeeinterfaceimpl.cpp
diff options
context:
space:
mode:
authorDavid Mason <davmason@microsoft.com>2017-10-23 20:19:04 -0700
committerGitHub <noreply@github.com>2017-10-23 20:19:04 -0700
commit5d66791a3a1932d2afcd3ef58dd0df91323662cb (patch)
treea602272273f0758b8bb8d59fd0f57350643fc264 /src/vm/proftoeeinterfaceimpl.cpp
parentf8d6405c8e0680a1184dc07123aeb4abe62e9e87 (diff)
downloadcoreclr-5d66791a3a1932d2afcd3ef58dd0df91323662cb.tar.gz
coreclr-5d66791a3a1932d2afcd3ef58dd0df91323662cb.tar.bz2
coreclr-5d66791a3a1932d2afcd3ef58dd0df91323662cb.zip
profiler changes for tiered compilation (#14612)
Add new apis for profiler to use with tiered jitting.
Diffstat (limited to 'src/vm/proftoeeinterfaceimpl.cpp')
-rw-r--r--src/vm/proftoeeinterfaceimpl.cpp328
1 files changed, 288 insertions, 40 deletions
diff --git a/src/vm/proftoeeinterfaceimpl.cpp b/src/vm/proftoeeinterfaceimpl.cpp
index 3958bdf354..b9e5481e0f 100644
--- a/src/vm/proftoeeinterfaceimpl.cpp
+++ b/src/vm/proftoeeinterfaceimpl.cpp
@@ -589,6 +589,10 @@ COM_METHOD ProfToEEInterfaceImpl::QueryInterface(REFIID id, void ** pInterface)
{
*pInterface = static_cast<ICorProfilerInfo8 *>(this);
}
+ else if (id == IID_ICorProfilerInfo9)
+ {
+ *pInterface = static_cast<ICorProfilerInfo9 *>(this);
+ }
else if (id == IID_IUnknown)
{
*pInterface = static_cast<IUnknown *>(static_cast<ICorProfilerInfo *>(this));
@@ -2592,24 +2596,28 @@ HRESULT ProfToEEInterfaceImpl::GetCodeInfo3(FunctionID functionId,
hr = ValidateParametersForGetCodeInfo(pMethodDesc, cCodeInfos, codeInfos);
if (SUCCEEDED(hr))
{
+ PCODE pCodeStart = NULL;
CodeVersionManager* pCodeVersionManager = pMethodDesc->GetCodeVersionManager();
- ILCodeVersion ilCodeVersion = pCodeVersionManager->GetILCodeVersion(pMethodDesc, reJitId);
-
- // Now that tiered compilation can create more than one jitted code version for the same rejit id
- // we are arbitrarily choosing the first one to return. To return all of them we'd presumably need
- // a new profiler API.
- NativeCodeVersionCollection nativeCodeVersions = ilCodeVersion.GetNativeCodeVersions(pMethodDesc);
- for (NativeCodeVersionIterator iter = nativeCodeVersions.Begin(); iter != nativeCodeVersions.End(); iter++)
{
- PCODE pCodeStart = iter->GetNativeCode();
- hr = GetCodeInfoFromCodeStart(
- pCodeStart,
- cCodeInfos,
- pcCodeInfos,
- codeInfos);
- break;
+ CodeVersionManager::TableLockHolder lockHolder(pCodeVersionManager);
+
+ ILCodeVersion ilCodeVersion = pCodeVersionManager->GetILCodeVersion(pMethodDesc, reJitId);
+
+ NativeCodeVersionCollection nativeCodeVersions = ilCodeVersion.GetNativeCodeVersions(pMethodDesc);
+ for (NativeCodeVersionIterator iter = nativeCodeVersions.Begin(); iter != nativeCodeVersions.End(); iter++)
+ {
+ // Now that tiered compilation can create more than one jitted code version for the same rejit id
+ // we are arbitrarily choosing the first one to return. To address a specific version of native code
+ // use GetCodeInfo4.
+ pCodeStart = iter->GetNativeCode();
+ break;
+ }
}
+ hr = GetCodeInfoFromCodeStart(pCodeStart,
+ cCodeInfos,
+ pcCodeInfos,
+ codeInfos);
}
}
EX_CATCH_HRESULT(hr);
@@ -5042,7 +5050,7 @@ HRESULT ProfToEEInterfaceImpl::GetILToNativeMapping2(FunctionID functionId,
ULONG32 cMap,
ULONG32 * pcMap, // [out]
COR_DEBUG_IL_TO_NATIVE_MAP map[]) // [out]
- {
+{
CONTRACTL
{
// MethodDesc::FindOrCreateTypicalSharedInstantiation throws
@@ -5070,7 +5078,7 @@ HRESULT ProfToEEInterfaceImpl::GetILToNativeMapping2(FunctionID functionId,
LL_INFO1000,
"**PROF: GetILToNativeMapping2 0x%p 0x%p.\n",
functionId, reJitId));
-
+
if (functionId == NULL)
{
return E_INVALIDARG;
@@ -5082,36 +5090,51 @@ HRESULT ProfToEEInterfaceImpl::GetILToNativeMapping2(FunctionID functionId,
return E_INVALIDARG;
}
- if (reJitId != 0)
+ HRESULT hr = S_OK;
+
+ EX_TRY
{
- return E_NOTIMPL;
- }
+ // Cast to proper type
+ MethodDesc * pMD = FunctionIdToMethodDesc(functionId);
-#ifdef DEBUGGING_SUPPORTED
- // Cast to proper type
- MethodDesc * pMD = FunctionIdToMethodDesc(functionId);
+ if (pMD->HasClassOrMethodInstantiation() && pMD->IsTypicalMethodDefinition())
+ {
+ // In this case, we used to replace pMD with its canonical instantiation
+ // (FindOrCreateTypicalSharedInstantiation). However, a profiler should never be able
+ // to get to this point anyway, since any MethodDesc a profiler gets from us
+ // cannot be typical (i.e., cannot be a generic with types still left uninstantiated).
+ // We assert here just in case a test proves me wrong, but generally we will
+ // disallow this code path.
+ _ASSERTE(!"Profiler passed a typical method desc (a generic with types still left uninstantiated) to GetILToNativeMapping2");
+ hr = E_INVALIDARG;
+ }
+ else
+ {
+ PCODE pCodeStart = NULL;
+ CodeVersionManager *pCodeVersionManager = pMD->GetCodeVersionManager();
+ ILCodeVersion ilCodeVersion = NULL;
+ {
+ CodeVersionManager::TableLockHolder lockHolder(pCodeVersionManager);
- if (pMD->HasClassOrMethodInstantiation() && pMD->IsTypicalMethodDefinition())
- {
- // In this case, we used to replace pMD with its canonical instantiation
- // (FindOrCreateTypicalSharedInstantiation). However, a profiler should never be able
- // to get to this point anyway, since any MethodDesc a profiler gets from us
- // cannot be typical (i.e., cannot be a generic with types still left uninstantiated).
- // We assert here just in case a test proves me wrong, but generally we will
- // disallow this code path.
- _ASSERTE(!"Profiler passed a typical method desc (a generic with types still left uninstantiated) to GetILToNativeMapping2");
- return E_INVALIDARG;
- }
+ pCodeVersionManager->GetILCodeVersion(pMD, reJitId);
+
+ NativeCodeVersionCollection nativeCodeVersions = ilCodeVersion.GetNativeCodeVersions(pMD);
+ for (NativeCodeVersionIterator iter = nativeCodeVersions.Begin(); iter != nativeCodeVersions.End(); iter++)
+ {
+ // Now that tiered compilation can create more than one jitted code version for the same rejit id
+ // we are arbitrarily choosing the first one to return. To address a specific version of native code
+ // use GetILToNativeMapping3.
+ pCodeStart = iter->GetNativeCode();
+ break;
+ }
+ }
- if (g_pDebugInterface == NULL)
- {
- return CORPROF_E_DEBUGGING_DISABLED;
+ hr = GetILToNativeMapping3(pCodeStart, cMap, pcMap, map);
+ }
}
+ EX_CATCH_HRESULT(hr);
- return (g_pDebugInterface->GetILToNativeMapping(pMD, cMap, pcMap, map));
-#else
- return E_NOTIMPL;
-#endif
+ return hr;
}
@@ -6583,6 +6606,231 @@ HRESULT ProfToEEInterfaceImpl::GetDynamicFunctionInfo(FunctionID functionId,
}
/*
+ * GetNativeCodeStartAddresses
+ *
+ * Gets all of the native code addresses associated with a particular function. iered compilation
+ * potentially creates different native code versions for a method, and this function allows profilers
+ * to view all native versions of a method.
+ *
+ * Parameters:
+ * functionID - The function that is being requested.
+ * reJitId - The ReJIT id.
+ * cCodeStartAddresses - A parameter for indicating the size of buffer for the codeStartAddresses parameter.
+ * pcCodeStartAddresses - An optional parameter for returning the true size of the codeStartAddresses parameter.
+ * codeStartAddresses - The array to be filled up with native code addresses.
+ *
+ * Returns:
+ * S_OK if successful
+ *
+ */
+HRESULT ProfToEEInterfaceImpl::GetNativeCodeStartAddresses(FunctionID functionID,
+ ReJITID reJitId,
+ ULONG32 cCodeStartAddresses,
+ ULONG32 *pcCodeStartAddresses,
+ UINT_PTR codeStartAddresses[])
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ EE_THREAD_NOT_REQUIRED;
+ CAN_TAKE_LOCK;
+
+ SO_NOT_MAINLINE;
+
+ PRECONDITION(CheckPointer(pcCodeStartAddresses, NULL_OK));
+ PRECONDITION(CheckPointer(codeStartAddresses, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ if (functionID == NULL)
+ {
+ return E_INVALIDARG;
+ }
+
+ PROFILER_TO_CLR_ENTRYPOINT_ASYNC_EX(kP2EEAllowableAfterAttach,
+ (LF_CORPROF,
+ LL_INFO1000,
+ "**PROF: GetNativeCodeStartAddresses 0x%p 0x%p.\n",
+ functionID, reJitId));
+
+ HRESULT hr = S_OK;
+
+ EX_TRY
+ {
+ if (pcCodeStartAddresses != NULL)
+ {
+ *pcCodeStartAddresses = 0;
+ }
+
+ MethodDesc * methodDesc = FunctionIdToMethodDesc(functionID);
+ PTR_MethodDesc pMD = PTR_MethodDesc(methodDesc);
+ ULONG32 trueLen = 0;
+ StackSArray<UINT_PTR> addresses;
+
+ CodeVersionManager *pCodeVersionManager = pMD->GetCodeVersionManager();
+
+ ILCodeVersion ilCodeVersion = NULL;
+ {
+ CodeVersionManager::TableLockHolder lockHolder(pCodeVersionManager);
+
+ ilCodeVersion = pCodeVersionManager->GetILCodeVersion(pMD, reJitId);
+
+ NativeCodeVersionCollection nativeCodeVersions = ilCodeVersion.GetNativeCodeVersions(pMD);
+ for (NativeCodeVersionIterator iter = nativeCodeVersions.Begin(); iter != nativeCodeVersions.End(); iter++)
+ {
+ addresses.Append((*iter).GetNativeCode());
+
+ ++trueLen;
+ }
+ }
+
+ if (pcCodeStartAddresses != NULL)
+ {
+ *pcCodeStartAddresses = trueLen;
+ }
+
+ if (codeStartAddresses != NULL)
+ {
+ if (cCodeStartAddresses < trueLen)
+ {
+ hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+ }
+ else
+ {
+ for(ULONG32 i = 0; i < trueLen; ++i)
+ {
+ codeStartAddresses[i] = addresses[i];
+ }
+ }
+ }
+ }
+ EX_CATCH_HRESULT(hr);
+
+ return hr;
+}
+
+/*
+ * GetILToNativeMapping3
+ *
+ * This overload behaves the same as GetILToNativeMapping2, except it allows the profiler
+ * to address specific native code versions instead of defaulting to the first one.
+ *
+ * Parameters:
+ * pNativeCodeStartAddress - start address of the native code version, returned by GetNativeCodeStartAddresses
+ * cMap - size of the map array
+ * pcMap - how many items are returned in the map array
+ * map - an array to store the il to native mappings in
+ *
+ * Returns:
+ * S_OK if successful
+ *
+ */
+HRESULT ProfToEEInterfaceImpl::GetILToNativeMapping3(UINT_PTR pNativeCodeStartAddress,
+ ULONG32 cMap,
+ ULONG32 *pcMap,
+ COR_DEBUG_IL_TO_NATIVE_MAP map[])
+{
+ CONTRACTL
+ {
+ THROWS;
+ DISABLED(GC_NOTRIGGER);
+ MODE_ANY;
+ CAN_TAKE_LOCK;
+
+ SO_NOT_MAINLINE;
+
+ PRECONDITION(CheckPointer(pcMap, NULL_OK));
+ PRECONDITION(CheckPointer(map, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(kP2EEAllowableAfterAttach,
+ (LF_CORPROF,
+ LL_INFO1000,
+ "**PROF: GetILToNativeMapping3 0x%p.\n",
+ pNativeCodeStartAddress));
+
+ if (pNativeCodeStartAddress == NULL)
+ {
+ return E_INVALIDARG;
+ }
+
+ if ((cMap > 0) &&
+ ((pcMap == NULL) || (map == NULL)))
+ {
+ return E_INVALIDARG;
+ }
+
+#ifdef DEBUGGING_SUPPORTED
+ if (g_pDebugInterface == NULL)
+ {
+ return CORPROF_E_DEBUGGING_DISABLED;
+ }
+
+ return (g_pDebugInterface->GetILToNativeMapping(pNativeCodeStartAddress, cMap, pcMap, map));
+#else
+ return E_NOTIMPL;
+#endif
+}
+
+/*
+ * GetCodeInfo4
+ *
+ * Gets the location and size of a jitted function. Tiered compilation potentially creates different native code
+ * versions for a method, and this overload allows profilers to specify which native version it would like the
+ * code info for.
+ *
+ * Parameters:
+ * pNativeCodeStartAddress - start address of the native code version, returned by GetNativeCodeStartAddresses
+ * cCodeInfos - size of the codeInfos array
+ * pcCodeInfos - how many items are returned in the codeInfos array
+ * codeInfos - an array to store the code infos in
+ *
+ * Returns:
+ * S_OK if successful
+ *
+ */
+HRESULT ProfToEEInterfaceImpl::GetCodeInfo4(UINT_PTR pNativeCodeStartAddress,
+ ULONG32 cCodeInfos,
+ ULONG32* pcCodeInfos,
+ COR_PRF_CODE_INFO codeInfos[])
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_ANY;
+ EE_THREAD_NOT_REQUIRED;
+ CAN_TAKE_LOCK;
+
+ SO_NOT_MAINLINE;
+
+ PRECONDITION(CheckPointer(pcCodeInfos, NULL_OK));
+ PRECONDITION(CheckPointer(codeInfos, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(
+ kP2EEAllowableAfterAttach | kP2EETriggers,
+ (LF_CORPROF,
+ LL_INFO1000,
+ "**PROF: GetCodeInfo4 0x%p.\n",
+ pNativeCodeStartAddress));
+
+ if ((cCodeInfos != 0) && (codeInfos == NULL))
+ {
+ return E_INVALIDARG;
+ }
+
+ return GetCodeInfoFromCodeStart(pNativeCodeStartAddress,
+ cCodeInfos,
+ pcCodeInfos,
+ codeInfos);
+}
+
+/*
* GetStringLayout
*
* This function describes to a profiler the internal layout of a string.