Where Online Learning is simpler!
The C and C++ Include Header Files
cat -n /usr/include/nodejs/src/tracing/trace_event.h
1 // Copyright 2015 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 SRC_TRACING_TRACE_EVENT_H_ 6 #define SRC_TRACING_TRACE_EVENT_H_ 7 8 #include "v8-platform.h" 9 #include "tracing/agent.h" 10 #include "trace_event_common.h" 11 #include <atomic> 12 13 // This header file defines implementation details of how the trace macros in 14 // trace_event_common.h collect and store trace events. Anything not 15 // implementation-specific should go in trace_macros_common.h instead of here. 16 17 18 // The pointer returned from GetCategoryGroupEnabled() points to a 19 // value with zero or more of the following bits. Used in this class only. 20 // The TRACE_EVENT macros should only use the value as a bool. 21 // These values must be in sync with macro values in trace_log.h in 22 // chromium. 23 enum CategoryGroupEnabledFlags { 24 // Category group enabled for the recording mode. 25 kEnabledForRecording_CategoryGroupEnabledFlags = 1 << 0, 26 // Category group enabled by SetEventCallbackEnabled(). 27 kEnabledForEventCallback_CategoryGroupEnabledFlags = 1 << 2, 28 // Category group enabled to export events to ETW. 29 kEnabledForETWExport_CategoryGroupEnabledFlags = 1 << 3, 30 }; 31 32 // By default, const char* argument values are assumed to have long-lived scope 33 // and will not be copied. Use this macro to force a const char* to be copied. 34 #define TRACE_STR_COPY(str) node::tracing::TraceStringWithCopy(str) 35 36 // By default, uint64 ID argument values are not mangled with the Process ID in 37 // TRACE_EVENT_ASYNC macros. Use this macro to force Process ID mangling. 38 #define TRACE_ID_MANGLE(id) node::tracing::TraceID::ForceMangle(id) 39 40 // By default, pointers are mangled with the Process ID in TRACE_EVENT_ASYNC 41 // macros. Use this macro to prevent Process ID mangling. 42 #define TRACE_ID_DONT_MANGLE(id) node::tracing::TraceID::DontMangle(id) 43 44 // By default, trace IDs are eventually converted to a single 64-bit number. Use 45 // this macro to add a scope string. 46 #define TRACE_ID_WITH_SCOPE(scope, id) \ 47 trace_event_internal::TraceID::WithScope(scope, id) 48 49 #define INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE() \ 50 *INTERNAL_TRACE_EVENT_UID(category_group_enabled) & \ 51 (kEnabledForRecording_CategoryGroupEnabledFlags | \ 52 kEnabledForEventCallback_CategoryGroupEnabledFlags) 53 54 // The following macro has no implementation, but it needs to exist since 55 // it gets called from scoped trace events. It cannot call UNIMPLEMENTED() 56 // since an empty implementation is a valid one. 57 #define INTERNAL_TRACE_MEMORY(category, name) 58 59 //////////////////////////////////////////////////////////////////////////////// 60 // Implementation specific tracing API definitions. 61 62 // Get a pointer to the enabled state of the given trace category. Only 63 // long-lived literal strings should be given as the category group. The 64 // returned pointer can be held permanently in a local static for example. If 65 // the unsigned char is non-zero, tracing is enabled. If tracing is enabled, 66 // TRACE_EVENT_API_ADD_TRACE_EVENT can be called. It's OK if tracing is disabled 67 // between the load of the tracing state and the call to 68 // TRACE_EVENT_API_ADD_TRACE_EVENT, because this flag only provides an early out 69 // for best performance when tracing is disabled. 70 // const uint8_t* 71 // TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(const char* category_group) 72 #define TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED \ 73 node::tracing::TraceEventHelper::GetCategoryGroupEnabled 74 75 // Get the number of times traces have been recorded. This is used to implement 76 // the TRACE_EVENT_IS_NEW_TRACE facility. 77 // unsigned int TRACE_EVENT_API_GET_NUM_TRACES_RECORDED() 78 #define TRACE_EVENT_API_GET_NUM_TRACES_RECORDED UNIMPLEMENTED() 79 80 // Add a trace event to the platform tracing system. 81 // uint64_t TRACE_EVENT_API_ADD_TRACE_EVENT( 82 // char phase, 83 // const uint8_t* category_group_enabled, 84 // const char* name, 85 // const char* scope, 86 // uint64_t id, 87 // uint64_t bind_id, 88 // int num_args, 89 // const char** arg_names, 90 // const uint8_t* arg_types, 91 // const uint64_t* arg_values, 92 // unsigned int flags) 93 #define TRACE_EVENT_API_ADD_TRACE_EVENT node::tracing::AddTraceEventImpl 94 95 // Add a trace event to the platform tracing system. 96 // uint64_t TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_TIMESTAMP( 97 // char phase, 98 // const uint8_t* category_group_enabled, 99 // const char* name, 100 // const char* scope, 101 // uint64_t id, 102 // uint64_t bind_id, 103 // int num_args, 104 // const char** arg_names, 105 // const uint8_t* arg_types, 106 // const uint64_t* arg_values, 107 // unsigned int flags, 108 // int64_t timestamp) 109 #define TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_TIMESTAMP \ 110 node::tracing::AddTraceEventWithTimestampImpl 111 112 // Set the duration field of a COMPLETE trace event. 113 // void TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION( 114 // const uint8_t* category_group_enabled, 115 // const char* name, 116 // uint64_t id) 117 #define TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION \ 118 if (auto controller = \ 119 node::tracing::TraceEventHelper::GetTracingController()) \ 120 controller->UpdateTraceEventDuration 121 122 // Adds a metadata event to the trace log. The |AppendValueAsTraceFormat| method 123 // on the convertable value will be called at flush time. 124 // TRACE_EVENT_API_ADD_METADATA_EVENT( 125 // const unsigned char* category_group_enabled, 126 // const char* event_name, 127 // const char* arg_name, 128 // std::unique_ptr<ConvertableToTraceFormat> arg_value) 129 #define TRACE_EVENT_API_ADD_METADATA_EVENT node::tracing::AddMetadataEvent 130 131 // Defines atomic operations used internally by the tracing system. 132 #define TRACE_EVENT_API_ATOMIC_WORD std::atomic<intptr_t> 133 #define TRACE_EVENT_API_ATOMIC_WORD_VALUE intptr_t 134 #define TRACE_EVENT_API_ATOMIC_LOAD(var) (var).load() 135 #define TRACE_EVENT_API_ATOMIC_STORE(var, value) (var).store(value) 136 137 //////////////////////////////////////////////////////////////////////////////// 138 139 // Implementation detail: trace event macros create temporary variables 140 // to keep instrumentation overhead low. These macros give each temporary 141 // variable a unique name based on the line number to prevent name collisions. 142 #define INTERNAL_TRACE_EVENT_UID3(a, b) trace_event_unique_##a##b 143 #define INTERNAL_TRACE_EVENT_UID2(a, b) INTERNAL_TRACE_EVENT_UID3(a, b) 144 #define INTERNAL_TRACE_EVENT_UID(name_prefix) \ 145 INTERNAL_TRACE_EVENT_UID2(name_prefix, __LINE__) 146 147 // Implementation detail: internal macro to create static category. 148 // No barriers are needed, because this code is designed to operate safely 149 // even when the unsigned char* points to garbage data (which may be the case 150 // on processors without cache coherency). 151 // TODO(fmeawad): This implementation contradicts that we can have a different 152 // configuration for each isolate, 153 // https://code.google.com/p/v8/issues/detail?id=4563 154 #define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO_CUSTOM_VARIABLES( \ 155 category_group, atomic, category_group_enabled) \ 156 category_group_enabled = \ 157 reinterpret_cast<const uint8_t*>(TRACE_EVENT_API_ATOMIC_LOAD(atomic)); \ 158 if (!category_group_enabled) { \ 159 category_group_enabled = \ 160 TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category_group); \ 161 TRACE_EVENT_API_ATOMIC_STORE( \ 162 atomic, reinterpret_cast<TRACE_EVENT_API_ATOMIC_WORD_VALUE>( \ 163 category_group_enabled)); \ 164 } 165 166 #define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group) \ 167 static TRACE_EVENT_API_ATOMIC_WORD INTERNAL_TRACE_EVENT_UID(atomic) {0}; \ 168 const uint8_t* INTERNAL_TRACE_EVENT_UID(category_group_enabled); \ 169 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO_CUSTOM_VARIABLES( \ 170 category_group, INTERNAL_TRACE_EVENT_UID(atomic), \ 171 INTERNAL_TRACE_EVENT_UID(category_group_enabled)); 172 173 // Implementation detail: internal macro to create static category and add 174 // event if the category is enabled. 175 #define INTERNAL_TRACE_EVENT_ADD(phase, category_group, name, flags, ...) \ 176 do { \ 177 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ 178 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \ 179 node::tracing::AddTraceEvent( \ 180 phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \ 181 node::tracing::kGlobalScope, node::tracing::kNoId, \ 182 node::tracing::kNoId, flags, ##__VA_ARGS__); \ 183 } \ 184 } while (0) 185 186 // Implementation detail: internal macro to create static category and add begin 187 // event if the category is enabled. Also adds the end event when the scope 188 // ends. 189 #define INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, ...) \ 190 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ 191 node::tracing::ScopedTracer INTERNAL_TRACE_EVENT_UID(tracer); \ 192 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \ 193 uint64_t h = node::tracing::AddTraceEvent( \ 194 TRACE_EVENT_PHASE_COMPLETE, \ 195 INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \ 196 node::tracing::kGlobalScope, node::tracing::kNoId, \ 197 node::tracing::kNoId, TRACE_EVENT_FLAG_NONE, ##__VA_ARGS__); \ 198 INTERNAL_TRACE_EVENT_UID(tracer) \ 199 .Initialize(INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \ 200 h); \ 201 } 202 203 #define INTERNAL_TRACE_EVENT_ADD_SCOPED_WITH_FLOW(category_group, name, \ 204 bind_id, flow_flags, ...) \ 205 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ 206 node::tracing::ScopedTracer INTERNAL_TRACE_EVENT_UID(tracer); \ 207 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \ 208 unsigned int trace_event_flags = flow_flags; \ 209 node::tracing::TraceID trace_event_bind_id(bind_id, \ 210 &trace_event_flags); \ 211 uint64_t h = node::tracing::AddTraceEvent( \ 212 TRACE_EVENT_PHASE_COMPLETE, \ 213 INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \ 214 node::tracing::kGlobalScope, node::tracing::kNoId, \ 215 trace_event_bind_id.raw_id(), trace_event_flags, ##__VA_ARGS__); \ 216 INTERNAL_TRACE_EVENT_UID(tracer) \ 217 .Initialize(INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \ 218 h); \ 219 } 220 221 // Implementation detail: internal macro to create static category and add 222 // event if the category is enabled. 223 #define INTERNAL_TRACE_EVENT_ADD_WITH_ID(phase, category_group, name, id, \ 224 flags, ...) \ 225 do { \ 226 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ 227 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \ 228 unsigned int trace_event_flags = flags | TRACE_EVENT_FLAG_HAS_ID; \ 229 node::tracing::TraceID trace_event_trace_id(id, \ 230 &trace_event_flags); \ 231 node::tracing::AddTraceEvent( \ 232 phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \ 233 trace_event_trace_id.scope(), trace_event_trace_id.raw_id(), \ 234 node::tracing::kNoId, trace_event_flags, ##__VA_ARGS__); \ 235 } \ 236 } while (0) 237 238 // Adds a trace event with a given timestamp. 239 #define INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP(phase, category_group, name, \ 240 timestamp, flags, ...) \ 241 do { \ 242 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ 243 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \ 244 node::tracing::AddTraceEventWithTimestamp( \ 245 phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \ 246 node::tracing::kGlobalScope, node::tracing::kNoId, \ 247 node::tracing::kNoId, flags, timestamp, ##__VA_ARGS__); \ 248 } \ 249 } while (0) 250 251 // Adds a trace event with a given id and timestamp. Not Implemented. 252 #define INTERNAL_TRACE_EVENT_ADD_WITH_ID_AND_TIMESTAMP( \ 253 phase, category_group, name, id, timestamp, flags, ...) \ 254 UNIMPLEMENTED() 255 256 // Adds a trace event with a given id, thread_id, and timestamp. Not 257 // Implemented. 258 #define INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \ 259 phase, category_group, name, id, thread_id, timestamp, flags, ...) \ 260 do { \ 261 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ 262 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \ 263 unsigned int trace_event_flags = flags | TRACE_EVENT_FLAG_HAS_ID; \ 264 node::tracing::TraceID trace_event_trace_id(id, \ 265 &trace_event_flags); \ 266 node::tracing::AddTraceEventWithTimestamp( \ 267 phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \ 268 trace_event_trace_id.scope(), trace_event_trace_id.raw_id(), \ 269 node::tracing::kNoId, trace_event_flags, timestamp, ##__VA_ARGS__);\ 270 } \ 271 } while (0) 272 273 #define INTERNAL_TRACE_EVENT_METADATA_ADD(category_group, name, ...) \ 274 do { \ 275 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category_group); \ 276 if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED_FOR_RECORDING_MODE()) { \ 277 TRACE_EVENT_API_ADD_METADATA_EVENT( \ 278 INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \ 279 ##__VA_ARGS__); \ 280 } \ 281 } while(0) 282 283 // Enter and leave a context based on the current scope. 284 #define INTERNAL_TRACE_EVENT_SCOPED_CONTEXT(category_group, name, context) \ 285 struct INTERNAL_TRACE_EVENT_UID(ScopedContext) { \ 286 public: \ 287 INTERNAL_TRACE_EVENT_UID(ScopedContext)(uint64_t cid) : cid_(cid) { \ 288 TRACE_EVENT_ENTER_CONTEXT(category_group, name, cid_); \ 289 } \ 290 ~INTERNAL_TRACE_EVENT_UID(ScopedContext)() { \ 291 TRACE_EVENT_LEAVE_CONTEXT(category_group, name, cid_); \ 292 } \ 293 \ 294 private: \ 295 /* Local class friendly DISALLOW_COPY_AND_ASSIGN */ \ 296 INTERNAL_TRACE_EVENT_UID(ScopedContext) \ 297 (const INTERNAL_TRACE_EVENT_UID(ScopedContext)&) {} \ 298 void operator=(const INTERNAL_TRACE_EVENT_UID(ScopedContext)&) {} \ 299 uint64_t cid_; \ 300 }; \ 301 INTERNAL_TRACE_EVENT_UID(ScopedContext) \ 302 INTERNAL_TRACE_EVENT_UID(scoped_context)(context); 303 304 namespace node { 305 namespace tracing { 306 307 // Specify these values when the corresponding argument of AddTraceEvent is not 308 // used. 309 const int kZeroNumArgs = 0; 310 const decltype(nullptr) kGlobalScope = nullptr; 311 const uint64_t kNoId = 0; 312 313 class TraceEventHelper { 314 public: 315 static v8::TracingController* GetTracingController(); 316 static void SetTracingController(v8::TracingController* controller); 317 318 static Agent* GetAgent(); 319 static void SetAgent(Agent* agent); 320 321 static inline const uint8_t* GetCategoryGroupEnabled(const char* group) { 322 v8::TracingController* controller = GetTracingController(); 323 static const uint8_t disabled = 0; 324 if (controller == nullptr) [[unlikely]] { 325 return &disabled; 326 } 327 return controller->GetCategoryGroupEnabled(group); 328 } 329 }; 330 331 // TraceID encapsulates an ID that can either be an integer or pointer. Pointers 332 // are by default mangled with the Process ID so that they are unlikely to 333 // collide when the same pointer is used on different processes. 334 class TraceID { 335 public: 336 class WithScope { 337 public: 338 WithScope(const char* scope, uint64_t raw_id) 339 : scope_(scope), raw_id_(raw_id) {} 340 uint64_t raw_id() const { return raw_id_; } 341 const char* scope() const { return scope_; } 342 343 private: 344 const char* scope_ = nullptr; 345 uint64_t raw_id_; 346 }; 347 348 class DontMangle { 349 public: 350 explicit DontMangle(const void* raw_id) 351 : raw_id_(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(raw_id))) {} 352 explicit DontMangle(uint64_t raw_id) : raw_id_(raw_id) {} 353 explicit DontMangle(unsigned int raw_id) : raw_id_(raw_id) {} 354 explicit DontMangle(uint16_t raw_id) : raw_id_(raw_id) {} 355 explicit DontMangle(unsigned char raw_id) : raw_id_(raw_id) {} 356 explicit DontMangle(int64_t raw_id) 357 : raw_id_(static_cast<uint64_t>(raw_id)) {} 358 explicit DontMangle(int raw_id) : raw_id_(static_cast<uint64_t>(raw_id)) {} 359 explicit DontMangle(int16_t raw_id) 360 : raw_id_(static_cast<uint64_t>(raw_id)) {} 361 explicit DontMangle(signed char raw_id) 362 : raw_id_(static_cast<uint64_t>(raw_id)) {} 363 explicit DontMangle(WithScope scoped_id) 364 : scope_(scoped_id.scope()), raw_id_(scoped_id.raw_id()) {} 365 const char* scope() const { return scope_; } 366 uint64_t raw_id() const { return raw_id_; } 367 368 private: 369 const char* scope_ = nullptr; 370 uint64_t raw_id_; 371 }; 372 373 class ForceMangle { 374 public: 375 explicit ForceMangle(uint64_t raw_id) : raw_id_(raw_id) {} 376 explicit ForceMangle(unsigned int raw_id) : raw_id_(raw_id) {} 377 explicit ForceMangle(uint16_t raw_id) : raw_id_(raw_id) {} 378 explicit ForceMangle(unsigned char raw_id) : raw_id_(raw_id) {} 379 explicit ForceMangle(int64_t raw_id) 380 : raw_id_(static_cast<uint64_t>(raw_id)) {} 381 explicit ForceMangle(int raw_id) : raw_id_(static_cast<uint64_t>(raw_id)) {} 382 explicit ForceMangle(int16_t raw_id) 383 : raw_id_(static_cast<uint64_t>(raw_id)) {} 384 explicit ForceMangle(signed char raw_id) 385 : raw_id_(static_cast<uint64_t>(raw_id)) {} 386 uint64_t raw_id() const { return raw_id_; } 387 388 private: 389 uint64_t raw_id_; 390 }; 391 392 TraceID(const void* raw_id, unsigned int* flags) 393 : raw_id_(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(raw_id))) { 394 *flags |= TRACE_EVENT_FLAG_MANGLE_ID; 395 } 396 TraceID(ForceMangle raw_id, unsigned int* flags) : raw_id_(raw_id.raw_id()) { 397 *flags |= TRACE_EVENT_FLAG_MANGLE_ID; 398 } 399 TraceID(DontMangle maybe_scoped_id, unsigned int* flags) 400 : scope_(maybe_scoped_id.scope()), raw_id_(maybe_scoped_id.raw_id()) {} 401 TraceID(uint64_t raw_id, unsigned int* flags) : raw_id_(raw_id) { 402 (void)flags; 403 } 404 TraceID(unsigned int raw_id, unsigned int* flags) : raw_id_(raw_id) { 405 (void)flags; 406 } 407 TraceID(uint16_t raw_id, unsigned int* flags) : raw_id_(raw_id) { 408 (void)flags; 409 } 410 TraceID(unsigned char raw_id, unsigned int* flags) : raw_id_(raw_id) { 411 (void)flags; 412 } 413 TraceID(int64_t raw_id, unsigned int* flags) 414 : raw_id_(static_cast<uint64_t>(raw_id)) { 415 (void)flags; 416 } 417 TraceID(int raw_id, unsigned int* flags) 418 : raw_id_(static_cast<uint64_t>(raw_id)) { 419 (void)flags; 420 } 421 TraceID(int16_t raw_id, unsigned int* flags) 422 : raw_id_(static_cast<uint64_t>(raw_id)) { 423 (void)flags; 424 } 425 TraceID(signed char raw_id, unsigned int* flags) 426 : raw_id_(static_cast<uint64_t>(raw_id)) { 427 (void)flags; 428 } 429 TraceID(WithScope scoped_id, unsigned int* flags) 430 : scope_(scoped_id.scope()), raw_id_(scoped_id.raw_id()) {} 431 432 uint64_t raw_id() const { return raw_id_; } 433 const char* scope() const { return scope_; } 434 435 private: 436 const char* scope_ = nullptr; 437 uint64_t raw_id_; 438 }; 439 440 // Simple union to store various types as uint64_t. 441 union TraceValueUnion { 442 bool as_bool; 443 uint64_t as_uint; 444 int64_t as_int; 445 double as_double; 446 const void* as_pointer; 447 const char* as_string; 448 }; 449 450 // Simple container for const char* that should be copied instead of retained. 451 class TraceStringWithCopy { 452 public: 453 explicit TraceStringWithCopy(const char* str) : str_(str) {} 454 operator const char*() const { return str_; } 455 456 private: 457 const char* str_; 458 }; 459 460 static inline uint64_t AddTraceEventImpl( 461 char phase, const uint8_t* category_group_enabled, const char* name, 462 const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args, 463 const char** arg_names, const uint8_t* arg_types, 464 const uint64_t* arg_values, unsigned int flags) { 465 std::unique_ptr<v8::ConvertableToTraceFormat> arg_convertibles[2]; 466 if (num_args > 0 && arg_types[0] == TRACE_VALUE_TYPE_CONVERTABLE) { 467 arg_convertibles[0].reset(reinterpret_cast<v8::ConvertableToTraceFormat*>( 468 static_cast<intptr_t>(arg_values[0]))); 469 } 470 if (num_args > 1 && arg_types[1] == TRACE_VALUE_TYPE_CONVERTABLE) { 471 arg_convertibles[1].reset(reinterpret_cast<v8::ConvertableToTraceFormat*>( 472 static_cast<intptr_t>(arg_values[1]))); 473 } 474 // DCHECK(num_args, 2); 475 v8::TracingController* controller = 476 node::tracing::TraceEventHelper::GetTracingController(); 477 if (controller == nullptr) return 0; 478 return controller->AddTraceEvent(phase, category_group_enabled, name, scope, id, 479 bind_id, num_args, arg_names, arg_types, 480 arg_values, arg_convertibles, flags); 481 } 482 483 static V8_INLINE uint64_t AddTraceEventWithTimestampImpl( 484 char phase, const uint8_t* category_group_enabled, const char* name, 485 const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args, 486 const char** arg_names, const uint8_t* arg_types, 487 const uint64_t* arg_values, unsigned int flags, int64_t timestamp) { 488 std::unique_ptr<v8::ConvertableToTraceFormat> arg_convertibles[2]; 489 if (num_args > 0 && arg_types[0] == TRACE_VALUE_TYPE_CONVERTABLE) { 490 arg_convertibles[0].reset(reinterpret_cast<v8::ConvertableToTraceFormat*>( 491 static_cast<intptr_t>(arg_values[0]))); 492 } 493 if (num_args > 1 && arg_types[1] == TRACE_VALUE_TYPE_CONVERTABLE) { 494 arg_convertibles[1].reset(reinterpret_cast<v8::ConvertableToTraceFormat*>( 495 static_cast<intptr_t>(arg_values[1]))); 496 } 497 // DCHECK_LE(num_args, 2); 498 v8::TracingController* controller = 499 node::tracing::TraceEventHelper::GetTracingController(); 500 if (controller == nullptr) return 0; 501 return controller->AddTraceEventWithTimestamp( 502 phase, category_group_enabled, name, scope, id, bind_id, num_args, 503 arg_names, arg_types, arg_values, arg_convertibles, flags, timestamp); 504 } 505 506 static V8_INLINE void AddMetadataEventImpl( 507 const uint8_t* category_group_enabled, const char* name, int32_t num_args, 508 const char** arg_names, const uint8_t* arg_types, 509 const uint64_t* arg_values, unsigned int flags) { 510 std::unique_ptr<v8::ConvertableToTraceFormat> arg_convertibles[2]; 511 if (num_args > 0 && arg_types[0] == TRACE_VALUE_TYPE_CONVERTABLE) { 512 arg_convertibles[0].reset(reinterpret_cast<v8::ConvertableToTraceFormat*>( 513 static_cast<intptr_t>(arg_values[0]))); 514 } 515 if (num_args > 1 && arg_types[1] == TRACE_VALUE_TYPE_CONVERTABLE) { 516 arg_convertibles[1].reset(reinterpret_cast<v8::ConvertableToTraceFormat*>( 517 static_cast<intptr_t>(arg_values[1]))); 518 } 519 node::tracing::Agent* agent = 520 node::tracing::TraceEventHelper::GetAgent(); 521 if (agent == nullptr) return; 522 return agent->GetTracingController()->AddMetadataEvent( 523 category_group_enabled, name, num_args, arg_names, arg_types, arg_values, 524 arg_convertibles, flags); 525 } 526 527 // Define SetTraceValue for each allowed type. It stores the type and 528 // value in the return arguments. This allows this API to avoid declaring any 529 // structures so that it is portable to third_party libraries. 530 #define INTERNAL_DECLARE_SET_TRACE_VALUE(actual_type, union_member, \ 531 value_type_id) \ 532 static inline void SetTraceValue(actual_type arg, unsigned char* type, \ 533 uint64_t* value) { \ 534 TraceValueUnion type_value; \ 535 type_value.union_member = arg; \ 536 *type = value_type_id; \ 537 *value = type_value.as_uint; \ 538 } 539 // Simpler form for int types that can be safely casted. 540 #define INTERNAL_DECLARE_SET_TRACE_VALUE_INT(actual_type, value_type_id) \ 541 static inline void SetTraceValue(actual_type arg, unsigned char* type, \ 542 uint64_t* value) { \ 543 *type = value_type_id; \ 544 *value = static_cast<uint64_t>(arg); \ 545 } 546 547 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(uint64_t, TRACE_VALUE_TYPE_UINT) 548 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned int, TRACE_VALUE_TYPE_UINT) 549 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(uint16_t, TRACE_VALUE_TYPE_UINT) 550 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned char, TRACE_VALUE_TYPE_UINT) 551 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int64_t, TRACE_VALUE_TYPE_INT) 552 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int, TRACE_VALUE_TYPE_INT) 553 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int16_t, TRACE_VALUE_TYPE_INT) 554 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(signed char, TRACE_VALUE_TYPE_INT) 555 INTERNAL_DECLARE_SET_TRACE_VALUE(bool, as_bool, TRACE_VALUE_TYPE_BOOL) 556 INTERNAL_DECLARE_SET_TRACE_VALUE(double, as_double, TRACE_VALUE_TYPE_DOUBLE) 557 INTERNAL_DECLARE_SET_TRACE_VALUE(const void*, as_pointer, 558 TRACE_VALUE_TYPE_POINTER) 559 INTERNAL_DECLARE_SET_TRACE_VALUE(const char*, as_string, 560 TRACE_VALUE_TYPE_STRING) 561 INTERNAL_DECLARE_SET_TRACE_VALUE(const TraceStringWithCopy&, as_string, 562 TRACE_VALUE_TYPE_COPY_STRING) 563 564 #undef INTERNAL_DECLARE_SET_TRACE_VALUE 565 #undef INTERNAL_DECLARE_SET_TRACE_VALUE_INT 566 567 static inline void SetTraceValue(v8::ConvertableToTraceFormat* convertable_value, 568 unsigned char* type, uint64_t* value) { 569 *type = TRACE_VALUE_TYPE_CONVERTABLE; 570 *value = static_cast<uint64_t>(reinterpret_cast<intptr_t>(convertable_value)); 571 } 572 573 template <typename T> 574 static inline typename std::enable_if< 575 std::is_convertible<T*, v8::ConvertableToTraceFormat*>::value>::type 576 SetTraceValue(std::unique_ptr<T> ptr, unsigned char* type, uint64_t* value) { 577 SetTraceValue(ptr.release(), type, value); 578 } 579 580 // These AddTraceEvent template 581 // function is defined here instead of in the macro, because the arg_values 582 // could be temporary objects, such as std::string. In order to store 583 // pointers to the internal c_str and pass through to the tracing API, 584 // the arg_values must live throughout these procedures. 585 586 static inline uint64_t AddTraceEvent(char phase, 587 const uint8_t* category_group_enabled, 588 const char* name, const char* scope, 589 uint64_t id, uint64_t bind_id, 590 unsigned int flags) { 591 return TRACE_EVENT_API_ADD_TRACE_EVENT(phase, category_group_enabled, name, 592 scope, id, bind_id, kZeroNumArgs, 593 nullptr, nullptr, nullptr, flags); 594 } 595 596 template <class ARG1_TYPE> 597 static inline uint64_t AddTraceEvent( 598 char phase, const uint8_t* category_group_enabled, const char* name, 599 const char* scope, uint64_t id, uint64_t bind_id, unsigned int flags, 600 const char* arg1_name, ARG1_TYPE&& arg1_val) { 601 const int num_args = 1; 602 uint8_t arg_type; 603 uint64_t arg_value; 604 SetTraceValue(std::forward<ARG1_TYPE>(arg1_val), &arg_type, &arg_value); 605 return TRACE_EVENT_API_ADD_TRACE_EVENT( 606 phase, category_group_enabled, name, scope, id, bind_id, num_args, 607 &arg1_name, &arg_type, &arg_value, flags); 608 } 609 610 template <class ARG1_TYPE, class ARG2_TYPE> 611 static inline uint64_t AddTraceEvent( 612 char phase, const uint8_t* category_group_enabled, const char* name, 613 const char* scope, uint64_t id, uint64_t bind_id, unsigned int flags, 614 const char* arg1_name, ARG1_TYPE&& arg1_val, const char* arg2_name, 615 ARG2_TYPE&& arg2_val) { 616 const int num_args = 2; 617 const char* arg_names[2] = {arg1_name, arg2_name}; 618 unsigned char arg_types[2]; 619 uint64_t arg_values[2]; 620 SetTraceValue(std::forward<ARG1_TYPE>(arg1_val), &arg_types[0], 621 &arg_values[0]); 622 SetTraceValue(std::forward<ARG2_TYPE>(arg2_val), &arg_types[1], 623 &arg_values[1]); 624 return TRACE_EVENT_API_ADD_TRACE_EVENT( 625 phase, category_group_enabled, name, scope, id, bind_id, num_args, 626 arg_names, arg_types, arg_values, flags); 627 } 628 629 static V8_INLINE uint64_t AddTraceEventWithTimestamp( 630 char phase, const uint8_t* category_group_enabled, const char* name, 631 const char* scope, uint64_t id, uint64_t bind_id, unsigned int flags, 632 int64_t timestamp) { 633 return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_TIMESTAMP( 634 phase, category_group_enabled, name, scope, id, bind_id, kZeroNumArgs, 635 nullptr, nullptr, nullptr, flags, timestamp); 636 } 637 638 template <class ARG1_TYPE> 639 static V8_INLINE uint64_t AddTraceEventWithTimestamp( 640 char phase, const uint8_t* category_group_enabled, const char* name, 641 const char* scope, uint64_t id, uint64_t bind_id, unsigned int flags, 642 int64_t timestamp, const char* arg1_name, ARG1_TYPE&& arg1_val) { 643 const int num_args = 1; 644 uint8_t arg_type; 645 uint64_t arg_value; 646 SetTraceValue(std::forward<ARG1_TYPE>(arg1_val), &arg_type, &arg_value); 647 return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_TIMESTAMP( 648 phase, category_group_enabled, name, scope, id, bind_id, num_args, 649 &arg1_name, &arg_type, &arg_value, flags, timestamp); 650 } 651 652 template <class ARG1_TYPE, class ARG2_TYPE> 653 static V8_INLINE uint64_t AddTraceEventWithTimestamp( 654 char phase, const uint8_t* category_group_enabled, const char* name, 655 const char* scope, uint64_t id, uint64_t bind_id, unsigned int flags, 656 int64_t timestamp, const char* arg1_name, ARG1_TYPE&& arg1_val, 657 const char* arg2_name, ARG2_TYPE&& arg2_val) { 658 const int num_args = 2; 659 const char* arg_names[2] = {arg1_name, arg2_name}; 660 unsigned char arg_types[2]; 661 uint64_t arg_values[2]; 662 SetTraceValue(std::forward<ARG1_TYPE>(arg1_val), &arg_types[0], 663 &arg_values[0]); 664 SetTraceValue(std::forward<ARG2_TYPE>(arg2_val), &arg_types[1], 665 &arg_values[1]); 666 return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_TIMESTAMP( 667 phase, category_group_enabled, name, scope, id, bind_id, num_args, 668 arg_names, arg_types, arg_values, flags, timestamp); 669 } 670 671 template <class ARG1_TYPE> 672 static V8_INLINE void AddMetadataEvent( 673 const uint8_t* category_group_enabled, const char* name, 674 const char* arg1_name, ARG1_TYPE&& arg1_val) { 675 const int num_args = 1; 676 uint8_t arg_type; 677 uint64_t arg_value; 678 SetTraceValue(std::forward<ARG1_TYPE>(arg1_val), &arg_type, &arg_value); 679 AddMetadataEventImpl( 680 category_group_enabled, name, num_args, &arg1_name, &arg_type, &arg_value, 681 TRACE_EVENT_FLAG_NONE); 682 } 683 684 // Used by TRACE_EVENTx macros. Do not use directly. 685 class ScopedTracer { 686 public: 687 // Note: members of data_ intentionally left uninitialized. See Initialize. 688 ScopedTracer() : p_data_(nullptr) {} 689 690 ~ScopedTracer() { 691 if (p_data_ && *data_.category_group_enabled) 692 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION( 693 data_.category_group_enabled, data_.name, data_.event_handle); 694 } 695 696 void Initialize(const uint8_t* category_group_enabled, const char* name, 697 uint64_t event_handle) { 698 data_.category_group_enabled = category_group_enabled; 699 data_.name = name; 700 data_.event_handle = event_handle; 701 p_data_ = &data_; 702 } 703 704 private: 705 // This Data struct workaround is to avoid initializing all the members 706 // in Data during construction of this object, since this object is always 707 // constructed, even when tracing is disabled. If the members of Data were 708 // members of this class instead, compiler warnings occur about potential 709 // uninitialized accesses. 710 struct Data { 711 const uint8_t* category_group_enabled; 712 const char* name; 713 uint64_t event_handle; 714 }; 715 Data* p_data_; 716 Data data_; 717 }; 718 719 } // namespace tracing 720 } // namespace node 721 722 #endif // SRC_TRACING_TRACE_EVENT_H_