diff options
Diffstat (limited to 'src/vm/eetoprofinterfaceimpl.cpp')
-rw-r--r-- | src/vm/eetoprofinterfaceimpl.cpp | 164 |
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, |