diff options
author | José Rivero <jorive@microsoft.com> | 2019-06-14 13:47:04 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-06-14 13:47:04 -0700 |
commit | fc29d38699b8e4ce619d669c2135548fe8abe730 (patch) | |
tree | 37f12f436470dc1710493a740903f0ee77e68168 | |
parent | 54d82b2c1b385025ea84a9fb8c60caa76f371f34 (diff) | |
download | coreclr-fc29d38699b8e4ce619d669c2135548fe8abe730.tar.gz coreclr-fc29d38699b8e4ce619d669c2135548fe8abe730.tar.bz2 coreclr-fc29d38699b8e4ce619d669c2135548fe8abe730.zip |
Moving non-EventPipe types out of eventpipe.* (#25161)
* Replace runtime check with compile time assert.
* Move EventPipeEventPayload to its own file.
* Move `StackContents` to its own file.
* Move other classes declaration/definition out of eventpipe.*
-rw-r--r-- | src/vm/CMakeLists.txt | 5 | ||||
-rw-r--r-- | src/vm/eventpipe.cpp | 141 | ||||
-rw-r--r-- | src/vm/eventpipe.h | 290 | ||||
-rw-r--r-- | src/vm/eventpipebuffer.cpp | 3 | ||||
-rw-r--r-- | src/vm/eventpipebuffermanager.cpp | 1 | ||||
-rw-r--r-- | src/vm/eventpipecommontypes.cpp | 28 | ||||
-rw-r--r-- | src/vm/eventpipecommontypes.h | 120 | ||||
-rw-r--r-- | src/vm/eventpipeconfiguration.h | 2 | ||||
-rw-r--r-- | src/vm/eventpipeeventpayload.cpp | 132 | ||||
-rw-r--r-- | src/vm/eventpipeeventpayload.h | 80 | ||||
-rw-r--r-- | src/vm/eventpipeeventsource.cpp | 1 | ||||
-rw-r--r-- | src/vm/eventpipesession.cpp | 1 | ||||
-rw-r--r-- | src/vm/stackcontents.h | 125 |
13 files changed, 501 insertions, 428 deletions
diff --git a/src/vm/CMakeLists.txt b/src/vm/CMakeLists.txt index 25b6335e61..9bdbee3c0e 100644 --- a/src/vm/CMakeLists.txt +++ b/src/vm/CMakeLists.txt @@ -323,8 +323,10 @@ set(VM_SOURCES_WKS eventpipeconfiguration.cpp eventpipeevent.cpp eventpipeeventinstance.cpp + eventpipeeventpayload.cpp eventpipeeventsource.cpp eventpipeblock.cpp + eventpipecommontypes.cpp eventpipefile.cpp eventpipeinternal.cpp eventpipejsonfile.cpp @@ -443,9 +445,11 @@ set(VM_HEADERS_WKS eventpipeblock.h eventpipebuffer.h eventpipebuffermanager.h + eventpipecommontypes.h eventpipeconfiguration.h eventpipeevent.h eventpipeeventinstance.h + eventpipeeventpayload.h eventpipeeventsource.h eventpipefile.h eventpipeinternal.h @@ -502,6 +506,7 @@ set(VM_HEADERS_WKS sha1.h simplerwlock.hpp sourceline.h + stackcontents.h stackingallocator.h stringliteralmap.h stubcache.h diff --git a/src/vm/eventpipe.cpp b/src/vm/eventpipe.cpp index 664fcfae2c..adec56bd16 100644 --- a/src/vm/eventpipe.cpp +++ b/src/vm/eventpipe.cpp @@ -9,6 +9,7 @@ #include "eventpipe.h" #include "eventpipebuffermanager.h" #include "eventpipeconfiguration.h" +#include "eventpipeeventpayload.h" #include "eventpipesessionprovider.h" #include "eventpipeevent.h" #include "eventpipeeventsource.h" @@ -40,146 +41,6 @@ extern "C" void InitProvidersAndEvents(); void InitProvidersAndEvents(); #endif -EventPipeEventPayload::EventPipeEventPayload(EventData *pEventData, unsigned int eventDataCount) -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - } - CONTRACTL_END; - - m_pData = NULL; - m_pEventData = pEventData; - m_eventDataCount = eventDataCount; - m_allocatedData = false; - - S_UINT32 tmp_size = S_UINT32(0); - for (unsigned int i = 0; i < m_eventDataCount; i++) - { - tmp_size += S_UINT32(m_pEventData[i].Size); - } - - if (tmp_size.IsOverflow()) - { - // If there is an overflow, drop the data and create an empty payload - m_pEventData = NULL; - m_eventDataCount = 0; - m_size = 0; - } - else - { - m_size = tmp_size.Value(); - } -} - -EventPipeEventPayload::~EventPipeEventPayload() -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - } - CONTRACTL_END; - - if (m_allocatedData && m_pData != NULL) - { - delete[] m_pData; - m_pData = NULL; - } -} - -void EventPipeEventPayload::Flatten() -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - } - CONTRACTL_END; - - if (m_size > 0) - { - if (!IsFlattened()) - { - BYTE *tmp_pData = new (nothrow) BYTE[m_size]; - if (tmp_pData != NULL) - { - m_allocatedData = true; - CopyData(tmp_pData); - m_pData = tmp_pData; - } - } - } -} - -void EventPipeEventPayload::CopyData(BYTE *pDst) -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - } - CONTRACTL_END; - - if (m_size > 0) - { - if (IsFlattened()) - { - memcpy(pDst, m_pData, m_size); - } - - else if (m_pEventData != NULL) - { - unsigned int offset = 0; - for (unsigned int i = 0; i < m_eventDataCount; i++) - { - memcpy(pDst + offset, (BYTE *)m_pEventData[i].Ptr, m_pEventData[i].Size); - offset += m_pEventData[i].Size; - } - } - } -} - -BYTE *EventPipeEventPayload::GetFlatData() -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - } - CONTRACTL_END; - - if (!IsFlattened()) - { - Flatten(); - } - return m_pData; -} - -void EventPipeProviderCallbackDataQueue::Enqueue(EventPipeProviderCallbackData *pEventPipeProviderCallbackData) -{ - SListElem<EventPipeProviderCallbackData> *listnode = new SListElem<EventPipeProviderCallbackData>(); // throws - listnode->m_Value = *pEventPipeProviderCallbackData; - list.InsertTail(listnode); -} - -bool EventPipeProviderCallbackDataQueue::TryDequeue(EventPipeProviderCallbackData *pEventPipeProviderCallbackData) -{ - if (list.IsEmpty()) - return false; - - SListElem<EventPipeProviderCallbackData> *listnode = list.RemoveHead(); - *pEventPipeProviderCallbackData = listnode->m_Value; - delete listnode; - return true; -} - void EventPipe::Initialize() { STANDARD_VM_CONTRACT; diff --git a/src/vm/eventpipe.h b/src/vm/eventpipe.h index 6f38289a9e..20f6c1fc7f 100644 --- a/src/vm/eventpipe.h +++ b/src/vm/eventpipe.h @@ -7,6 +7,8 @@ #ifdef FEATURE_PERFTRACING #include "common.h" +#include "eventpipecommontypes.h" +#include "stackcontents.h" class CrstStatic; class CrawlFrame; @@ -14,257 +16,17 @@ class EventPipeConfiguration; class EventPipeEvent; class EventPipeEventInstance; class EventPipeFile; -class EventPipeBufferManager; class EventPipeEventSource; class EventPipeProvider; -class MethodDesc; -struct EventPipeProviderConfiguration; class EventPipeSession; class IpcStream; enum class EventPipeSessionType; enum class EventPipeSerializationFormat; - -enum class EventPipeEventLevel -{ - LogAlways, - Critical, - Error, - Warning, - Informational, - Verbose -}; - -// EVENT_FILTER_DESCRIPTOR (This type does not exist on non-Windows platforms.) -// https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/ns-evntprov-_event_filter_descriptor -// The structure supplements the event provider, level, and keyword data that -// determines which events are reported and traced. The structure gives the -// event provider greater control over the selection of events for reporting -// and tracing. -// TODO: EventFilterDescriptor and EventData (defined below) are the same. -struct EventFilterDescriptor -{ - // A pointer to the filter data. - ULONGLONG Ptr; - - // The size of the filter data, in bytes. The maximum size is 1024 bytes. - ULONG Size; - - // The type of filter data. The type is application-defined. An event - // controller that knows about the provider and knows details about the - // provider's events can use the Type field to send the provider an - // arbitrary set of data for use as enhancements to the filtering of events. - ULONG Type; -}; - -// Define the event pipe callback to match the ETW callback signature. -typedef void (*EventPipeCallback)( - LPCGUID SourceID, - ULONG IsEnabled, - UCHAR Level, - ULONGLONG MatchAnyKeywords, - ULONGLONG MatchAllKeywords, - EventFilterDescriptor *FilterData, - void *CallbackContext); - -struct EventData -{ - UINT64 Ptr; - unsigned int Size; - unsigned int Reserved; -}; - -class EventPipeEventPayload -{ -private: - BYTE *m_pData; - EventData *m_pEventData; - unsigned int m_eventDataCount; - unsigned int m_size; - bool m_allocatedData; - - // If the data is stored only as an array of EventData objects, create a flat buffer and copy into it - void Flatten(); - -public: - // Build this payload with a flat buffer inside - EventPipeEventPayload(BYTE *pData, unsigned int length) : - m_pData(pData), - m_pEventData(nullptr), - m_eventDataCount(0), - m_size(length), - m_allocatedData(false) - { - LIMITED_METHOD_CONTRACT; - } - - // Build this payload to contain an array of EventData objects - EventPipeEventPayload(EventData *pEventData, unsigned int eventDataCount); - - // If a buffer was allocated internally, delete it - ~EventPipeEventPayload(); - - // Copy the data (whether flat or array of objects) into a flat buffer at pDst - // Assumes that pDst points to an appropriatly sized buffer - void CopyData(BYTE *pDst); - - // Get the flat formatted data in this payload - // This method will allocate a buffer if it does not already contain flattened data - // This method will return NULL on OOM if a buffer needed to be allocated - BYTE *GetFlatData(); - - // Return true is the data is stored in a flat buffer - bool IsFlattened() const - { - LIMITED_METHOD_CONTRACT; - return m_pData != NULL; - } - - // The the size of buffer needed to contain the stored data - unsigned int GetSize() const - { - LIMITED_METHOD_CONTRACT; - return m_size; - } - - EventData *GetEventDataArray() const - { - LIMITED_METHOD_CONTRACT; - return m_pEventData; - } -}; - -class StackContents -{ -private: - const static unsigned int MAX_STACK_DEPTH = 100; - - // Array of IP values from a stack crawl. - // Top of stack is at index 0. - UINT_PTR m_stackFrames[MAX_STACK_DEPTH]; - -#ifdef _DEBUG - // Parallel array of MethodDesc pointers. - // Used for debug-only stack printing. - MethodDesc *m_methods[MAX_STACK_DEPTH]; -#endif // _DEBUG - - // The next available slot in StackFrames. - unsigned int m_nextAvailableFrame; - -public: - StackContents() - { - LIMITED_METHOD_CONTRACT; - Reset(); - } - - void CopyTo(StackContents *pDest) - { - LIMITED_METHOD_CONTRACT; - _ASSERTE(pDest != NULL); - - memcpy_s(pDest->m_stackFrames, MAX_STACK_DEPTH * sizeof(UINT_PTR), m_stackFrames, sizeof(UINT_PTR) * m_nextAvailableFrame); -#ifdef _DEBUG - memcpy_s(pDest->m_methods, MAX_STACK_DEPTH * sizeof(MethodDesc *), m_methods, sizeof(MethodDesc *) * m_nextAvailableFrame); -#endif - pDest->m_nextAvailableFrame = m_nextAvailableFrame; - } - - void Reset() - { - LIMITED_METHOD_CONTRACT; - m_nextAvailableFrame = 0; - } - - bool IsEmpty() - { - LIMITED_METHOD_CONTRACT; - return (m_nextAvailableFrame == 0); - } - - unsigned int GetLength() - { - LIMITED_METHOD_CONTRACT; - return m_nextAvailableFrame; - } - - UINT_PTR GetIP(unsigned int frameIndex) - { - LIMITED_METHOD_CONTRACT; - _ASSERTE(frameIndex < MAX_STACK_DEPTH); - - if (frameIndex >= MAX_STACK_DEPTH) - { - return 0; - } - - return m_stackFrames[frameIndex]; - } - -#ifdef _DEBUG - MethodDesc *GetMethod(unsigned int frameIndex) - { - LIMITED_METHOD_CONTRACT; - _ASSERTE(frameIndex < MAX_STACK_DEPTH); - - if (frameIndex >= MAX_STACK_DEPTH) - { - return NULL; - } - - return m_methods[frameIndex]; - } -#endif // _DEBUG - - void Append(UINT_PTR controlPC, MethodDesc *pMethod) - { - LIMITED_METHOD_CONTRACT; - - if (m_nextAvailableFrame < MAX_STACK_DEPTH) - { - m_stackFrames[m_nextAvailableFrame] = controlPC; -#ifdef _DEBUG - m_methods[m_nextAvailableFrame] = pMethod; -#endif - m_nextAvailableFrame++; - } - } - - BYTE *GetPointer() const - { - LIMITED_METHOD_CONTRACT; - return (BYTE *)m_stackFrames; - } - - unsigned int GetSize() const - { - LIMITED_METHOD_CONTRACT; - return (m_nextAvailableFrame * sizeof(UINT_PTR)); - } -}; +class EventPipeEventPayload; +struct EventData; typedef uint64_t EventPipeSessionID; -struct EventPipeProviderCallbackData -{ - LPCWSTR pFilterData; - EventPipeCallback pCallbackFunction; - bool enabled; - INT64 keywords; - EventPipeEventLevel providerLevel; - void* pCallbackData; -}; - -class EventPipeProviderCallbackDataQueue -{ -public: - void Enqueue(EventPipeProviderCallbackData* pEventPipeProviderCallbackData); - bool TryDequeue(EventPipeProviderCallbackData* pEventPipeProviderCallbackData); - -private: - SList<SListElem<EventPipeProviderCallbackData>> list; -}; - class EventPipe { // Declare friends. @@ -414,49 +176,7 @@ private: static EventPipeEventSource *s_pEventSource; }; -struct EventPipeProviderConfiguration -{ -private: - LPCWSTR m_pProviderName = nullptr; - UINT64 m_keywords = 0; - UINT32 m_loggingLevel = 0; - LPCWSTR m_pFilterData = nullptr; - -public: - EventPipeProviderConfiguration() = default; - - EventPipeProviderConfiguration(LPCWSTR pProviderName, UINT64 keywords, UINT32 loggingLevel, LPCWSTR pFilterData) : - m_pProviderName(pProviderName), - m_keywords(keywords), - m_loggingLevel(loggingLevel), - m_pFilterData(pFilterData) - { - } - - LPCWSTR GetProviderName() const - { - LIMITED_METHOD_CONTRACT; - return m_pProviderName; - } - - UINT64 GetKeywords() const - { - LIMITED_METHOD_CONTRACT; - return m_keywords; - } - - UINT32 GetLevel() const - { - LIMITED_METHOD_CONTRACT; - return m_loggingLevel; - } - - LPCWSTR GetFilterData() const - { - LIMITED_METHOD_CONTRACT; - return m_pFilterData; - } -}; +static_assert(EventPipe::MaxNumberOfSessions == 64, "Maximum number of EventPipe sessions is not 64."); #endif // FEATURE_PERFTRACING diff --git a/src/vm/eventpipebuffer.cpp b/src/vm/eventpipebuffer.cpp index dbcea681a3..913fc57fcb 100644 --- a/src/vm/eventpipebuffer.cpp +++ b/src/vm/eventpipebuffer.cpp @@ -5,6 +5,7 @@ #include "common.h" #include "eventpipe.h" #include "eventpipeeventinstance.h" +#include "eventpipeeventpayload.h" #include "eventpipebuffer.h" #include "eventpipebuffermanager.h" @@ -89,7 +90,7 @@ bool EventPipeBuffer::WriteEvent(Thread *pThread, EventPipeSession &session, Eve EventPipeEventInstance *pInstance = new (m_pCurrent) EventPipeEventInstance( event, - (pThread == NULL) ? + (pThread == NULL) ? #ifdef FEATURE_PAL ::PAL_GetCurrentOSThreadId() #else diff --git a/src/vm/eventpipebuffermanager.cpp b/src/vm/eventpipebuffermanager.cpp index 1b76c168ab..e8f4c5a051 100644 --- a/src/vm/eventpipebuffermanager.cpp +++ b/src/vm/eventpipebuffermanager.cpp @@ -7,6 +7,7 @@ #include "eventpipeconfiguration.h" #include "eventpipebuffer.h" #include "eventpipebuffermanager.h" +#include "eventpipeeventpayload.h" #include "eventpipefile.h" #include "eventpipethread.h" #include "eventpipesession.h" diff --git a/src/vm/eventpipecommontypes.cpp b/src/vm/eventpipecommontypes.cpp new file mode 100644 index 0000000000..06382e506e --- /dev/null +++ b/src/vm/eventpipecommontypes.cpp @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#include "common.h" +#include "eventpipecommontypes.h" + +#ifdef FEATURE_PERFTRACING + +void EventPipeProviderCallbackDataQueue::Enqueue(EventPipeProviderCallbackData *pEventPipeProviderCallbackData) +{ + SListElem<EventPipeProviderCallbackData> *listnode = new SListElem<EventPipeProviderCallbackData>(); // throws + listnode->m_Value = *pEventPipeProviderCallbackData; + list.InsertTail(listnode); +} + +bool EventPipeProviderCallbackDataQueue::TryDequeue(EventPipeProviderCallbackData *pEventPipeProviderCallbackData) +{ + if (list.IsEmpty()) + return false; + + SListElem<EventPipeProviderCallbackData> *listnode = list.RemoveHead(); + *pEventPipeProviderCallbackData = listnode->m_Value; + delete listnode; + return true; +} + +#endif // FEATURE_PERFTRACING diff --git a/src/vm/eventpipecommontypes.h b/src/vm/eventpipecommontypes.h new file mode 100644 index 0000000000..fe08196312 --- /dev/null +++ b/src/vm/eventpipecommontypes.h @@ -0,0 +1,120 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef __EVENTPIPE_PROVIDERCALLBACKDATA_H__ +#define __EVENTPIPE_PROVIDERCALLBACKDATA_H__ + +#ifdef FEATURE_PERFTRACING + +#include "common.h" + +enum class EventPipeEventLevel +{ + LogAlways, + Critical, + Error, + Warning, + Informational, + Verbose +}; + +struct EventPipeProviderConfiguration +{ +private: + LPCWSTR m_pProviderName = nullptr; + UINT64 m_keywords = 0; + UINT32 m_loggingLevel = 0; + LPCWSTR m_pFilterData = nullptr; + +public: + EventPipeProviderConfiguration() = default; + + EventPipeProviderConfiguration(LPCWSTR pProviderName, UINT64 keywords, UINT32 loggingLevel, LPCWSTR pFilterData) : + m_pProviderName(pProviderName), + m_keywords(keywords), + m_loggingLevel(loggingLevel), + m_pFilterData(pFilterData) + { + } + + LPCWSTR GetProviderName() const + { + LIMITED_METHOD_CONTRACT; + return m_pProviderName; + } + + UINT64 GetKeywords() const + { + LIMITED_METHOD_CONTRACT; + return m_keywords; + } + + UINT32 GetLevel() const + { + LIMITED_METHOD_CONTRACT; + return m_loggingLevel; + } + + LPCWSTR GetFilterData() const + { + LIMITED_METHOD_CONTRACT; + return m_pFilterData; + } +}; + +// EVENT_FILTER_DESCRIPTOR (This type does not exist on non-Windows platforms.) +// https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/ns-evntprov-_event_filter_descriptor +// The structure supplements the event provider, level, and keyword data that +// determines which events are reported and traced. The structure gives the +// event provider greater control over the selection of events for reporting +// and tracing. +// TODO: EventFilterDescriptor and EventData (defined below) are the same. +struct EventFilterDescriptor +{ + // A pointer to the filter data. + ULONGLONG Ptr; + + // The size of the filter data, in bytes. The maximum size is 1024 bytes. + ULONG Size; + + // The type of filter data. The type is application-defined. An event + // controller that knows about the provider and knows details about the + // provider's events can use the Type field to send the provider an + // arbitrary set of data for use as enhancements to the filtering of events. + ULONG Type; +}; + +// Define the event pipe callback to match the ETW callback signature. +typedef void (*EventPipeCallback)( + LPCGUID SourceID, + ULONG IsEnabled, + UCHAR Level, + ULONGLONG MatchAnyKeywords, + ULONGLONG MatchAllKeywords, + EventFilterDescriptor *FilterData, + void *CallbackContext); + +struct EventPipeProviderCallbackData +{ + LPCWSTR pFilterData; + EventPipeCallback pCallbackFunction; + bool enabled; + INT64 keywords; + EventPipeEventLevel providerLevel; + void* pCallbackData; +}; + +class EventPipeProviderCallbackDataQueue +{ +public: + void Enqueue(EventPipeProviderCallbackData* pEventPipeProviderCallbackData); + bool TryDequeue(EventPipeProviderCallbackData* pEventPipeProviderCallbackData); + +private: + SList<SListElem<EventPipeProviderCallbackData>> list; +}; + +#endif // FEATURE_PERFTRACING + +#endif // __EVENTPIPE_PROVIDERCALLBACKDATA_H__ diff --git a/src/vm/eventpipeconfiguration.h b/src/vm/eventpipeconfiguration.h index 403b44b3ff..f97b78f99a 100644 --- a/src/vm/eventpipeconfiguration.h +++ b/src/vm/eventpipeconfiguration.h @@ -94,7 +94,7 @@ private: unsigned int GenerateSessionIndex() const { LIMITED_METHOD_CONTRACT; - _ASSERTE(EventPipe::MaxNumberOfSessions == 64); + uint64_t id = 1; for (unsigned int i = 0; i < 64; ++i, id <<= i) if ((m_activeSessions & id) == 0) diff --git a/src/vm/eventpipeeventpayload.cpp b/src/vm/eventpipeeventpayload.cpp new file mode 100644 index 0000000000..b9f6f9e30a --- /dev/null +++ b/src/vm/eventpipeeventpayload.cpp @@ -0,0 +1,132 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#include "common.h" +#include "eventpipeeventpayload.h" + +#ifdef FEATURE_PERFTRACING + +EventPipeEventPayload::EventPipeEventPayload(EventData *pEventData, unsigned int eventDataCount) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + MODE_ANY; + } + CONTRACTL_END; + + m_pData = NULL; + m_pEventData = pEventData; + m_eventDataCount = eventDataCount; + m_allocatedData = false; + + S_UINT32 tmp_size = S_UINT32(0); + for (unsigned int i = 0; i < m_eventDataCount; i++) + { + tmp_size += S_UINT32(m_pEventData[i].Size); + } + + if (tmp_size.IsOverflow()) + { + // If there is an overflow, drop the data and create an empty payload + m_pEventData = NULL; + m_eventDataCount = 0; + m_size = 0; + } + else + { + m_size = tmp_size.Value(); + } +} + +EventPipeEventPayload::~EventPipeEventPayload() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + MODE_ANY; + } + CONTRACTL_END; + + if (m_allocatedData && m_pData != NULL) + { + delete[] m_pData; + m_pData = NULL; + } +} + +void EventPipeEventPayload::Flatten() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + MODE_ANY; + } + CONTRACTL_END; + + if (m_size > 0) + { + if (!IsFlattened()) + { + BYTE *tmp_pData = new (nothrow) BYTE[m_size]; + if (tmp_pData != NULL) + { + m_allocatedData = true; + CopyData(tmp_pData); + m_pData = tmp_pData; + } + } + } +} + +void EventPipeEventPayload::CopyData(BYTE *pDst) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + MODE_ANY; + } + CONTRACTL_END; + + if (m_size > 0) + { + if (IsFlattened()) + { + memcpy(pDst, m_pData, m_size); + } + + else if (m_pEventData != NULL) + { + unsigned int offset = 0; + for (unsigned int i = 0; i < m_eventDataCount; i++) + { + memcpy(pDst + offset, (BYTE *)m_pEventData[i].Ptr, m_pEventData[i].Size); + offset += m_pEventData[i].Size; + } + } + } +} + +BYTE *EventPipeEventPayload::GetFlatData() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + MODE_ANY; + } + CONTRACTL_END; + + if (!IsFlattened()) + { + Flatten(); + } + return m_pData; +} + +#endif // FEATURE_PERFTRACING diff --git a/src/vm/eventpipeeventpayload.h b/src/vm/eventpipeeventpayload.h new file mode 100644 index 0000000000..0da1e81ab1 --- /dev/null +++ b/src/vm/eventpipeeventpayload.h @@ -0,0 +1,80 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef __EVENTPIPE_EVENTPAYLOAD_H__ +#define __EVENTPIPE_EVENTPAYLOAD_H__ + +#ifdef FEATURE_PERFTRACING +#include "common.h" + +struct EventData +{ + UINT64 Ptr; + unsigned int Size; + unsigned int Reserved; +}; + +class EventPipeEventPayload +{ +private: + BYTE *m_pData; + EventData *m_pEventData; + unsigned int m_eventDataCount; + unsigned int m_size; + bool m_allocatedData; + + // If the data is stored only as an array of EventData objects, create a flat buffer and copy into it + void Flatten(); + +public: + // Build this payload with a flat buffer inside + EventPipeEventPayload(BYTE *pData, unsigned int length) : + m_pData(pData), + m_pEventData(nullptr), + m_eventDataCount(0), + m_size(length), + m_allocatedData(false) + { + LIMITED_METHOD_CONTRACT; + } + + // Build this payload to contain an array of EventData objects + EventPipeEventPayload(EventData *pEventData, unsigned int eventDataCount); + + // If a buffer was allocated internally, delete it + ~EventPipeEventPayload(); + + // Copy the data (whether flat or array of objects) into a flat buffer at pDst + // Assumes that pDst points to an appropriatly sized buffer + void CopyData(BYTE *pDst); + + // Get the flat formatted data in this payload + // This method will allocate a buffer if it does not already contain flattened data + // This method will return NULL on OOM if a buffer needed to be allocated + BYTE *GetFlatData(); + + // Return true is the data is stored in a flat buffer + bool IsFlattened() const + { + LIMITED_METHOD_CONTRACT; + return m_pData != NULL; + } + + // The the size of buffer needed to contain the stored data + unsigned int GetSize() const + { + LIMITED_METHOD_CONTRACT; + return m_size; + } + + EventData *GetEventDataArray() const + { + LIMITED_METHOD_CONTRACT; + return m_pEventData; + } +}; + +#endif // FEATURE_PERFTRACING + +#endif // __EVENTPIPE_EVENTPAYLOAD_H__ diff --git a/src/vm/eventpipeeventsource.cpp b/src/vm/eventpipeeventsource.cpp index 8545631347..c67441d73f 100644 --- a/src/vm/eventpipeeventsource.cpp +++ b/src/vm/eventpipeeventsource.cpp @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. #include "common.h" +#include "eventpipeeventpayload.h" #include "eventpipeeventsource.h" #include "eventpipe.h" #include "eventpipeevent.h" diff --git a/src/vm/eventpipesession.cpp b/src/vm/eventpipesession.cpp index 83eee06e87..b91d9b1ee2 100644 --- a/src/vm/eventpipesession.cpp +++ b/src/vm/eventpipesession.cpp @@ -34,7 +34,6 @@ EventPipeSession::EventPipeSession( GC_TRIGGERS; MODE_PREEMPTIVE; PRECONDITION(index < EventPipe::MaxNumberOfSessions); - PRECONDITION(EventPipe::MaxNumberOfSessions == 64); // If MaxNumberOfSessions ever changed, fix the m_id calculation above PRECONDITION(format < EventPipeSerializationFormat::Count); PRECONDITION(circularBufferSizeInMB > 0); PRECONDITION(numProviders > 0 && pProviders != nullptr); diff --git a/src/vm/stackcontents.h b/src/vm/stackcontents.h new file mode 100644 index 0000000000..10e2ea0d30 --- /dev/null +++ b/src/vm/stackcontents.h @@ -0,0 +1,125 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef __STACKCONTENTS_H__ +#define __STACKCONTENTS_H__ + +#ifdef FEATURE_PERFTRACING +#include "common.h" + +class MethodDesc; + +class StackContents +{ +private: + const static unsigned int MAX_STACK_DEPTH = 100; + + // Array of IP values from a stack crawl. + // Top of stack is at index 0. + UINT_PTR m_stackFrames[MAX_STACK_DEPTH]; + +#ifdef _DEBUG + // Parallel array of MethodDesc pointers. + // Used for debug-only stack printing. + MethodDesc *m_methods[MAX_STACK_DEPTH]; +#endif // _DEBUG + + // The next available slot in StackFrames. + unsigned int m_nextAvailableFrame; + +public: + StackContents() + { + LIMITED_METHOD_CONTRACT; + Reset(); + } + + void CopyTo(StackContents *pDest) + { + LIMITED_METHOD_CONTRACT; + _ASSERTE(pDest != NULL); + + memcpy_s(pDest->m_stackFrames, MAX_STACK_DEPTH * sizeof(UINT_PTR), m_stackFrames, sizeof(UINT_PTR) * m_nextAvailableFrame); +#ifdef _DEBUG + memcpy_s(pDest->m_methods, MAX_STACK_DEPTH * sizeof(MethodDesc *), m_methods, sizeof(MethodDesc *) * m_nextAvailableFrame); +#endif + pDest->m_nextAvailableFrame = m_nextAvailableFrame; + } + + void Reset() + { + LIMITED_METHOD_CONTRACT; + m_nextAvailableFrame = 0; + } + + bool IsEmpty() + { + LIMITED_METHOD_CONTRACT; + return (m_nextAvailableFrame == 0); + } + + unsigned int GetLength() + { + LIMITED_METHOD_CONTRACT; + return m_nextAvailableFrame; + } + + UINT_PTR GetIP(unsigned int frameIndex) + { + LIMITED_METHOD_CONTRACT; + _ASSERTE(frameIndex < MAX_STACK_DEPTH); + + if (frameIndex >= MAX_STACK_DEPTH) + { + return 0; + } + + return m_stackFrames[frameIndex]; + } + +#ifdef _DEBUG + MethodDesc *GetMethod(unsigned int frameIndex) + { + LIMITED_METHOD_CONTRACT; + _ASSERTE(frameIndex < MAX_STACK_DEPTH); + + if (frameIndex >= MAX_STACK_DEPTH) + { + return NULL; + } + + return m_methods[frameIndex]; + } +#endif // _DEBUG + + void Append(UINT_PTR controlPC, MethodDesc *pMethod) + { + LIMITED_METHOD_CONTRACT; + + if (m_nextAvailableFrame < MAX_STACK_DEPTH) + { + m_stackFrames[m_nextAvailableFrame] = controlPC; +#ifdef _DEBUG + m_methods[m_nextAvailableFrame] = pMethod; +#endif + m_nextAvailableFrame++; + } + } + + BYTE *GetPointer() const + { + LIMITED_METHOD_CONTRACT; + return (BYTE *)m_stackFrames; + } + + unsigned int GetSize() const + { + LIMITED_METHOD_CONTRACT; + return (m_nextAvailableFrame * sizeof(UINT_PTR)); + } +}; + +#endif // FEATURE_PERFTRACING + +#endif // __STACKCONTENTS_H__ |