v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
etw-jit-metadata-win.h
Go to the documentation of this file.
1// Copyright 2020 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_DIAGNOSTICS_ETW_JIT_METADATA_WIN_H_
6#define V8_DIAGNOSTICS_ETW_JIT_METADATA_WIN_H_
7
8#include <string>
9#include <utility>
10
12
13namespace v8 {
14namespace internal {
15namespace ETWJITInterface {
16
17/*******************************************************************************
18Helper templates to create tightly packed metadata of the format expected by the
19ETW data structures.
20*******************************************************************************/
21
22// All "manifest-free" events should go to channel 11 by default
23const uint8_t kManifestFreeChannel = 11;
24
25// Number of metadescriptors. Use this to find out the index of the field
26// descriptors in the descriptors_array
27const uint8_t kMetaDescriptorsCount = 2;
28
29// ETW control code for capturing state
30// https://learn.microsoft.com/en-us/windows/win32/api/evntprov/nc-evntprov-penablecallback
31constexpr uint32_t kEtwControlDisable = 0;
32constexpr uint32_t kEtwControlEnable = 1;
33constexpr uint32_t kEtwControlCaptureState = 2;
34
35// Filtering keyword to find JScript stack-walking events
36constexpr uint64_t kJScriptRuntimeKeyword = 1;
37
38constexpr uint16_t kSourceLoadEventID = 41;
39constexpr uint16_t kMethodLoadEventID = 9;
40constexpr uint16_t kSourceDCStartEventID = 39;
41constexpr uint16_t kMethodDCStartEventID = 5;
42
43constexpr unsigned char kTraceLevel = TRACE_LEVEL_INFORMATION;
44
45// Structure to treat a string literal, or char[], as a constexpr byte sequence
46template <size_t count>
47struct str_bytes {
48 template <std::size_t... idx>
49 constexpr str_bytes(char const (&str)[count], std::index_sequence<idx...>)
50 : bytes{str[idx]...}, size(count) {}
51
52 // Concatenate two str_bytes
53 template <std::size_t count1, std::size_t count2, std::size_t... idx1,
54 std::size_t... idx2>
55 constexpr str_bytes(const str_bytes<count1>& s1, std::index_sequence<idx1...>,
56 const str_bytes<count2>& s2, std::index_sequence<idx2...>)
57 : bytes{s1.bytes[idx1]..., s2.bytes[idx2]...}, size(count) {}
58
59 char bytes[count]; // NOLINT
60 size_t size;
61};
62
63// Specialization for 0 (base case when joining fields)
64template <>
65struct str_bytes<0> {
66 constexpr str_bytes() : bytes{}, size(0) {}
67 char bytes[1]; // MSVC doesn't like an array of 0 bytes
68 size_t size;
69};
70
71// Factory function to simplify creating a str_bytes from a string literal
72template <size_t count, typename idx = std::make_index_sequence<count>>
73constexpr auto MakeStrBytes(char const (&s)[count]) {
74 return str_bytes<count>{s, idx{}};
75}
76
77// Concatenates two str_bytes into one
78template <std::size_t size1, std::size_t size2>
79constexpr auto JoinBytes(const str_bytes<size1>& str1,
80 const str_bytes<size2>& str2) {
81 auto idx1 = std::make_index_sequence<size1>();
82 auto idx2 = std::make_index_sequence<size2>();
83 return str_bytes<size1 + size2>{str1, idx1, str2, idx2};
84}
85
86// Creates an str_bytes which is the field name suffixed with the field type
87template <size_t count>
88constexpr auto Field(char const (&s)[count], uint8_t type) {
89 auto field_name = MakeStrBytes(s);
90 const char type_arr[1] = {static_cast<char>(type)};
91 return JoinBytes(field_name, MakeStrBytes(type_arr));
92}
93
94// Creates the ETW event metadata header, which consists of a uint16_t
95// representing the total size, and a tag byte (always 0x00 currently).
96constexpr auto Header(size_t size) {
97 size_t total_size = size + 3; // total_size includes the 2 byte size + tag
98 const char header_bytes[3] = {static_cast<char>(total_size & 0xFF),
99 static_cast<char>(total_size >> 8 & 0xFF),
100 '\0'};
101 return MakeStrBytes(header_bytes);
102}
103
104// The JoinFields implementations below are a set of overloads for constructing
105// a str_bytes representing the concatenated fields from a parameter pack.
106
107// Empty case needed for events with no fields.
108constexpr auto JoinFields() { return str_bytes<0>{}; }
109
110// Only one field, or base case when multiple fields.
111template <typename T1>
112constexpr auto JoinFields(T1 field) {
113 return field;
114}
115
116// Join two or more fields together.
117template <typename T1, typename T2, typename... Ts>
118constexpr auto JoinFields(T1 field1, T2 field2, Ts... args) {
119 auto bytes = JoinBytes(field1, field2);
120 return JoinFields(bytes, args...);
121}
122
123// Creates a constexpr char[] representing the fields for an ETW event.
124// Declare the variable as `constexpr static auto` and provide the event name,
125// followed by a series of `Field` invocations for each field.
126//
127// Example:
128// constexpr static auto event_fields = EventFields("my1stEvent",
129// Field("MyIntVal", kTypeInt32),
130// Field("MyMsg", kTypeAnsiStr),
131// Field("Address", kTypePointer));
132template <std::size_t count, typename... Ts>
133constexpr auto EventFields(char const (&name)[count], Ts... field_args) {
134 auto name_bytes = MakeStrBytes(name);
135 auto fields = JoinFields(field_args...);
136 auto data = JoinBytes(name_bytes, fields);
137
138 auto header = Header(data.size);
139 return JoinBytes(header, data);
140}
141
142constexpr auto EventMetadata(uint16_t id, uint64_t keywords) {
143 return EVENT_DESCRIPTOR{id,
144 0, // Version
146 kTraceLevel, // Level
147 EVENT_TRACE_TYPE_START, // Opcode
148 0, // Task
149 keywords};
150}
151
152void SetMetaDescriptors(EVENT_DATA_DESCRIPTOR* data_descriptor,
153 UINT16 const UNALIGNED* traits, const void* metadata,
154 size_t size);
155
156// Base case, no fields left to set
157inline void SetFieldDescriptors(EVENT_DATA_DESCRIPTOR* data_descriptors) {}
158
159// Need to declare all the base overloads in advance, as ther bodies may become
160// a point of reference for any of the overloads, and only overloads that have
161// been seen will be candidates.
162template <typename... Ts>
163void SetFieldDescriptors(EVENT_DATA_DESCRIPTOR* data_descriptors,
164 const std::wstring& value, const Ts&... rest);
165template <typename... Ts>
166void SetFieldDescriptors(EVENT_DATA_DESCRIPTOR* data_descriptors,
167 const std::string& value, const Ts&... rest);
168template <typename... Ts>
169void SetFieldDescriptors(EVENT_DATA_DESCRIPTOR* data_descriptors,
170 const char* value, const Ts&... rest);
171
172// One or more fields to set
173template <typename T, typename... Ts>
174void SetFieldDescriptors(EVENT_DATA_DESCRIPTOR* data_descriptors,
175 const T& value, const Ts&... rest) {
176 EventDataDescCreate(data_descriptors, &value, sizeof(value));
177 SetFieldDescriptors(++data_descriptors, rest...);
178}
179
180// Specialize for strings
181template <typename... Ts>
182void SetFieldDescriptors(EVENT_DATA_DESCRIPTOR* data_descriptors,
183 const std::wstring& value, const Ts&... rest) {
184 EventDataDescCreate(data_descriptors, value.data(),
185 static_cast<ULONG>(value.size() * 2 + 2));
186 SetFieldDescriptors(++data_descriptors, rest...);
187}
188
189template <typename... Ts>
190void SetFieldDescriptors(EVENT_DATA_DESCRIPTOR* data_descriptors,
191 const std::string& value, const Ts&... rest) {
192 EventDataDescCreate(data_descriptors, value.data(),
193 static_cast<ULONG>(value.size() + 1));
194 SetFieldDescriptors(++data_descriptors, rest...);
195}
196
197template <typename... Ts>
198void SetFieldDescriptors(EVENT_DATA_DESCRIPTOR* data_descriptors,
199 const char* value, const Ts&... rest) {
200 ULONG size = static_cast<ULONG>(strlen(value) + 1);
201 EventDataDescCreate(data_descriptors, value, size);
202 SetFieldDescriptors(++data_descriptors, rest...);
203}
204
205// This function does the actual writing of the event via the Win32 API
206inline ULONG LogEvent(uint64_t regHandle,
207 const EVENT_DESCRIPTOR* event_descriptor,
208 EVENT_DATA_DESCRIPTOR* data_descriptor,
209 ULONG desc_count) {
210 if (regHandle == 0) return ERROR_SUCCESS;
211 return EventWriteTransfer(regHandle, event_descriptor, NULL /* ActivityId */,
212 NULL /* RelatedActivityId */, desc_count,
213 data_descriptor);
214}
215
216// This template is called by the provider implementation
217template <typename T, typename... Fs>
218void LogEventData(const TraceLoggingHProvider provider,
219 const EVENT_DESCRIPTOR* event_descriptor, T* meta,
220 const Fs&... fields) {
221 const size_t descriptor_count = sizeof...(fields) + kMetaDescriptorsCount;
222 EVENT_DATA_DESCRIPTOR descriptors[sizeof...(fields) + kMetaDescriptorsCount];
223
224 SetMetaDescriptors(descriptors, provider->ProviderMetadataPtr, meta->bytes,
225 meta->size);
226
227 EVENT_DATA_DESCRIPTOR* data_descriptors = descriptors + kMetaDescriptorsCount;
228 SetFieldDescriptors(data_descriptors, fields...);
229
230 LogEvent(provider->RegHandle, event_descriptor, descriptors,
231 descriptor_count);
232}
233
234} // namespace ETWJITInterface
235} // namespace internal
236} // namespace v8
237
238#endif // V8_DIAGNOSTICS_ETW_JIT_METADATA_WIN_H_
#define T
uint32_t count
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
int s
Definition mul-fft.cc:297
constexpr unsigned char kTraceLevel
void LogEventData(const TraceLoggingHProvider provider, const EVENT_DESCRIPTOR *event_descriptor, T *meta, const Fs &... fields)
constexpr auto Field(char const (&s)[count], uint8_t type)
void SetMetaDescriptors(EVENT_DATA_DESCRIPTOR *data_descriptor, UINT16 const UNALIGNED *traits, const void *metadata, size_t size)
constexpr uint64_t kJScriptRuntimeKeyword
constexpr auto JoinBytes(const str_bytes< size1 > &str1, const str_bytes< size2 > &str2)
constexpr auto EventMetadata(uint16_t id, uint64_t keywords)
ULONG LogEvent(uint64_t regHandle, const EVENT_DESCRIPTOR *event_descriptor, EVENT_DATA_DESCRIPTOR *data_descriptor, ULONG desc_count)
constexpr uint32_t kEtwControlCaptureState
constexpr auto MakeStrBytes(char const (&s)[count])
void SetFieldDescriptors(EVENT_DATA_DESCRIPTOR *data_descriptors)
constexpr auto Header(size_t size)
constexpr auto EventFields(char const (&name)[count], Ts... field_args)
constexpr str_bytes(char const (&str)[count], std::index_sequence< idx... >)
constexpr str_bytes(const str_bytes< count1 > &s1, std::index_sequence< idx1... >, const str_bytes< count2 > &s2, std::index_sequence< idx2... >)
#define T1(name, string, precedence)
Definition token.cc:28
#define T2(name, string, precedence)
Definition token.cc:30
wasm::ValueType type