summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosé Rivero <jorive@microsoft.com>2019-06-14 13:47:04 -0700
committerGitHub <noreply@github.com>2019-06-14 13:47:04 -0700
commitfc29d38699b8e4ce619d669c2135548fe8abe730 (patch)
tree37f12f436470dc1710493a740903f0ee77e68168
parent54d82b2c1b385025ea84a9fb8c60caa76f371f34 (diff)
downloadcoreclr-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.txt5
-rw-r--r--src/vm/eventpipe.cpp141
-rw-r--r--src/vm/eventpipe.h290
-rw-r--r--src/vm/eventpipebuffer.cpp3
-rw-r--r--src/vm/eventpipebuffermanager.cpp1
-rw-r--r--src/vm/eventpipecommontypes.cpp28
-rw-r--r--src/vm/eventpipecommontypes.h120
-rw-r--r--src/vm/eventpipeconfiguration.h2
-rw-r--r--src/vm/eventpipeeventpayload.cpp132
-rw-r--r--src/vm/eventpipeeventpayload.h80
-rw-r--r--src/vm/eventpipeeventsource.cpp1
-rw-r--r--src/vm/eventpipesession.cpp1
-rw-r--r--src/vm/stackcontents.h125
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__