diff options
author | David Mason <davmason@microsoft.com> | 2017-10-23 20:19:04 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-10-23 20:19:04 -0700 |
commit | 5d66791a3a1932d2afcd3ef58dd0df91323662cb (patch) | |
tree | a602272273f0758b8bb8d59fd0f57350643fc264 /src/vm/proftoeeinterfaceimpl.cpp | |
parent | f8d6405c8e0680a1184dc07123aeb4abe62e9e87 (diff) | |
download | coreclr-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.cpp | 328 |
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. |