Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/tests/profiler/native/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ set(SOURCES
rejitprofiler/ilrewriter.cpp
rejitprofiler/sigparse.cpp
releaseondetach/releaseondetach.cpp
runtimeasyncapis/runtimeasyncapisprofiler.cpp
runtimeasynctypes/runtimeasynctypesprofiler.cpp
transitions/transitions.cpp
profiler.def
profiler.cpp
Expand Down
10 changes: 10 additions & 0 deletions src/tests/profiler/native/classfactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#include "nullprofiler/nullprofiler.h"
#include "rejitprofiler/rejitprofiler.h"
#include "releaseondetach/releaseondetach.h"
#include "runtimeasyncapis/runtimeasyncapisprofiler.h"
#include "runtimeasynctypes/runtimeasynctypesprofiler.h"
#include "transitions/transitions.h"
#include "multiple/multiple.h"
#include "inlining/inlining.h"
Expand Down Expand Up @@ -127,6 +129,14 @@ HRESULT STDMETHODCALLTYPE ClassFactory::CreateInstance(IUnknown *pUnkOuter, REFI
{
profiler = new ReleaseOnDetach();
}
else if (clsid == RuntimeAsyncApisProfiler::GetClsid())
{
profiler = new RuntimeAsyncApisProfiler();
}
else if (clsid == RuntimeAsyncTypesProfiler::GetClsid())
{
profiler = new RuntimeAsyncTypesProfiler();
}
else if (clsid == Transitions::GetClsid())
{
profiler = new Transitions();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#include "runtimeasyncapisprofiler.h"

RuntimeAsyncApisProfiler::RuntimeAsyncApisProfiler()
: Profiler(),
_failures(0),
_target(0),
_jitStarts(0),
_jitFinishes(0),
_ipRoundTrips(0),
_ilMappings(0),
_exceptionsThrown(0),
_targetSearches(0),
_targetUnwinds(0),
_catchers(0)
{
}

GUID RuntimeAsyncApisProfiler::GetClsid()
{
// {9A20F5D8-47B1-4E63-82CD-1F7690AB34E2}
GUID clsid = {0x9a20f5d8, 0x47b1, 0x4e63, {0x82, 0xcd, 0x1f, 0x76, 0x90, 0xab, 0x34, 0xe2}};
return clsid;
}

HRESULT RuntimeAsyncApisProfiler::Initialize(IUnknown* pCorProfilerInfoUnk)
{
HRESULT hr = Profiler::Initialize(pCorProfilerInfoUnk);
if (FAILED(hr))
{
return hr;
}

return pCorProfilerInfo->SetEventMask2(
COR_PRF_MONITOR_JIT_COMPILATION | COR_PRF_MONITOR_EXCEPTIONS, 0);
}

bool RuntimeAsyncApisProfiler::IsTarget(FunctionID functionId)
{
if (GetFunctionIDName(functionId) != WCHAR("Work"))
{
return false;
}

std::wstring moduleName = GetModuleIDName(GetModuleId(functionId)).ToWString();
return moduleName.find(L"runtimeasyncapis") != std::wstring::npos;
}

HRESULT RuntimeAsyncApisProfiler::JITCompilationStarted(FunctionID functionId, BOOL fIsSafeToBlock)
{
if (IsTarget(functionId))
Comment thread
tommcdon marked this conversation as resolved.
{
_jitStarts++;
}
return S_OK;
}

HRESULT RuntimeAsyncApisProfiler::JITCompilationFinished(
FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock)
{
if (!IsTarget(functionId))
{
return S_OK;
}

_target = functionId;
if (FAILED(hrStatus))
{
_failures++;
return S_OK;
}

_jitFinishes++;

COR_PRF_CODE_INFO codeInfos[16];
ULONG32 codeInfoCount = 0;
HRESULT hr = pCorProfilerInfo->GetCodeInfo2(
functionId, static_cast<ULONG32>(sizeof(codeInfos) / sizeof(codeInfos[0])),
&codeInfoCount, codeInfos);
if (FAILED(hr) || codeInfoCount == 0)
{
_failures++;
}
else
{
FunctionID roundTrip = 0;
hr = pCorProfilerInfo->GetFunctionFromIP(
reinterpret_cast<LPCBYTE>(codeInfos[0].startAddress), &roundTrip);
if (SUCCEEDED(hr) && roundTrip == functionId)
{
_ipRoundTrips++;
}
else
{
_failures++;
}
}

COR_DEBUG_IL_TO_NATIVE_MAP mappings[512];
ULONG32 mappingCount = 0;
hr = pCorProfilerInfo->GetILToNativeMapping(
functionId, static_cast<ULONG32>(sizeof(mappings) / sizeof(mappings[0])),
&mappingCount, mappings);
if (SUCCEEDED(hr) && mappingCount > 0)
{
_ilMappings++;
}
else
{
_failures++;
}

return S_OK;
}

HRESULT RuntimeAsyncApisProfiler::ExceptionThrown(ObjectID thrownObjectId)
{
_exceptionsThrown++;
return S_OK;
}

HRESULT RuntimeAsyncApisProfiler::ExceptionSearchFunctionEnter(FunctionID functionId)
{
if (functionId == _target.load())
{
_targetSearches++;
}
return S_OK;
}

HRESULT RuntimeAsyncApisProfiler::ExceptionUnwindFunctionEnter(FunctionID functionId)
{
if (functionId == _target.load())
{
_targetUnwinds++;
}
return S_OK;
}

HRESULT RuntimeAsyncApisProfiler::ExceptionCatcherEnter(FunctionID functionId, ObjectID objectId)
{
_catchers++;
return S_OK;
}

HRESULT RuntimeAsyncApisProfiler::Shutdown()
{
HRESULT hr = Profiler::Shutdown();

printf("RuntimeAsyncApisProfiler: failures=%d jit=%d/%d ip=%d il=%d "
"thrown=%d searches=%d unwinds=%d catchers=%d\n",
_failures.load(), _jitStarts.load(), _jitFinishes.load(),
_ipRoundTrips.load(), _ilMappings.load(), _exceptionsThrown.load(),
_targetSearches.load(), _targetUnwinds.load(), _catchers.load());

bool passed =
SUCCEEDED(hr) &&
_failures == 0 &&
_target != 0 &&
_jitStarts > 0 &&
_jitFinishes > 0 &&
_ipRoundTrips > 0 &&
_ilMappings > 0 &&
_exceptionsThrown > 0 &&
(_targetSearches > 0 || _targetUnwinds > 0) &&
_catchers > 0;

printf(passed ? "PROFILER TEST PASSES\n" : "PROFILER TEST FAILED\n");
fflush(stdout);
return hr;
}

ModuleID RuntimeAsyncApisProfiler::GetModuleId(FunctionID functionId)
{
ClassID classId = 0;
ModuleID moduleId = 0;
mdToken token = 0;
ULONG32 typeArgumentCount = 0;
ClassID typeArguments[SHORT_LENGTH];
COR_PRF_FRAME_INFO frameInfo = 0;

HRESULT hr = pCorProfilerInfo->GetFunctionInfo2(
functionId, frameInfo, &classId, &moduleId, &token,
SHORT_LENGTH, &typeArgumentCount, typeArguments);
return SUCCEEDED(hr) ? moduleId : 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#pragma once

#include "../profiler.h"

class RuntimeAsyncApisProfiler : public Profiler
{
public:
RuntimeAsyncApisProfiler();

static GUID GetClsid();
HRESULT STDMETHODCALLTYPE Initialize(IUnknown* pCorProfilerInfoUnk) override;
HRESULT STDMETHODCALLTYPE Shutdown() override;
HRESULT STDMETHODCALLTYPE JITCompilationStarted(
FunctionID functionId, BOOL fIsSafeToBlock) override;
HRESULT STDMETHODCALLTYPE JITCompilationFinished(
FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock) override;
HRESULT STDMETHODCALLTYPE ExceptionThrown(ObjectID thrownObjectId) override;
HRESULT STDMETHODCALLTYPE ExceptionSearchFunctionEnter(FunctionID functionId) override;
HRESULT STDMETHODCALLTYPE ExceptionUnwindFunctionEnter(FunctionID functionId) override;
HRESULT STDMETHODCALLTYPE ExceptionCatcherEnter(FunctionID functionId, ObjectID objectId) override;

private:
bool IsTarget(FunctionID functionId);
ModuleID GetModuleId(FunctionID functionId);

std::atomic<int> _failures;
std::atomic<FunctionID> _target;
std::atomic<int> _jitStarts;
std::atomic<int> _jitFinishes;
std::atomic<int> _ipRoundTrips;
std::atomic<int> _ilMappings;
std::atomic<int> _exceptionsThrown;
std::atomic<int> _targetSearches;
std::atomic<int> _targetUnwinds;
std::atomic<int> _catchers;
};
Loading