diff options
author | David Mason <davmason@microsoft.com> | 2021-06-15 21:54:02 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-06-15 21:54:02 +0300 |
commit | ab71c1f4031d449ed3d60ccaaecb629bb73b648a (patch) | |
tree | 891426baadbc67a3718edc12632887ef5cc83d00 /src/coreclr/inc | |
parent | 63c8ab2e7acedca0547bc9d59ba8b7d34faf3ddb (diff) |
Add the concept of "notification profilers" to the runtime (#53122)
Diffstat (limited to 'src/coreclr/inc')
-rw-r--r-- | src/coreclr/inc/CrstTypes.def | 2 | ||||
-rw-r--r-- | src/coreclr/inc/clrconfigvalues.h | 4 | ||||
-rw-r--r-- | src/coreclr/inc/corprof.idl | 47 | ||||
-rw-r--r-- | src/coreclr/inc/profilepriv.h | 306 | ||||
-rw-r--r-- | src/coreclr/inc/profilepriv.inl | 1837 | ||||
-rw-r--r-- | src/coreclr/inc/sarray.inl | 2 |
6 files changed, 1994 insertions, 204 deletions
diff --git a/src/coreclr/inc/CrstTypes.def b/src/coreclr/inc/CrstTypes.def index 185a590d938..c48872a0b94 100644 --- a/src/coreclr/inc/CrstTypes.def +++ b/src/coreclr/inc/CrstTypes.def @@ -433,7 +433,7 @@ Crst SingleUseLock End Crst UnwindInfoTableLock - AcquiredAfter StubUnwindInfoHeapSegments SingleUseLock + AcquiredAfter StubUnwindInfoHeapSegments SingleUseLock AcquiredBefore StressLog End diff --git a/src/coreclr/inc/clrconfigvalues.h b/src/coreclr/inc/clrconfigvalues.h index 5dc7e5d34b2..3f21e41dfa3 100644 --- a/src/coreclr/inc/clrconfigvalues.h +++ b/src/coreclr/inc/clrconfigvalues.h @@ -504,6 +504,10 @@ RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_CORECLR_PROFILER_PATH_32, W("CORECLR_PROFI RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_CORECLR_PROFILER_PATH_64, W("CORECLR_PROFILER_PATH_64"), "CoreCLR only: Specifies the path to the DLL of profiler to load into currently running 64 process", CLRConfig::LookupOptions::DontPrependPrefix) RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_CORECLR_PROFILER_PATH_ARM32, W("CORECLR_PROFILER_PATH_ARM32"), "CoreCLR only: Specifies the path to the DLL of profiler to load into currently running ARM32 process", CLRConfig::LookupOptions::DontPrependPrefix) RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_CORECLR_PROFILER_PATH_ARM64, W("CORECLR_PROFILER_PATH_ARM64"), "CoreCLR only: Specifies the path to the DLL of profiler to load into currently running ARM64 process", CLRConfig::LookupOptions::DontPrependPrefix) +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_CORECLR_ENABLE_NOTIFICATION_PROFILERS, W("CORECLR_ENABLE_NOTIFICATION_PROFILERS"), 0, "Set to 0 to disable loading notification profilers.", CLRConfig::LookupOptions::DontPrependPrefix) +RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_CORECLR_NOTIFICATION_PROFILERS_64, W("CORECLR_NOTIFICATION_PROFILERS_64"), "A semi-colon separated list of notification profilers to load in the form \"path={guid}\"", CLRConfig::LookupOptions::DontPrependPrefix) +RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_CORECLR_NOTIFICATION_PROFILERS_32, W("CORECLR_NOTIFICATION_PROFILERS_32"), "A semi-colon separated list of notification profilers to load in the form \"path={guid}\"", CLRConfig::LookupOptions::DontPrependPrefix) +RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_CORECLR_NOTIFICATION_PROFILERS, W("CORECLR_NOTIFICATION_PROFILERS"), "A semi-colon separated list of notification profilers to load in the form \"path={guid}\"", CLRConfig::LookupOptions::DontPrependPrefix) RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_ProfAPI_ProfilerCompatibilitySetting, W("ProfAPI_ProfilerCompatibilitySetting"), "Specifies the profiler loading policy (the default is not to load a V2 profiler in V4)", CLRConfig::LookupOptions::TrimWhiteSpaceFromStringValue) RETAIL_CONFIG_DWORD_INFO(EXTERNAL_ProfAPI_DetachMinSleepMs, W("ProfAPI_DetachMinSleepMs"), 0, "The minimum time, in milliseconds, the CLR will wait before checking whether a profiler that is in the process of detaching is ready to be unloaded.") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_ProfAPI_DetachMaxSleepMs, W("ProfAPI_DetachMaxSleepMs"), 0, "The maximum time, in milliseconds, the CLR will wait before checking whether a profiler that is in the process of detaching is ready to be unloaded.") diff --git a/src/coreclr/inc/corprof.idl b/src/coreclr/inc/corprof.idl index 74fb8099281..8fc965a84f6 100644 --- a/src/coreclr/inc/corprof.idl +++ b/src/coreclr/inc/corprof.idl @@ -475,6 +475,7 @@ typedef enum // and ThreadNameChanged callbacks. COR_PRF_MONITOR_THREADS = 0x00000200, + // CORECLR DEPRECATION WARNING: Remoting no longer exists in coreclr // MONITOR_REMOTING controls the Remoting* // callbacks. COR_PRF_MONITOR_REMOTING = 0x00000400, @@ -492,10 +493,12 @@ typedef enum // callbacks. COR_PRF_MONITOR_CCW = 0x00002000, + // CORECLR DEPRECATION WARNING: Remoting no longer exists in coreclr // MONITOR_REMOTING_COOKIE controls whether // a cookie will be passed to the Remoting* callbacks COR_PRF_MONITOR_REMOTING_COOKIE = 0x00004000 | COR_PRF_MONITOR_REMOTING, + // CORECLR DEPRECATION WARNING: Remoting no longer exists in coreclr // MONITOR_REMOTING_ASYNC controls whether // the Remoting* callbacks will monitor async events COR_PRF_MONITOR_REMOTING_ASYNC = 0x00008000 | COR_PRF_MONITOR_REMOTING, @@ -594,6 +597,28 @@ typedef enum COR_PRF_MONITOR_JIT_COMPILATION | COR_PRF_ENABLE_REJIT, + COR_PRF_ALLOWABLE_NOTIFICATION_PROFILER + = COR_PRF_MONITOR_FUNCTION_UNLOADS | + COR_PRF_MONITOR_CLASS_LOADS | + COR_PRF_MONITOR_MODULE_LOADS | + COR_PRF_MONITOR_ASSEMBLY_LOADS | + COR_PRF_MONITOR_APPDOMAIN_LOADS | + COR_PRF_MONITOR_JIT_COMPILATION | + COR_PRF_MONITOR_EXCEPTIONS | + COR_PRF_MONITOR_OBJECT_ALLOCATED | + COR_PRF_MONITOR_THREADS | + COR_PRF_MONITOR_CODE_TRANSITIONS | + COR_PRF_MONITOR_CCW | + COR_PRF_MONITOR_SUSPENDS | + COR_PRF_MONITOR_CACHE_SEARCHES | + COR_PRF_DISABLE_INLINING | + COR_PRF_DISABLE_OPTIMIZATIONS | + COR_PRF_ENABLE_OBJECT_ALLOCATED | + COR_PRF_MONITOR_CLR_EXCEPTIONS | + COR_PRF_ENABLE_STACK_SNAPSHOT | + COR_PRF_USE_PROFILE_IMAGES | + COR_PRF_DISABLE_ALL_NGEN_IMAGES, + // MONITOR_IMMUTABLE represents all flags that may only be set during initialization. // Trying to change any of these flags elsewhere will result in a // failed HRESULT. @@ -621,6 +646,7 @@ typedef enum { COR_PRF_HIGH_MONITOR_NONE = 0x00000000, + // CORECLR DEPRECATION WARNING: This flag is no longer checked by the runtime COR_PRF_HIGH_ADD_ASSEMBLY_REFERENCES = 0x00000001, COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED = 0x00000002, @@ -648,6 +674,15 @@ typedef enum COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED | COR_PRF_HIGH_MONITOR_EVENT_PIPE, + COR_PRF_HIGH_ALLOWABLE_NOTIFICATION_PROFILER + = COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED | + COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS | + COR_PRF_HIGH_DISABLE_TIERED_COMPILATION | + COR_PRF_HIGH_BASIC_GC | + COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS | + COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED | + COR_PRF_HIGH_MONITOR_EVENT_PIPE, + // MONITOR_IMMUTABLE represents all flags that may only be set during initialization. // Trying to change any of these flags elsewhere will result in a // failed HRESULT. @@ -2433,6 +2468,7 @@ interface ICorProfilerCallback5 : ICorProfilerCallback4 ] interface ICorProfilerCallback6 : ICorProfilerCallback5 { + // CORECLR DEPRECATION WARNING: This callback does not occur on coreclr. // Controlled by the COR_PRF_HIGH_ADD_ASSEMBLY_REFERENCES event mask flag. // Notifies the profiler of a very early stage in the loading of an Assembly, where the CLR // performs an assembly reference closure walk. This is useful ONLY if the profiler will need @@ -2555,6 +2591,17 @@ interface ICorProfilerCallback10 : ICorProfilerCallback9 HRESULT EventPipeProviderCreated([in] EVENTPIPE_PROVIDER provider); } +[ + object, + uuid(42350846-AAED-47F7-B128-FD0C98881CDE), + pointer_default(unique), + local +] +interface ICorProfilerCallback11 : ICorProfilerCallback10 +{ + HRESULT LoadAsNotficationOnly(BOOL *pbNotificationOnly); +} + /* * COR_PRF_CODEGEN_FLAGS controls various flags and hooks for a specific * method. A combination of COR_PRF_CODEGEN_FLAGS is provided by the diff --git a/src/coreclr/inc/profilepriv.h b/src/coreclr/inc/profilepriv.h index bd5533f12c6..75d1c3dbcc2 100644 --- a/src/coreclr/inc/profilepriv.h +++ b/src/coreclr/inc/profilepriv.h @@ -16,8 +16,15 @@ // Forward declarations class EEToProfInterfaceImpl; +class ProfToEEInterfaceImpl; class Object; struct ScanContext; +enum EtwGCRootFlags: int32_t; +enum EtwGCRootKind: int32_t; +struct IAssemblyBindingClosure; +struct AssemblyReferenceClosureWalkContextForProfAPI; + +#include "eventpipeadaptertypes.h" #if defined (PROFILING_SUPPORTED_DATA) || defined(PROFILING_SUPPORTED) #ifndef PROFILING_SUPPORTED_DATA @@ -25,6 +32,9 @@ struct ScanContext; #endif // PROFILING_SUPPORTED_DATA #include "corprof.h" +#include "slist.h" + +#define MAX_NOTIFICATION_PROFILERS 32 //--------------------------------------------------------------------------------------- // Enumerates the various init states of profiling. @@ -55,33 +65,183 @@ public: void Set(ProfilerStatus profStatus); }; -// --------------------------------------------------------------------------------------- -// Global struct that lets the EE see the load status of the profiler, and provides a -// pointer (pProfInterface) through which profiler calls can be made -// -// When you are adding new session, please refer to -// code:ProfControlBlock::ResetPerSessionStatus#ProfileResetSessionStatus for more details. -struct ProfControlBlock +class EventMask { + friend class ProfControlBlock; +private: + const UINT64 EventMaskLowMask = 0x00000000FFFFFFFF; + const UINT64 EventMaskHighShiftAmount = 32; + const UINT64 EventMaskHighMask = 0xFFFFFFFF00000000; + + Volatile<UINT64> m_eventMask; + +public: + EventMask() : + m_eventMask(0) + { + + } + + EventMask& operator=(const EventMask& other); + + BOOL IsEventMaskSet(DWORD eventMask); + DWORD GetEventMask(); + void SetEventMask(DWORD eventMask); + BOOL IsEventMaskHighSet(DWORD eventMaskHigh); + DWORD GetEventMaskHigh(); + void SetEventMaskHigh(DWORD eventMaskHigh); +}; + +class ProfilerInfo +{ +public: // **** IMPORTANT!! **** // All uses of pProfInterface must be properly synchronized to avoid the profiler // from detaching while the EE attempts to call into it. The recommended way to do - // this is to use the (lockless) BEGIN_PIN_PROFILER / END_PIN_PROFILER macros. See - // code:BEGIN_PIN_PROFILER for instructions. For full details on how the + // this is to use the (lockless) BEGIN_PROFILER_CALLBACK / END_PROFILER_CALLBACK macros. See + // code:BEGIN_PROFILER_CALLBACK for instructions. For full details on how the // synchronization works, see // code:ProfilingAPIUtility::InitializeProfiling#LoadUnloadCallbackSynchronization VolatilePtr<EEToProfInterfaceImpl> pProfInterface; // **** IMPORTANT!! **** - DWORD dwEventMask; // Original low event mask bits - DWORD dwEventMaskHigh; // New high event mask bits CurrentProfilerStatus curProfStatus; + + EventMask eventMask; + + //--------------------------------------------------------------- + // m_dwProfilerEvacuationCounter keeps track of how many profiler + // callback calls remain on the stack + //--------------------------------------------------------------- + // Why volatile? + // See code:ProfilingAPIUtility::InitializeProfiling#LoadUnloadCallbackSynchronization. + Volatile<DWORD> dwProfilerEvacuationCounter; + + Volatile<BOOL> inUse; + + // Reset those variables that is only for the current attach session + void ResetPerSessionStatus(); + void Init(); +}; + +enum class ProfilerCallbackType +{ + Active, + ActiveOrInitializing +}; + +// We need a way to track which profilers are in active calls, to synchronize with detach. +// If we detached a profiler while it was actively in a callback there would be issues. +// However, we don't want to pin all profilers, because then a chatty profiler could +// cause another profiler to not be able to detach. We can't just check the event masks +// before and after the call because it is legal for a profiler to change its event mask, +// and then it would be possible for a profiler to permanently prevent itself from detaching. +// +// WHEN IS EvacuationCounterHolder REQUIRED? +// Answer: any time you access a ProfilerInfo *. There is a specific sequence that must be followed: +// - Do a dirty read of the Profiler interface +// - Increment an evacuation counter by using EvacuationCounterHolder as a RAII guard class +// - Now do a clean read of the ProfilerInfo's status - this will be changed during detach and +// is always read with a memory barrier +// +// The DoProfilerCallback/IterateProfilers functions automate this process for you, you should use +// them unless you are absoultely sure you know what you're doing +class EvacuationCounterHolder +{ +private: + ProfilerInfo *m_pProfilerInfo; + +public: + EvacuationCounterHolder(ProfilerInfo *pProfilerInfo) : + m_pProfilerInfo(pProfilerInfo) + { + _ASSERTE(m_pProfilerInfo != NULL); + InterlockedIncrement((LONG *)(m_pProfilerInfo->dwProfilerEvacuationCounter.GetPointer())); + } + + ~EvacuationCounterHolder() + { + InterlockedDecrement((LONG *)(m_pProfilerInfo->dwProfilerEvacuationCounter.GetPointer())); + } +}; + +struct StoredProfilerNode +{ + CLSID guid; + SString path; + SLink m_Link; +}; + +typedef SList<StoredProfilerNode, true> STOREDPROFILERLIST; +// --------------------------------------------------------------------------------------- +// Global struct that lets the EE see the load status of the profiler, and provides a +// pointer (pProfInterface) through which profiler calls can be made +// +// When you are adding new session, please refer to +// code:ProfControlBlock::ResetPerSessionStatus#ProfileResetSessionStatus for more details. +class ProfControlBlock +{ +private: + // IsProfilerPresent(pProfilerInfo) returns whether or not a CLR Profiler is actively loaded + // (meaning it's initialized and ready to receive callbacks). + FORCEINLINE BOOL IsProfilerPresent(ProfilerInfo *pProfilerInfo) + { + LIMITED_METHOD_DAC_CONTRACT; + + return pProfilerInfo->curProfStatus.Get() >= kProfStatusActive; + } + + FORCEINLINE BOOL IsProfilerPresentOrInitializing(ProfilerInfo *pProfilerInfo) + { + return pProfilerInfo->curProfStatus.Get() > kProfStatusDetaching; + } + + template<typename Func, typename... Args> + FORCEINLINE VOID DoOneProfilerIteration(ProfilerInfo *pProfilerInfo, ProfilerCallbackType callbackType, Func callback, Args... args) + { + // This is the dirty read + if (pProfilerInfo->pProfInterface.Load() != NULL) + { +#ifdef FEATURE_PROFAPI_ATTACH_DETACH + // Now indicate we are accessing the profiler + EvacuationCounterHolder evacuationCounter(pProfilerInfo); +#endif // FEATURE_PROFAPI_ATTACH_DETACH + + if ((callbackType == ProfilerCallbackType::Active && IsProfilerPresent(pProfilerInfo)) + || (callbackType == ProfilerCallbackType::ActiveOrInitializing && IsProfilerPresentOrInitializing(pProfilerInfo))) + { + callback(pProfilerInfo, args...); + } + } + } + + template<typename Func, typename... Args> + FORCEINLINE VOID IterateProfilers(ProfilerCallbackType callbackType, Func callback, Args... args) + { + DoOneProfilerIteration(&mainProfilerInfo, callbackType, callback, args...); + + if (notificationProfilerCount > 0) + { + for (SIZE_T i = 0; i < MAX_NOTIFICATION_PROFILERS; ++i) + { + ProfilerInfo *current = &(notificationOnlyProfilers[i]); + DoOneProfilerIteration(current, callbackType, callback, args...); + } + } + } + +public: BOOL fGCInProgress; BOOL fBaseSystemClassesLoaded; - BOOL fIsStoredProfilerRegistered; - CLSID clsStoredProfilerGuid; - SString sStoredProfilerPath; + STOREDPROFILERLIST storedProfilers; + + ProfilerInfo mainProfilerInfo; + + ProfilerInfo notificationOnlyProfilers[MAX_NOTIFICATION_PROFILERS]; + Volatile<LONG> notificationProfilerCount; + + EventMask globalEventMask; #ifdef PROF_TEST_ONLY_FORCE_ELT_DATA // #TestOnlyELT This implements a test-only (and debug-only) hook that allows a test @@ -118,14 +278,128 @@ struct ProfControlBlock #endif // _DEBUG // Whether we've turned off concurrent GC during attach - BOOL fConcurrentGCDisabledForAttach; + Volatile<BOOL> fConcurrentGCDisabledForAttach; Volatile<BOOL> fProfControlBlockInitialized; Volatile<BOOL> fProfilerRequestedRuntimeSuspend; void Init(); - void ResetPerSessionStatus(); + BOOL IsMainProfiler(EEToProfInterfaceImpl *pEEToProf); + BOOL IsMainProfiler(ProfToEEInterfaceImpl *pProfToEE); + ProfilerInfo *GetProfilerInfo(ProfToEEInterfaceImpl *pProfToEE); + + template<typename ConditionFunc, typename CallbackFunc, typename Data = void, typename... Args> + FORCEINLINE HRESULT DoProfilerCallback(ProfilerCallbackType callbackType, ConditionFunc condition, Data *additionalData, CallbackFunc callback, Args... args) + { + HRESULT hr = S_OK; + IterateProfilers(callbackType, + [](ProfilerInfo *pProfilerInfo, ConditionFunc condition, Data *additionalData, CallbackFunc callback, HRESULT *pHR, Args... args) + { + if (condition(pProfilerInfo)) + { + HRESULT innerHR = callback(additionalData, pProfilerInfo->pProfInterface, args...); + if (FAILED(innerHR)) + { + *pHR = innerHR; + } + } + }, + condition, additionalData, callback, &hr, args...); + return hr; + } + +#ifndef DACCESS_COMPILE + ProfilerInfo *FindNextFreeProfilerInfoSlot(); + void DeRegisterProfilerInfo(ProfilerInfo *pProfilerInfo); + void UpdateGlobalEventMask(); +#endif // DACCESS_COMPILE + + BOOL IsCallback3Supported(); + BOOL IsCallback5Supported(); + BOOL IsDisableTransparencySet(); + BOOL RequiresGenericsContextForEnterLeave(); + UINT_PTR EEFunctionIDMapper(FunctionID funcId, BOOL * pbHookFunction); + + void ThreadCreated(ThreadID threadID); + void ThreadDestroyed(ThreadID threadID); + void ThreadAssignedToOSThread(ThreadID managedThreadId, DWORD osThreadId); + void ThreadNameChanged(ThreadID managedThreadId, ULONG cchName, WCHAR name[]); + void Shutdown(); + void FunctionUnloadStarted(FunctionID functionId); + void JITCompilationFinished(FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock); + void JITCompilationStarted(FunctionID functionId, BOOL fIsSafeToBlock); + void DynamicMethodJITCompilationStarted(FunctionID functionId, BOOL fIsSafeToBlock, LPCBYTE pILHeader, ULONG cbILHeader); + void DynamicMethodJITCompilationFinished(FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock); + void DynamicMethodUnloaded(FunctionID functionId); + void JITCachedFunctionSearchStarted(FunctionID functionId, BOOL *pbUseCachedFunction); + void JITCachedFunctionSearchFinished(FunctionID functionId, COR_PRF_JIT_CACHE result); + HRESULT JITInlining(FunctionID callerId, FunctionID calleeId, BOOL *pfShouldInline); + void ReJITCompilationStarted(FunctionID functionId, ReJITID reJitId, BOOL fIsSafeToBlock); + HRESULT GetReJITParameters(ModuleID moduleId, mdMethodDef methodId, ICorProfilerFunctionControl *pFunctionControl); + void ReJITCompilationFinished(FunctionID functionId, ReJITID reJitId, HRESULT hrStatus, BOOL fIsSafeToBlock); + void ReJITError(ModuleID moduleId, mdMethodDef methodId, FunctionID functionId, HRESULT hrStatus); + void ModuleLoadStarted(ModuleID moduleId); + void ModuleLoadFinished(ModuleID moduleId, HRESULT hrStatus); + void ModuleUnloadStarted(ModuleID moduleId); + void ModuleUnloadFinished(ModuleID moduleId, HRESULT hrStatus); + void ModuleAttachedToAssembly(ModuleID moduleId, AssemblyID AssemblyId); + void ModuleInMemorySymbolsUpdated(ModuleID moduleId); + void ClassLoadStarted(ClassID classId); + void ClassLoadFinished(ClassID classId, HRESULT hrStatus); + void ClassUnloadStarted(ClassID classId); + void ClassUnloadFinished(ClassID classId, HRESULT hrStatus); + void AppDomainCreationStarted(AppDomainID appDomainId); + void AppDomainCreationFinished(AppDomainID appDomainId, HRESULT hrStatus); + void AppDomainShutdownStarted(AppDomainID appDomainId); + void AppDomainShutdownFinished(AppDomainID appDomainId, HRESULT hrStatus); + void AssemblyLoadStarted(AssemblyID assemblyId); + void AssemblyLoadFinished(AssemblyID assemblyId, HRESULT hrStatus); + void AssemblyUnloadStarted(AssemblyID assemblyId); + void AssemblyUnloadFinished(AssemblyID assemblyId, HRESULT hrStatus); + void UnmanagedToManagedTransition(FunctionID functionId, COR_PRF_TRANSITION_REASON reason); + void ManagedToUnmanagedTransition(FunctionID functionId, COR_PRF_TRANSITION_REASON reason); + void ExceptionThrown(ObjectID thrownObjectId); + void ExceptionSearchFunctionEnter(FunctionID functionId); + void ExceptionSearchFunctionLeave(); + void ExceptionSearchFilterEnter(FunctionID funcId); + void ExceptionSearchFilterLeave(); + void ExceptionSearchCatcherFound(FunctionID functionId); + void ExceptionOSHandlerEnter(FunctionID funcId); + void ExceptionOSHandlerLeave(FunctionID funcId); + void ExceptionUnwindFunctionEnter(FunctionID functionId); + void ExceptionUnwindFunctionLeave(); + void ExceptionUnwindFinallyEnter(FunctionID functionId); + void ExceptionUnwindFinallyLeave(); + void ExceptionCatcherEnter(FunctionID functionId, ObjectID objectId); + void ExceptionCatcherLeave(); + void COMClassicVTableCreated(ClassID wrappedClassId, REFGUID implementedIID, void *pVTable, ULONG cSlots); + void RuntimeSuspendStarted(COR_PRF_SUSPEND_REASON suspendReason); + void RuntimeSuspendFinished(); + void RuntimeSuspendAborted(); + void RuntimeResumeStarted(); + void RuntimeResumeFinished(); + void RuntimeThreadSuspended(ThreadID suspendedThreadId); + void RuntimeThreadResumed(ThreadID resumedThreadId); + void ObjectAllocated(ObjectID objectId, ClassID classId); + void FinalizeableObjectQueued(BOOL isCritical, ObjectID objectID); + void MovedReference(BYTE *pbMemBlockStart, BYTE *pbMemBlockEnd, ptrdiff_t cbRelocDistance, void *pHeapId, BOOL fCompacting); + void EndMovedReferences(void *pHeapId); + void RootReference2(BYTE *objectId, EtwGCRootKind dwEtwRootKind, EtwGCRootFlags dwEtwRootFlags, void *rootID, void *pHeapId); + void EndRootReferences2(void *pHeapId); + void ConditionalWeakTableElementReference(BYTE *primaryObjectId, BYTE *secondaryObjectId, void *rootID, void *pHeapId); + void EndConditionalWeakTableElementReferences(void *pHeapId); + void AllocByClass(ObjectID objId, ClassID classId, void *pHeapId); + void EndAllocByClass(void *pHeapId); + HRESULT ObjectReference(ObjectID objId, ClassID classId, ULONG cNumRefs, ObjectID *arrObjRef); + void HandleCreated(UINT_PTR handleId, ObjectID initialObjectId); + void HandleDestroyed(UINT_PTR handleId); + void GarbageCollectionStarted(int cGenerations, BOOL generationCollected[], COR_PRF_GC_REASON reason); + void GarbageCollectionFinished(); + void GetAssemblyReferences(LPCWSTR wszAssemblyPath, IAssemblyBindingClosure *pClosure, AssemblyReferenceClosureWalkContextForProfAPI *pContext); + void EventPipeEventDelivered(EventPipeProvider *provider, DWORD eventId, DWORD eventVersion, ULONG cbMetadataBlob, LPCBYTE metadataBlob, ULONG cbEventData, + LPCBYTE eventData, LPCGUID pActivityId, LPCGUID pRelatedActivityId, Thread *pEventThread, ULONG numStackFrames, UINT_PTR stackFrames[]); + void EventPipeProviderCreated(EventPipeProvider *provider); }; diff --git a/src/coreclr/inc/profilepriv.inl b/src/coreclr/inc/profilepriv.inl index 41e0bf3da96..08ba58f5623 100644 --- a/src/coreclr/inc/profilepriv.inl +++ b/src/coreclr/inc/profilepriv.inl @@ -17,7 +17,6 @@ #include "eetoprofinterfaceimpl.h" #ifdef PROFILING_SUPPORTED #include "profilinghelper.h" -BOOL CORProfilerBypassSecurityChecks(); #endif // PROFILING_SUPPORTED //--------------------------------------------------------------------------------------- @@ -36,6 +35,76 @@ inline ProfilerStatus CurrentProfilerStatus::Get() return m_profStatus; } +inline EventMask& EventMask::operator=(const EventMask& other) +{ + m_eventMask = other.m_eventMask; + return *this; +} + +inline BOOL EventMask::IsEventMaskSet(DWORD eventMask) +{ + return (GetEventMask() & eventMask) != 0; +} + +inline DWORD EventMask::GetEventMask() +{ + return (DWORD)(m_eventMask & EventMaskLowMask); +} + +inline void EventMask::SetEventMask(DWORD eventMask) +{ + m_eventMask = (m_eventMask & EventMaskHighMask) | (UINT64)eventMask; +} + +inline BOOL EventMask::IsEventMaskHighSet(DWORD eventMaskHigh) +{ + return (GetEventMaskHigh() & eventMaskHigh) != 0; +} + +inline DWORD EventMask::GetEventMaskHigh() +{ + return (DWORD)((m_eventMask & EventMaskHighMask) >> EventMaskHighShiftAmount); +} + +inline void EventMask::SetEventMaskHigh(DWORD eventMaskHigh) +{ + m_eventMask = (m_eventMask & EventMaskLowMask) | ((UINT64)eventMaskHigh << EventMaskHighShiftAmount); +} + +// Reset those variables that is only for the current attach session +inline void ProfilerInfo::ResetPerSessionStatus() +{ + LIMITED_METHOD_CONTRACT; + + pProfInterface = NULL; + eventMask.SetEventMask(COR_PRF_MONITOR_NONE); + eventMask.SetEventMaskHigh(COR_PRF_HIGH_MONITOR_NONE); +} + +inline void ProfilerInfo::Init() +{ + curProfStatus.Init(); + dwProfilerEvacuationCounter = 0; + ResetPerSessionStatus(); + inUse = FALSE; +} + +template<typename ConditionFunc> +inline BOOL AnyProfilerPassesCondition(ConditionFunc condition) +{ + BOOL anyPassed = FALSE; + (&g_profControlBlock)->DoProfilerCallback(ProfilerCallbackType::ActiveOrInitializing, + condition, + &anyPassed, + [](BOOL *pAnyPassed, VolatilePtr<EEToProfInterfaceImpl> profInterface) + { + *pAnyPassed = TRUE; + return S_OK; + }); + + return anyPassed; +} + //--------------------------------------------------------------------------------------- // ProfControlBlock //--------------------------------------------------------------------------------------- @@ -50,7 +119,15 @@ inline void ProfControlBlock::Init() } CONTRACTL_END; - curProfStatus.Init(); + mainProfilerInfo.Init(); + + for (SIZE_T i = 0; i < MAX_NOTIFICATION_PROFILERS; ++i) + { + notificationOnlyProfilers[i].Init(); + } + + globalEventMask.SetEventMask(COR_PRF_MONITOR_NONE); + globalEventMask.SetEventMaskHigh(COR_PRF_HIGH_MONITOR_NONE); fGCInProgress = FALSE; fBaseSystemClassesLoaded = FALSE; @@ -68,21 +145,1518 @@ inline void ProfControlBlock::Init() fConcurrentGCDisabledForAttach = FALSE; - ResetPerSessionStatus(); + mainProfilerInfo.ResetPerSessionStatus(); fProfControlBlockInitialized = TRUE; fProfilerRequestedRuntimeSuspend = FALSE; } -// Reset those variables that is only for the current attach session -inline void ProfControlBlock::ResetPerSessionStatus() + +inline BOOL ProfControlBlock::IsMainProfiler(EEToProfInterfaceImpl *pEEToProf) +{ + EEToProfInterfaceImpl *pProfInterface = mainProfilerInfo.pProfInterface.Load(); + return pProfInterface == pEEToProf; +} + +inline BOOL ProfControlBlock::IsMainProfiler(ProfToEEInterfaceImpl *pProfToEE) +{ + EEToProfInterfaceImpl *pProfInterface = mainProfilerInfo.pProfInterface.Load(); + return pProfInterface != NULL && pProfInterface->m_pProfToEE == pProfToEE; +} + +inline ProfilerInfo *ProfControlBlock::GetProfilerInfo(ProfToEEInterfaceImpl *pProfToEE) +{ + ProfilerInfo *pProfilerInfo = NULL; + IterateProfilers(ProfilerCallbackType::Active, + [](ProfilerInfo *pProfilerInfo, ProfToEEInterfaceImpl *pProfToEE, ProfilerInfo **ppFoundProfilerInfo) + { + if (pProfilerInfo->pProfInterface->m_pProfToEE == pProfToEE) + { + *ppFoundProfilerInfo = pProfilerInfo; + } + }, + pProfToEE, + &pProfilerInfo); + + return pProfilerInfo; +} + +#ifndef DACCESS_COMPILE +inline ProfilerInfo *ProfControlBlock::FindNextFreeProfilerInfoSlot() +{ + for (SIZE_T i = 0; i < MAX_NOTIFICATION_PROFILERS; ++i) + { + if (InterlockedCompareExchange((LONG *)notificationOnlyProfilers[i].inUse.GetPointer(), TRUE, FALSE) == FALSE) + { + InterlockedIncrement(notificationProfilerCount.GetPointer()); + return &(notificationOnlyProfilers[i]); + } + } + + return NULL; +} + +inline void ProfControlBlock::DeRegisterProfilerInfo(ProfilerInfo *pProfilerInfo) +{ + pProfilerInfo->inUse = FALSE; + InterlockedDecrement(notificationProfilerCount.GetPointer()); +} + +inline void ProfControlBlock::UpdateGlobalEventMask() +{ + while (true) + { + UINT64 originalEventMask = globalEventMask.m_eventMask; + UINT64 qwEventMask = 0; + + IterateProfilers(ProfilerCallbackType::ActiveOrInitializing, + [](ProfilerInfo *pProfilerInfo, UINT64 *pEventMask) + { + *pEventMask |= pProfilerInfo->eventMask.m_eventMask; + }, + &qwEventMask); + + // We are relying on the memory barrier introduced by InterlockedCompareExchange64 to observer any + // change to the global event mask. + if ((UINT64)InterlockedCompareExchange64((LONG64 *)&(globalEventMask.m_eventMask), (LONG64)qwEventMask, (LONG64)originalEventMask) == originalEventMask) + { + break; + } + } +} +#endif // DACCESS_COMPILE + +inline BOOL ProfControlBlock::IsCallback3Supported() +{ + return AnyProfilerPassesCondition([](ProfilerInfo *pProfilerInfo) { return pProfilerInfo->pProfInterface->IsCallback3Supported(); }); +} + +inline BOOL ProfControlBlock::IsCallback5Supported() +{ + return AnyProfilerPassesCondition([](ProfilerInfo *pProfilerInfo) { return pProfilerInfo->pProfInterface->IsCallback5Supported(); }); +} + +inline BOOL ProfControlBlock::IsDisableTransparencySet() +{ + return AnyProfilerPassesCondition([](ProfilerInfo *pProfilerInfo) { return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_DISABLE_TRANSPARENCY_CHECKS_UNDER_FULL_TRUST); }); +} + +inline BOOL ProfControlBlock::RequiresGenericsContextForEnterLeave() +{ + return AnyProfilerPassesCondition([](ProfilerInfo *pProfilerInfo) { return pProfilerInfo->pProfInterface->RequiresGenericsContextForEnterLeave(); }); +} + +inline bool DoesProfilerWantEEFunctionIDMapper(ProfilerInfo *pProfilerInfo) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return ((pProfilerInfo->pProfInterface->GetFunctionIDMapper() != NULL) || + (pProfilerInfo->pProfInterface->GetFunctionIDMapper2() != NULL)); +} + +inline UINT_PTR ProfControlBlock::EEFunctionIDMapper(FunctionID funcId, BOOL *pbHookFunction) { LIMITED_METHOD_CONTRACT; + UINT_PTR ptr = NULL; + DoOneProfilerIteration(&mainProfilerInfo, + ProfilerCallbackType::Active, + [](ProfilerInfo *pProfilerInfo, FunctionID funcId, BOOL *pbHookFunction, UINT_PTR *pPtr) + { + if (DoesProfilerWantEEFunctionIDMapper(pProfilerInfo)) + { + *pPtr = pProfilerInfo->pProfInterface->EEFunctionIDMapper(funcId, pbHookFunction); + } + }, + funcId, pbHookFunction, &ptr); + + return ptr; +} - pProfInterface = NULL; - dwEventMask = COR_PRF_MONITOR_NONE; - dwEventMaskHigh = COR_PRF_HIGH_MONITOR_NONE; +inline BOOL IsProfilerTrackingThreads(ProfilerInfo *pProfilerInfo) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_THREADS); +} + +inline void ProfControlBlock::ThreadCreated(ThreadID threadID) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingThreads, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ThreadID threadID) + { + return profInterface->ThreadCreated(threadID); + }, + threadID); +} + +inline void ProfControlBlock::ThreadDestroyed(ThreadID threadID) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingThreads, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ThreadID threadID) + { + return profInterface->ThreadDestroyed(threadID); + }, + threadID); +} + +inline void ProfControlBlock::ThreadAssignedToOSThread(ThreadID managedThreadId, DWORD osThreadId) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingThreads, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ThreadID managedThreadId, DWORD osThreadId) + { + return profInterface->ThreadAssignedToOSThread(managedThreadId, osThreadId); + }, + managedThreadId, osThreadId); +} + +inline void ProfControlBlock::ThreadNameChanged(ThreadID managedThreadId, ULONG cchName, WCHAR name[]) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingThreads, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ThreadID managedThreadId, ULONG cchName, WCHAR name[]) + { + return profInterface->ThreadNameChanged(managedThreadId, cchName, name); + }, + managedThreadId, cchName, name); +} + +inline void ProfControlBlock::Shutdown() +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + [](ProfilerInfo *pProfilerInfo) { return true; }, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface) + { + return profInterface->Shutdown(); + }); +} + +inline BOOL IsProfilerTrackingJITInfo(ProfilerInfo *pProfilerInfo) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_JIT_COMPILATION); +} + +inline void ProfControlBlock::JITCompilationFinished(FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingJITInfo, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock) + { + return profInterface->JITCompilationFinished(functionId, hrStatus, fIsSafeToBlock); + }, + functionId, hrStatus, fIsSafeToBlock); +} + +inline void ProfControlBlock::JITCompilationStarted(FunctionID functionId, BOOL fIsSafeToBlock) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingJITInfo, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID functionId, BOOL fIsSafeToBlock) + { + return profInterface->JITCompilationStarted(functionId, fIsSafeToBlock); + }, + functionId, fIsSafeToBlock); +} + +inline void ProfControlBlock::DynamicMethodJITCompilationStarted(FunctionID functionId, BOOL fIsSafeToBlock, LPCBYTE pILHeader, ULONG cbILHeader) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingJITInfo, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID functionId, BOOL fIsSafeToBlock, LPCBYTE pILHeader, ULONG cbILHeader) + { + return profInterface->DynamicMethodJITCompilationStarted(functionId, fIsSafeToBlock, pILHeader, cbILHeader); + }, + functionId, fIsSafeToBlock, pILHeader, cbILHeader); +} + +inline void ProfControlBlock::DynamicMethodJITCompilationFinished(FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingJITInfo, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock) + { + return profInterface->DynamicMethodJITCompilationFinished(functionId, hrStatus, fIsSafeToBlock); + }, + functionId, hrStatus, fIsSafeToBlock); +} + +inline BOOL IsProfilerMonitoringDynamicFunctionUnloads(ProfilerInfo *pProfilerInfo) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return pProfilerInfo->eventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS); +} + +inline void ProfControlBlock::DynamicMethodUnloaded(FunctionID functionId) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerMonitoringDynamicFunctionUnloads, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID functionId) + { + return profInterface->DynamicMethodUnloaded(functionId); + }, + functionId); +} + +inline BOOL IsProfilerTrackingCacheSearches(ProfilerInfo *pProfilerInfo) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_CACHE_SEARCHES); +} + +inline void ProfControlBlock::JITCachedFunctionSearchStarted(FunctionID functionId, BOOL *pbUseCachedFunction) +{ + LIMITED_METHOD_CONTRACT; + + BOOL allTrue = TRUE; + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingCacheSearches, + &allTrue, + [](BOOL *pAllTrue, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID functionId, BOOL *pbUseCachedFunction) + { + HRESULT hr = profInterface->JITCachedFunctionSearchStarted(functionId, pbUseCachedFunction); + *pAllTrue &= *pbUseCachedFunction; + return hr; + }, + functionId, pbUseCachedFunction); + + // If any reject it, consider it rejected. + *pbUseCachedFunction = allTrue; +} + +inline void ProfControlBlock::JITCachedFunctionSearchFinished(FunctionID functionId, COR_PRF_JIT_CACHE result) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingCacheSearches, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID functionId, COR_PRF_JIT_CACHE result) + { + return profInterface->JITCachedFunctionSearchFinished(functionId, result); + }, + functionId, result); +} + +inline HRESULT ProfControlBlock::JITInlining(FunctionID callerId, FunctionID calleeId, BOOL *pfShouldInline) +{ + LIMITED_METHOD_CONTRACT; + + BOOL allTrue = TRUE; + HRESULT hr = DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingJITInfo, + &allTrue, + [](BOOL *pAllTrue, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID callerId, FunctionID calleeId, BOOL *pfShouldInline) + { + HRESULT hr = profInterface->JITInlining(callerId, calleeId, pfShouldInline); + *pAllTrue &= *pfShouldInline; + return hr; + }, + callerId, calleeId, pfShouldInline); + + // If any reject it, consider it rejected. + *pfShouldInline = allTrue; + return hr; +} + +inline BOOL IsRejitEnabled(ProfilerInfo *pProfilerInfo) +{ + return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_ENABLE_REJIT); +} + +inline void ProfControlBlock::ReJITCompilationStarted(FunctionID functionId, ReJITID reJitId, BOOL fIsSafeToBlock) +{ + LIMITED_METHOD_CONTRACT; + DoOneProfilerIteration(&mainProfilerInfo, + ProfilerCallbackType::Active, + [](ProfilerInfo *pProfilerInfo, FunctionID functionId, ReJITID reJitId, BOOL fIsSafeToBlock) + { + if (IsRejitEnabled(pProfilerInfo)) + { + pProfilerInfo->pProfInterface->ReJITCompilationStarted(functionId, reJitId, fIsSafeToBlock); + } + }, + functionId, reJitId, fIsSafeToBlock); +} + +inline HRESULT ProfControlBlock::GetReJITParameters(ModuleID moduleId, mdMethodDef methodId, ICorProfilerFunctionControl *pFunctionControl) +{ + LIMITED_METHOD_CONTRACT; + HRESULT hr = S_OK; + DoOneProfilerIteration(&mainProfilerInfo, + ProfilerCallbackType::Active, + [](ProfilerInfo *pProfilerInfo, ModuleID moduleId, mdMethodDef methodId, ICorProfilerFunctionControl *pFunctionControl, HRESULT *pHr) + { + if (IsRejitEnabled(pProfilerInfo)) + { + *pHr = pProfilerInfo->pProfInterface->GetReJITParameters(moduleId, methodId, pFunctionControl); + } + }, + moduleId, methodId, pFunctionControl, &hr); + return hr; +} + +inline void ProfControlBlock::ReJITCompilationFinished(FunctionID functionId, ReJITID reJitId, HRESULT hrStatus, BOOL fIsSafeToBlock) +{ + LIMITED_METHOD_CONTRACT; + DoOneProfilerIteration(&mainProfilerInfo, + ProfilerCallbackType::Active, + [](ProfilerInfo *pProfilerInfo, FunctionID functionId, ReJITID reJitId, HRESULT hrStatus, BOOL fIsSafeToBlock) + { + if (IsRejitEnabled(pProfilerInfo)) + { + pProfilerInfo->pProfInterface->ReJITCompilationFinished(functionId, reJitId, hrStatus, fIsSafeToBlock); + } + }, + functionId, reJitId, hrStatus, fIsSafeToBlock); +} + +inline void ProfControlBlock::ReJITError(ModuleID moduleId, mdMethodDef methodId, FunctionID functionId, HRESULT hrStatus) +{ + LIMITED_METHOD_CONTRACT; + DoOneProfilerIteration(&mainProfilerInfo, + ProfilerCallbackType::Active, + [](ProfilerInfo *pProfilerInfo, ModuleID moduleId, mdMethodDef methodId, FunctionID functionId, HRESULT hrStatus) + { + if (IsRejitEnabled(pProfilerInfo)) + { + pProfilerInfo->pProfInterface->ReJITError(moduleId, methodId, functionId, hrStatus); + } + }, + moduleId, methodId, functionId, hrStatus); +} + +inline BOOL IsProfilerTrackingModuleLoads(ProfilerInfo *pProfilerInfo) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_MODULE_LOADS); +} + +inline void ProfControlBlock::ModuleLoadStarted(ModuleID moduleId) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingModuleLoads, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ModuleID moduleId) + { + return profInterface->ModuleLoadStarted(moduleId); + }, + moduleId); +} + +inline void ProfControlBlock::ModuleLoadFinished(ModuleID moduleId, HRESULT hrStatus) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingModuleLoads, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ModuleID moduleId, HRESULT hrStatus) + { + return profInterface->ModuleLoadFinished(moduleId, hrStatus); + }, + moduleId, hrStatus); +} + +inline void ProfControlBlock::ModuleUnloadStarted(ModuleID moduleId) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingModuleLoads, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ModuleID moduleId) + { + return profInterface->ModuleUnloadStarted(moduleId); + }, + moduleId); +} + +inline void ProfControlBlock::ModuleUnloadFinished(ModuleID moduleId, HRESULT hrStatus) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingModuleLoads, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ModuleID moduleId, HRESULT hrStatus) + { + return profInterface->ModuleUnloadFinished(moduleId, hrStatus); + }, + moduleId, hrStatus); +} + +inline void ProfControlBlock::ModuleAttachedToAssembly(ModuleID moduleId, AssemblyID AssemblyId) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingModuleLoads, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ModuleID moduleId, AssemblyID AssemblyId) + { + return profInterface->ModuleAttachedToAssembly(moduleId, AssemblyId); + }, + moduleId, AssemblyId); +} + +inline BOOL IsProfilerTrackingInMemorySymbolsUpdatesEnabled(ProfilerInfo *pProfilerInfo) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return pProfilerInfo->eventMask.IsEventMaskHighSet(COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED); +} + +inline void ProfControlBlock::ModuleInMemorySymbolsUpdated(ModuleID moduleId) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingInMemorySymbolsUpdatesEnabled, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ModuleID moduleId) + { + return profInterface->ModuleInMemorySymbolsUpdated(moduleId); + }, + moduleId); +} + +inline BOOL IsProfilerTrackingClasses(ProfilerInfo *pProfilerInfo) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_CLASS_LOADS); +} + +inline void ProfControlBlock::ClassLoadStarted(ClassID classId) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingClasses, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ClassID classId) + { + return profInterface->ClassLoadStarted(classId); + }, + classId); +} + +inline void ProfControlBlock::ClassLoadFinished(ClassID classId, HRESULT hrStatus) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingClasses, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ClassID classId, HRESULT hrStatus) + { + return profInterface->ClassLoadFinished(classId, hrStatus); + }, + classId, hrStatus); +} + +inline void ProfControlBlock::ClassUnloadStarted(ClassID classId) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingClasses, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ClassID classId) + { + return profInterface->ClassUnloadStarted(classId); + }, + classId); +} + +inline void ProfControlBlock::ClassUnloadFinished(ClassID classId, HRESULT hrStatus) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingClasses, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ClassID classId, HRESULT hrStatus) + { + return profInterface->ClassUnloadFinished(classId, hrStatus); + }, + classId, hrStatus); +} + +inline BOOL IsProfilerTrackingAppDomainLoads(ProfilerInfo *pProfilerInfo) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_APPDOMAIN_LOADS); +} + +inline void ProfControlBlock::AppDomainCreationStarted(AppDomainID appDomainId) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingAppDomainLoads, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, AppDomainID appDomainId) + { + return profInterface->AppDomainCreationStarted(appDomainId); + }, + appDomainId); +} + +inline void ProfControlBlock::AppDomainCreationFinished(AppDomainID appDomainId, HRESULT hrStatus) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingAppDomainLoads, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, AppDomainID appDomainId, HRESULT hrStatus) + { + return profInterface->AppDomainCreationFinished(appDomainId, hrStatus); + }, + appDomainId, hrStatus); +} + +inline void ProfControlBlock::AppDomainShutdownStarted(AppDomainID appDomainId) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingAppDomainLoads, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, AppDomainID appDomainId) + { + return profInterface->AppDomainShutdownStarted(appDomainId); + }, + appDomainId); +} + +inline void ProfControlBlock::AppDomainShutdownFinished(AppDomainID appDomainId, HRESULT hrStatus) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingAppDomainLoads, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, AppDomainID appDomainId, HRESULT hrStatus) + { + return profInterface->AppDomainShutdownFinished(appDomainId, hrStatus); + }, + appDomainId, hrStatus); +} + +inline BOOL IsProfilerTrackingAssemblyLoads(ProfilerInfo *pProfilerInfo) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_ASSEMBLY_LOADS); +} + +inline void ProfControlBlock::AssemblyLoadStarted(AssemblyID assemblyId) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingAssemblyLoads, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, AssemblyID assemblyId) + { + return profInterface->AssemblyLoadStarted(assemblyId); + }, + assemblyId); +} + +inline void ProfControlBlock::AssemblyLoadFinished(AssemblyID assemblyId, HRESULT hrStatus) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingAssemblyLoads, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, AssemblyID assemblyId, HRESULT hrStatus) + { + return profInterface->AssemblyLoadFinished(assemblyId, hrStatus); + }, + assemblyId, hrStatus); +} + +inline void ProfControlBlock::AssemblyUnloadStarted(AssemblyID assemblyId) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingAssemblyLoads, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, AssemblyID assemblyId) + { + return profInterface->AssemblyUnloadStarted(assemblyId); + }, + assemblyId); +} + +inline void ProfControlBlock::AssemblyUnloadFinished(AssemblyID assemblyId, HRESULT hrStatus) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingAssemblyLoads, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, AssemblyID assemblyId, HRESULT hrStatus) + { + return profInterface->AssemblyUnloadFinished(assemblyId, hrStatus); + }, + assemblyId, hrStatus); +} + +inline BOOL IsProfilerTrackingTransitions(ProfilerInfo *pProfilerInfo) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_CODE_TRANSITIONS); +} + +inline void ProfControlBlock::UnmanagedToManagedTransition(FunctionID functionId, COR_PRF_TRANSITION_REASON reason) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingTransitions, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID functionId, COR_PRF_TRANSITION_REASON reason) + { + return profInterface->UnmanagedToManagedTransition(functionId, reason); + }, + functionId, reason); +} + +inline void ProfControlBlock::ManagedToUnmanagedTransition(FunctionID functionId, COR_PRF_TRANSITION_REASON reason) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingTransitions, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID functionId, COR_PRF_TRANSITION_REASON reason) + { + return profInterface->ManagedToUnmanagedTransition(functionId, reason); + }, + functionId, reason); +} + +inline BOOL IsProfilerTrackingExceptions(ProfilerInfo *pProfilerInfo) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_EXCEPTIONS); +} + +inline void ProfControlBlock::ExceptionThrown(ObjectID thrownObjectId) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingExceptions, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ObjectID thrownObjectId) + { + return profInterface->ExceptionThrown(thrownObjectId); + }, + thrownObjectId); +} + +inline void ProfControlBlock::ExceptionSearchFunctionEnter(FunctionID functionId) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingExceptions, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID functionId) + { + return profInterface->ExceptionSearchFunctionEnter(functionId); + }, + functionId); +} + +inline void ProfControlBlock::ExceptionSearchFunctionLeave() +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingExceptions, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface) + { + return profInterface->ExceptionSearchFunctionLeave(); + }); +} + +inline void ProfControlBlock::ExceptionSearchFilterEnter(FunctionID funcId) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingExceptions, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID funcId) + { + return profInterface->ExceptionSearchFilterEnter(funcId); + }, + funcId); +} + +inline void ProfControlBlock::ExceptionSearchFilterLeave() +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingExceptions, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface) + { + return profInterface->ExceptionSearchFilterLeave(); + }); +} + +inline void ProfControlBlock::ExceptionSearchCatcherFound(FunctionID functionId) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingExceptions, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID functionId) + { + return profInterface->ExceptionSearchCatcherFound(functionId); + }, + functionId); +} + +inline void ProfControlBlock::ExceptionOSHandlerEnter(FunctionID funcId) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingExceptions, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID funcId) + { + return profInterface->ExceptionOSHandlerEnter(funcId); + }, + funcId); +} + +inline void ProfControlBlock::ExceptionOSHandlerLeave(FunctionID funcId) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingExceptions, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID funcId) + { + return profInterface->ExceptionOSHandlerLeave(funcId); + }, + funcId); +} + +inline void ProfControlBlock::ExceptionUnwindFunctionEnter(FunctionID functionId) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingExceptions, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID functionId) + { + return profInterface->ExceptionUnwindFunctionEnter(functionId); + }, + functionId); +} + +inline void ProfControlBlock::ExceptionUnwindFunctionLeave() +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingExceptions, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface) + { + return profInterface->ExceptionUnwindFunctionLeave(); + }); +} + +inline void ProfControlBlock::ExceptionUnwindFinallyEnter(FunctionID functionId) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingExceptions, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID functionId) + { + return profInterface->ExceptionUnwindFinallyEnter(functionId); + }, + functionId); +} + +inline void ProfControlBlock::ExceptionUnwindFinallyLeave() +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingExceptions, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface) + { + return profInterface->ExceptionUnwindFinallyLeave(); + }); +} + +inline void ProfControlBlock::ExceptionCatcherEnter(FunctionID functionId, ObjectID objectId) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingExceptions, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, FunctionID functionId, ObjectID objectId) + { + return profInterface->ExceptionCatcherEnter(functionId, objectId); + }, + functionId, objectId); +} + +inline void ProfControlBlock::ExceptionCatcherLeave() +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingExceptions, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface) + { + return profInterface->ExceptionCatcherLeave(); + }); +} + +inline BOOL IsProfilerTrackingCCW(ProfilerInfo *pProfilerInfo) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_CCW); +} + +inline void ProfControlBlock::COMClassicVTableCreated(ClassID wrappedClassId, REFGUID implementedIID, void *pVTable, ULONG cSlots) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingCCW, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ClassID wrappedClassId, REFGUID implementedIID, void *pVTable, ULONG cSlots) + { + return profInterface->COMClassicVTableCreated(wrappedClassId, implementedIID, pVTable, cSlots); + }, + wrappedClassId, implementedIID, pVTable, cSlots); +} + +inline BOOL IsProfilerTrackingSuspends(ProfilerInfo *pProfilerInfo) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_SUSPENDS); +} + +inline void ProfControlBlock::RuntimeSuspendStarted(COR_PRF_SUSPEND_REASON suspendReason) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingSuspends, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, COR_PRF_SUSPEND_REASON suspendReason) + { + return profInterface->RuntimeSuspendStarted(suspendReason); + }, + suspendReason); +} + +inline void ProfControlBlock::RuntimeSuspendFinished() +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingSuspends, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface) + { + return profInterface->RuntimeSuspendFinished(); + }); +} + +inline void ProfControlBlock::RuntimeSuspendAborted() +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingSuspends, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface) + { + return profInterface->RuntimeSuspendAborted(); + }); +} + +inline void ProfControlBlock::RuntimeResumeStarted() +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingSuspends, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface) + { + return profInterface->RuntimeResumeStarted(); + }); +} + +inline void ProfControlBlock::RuntimeResumeFinished() +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingSuspends, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface) + { + return profInterface->RuntimeResumeFinished(); + }); +} + +inline void ProfControlBlock::RuntimeThreadSuspended(ThreadID suspendedThreadId) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingSuspends, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ThreadID suspendedThreadId) + { + return profInterface->RuntimeThreadSuspended(suspendedThreadId); + }, + suspendedThreadId); +} + +inline void ProfControlBlock::RuntimeThreadResumed(ThreadID resumedThreadId) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingSuspends, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ThreadID resumedThreadId) + { + return profInterface->RuntimeThreadResumed(resumedThreadId); + }, + resumedThreadId); +} + +inline BOOL IsProfilerTrackingAllocations(ProfilerInfo *pProfilerInfo) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_ENABLE_OBJECT_ALLOCATED) + || pProfilerInfo->eventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED)); +} + +inline void ProfControlBlock::ObjectAllocated(ObjectID objectId, ClassID classId) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingAllocations, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ObjectID objectId, ClassID classId) + { + return profInterface->ObjectAllocated(objectId, classId); + }, + objectId, classId); +} + + +inline BOOL IsProfilerTrackingGC(ProfilerInfo *pProfilerInfo) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_GC); +} + +inline void ProfControlBlock::FinalizeableObjectQueued(BOOL isCritical, ObjectID objectID) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingGC, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, BOOL isCritical, ObjectID objectID) + { + return profInterface->FinalizeableObjectQueued(isCritical, objectID); + }, + isCritical, objectID); +} + +inline void ProfControlBlock::MovedReference(BYTE *pbMemBlockStart, BYTE *pbMemBlockEnd, ptrdiff_t cbRelocDistance, void *pHeapId, BOOL fCompacting) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingGC, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, BYTE *pbMemBlockStart, BYTE *pbMemBlockEnd, ptrdiff_t cbRelocDistance, void *pHeapId, BOOL fCompacting) + { + return profInterface->MovedReference(pbMemBlockStart, pbMemBlockEnd, cbRelocDistance, pHeapId, fCompacting); + }, + pbMemBlockStart, pbMemBlockEnd, cbRelocDistance, pHeapId, fCompacting); +} + +inline void ProfControlBlock::EndMovedReferences(void *pHeapId) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingGC, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, void *pHeapId) + { + return profInterface->EndMovedReferences(pHeapId); + }, + pHeapId); +} + +inline void ProfControlBlock::RootReference2(BYTE *objectId, EtwGCRootKind dwEtwRootKind, EtwGCRootFlags dwEtwRootFlags, void *rootID, void *pHeapId) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingGC, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, BYTE *objectId, EtwGCRootKind dwEtwRootKind, EtwGCRootFlags dwEtwRootFlags, void *rootID, void *pHeapId) + { + return profInterface->RootReference2(objectId, dwEtwRootKind, dwEtwRootFlags, rootID, pHeapId); + }, + objectId, dwEtwRootKind, dwEtwRootFlags, rootID, pHeapId); +} + +inline void ProfControlBlock::EndRootReferences2(void *pHeapId) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingGC, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, void *pHeapId) + { + return profInterface->EndRootReferences2(pHeapId); + }, + pHeapId); +} + +inline void ProfControlBlock::ConditionalWeakTableElementReference(BYTE *primaryObjectId, BYTE *secondaryObjectId, void *rootID, void *pHeapId) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingGC, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, BYTE *primaryObjectId, BYTE *secondaryObjectId, void *rootID, void *pHeapId) + { + if (!profInterface->IsCallback5Supported()) + { + return S_OK; + } + + return profInterface->ConditionalWeakTableElementReference(primaryObjectId, secondaryObjectId, rootID, pHeapId); + }, + primaryObjectId, secondaryObjectId, rootID, pHeapId); +} + +inline void ProfControlBlock::EndConditionalWeakTableElementReferences(void *pHeapId) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingGC, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, void *pHeapId) + { + if (!profInterface->IsCallback5Supported()) + { + return S_OK; + } + + return profInterface->EndConditionalWeakTableElementReferences(pHeapId); + }, + pHeapId); +} + +inline void ProfControlBlock::AllocByClass(ObjectID objId, ClassID classId, void *pHeapId) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingGC, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ObjectID objId, ClassID classId, void *pHeapId) + { + return profInterface->AllocByClass(objId, classId, pHeapId); + }, + objId, classId, pHeapId); +} + +inline void ProfControlBlock::EndAllocByClass(void *pHeapId) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingGC, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, void *pHeapId) + { + return profInterface->EndAllocByClass(pHeapId); + }, + pHeapId); +} + +inline HRESULT ProfControlBlock::ObjectReference(ObjectID objId, ClassID classId, ULONG cNumRefs, ObjectID *arrObjRef) +{ + LIMITED_METHOD_CONTRACT; + + return DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingGC, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, ObjectID objId, ClassID classId, ULONG cNumRefs, ObjectID *arrObjRef) + { + return profInterface->ObjectReference(objId, classId, cNumRefs, arrObjRef); + }, + objId, classId, cNumRefs, arrObjRef); +} + +inline void ProfControlBlock::HandleCreated(UINT_PTR handleId, ObjectID initialObjectId) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingGC, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, UINT_PTR handleId, ObjectID initialObjectId) + { + return profInterface->HandleCreated(handleId, initialObjectId); + }, + handleId, initialObjectId); +} + +inline void ProfControlBlock::HandleDestroyed(UINT_PTR handleId) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingGC, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, UINT_PTR handleId) + { + return profInterface->HandleDestroyed(handleId); + }, + handleId); +} + + +inline BOOL IsProfilerTrackingBasicGC(ProfilerInfo *pProfilerInfo) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return pProfilerInfo->eventMask.IsEventMaskHighSet(COR_PRF_HIGH_BASIC_GC); +} + +inline BOOL IsProfilerTrackingMovedObjects(ProfilerInfo *pProfilerInfo) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return pProfilerInfo->eventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS); +} + +inline BOOL IsProfilerTrackingGCOrBasicGC(ProfilerInfo *pProfilerInfo) +{ + return IsProfilerTrackingGC(pProfilerInfo) || IsProfilerTrackingBasicGC(pProfilerInfo); +} + +inline BOOL IsProfilerTrackingGCOrMovedObjects(ProfilerInfo *pProfilerInfo) +{ + return IsProfilerTrackingGC(pProfilerInfo) || IsProfilerTrackingMovedObjects(pProfilerInfo); +} + +inline void ProfControlBlock::GarbageCollectionStarted(int cGenerations, BOOL generationCollected[], COR_PRF_GC_REASON reason) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingGCOrBasicGC, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, int cGenerations, BOOL generationCollected[], COR_PRF_GC_REASON reason) + { + return profInterface->GarbageCollectionStarted(cGenerations, generationCollected, reason); + }, + cGenerations, generationCollected, reason); +} + +inline void ProfControlBlock::GarbageCollectionFinished() +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingGCOrBasicGC, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface) + { + return profInterface->GarbageCollectionFinished(); + }); +} + + +inline BOOL IsProfilerMonitoringEventPipe(ProfilerInfo *pProfilerInfo) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return pProfilerInfo->eventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_EVENT_PIPE); +} + + +inline void ProfControlBlock::EventPipeEventDelivered(EventPipeProvider *provider, + DWORD eventId, + DWORD eventVersion, + ULONG cbMetadataBlob, + LPCBYTE metadataBlob, + ULONG cbEventData, + LPCBYTE eventData, + LPCGUID pActivityId, + LPCGUID pRelatedActivityId, + Thread *pEventThread, + ULONG numStackFrames, + UINT_PTR stackFrames[]) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerMonitoringEventPipe, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, EventPipeProvider *provider, + DWORD eventId, + DWORD eventVersion, + ULONG cbMetadataBlob, + LPCBYTE metadataBlob, + ULONG cbEventData, + LPCBYTE eventData, + LPCGUID pActivityId, + LPCGUID pRelatedActivityId, + Thread *pEventThread, + ULONG numStackFrames, + UINT_PTR stackFrames[]) + { + return profInterface->EventPipeEventDelivered(provider, + eventId, + eventVersion, + cbMetadataBlob, + metadataBlob, + cbEventData, + eventData, + pActivityId, + pRelatedActivityId, + pEventThread, + numStackFrames, + stackFrames); + }, + provider, + eventId, + eventVersion, + cbMetadataBlob, + metadataBlob, + cbEventData, + eventData, + pActivityId, + pRelatedActivityId, + pEventThread, + numStackFrames, + stackFrames); +} + +inline void ProfControlBlock::EventPipeProviderCreated(EventPipeProvider *provider) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerMonitoringEventPipe, + (void *)NULL, + [](void *additionalData, VolatilePtr<EEToProfInterfaceImpl> profInterface, EventPipeProvider *provider) + { + return profInterface->EventPipeProviderCreated(provider); + }, + provider); } //--------------------------------------------------------------------------------------- @@ -90,14 +1664,18 @@ inline void ProfControlBlock::ResetPerSessionStatus() // and what features it enabled callbacks for. //--------------------------------------------------------------------------------------- - -// CORProfilerPresent() returns whether or not a CLR Profiler is actively loaded -// (meaning it's initialized and ready to receive callbacks). inline BOOL CORProfilerPresent() { LIMITED_METHOD_DAC_CONTRACT; - return ((&g_profControlBlock)->curProfStatus.Get() == kProfStatusActive); + return AnyProfilerPassesCondition([](ProfilerInfo *pProfilerInfo) { return pProfilerInfo->curProfStatus.Get() >= kProfStatusActive; }); +} + +inline BOOL CORMainProfilerPresent() +{ + LIMITED_METHOD_DAC_CONTRACT; + + return (&g_profControlBlock)->mainProfilerInfo.curProfStatus.Get() >= kProfStatusActive; } // These return whether a CLR Profiler is actively loaded AND has requested the @@ -113,10 +1691,10 @@ inline BOOL CORProfilerFunctionIDMapperEnabled() } CONTRACTL_END; - return (CORProfilerPresent() && + return (CORMainProfilerPresent() && ( - ((&g_profControlBlock)->pProfInterface->GetFunctionIDMapper() != NULL) || - ((&g_profControlBlock)->pProfInterface->GetFunctionIDMapper2() != NULL) + ((&g_profControlBlock)->mainProfilerInfo.pProfInterface->GetFunctionIDMapper() != NULL) || + ((&g_profControlBlock)->mainProfilerInfo.pProfInterface->GetFunctionIDMapper2() != NULL) )); } @@ -131,7 +1709,7 @@ inline BOOL CORProfilerTrackJITInfo() CONTRACTL_END; return (CORProfilerPresent() && - ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_JIT_COMPILATION)); + (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_JIT_COMPILATION)); } inline BOOL CORProfilerTrackCacheSearches() @@ -145,7 +1723,7 @@ inline BOOL CORProfilerTrackCacheSearches() CONTRACTL_END; return (CORProfilerPresent() && - ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_CACHE_SEARCHES)); + (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_CACHE_SEARCHES)); } inline BOOL CORProfilerTrackModuleLoads() @@ -159,7 +1737,7 @@ inline BOOL CORProfilerTrackModuleLoads() CONTRACTL_END; return (CORProfilerPresent() && - ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_MODULE_LOADS)); + (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_MODULE_LOADS)); } inline BOOL CORProfilerTrackAssemblyLoads() @@ -173,7 +1751,7 @@ inline BOOL CORProfilerTrackAssemblyLoads() CONTRACTL_END; return (CORProfilerPresent() && - ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_ASSEMBLY_LOADS)); + (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_ASSEMBLY_LOADS)); } inline BOOL CORProfilerTrackAppDomainLoads() @@ -187,7 +1765,7 @@ inline BOOL CORProfilerTrackAppDomainLoads() CONTRACTL_END; return (CORProfilerPresent() && - ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_APPDOMAIN_LOADS)); + (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_APPDOMAIN_LOADS)); } inline BOOL CORProfilerTrackThreads() @@ -201,7 +1779,7 @@ inline BOOL CORProfilerTrackThreads() CONTRACTL_END; return (CORProfilerPresent() && - ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_THREADS)); + (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_THREADS)); } inline BOOL CORProfilerTrackClasses() @@ -215,7 +1793,7 @@ inline BOOL CORProfilerTrackClasses() CONTRACTL_END; return (CORProfilerPresent() && - ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_CLASS_LOADS)); + (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_CLASS_LOADS)); } inline BOOL CORProfilerTrackGC() @@ -229,7 +1807,7 @@ inline BOOL CORProfilerTrackGC() CONTRACTL_END; return (CORProfilerPresent() && - ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_GC)); + (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_GC)); } inline BOOL CORProfilerTrackAllocationsEnabled() @@ -248,7 +1826,7 @@ inline BOOL CORProfilerTrackAllocationsEnabled() (&g_profControlBlock)->fTestOnlyForceObjectAllocated || #endif (CORProfilerPresent() && - ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_OBJECT_ALLOCATED)) + (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_ENABLE_OBJECT_ALLOCATED)) ); } @@ -264,7 +1842,7 @@ inline BOOL CORProfilerTrackAllocations() return (CORProfilerTrackAllocationsEnabled() && - ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_OBJECT_ALLOCATED)); + (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_OBJECT_ALLOCATED)); } inline BOOL CORProfilerTrackLargeAllocations() @@ -279,7 +1857,7 @@ inline BOOL CORProfilerTrackLargeAllocations() return (CORProfilerPresent() && - ((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED)); + (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED)); } inline BOOL CORProfilerEnableRejit() @@ -292,8 +1870,8 @@ inline BOOL CORProfilerEnableRejit() } CONTRACTL_END; - return (CORProfilerPresent() && - ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_REJIT)); + return (CORMainProfilerPresent() && + (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_ENABLE_REJIT)); } inline BOOL CORProfilerTrackExceptions() @@ -307,7 +1885,7 @@ inline BOOL CORProfilerTrackExceptions() CONTRACTL_END; return (CORProfilerPresent() && - ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_EXCEPTIONS)); + (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_EXCEPTIONS)); } inline BOOL CORProfilerTrackTransitions() @@ -321,7 +1899,7 @@ inline BOOL CORProfilerTrackTransitions() CONTRACTL_END; return (CORProfilerPresent() && - ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_CODE_TRANSITIONS)); + (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_CODE_TRANSITIONS)); } inline BOOL CORProfilerTrackEnterLeave() @@ -340,7 +1918,7 @@ inline BOOL CORProfilerTrackEnterLeave() #endif // PROF_TEST_ONLY_FORCE_ELT return (CORProfilerPresent() && - ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_ENTERLEAVE)); + (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_ENTERLEAVE)); } inline BOOL CORProfilerTrackCCW() @@ -354,53 +1932,7 @@ inline BOOL CORProfilerTrackCCW() CONTRACTL_END; return (CORProfilerPresent() && - ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_CCW)); -} - -inline BOOL CORProfilerTrackRemoting() -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; - - return (CORProfilerPresent() && - ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_REMOTING)); -} - -inline BOOL CORProfilerTrackRemotingCookie() -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; - - return - (CORProfilerPresent() && - (((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_REMOTING_COOKIE) - == COR_PRF_MONITOR_REMOTING_COOKIE)); -} - -inline BOOL CORProfilerTrackRemotingAsync() -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; - - return - (CORProfilerPresent() && - (((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_REMOTING_ASYNC) - == COR_PRF_MONITOR_REMOTING_ASYNC)); + (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_CCW)); } inline BOOL CORProfilerTrackSuspends() @@ -414,7 +1946,7 @@ inline BOOL CORProfilerTrackSuspends() CONTRACTL_END; return (CORProfilerPresent() && - ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_SUSPENDS)); + (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_SUSPENDS)); } inline BOOL CORProfilerDisableInlining() @@ -428,21 +1960,7 @@ inline BOOL CORProfilerDisableInlining() CONTRACTL_END; return (CORProfilerPresent() && - ((&g_profControlBlock)->dwEventMask & COR_PRF_DISABLE_INLINING)); -} - -inline BOOL CORProfilerJITMapEnabled() -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; - - return (CORProfilerPresent() && - ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_JIT_MAPS)); + (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_DISABLE_INLINING)); } inline BOOL CORProfilerDisableOptimizations() @@ -457,7 +1975,7 @@ inline BOOL CORProfilerDisableOptimizations() CONTRACTL_END; return (CORProfilerPresent() && - ((&g_profControlBlock)->dwEventMask & COR_PRF_DISABLE_OPTIMIZATIONS)); + (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_DISABLE_OPTIMIZATIONS)); } inline BOOL CORProfilerUseProfileImages() @@ -475,14 +1993,8 @@ inline BOOL CORProfilerUseProfileImages() return TRUE; #endif // PROF_TEST_ONLY_FORCE_ELT - if (!CORProfilerPresent()) - return FALSE; - - if (((&g_profControlBlock)->dwEventMask & - COR_PRF_REQUIRE_PROFILE_IMAGE) == 0) - return FALSE; - - return TRUE; + return (CORProfilerPresent() && + (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_REQUIRE_PROFILE_IMAGE)); } inline BOOL CORProfilerDisableAllNGenImages() @@ -490,14 +2002,14 @@ inline BOOL CORProfilerDisableAllNGenImages() LIMITED_METHOD_DAC_CONTRACT; return (CORProfilerPresent() && - ((&g_profControlBlock)->dwEventMask & COR_PRF_DISABLE_ALL_NGEN_IMAGES)); + (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_DISABLE_ALL_NGEN_IMAGES)); } inline BOOL CORProfilerTrackConditionalWeakTableElements() { LIMITED_METHOD_DAC_CONTRACT; - return CORProfilerTrackGC() && (&g_profControlBlock)->pProfInterface->IsCallback5Supported(); + return CORProfilerTrackGC() && (&g_profControlBlock)->IsCallback5Supported(); } // CORProfilerPresentOrInitializing() returns nonzero iff a CLR Profiler is actively @@ -508,8 +2020,8 @@ inline BOOL CORProfilerTrackConditionalWeakTableElements() // that may still be initializing, and this function is appropriate for that code. inline BOOL CORProfilerPresentOrInitializing() { - LIMITED_METHOD_DAC_CONTRACT; - return ((&g_profControlBlock)->curProfStatus.Get() > kProfStatusDetaching); + LIMITED_METHOD_CONTRACT; + return AnyProfilerPassesCondition([](ProfilerInfo *pProfilerInfo) { return pProfilerInfo->curProfStatus.Get() > kProfStatusDetaching; }); } // These return whether a CLR Profiler has requested the specified functionality. @@ -531,7 +2043,7 @@ inline BOOL CORProfilerELT3SlowPathEnabled() CONTRACTL_END; return (CORProfilerPresentOrInitializing() && - ((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO))); + (&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO))); } inline BOOL CORProfilerELT3SlowPathEnterEnabled() @@ -545,7 +2057,7 @@ inline BOOL CORProfilerELT3SlowPathEnterEnabled() CONTRACTL_END; return (CORProfilerPresentOrInitializing() && - ((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FRAME_INFO))); + (&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FRAME_INFO))); } inline BOOL CORProfilerELT3SlowPathLeaveEnabled() @@ -559,7 +2071,7 @@ inline BOOL CORProfilerELT3SlowPathLeaveEnabled() CONTRACTL_END; return (CORProfilerPresentOrInitializing() && - ((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO))); + (&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO))); } inline BOOL CORProfilerELT3SlowPathTailcallEnabled() @@ -573,7 +2085,7 @@ inline BOOL CORProfilerELT3SlowPathTailcallEnabled() CONTRACTL_END; return (CORProfilerPresentOrInitializing() && - ((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_FRAME_INFO))); + (&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_FRAME_INFO))); } inline BOOL CORProfilerELT2FastPathEnterEnabled() @@ -587,7 +2099,7 @@ inline BOOL CORProfilerELT2FastPathEnterEnabled() CONTRACTL_END; return (CORProfilerPresentOrInitializing() && - (!((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FRAME_INFO)))); + !((&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FRAME_INFO)))); } inline BOOL CORProfilerELT2FastPathLeaveEnabled() @@ -601,7 +2113,7 @@ inline BOOL CORProfilerELT2FastPathLeaveEnabled() CONTRACTL_END; return (CORProfilerPresentOrInitializing() && - (!((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO)))); + !((&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO)))); } inline BOOL CORProfilerELT2FastPathTailcallEnabled() @@ -615,7 +2127,7 @@ inline BOOL CORProfilerELT2FastPathTailcallEnabled() CONTRACTL_END; return (CORProfilerPresentOrInitializing() && - (!((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_ENABLE_FRAME_INFO)))); + !((&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_ENABLE_FRAME_INFO)))); } inline BOOL CORProfilerFunctionArgsEnabled() @@ -629,7 +2141,7 @@ inline BOOL CORProfilerFunctionArgsEnabled() CONTRACTL_END; return (CORProfilerPresentOrInitializing() && - ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_FUNCTION_ARGS)); + (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_ENABLE_FUNCTION_ARGS)); } inline BOOL CORProfilerFunctionReturnValueEnabled() @@ -643,7 +2155,7 @@ inline BOOL CORProfilerFunctionReturnValueEnabled() CONTRACTL_END; return (CORProfilerPresentOrInitializing() && - ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_FUNCTION_RETVAL)); + (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_ENABLE_FUNCTION_RETVAL)); } inline BOOL CORProfilerFrameInfoEnabled() @@ -657,7 +2169,7 @@ inline BOOL CORProfilerFrameInfoEnabled() CONTRACTL_END; return (CORProfilerPresentOrInitializing() && - ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_FRAME_INFO)); + (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_ENABLE_FRAME_INFO)); } inline BOOL CORProfilerStackSnapshotEnabled() @@ -671,21 +2183,7 @@ inline BOOL CORProfilerStackSnapshotEnabled() CONTRACTL_END; return (CORProfilerPresentOrInitializing() && - ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_STACK_SNAPSHOT)); -} - -inline BOOL CORProfilerAddsAssemblyReferences() -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; - - return (CORProfilerPresent() && - ((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_ADD_ASSEMBLY_REFERENCES)); + (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_ENABLE_STACK_SNAPSHOT)); } inline BOOL CORProfilerInMemorySymbolsUpdatesEnabled() @@ -699,10 +2197,10 @@ inline BOOL CORProfilerInMemorySymbolsUpdatesEnabled() CONTRACTL_END; return (CORProfilerPresent() && - ((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED)); + (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED)); } -inline BOOL CORProfilerIsMonitoringDynamicFunctionUnloads() +inline BOOL CORProfilerTrackDynamicFunctionUnloads() { CONTRACTL { @@ -713,7 +2211,7 @@ inline BOOL CORProfilerIsMonitoringDynamicFunctionUnloads() CONTRACTL_END; return (CORProfilerPresent() && - ((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS)); + (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS)); } inline BOOL CORProfilerDisableTieredCompilation() @@ -728,7 +2226,7 @@ inline BOOL CORProfilerDisableTieredCompilation() return (CORProfilerPresent() && - ((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_DISABLE_TIERED_COMPILATION)); + (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_DISABLE_TIERED_COMPILATION)); } inline BOOL CORProfilerTrackBasicGC() @@ -742,7 +2240,7 @@ inline BOOL CORProfilerTrackBasicGC() CONTRACTL_END; return (CORProfilerPresent() && - ((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_BASIC_GC)); + (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_BASIC_GC)); } inline BOOL CORProfilerTrackGCMovedObjects() @@ -756,10 +2254,10 @@ inline BOOL CORProfilerTrackGCMovedObjects() CONTRACTL_END; return (CORProfilerPresent() && - ((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS)); + (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS)); } -inline BOOL CORProfilerIsMonitoringEventPipe() +inline BOOL CORProfilerTrackEventPipe() { CONTRACTL { @@ -770,55 +2268,38 @@ inline BOOL CORProfilerIsMonitoringEventPipe() CONTRACTL_END; return (CORProfilerPresent() && - ((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_MONITOR_EVENT_PIPE)); + (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_EVENT_PIPE)); } #if defined(PROFILING_SUPPORTED) && !defined(CROSSGEN_COMPILE) -#if defined(FEATURE_PROFAPI_ATTACH_DETACH) - //--------------------------------------------------------------------------------------- -// When EE calls into the profiler, an EvacuationCounterHolder object is instantiated on -// the stack to increment the evacuation counter inside the EE Thread. Upon returning to -// EE, this EvacuationCounterHolder object when being destroyed decreases the evacuation -// counter by one. -// -// Do not use this object directly. Use BEGIN_PIN_PROFILER / END_PIN_PROFILER defined -// below. -// -// See code:ProfilingAPIUtility::InitializeProfiling#LoadUnloadCallbackSynchronization. -// -typedef Wrapper<Thread *, ProfilingAPIUtility::IncEvacuationCounter, ProfilingAPIUtility::DecEvacuationCounter, - (UINT_PTR)0, CompareDefault<Thread *>> EvacuationCounterHolder; - - -//--------------------------------------------------------------------------------------- -// These macros must be placed around any access to g_profControlBlock.pProfInterface by +// These macros must be placed around any callbacks to g_profControlBlock by // the EE. Example: // { -// BEGIN_PIN_PROFILER(CORProfilerTrackAppDomainLoads()); -// g_profControlBlock.pProfInterface->AppDomainCreationStarted(MyAppDomainID); -// END_PIN_PROFILER(); +// BEGIN_PROFILER_CALLBACK(CORProfilerTrackAppDomainLoads; +// g_profControlBlock.AppDomainCreationStarted(MyAppDomainID); +// END_PROFILER_CALLBACK(); // } -// The parameter to the BEGIN_PIN_PROFILER is the condition you want to check for, to +// The parameter to the BEGIN_PROFILER_CALLBACK is the condition you want to check for, to // determine whether the profiler is loaded and requesting the callback you're about to // issue. Typically, this will be a call to one of the inline functions in // profilepriv.inl. If the condition is true, the macro will increment an evacuation // counter that effectively pins the profiler, recheck the condition, and (if still -// true), execute whatever code you place inside the BEGIN/END_PIN_PROFILER block. If +// true), execute whatever code you place inside the BEGIN/END_PROFILER_CALLBACK block. If // your condition is more complex than a simple profiler status check, then place the // profiler status check as parameter to the macro, and add a separate if inside the // block. Example: // // { -// BEGIN_PIN_PROFILER(CORProfilerTrackTransitions()); +// BEGIN_PROFILER_CALLBACK(CorProfilerTrackTransitions); // if (!pNSL->pMD->IsQCall()) // { -// g_profControlBlock.pProfInterface-> +// g_profControlBlock. // ManagedToUnmanagedTransition((FunctionID) pNSL->pMD, // COR_PRF_TRANSITION_CALL); // } -// END_PIN_PROFILER(); +// END_PROFILER_CALLBACK(); // } // // This ensures that the extra condition check (in this case "if @@ -827,35 +2308,19 @@ typedef Wrapper<Thread *, ProfilingAPIUtility::IncEvacuationCounter, ProfilingAP // // See code:ProfilingAPIUtility::InitializeProfiling#LoadUnloadCallbackSynchronization // for more details about how the synchronization works. -#define BEGIN_PIN_PROFILER(condition) \ +#define BEGIN_PROFILER_CALLBACK(condition) \ /* Do a cheap check of the condition (dirty-read) */ \ if (condition) \ { \ - EvacuationCounterHolder __evacuationCounter(GetThreadNULLOk()); \ - /* Now that the evacuation counter is incremented, the condition re-check */ \ - /* below is a clean read. There's no MemoryBarrier() here, but that's ok */ \ - /* as writes to the profiler status force a FlushStoreBuffers(). */ \ - if (condition) \ - { -#define END_PIN_PROFILER() } } - -#else // FEATURE_PROFAPI_ATTACH_DETACH - -// For builds that include profiling but not attach / detach (e.g., Silverlight 2), the -// *PIN_PROFILER macros should just check the condition without using the evacuation -// counters. - -#define BEGIN_PIN_PROFILER(condition) if (condition) { -#define END_PIN_PROFILER() } -#endif // FEATURE_PROFAPI_ATTACH_DETACH +#define END_PROFILER_CALLBACK() } #else // PROFILING_SUPPORTED && !CROSSGEN_COMPILE // Profiling feature not supported -#define BEGIN_PIN_PROFILER(condition) if (false) { -#define END_PIN_PROFILER() } +#define BEGIN_PROFILER_CALLBACK(condition) if (false) { +#define END_PROFILER_CALLBACK() } #endif // PROFILING_SUPPORTED && !CROSSGEN_COMPILE diff --git a/src/coreclr/inc/sarray.inl b/src/coreclr/inc/sarray.inl index b375b6a633b..7d6a5b6a37d 100644 --- a/src/coreclr/inc/sarray.inl +++ b/src/coreclr/inc/sarray.inl @@ -247,7 +247,7 @@ inline void SArray<ELEMENT, BITWISE_COPY>::Delete(const Iterator &i, COUNT_T cou } template <typename ELEMENT, BOOL BITWISE_COPY> -inline void SArray<ELEMENT, BITWISE_COPY>:: Replace(const Iterator &i, COUNT_T deleteCount, COUNT_T insertCount) +inline void SArray<ELEMENT, BITWISE_COPY>::Replace(const Iterator &i, COUNT_T deleteCount, COUNT_T insertCount) { WRAPPER_NO_CONTRACT; DestructBuffer(i, deleteCount); |