1 // Copyright 2016 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_LIBPLATFORM_V8_TRACING_H_ 6 #define V8_LIBPLATFORM_V8_TRACING_H_ 7 8 #include <fstream> 9 #include <memory> 10 #include <unordered_set> 11 #include <vector> 12 13 #include "libplatform/libplatform-export.h" 14 #include "v8-platform.h" // NOLINT(build/include) 15 16 namespace v8 { 17 18 namespace base { 19 class Mutex; 20 } // namespace base 21 22 namespace platform { 23 namespace tracing { 24 25 const int kTraceMaxNumArgs = 2; 26 27 class V8_PLATFORM_EXPORT TraceObject { 28 public: 29 union ArgValue { 30 bool as_bool; 31 uint64_t as_uint; 32 int64_t as_int; 33 double as_double; 34 const void* as_pointer; 35 const char* as_string; 36 }; 37 TraceObject()38 TraceObject() {} 39 ~TraceObject(); 40 void Initialize( 41 char phase, const uint8_t* category_enabled_flag, const char* name, 42 const char* scope, uint64_t id, uint64_t bind_id, int num_args, 43 const char** arg_names, const uint8_t* arg_types, 44 const uint64_t* arg_values, 45 std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables, 46 unsigned int flags, int64_t timestamp, int64_t cpu_timestamp); 47 void UpdateDuration(int64_t timestamp, int64_t cpu_timestamp); 48 void InitializeForTesting( 49 char phase, const uint8_t* category_enabled_flag, const char* name, 50 const char* scope, uint64_t id, uint64_t bind_id, int num_args, 51 const char** arg_names, const uint8_t* arg_types, 52 const uint64_t* arg_values, 53 std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables, 54 unsigned int flags, int pid, int tid, int64_t ts, int64_t tts, 55 uint64_t duration, uint64_t cpu_duration); 56 pid()57 int pid() const { return pid_; } tid()58 int tid() const { return tid_; } phase()59 char phase() const { return phase_; } category_enabled_flag()60 const uint8_t* category_enabled_flag() const { 61 return category_enabled_flag_; 62 } name()63 const char* name() const { return name_; } scope()64 const char* scope() const { return scope_; } id()65 uint64_t id() const { return id_; } bind_id()66 uint64_t bind_id() const { return bind_id_; } num_args()67 int num_args() const { return num_args_; } arg_names()68 const char** arg_names() { return arg_names_; } arg_types()69 uint8_t* arg_types() { return arg_types_; } arg_values()70 ArgValue* arg_values() { return arg_values_; } arg_convertables()71 std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables() { 72 return arg_convertables_; 73 } flags()74 unsigned int flags() const { return flags_; } ts()75 int64_t ts() { return ts_; } tts()76 int64_t tts() { return tts_; } duration()77 uint64_t duration() { return duration_; } cpu_duration()78 uint64_t cpu_duration() { return cpu_duration_; } 79 80 private: 81 int pid_; 82 int tid_; 83 char phase_; 84 const char* name_; 85 const char* scope_; 86 const uint8_t* category_enabled_flag_; 87 uint64_t id_; 88 uint64_t bind_id_; 89 int num_args_ = 0; 90 const char* arg_names_[kTraceMaxNumArgs]; 91 uint8_t arg_types_[kTraceMaxNumArgs]; 92 ArgValue arg_values_[kTraceMaxNumArgs]; 93 std::unique_ptr<v8::ConvertableToTraceFormat> 94 arg_convertables_[kTraceMaxNumArgs]; 95 char* parameter_copy_storage_ = nullptr; 96 unsigned int flags_; 97 int64_t ts_; 98 int64_t tts_; 99 uint64_t duration_; 100 uint64_t cpu_duration_; 101 102 // Disallow copy and assign 103 TraceObject(const TraceObject&) = delete; 104 void operator=(const TraceObject&) = delete; 105 }; 106 107 class V8_PLATFORM_EXPORT TraceWriter { 108 public: TraceWriter()109 TraceWriter() {} ~TraceWriter()110 virtual ~TraceWriter() {} 111 virtual void AppendTraceEvent(TraceObject* trace_event) = 0; 112 virtual void Flush() = 0; 113 114 static TraceWriter* CreateJSONTraceWriter(std::ostream& stream); 115 static TraceWriter* CreateJSONTraceWriter(std::ostream& stream, 116 const std::string& tag); 117 118 private: 119 // Disallow copy and assign 120 TraceWriter(const TraceWriter&) = delete; 121 void operator=(const TraceWriter&) = delete; 122 }; 123 124 class V8_PLATFORM_EXPORT TraceBufferChunk { 125 public: 126 explicit TraceBufferChunk(uint32_t seq); 127 128 void Reset(uint32_t new_seq); IsFull()129 bool IsFull() const { return next_free_ == kChunkSize; } 130 TraceObject* AddTraceEvent(size_t* event_index); GetEventAt(size_t index)131 TraceObject* GetEventAt(size_t index) { return &chunk_[index]; } 132 seq()133 uint32_t seq() const { return seq_; } size()134 size_t size() const { return next_free_; } 135 136 static const size_t kChunkSize = 64; 137 138 private: 139 size_t next_free_ = 0; 140 TraceObject chunk_[kChunkSize]; 141 uint32_t seq_; 142 143 // Disallow copy and assign 144 TraceBufferChunk(const TraceBufferChunk&) = delete; 145 void operator=(const TraceBufferChunk&) = delete; 146 }; 147 148 class V8_PLATFORM_EXPORT TraceBuffer { 149 public: TraceBuffer()150 TraceBuffer() {} ~TraceBuffer()151 virtual ~TraceBuffer() {} 152 153 virtual TraceObject* AddTraceEvent(uint64_t* handle) = 0; 154 virtual TraceObject* GetEventByHandle(uint64_t handle) = 0; 155 virtual bool Flush() = 0; 156 157 static const size_t kRingBufferChunks = 1024; 158 159 static TraceBuffer* CreateTraceBufferRingBuffer(size_t max_chunks, 160 TraceWriter* trace_writer); 161 162 private: 163 // Disallow copy and assign 164 TraceBuffer(const TraceBuffer&) = delete; 165 void operator=(const TraceBuffer&) = delete; 166 }; 167 168 // Options determines how the trace buffer stores data. 169 enum TraceRecordMode { 170 // Record until the trace buffer is full. 171 RECORD_UNTIL_FULL, 172 173 // Record until the user ends the trace. The trace buffer is a fixed size 174 // and we use it as a ring buffer during recording. 175 RECORD_CONTINUOUSLY, 176 177 // Record until the trace buffer is full, but with a huge buffer size. 178 RECORD_AS_MUCH_AS_POSSIBLE, 179 180 // Echo to console. Events are discarded. 181 ECHO_TO_CONSOLE, 182 }; 183 184 class V8_PLATFORM_EXPORT TraceConfig { 185 public: 186 typedef std::vector<std::string> StringList; 187 188 static TraceConfig* CreateDefaultTraceConfig(); 189 TraceConfig()190 TraceConfig() : enable_systrace_(false), enable_argument_filter_(false) {} GetTraceRecordMode()191 TraceRecordMode GetTraceRecordMode() const { return record_mode_; } IsSystraceEnabled()192 bool IsSystraceEnabled() const { return enable_systrace_; } IsArgumentFilterEnabled()193 bool IsArgumentFilterEnabled() const { return enable_argument_filter_; } 194 SetTraceRecordMode(TraceRecordMode mode)195 void SetTraceRecordMode(TraceRecordMode mode) { record_mode_ = mode; } EnableSystrace()196 void EnableSystrace() { enable_systrace_ = true; } EnableArgumentFilter()197 void EnableArgumentFilter() { enable_argument_filter_ = true; } 198 199 void AddIncludedCategory(const char* included_category); 200 201 bool IsCategoryGroupEnabled(const char* category_group) const; 202 203 private: 204 TraceRecordMode record_mode_; 205 bool enable_systrace_ : 1; 206 bool enable_argument_filter_ : 1; 207 StringList included_categories_; 208 209 // Disallow copy and assign 210 TraceConfig(const TraceConfig&) = delete; 211 void operator=(const TraceConfig&) = delete; 212 }; 213 214 #if defined(_MSC_VER) 215 #define V8_PLATFORM_NON_EXPORTED_BASE(code) \ 216 __pragma(warning(suppress : 4275)) code 217 #else 218 #define V8_PLATFORM_NON_EXPORTED_BASE(code) code 219 #endif // defined(_MSC_VER) 220 221 class V8_PLATFORM_EXPORT TracingController V8_PLATFORM_NON_EXPORTED_BASE(v8::TracingController)222 : public V8_PLATFORM_NON_EXPORTED_BASE(v8::TracingController) { 223 public: 224 enum Mode { DISABLED = 0, RECORDING_MODE }; 225 226 // The pointer returned from GetCategoryGroupEnabledInternal() points to a 227 // value with zero or more of the following bits. Used in this class only. 228 // The TRACE_EVENT macros should only use the value as a bool. 229 // These values must be in sync with macro values in TraceEvent.h in Blink. 230 enum CategoryGroupEnabledFlags { 231 // Category group enabled for the recording mode. 232 ENABLED_FOR_RECORDING = 1 << 0, 233 // Category group enabled by SetEventCallbackEnabled(). 234 ENABLED_FOR_EVENT_CALLBACK = 1 << 2, 235 // Category group enabled to export events to ETW. 236 ENABLED_FOR_ETW_EXPORT = 1 << 3 237 }; 238 239 TracingController(); 240 ~TracingController() override; 241 void Initialize(TraceBuffer* trace_buffer); 242 243 // v8::TracingController implementation. 244 const uint8_t* GetCategoryGroupEnabled(const char* category_group) override; 245 uint64_t AddTraceEvent( 246 char phase, const uint8_t* category_enabled_flag, const char* name, 247 const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args, 248 const char** arg_names, const uint8_t* arg_types, 249 const uint64_t* arg_values, 250 std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables, 251 unsigned int flags) override; 252 uint64_t AddTraceEventWithTimestamp( 253 char phase, const uint8_t* category_enabled_flag, const char* name, 254 const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args, 255 const char** arg_names, const uint8_t* arg_types, 256 const uint64_t* arg_values, 257 std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables, 258 unsigned int flags, int64_t timestamp) override; 259 void UpdateTraceEventDuration(const uint8_t* category_enabled_flag, 260 const char* name, uint64_t handle) override; 261 void AddTraceStateObserver( 262 v8::TracingController::TraceStateObserver* observer) override; 263 void RemoveTraceStateObserver( 264 v8::TracingController::TraceStateObserver* observer) override; 265 266 void StartTracing(TraceConfig* trace_config); 267 void StopTracing(); 268 269 static const char* GetCategoryGroupName(const uint8_t* category_enabled_flag); 270 271 protected: 272 virtual int64_t CurrentTimestampMicroseconds(); 273 virtual int64_t CurrentCpuTimestampMicroseconds(); 274 275 private: 276 const uint8_t* GetCategoryGroupEnabledInternal(const char* category_group); 277 void UpdateCategoryGroupEnabledFlag(size_t category_index); 278 void UpdateCategoryGroupEnabledFlags(); 279 280 std::unique_ptr<TraceBuffer> trace_buffer_; 281 std::unique_ptr<TraceConfig> trace_config_; 282 std::unique_ptr<base::Mutex> mutex_; 283 std::unordered_set<v8::TracingController::TraceStateObserver*> observers_; 284 Mode mode_ = DISABLED; 285 286 // Disallow copy and assign 287 TracingController(const TracingController&) = delete; 288 void operator=(const TracingController&) = delete; 289 }; 290 291 #undef V8_PLATFORM_NON_EXPORTED_BASE 292 293 } // namespace tracing 294 } // namespace platform 295 } // namespace v8 296 297 #endif // V8_LIBPLATFORM_V8_TRACING_H_ 298