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); 47 void UpdateDuration(); 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 116 private: 117 // Disallow copy and assign 118 TraceWriter(const TraceWriter&) = delete; 119 void operator=(const TraceWriter&) = delete; 120 }; 121 122 class V8_PLATFORM_EXPORT TraceBufferChunk { 123 public: 124 explicit TraceBufferChunk(uint32_t seq); 125 126 void Reset(uint32_t new_seq); IsFull()127 bool IsFull() const { return next_free_ == kChunkSize; } 128 TraceObject* AddTraceEvent(size_t* event_index); GetEventAt(size_t index)129 TraceObject* GetEventAt(size_t index) { return &chunk_[index]; } 130 seq()131 uint32_t seq() const { return seq_; } size()132 size_t size() const { return next_free_; } 133 134 static const size_t kChunkSize = 64; 135 136 private: 137 size_t next_free_ = 0; 138 TraceObject chunk_[kChunkSize]; 139 uint32_t seq_; 140 141 // Disallow copy and assign 142 TraceBufferChunk(const TraceBufferChunk&) = delete; 143 void operator=(const TraceBufferChunk&) = delete; 144 }; 145 146 class V8_PLATFORM_EXPORT TraceBuffer { 147 public: TraceBuffer()148 TraceBuffer() {} ~TraceBuffer()149 virtual ~TraceBuffer() {} 150 151 virtual TraceObject* AddTraceEvent(uint64_t* handle) = 0; 152 virtual TraceObject* GetEventByHandle(uint64_t handle) = 0; 153 virtual bool Flush() = 0; 154 155 static const size_t kRingBufferChunks = 1024; 156 157 static TraceBuffer* CreateTraceBufferRingBuffer(size_t max_chunks, 158 TraceWriter* trace_writer); 159 160 private: 161 // Disallow copy and assign 162 TraceBuffer(const TraceBuffer&) = delete; 163 void operator=(const TraceBuffer&) = delete; 164 }; 165 166 // Options determines how the trace buffer stores data. 167 enum TraceRecordMode { 168 // Record until the trace buffer is full. 169 RECORD_UNTIL_FULL, 170 171 // Record until the user ends the trace. The trace buffer is a fixed size 172 // and we use it as a ring buffer during recording. 173 RECORD_CONTINUOUSLY, 174 175 // Record until the trace buffer is full, but with a huge buffer size. 176 RECORD_AS_MUCH_AS_POSSIBLE, 177 178 // Echo to console. Events are discarded. 179 ECHO_TO_CONSOLE, 180 }; 181 182 class V8_PLATFORM_EXPORT TraceConfig { 183 public: 184 typedef std::vector<std::string> StringList; 185 186 static TraceConfig* CreateDefaultTraceConfig(); 187 TraceConfig()188 TraceConfig() : enable_systrace_(false), enable_argument_filter_(false) {} GetTraceRecordMode()189 TraceRecordMode GetTraceRecordMode() const { return record_mode_; } IsSystraceEnabled()190 bool IsSystraceEnabled() const { return enable_systrace_; } IsArgumentFilterEnabled()191 bool IsArgumentFilterEnabled() const { return enable_argument_filter_; } 192 SetTraceRecordMode(TraceRecordMode mode)193 void SetTraceRecordMode(TraceRecordMode mode) { record_mode_ = mode; } EnableSystrace()194 void EnableSystrace() { enable_systrace_ = true; } EnableArgumentFilter()195 void EnableArgumentFilter() { enable_argument_filter_ = true; } 196 197 void AddIncludedCategory(const char* included_category); 198 199 bool IsCategoryGroupEnabled(const char* category_group) const; 200 201 private: 202 TraceRecordMode record_mode_; 203 bool enable_systrace_ : 1; 204 bool enable_argument_filter_ : 1; 205 StringList included_categories_; 206 207 // Disallow copy and assign 208 TraceConfig(const TraceConfig&) = delete; 209 void operator=(const TraceConfig&) = delete; 210 }; 211 212 class V8_PLATFORM_EXPORT TracingController { 213 public: 214 enum Mode { DISABLED = 0, RECORDING_MODE }; 215 216 // The pointer returned from GetCategoryGroupEnabledInternal() points to a 217 // value with zero or more of the following bits. Used in this class only. 218 // The TRACE_EVENT macros should only use the value as a bool. 219 // These values must be in sync with macro values in TraceEvent.h in Blink. 220 enum CategoryGroupEnabledFlags { 221 // Category group enabled for the recording mode. 222 ENABLED_FOR_RECORDING = 1 << 0, 223 // Category group enabled by SetEventCallbackEnabled(). 224 ENABLED_FOR_EVENT_CALLBACK = 1 << 2, 225 // Category group enabled to export events to ETW. 226 ENABLED_FOR_ETW_EXPORT = 1 << 3 227 }; 228 229 TracingController(); 230 ~TracingController(); 231 void Initialize(TraceBuffer* trace_buffer); 232 const uint8_t* GetCategoryGroupEnabled(const char* category_group); 233 static const char* GetCategoryGroupName(const uint8_t* category_enabled_flag); 234 uint64_t AddTraceEvent( 235 char phase, const uint8_t* category_enabled_flag, const char* name, 236 const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args, 237 const char** arg_names, const uint8_t* arg_types, 238 const uint64_t* arg_values, 239 std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables, 240 unsigned int flags); 241 void UpdateTraceEventDuration(const uint8_t* category_enabled_flag, 242 const char* name, uint64_t handle); 243 244 void StartTracing(TraceConfig* trace_config); 245 void StopTracing(); 246 247 void AddTraceStateObserver(Platform::TraceStateObserver* observer); 248 void RemoveTraceStateObserver(Platform::TraceStateObserver* observer); 249 250 private: 251 const uint8_t* GetCategoryGroupEnabledInternal(const char* category_group); 252 void UpdateCategoryGroupEnabledFlag(size_t category_index); 253 void UpdateCategoryGroupEnabledFlags(); 254 255 std::unique_ptr<TraceBuffer> trace_buffer_; 256 std::unique_ptr<TraceConfig> trace_config_; 257 std::unique_ptr<base::Mutex> mutex_; 258 std::unordered_set<Platform::TraceStateObserver*> observers_; 259 Mode mode_ = DISABLED; 260 261 // Disallow copy and assign 262 TracingController(const TracingController&) = delete; 263 void operator=(const TracingController&) = delete; 264 }; 265 266 } // namespace tracing 267 } // namespace platform 268 } // namespace v8 269 270 #endif // V8_LIBPLATFORM_V8_TRACING_H_ 271