|
24 | 24 | #include <wtf/Assertions.h> |
25 | 25 | #include <wtf/SystemTracing.h> |
26 | 26 | #include <wtf/text/ASCIILiteral.h> |
| 27 | +#include <wtf/text/StringBuilder.h> |
| 28 | +#include <wtf/HexNumber.h> |
| 29 | +#include <wtf/StdLibExtras.h> |
27 | 30 |
|
| 31 | +#include <algorithm> |
28 | 32 | #include <cstdio> |
29 | 33 | #include <cstring> |
30 | 34 | #include <mutex> |
@@ -208,6 +212,117 @@ class SystemTracingFTrace { |
208 | 212 | } |
209 | 213 | } |
210 | 214 |
|
| 215 | + void addMark(const char phase, std::span<const char> name, const char* format, va_list args) WTF_ATTRIBUTE_PRINTF(4, 0) { |
| 216 | + // "<phase>|<pid>|<name>[|<args>]" |
| 217 | + Vector<char> buffer(1024); |
| 218 | + |
| 219 | + size_t len = 0; |
| 220 | + int ret; |
| 221 | + |
| 222 | + ret = snprintf(buffer.data(), buffer.size(), "%c|%u|%.*s", phase, m_pid, name.size(), name.data()); |
| 223 | + if (ret < 0) { |
| 224 | + return; |
| 225 | + } |
| 226 | + len += ret; |
| 227 | + |
| 228 | + if (format && format[0] != '\0' && len < buffer.size()) { |
| 229 | + buffer[len++] = (phase == 'I' ? ',' : '|'); // add args to the name so it is easier to see data in timeline |
| 230 | + ret = vsnprintf(buffer.data() + len, buffer.size() - len, format, args); |
| 231 | + if (ret < 0) { |
| 232 | + return; |
| 233 | + } |
| 234 | + len += ret; |
| 235 | + } |
| 236 | + |
| 237 | + writeFTraceMarker(buffer.data(), std::min(buffer.size() - 1, len)); |
| 238 | + } |
| 239 | + |
| 240 | + void addMark(const char phase, std::span<const char> name, const char *format, ...) WTF_ATTRIBUTE_PRINTF(4, 5) { |
| 241 | + va_list args; |
| 242 | + va_start(args, format); |
| 243 | + addMark(phase, WTFMove(name), format, args); |
| 244 | + va_end(args); |
| 245 | + } |
| 246 | + |
| 247 | + void addMark(const char phase, std::span<const char> name) { |
| 248 | + addMark(phase, WTFMove(name), ""); |
| 249 | + } |
| 250 | + |
| 251 | + void addTraceEvent(char phase, |
| 252 | + const unsigned char* categoryEnabled, |
| 253 | + const char* name, |
| 254 | + unsigned long long id, |
| 255 | + int numArgs, |
| 256 | + const char** argNames, |
| 257 | + const unsigned char* argTypes, |
| 258 | + const unsigned long long* argValues, |
| 259 | + unsigned char flags) { |
| 260 | + UNUSED_PARAM(id); |
| 261 | + UNUSED_PARAM(flags); |
| 262 | + |
| 263 | + // "<phase>|<pid>|<name>[|<argNames0>=<argValues0>,<argNames1>=<argValues1>...]" |
| 264 | + StringBuilder builder; |
| 265 | + |
| 266 | + builder.append(phase, '|', String::number(m_pid), '|'); |
| 267 | + builder.append(StringView::fromLatin1(reinterpret_cast<const char*>(categoryEnabled)), ':', StringView::fromLatin1(name)); |
| 268 | + |
| 269 | + for (int i = 0; i < numArgs; ++i) { |
| 270 | + union TraceArgValueUnion { |
| 271 | + bool as_bool; |
| 272 | + unsigned long long as_uint; |
| 273 | + long long as_int; |
| 274 | + double as_double; |
| 275 | + const void* as_pointer; |
| 276 | + const char* as_string; |
| 277 | + } arg; |
| 278 | + |
| 279 | + enum TraceArgValueType : int8_t { |
| 280 | + Bool = 1, |
| 281 | + Uint = 2, |
| 282 | + Int = 3, |
| 283 | + Double = 4, |
| 284 | + Pointer = 5, |
| 285 | + String = 6, |
| 286 | + CopyString = 7 |
| 287 | + }; |
| 288 | + |
| 289 | + const auto argName = StringView::fromLatin1(argNames[i]); |
| 290 | + arg.as_uint = argValues[i]; |
| 291 | + if (i == 0) |
| 292 | + builder.append('|'); |
| 293 | + else |
| 294 | + builder.append(','); |
| 295 | + builder.append(argName, '='); |
| 296 | + |
| 297 | + switch(argTypes[i]) { |
| 298 | + case TraceArgValueType::String: |
| 299 | + case TraceArgValueType::CopyString: |
| 300 | + builder.append(StringView::fromLatin1(arg.as_string)); |
| 301 | + break; |
| 302 | + case TraceArgValueType::Bool: |
| 303 | + builder.append(arg.as_bool ? "true"_s : "false"_s); |
| 304 | + break; |
| 305 | + case TraceArgValueType::Uint: |
| 306 | + builder.append(String::number(arg.as_uint)); |
| 307 | + break; |
| 308 | + case TraceArgValueType::Int: |
| 309 | + builder.append(String::number(arg.as_int)); |
| 310 | + break; |
| 311 | + case TraceArgValueType::Double: |
| 312 | + builder.append(String::number(arg.as_double)); |
| 313 | + break; |
| 314 | + case TraceArgValueType::Pointer: |
| 315 | + builder.append("0x"_s, hex(reinterpret_cast<uintptr_t>(arg.as_pointer))); |
| 316 | + break; |
| 317 | + default: |
| 318 | + break; |
| 319 | + } |
| 320 | + } |
| 321 | + |
| 322 | + const auto buffer = spanReinterpretCast<const char>(builder.span<uint8_t>()); |
| 323 | + writeFTraceMarker(buffer.data(), buffer.size()); |
| 324 | + } |
| 325 | + |
211 | 326 | static bool isEnabled() { |
212 | 327 | return !(instance().m_traceMarkerFd < 0); |
213 | 328 | } |
|
0 commit comments