summaryrefslogtreecommitdiff
path: root/src/vm/eetoprofinterfaceimpl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm/eetoprofinterfaceimpl.cpp')
-rw-r--r--src/vm/eetoprofinterfaceimpl.cpp164
1 files changed, 145 insertions, 19 deletions
diff --git a/src/vm/eetoprofinterfaceimpl.cpp b/src/vm/eetoprofinterfaceimpl.cpp
index 2ec3812159..1ceed3d81b 100644
--- a/src/vm/eetoprofinterfaceimpl.cpp
+++ b/src/vm/eetoprofinterfaceimpl.cpp
@@ -414,6 +414,7 @@ EEToProfInterfaceImpl::EEToProfInterfaceImpl() :
m_pCallback5(NULL),
m_pCallback6(NULL),
m_pCallback7(NULL),
+ m_pCallback8(NULL),
m_hmodProfilerDLL(NULL),
m_fLoadedViaAttach(FALSE),
m_pProfToEE(NULL),
@@ -664,21 +665,25 @@ HRESULT EEToProfInterfaceImpl::CreateProfiler(
m_hmodProfilerDLL = hmodProfilerDLL.Extract();
hmodProfilerDLL = NULL;
- // The profiler may optionally support ICorProfilerCallback3,4,5,6,7. Let's check.
+ // The profiler may optionally support ICorProfilerCallback3,4,5,6,7,8. Let's check.
- ReleaseHolder<ICorProfilerCallback7> pCallback7;
+ ReleaseHolder<ICorProfilerCallback8> pCallback8;
hr = m_pCallback2->QueryInterface(
- IID_ICorProfilerCallback7,
- (LPVOID *)&pCallback7);
- if (SUCCEEDED(hr) && (pCallback7 != NULL))
+ IID_ICorProfilerCallback8,
+ (LPVOID *)&pCallback8);
+ if (SUCCEEDED(hr) && (pCallback8 != NULL))
{
// Nifty. Transfer ownership to this class
- _ASSERTE(m_pCallback7 == NULL);
- m_pCallback7 = pCallback7.Extract();
- pCallback7 = NULL;
+ _ASSERTE(m_pCallback8 == NULL);
+ m_pCallback8 = pCallback8.Extract();
+ pCallback8 = NULL;
- // And while we're at it, we must now also have an ICorProfilerCallback3,4,5,6
+ // And while we're at it, we must now also have an ICorProfilerCallback3,4,5,6,7
// due to inheritance relationship of the interfaces
+ _ASSERTE(m_pCallback7 == NULL);
+ m_pCallback7 = static_cast<ICorProfilerCallback7 *>(m_pCallback8);
+ m_pCallback7->AddRef();
+
_ASSERTE(m_pCallback6 == NULL);
m_pCallback6 = static_cast<ICorProfilerCallback6 *>(m_pCallback7);
m_pCallback6->AddRef();
@@ -696,6 +701,40 @@ HRESULT EEToProfInterfaceImpl::CreateProfiler(
m_pCallback3->AddRef();
}
+ if (m_pCallback7 == NULL)
+ {
+ ReleaseHolder<ICorProfilerCallback7> pCallback7;
+ hr = m_pCallback2->QueryInterface(
+ IID_ICorProfilerCallback7,
+ (LPVOID *)&pCallback7);
+ if (SUCCEEDED(hr) && (pCallback7 != NULL))
+ {
+ // Nifty. Transfer ownership to this class
+ _ASSERTE(m_pCallback7 == NULL);
+ m_pCallback7 = pCallback7.Extract();
+ pCallback7 = NULL;
+
+ // And while we're at it, we must now also have an ICorProfilerCallback3,4,5,6
+ // due to inheritance relationship of the interfaces
+
+ _ASSERTE(m_pCallback6 == NULL);
+ m_pCallback6 = static_cast<ICorProfilerCallback6 *>(m_pCallback7);
+ m_pCallback6->AddRef();
+
+ _ASSERTE(m_pCallback5 == NULL);
+ m_pCallback5 = static_cast<ICorProfilerCallback5 *>(m_pCallback6);
+ m_pCallback5->AddRef();
+
+ _ASSERTE(m_pCallback4 == NULL);
+ m_pCallback4 = static_cast<ICorProfilerCallback4 *>(m_pCallback5);
+ m_pCallback4->AddRef();
+
+ _ASSERTE(m_pCallback3 == NULL);
+ m_pCallback3 = static_cast<ICorProfilerCallback3 *>(m_pCallback4);
+ m_pCallback3->AddRef();
+ }
+ }
+
if (m_pCallback6 == NULL)
{
ReleaseHolder<ICorProfilerCallback6> pCallback6;
@@ -873,6 +912,13 @@ EEToProfInterfaceImpl::~EEToProfInterfaceImpl()
m_pCallback7 = NULL;
}
+ if (m_pCallback8 != NULL)
+ {
+ REMOVE_STACK_GUARD_FOR_PROFILER_CALL;
+ m_pCallback8->Release();
+ m_pCallback8 = NULL;
+ }
+
// Only unload the V4 profiler if this is not part of shutdown. This protects
// Whidbey profilers that aren't used to being FreeLibrary'd.
if (fIsV4Profiler && !g_fEEShutDown)
@@ -2294,7 +2340,7 @@ HRESULT EEToProfInterfaceImpl::SetEventMask(DWORD dwEventMask, DWORD dwEventMask
// in this function
if (g_profControlBlock.curProfStatus.Get() == kProfStatusInitializingForAttachLoad)
{
- if (GCHeap::GetGCHeap()->IsConcurrentGCEnabled())
+ if (GCHeapUtilities::GetGCHeap()->IsConcurrentGCEnabled())
{
// We only allow turning off concurrent GC in the profiler attach thread inside
// InitializeForAttach, otherwise we would be vulnerable to weird races such as
@@ -2316,7 +2362,7 @@ HRESULT EEToProfInterfaceImpl::SetEventMask(DWORD dwEventMask, DWORD dwEventMask
// Fail if concurrent GC is enabled
// This should only happen for attach profilers if user didn't turn on COR_PRF_MONITOR_GC
// at attach time
- if (GCHeap::GetGCHeap()->IsConcurrentGCEnabled())
+ if (GCHeapUtilities::GetGCHeap()->IsConcurrentGCEnabled())
{
return CORPROF_E_CONCURRENT_GC_NOT_PROFILABLE;
}
@@ -2384,7 +2430,7 @@ HRESULT EEToProfInterfaceImpl::SetEventMask(DWORD dwEventMask, DWORD dwEventMask
if (fNeedToTurnOffConcurrentGC)
{
// Turn off concurrent GC if it is on so that user can walk the heap safely in GC callbacks
- GCHeap * pGCHeap = GCHeap::GetGCHeap();
+ IGCHeap * pGCHeap = GCHeapUtilities::GetGCHeap();
LOG((LF_CORPROF, LL_INFO10, "**PROF: Turning off concurrent GC at attach.\n"));
@@ -3184,6 +3230,86 @@ HRESULT EEToProfInterfaceImpl::JITCompilationStarted(FunctionID functionId,
}
}
+HRESULT EEToProfInterfaceImpl::DynamicMethodJITCompilationFinished(FunctionID functionId,
+ HRESULT hrStatus,
+ BOOL fIsSafeToBlock)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ CAN_TAKE_LOCK;
+
+ // The JIT / MethodDesc code likely hold locks while this callback is made
+
+ SO_NOT_MAINLINE;
+ }
+ CONTRACTL_END;
+
+ CLR_TO_PROFILER_ENTRYPOINT((LF_CORPROF,
+ LL_INFO1000,
+ "**PROF: DynamicMethodJITCompilationFinished 0x%p.\n",
+ functionId));
+
+ _ASSERTE(functionId);
+
+ if (m_pCallback8 == NULL)
+ {
+ return S_OK;
+ }
+
+ {
+ // All callbacks are really NOTHROW, but that's enforced partially by the profiler,
+ // whose try/catch blocks aren't visible to the contract system
+ PERMANENT_CONTRACT_VIOLATION(ThrowsViolation, ReasonProfilerCallout);
+ return m_pCallback8->DynamicMethodJITCompilationFinished(functionId, hrStatus, fIsSafeToBlock);
+ }
+}
+
+HRESULT EEToProfInterfaceImpl::DynamicMethodJITCompilationStarted(FunctionID functionId,
+ BOOL fIsSafeToBlock,
+ LPCBYTE pILHeader,
+ ULONG cbILHeader)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_PREEMPTIVE;
+ CAN_TAKE_LOCK;
+
+ // The JIT / MethodDesc code likely hold locks while this callback is made
+
+ SO_NOT_MAINLINE;
+ }
+ CONTRACTL_END;
+
+ CLR_TO_PROFILER_ENTRYPOINT((LF_CORPROF,
+ LL_INFO1000,
+ "**PROF: DynamicMethodJITCompilationStarted 0x%p.\n",
+ functionId));
+
+ _ASSERTE(functionId);
+
+ // Currently DynamicMethodJITCompilationStarted is always called with fIsSafeToBlock==TRUE. If this ever changes,
+ // it's safe to remove this assert, but this should serve as a trigger to change our
+ // public documentation to state that this callback is no longer called in preemptive mode all the time.
+ _ASSERTE(fIsSafeToBlock);
+
+ if (m_pCallback8 == NULL)
+ {
+ return S_OK;
+ }
+
+ {
+ // All callbacks are really NOTHROW, but that's enforced partially by the profiler,
+ // whose try/catch blocks aren't visible to the contract system
+ PERMANENT_CONTRACT_VIOLATION(ThrowsViolation, ReasonProfilerCallout);
+ return m_pCallback8->DynamicMethodJITCompilationStarted(functionId, fIsSafeToBlock, pILHeader, cbILHeader);
+ }
+}
+
HRESULT EEToProfInterfaceImpl::JITCachedFunctionSearchStarted(
/* [in] */ FunctionID functionId,
/* [out] */ BOOL *pbUseCachedFunction)
@@ -5609,7 +5735,7 @@ HRESULT EEToProfInterfaceImpl::MovedReferences(GCReferencesData *pData)
LL_INFO10000,
"**PROF: MovedReferences.\n"));
- _ASSERTE(!GCHeap::GetGCHeap()->IsConcurrentGCEnabled());
+ _ASSERTE(!GCHeapUtilities::GetGCHeap()->IsConcurrentGCEnabled());
if (pData->curIdx == 0)
{
@@ -5805,7 +5931,7 @@ HRESULT EEToProfInterfaceImpl::ObjectReference(ObjectID objId,
LL_INFO100000,
"**PROF: ObjectReferences.\n"));
- _ASSERTE(!GCHeap::GetGCHeap()->IsConcurrentGCEnabled());
+ _ASSERTE(!GCHeapUtilities::GetGCHeap()->IsConcurrentGCEnabled());
{
// All callbacks are really NOTHROW, but that's enforced partially by the profiler,
@@ -5844,7 +5970,7 @@ HRESULT EEToProfInterfaceImpl::FinalizeableObjectQueued(BOOL isCritical, ObjectI
LL_INFO100,
"**PROF: Notifying profiler of finalizeable object.\n"));
- _ASSERTE(!GCHeap::GetGCHeap()->IsConcurrentGCEnabled());
+ _ASSERTE(!GCHeapUtilities::GetGCHeap()->IsConcurrentGCEnabled());
{
// All callbacks are really NOTHROW, but that's enforced partially by the profiler,
@@ -5883,7 +6009,7 @@ HRESULT EEToProfInterfaceImpl::RootReferences2(GCReferencesData *pData)
LL_INFO10000,
"**PROF: RootReferences2.\n"));
- _ASSERTE(!GCHeap::GetGCHeap()->IsConcurrentGCEnabled());
+ _ASSERTE(!GCHeapUtilities::GetGCHeap()->IsConcurrentGCEnabled());
HRESULT hr = S_OK;
@@ -5948,7 +6074,7 @@ HRESULT EEToProfInterfaceImpl::ConditionalWeakTableElementReferences(GCReference
LL_INFO10000,
"**PROF: ConditionalWeakTableElementReferences.\n"));
- _ASSERTE(!GCHeap::GetGCHeap()->IsConcurrentGCEnabled());
+ _ASSERTE(!GCHeapUtilities::GetGCHeap()->IsConcurrentGCEnabled());
HRESULT hr = S_OK;
@@ -6082,7 +6208,7 @@ HRESULT EEToProfInterfaceImpl::GarbageCollectionStarted(int cGenerations, BOOL g
LL_INFO10000,
"**PROF: GarbageCollectionStarted.\n"));
- _ASSERTE(!GCHeap::GetGCHeap()->IsConcurrentGCEnabled());
+ _ASSERTE(!GCHeapUtilities::GetGCHeap()->IsConcurrentGCEnabled());
{
// All callbacks are really NOTHROW, but that's enforced partially by the profiler,
@@ -6120,7 +6246,7 @@ HRESULT EEToProfInterfaceImpl::GarbageCollectionFinished()
LL_INFO10000,
"**PROF: GarbageCollectionFinished.\n"));
- _ASSERTE(!GCHeap::GetGCHeap()->IsConcurrentGCEnabled());
+ _ASSERTE(!GCHeapUtilities::GetGCHeap()->IsConcurrentGCEnabled());
{
// All callbacks are really NOTHROW, but that's enforced partially by the profiler,