diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-02-08 10:17:06 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-02-22 09:00:46 +0000 |
commit | bfb9a9d92676d425e2a57c052882458d991d19cc (patch) | |
tree | 3c4d7f528e5acc437f4a84acf319c1941147f954 | |
parent | ee09936d80b3731c8658f3613269cee12be403cc (diff) | |
download | qtwebengine-chromium-bfb9a9d92676d425e2a57c052882458d991d19cc.tar.gz |
[Revert] Introduction of TraceArguments
Convoluted macro and template mess that doesn't compile on MSVC.
Upstream commmits:
eebbd7f63c58e92d8b7081b3287b28f07706b95f
3e390e1cf6a97441fcdc5c5bc34f813f0053f6e9
ff2599dc95f6cfd211c131b63d494f7114326c0a
fd0d2d18ae70c83daa081fbc9ae5de0b0aad791e
c1b9c28bfe1b5439f61e27148acd079e843d2129
Change-Id: I73f23b51fa8a3690d9e1f7658a26e969ae047570
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
25 files changed, 1084 insertions, 1783 deletions
diff --git a/chromium/base/BUILD.gn b/chromium/base/BUILD.gn index 1cf6f176455..995f6c3ed68 100644 --- a/chromium/base/BUILD.gn +++ b/chromium/base/BUILD.gn @@ -937,8 +937,6 @@ jumbo_component("base") { "trace_event/memory_usage_estimator.h", "trace_event/process_memory_dump.cc", "trace_event/process_memory_dump.h", - "trace_event/trace_arguments.cc", - "trace_event/trace_arguments.h", "trace_event/trace_buffer.cc", "trace_event/trace_buffer.h", "trace_event/trace_category.h", @@ -2568,7 +2566,6 @@ test("base_unittests") { "trace_event/memory_infra_background_whitelist_unittest.cc", "trace_event/memory_usage_estimator_unittest.cc", "trace_event/process_memory_dump_unittest.cc", - "trace_event/trace_arguments_unittest.cc", "trace_event/trace_category_unittest.cc", "trace_event/trace_config_unittest.cc", "trace_event/trace_event_filter_test_utils.cc", diff --git a/chromium/base/trace_event/blame_context.cc b/chromium/base/trace_event/blame_context.cc index b46412c1db9..0ed9aa7ad05 100644 --- a/chromium/base/trace_event/blame_context.cc +++ b/chromium/base/trace_event/blame_context.cc @@ -33,9 +33,9 @@ BlameContext::BlameContext(const char* category, BlameContext::~BlameContext() { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(WasInitialized()); - TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_DELETE_OBJECT, - category_group_enabled_, type_, scope_, id_, - nullptr, TRACE_EVENT_FLAG_HAS_ID); + TRACE_EVENT_API_ADD_TRACE_EVENT( + TRACE_EVENT_PHASE_DELETE_OBJECT, category_group_enabled_, type_, scope_, + id_, 0, nullptr, nullptr, nullptr, nullptr, TRACE_EVENT_FLAG_HAS_ID); trace_event::TraceLog::GetInstance()->RemoveAsyncEnabledStateObserver(this); } @@ -43,6 +43,7 @@ void BlameContext::Enter() { DCHECK(WasInitialized()); TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_ENTER_CONTEXT, category_group_enabled_, name_, scope_, id_, + 0 /* num_args */, nullptr, nullptr, nullptr, nullptr, TRACE_EVENT_FLAG_HAS_ID); } @@ -50,6 +51,7 @@ void BlameContext::Leave() { DCHECK(WasInitialized()); TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_LEAVE_CONTEXT, category_group_enabled_, name_, scope_, id_, + 0 /* num_args */, nullptr, nullptr, nullptr, nullptr, TRACE_EVENT_FLAG_HAS_ID); } @@ -61,10 +63,15 @@ void BlameContext::TakeSnapshot() { std::unique_ptr<trace_event::TracedValue> snapshot( new trace_event::TracedValue); AsValueInto(snapshot.get()); - TraceArguments args("snapshot", std::move(snapshot)); + static const char* const kArgName = "snapshot"; + const int kNumArgs = 1; + unsigned char arg_types[1] = {TRACE_VALUE_TYPE_CONVERTABLE}; + std::unique_ptr<trace_event::ConvertableToTraceFormat> arg_values[1] = { + std::move(snapshot)}; TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_SNAPSHOT_OBJECT, category_group_enabled_, type_, scope_, id_, - &args, TRACE_EVENT_FLAG_HAS_ID); + kNumArgs, &kArgName, arg_types, nullptr, + arg_values, TRACE_EVENT_FLAG_HAS_ID); } void BlameContext::OnTraceLogEnabled() { @@ -88,9 +95,9 @@ void BlameContext::Initialize() { DCHECK(thread_checker_.CalledOnValidThread()); category_group_enabled_ = TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category_); - TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_CREATE_OBJECT, - category_group_enabled_, type_, scope_, id_, - nullptr, TRACE_EVENT_FLAG_HAS_ID); + TRACE_EVENT_API_ADD_TRACE_EVENT( + TRACE_EVENT_PHASE_CREATE_OBJECT, category_group_enabled_, type_, scope_, + id_, 0, nullptr, nullptr, nullptr, nullptr, TRACE_EVENT_FLAG_HAS_ID); trace_event::TraceLog::GetInstance()->AddAsyncEnabledStateObserver( weak_factory_.GetWeakPtr()); TakeSnapshot(); diff --git a/chromium/base/trace_event/event_name_filter_unittest.cc b/chromium/base/trace_event/event_name_filter_unittest.cc index d0b32d11dae..e1d6f51d9f2 100644 --- a/chromium/base/trace_event/event_name_filter_unittest.cc +++ b/chromium/base/trace_event/event_name_filter_unittest.cc @@ -13,8 +13,8 @@ namespace trace_event { const TraceEvent& MakeTraceEvent(const char* name) { static TraceEvent event; - event.Reset(0, TimeTicks(), ThreadTicks(), 'b', nullptr, name, "", 0, 0, - nullptr, 0); + event.Reset(0, TimeTicks(), ThreadTicks(), 'b', nullptr, name, "", 0, 0, 0, + nullptr, nullptr, nullptr, nullptr, 0); return event; } diff --git a/chromium/base/trace_event/process_memory_dump.cc b/chromium/base/trace_event/process_memory_dump.cc index 5a049cc1d5c..8f851f4b0cb 100644 --- a/chromium/base/trace_event/process_memory_dump.cc +++ b/chromium/base/trace_event/process_memory_dump.cc @@ -13,7 +13,6 @@ #include "base/process/process_metrics.h" #include "base/strings/stringprintf.h" #include "base/trace_event/memory_infra_background_whitelist.h" -#include "base/trace_event/trace_event_impl.h" #include "base/trace_event/traced_value.h" #include "base/unguessable_token.h" #include "build/build_config.h" diff --git a/chromium/base/trace_event/trace_arguments.cc b/chromium/base/trace_event/trace_arguments.cc deleted file mode 100644 index 642ba2311d7..00000000000 --- a/chromium/base/trace_event/trace_arguments.cc +++ /dev/null @@ -1,271 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/trace_arguments.h" - -#include <inttypes.h> -#include <stddef.h> -#include <stdio.h> -#include <string.h> - -#include <cmath> - -#include "base/json/string_escape.h" -#include "base/logging.h" -#include "base/stl_util.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "base/strings/utf_string_conversions.h" - -namespace base { -namespace trace_event { - -namespace { - -size_t GetAllocLength(const char* str) { - return str ? strlen(str) + 1 : 0; -} - -// Copies |*member| into |*buffer|, sets |*member| to point to this new -// location, and then advances |*buffer| by the amount written. -void CopyTraceEventParameter(char** buffer, - const char** member, - const char* end) { - if (*member) { - size_t written = strlcpy(*buffer, *member, end - *buffer) + 1; - DCHECK_LE(static_cast<int>(written), end - *buffer); - *member = *buffer; - *buffer += written; - } -} - -// Append |val| as a JSON output value to |*out|. -void AppendDoubleAsJSON(double val, std::string* out) { - // FIXME: base/json/json_writer.cc is using the same code, - // should be made into a common method. - std::string real; - if (std::isfinite(val)) { - real = NumberToString(val); - // Ensure that the number has a .0 if there's no decimal or 'e'. This - // makes sure that when we read the JSON back, it's interpreted as a - // real rather than an int. - if (real.find('.') == std::string::npos && - real.find('e') == std::string::npos && - real.find('E') == std::string::npos) { - real.append(".0"); - } - // The JSON spec requires that non-integer values in the range (-1,1) - // have a zero before the decimal point - ".52" is not valid, "0.52" is. - if (real[0] == '.') { - real.insert(0, "0"); - } else if (real.length() > 1 && real[0] == '-' && real[1] == '.') { - // "-.1" bad "-0.1" good - real.insert(1, "0"); - } - } else if (std::isnan(val)) { - // The JSON spec doesn't allow NaN and Infinity (since these are - // objects in EcmaScript). Use strings instead. - real = "\"NaN\""; - } else if (val < 0) { - real = "\"-Infinity\""; - } else { - real = "\"Infinity\""; - } - StringAppendF(out, "%s", real.c_str()); -} - -const char* TypeToString(char arg_type) { - switch (arg_type) { - case TRACE_VALUE_TYPE_INT: - return "int"; - case TRACE_VALUE_TYPE_UINT: - return "uint"; - case TRACE_VALUE_TYPE_DOUBLE: - return "double"; - case TRACE_VALUE_TYPE_BOOL: - return "bool"; - case TRACE_VALUE_TYPE_POINTER: - return "pointer"; - case TRACE_VALUE_TYPE_STRING: - return "string"; - case TRACE_VALUE_TYPE_COPY_STRING: - return "copy_string"; - case TRACE_VALUE_TYPE_CONVERTABLE: - return "convertable"; - default: - NOTREACHED(); - return "UNKNOWN_TYPE"; - } -} - -void AppendValueDebugString(const TraceArguments& args, - size_t idx, - std::string* out) { - *out += (args.names()[idx] ? args.names()[idx] : "NULL_NAME"); - *out += "="; - *out += TypeToString(args.types()[idx]); - *out += "("; - args.values()[idx].AppendAsJSON(args.types()[idx], out); - *out += ")"; -} - -} // namespace - -void StringStorage::Reset(size_t alloc_size) { - if (!alloc_size) { - if (data_) - ::free(data_); - data_ = nullptr; - } else if (!data_ || alloc_size != data_->size) { - data_ = static_cast<Data*>(::realloc(data_, sizeof(size_t) + alloc_size)); - data_->size = alloc_size; - } -} - -bool StringStorage::Contains(const TraceArguments& args) const { - for (size_t n = 0; n < args.size(); ++n) { - if (args.types()[n] == TRACE_VALUE_TYPE_COPY_STRING && - !Contains(args.values()[n].as_string)) { - return false; - } - } - return true; -} - -static_assert( - std::is_pod<TraceValue>::value, - "TraceValue must be plain-old-data type for performance reasons!"); - -void TraceValue::AppendAsJSON(unsigned char type, std::string* out) const { - switch (type) { - case TRACE_VALUE_TYPE_BOOL: - *out += this->as_bool ? "true" : "false"; - break; - case TRACE_VALUE_TYPE_UINT: - StringAppendF(out, "%" PRIu64, static_cast<uint64_t>(this->as_uint)); - break; - case TRACE_VALUE_TYPE_INT: - StringAppendF(out, "%" PRId64, static_cast<int64_t>(this->as_int)); - break; - case TRACE_VALUE_TYPE_DOUBLE: - AppendDoubleAsJSON(this->as_double, out); - break; - case TRACE_VALUE_TYPE_POINTER: - // JSON only supports double and int numbers. - // So as not to lose bits from a 64-bit pointer, output as a hex string. - StringAppendF( - out, "\"0x%" PRIx64 "\"", - static_cast<uint64_t>(reinterpret_cast<uintptr_t>(this->as_pointer))); - break; - case TRACE_VALUE_TYPE_STRING: - case TRACE_VALUE_TYPE_COPY_STRING: - EscapeJSONString(this->as_string ? this->as_string : "NULL", true, out); - break; - case TRACE_VALUE_TYPE_CONVERTABLE: - this->as_convertable->AppendAsTraceFormat(out); - break; - default: - NOTREACHED() << "Don't know how to print this value"; - break; - } -} - -TraceArguments& TraceArguments::operator=(TraceArguments&& other) noexcept { - if (this != &other) { - this->~TraceArguments(); - new (this) TraceArguments(std::move(other)); - } - return *this; -} - -TraceArguments::TraceArguments(int num_args, - const char* const* arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values) { - if (num_args > static_cast<int>(kMaxSize)) - num_args = static_cast<int>(kMaxSize); - - size_ = static_cast<unsigned char>(num_args); - for (size_t n = 0; n < size_; ++n) { - types_[n] = arg_types[n]; - names_[n] = arg_names[n]; - values_[n].as_uint = arg_values[n]; - } -} - -void TraceArguments::Reset() { - for (size_t n = 0; n < size_; ++n) { - if (types_[n] == TRACE_VALUE_TYPE_CONVERTABLE) - delete values_[n].as_convertable; - } - size_ = 0; -} - -void TraceArguments::CopyStringsTo(StringStorage* storage, - bool copy_all_strings, - const char** extra_string1, - const char** extra_string2) { - // First, compute total allocation size. - size_t alloc_size = 0; - - if (copy_all_strings) { - alloc_size += - GetAllocLength(*extra_string1) + GetAllocLength(*extra_string2); - for (size_t n = 0; n < size_; ++n) - alloc_size += GetAllocLength(names_[n]); - } - for (size_t n = 0; n < size_; ++n) { - if (copy_all_strings && types_[n] == TRACE_VALUE_TYPE_STRING) - types_[n] = TRACE_VALUE_TYPE_COPY_STRING; - if (types_[n] == TRACE_VALUE_TYPE_COPY_STRING) - alloc_size += GetAllocLength(values_[n].as_string); - } - - if (alloc_size) { - storage->Reset(alloc_size); - char* ptr = storage->data(); - const char* end = ptr + alloc_size; - if (copy_all_strings) { - CopyTraceEventParameter(&ptr, extra_string1, end); - CopyTraceEventParameter(&ptr, extra_string2, end); - for (size_t n = 0; n < size_; ++n) - CopyTraceEventParameter(&ptr, &names_[n], end); - } - for (size_t n = 0; n < size_; ++n) { - if (types_[n] == TRACE_VALUE_TYPE_COPY_STRING) - CopyTraceEventParameter(&ptr, &values_[n].as_string, end); - } -#if DCHECK_IS_ON() - DCHECK_EQ(end, ptr) << "Overrun by " << ptr - end; - if (copy_all_strings) { - if (extra_string1 && *extra_string1) - DCHECK(storage->Contains(*extra_string1)); - if (extra_string2 && *extra_string2) - DCHECK(storage->Contains(*extra_string2)); - for (size_t n = 0; n < size_; ++n) - DCHECK(storage->Contains(names_[n])); - } - for (size_t n = 0; n < size_; ++n) { - if (types_[n] == TRACE_VALUE_TYPE_COPY_STRING) - DCHECK(storage->Contains(values_[n].as_string)); - } -#endif // DCHECK_IS_ON() - } else { - storage->Reset(); - } -} - -void TraceArguments::AppendDebugString(std::string* out) { - *out += "TraceArguments("; - for (size_t n = 0; n < size_; ++n) { - if (n > 0) - *out += ", "; - AppendValueDebugString(*this, n, out); - } - *out += ")"; -} - -} // namespace trace_event -} // namespace base diff --git a/chromium/base/trace_event/trace_arguments.h b/chromium/base/trace_event/trace_arguments.h deleted file mode 100644 index 6a9af808e4c..00000000000 --- a/chromium/base/trace_event/trace_arguments.h +++ /dev/null @@ -1,671 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TRACE_EVENT_TRACE_ARGUMENTS_H_ -#define BASE_TRACE_EVENT_TRACE_ARGUMENTS_H_ - -#include <stdlib.h> -#include <string.h> - -#include <algorithm> -#include <memory> -#include <string> - -#include "base/base_export.h" -#include "base/macros.h" -#include "base/trace_event/common/trace_event_common.h" - -// Trace macro can have one or two optional arguments, each one of them -// identified by a name (a C string literal) and a value, which can be an -// integer, enum, floating point, boolean, string pointer or reference, or -// std::unique_ptr<ConvertableToTraceFormat> compatible values. Additionally, -// custom data types need to be supported, like time values or WTF::CString. -// -// TraceArguments is a helper class used to store 0 to 2 named arguments -// corresponding to an individual trace macro call. As efficiently as possible, -// and with the minimal amount of generated machine code (since this affects -// any TRACE macro call). Each argument has: -// -// - A name (C string literal, e.g "dumps") -// - An 8-bit type value, corresponding to the TRACE_VALUE_TYPE_XXX macros. -// - A value, stored in a TraceValue union -// -// IMPORTANT: For a TRACE_VALUE_TYPE_CONVERTABLE types, the TraceArguments -// instance owns the pointed ConvertableToTraceFormat object, i.e. it will -// delete it automatically on destruction. -// -// TraceArguments instances should be built using one of specialized -// constructors declared below. One cannot modify an instance once it has -// been built, except for move operations, Reset() and destruction. Examples: -// -// TraceArguments args; // No arguments. -// // args.size() == 0 -// -// TraceArguments("foo", 100); -// // args.size() == 1 -// // args.types()[0] == TRACE_VALUE_TYPE_INT -// // args.names()[0] == "foo" -// // args.values()[0].as_int == 100 -// -// TraceArguments("bar", 1ULL); -// // args.size() == 1 -// // args.types()[0] == TRACE_VALUE_TYPE_UINT -// // args.names()[0] == "bar" -// // args.values()[0].as_uint == 100 -// -// TraceArguments("foo", "Hello", "bar", "World"); -// // args.size() == 2 -// // args.types()[0] == TRACE_VALUE_TYPE_STRING -// // args.types()[1] == TRACE_VALUE_TYPE_STRING -// // args.names()[0] == "foo" -// // args.names()[1] == "bar" -// // args.values()[0].as_string == "Hello" -// // args.values()[1].as_string == "World" -// -// std::string some_string = ...; -// TraceArguments("str1", some_string); -// // args.size() == 1 -// // args.types()[0] == TRACE_VALUE_TYPE_COPY_STRING -// // args.names()[0] == "str1" -// // args.values()[0].as_string == some_string.c_str() -// -// Note that TRACE_VALUE_TYPE_COPY_STRING corresponds to string pointers -// that point to temporary values that may disappear soon. The -// TraceArguments::CopyStringTo() method can be used to copy their content -// into a StringStorage memory block, and update the |as_string| value pointers -// to it to avoid keeping any dangling pointers. This is used by TraceEvent -// to keep copies of such strings in the log after their initialization values -// have disappeared. -// -// The TraceStringWithCopy helper class can be used to initialize a value -// from a regular string pointer with TRACE_VALUE_TYPE_COPY_STRING too, as in: -// -// const char str[] = "...."; -// TraceArguments("foo", str, "bar", TraceStringWithCopy(str)); -// // args.size() == 2 -// // args.types()[0] == TRACE_VALUE_TYPE_STRING -// // args.types()[1] == TRACE_VALUE_TYPE_COPY_STRING -// // args.names()[0] == "foo" -// // args.names()[1] == "bar" -// // args.values()[0].as_string == str -// // args.values()[1].as_string == str -// -// StringStorage storage; -// args.CopyStringTo(&storage, false, nullptr, nullptr); -// // args.size() == 2 -// // args.types()[0] == TRACE_VALUE_TYPE_STRING -// // args.types()[1] == TRACE_VALUE_TYPE_COPY_STRING -// // args.names()[0] == "foo" -// // args.names()[1] == "bar" -// // args.values()[0].as_string == str -// // args.values()[1].as_string == Address inside |storage|. -// -// Initialization from a std::unique_ptr<ConvertableToTraceFormat> -// is supported but will move ownership of the pointer objects to the -// TraceArguments instance: -// -// class MyConvertableType : -// public base::trace_event::AsConvertableToTraceFormat { -// ... -// }; -// -// { -// TraceArguments args("foo" , std::make_unique<MyConvertableType>(...)); -// // args.size() == 1 -// // args.values()[0].as_convertable == address of MyConvertable object. -// } // Calls |args| destructor, which will delete the object too. -// -// Finally, it is possible to support initialization from custom values by -// specializing the TraceValue::Helper<> template struct as described below. -// -// This is how values of custom types like WTF::CString can be passed directly -// to trace macros. - -namespace base { - -class Time; -class TimeTicks; -class ThreadTicks; - -namespace trace_event { - -class TraceEventMemoryOverhead; - -// For any argument of type TRACE_VALUE_TYPE_CONVERTABLE the provided -// class must implement this interface. Note that unlike other values, -// these objects will be owned by the TraceArguments instance that points -// to them. -class BASE_EXPORT ConvertableToTraceFormat { - public: - ConvertableToTraceFormat() = default; - virtual ~ConvertableToTraceFormat() = default; - - // Append the class info to the provided |out| string. The appended - // data must be a valid JSON object. Strings must be properly quoted, and - // escaped. There is no processing applied to the content after it is - // appended. - virtual void AppendAsTraceFormat(std::string* out) const = 0; - - // Append the class info directly into the Perfetto-defined proto - // format; this is attempted first and if this returns true, - // AppendAsTraceFormat is not called. The ProtoAppender interface - // acts as a bridge to avoid proto/Perfetto dependencies in base. - class BASE_EXPORT ProtoAppender { - public: - virtual ~ProtoAppender() = default; - - virtual void AddBuffer(uint8_t* begin, uint8_t* end) = 0; - // Copy all of the previous buffers registered with AddBuffer - // into the proto, with the given |field_id|. - virtual size_t Finalize(uint32_t field_id) = 0; - }; - virtual bool AppendToProto(ProtoAppender* appender); - - virtual void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead); - - std::string ToString() const { - std::string result; - AppendAsTraceFormat(&result); - return result; - } - - private: - DISALLOW_COPY_AND_ASSIGN(ConvertableToTraceFormat); -}; - -const int kTraceMaxNumArgs = 2; - -// A union used to hold the values of individual trace arguments. -// -// This is a POD union for performance reason. Initialization from an -// explicit C++ trace argument should be performed with the Init() -// templated method described below. -// -// Initialization from custom types is possible by implementing a custom -// TraceValue::Helper<> instantiation as described below. -// -// IMPORTANT: Pointer storage inside a TraceUnion follows specific rules: -// -// - |as_pointer| is for raw pointers that should be treated as a simple -// address and will never be dereferenced. Associated with the -// TRACE_VALUE_TYPE_POINTER type. -// -// - |as_string| is for C-string pointers, associated with both -// TRACE_VALUE_TYPE_STRING and TRACE_VALUE_TYPE_COPY_STRING. The former -// indicates that the string pointer is persistent (e.g. a C string -// literal), while the second indicates that the pointer belongs to a -// temporary variable that may disappear soon. The TraceArguments class -// provides a CopyStringTo() method to copy these strings into a -// StringStorage instance, which is useful if the instance needs to -// survive longer than the temporaries. -// -// - |as_convertable| is equivalent to -// std::unique_ptr<ConvertableToTraceFormat>, except that it is a pointer -// to keep this union POD and avoid un-necessary declarations and potential -// code generation. This means that its ownership is passed to the -// TraceValue instance when Init(std::unique_ptr<ConvertableToTraceFormat>) -// is called, and that it will be deleted by the containing TraceArguments -// destructor, or Reset() method. -// -union BASE_EXPORT TraceValue { - bool as_bool; - unsigned long long as_uint; - long long as_int; - double as_double; - const void* as_pointer; - const char* as_string; - ConvertableToTraceFormat* as_convertable; - - // There is no constructor to keep this structure POD intentionally. - // This avoids un-needed initialization when only 0 or 1 arguments are - // used to construct a TraceArguments instance. Use Init() instead to - // perform explicit initialization from a given C++ value. - - // Initialize TraceValue instance from a C++ trace value. - // This relies on the proper specialization of TraceValue::Helper<> - // described below. Usage is simply: - // - // TraceValue v; - // v.Init(<value>); - // - // NOTE: For ConvertableToTraceFormat values, see the note above and - // the one for TraceValue::Helper for CONVERTABLE_TYPE below. - template <typename T> - void Init(T&& value) { - using ValueType = typename InnerType<T>::type; - Helper<ValueType>::SetValue(this, std::forward<T>(value)); - } - - // Static method to create a new TraceValue instance from a given - // initialization value. Note that this deduces the TRACE_VALUE_TYPE_XXX - // type but doesn't return it, use ForType<T>::value for this. - // - // Usage example: - // auto v = TraceValue::Make(100); - // auto v2 = TraceValue::Make("Some text string"); - // - // IMPORTANT: Experience shows that the compiler generates worse code when - // using this method rather than calling Init() directly on an existing - // TraceValue union :-( - // - template <typename T> - static TraceValue Make(T&& value) { - TraceValue ret; - ret.Init(std::forward<T>(value)); - return ret; - } - - // Output current value as a JSON string. |type| must be a valid - // TRACE_VALUE_TYPE_XXX value. - void AppendAsJSON(unsigned char type, std::string* out) const; - - private: - // InnerType<T>::type removes reference, cv-qualifications and decays - // function and arrays into pointers. Only used internally. - template <typename T> - struct InnerType { - using type = typename std::remove_cv<typename std::remove_reference< - typename std::decay<T>::type>::type>::type; - }; - - public: - // TraceValue::Helper is used to provide information about initialization - // value types and an initialization function. It is a struct that should - // provide the following for supported initialization value types: - // - // - kType: is a static TRACE_VALUE_TYPE_XXX constant. - // - // - SetValue(TraceValue*, T): is a static inline method that sets - // TraceValue value from a given T value. Second parameter type - // can also be const T& or T&& to restrict uses. - // - // IMPORTANT: The type T must be InnerType<Q>, where Q is the real C++ - // argument type. I.e. you should not have to deal with reference types - // in your specialization. - // - // Specializations are defined for integers, enums, floating point, pointers, - // constant C string literals and pointers, std::string, time values below. - // - // Specializations for custom types are possible provided that there exists - // a corresponding Helper specialization, for example: - // - // template <> - // struct base::trace_event::TraceValue::Helper<Foo> { - // static constexpr unsigned char kTypes = TRACE_VALUE_TYPE_COPY_STRING; - // static inline void SetValue(TraceValue* v, const Foo& value) { - // v->as_string = value.c_str(); - // } - // }; - // - // Will allow code like: - // - // Foo foo = ...; - // auto v = TraceValue::Make(foo); - // - // Or even: - // Foo foo = ...; - // TraceArguments args("foo_arg1", foo); - // - template <typename T, class = void> - struct Helper {}; - - // TraceValue::TypeFor<T>::value returns the TRACE_VALUE_TYPE_XXX - // corresponding to initialization values of type T. - template <typename T> - struct TypeFor { - using ValueType = typename InnerType<T>::type; - static const unsigned char value = Helper<ValueType>::kType; - }; - - // TraceValue::TypeCheck<T>::value is only defined iff T can be used to - // initialize a TraceValue instance. This is useful to restrict template - // instantiation to only the appropriate type (see TraceArguments - // constructors below). - template <typename T, - class = decltype(TraceValue::Helper< - typename TraceValue::InnerType<T>::type>::kType)> - struct TypeCheck { - static const bool value = true; - }; -}; - -// TraceValue::Helper for integers and enums. -template <typename T> -struct TraceValue::Helper< - T, - typename std::enable_if<std::is_integral<T>::value || - std::is_enum<T>::value>::type> { - static constexpr unsigned char kType = - std::is_signed<T>::value ? TRACE_VALUE_TYPE_INT : TRACE_VALUE_TYPE_UINT; - static inline void SetValue(TraceValue* v, T value) { - v->as_uint = static_cast<unsigned long long>(value); - } -}; - -// TraceValue::Helper for floating-point types -template <typename T> -struct TraceValue:: - Helper<T, typename std::enable_if<std::is_floating_point<T>::value>::type> { - static constexpr unsigned char kType = TRACE_VALUE_TYPE_DOUBLE; - static inline void SetValue(TraceValue* v, T value) { v->as_double = value; } -}; - -// TraceValue::Helper for bool. -template <> -struct TraceValue::Helper<bool> { - static constexpr unsigned char kType = TRACE_VALUE_TYPE_BOOL; - static inline void SetValue(TraceValue* v, bool value) { v->as_bool = value; } -}; - -// TraceValue::Helper for generic pointer types. -template <typename T> -struct TraceValue::Helper<T*> { - static constexpr unsigned char kType = TRACE_VALUE_TYPE_POINTER; - static inline void SetValue(TraceValue* v, - const typename std::decay<T>::type* value) { - v->as_pointer = value; - } -}; - -// TraceValue::Helper for raw persistent C strings. -template <> -struct TraceValue::Helper<const char*> { - static constexpr unsigned char kType = TRACE_VALUE_TYPE_STRING; - static inline void SetValue(TraceValue* v, const char* value) { - v->as_string = value; - } -}; - -// TraceValue::Helper for std::string values. -template <> -struct TraceValue::Helper<std::string> { - static constexpr unsigned char kType = TRACE_VALUE_TYPE_COPY_STRING; - static inline void SetValue(TraceValue* v, const std::string& value) { - v->as_string = value.c_str(); - } -}; - -// Special case for scoped pointers to convertables to trace format. -// |CONVERTABLE_TYPE| must be a type whose pointers can be converted to a -// ConvertableToTraceFormat* pointer as well (e.g. a derived class). -// IMPORTANT: This takes an std::unique_ptr<CONVERTABLE_TYPE> value, and takes -// ownership of the pointed object! -template <typename CONVERTABLE_TYPE> -struct TraceValue::Helper<std::unique_ptr<CONVERTABLE_TYPE>, - typename std::enable_if<std::is_convertible< - CONVERTABLE_TYPE*, - ConvertableToTraceFormat*>::value>::type> { - static constexpr unsigned char kType = TRACE_VALUE_TYPE_CONVERTABLE; - static inline void SetValue(TraceValue* v, - std::unique_ptr<CONVERTABLE_TYPE> value) { - v->as_convertable = value.release(); - } -}; - -// Specialization for time-based values like base::Time, which provide a -// a ToInternalValue() method. -template <typename T> -struct TraceValue::Helper< - T, - typename std::enable_if<std::is_same<T, base::Time>::value || - std::is_same<T, base::TimeTicks>::value || - std::is_same<T, base::ThreadTicks>::value>::type> { - static constexpr unsigned char kType = TRACE_VALUE_TYPE_INT; - static inline void SetValue(TraceValue* v, const T& value) { - v->as_int = value.ToInternalValue(); - } -}; - -// Simple container for const char* that should be copied instead of retained. -// The goal is to indicate that the C string is copyable, unlike the default -// Init(const char*) implementation. Usage is: -// -// const char* str = ...; -// v.Init(TraceStringWithCopy(str)); -// -// Which will mark the string as TRACE_VALUE_TYPE_COPY_STRING, instead of -// TRACE_VALUE_TYPE_STRING. -// -class TraceStringWithCopy { - public: - explicit TraceStringWithCopy(const char* str) : str_(str) {} - const char* str() const { return str_; } - - private: - const char* str_; -}; - -template <> -struct TraceValue::Helper<TraceStringWithCopy> { - static constexpr unsigned char kType = TRACE_VALUE_TYPE_COPY_STRING; - static inline void SetValue(TraceValue* v, const TraceStringWithCopy& value) { - v->as_string = value.str(); - } -}; - -class TraceArguments; - -// A small class used to store a copy of all strings from a given -// TraceArguments instance (see below). When empty, this should only -// take the size of a pointer. Otherwise, this will point to a heap -// allocated block containing a size_t value followed by all characters -// in the storage area. For most cases, this is more efficient -// than using a std::unique_ptr<std::string> or an std::vector<char>. -class BASE_EXPORT StringStorage { - public: - constexpr StringStorage() = default; - - explicit StringStorage(size_t alloc_size) { Reset(alloc_size); } - - ~StringStorage() { - if (data_) - ::free(data_); - } - - StringStorage(StringStorage&& other) noexcept : data_(other.data_) { - other.data_ = nullptr; - } - - StringStorage& operator=(StringStorage&& other) noexcept { - if (this != &other) { - if (data_) - ::free(data_); - data_ = other.data_; - other.data_ = nullptr; - } - return *this; - } - - // Reset storage area to new allocation size. Existing content might not - // be preserved. If |alloc_size| is 0, this will free the storage area - // as well. - void Reset(size_t alloc_size = 0); - - // Accessors. - constexpr size_t size() const { return data_ ? data_->size : 0u; } - constexpr const char* data() const { return data_ ? data_->chars : nullptr; } - constexpr char* data() { return data_ ? data_->chars : nullptr; } - - constexpr const char* begin() const { return data(); } - constexpr const char* end() const { return data() + size(); } - inline char* begin() { return data(); } - inline char* end() { return data() + size(); } - - // True iff storage is empty. - constexpr bool empty() const { return size() == 0; } - - // Returns true if |ptr| is inside the storage area, false otherwise. - // Used during unit-testing. - constexpr bool Contains(const void* ptr) const { - const char* char_ptr = static_cast<const char*>(ptr); - return (char_ptr >= begin() && char_ptr < end()); - } - - // Returns true if all string pointers in |args| are contained in this - // storage area. - bool Contains(const TraceArguments& args) const; - - // Return an estimate of the memory overhead of this instance. This doesn't - // count the size of |data_| itself. - constexpr size_t EstimateTraceMemoryOverhead() const { - return data_ ? sizeof(size_t) + data_->size : 0u; - } - - private: - // Heap allocated data block (variable size), made of: - // - // - size: a size_t field, giving the size of the following |chars| array. - // - chars: an array of |size| characters, holding all zero-terminated - // strings referenced from a TraceArguments instance. - struct Data { - size_t size = 0; - char chars[1]; // really |size| character items in storage. - }; - - // This is an owning pointer. Normally, using a std::unique_ptr<> would be - // enough, but the compiler will then complaing about inlined constructors - // and destructors being too complex (!), resulting in larger code for no - // good reason. - Data* data_ = nullptr; -}; - -// TraceArguments models an array of kMaxSize trace-related items, -// each one of them having: -// - a name, which is a constant char array literal. -// - a type, as described by TRACE_VALUE_TYPE_XXX macros. -// - a value, stored in a TraceValue union. -// -// IMPORTANT: For TRACE_VALUE_TYPE_CONVERTABLE, the value holds an owning -// pointer to an AsConvertableToTraceFormat instance, which will -// be destroyed with the array (or moved out of it when passed -// to a TraceEvent instance). -// -// For TRACE_VALUE_TYPE_COPY_STRING, the value holds a const char* pointer -// whose content will be copied when creating a TraceEvent instance. -// -// IMPORTANT: Most constructors and the destructor are all inlined -// intentionally, in order to let the compiler remove un-necessary operations -// and reduce machine code. -// -class BASE_EXPORT TraceArguments { - public: - // Maximum number of arguments held by this structure. - static constexpr size_t kMaxSize = 2; - - // Default constructor, no arguments. - TraceArguments() : size_(0) {} - - // Constructor for a single argument. - template <typename T, class = decltype(TraceValue::TypeCheck<T>::value)> - TraceArguments(const char* arg1_name, T&& arg1_value) : size_(1) { - types_[0] = TraceValue::TypeFor<T>::value; - names_[0] = arg1_name; - values_[0].Init(std::forward<T>(arg1_value)); - } - - // Constructor for two arguments. - template <typename T1, - typename T2, - class = decltype(TraceValue::TypeCheck<T1>::value && - TraceValue::TypeCheck<T2>::value)> - TraceArguments(const char* arg1_name, - T1&& arg1_value, - const char* arg2_name, - T2&& arg2_value) - : size_(2) { - types_[0] = TraceValue::TypeFor<T1>::value; - types_[1] = TraceValue::TypeFor<T2>::value; - names_[0] = arg1_name; - names_[1] = arg2_name; - values_[0].Init(std::forward<T1>(arg1_value)); - values_[1].Init(std::forward<T2>(arg2_value)); - } - - // Constructor used to convert a legacy set of arguments when there - // are no convertable values at all. - TraceArguments(int num_args, - const char* const* arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values); - - // Constructor used to convert legacy set of arguments, where the - // convertable values are also provided by an array of CONVERTABLE_TYPE. - template <typename CONVERTABLE_TYPE> - TraceArguments(int num_args, - const char* const* arg_names, - const unsigned char* arg_types, - const unsigned long long* arg_values, - CONVERTABLE_TYPE* arg_convertables) { - static int max_args = static_cast<int>(kMaxSize); - if (num_args > max_args) - num_args = max_args; - size_ = static_cast<unsigned char>(num_args); - for (size_t n = 0; n < size_; ++n) { - types_[n] = arg_types[n]; - names_[n] = arg_names[n]; - if (arg_types[n] == TRACE_VALUE_TYPE_CONVERTABLE) { - values_[n].Init( - std::forward<CONVERTABLE_TYPE>(std::move(arg_convertables[n]))); - } else { - values_[n].as_uint = arg_values[n]; - } - } - } - - // Destructor. NOTE: Intentionally inlined (see note above). - ~TraceArguments() { - for (size_t n = 0; n < size_; ++n) { - if (types_[n] == TRACE_VALUE_TYPE_CONVERTABLE) - delete values_[n].as_convertable; - } - } - - // Disallow copy operations. - TraceArguments(const TraceArguments&) = delete; - TraceArguments& operator=(const TraceArguments&) = delete; - - // Allow move operations. - TraceArguments(TraceArguments&& other) noexcept { - ::memcpy(this, &other, sizeof(*this)); - // All owning pointers were copied to |this|. Setting |other.size_| will - // mask the pointer values still in |other|. - other.size_ = 0; - } - - TraceArguments& operator=(TraceArguments&&) noexcept; - - // Accessors - size_t size() const { return size_; } - const unsigned char* types() const { return types_; } - const char* const* names() const { return names_; } - const TraceValue* values() const { return values_; } - - // Reset to empty arguments list. - void Reset(); - - // Use |storage| to copy all copyable strings. - // If |copy_all_strings| is false, then only the TRACE_VALUE_TYPE_COPY_STRING - // values will be copied into storage. If it is true, then argument names are - // also copied to storage, as well as the strings pointed to by - // |*extra_string1| and |*extra_string2|. - // NOTE: If there are no strings to copy, |*storage| is left untouched. - void CopyStringsTo(StringStorage* storage, - bool copy_all_strings, - const char** extra_string1, - const char** extra_string2); - - // Append debug string representation to |*out|. - void AppendDebugString(std::string* out); - - private: - unsigned char size_; - unsigned char types_[kMaxSize]; - const char* names_[kMaxSize]; - TraceValue values_[kMaxSize]; -}; - -} // namespace trace_event -} // namespace base - -#endif // BASE_TRACE_EVENT_TRACE_ARGUMENTS_H_ diff --git a/chromium/base/trace_event/trace_arguments_unittest.cc b/chromium/base/trace_event/trace_arguments_unittest.cc deleted file mode 100644 index a550cd616c4..00000000000 --- a/chromium/base/trace_event/trace_arguments_unittest.cc +++ /dev/null @@ -1,472 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/trace_event/trace_arguments.h" - -#include <gtest/gtest.h> -#include <string> - -namespace base { -namespace trace_event { - -namespace { - -// Simple convertable that holds a string to append to the trace, -// and can also write to a boolean flag on destruction. -class MyConvertable : public ConvertableToTraceFormat { - public: - MyConvertable(const char* text, bool* destroy_flag = nullptr) - : text_(text), destroy_flag_(destroy_flag) {} - ~MyConvertable() override { - if (destroy_flag_) - *destroy_flag_ = true; - } - void AppendAsTraceFormat(std::string* out) const override { *out += text_; } - const char* text() const { return text_; } - - private: - const char* text_; - bool* destroy_flag_; -}; - -} // namespace - -TEST(TraceArguments, StringStorageDefaultConstruction) { - StringStorage storage; - EXPECT_TRUE(storage.empty()); - EXPECT_FALSE(storage.data()); - EXPECT_EQ(0U, storage.size()); -} - -TEST(TraceArguments, StringStorageConstructionWithSize) { - const size_t kSize = 128; - StringStorage storage(kSize); - EXPECT_FALSE(storage.empty()); - EXPECT_TRUE(storage.data()); - EXPECT_EQ(kSize, storage.size()); - EXPECT_EQ(storage.data(), storage.begin()); - EXPECT_EQ(storage.data() + kSize, storage.end()); -} - -TEST(TraceArguments, StringStorageReset) { - StringStorage storage(128); - EXPECT_FALSE(storage.empty()); - - storage.Reset(); - EXPECT_TRUE(storage.empty()); - EXPECT_FALSE(storage.data()); - EXPECT_EQ(0u, storage.size()); -} - -TEST(TraceArguments, StringStorageResetWithSize) { - StringStorage storage; - EXPECT_TRUE(storage.empty()); - - const size_t kSize = 128; - storage.Reset(kSize); - EXPECT_FALSE(storage.empty()); - EXPECT_TRUE(storage.data()); - EXPECT_EQ(kSize, storage.size()); - EXPECT_EQ(storage.data(), storage.begin()); - EXPECT_EQ(storage.data() + kSize, storage.end()); -} - -TEST(TraceArguments, StringStorageEstimateTraceMemoryOverhead) { - StringStorage storage; - EXPECT_EQ(0u, storage.EstimateTraceMemoryOverhead()); - - const size_t kSize = 128; - storage.Reset(kSize); - EXPECT_EQ(sizeof(size_t) + kSize, storage.EstimateTraceMemoryOverhead()); -} - -static void CheckJSONFor(TraceValue v, char type, const char* expected) { - std::string out; - v.AppendAsJSON(type, &out); - EXPECT_STREQ(expected, out.c_str()); -} - -TEST(TraceArguments, TraceValueAppendAsJSON) { - TraceValue v; - - v.Init(-1024); - CheckJSONFor(v, TRACE_VALUE_TYPE_INT, "-1024"); - v.Init(1024ULL); - CheckJSONFor(v, TRACE_VALUE_TYPE_UINT, "1024"); - v.Init(3.1415926535); - CheckJSONFor(v, TRACE_VALUE_TYPE_DOUBLE, "3.1415926535"); - v.Init(true); - CheckJSONFor(v, TRACE_VALUE_TYPE_BOOL, "true"); - v.Init(false); - CheckJSONFor(v, TRACE_VALUE_TYPE_BOOL, "false"); - v.Init("Some \"nice\" String"); - CheckJSONFor(v, TRACE_VALUE_TYPE_STRING, "\"Some \\\"nice\\\" String\""); - CheckJSONFor(v, TRACE_VALUE_TYPE_COPY_STRING, "\"Some \\\"nice\\\" String\""); -} - -TEST(TraceArguments, DefaultConstruction) { - TraceArguments args; - EXPECT_EQ(0U, args.size()); -} - -TEST(TraceArguments, ConstructorSingleInteger) { - TraceArguments args("foo_int", int(10)); - EXPECT_EQ(1U, args.size()); - EXPECT_EQ(TRACE_VALUE_TYPE_INT, args.types()[0]); - EXPECT_STREQ("foo_int", args.names()[0]); - EXPECT_EQ(10, args.values()[0].as_int); -} - -TEST(TraceArguments, ConstructorSingleFloat) { - TraceArguments args("foo_pi", float(3.1415)); - double expected = float(3.1415); - EXPECT_EQ(1U, args.size()); - EXPECT_EQ(TRACE_VALUE_TYPE_DOUBLE, args.types()[0]); - EXPECT_STREQ("foo_pi", args.names()[0]); - EXPECT_EQ(expected, args.values()[0].as_double); -} - -TEST(TraceArguments, ConstructorSingleNoCopyString) { - const char kText[] = "Persistent string"; - TraceArguments args("foo_cstring", kText); - EXPECT_EQ(1U, args.size()); - EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args.types()[0]); - EXPECT_STREQ("foo_cstring", args.names()[0]); - EXPECT_EQ(kText, args.values()[0].as_string); -} - -TEST(TraceArguments, ConstructorSingleStdString) { - std::string text = "Non-persistent string"; - TraceArguments args("foo_stdstring", text); - EXPECT_EQ(1U, args.size()); - EXPECT_EQ(TRACE_VALUE_TYPE_COPY_STRING, args.types()[0]); - EXPECT_STREQ("foo_stdstring", args.names()[0]); - EXPECT_EQ(text.c_str(), args.values()[0].as_string); -} - -TEST(TraceArguments, ConstructorSingleTraceStringWithCopy) { - const char kText[] = "Persistent string #2"; - TraceArguments args("foo_tracestring", TraceStringWithCopy(kText)); - EXPECT_EQ(1U, args.size()); - EXPECT_EQ(TRACE_VALUE_TYPE_COPY_STRING, args.types()[0]); - EXPECT_STREQ("foo_tracestring", args.names()[0]); - EXPECT_EQ(kText, args.values()[0].as_string); -} - -TEST(TraceArguments, ConstructorSinglePointer) { - bool destroy_flag = false; - { - // Simple class that can set a boolean flag on destruction. - class Foo { - public: - Foo(bool* destroy_flag) : destroy_flag_(destroy_flag) {} - ~Foo() { - if (destroy_flag_) - *destroy_flag_ = true; - } - - private: - bool* destroy_flag_; - }; - auto foo = std::make_unique<Foo>(&destroy_flag); - EXPECT_FALSE(destroy_flag); - // This test also verifies that the object is not destroyed by the - // TraceArguments destructor. This should only be possible for - // TRACE_VALUE_TYPE_CONVERTABLE instances. - { - TraceArguments args("foo_pointer", foo.get()); - EXPECT_EQ(1U, args.size()); - EXPECT_EQ(TRACE_VALUE_TYPE_POINTER, args.types()[0]); - EXPECT_STREQ("foo_pointer", args.names()[0]); - EXPECT_EQ(foo.get(), args.values()[0].as_pointer); - EXPECT_FALSE(destroy_flag); - } // Calls TraceArguments destructor. - EXPECT_FALSE(destroy_flag); - } // Calls Foo destructor. - EXPECT_TRUE(destroy_flag); -} - -TEST(TraceArguments, ConstructorSingleConvertable) { - bool destroy_flag = false; - const char kText[] = "Text for MyConvertable instance"; - MyConvertable* ptr = new MyConvertable(kText, &destroy_flag); - - // This test also verifies that the MyConvertable instance is properly - // destroyed when the TraceArguments destructor is called. - EXPECT_FALSE(destroy_flag); - { - TraceArguments args("foo_convertable", std::unique_ptr<MyConvertable>(ptr)); - EXPECT_EQ(1U, args.size()); - EXPECT_EQ(TRACE_VALUE_TYPE_CONVERTABLE, args.types()[0]); - EXPECT_STREQ("foo_convertable", args.names()[0]); - EXPECT_EQ(ptr, args.values()[0].as_convertable); - EXPECT_FALSE(destroy_flag); - } // Calls TraceArguments destructor. - EXPECT_TRUE(destroy_flag); -} - -TEST(TraceArguments, ConstructorWithTwoArguments) { - const char kText1[] = "First argument"; - const char kText2[] = "Second argument"; - bool destroy_flag = false; - - { - MyConvertable* ptr = new MyConvertable(kText2, &destroy_flag); - TraceArguments args1("foo_arg1_cstring", kText1, "foo_arg2_convertable", - std::unique_ptr<MyConvertable>(ptr)); - EXPECT_EQ(2U, args1.size()); - EXPECT_STREQ("foo_arg1_cstring", args1.names()[0]); - EXPECT_STREQ("foo_arg2_convertable", args1.names()[1]); - EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args1.types()[0]); - EXPECT_EQ(TRACE_VALUE_TYPE_CONVERTABLE, args1.types()[1]); - EXPECT_EQ(kText1, args1.values()[0].as_string); - EXPECT_EQ(ptr, args1.values()[1].as_convertable); - EXPECT_FALSE(destroy_flag); - } // calls |args1| destructor. Should delete |ptr|. - EXPECT_TRUE(destroy_flag); -} - -TEST(TraceArguments, ConstructorLegacyNoConvertables) { - const char* const kNames[3] = {"legacy_arg1", "legacy_arg2", "legacy_arg3"}; - const unsigned char kTypes[3] = { - TRACE_VALUE_TYPE_INT, - TRACE_VALUE_TYPE_STRING, - TRACE_VALUE_TYPE_POINTER, - }; - static const char kText[] = "Some text"; - const unsigned long long kValues[3] = { - 1000042ULL, - reinterpret_cast<unsigned long long>(kText), - reinterpret_cast<unsigned long long>(kText + 2), - }; - TraceArguments args(3, kNames, kTypes, kValues); - // Check that only the first kMaxSize arguments are taken! - EXPECT_EQ(2U, args.size()); - EXPECT_STREQ(kNames[0], args.names()[0]); - EXPECT_STREQ(kNames[1], args.names()[1]); - EXPECT_EQ(TRACE_VALUE_TYPE_INT, args.types()[0]); - EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args.types()[1]); - EXPECT_EQ(kValues[0], args.values()[0].as_uint); - EXPECT_EQ(kText, args.values()[1].as_string); -}; - -TEST(TraceArguments, ConstructorLegacyWithConvertables) { - const char* const kNames[3] = {"legacy_arg1", "legacy_arg2", "legacy_arg3"}; - const unsigned char kTypes[3] = { - TRACE_VALUE_TYPE_CONVERTABLE, - TRACE_VALUE_TYPE_CONVERTABLE, - TRACE_VALUE_TYPE_CONVERTABLE, - }; - std::unique_ptr<MyConvertable> convertables[3] = { - std::make_unique<MyConvertable>("First one"), - std::make_unique<MyConvertable>("Second one"), - std::make_unique<MyConvertable>("Third one"), - }; - TraceArguments args(3, kNames, kTypes, nullptr, convertables); - // Check that only the first kMaxSize arguments are taken! - EXPECT_EQ(2U, args.size()); - EXPECT_STREQ(kNames[0], args.names()[0]); - EXPECT_STREQ(kNames[1], args.names()[1]); - EXPECT_EQ(TRACE_VALUE_TYPE_CONVERTABLE, args.types()[0]); - EXPECT_EQ(TRACE_VALUE_TYPE_CONVERTABLE, args.types()[1]); - // Check that only the first two items were moved to |args|. - EXPECT_FALSE(convertables[0].get()); - EXPECT_FALSE(convertables[1].get()); - EXPECT_TRUE(convertables[2].get()); -} - -TEST(TraceArguments, MoveConstruction) { - const char kText1[] = "First argument"; - const char kText2[] = "Second argument"; - bool destroy_flag = false; - - { - MyConvertable* ptr = new MyConvertable(kText2, &destroy_flag); - TraceArguments args1("foo_arg1_cstring", kText1, "foo_arg2_convertable", - std::unique_ptr<MyConvertable>(ptr)); - EXPECT_EQ(2U, args1.size()); - EXPECT_STREQ("foo_arg1_cstring", args1.names()[0]); - EXPECT_STREQ("foo_arg2_convertable", args1.names()[1]); - EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args1.types()[0]); - EXPECT_EQ(TRACE_VALUE_TYPE_CONVERTABLE, args1.types()[1]); - EXPECT_EQ(kText1, args1.values()[0].as_string); - EXPECT_EQ(ptr, args1.values()[1].as_convertable); - - { - TraceArguments args2(std::move(args1)); - EXPECT_FALSE(destroy_flag); - - // |args1| is now empty. - EXPECT_EQ(0U, args1.size()); - - // Check that everything was transferred to |args2|. - EXPECT_EQ(2U, args2.size()); - EXPECT_STREQ("foo_arg1_cstring", args2.names()[0]); - EXPECT_STREQ("foo_arg2_convertable", args2.names()[1]); - EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args2.types()[0]); - EXPECT_EQ(TRACE_VALUE_TYPE_CONVERTABLE, args2.types()[1]); - EXPECT_EQ(kText1, args2.values()[0].as_string); - EXPECT_EQ(ptr, args2.values()[1].as_convertable); - } // Calls |args2| destructor. Should delete |ptr|. - EXPECT_TRUE(destroy_flag); - destroy_flag = false; - } // Calls |args1| destructor. Should not delete |ptr|. - EXPECT_FALSE(destroy_flag); -} - -TEST(TraceArguments, MoveAssignment) { - const char kText1[] = "First argument"; - const char kText2[] = "Second argument"; - bool destroy_flag = false; - - { - MyConvertable* ptr = new MyConvertable(kText2, &destroy_flag); - TraceArguments args1("foo_arg1_cstring", kText1, "foo_arg2_convertable", - std::unique_ptr<MyConvertable>(ptr)); - EXPECT_EQ(2U, args1.size()); - EXPECT_STREQ("foo_arg1_cstring", args1.names()[0]); - EXPECT_STREQ("foo_arg2_convertable", args1.names()[1]); - EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args1.types()[0]); - EXPECT_EQ(TRACE_VALUE_TYPE_CONVERTABLE, args1.types()[1]); - EXPECT_EQ(kText1, args1.values()[0].as_string); - EXPECT_EQ(ptr, args1.values()[1].as_convertable); - - { - TraceArguments args2; - - args2 = std::move(args1); - EXPECT_FALSE(destroy_flag); - - // |args1| is now empty. - EXPECT_EQ(0U, args1.size()); - - // Check that everything was transferred to |args2|. - EXPECT_EQ(2U, args2.size()); - EXPECT_STREQ("foo_arg1_cstring", args2.names()[0]); - EXPECT_STREQ("foo_arg2_convertable", args2.names()[1]); - EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args2.types()[0]); - EXPECT_EQ(TRACE_VALUE_TYPE_CONVERTABLE, args2.types()[1]); - EXPECT_EQ(kText1, args2.values()[0].as_string); - EXPECT_EQ(ptr, args2.values()[1].as_convertable); - } // Calls |args2| destructor. Should delete |ptr|. - EXPECT_TRUE(destroy_flag); - destroy_flag = false; - } // Calls |args1| destructor. Should not delete |ptr|. - EXPECT_FALSE(destroy_flag); -} - -TEST(TraceArguments, Reset) { - bool destroy_flag = false; - { - TraceArguments args( - "foo_arg1", "Hello", "foo_arg2", - std::make_unique<MyConvertable>("World", &destroy_flag)); - - EXPECT_EQ(2U, args.size()); - EXPECT_FALSE(destroy_flag); - args.Reset(); - EXPECT_EQ(0U, args.size()); - EXPECT_TRUE(destroy_flag); - destroy_flag = false; - } // Calls |args| destructor. Should not delete twice. - EXPECT_FALSE(destroy_flag); -} - -TEST(TraceArguments, CopyStringsTo_NoStrings) { - StringStorage storage; - - TraceArguments args("arg1", 10, "arg2", 42); - args.CopyStringsTo(&storage, false, nullptr, nullptr); - EXPECT_TRUE(storage.empty()); - EXPECT_EQ(0U, storage.size()); -} - -TEST(TraceArguments, CopyStringsTo_OnlyArgs) { - StringStorage storage; - - TraceArguments args("arg1", TraceStringWithCopy("Hello"), "arg2", - TraceStringWithCopy("World")); - - const char kExtra1[] = "extra1"; - const char kExtra2[] = "extra2"; - const char* extra1 = kExtra1; - const char* extra2 = kExtra2; - - // Types should be copyable strings. - EXPECT_EQ(TRACE_VALUE_TYPE_COPY_STRING, args.types()[0]); - EXPECT_EQ(TRACE_VALUE_TYPE_COPY_STRING, args.types()[1]); - - args.CopyStringsTo(&storage, false, &extra1, &extra2); - - // Storage should be allocated. - EXPECT_TRUE(storage.data()); - EXPECT_NE(0U, storage.size()); - - // Types should not be changed. - EXPECT_EQ(TRACE_VALUE_TYPE_COPY_STRING, args.types()[0]); - EXPECT_EQ(TRACE_VALUE_TYPE_COPY_STRING, args.types()[1]); - - // names should not be copied. - EXPECT_FALSE(storage.Contains(args.names()[0])); - EXPECT_FALSE(storage.Contains(args.names()[1])); - EXPECT_STREQ("arg1", args.names()[0]); - EXPECT_STREQ("arg2", args.names()[1]); - - // strings should be copied. - EXPECT_TRUE(storage.Contains(args.values()[0].as_string)); - EXPECT_TRUE(storage.Contains(args.values()[1].as_string)); - EXPECT_STREQ("Hello", args.values()[0].as_string); - EXPECT_STREQ("World", args.values()[1].as_string); - - // |extra1| and |extra2| should not be copied. - EXPECT_EQ(kExtra1, extra1); - EXPECT_EQ(kExtra2, extra2); -} - -TEST(TraceArguments, CopyStringsTo_Everything) { - StringStorage storage; - - TraceArguments args("arg1", "Hello", "arg2", "World"); - const char kExtra1[] = "extra1"; - const char kExtra2[] = "extra2"; - const char* extra1 = kExtra1; - const char* extra2 = kExtra2; - - // Types should be normal strings. - EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args.types()[0]); - EXPECT_EQ(TRACE_VALUE_TYPE_STRING, args.types()[1]); - - args.CopyStringsTo(&storage, true, &extra1, &extra2); - - // Storage should be allocated. - EXPECT_TRUE(storage.data()); - EXPECT_NE(0U, storage.size()); - - // Types should be changed to copyable strings. - EXPECT_EQ(TRACE_VALUE_TYPE_COPY_STRING, args.types()[0]); - EXPECT_EQ(TRACE_VALUE_TYPE_COPY_STRING, args.types()[1]); - - // names should be copied. - EXPECT_TRUE(storage.Contains(args.names()[0])); - EXPECT_TRUE(storage.Contains(args.names()[1])); - EXPECT_STREQ("arg1", args.names()[0]); - EXPECT_STREQ("arg2", args.names()[1]); - - // strings should be copied. - EXPECT_TRUE(storage.Contains(args.values()[0].as_string)); - EXPECT_TRUE(storage.Contains(args.values()[1].as_string)); - EXPECT_STREQ("Hello", args.values()[0].as_string); - EXPECT_STREQ("World", args.values()[1].as_string); - - // |extra1| and |extra2| should be copied. - EXPECT_NE(kExtra1, extra1); - EXPECT_NE(kExtra2, extra2); - EXPECT_TRUE(storage.Contains(extra1)); - EXPECT_TRUE(storage.Contains(extra2)); - EXPECT_STREQ(kExtra1, extra1); - EXPECT_STREQ(kExtra2, extra2); -} - -} // namespace trace_event -} // namespace base diff --git a/chromium/base/trace_event/trace_event.h b/chromium/base/trace_event/trace_event.h index 53d8ca24d06..9bac00617f8 100644 --- a/chromium/base/trace_event/trace_event.h +++ b/chromium/base/trace_event/trace_event.h @@ -22,7 +22,6 @@ #include "base/trace_event/builtin_categories.h" #include "base/trace_event/common/trace_event_common.h" #include "base/trace_event/heap_profiler.h" -#include "base/trace_event/trace_arguments.h" #include "base/trace_event/trace_category.h" #include "base/trace_event/trace_event_system_stats_monitor.h" #include "base/trace_event/trace_log.h" @@ -30,7 +29,8 @@ // By default, const char* argument values are assumed to have long-lived scope // and will not be copied. Use this macro to force a const char* to be copied. -#define TRACE_STR_COPY(str) ::base::trace_event::TraceStringWithCopy(str) +#define TRACE_STR_COPY(str) \ + trace_event_internal::TraceStringWithCopy(str) // DEPRECATED: do not use: Consider using the TRACE_ID_LOCAL macro instead. By // default, uint64_t ID argument values are not mangled with the Process ID in @@ -659,86 +659,113 @@ class BASE_EXPORT TraceID { unsigned int id_flags_ = TRACE_EVENT_FLAG_HAS_ID; }; -// These functions all internally call -// base::trace_event::TraceLog::GetInstance() then call the method with the same -// name on it. This is used to reduce the generated machine code at each -// TRACE_EVENTXXX macro call. - -base::trace_event::TraceEventHandle BASE_EXPORT -AddTraceEvent(char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - base::trace_event::TraceArguments* args, - unsigned int flags); - -base::trace_event::TraceEventHandle BASE_EXPORT -AddTraceEventWithBindId(char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - unsigned long long bind_id, - base::trace_event::TraceArguments* args, - unsigned int flags); +// Simple union to store various types as unsigned long long. +union TraceValueUnion { + bool as_bool; + unsigned long long as_uint; + long long as_int; + double as_double; + const void* as_pointer; + const char* as_string; +}; -base::trace_event::TraceEventHandle BASE_EXPORT -AddTraceEventWithProcessId(char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - int process_id, - base::trace_event::TraceArguments* args, - unsigned int flags); +// Simple container for const char* that should be copied instead of retained. +class TraceStringWithCopy { + public: + explicit TraceStringWithCopy(const char* str) : str_(str) {} + const char* str() const { return str_; } + private: + const char* str_; +}; -base::trace_event::TraceEventHandle BASE_EXPORT -AddTraceEventWithThreadIdAndTimestamp( - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - int thread_id, - const base::TimeTicks& timestamp, - base::trace_event::TraceArguments* args, - unsigned int flags); +// Define SetTraceValue for each allowed type. It stores the type and +// value in the return arguments. This allows this API to avoid declaring any +// structures so that it is portable to third_party libraries. +#define INTERNAL_DECLARE_SET_TRACE_VALUE(actual_type, \ + arg_expression, \ + union_member, \ + value_type_id) \ + static inline void SetTraceValue( \ + actual_type arg, \ + unsigned char* type, \ + unsigned long long* value) { \ + TraceValueUnion type_value; \ + type_value.union_member = arg_expression; \ + *type = value_type_id; \ + *value = type_value.as_uint; \ + } +// Simpler form for int types that can be safely casted. +#define INTERNAL_DECLARE_SET_TRACE_VALUE_INT(actual_type, \ + value_type_id) \ + static inline void SetTraceValue( \ + actual_type arg, \ + unsigned char* type, \ + unsigned long long* value) { \ + *type = value_type_id; \ + *value = static_cast<unsigned long long>(arg); \ + } -base::trace_event::TraceEventHandle BASE_EXPORT -AddTraceEventWithThreadIdAndTimestamp( - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - unsigned long long bind_id, - int thread_id, - const base::TimeTicks& timestamp, - base::trace_event::TraceArguments* args, - unsigned int flags); +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned long long, TRACE_VALUE_TYPE_UINT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned long, TRACE_VALUE_TYPE_UINT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned int, TRACE_VALUE_TYPE_UINT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned short, TRACE_VALUE_TYPE_UINT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned char, TRACE_VALUE_TYPE_UINT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long long, TRACE_VALUE_TYPE_INT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long, TRACE_VALUE_TYPE_INT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int, TRACE_VALUE_TYPE_INT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(short, TRACE_VALUE_TYPE_INT) +INTERNAL_DECLARE_SET_TRACE_VALUE_INT(signed char, TRACE_VALUE_TYPE_INT) +INTERNAL_DECLARE_SET_TRACE_VALUE(bool, arg, as_bool, TRACE_VALUE_TYPE_BOOL) +INTERNAL_DECLARE_SET_TRACE_VALUE(double, arg, as_double, + TRACE_VALUE_TYPE_DOUBLE) +INTERNAL_DECLARE_SET_TRACE_VALUE(const void*, arg, as_pointer, + TRACE_VALUE_TYPE_POINTER) +INTERNAL_DECLARE_SET_TRACE_VALUE(const char*, arg, as_string, + TRACE_VALUE_TYPE_STRING) +INTERNAL_DECLARE_SET_TRACE_VALUE(const TraceStringWithCopy&, arg.str(), + as_string, TRACE_VALUE_TYPE_COPY_STRING) + +#undef INTERNAL_DECLARE_SET_TRACE_VALUE +#undef INTERNAL_DECLARE_SET_TRACE_VALUE_INT + +// std::string version of SetTraceValue so that trace arguments can be strings. +static inline void SetTraceValue(const std::string& arg, + unsigned char* type, + unsigned long long* value) { + TraceValueUnion type_value; + type_value.as_string = arg.c_str(); + *type = TRACE_VALUE_TYPE_COPY_STRING; + *value = type_value.as_uint; +} -void BASE_EXPORT AddMetadataEvent(const unsigned char* category_group_enabled, - const char* name, - base::trace_event::TraceArguments* args, - unsigned int flags); +// base::Time, base::TimeTicks, etc. versions of SetTraceValue to make it easier +// to trace these types. +static inline void SetTraceValue(const base::Time arg, + unsigned char* type, + unsigned long long* value) { + *type = TRACE_VALUE_TYPE_INT; + *value = arg.ToInternalValue(); +} -int BASE_EXPORT GetNumTracesRecorded(); +static inline void SetTraceValue(const base::TimeTicks arg, + unsigned char* type, + unsigned long long* value) { + *type = TRACE_VALUE_TYPE_INT; + *value = arg.ToInternalValue(); +} -void BASE_EXPORT -UpdateTraceEventDuration(const unsigned char* category_group_enabled, - const char* name, - base::trace_event::TraceEventHandle handle); +static inline void SetTraceValue(const base::ThreadTicks arg, + unsigned char* type, + unsigned long long* value) { + *type = TRACE_VALUE_TYPE_INT; + *value = arg.ToInternalValue(); +} -void BASE_EXPORT -UpdateTraceEventDurationExplicit(const unsigned char* category_group_enabled, - const char* name, - base::trace_event::TraceEventHandle handle, - const base::TimeTicks& now, - const base::ThreadTicks& thread_now); +// These functions all internally call +// base::trace_event::TraceLog::GetInstance() then call the method with the same +// name on it. This is used to reduce the generated machine code at each +// TRACE_EVENTXXX macro call. -// TODO(898794): Remove these functions once all callers have been updated -// to use base::trace_event::Arguments instead. base::trace_event::TraceEventHandle BASE_EXPORT AddTraceEvent(char phase, const unsigned char* category_group_enabled, @@ -829,13 +856,51 @@ AddMetadataEvent(const unsigned char* category_group_enabled, convertable_values, unsigned int flags); +int BASE_EXPORT GetNumTracesRecorded(); + +void BASE_EXPORT +UpdateTraceEventDuration(const unsigned char* category_group_enabled, + const char* name, + base::trace_event::TraceEventHandle handle); + +void BASE_EXPORT +UpdateTraceEventDurationExplicit(const unsigned char* category_group_enabled, + const char* name, + base::trace_event::TraceEventHandle handle, + const base::TimeTicks& now, + const base::ThreadTicks& thread_now); + // These AddTraceEvent and AddTraceEventWithThreadIdAndTimestamp template // functions are defined here instead of in the macro, because the arg_values // could be temporary objects, such as std::string. In order to store // pointers to the internal c_str and pass through to the tracing API, // the arg_values must live throughout these procedures. -template <class ARG1_TYPE> +template <class ARG1_CONVERTABLE_TYPE> +static inline base::trace_event::TraceEventHandle +AddTraceEventWithThreadIdAndTimestamp( + char phase, + const unsigned char* category_group_enabled, + const char* name, + const char* scope, + unsigned long long id, + int thread_id, + const base::TimeTicks& timestamp, + unsigned int flags, + unsigned long long bind_id, + const char* arg1_name, + std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg1_val) { + const int num_args = 1; + unsigned char arg_types[1] = { TRACE_VALUE_TYPE_CONVERTABLE }; + std::unique_ptr<base::trace_event::ConvertableToTraceFormat> + convertable_values[1] = {std::move(arg1_val)}; + return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( + phase, category_group_enabled, name, scope, id, bind_id, thread_id, + timestamp, num_args, &arg1_name, arg_types, NULL, convertable_values, + flags); +} + +template <class ARG1_TYPE, class ARG2_CONVERTABLE_TYPE> static inline base::trace_event::TraceEventHandle AddTraceEventWithThreadIdAndTimestamp( char phase, @@ -848,15 +913,25 @@ AddTraceEventWithThreadIdAndTimestamp( unsigned int flags, unsigned long long bind_id, const char* arg1_name, - ARG1_TYPE&& arg1_val) { - base::trace_event::TraceArguments args(arg1_name, - std::forward<ARG1_TYPE>(arg1_val)); + const ARG1_TYPE& arg1_val, + const char* arg2_name, + std::unique_ptr<ARG2_CONVERTABLE_TYPE> arg2_val) { + const int num_args = 2; + const char* arg_names[2] = { arg1_name, arg2_name }; + + unsigned char arg_types[2]; + unsigned long long arg_values[2]; + SetTraceValue(arg1_val, &arg_types[0], &arg_values[0]); + arg_types[1] = TRACE_VALUE_TYPE_CONVERTABLE; + std::unique_ptr<base::trace_event::ConvertableToTraceFormat> + convertable_values[2] = {nullptr, std::move(arg2_val)}; return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( phase, category_group_enabled, name, scope, id, bind_id, thread_id, - timestamp, &args, flags); + timestamp, num_args, arg_names, arg_types, arg_values, convertable_values, + flags); } -template <class ARG1_TYPE, class ARG2_TYPE> +template <class ARG1_CONVERTABLE_TYPE, class ARG2_TYPE> static inline base::trace_event::TraceEventHandle AddTraceEventWithThreadIdAndTimestamp( char phase, @@ -869,15 +944,51 @@ AddTraceEventWithThreadIdAndTimestamp( unsigned int flags, unsigned long long bind_id, const char* arg1_name, - ARG1_TYPE&& arg1_val, + std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg1_val, const char* arg2_name, - ARG2_TYPE&& arg2_val) { - base::trace_event::TraceArguments args( - arg1_name, std::forward<ARG1_TYPE>(arg1_val), arg2_name, - std::forward<ARG2_TYPE>(arg2_val)); + const ARG2_TYPE& arg2_val) { + const int num_args = 2; + const char* arg_names[2] = { arg1_name, arg2_name }; + + unsigned char arg_types[2]; + unsigned long long arg_values[2]; + arg_types[0] = TRACE_VALUE_TYPE_CONVERTABLE; + arg_values[0] = 0; + SetTraceValue(arg2_val, &arg_types[1], &arg_values[1]); + std::unique_ptr<base::trace_event::ConvertableToTraceFormat> + convertable_values[2] = {std::move(arg1_val), nullptr}; return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( phase, category_group_enabled, name, scope, id, bind_id, thread_id, - timestamp, &args, flags); + timestamp, num_args, arg_names, arg_types, arg_values, convertable_values, + flags); +} + +template <class ARG1_CONVERTABLE_TYPE, class ARG2_CONVERTABLE_TYPE> +static inline base::trace_event::TraceEventHandle +AddTraceEventWithThreadIdAndTimestamp( + char phase, + const unsigned char* category_group_enabled, + const char* name, + const char* scope, + unsigned long long id, + int thread_id, + const base::TimeTicks& timestamp, + unsigned int flags, + unsigned long long bind_id, + const char* arg1_name, + std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg1_val, + const char* arg2_name, + std::unique_ptr<ARG2_CONVERTABLE_TYPE> arg2_val) { + const int num_args = 2; + const char* arg_names[2] = { arg1_name, arg2_name }; + unsigned char arg_types[2] = + { TRACE_VALUE_TYPE_CONVERTABLE, TRACE_VALUE_TYPE_CONVERTABLE }; + std::unique_ptr<base::trace_event::ConvertableToTraceFormat> + convertable_values[2] = {std::move(arg1_val), std::move(arg2_val)}; + return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( + phase, category_group_enabled, name, scope, id, bind_id, thread_id, + timestamp, num_args, arg_names, arg_types, NULL, convertable_values, + flags); } static inline base::trace_event::TraceEventHandle @@ -893,7 +1004,7 @@ AddTraceEventWithThreadIdAndTimestamp( unsigned long long bind_id) { return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( phase, category_group_enabled, name, scope, id, bind_id, thread_id, - timestamp, nullptr, flags); + timestamp, kZeroNumArgs, NULL, NULL, NULL, NULL, flags); } static inline base::trace_event::TraceEventHandle AddTraceEvent( @@ -911,7 +1022,113 @@ static inline base::trace_event::TraceEventHandle AddTraceEvent( bind_id); } -template <class ARG1_TYPE> +template<class ARG1_TYPE> +static inline base::trace_event::TraceEventHandle +AddTraceEventWithThreadIdAndTimestamp( + char phase, + const unsigned char* category_group_enabled, + const char* name, + const char* scope, + unsigned long long id, + int thread_id, + const base::TimeTicks& timestamp, + unsigned int flags, + unsigned long long bind_id, + const char* arg1_name, + const ARG1_TYPE& arg1_val) { + const int num_args = 1; + unsigned char arg_types[1]; + unsigned long long arg_values[1]; + SetTraceValue(arg1_val, &arg_types[0], &arg_values[0]); + return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( + phase, category_group_enabled, name, scope, id, bind_id, thread_id, + timestamp, num_args, &arg1_name, arg_types, arg_values, NULL, flags); +} + +template<class ARG1_TYPE> +static inline base::trace_event::TraceEventHandle AddTraceEvent( + char phase, + const unsigned char* category_group_enabled, + const char* name, + const char* scope, + unsigned long long id, + unsigned int flags, + unsigned long long bind_id, + const char* arg1_name, + const ARG1_TYPE& arg1_val) { + int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); + base::TimeTicks now = TRACE_TIME_TICKS_NOW(); + return AddTraceEventWithThreadIdAndTimestamp( + phase, category_group_enabled, name, scope, id, thread_id, now, flags, + bind_id, arg1_name, arg1_val); +} + +template <class ARG1_CONVERTABLE_TYPE> +static inline base::trace_event::TraceEventHandle AddTraceEvent( + char phase, + const unsigned char* category_group_enabled, + const char* name, + const char* scope, + unsigned long long id, + unsigned int flags, + unsigned long long bind_id, + const char* arg1_name, + std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg1_val) { + int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); + base::TimeTicks now = TRACE_TIME_TICKS_NOW(); + return AddTraceEventWithThreadIdAndTimestamp( + phase, category_group_enabled, name, scope, id, thread_id, now, flags, + bind_id, arg1_name, std::move(arg1_val)); +} + +template<class ARG1_TYPE, class ARG2_TYPE> +static inline base::trace_event::TraceEventHandle +AddTraceEventWithThreadIdAndTimestamp( + char phase, + const unsigned char* category_group_enabled, + const char* name, + const char* scope, + unsigned long long id, + int thread_id, + const base::TimeTicks& timestamp, + unsigned int flags, + unsigned long long bind_id, + const char* arg1_name, + const ARG1_TYPE& arg1_val, + const char* arg2_name, + const ARG2_TYPE& arg2_val) { + const int num_args = 2; + const char* arg_names[2] = { arg1_name, arg2_name }; + unsigned char arg_types[2]; + unsigned long long arg_values[2]; + SetTraceValue(arg1_val, &arg_types[0], &arg_values[0]); + SetTraceValue(arg2_val, &arg_types[1], &arg_values[1]); + return TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( + phase, category_group_enabled, name, scope, id, bind_id, thread_id, + timestamp, num_args, arg_names, arg_types, arg_values, NULL, flags); +} + +template <class ARG1_CONVERTABLE_TYPE, class ARG2_TYPE> +static inline base::trace_event::TraceEventHandle AddTraceEvent( + char phase, + const unsigned char* category_group_enabled, + const char* name, + const char* scope, + unsigned long long id, + unsigned int flags, + unsigned long long bind_id, + const char* arg1_name, + std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg1_val, + const char* arg2_name, + const ARG2_TYPE& arg2_val) { + int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); + base::TimeTicks now = TRACE_TIME_TICKS_NOW(); + return AddTraceEventWithThreadIdAndTimestamp( + phase, category_group_enabled, name, scope, id, thread_id, now, flags, + bind_id, arg1_name, std::move(arg1_val), arg2_name, arg2_val); +} + +template <class ARG1_TYPE, class ARG2_CONVERTABLE_TYPE> static inline base::trace_event::TraceEventHandle AddTraceEvent( char phase, const unsigned char* category_group_enabled, @@ -921,15 +1138,17 @@ static inline base::trace_event::TraceEventHandle AddTraceEvent( unsigned int flags, unsigned long long bind_id, const char* arg1_name, - ARG1_TYPE&& arg1_val) { + const ARG1_TYPE& arg1_val, + const char* arg2_name, + std::unique_ptr<ARG2_CONVERTABLE_TYPE> arg2_val) { int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); base::TimeTicks now = TRACE_TIME_TICKS_NOW(); return AddTraceEventWithThreadIdAndTimestamp( phase, category_group_enabled, name, scope, id, thread_id, now, flags, - bind_id, arg1_name, std::forward<ARG1_TYPE>(arg1_val)); + bind_id, arg1_name, arg1_val, arg2_name, std::move(arg2_val)); } -template <class ARG1_TYPE, class ARG2_TYPE> +template <class ARG1_CONVERTABLE_TYPE, class ARG2_CONVERTABLE_TYPE> static inline base::trace_event::TraceEventHandle AddTraceEvent( char phase, const unsigned char* category_group_enabled, @@ -939,26 +1158,68 @@ static inline base::trace_event::TraceEventHandle AddTraceEvent( unsigned int flags, unsigned long long bind_id, const char* arg1_name, - ARG1_TYPE&& arg1_val, + std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg1_val, const char* arg2_name, - ARG2_TYPE&& arg2_val) { + std::unique_ptr<ARG2_CONVERTABLE_TYPE> arg2_val) { int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); base::TimeTicks now = TRACE_TIME_TICKS_NOW(); return AddTraceEventWithThreadIdAndTimestamp( phase, category_group_enabled, name, scope, id, thread_id, now, flags, - bind_id, arg1_name, std::forward<ARG1_TYPE>(arg1_val), arg2_name, - std::forward<ARG2_TYPE>(arg2_val)); + bind_id, arg1_name, std::move(arg1_val), arg2_name, std::move(arg2_val)); +} + +template<class ARG1_TYPE, class ARG2_TYPE> +static inline base::trace_event::TraceEventHandle AddTraceEvent( + char phase, + const unsigned char* category_group_enabled, + const char* name, + const char* scope, + unsigned long long id, + unsigned int flags, + unsigned long long bind_id, + const char* arg1_name, + const ARG1_TYPE& arg1_val, + const char* arg2_name, + const ARG2_TYPE& arg2_val) { + int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); + base::TimeTicks now = TRACE_TIME_TICKS_NOW(); + return AddTraceEventWithThreadIdAndTimestamp( + phase, category_group_enabled, name, scope, id, thread_id, now, flags, + bind_id, arg1_name, arg1_val, arg2_name, arg2_val); +} + +template <class ARG1_CONVERTABLE_TYPE> +static inline void AddMetadataEvent( + const unsigned char* category_group_enabled, + const char* event_name, + const char* arg_name, + std::unique_ptr<ARG1_CONVERTABLE_TYPE> arg_value) { + const char* arg_names[1] = {arg_name}; + unsigned char arg_types[1] = {TRACE_VALUE_TYPE_CONVERTABLE}; + std::unique_ptr<base::trace_event::ConvertableToTraceFormat> + convertable_values[1] = {std::move(arg_value)}; + trace_event_internal::AddMetadataEvent(category_group_enabled, event_name, + 1, // num_args + arg_names, arg_types, + nullptr, // arg_values + convertable_values, + TRACE_EVENT_FLAG_NONE); } template <class ARG1_TYPE> static void AddMetadataEvent(const unsigned char* category_group_enabled, const char* event_name, const char* arg_name, - ARG1_TYPE&& arg_val) { - base::trace_event::TraceArguments args(arg_name, - std::forward<ARG1_TYPE>(arg_val)); - trace_event_internal::AddMetadataEvent(category_group_enabled, event_name, - &args, TRACE_EVENT_FLAG_NONE); + const ARG1_TYPE& arg_val) { + const int num_args = 1; + const char* arg_names[1] = {arg_name}; + unsigned char arg_types[1]; + unsigned long long arg_values[1]; + SetTraceValue(arg_val, &arg_types[0], &arg_values[0]); + + trace_event_internal::AddMetadataEvent( + category_group_enabled, event_name, num_args, arg_names, arg_types, + arg_values, nullptr, TRACE_EVENT_FLAG_NONE); } // Used by TRACE_EVENTx macros. Do not use directly. diff --git a/chromium/base/trace_event/trace_event_android.cc b/chromium/base/trace_event/trace_event_android.cc index a1e51e8f21d..30d9c74a6d7 100644 --- a/chromium/base/trace_event/trace_event_android.cc +++ b/chromium/base/trace_event/trace_event_android.cc @@ -39,25 +39,32 @@ void WriteToATrace(int fd, const char* buffer, size_t size) { } } -void WriteEvent(char phase, - const char* category_group, - const char* name, - unsigned long long id, - const TraceArguments& args, - unsigned int flags) { +void WriteEvent( + char phase, + const char* category_group, + const char* name, + unsigned long long id, + const char** arg_names, + const unsigned char* arg_types, + const TraceEvent::TraceValue* arg_values, + const std::unique_ptr<ConvertableToTraceFormat>* convertable_values, + unsigned int flags) { std::string out = StringPrintf("%c|%d|%s", phase, getpid(), name); if (flags & TRACE_EVENT_FLAG_HAS_ID) StringAppendF(&out, "-%" PRIx64, static_cast<uint64_t>(id)); out += '|'; - const char* const* arg_names = args.names(); - for (size_t i = 0; i < args.size() && arg_names[i]; ++i) { + for (int i = 0; i < kTraceMaxNumArgs && arg_names[i]; + ++i) { if (i) out += ';'; out += arg_names[i]; out += '='; std::string::size_type value_start = out.length(); - args.values()[i].AppendAsJSON(args.types()[i], &out); + if (arg_types[i] == TRACE_VALUE_TYPE_CONVERTABLE) + convertable_values[i]->AppendAsTraceFormat(&out); + else + TraceEvent::AppendValueAsJSON(arg_types[i], arg_values[i], &out); // Remove the quotes which may confuse the atrace script. ReplaceSubstringsAfterOffset(&out, value_start, "\\\"", "'"); @@ -140,35 +147,43 @@ void TraceEvent::SendToATrace() { switch (phase_) { case TRACE_EVENT_PHASE_BEGIN: - WriteEvent('B', category_group, name_, id_, args_, flags_); + WriteEvent('B', category_group, name_, id_, + arg_names_, arg_types_, arg_values_, convertable_values_, + flags_); break; case TRACE_EVENT_PHASE_COMPLETE: - WriteEvent(duration_.ToInternalValue() == -1 ? 'B' : 'E', category_group, - name_, id_, args_, flags_); + WriteEvent(duration_.ToInternalValue() == -1 ? 'B' : 'E', + category_group, name_, id_, + arg_names_, arg_types_, arg_values_, convertable_values_, + flags_); break; case TRACE_EVENT_PHASE_END: // Though a single 'E' is enough, here append pid, name and // category_group etc. So that unpaired events can be found easily. - WriteEvent('E', category_group, name_, id_, args_, flags_); + WriteEvent('E', category_group, name_, id_, + arg_names_, arg_types_, arg_values_, convertable_values_, + flags_); break; case TRACE_EVENT_PHASE_INSTANT: // Simulate an instance event with a pair of begin/end events. - WriteEvent('B', category_group, name_, id_, args_, flags_); + WriteEvent('B', category_group, name_, id_, + arg_names_, arg_types_, arg_values_, convertable_values_, + flags_); WriteToATrace(g_atrace_fd, "E", 1); break; case TRACE_EVENT_PHASE_COUNTER: - for (size_t i = 0; i < arg_size() && arg_name(i); ++i) { - DCHECK(arg_type(i) == TRACE_VALUE_TYPE_INT); - std::string out = - base::StringPrintf("C|%d|%s-%s", getpid(), name_, arg_name(i)); + for (int i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) { + DCHECK(arg_types_[i] == TRACE_VALUE_TYPE_INT); + std::string out = base::StringPrintf( + "C|%d|%s-%s", getpid(), name_, arg_names_[i]); if (flags_ & TRACE_EVENT_FLAG_HAS_ID) StringAppendF(&out, "-%" PRIx64, static_cast<uint64_t>(id_)); - StringAppendF(&out, "|%d|%s", static_cast<int>(arg_value(i).as_int), - category_group); + StringAppendF(&out, "|%d|%s", + static_cast<int>(arg_values_[i].as_int), category_group); WriteToATrace(g_atrace_fd, out.c_str(), out.size()); } break; diff --git a/chromium/base/trace_event/trace_event_etw_export_win.cc b/chromium/base/trace_event/trace_event_etw_export_win.cc index e2c4f80dc16..89059da3556 100644 --- a/chromium/base/trace_event/trace_event_etw_export_win.cc +++ b/chromium/base/trace_event/trace_event_etw_export_win.cc @@ -168,11 +168,16 @@ bool TraceEventETWExport::IsETWExportEnabled() { } // static -void TraceEventETWExport::AddEvent(char phase, - const unsigned char* category_group_enabled, - const char* name, - unsigned long long id, - const TraceArguments* args) { +void TraceEventETWExport::AddEvent( + char phase, + const unsigned char* category_group_enabled, + const char* name, + unsigned long long id, + int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + const std::unique_ptr<ConvertableToTraceFormat>* convertable_values) { // We bail early in case exporting is disabled or no consumer is listening. auto* instance = GetInstance(); if (!instance || !instance->etw_export_enabled_ || !EventEnabledChromeEvent()) @@ -250,22 +255,26 @@ void TraceEventETWExport::AddEvent(char phase, } std::string arg_values_string[3]; - size_t num_args = args ? args->size() : 0; - for (size_t i = 0; i < num_args; i++) { - if (args->types()[i] == TRACE_VALUE_TYPE_CONVERTABLE) { + for (int i = 0; i < num_args; i++) { + if (arg_types[i] == TRACE_VALUE_TYPE_CONVERTABLE) { // Temporarily do nothing here. This function consumes 1/3 to 1/2 of // *total* process CPU time when ETW tracing, and many of the strings // created exceed WPA's 4094 byte limit and are shown as: // "Unable to parse data". See crbug.com/488257 + // convertable_values[i]->AppendAsTraceFormat(arg_values_string + i); } else { - args->values()[i].AppendAsJSON(args->types()[i], arg_values_string + i); + TraceEvent::TraceValue trace_event; + trace_event.as_uint = arg_values[i]; + TraceEvent::AppendValueAsJSON(arg_types[i], trace_event, + arg_values_string + i); } } EventWriteChromeEvent( - name, phase_string, num_args > 0 ? args->names()[0] : "", - arg_values_string[0].c_str(), num_args > 1 ? args->names()[1] : "", - arg_values_string[1].c_str(), "", ""); + name, phase_string, num_args > 0 ? arg_names[0] : "", + arg_values_string[0].c_str(), num_args > 1 ? arg_names[1] : "", + arg_values_string[1].c_str(), num_args > 2 ? arg_names[2] : "", + arg_values_string[2].c_str()); } // static diff --git a/chromium/base/trace_event/trace_event_etw_export_win.h b/chromium/base/trace_event/trace_event_etw_export_win.h index ac19553a527..345e87b9ae9 100644 --- a/chromium/base/trace_event/trace_event_etw_export_win.h +++ b/chromium/base/trace_event/trace_event_etw_export_win.h @@ -47,11 +47,16 @@ class BASE_EXPORT TraceEventETWExport { // Exports an event to ETW. This is mainly used in // TraceLog::AddTraceEventWithThreadIdAndTimestamp to export internal events. - static void AddEvent(char phase, - const unsigned char* category_group_enabled, - const char* name, - unsigned long long id, - const TraceArguments* args); + static void AddEvent( + char phase, + const unsigned char* category_group_enabled, + const char* name, + unsigned long long id, + int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + const std::unique_ptr<ConvertableToTraceFormat>* convertable_values); // Exports an ETW event that marks the end of a complete event. static void AddCompleteEndEvent(const char* name); diff --git a/chromium/base/trace_event/trace_event_impl.cc b/chromium/base/trace_event/trace_event_impl.cc index ee3e21d4483..66b69c3d87f 100644 --- a/chromium/base/trace_event/trace_event_impl.cc +++ b/chromium/base/trace_event/trace_event_impl.cc @@ -22,6 +22,25 @@ namespace base { namespace trace_event { +namespace { + +size_t GetAllocLength(const char* str) { return str ? strlen(str) + 1 : 0; } + +// Copies |*member| into |*buffer|, sets |*member| to point to this new +// location, and then advances |*buffer| by the amount written. +void CopyTraceEventParameter(char** buffer, + const char** member, + const char* end) { + if (*member) { + size_t written = strlcpy(*buffer, *member, end - *buffer) + 1; + DCHECK_LE(static_cast<int>(written), end - *buffer); + *member = *buffer; + *buffer += written; + } +} + +} // namespace + bool ConvertableToTraceFormat::AppendToProto(ProtoAppender* appender) { return false; } @@ -30,19 +49,48 @@ bool ConvertableToTraceFormat::AppendToProto(ProtoAppender* appender) { static_assert(trace_event_internal::kGlobalScope == nullptr, "Invalid TraceEvent::scope default initializer value"); -TraceEvent::TraceEvent() = default; - -TraceEvent::TraceEvent(int thread_id, - TimeTicks timestamp, - ThreadTicks thread_timestamp, - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - unsigned long long bind_id, - TraceArguments* args, - unsigned int flags) +TraceEvent::TraceEvent() { + for (int i = 0; i < kTraceMaxNumArgs; ++i) { + arg_values_[i].as_uint = 0u; + arg_names_[i] = nullptr; + arg_types_[i] = TRACE_VALUE_TYPE_UINT; + } +} + +TraceEvent::~TraceEvent() = default; + +TraceEvent::TraceEvent(TraceEvent&& other) noexcept = default; + +#if !defined(__clang__) +// Clang will crash at runtime when trying to compile the line below +// with coverage instrumentation enabled (https://crbug.com/908937) +TraceEvent& TraceEvent::operator=(TraceEvent&& other) noexcept = default; +#else // defined(__clang__) +TraceEvent& TraceEvent::operator=(TraceEvent&& other) noexcept { + if (this != &other) { + this->~TraceEvent(); + new (this) TraceEvent(std::move(other)); + } + return *this; +} +#endif // defined(__clang__) + +TraceEvent::TraceEvent( + int thread_id, + TimeTicks timestamp, + ThreadTicks thread_timestamp, + char phase, + const unsigned char* category_group_enabled, + const char* name, + const char* scope, + unsigned long long id, + unsigned long long bind_id, + int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + std::unique_ptr<ConvertableToTraceFormat>* convertable_values, + unsigned int flags) : timestamp_(timestamp), thread_timestamp_(thread_timestamp), scope_(scope), @@ -53,33 +101,121 @@ TraceEvent::TraceEvent(int thread_id, flags_(flags), bind_id_(bind_id), phase_(phase) { - InitArgs(args); + InitArgs(num_args, arg_names, arg_types, arg_values, convertable_values, + flags); } -TraceEvent::~TraceEvent() = default; +void TraceEvent::InitArgs( + int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + std::unique_ptr<ConvertableToTraceFormat>* convertable_values, + unsigned int flags) { + // Clamp num_args since it may have been set by a third_party library. + num_args = (num_args > kTraceMaxNumArgs) ? kTraceMaxNumArgs : num_args; + int i = 0; + for (; i < num_args; ++i) { + arg_names_[i] = arg_names[i]; + arg_types_[i] = arg_types[i]; + + if (arg_types[i] == TRACE_VALUE_TYPE_CONVERTABLE) { + convertable_values_[i] = std::move(convertable_values[i]); + } else { + arg_values_[i].as_uint = arg_values[i]; + convertable_values_[i].reset(); + } + } + for (; i < kTraceMaxNumArgs; ++i) { + arg_names_[i] = nullptr; + arg_values_[i].as_uint = 0u; + convertable_values_[i].reset(); + arg_types_[i] = TRACE_VALUE_TYPE_UINT; + } -TraceEvent::TraceEvent(TraceEvent&& other) noexcept = default; -TraceEvent& TraceEvent::operator=(TraceEvent&& other) noexcept = default; + bool copy = !!(flags & TRACE_EVENT_FLAG_COPY); + size_t alloc_size = 0; + if (copy) { + alloc_size += GetAllocLength(name_) + GetAllocLength(scope_); + for (i = 0; i < num_args; ++i) { + alloc_size += GetAllocLength(arg_names_[i]); + if (arg_types_[i] == TRACE_VALUE_TYPE_STRING) + arg_types_[i] = TRACE_VALUE_TYPE_COPY_STRING; + } + } + + bool arg_is_copy[kTraceMaxNumArgs]; + for (i = 0; i < num_args; ++i) { + // No copying of convertable types, we retain ownership. + if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE) + continue; + + // We only take a copy of arg_vals if they are of type COPY_STRING. + arg_is_copy[i] = (arg_types_[i] == TRACE_VALUE_TYPE_COPY_STRING); + if (arg_is_copy[i]) + alloc_size += GetAllocLength(arg_values_[i].as_string); + } + + if (alloc_size) { + parameter_copy_storage_.reset(new std::string); + parameter_copy_storage_->resize(alloc_size); + char* ptr = base::data(*parameter_copy_storage_); + const char* end = ptr + alloc_size; + if (copy) { + CopyTraceEventParameter(&ptr, &name_, end); + CopyTraceEventParameter(&ptr, &scope_, end); + for (i = 0; i < num_args; ++i) { + CopyTraceEventParameter(&ptr, &arg_names_[i], end); + } + } + for (i = 0; i < num_args; ++i) { + if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE) + continue; + if (arg_is_copy[i]) + CopyTraceEventParameter(&ptr, &arg_values_[i].as_string, end); + } + DCHECK_EQ(end, ptr) << "Overrun by " << ptr - end; + } +} void TraceEvent::Reset() { // Only reset fields that won't be initialized in Reset(int, ...), or that may // hold references to other objects. duration_ = TimeDelta::FromInternalValue(-1); - args_.Reset(); - parameter_copy_storage_.Reset(); + + // The following pointers might point into parameter_copy_storage_ so + // must be reset to nullptr first. + for (int i = 0; i < kTraceMaxNumArgs; ++i) { + arg_names_[i] = nullptr; + arg_values_[i].as_uint = 0u; + arg_types_[i] = TRACE_VALUE_TYPE_UINT; + } + scope_ = nullptr; + name_ = nullptr; + + // It is now safe to reset the storage area. + parameter_copy_storage_.reset(); + + for (int i = 0; i < kTraceMaxNumArgs; ++i) + convertable_values_[i].reset(); } -void TraceEvent::Reset(int thread_id, - TimeTicks timestamp, - ThreadTicks thread_timestamp, - char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - unsigned long long bind_id, - TraceArguments* args, - unsigned int flags) { +void TraceEvent::Reset( + int thread_id, + TimeTicks timestamp, + ThreadTicks thread_timestamp, + char phase, + const unsigned char* category_group_enabled, + const char* name, + const char* scope, + unsigned long long id, + unsigned long long bind_id, + int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + std::unique_ptr<ConvertableToTraceFormat>* convertable_values, + unsigned int flags) { Reset(); timestamp_ = timestamp; thread_timestamp_ = thread_timestamp; @@ -92,14 +228,8 @@ void TraceEvent::Reset(int thread_id, bind_id_ = bind_id; phase_ = phase; - InitArgs(args); -} - -void TraceEvent::InitArgs(TraceArguments* args) { - if (args) - args_ = std::move(*args); - args_.CopyStringsTo(¶meter_copy_storage_, - !!(flags_ & TRACE_EVENT_FLAG_COPY), &name_, &scope_); + InitArgs(num_args, arg_names, arg_types, arg_values, convertable_values, + flags); } void TraceEvent::UpdateDuration(const TimeTicks& now, @@ -115,12 +245,80 @@ void TraceEvent::UpdateDuration(const TimeTicks& now, void TraceEvent::EstimateTraceMemoryOverhead( TraceEventMemoryOverhead* overhead) { - overhead->Add(TraceEventMemoryOverhead::kTraceEvent, - parameter_copy_storage_.EstimateTraceMemoryOverhead()); + overhead->Add(TraceEventMemoryOverhead::kTraceEvent, sizeof(*this)); + + if (parameter_copy_storage_) + overhead->AddString(*parameter_copy_storage_); - for (size_t i = 0; i < arg_size(); ++i) { - if (arg_type(i) == TRACE_VALUE_TYPE_CONVERTABLE) - arg_value(i).as_convertable->EstimateTraceMemoryOverhead(overhead); + for (size_t i = 0; i < kTraceMaxNumArgs; ++i) { + if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE) + convertable_values_[i]->EstimateTraceMemoryOverhead(overhead); + } +} + +// static +void TraceEvent::AppendValueAsJSON(unsigned char type, + TraceEvent::TraceValue value, + std::string* out) { + switch (type) { + case TRACE_VALUE_TYPE_BOOL: + *out += value.as_bool ? "true" : "false"; + break; + case TRACE_VALUE_TYPE_UINT: + StringAppendF(out, "%" PRIu64, static_cast<uint64_t>(value.as_uint)); + break; + case TRACE_VALUE_TYPE_INT: + StringAppendF(out, "%" PRId64, static_cast<int64_t>(value.as_int)); + break; + case TRACE_VALUE_TYPE_DOUBLE: { + // FIXME: base/json/json_writer.cc is using the same code, + // should be made into a common method. + std::string real; + double val = value.as_double; + if (std::isfinite(val)) { + real = NumberToString(val); + // Ensure that the number has a .0 if there's no decimal or 'e'. This + // makes sure that when we read the JSON back, it's interpreted as a + // real rather than an int. + if (real.find('.') == std::string::npos && + real.find('e') == std::string::npos && + real.find('E') == std::string::npos) { + real.append(".0"); + } + // The JSON spec requires that non-integer values in the range (-1,1) + // have a zero before the decimal point - ".52" is not valid, "0.52" is. + if (real[0] == '.') { + real.insert(0, "0"); + } else if (real.length() > 1 && real[0] == '-' && real[1] == '.') { + // "-.1" bad "-0.1" good + real.insert(1, "0"); + } + } else if (std::isnan(val)){ + // The JSON spec doesn't allow NaN and Infinity (since these are + // objects in EcmaScript). Use strings instead. + real = "\"NaN\""; + } else if (val < 0) { + real = "\"-Infinity\""; + } else { + real = "\"Infinity\""; + } + StringAppendF(out, "%s", real.c_str()); + break; + } + case TRACE_VALUE_TYPE_POINTER: + // JSON only supports double and int numbers. + // So as not to lose bits from a 64-bit pointer, output as a hex string. + StringAppendF( + out, "\"0x%" PRIx64 "\"", + static_cast<uint64_t>(reinterpret_cast<uintptr_t>(value.as_pointer))); + break; + case TRACE_VALUE_TYPE_STRING: + case TRACE_VALUE_TYPE_COPY_STRING: + EscapeJSONString(value.as_string ? value.as_string : "NULL", true, out); + break; + default: + NOTREACHED() << "Don't know how to print this value"; + break; } } @@ -155,7 +353,7 @@ void TraceEvent::AppendAsJSON( // approach ArgumentNameFilterPredicate argument_name_filter_predicate; bool strip_args = - arg_size() > 0 && arg_name(0) && !argument_filter_predicate.is_null() && + arg_names_[0] && !argument_filter_predicate.is_null() && !argument_filter_predicate.Run(category_group_name, name_, &argument_name_filter_predicate); @@ -164,16 +362,19 @@ void TraceEvent::AppendAsJSON( } else { *out += "{"; - for (size_t i = 0; i < arg_size() && arg_name(i); ++i) { + for (int i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) { if (i > 0) *out += ","; *out += "\""; - *out += arg_name(i); + *out += arg_names_[i]; *out += "\":"; if (argument_name_filter_predicate.is_null() || - argument_name_filter_predicate.Run(arg_name(i))) { - arg_value(i).AppendAsJSON(arg_type(i), out); + argument_name_filter_predicate.Run(arg_names_[i])) { + if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE) + convertable_values_[i]->AppendAsTraceFormat(out); + else + AppendValueAsJSON(arg_types_[i], arg_values_[i], out); } else { *out += "\"__stripped__\""; } @@ -274,14 +475,19 @@ void TraceEvent::AppendPrettyPrinted(std::ostringstream* out) const { *out << name_ << "["; *out << TraceLog::GetCategoryGroupName(category_group_enabled_); *out << "]"; - if (arg_size() > 0 && arg_name(0)) { + if (arg_names_[0]) { *out << ", {"; - for (size_t i = 0; i < arg_size() && arg_name(i); ++i) { + for (int i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) { if (i > 0) *out << ", "; - *out << arg_name(i) << ":"; + *out << arg_names_[i] << ":"; std::string value_as_text; - arg_value(i).AppendAsJSON(arg_type(i), &value_as_text); + + if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE) + convertable_values_[i]->AppendAsTraceFormat(&value_as_text); + else + AppendValueAsJSON(arg_types_[i], arg_values_[i], &value_as_text); + *out << value_as_text; } *out << "}"; diff --git a/chromium/base/trace_event/trace_event_impl.h b/chromium/base/trace_event/trace_event_impl.h index 93eed6225b9..3c459530c52 100644 --- a/chromium/base/trace_event/trace_event_impl.h +++ b/chromium/base/trace_event/trace_event_impl.h @@ -23,7 +23,6 @@ #include "base/synchronization/lock.h" #include "base/threading/thread_local.h" #include "base/trace_event/common/trace_event_common.h" -#include "base/trace_event/trace_arguments.h" #include "base/trace_event/trace_event_memory_overhead.h" #include "build/build_config.h" @@ -37,6 +36,48 @@ typedef base::Callback<bool(const char* category_group_name, ArgumentNameFilterPredicate*)> ArgumentFilterPredicate; +// For any argument of type TRACE_VALUE_TYPE_CONVERTABLE the provided +// class must implement this interface. +class BASE_EXPORT ConvertableToTraceFormat { + public: + ConvertableToTraceFormat() = default; + virtual ~ConvertableToTraceFormat() = default; + + // Append the class info to the provided |out| string. The appended + // data must be a valid JSON object. Strings must be properly quoted, and + // escaped. There is no processing applied to the content after it is + // appended. + virtual void AppendAsTraceFormat(std::string* out) const = 0; + + // Append the class info directly into the Perfetto-defined proto + // format; this is attempted first and if this returns true, + // AppendAsTraceFormat is not called. The ProtoAppender interface + // acts as a bridge to avoid proto/Perfetto dependencies in base. + class BASE_EXPORT ProtoAppender { + public: + virtual ~ProtoAppender() = default; + + virtual void AddBuffer(uint8_t* begin, uint8_t* end) = 0; + // Copy all of the previous buffers registered with AddBuffer + // into the proto, with the given |field_id|. + virtual size_t Finalize(uint32_t field_id) = 0; + }; + virtual bool AppendToProto(ProtoAppender* appender); + + virtual void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead); + + std::string ToString() const { + std::string result; + AppendAsTraceFormat(&result); + return result; + } + + private: + DISALLOW_COPY_AND_ASSIGN(ConvertableToTraceFormat); +}; + +const int kTraceMaxNumArgs = 2; + struct TraceEventHandle { uint32_t chunk_seq; // These numbers of bits must be kept consistent with @@ -48,8 +89,14 @@ struct TraceEventHandle { class BASE_EXPORT TraceEvent { public: - // TODO(898794): Remove once all users have been updated. - using TraceValue = base::trace_event::TraceValue; + union TraceValue { + bool as_bool; + unsigned long long as_uint; + long long as_int; + double as_double; + const void* as_pointer; + const char* as_string; + }; TraceEvent(); @@ -62,7 +109,11 @@ class BASE_EXPORT TraceEvent { const char* scope, unsigned long long id, unsigned long long bind_id, - TraceArguments* args, + int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + std::unique_ptr<ConvertableToTraceFormat>* convertable_values, unsigned int flags); ~TraceEvent(); @@ -90,7 +141,11 @@ class BASE_EXPORT TraceEvent { const char* scope, unsigned long long id, unsigned long long bind_id, - TraceArguments* args, + int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + std::unique_ptr<ConvertableToTraceFormat>* convertable_values, unsigned int flags); void UpdateDuration(const TimeTicks& now, const ThreadTicks& thread_now); @@ -103,12 +158,9 @@ class BASE_EXPORT TraceEvent { const ArgumentFilterPredicate& argument_filter_predicate) const; void AppendPrettyPrinted(std::ostringstream* out) const; - // TODO(898794): Remove once caller has been updated. static void AppendValueAsJSON(unsigned char type, TraceValue value, - std::string* out) { - value.AppendAsJSON(type, out); - } + std::string* out); TimeTicks timestamp() const { return timestamp_; } ThreadTicks thread_timestamp() const { return thread_timestamp_; } @@ -123,8 +175,8 @@ class BASE_EXPORT TraceEvent { unsigned long long bind_id() const { return bind_id_; } // Exposed for unittesting: - const StringStorage& parameter_copy_storage() const { - return parameter_copy_storage_; + const std::string* parameter_copy_storage() const { + return parameter_copy_storage_.get(); } const unsigned char* category_group_enabled() const { @@ -133,17 +185,12 @@ class BASE_EXPORT TraceEvent { const char* name() const { return name_; } - size_t arg_size() const { return args_.size(); } - unsigned char arg_type(size_t index) const { return args_.types()[index]; } - const char* arg_name(size_t index) const { return args_.names()[index]; } - const TraceValue& arg_value(size_t index) const { - return args_.values()[index]; - } + unsigned char arg_type(size_t index) const { return arg_types_[index]; } + const char* arg_name(size_t index) const { return arg_names_[index]; } + const TraceValue& arg_value(size_t index) const { return arg_values_[index]; } ConvertableToTraceFormat* arg_convertible_value(size_t index) { - return (arg_type(index) == TRACE_VALUE_TYPE_CONVERTABLE) - ? arg_value(index).as_convertable - : nullptr; + return convertable_values_[index].get(); } #if defined(OS_ANDROID) @@ -151,7 +198,12 @@ class BASE_EXPORT TraceEvent { #endif private: - void InitArgs(TraceArguments* args); + void InitArgs(int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + std::unique_ptr<ConvertableToTraceFormat>* convertable_values, + unsigned int flags); // Note: these are ordered by size (largest first) for optimal packing. TimeTicks timestamp_ = TimeTicks(); @@ -165,10 +217,13 @@ class BASE_EXPORT TraceEvent { // The equivalence is checked with a static_assert() in trace_event_impl.cc. const char* scope_ = nullptr; unsigned long long id_ = 0u; + TraceValue arg_values_[kTraceMaxNumArgs]; + const char* arg_names_[kTraceMaxNumArgs]; + std::unique_ptr<ConvertableToTraceFormat> + convertable_values_[kTraceMaxNumArgs]; const unsigned char* category_group_enabled_ = nullptr; const char* name_ = nullptr; - StringStorage parameter_copy_storage_; - TraceArguments args_; + std::unique_ptr<std::string> parameter_copy_storage_; // Depending on TRACE_EVENT_FLAG_HAS_PROCESS_ID the event will have either: // tid: thread_id_, pid: current_process_id (default case). // tid: -1, pid: process_id_ (when flags_ & TRACE_EVENT_FLAG_HAS_PROCESS_ID). @@ -178,6 +233,7 @@ class BASE_EXPORT TraceEvent { }; unsigned int flags_ = 0; unsigned long long bind_id_ = 0; + unsigned char arg_types_[kTraceMaxNumArgs]; char phase_ = TRACE_EVENT_PHASE_BEGIN; DISALLOW_COPY_AND_ASSIGN(TraceEvent); diff --git a/chromium/base/trace_event/trace_event_unittest.cc b/chromium/base/trace_event/trace_event_unittest.cc index 47272e195c4..a0d46822e2f 100644 --- a/chromium/base/trace_event/trace_event_unittest.cc +++ b/chromium/base/trace_event/trace_event_unittest.cc @@ -1672,10 +1672,10 @@ TEST_F(TraceEventTestFixture, StaticStringVsString) { ASSERT_TRUE(event2); EXPECT_STREQ("name1", event1->name()); EXPECT_STREQ("name2", event2->name()); - EXPECT_FALSE(event1->parameter_copy_storage().empty()); - EXPECT_FALSE(event2->parameter_copy_storage().empty()); - EXPECT_GT(event1->parameter_copy_storage().size(), 0u); - EXPECT_GT(event2->parameter_copy_storage().size(), 0u); + EXPECT_TRUE(event1->parameter_copy_storage() != nullptr); + EXPECT_TRUE(event2->parameter_copy_storage() != nullptr); + EXPECT_GT(event1->parameter_copy_storage()->size(), 0u); + EXPECT_GT(event2->parameter_copy_storage()->size(), 0u); EndTraceAndFlush(); } @@ -1705,8 +1705,8 @@ TEST_F(TraceEventTestFixture, StaticStringVsString) { ASSERT_TRUE(event2); EXPECT_STREQ("name1", event1->name()); EXPECT_STREQ("name2", event2->name()); - EXPECT_TRUE(event1->parameter_copy_storage().empty()); - EXPECT_TRUE(event2->parameter_copy_storage().empty()); + EXPECT_TRUE(event1->parameter_copy_storage() == nullptr); + EXPECT_TRUE(event2->parameter_copy_storage() == nullptr); EndTraceAndFlush(); } } diff --git a/chromium/base/trace_event/trace_log.cc b/chromium/base/trace_event/trace_log.cc index 2f704e59bb5..1ab7161fc16 100644 --- a/chromium/base/trace_event/trace_log.cc +++ b/chromium/base/trace_event/trace_log.cc @@ -107,14 +107,19 @@ void InitializeMetadataEvent(TraceEvent* trace_event, if (!trace_event) return; - TraceArguments args(arg_name, value); + int num_args = 1; + unsigned char arg_type; + unsigned long long arg_value; + ::trace_event_internal::SetTraceValue(value, &arg_type, &arg_value); + trace_event->Reset( thread_id, TimeTicks(), ThreadTicks(), TRACE_EVENT_PHASE_METADATA, CategoryRegistry::kCategoryMetadata->state_ptr(), metadata_name, trace_event_internal::kGlobalScope, // scope trace_event_internal::kNoId, // id trace_event_internal::kNoId, // bind_id - &args, TRACE_EVENT_FLAG_NONE); + num_args, &arg_name, &arg_type, &arg_value, nullptr, + TRACE_EVENT_FLAG_NONE); } class AutoThreadLocalBoolean { @@ -1065,14 +1070,29 @@ TraceEventHandle TraceLog::AddTraceEvent( const char* name, const char* scope, unsigned long long id, - TraceArguments* args, + int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + std::unique_ptr<ConvertableToTraceFormat>* convertable_values, unsigned int flags) { int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); base::TimeTicks now = TRACE_TIME_TICKS_NOW(); return AddTraceEventWithThreadIdAndTimestamp( - phase, category_group_enabled, name, scope, id, + phase, + category_group_enabled, + name, + scope, + id, trace_event_internal::kNoId, // bind_id - thread_id, now, args, flags); + thread_id, + now, + num_args, + arg_names, + arg_types, + arg_values, + convertable_values, + flags); } TraceEventHandle TraceLog::AddTraceEventWithBindId( @@ -1082,13 +1102,29 @@ TraceEventHandle TraceLog::AddTraceEventWithBindId( const char* scope, unsigned long long id, unsigned long long bind_id, - TraceArguments* args, + int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + std::unique_ptr<ConvertableToTraceFormat>* convertable_values, unsigned int flags) { int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); base::TimeTicks now = TRACE_TIME_TICKS_NOW(); return AddTraceEventWithThreadIdAndTimestamp( - phase, category_group_enabled, name, scope, id, bind_id, thread_id, now, - args, flags | TRACE_EVENT_FLAG_HAS_CONTEXT_ID); + phase, + category_group_enabled, + name, + scope, + id, + bind_id, + thread_id, + now, + num_args, + arg_names, + arg_types, + arg_values, + convertable_values, + flags | TRACE_EVENT_FLAG_HAS_CONTEXT_ID); } TraceEventHandle TraceLog::AddTraceEventWithProcessId( @@ -1098,13 +1134,28 @@ TraceEventHandle TraceLog::AddTraceEventWithProcessId( const char* scope, unsigned long long id, int process_id, - TraceArguments* args, + int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + std::unique_ptr<ConvertableToTraceFormat>* convertable_values, unsigned int flags) { base::TimeTicks now = TRACE_TIME_TICKS_NOW(); return AddTraceEventWithThreadIdAndTimestamp( - phase, category_group_enabled, name, scope, id, + phase, + category_group_enabled, + name, + scope, + id, trace_event_internal::kNoId, // bind_id - process_id, now, args, flags | TRACE_EVENT_FLAG_HAS_PROCESS_ID); + process_id, + now, + num_args, + arg_names, + arg_types, + arg_values, + convertable_values, + flags | TRACE_EVENT_FLAG_HAS_PROCESS_ID); } // Handle legacy calls to AddTraceEventWithThreadIdAndTimestamp @@ -1117,12 +1168,27 @@ TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp( unsigned long long id, int thread_id, const TimeTicks& timestamp, - TraceArguments* args, + int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + std::unique_ptr<ConvertableToTraceFormat>* convertable_values, unsigned int flags) { return AddTraceEventWithThreadIdAndTimestamp( - phase, category_group_enabled, name, scope, id, + phase, + category_group_enabled, + name, + scope, + id, trace_event_internal::kNoId, // bind_id - thread_id, timestamp, args, flags); + thread_id, + timestamp, + num_args, + arg_names, + arg_types, + arg_values, + convertable_values, + flags); } TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp( @@ -1134,7 +1200,11 @@ TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp( unsigned long long bind_id, int thread_id, const TimeTicks& timestamp, - TraceArguments* args, + int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + std::unique_ptr<ConvertableToTraceFormat>* convertable_values, unsigned int flags) { TraceEventHandle handle = {0, 0, 0}; if (!*category_group_enabled) @@ -1208,7 +1278,8 @@ TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp( // acquiring the lock, which is not needed for ETW as it's already threadsafe. if (*category_group_enabled & TraceCategory::ENABLED_FOR_ETW_EXPORT) TraceEventETWExport::AddEvent(phase, category_group_enabled, name, id, - args); + num_args, arg_names, arg_types, arg_values, + convertable_values); #endif // OS_WIN auto trace_event_override = @@ -1216,7 +1287,8 @@ TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp( if (trace_event_override) { TraceEvent new_trace_event(thread_id, offset_event_timestamp, thread_now, phase, category_group_enabled, name, scope, id, - bind_id, args, flags); + bind_id, num_args, arg_names, arg_types, + arg_values, convertable_values, flags); trace_event_override( &new_trace_event, @@ -1230,7 +1302,8 @@ TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp( if (*category_group_enabled & TraceCategory::ENABLED_FOR_FILTERING) { auto new_trace_event = std::make_unique<TraceEvent>( thread_id, offset_event_timestamp, thread_now, phase, - category_group_enabled, name, scope, id, bind_id, args, flags); + category_group_enabled, name, scope, id, bind_id, num_args, arg_names, + arg_types, arg_values, convertable_values, flags); disabled_by_filters = true; ForEachCategoryFilter( @@ -1263,7 +1336,8 @@ TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp( } else { trace_event->Reset(thread_id, offset_event_timestamp, thread_now, phase, category_group_enabled, name, scope, id, bind_id, - args, flags); + num_args, arg_names, arg_types, arg_values, + convertable_values, flags); } #if defined(OS_ANDROID) @@ -1284,10 +1358,15 @@ TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp( return handle; } -void TraceLog::AddMetadataEvent(const unsigned char* category_group_enabled, - const char* name, - TraceArguments* args, - unsigned int flags) { +void TraceLog::AddMetadataEvent( + const unsigned char* category_group_enabled, + const char* name, + int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + std::unique_ptr<ConvertableToTraceFormat>* convertable_values, + unsigned int flags) { HEAP_PROFILER_SCOPED_IGNORE; int thread_id = static_cast<int>(base::PlatformThread::CurrentId()); ThreadTicks thread_now = ThreadNow(); @@ -1299,7 +1378,7 @@ void TraceLog::AddMetadataEvent(const unsigned char* category_group_enabled, trace_event_internal::kGlobalScope, // scope trace_event_internal::kNoId, // id trace_event_internal::kNoId, // bind_id - args, flags); + num_args, arg_names, arg_types, arg_values, convertable_values, flags); metadata_events_.push_back(std::move(trace_event)); } @@ -1691,10 +1770,16 @@ base::trace_event::TraceEventHandle AddTraceEvent( const char* name, const char* scope, unsigned long long id, - base::trace_event::TraceArguments* args, + int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + std::unique_ptr<base::trace_event::ConvertableToTraceFormat>* + convertable_values, unsigned int flags) { return base::trace_event::TraceLog::GetInstance()->AddTraceEvent( - phase, category_group_enabled, name, scope, id, args, flags); + phase, category_group_enabled, name, scope, id, num_args, arg_names, + arg_types, arg_values, convertable_values, flags); } base::trace_event::TraceEventHandle AddTraceEventWithBindId( @@ -1704,10 +1789,16 @@ base::trace_event::TraceEventHandle AddTraceEventWithBindId( const char* scope, unsigned long long id, unsigned long long bind_id, - base::trace_event::TraceArguments* args, + int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + std::unique_ptr<base::trace_event::ConvertableToTraceFormat>* + convertable_values, unsigned int flags) { return base::trace_event::TraceLog::GetInstance()->AddTraceEventWithBindId( - phase, category_group_enabled, name, scope, id, bind_id, args, flags); + phase, category_group_enabled, name, scope, id, bind_id, num_args, + arg_names, arg_types, arg_values, convertable_values, flags); } base::trace_event::TraceEventHandle AddTraceEventWithProcessId( @@ -1717,10 +1808,16 @@ base::trace_event::TraceEventHandle AddTraceEventWithProcessId( const char* scope, unsigned long long id, int process_id, - base::trace_event::TraceArguments* args, + int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + std::unique_ptr<base::trace_event::ConvertableToTraceFormat>* + convertable_values, unsigned int flags) { return base::trace_event::TraceLog::GetInstance()->AddTraceEventWithProcessId( - phase, category_group_enabled, name, scope, id, process_id, args, flags); + phase, category_group_enabled, name, scope, id, process_id, num_args, + arg_names, arg_types, arg_values, convertable_values, flags); } base::trace_event::TraceEventHandle AddTraceEventWithThreadIdAndTimestamp( @@ -1731,12 +1828,18 @@ base::trace_event::TraceEventHandle AddTraceEventWithThreadIdAndTimestamp( unsigned long long id, int thread_id, const base::TimeTicks& timestamp, - base::trace_event::TraceArguments* args, + int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + std::unique_ptr<base::trace_event::ConvertableToTraceFormat>* + convertable_values, unsigned int flags) { return base::trace_event::TraceLog::GetInstance() - ->AddTraceEventWithThreadIdAndTimestamp(phase, category_group_enabled, - name, scope, id, thread_id, - timestamp, args, flags); + ->AddTraceEventWithThreadIdAndTimestamp( + phase, category_group_enabled, name, scope, id, thread_id, timestamp, + num_args, arg_names, arg_types, arg_values, convertable_values, + flags); } base::trace_event::TraceEventHandle AddTraceEventWithThreadIdAndTimestamp( @@ -1748,20 +1851,33 @@ base::trace_event::TraceEventHandle AddTraceEventWithThreadIdAndTimestamp( unsigned long long bind_id, int thread_id, const base::TimeTicks& timestamp, - base::trace_event::TraceArguments* args, + int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + std::unique_ptr<base::trace_event::ConvertableToTraceFormat>* + convertable_values, unsigned int flags) { return base::trace_event::TraceLog::GetInstance() ->AddTraceEventWithThreadIdAndTimestamp( phase, category_group_enabled, name, scope, id, bind_id, thread_id, - timestamp, args, flags); + timestamp, num_args, arg_names, arg_types, arg_values, + convertable_values, flags); } -void AddMetadataEvent(const unsigned char* category_group_enabled, - const char* name, - base::trace_event::TraceArguments* args, - unsigned int flags) { +void AddMetadataEvent( + const unsigned char* category_group_enabled, + const char* name, + int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + std::unique_ptr<base::trace_event::ConvertableToTraceFormat>* + convertable_values, + unsigned int flags) { return base::trace_event::TraceLog::GetInstance()->AddMetadataEvent( - category_group_enabled, name, args, flags); + category_group_enabled, name, num_args, arg_names, arg_types, arg_values, + convertable_values, flags); } int GetNumTracesRecorded() { @@ -1802,7 +1918,8 @@ ScopedTraceBinaryEfficient::ScopedTraceBinaryEfficient( trace_event_internal::kGlobalScope, // scope trace_event_internal::kNoId, // id static_cast<int>(base::PlatformThread::CurrentId()), // thread_id - TRACE_TIME_TICKS_NOW(), nullptr, TRACE_EVENT_FLAG_NONE); + TRACE_TIME_TICKS_NOW(), 0, nullptr, nullptr, nullptr, nullptr, + TRACE_EVENT_FLAG_NONE); } } diff --git a/chromium/base/trace_event/trace_log.h b/chromium/base/trace_event/trace_log.h index debdf7d835a..be5a483ba73 100644 --- a/chromium/base/trace_event/trace_log.h +++ b/chromium/base/trace_event/trace_log.h @@ -216,13 +216,20 @@ class BASE_EXPORT TraceLog : public MemoryDumpProvider { // Called by TRACE_EVENT* macros, don't call this directly. // If |copy| is set, |name|, |arg_name1| and |arg_name2| will be deep copied // into the event; see "Memory scoping note" and TRACE_EVENT_COPY_XXX above. - TraceEventHandle AddTraceEvent(char phase, - const unsigned char* category_group_enabled, - const char* name, - const char* scope, - unsigned long long id, - TraceArguments* args, - unsigned int flags); + + // TODO(898794): Remove methods below when all callers have been updated. + TraceEventHandle AddTraceEvent( + char phase, + const unsigned char* category_group_enabled, + const char* name, + const char* scope, + unsigned long long id, + int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + std::unique_ptr<ConvertableToTraceFormat>* convertable_values, + unsigned int flags); TraceEventHandle AddTraceEventWithBindId( char phase, const unsigned char* category_group_enabled, @@ -230,7 +237,11 @@ class BASE_EXPORT TraceLog : public MemoryDumpProvider { const char* scope, unsigned long long id, unsigned long long bind_id, - TraceArguments* args, + int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + std::unique_ptr<ConvertableToTraceFormat>* convertable_values, unsigned int flags); TraceEventHandle AddTraceEventWithProcessId( char phase, @@ -239,7 +250,11 @@ class BASE_EXPORT TraceLog : public MemoryDumpProvider { const char* scope, unsigned long long id, int process_id, - TraceArguments* args, + int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + std::unique_ptr<ConvertableToTraceFormat>* convertable_values, unsigned int flags); TraceEventHandle AddTraceEventWithThreadIdAndTimestamp( char phase, @@ -249,7 +264,11 @@ class BASE_EXPORT TraceLog : public MemoryDumpProvider { unsigned long long id, int thread_id, const TimeTicks& timestamp, - TraceArguments* args, + int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + std::unique_ptr<ConvertableToTraceFormat>* convertable_values, unsigned int flags); TraceEventHandle AddTraceEventWithThreadIdAndTimestamp( char phase, @@ -260,14 +279,23 @@ class BASE_EXPORT TraceLog : public MemoryDumpProvider { unsigned long long bind_id, int thread_id, const TimeTicks& timestamp, - TraceArguments* args, + int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + std::unique_ptr<ConvertableToTraceFormat>* convertable_values, unsigned int flags); // Adds a metadata event that will be written when the trace log is flushed. - void AddMetadataEvent(const unsigned char* category_group_enabled, - const char* name, - TraceArguments* args, - unsigned int flags); + void AddMetadataEvent( + const unsigned char* category_group_enabled, + const char* name, + int num_args, + const char* const* arg_names, + const unsigned char* arg_types, + const unsigned long long* arg_values, + std::unique_ptr<ConvertableToTraceFormat>* convertable_values, + unsigned int flags); void UpdateTraceEventDuration(const unsigned char* category_group_enabled, const char* name, diff --git a/chromium/gin/v8_platform.cc b/chromium/gin/v8_platform.cc index cdf89444b43..310b5b2be54 100644 --- a/chromium/gin/v8_platform.cc +++ b/chromium/gin/v8_platform.cc @@ -47,7 +47,7 @@ class ConvertableToTraceFormatWrapper final : public base::trace_event::ConvertableToTraceFormat { public: explicit ConvertableToTraceFormatWrapper( - std::unique_ptr<v8::ConvertableToTraceFormat> inner) + std::unique_ptr<v8::ConvertableToTraceFormat>& inner) : inner_(std::move(inner)) {} ~ConvertableToTraceFormatWrapper() override = default; void AppendAsTraceFormat(std::string* out) const final { @@ -266,26 +266,6 @@ base::LazyInstance<PageAllocator>::Leaky g_page_allocator = } // namespace -} // namespace gin - -// Allow std::unique_ptr<v8::ConvertableToTraceFormat> to be a valid -// initialization value for trace macros. -template <> -struct base::trace_event::TraceValue::Helper< - std::unique_ptr<v8::ConvertableToTraceFormat>> { - static constexpr unsigned char kType = TRACE_VALUE_TYPE_CONVERTABLE; - static inline void SetValue( - TraceValue* v, - std::unique_ptr<v8::ConvertableToTraceFormat> value) { - // NOTE: |as_convertable| is an owning pointer, so using new here - // is acceptable. - v->as_convertable = - new gin::ConvertableToTraceFormatWrapper(std::move(value)); - } -}; - -namespace gin { - class V8Platform::TracingControllerImpl : public v8::TracingController { public: TracingControllerImpl() = default; @@ -308,15 +288,22 @@ class V8Platform::TracingControllerImpl : public v8::TracingController { const uint64_t* arg_values, std::unique_ptr<v8::ConvertableToTraceFormat>* arg_convertables, unsigned int flags) override { - base::trace_event::TraceArguments args( - num_args, arg_names, arg_types, - reinterpret_cast<const unsigned long long*>(arg_values), - arg_convertables); + std::unique_ptr<base::trace_event::ConvertableToTraceFormat> + convertables[2]; + if (num_args > 0 && arg_types[0] == TRACE_VALUE_TYPE_CONVERTABLE) { + convertables[0].reset( + new ConvertableToTraceFormatWrapper(arg_convertables[0])); + } + if (num_args > 1 && arg_types[1] == TRACE_VALUE_TYPE_CONVERTABLE) { + convertables[1].reset( + new ConvertableToTraceFormatWrapper(arg_convertables[1])); + } DCHECK_LE(num_args, 2); base::trace_event::TraceEventHandle handle = TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_BIND_ID( - phase, category_enabled_flag, name, scope, id, bind_id, &args, - flags); + phase, category_enabled_flag, name, scope, id, bind_id, num_args, + arg_names, arg_types, (const long long unsigned int*)arg_values, + convertables, flags); uint64_t result; memcpy(&result, &handle, sizeof(result)); return result; diff --git a/chromium/ppapi/shared_impl/ppb_trace_event_impl.cc b/chromium/ppapi/shared_impl/ppb_trace_event_impl.cc index 2f26fb8c4e7..08bf7d07f48 100644 --- a/chromium/ppapi/shared_impl/ppb_trace_event_impl.cc +++ b/chromium/ppapi/shared_impl/ppb_trace_event_impl.cc @@ -40,15 +40,22 @@ void TraceEventImpl::AddTraceEvent(int8_t phase, static_assert(sizeof(unsigned long long) == sizeof(uint64_t), "unexpected data type sizes"); - // NOTE: The |arg_values| cast is required to avoid a compiler warning, - // since uint64_t and unsigned long long are not the same type, even - // though they have the same size, on all platforms we care about. - base::trace_event::TraceArguments args( - num_args, arg_names, arg_types, - reinterpret_cast<const unsigned long long*>(arg_values)); + base::trace_event::TraceLog::GetInstance()->AddTraceEvent( - phase, static_cast<const unsigned char*>(category_enabled), name, - trace_event_internal::kGlobalScope, id, &args, flags); + phase, + static_cast<const unsigned char*>(category_enabled), + name, + trace_event_internal::kGlobalScope, id, + num_args, + arg_names, + arg_types, + // This cast is necessary for LP64 systems, where uint64_t is defined as + // an unsigned long int, but trace_event internals are hermetic and + // accepts an |unsigned long long*|. The pointer types are compatible but + // the compiler throws an error without an explicit cast. + reinterpret_cast<const unsigned long long*>(arg_values), + NULL, + flags); } // static @@ -64,16 +71,25 @@ void TraceEventImpl::AddTraceEventWithThreadIdAndTimestamp( const uint8_t arg_types[], const uint64_t arg_values[], uint8_t flags) { - // See above comment about the cast to |const unsigned long long*|. - base::trace_event::TraceArguments args( - num_args, arg_names, arg_types, - reinterpret_cast<const unsigned long long*>(arg_values)); base::trace_event::TraceLog::GetInstance() ->AddTraceEventWithThreadIdAndTimestamp( - phase, static_cast<const unsigned char*>(category_enabled), name, - trace_event_internal::kGlobalScope, id, trace_event_internal::kNoId, - thread_id, base::TimeTicks::FromInternalValue(timestamp), &args, - flags); + phase, + static_cast<const unsigned char*>(category_enabled), + name, + trace_event_internal::kGlobalScope, id, + trace_event_internal::kNoId, + thread_id, + base::TimeTicks::FromInternalValue(timestamp), + num_args, + arg_names, + arg_types, + // This cast is necessary for LP64 systems, where uint64_t is defined as + // an unsigned long int, but trace_event internals are hermetic and + // accepts an |unsigned long long*|. The pointer types are compatible but + // the compiler throws an error without an explicit cast. + reinterpret_cast<const unsigned long long*>(arg_values), + NULL, + flags); } // static diff --git a/chromium/services/resource_coordinator/memory_instrumentation/coordinator_impl.cc b/chromium/services/resource_coordinator/memory_instrumentation/coordinator_impl.cc index 54c2b43f075..d539bfa7ae5 100644 --- a/chromium/services/resource_coordinator/memory_instrumentation/coordinator_impl.cc +++ b/chromium/services/resource_coordinator/memory_instrumentation/coordinator_impl.cc @@ -48,7 +48,7 @@ constexpr base::TimeDelta kHeapDumpTimeout = base::TimeDelta::FromSeconds(60); // event. class StringWrapper : public base::trace_event::ConvertableToTraceFormat { public: - explicit StringWrapper(std::string&& json) : json_(std::move(json)) {} + explicit StringWrapper(std::string json) : json_(std::move(json)) {} void AppendAsTraceFormat(std::string* out) const override { out->append(json_); @@ -552,8 +552,12 @@ void CoordinatorImpl::OnDumpProcessesForTracing( const char* char_buffer = static_cast<const char*>(mapping.get()); std::string json(char_buffer, char_buffer + size); - base::trace_event::TraceArguments args( - "dumps", std::make_unique<StringWrapper>(std::move(json))); + + const int kTraceEventNumArgs = 1; + const char* const kTraceEventArgNames[] = {"dumps"}; + const unsigned char kTraceEventArgTypes[] = {TRACE_VALUE_TYPE_CONVERTABLE}; + std::unique_ptr<base::trace_event::ConvertableToTraceFormat> wrapper( + new StringWrapper(std::move(json))); // Using the same id merges all of the heap dumps into a single detailed // dump node in the UI. @@ -562,7 +566,9 @@ void CoordinatorImpl::OnDumpProcessesForTracing( base::trace_event::TraceLog::GetCategoryGroupEnabled( base::trace_event::MemoryDumpManager::kTraceCategory), "periodic_interval", trace_event_internal::kGlobalScope, dump_guid, - buffer_ptr->pid, &args, TRACE_EVENT_FLAG_HAS_ID); + buffer_ptr->pid, kTraceEventNumArgs, kTraceEventArgNames, + kTraceEventArgTypes, nullptr /* arg_values */, &wrapper, + TRACE_EVENT_FLAG_HAS_ID); } FinalizeGlobalMemoryDumpIfAllManagersReplied(); diff --git a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.cc b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.cc index 0fc8548bb60..b8708ffa401 100644 --- a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.cc +++ b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.cc @@ -18,6 +18,10 @@ using base::trace_event::ProcessMemoryDump; namespace { +const int kTraceEventNumArgs = 1; +const char* const kTraceEventArgNames[] = {"dumps"}; +const unsigned char kTraceEventArgTypes[] = {TRACE_VALUE_TYPE_CONVERTABLE}; + bool IsMemoryInfraTracingEnabled() { bool enabled; TRACE_EVENT_CATEGORY_GROUP_ENABLED( @@ -116,14 +120,15 @@ void TracingObserver::AddToTrace( const uint64_t dump_guid = args.dump_guid; const char* const event_name = base::trace_event::MemoryDumpTypeToString(args.dump_type); - base::trace_event::TraceArguments trace_args("dumps", - std::move(traced_value)); + std::unique_ptr<base::trace_event::ConvertableToTraceFormat> event_value( + std::move(traced_value)); TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_PROCESS_ID( TRACE_EVENT_PHASE_MEMORY_DUMP, base::trace_event::TraceLog::GetCategoryGroupEnabled( base::trace_event::MemoryDumpManager::kTraceCategory), event_name, trace_event_internal::kGlobalScope, dump_guid, pid, - &trace_args, TRACE_EVENT_FLAG_HAS_ID); + kTraceEventNumArgs, kTraceEventArgNames, kTraceEventArgTypes, + nullptr /* arg_values */, &event_value, TRACE_EVENT_FLAG_HAS_ID); } bool TracingObserver::AddChromeDumpToTraceIfEnabled( diff --git a/chromium/services/tracing/public/cpp/perfetto/trace_event_data_source.cc b/chromium/services/tracing/public/cpp/perfetto/trace_event_data_source.cc index cb782c47a2c..629f8cc7dec 100644 --- a/chromium/services/tracing/public/cpp/perfetto/trace_event_data_source.cc +++ b/chromium/services/tracing/public/cpp/perfetto/trace_event_data_source.cc @@ -236,10 +236,9 @@ class TraceEventDataSource::ThreadLocalEventSink { EnsureValidHandles(); - uint32_t name_index = 0; - uint32_t category_name_index = 0; - const size_t kMaxSize = base::trace_event::TraceArguments::kMaxSize; - uint32_t arg_name_indices[kMaxSize] = {0}; + int name_index = 0; + int category_name_index = 0; + int arg_name_indices[base::trace_event::kTraceMaxNumArgs] = {0}; // Populate any new string table parts first; has to be done before // the add_trace_events() call (as the string table is part of the outer @@ -255,8 +254,9 @@ class TraceEventDataSource::ThreadLocalEventSink { GetStringTableIndexForString(TraceLog::GetCategoryGroupName( trace_event->category_group_enabled())); - for (size_t i = 0; - i < trace_event->arg_size() && trace_event->arg_name(i); ++i) { + for (int i = 0; + i < base::trace_event::kTraceMaxNumArgs && trace_event->arg_name(i); + ++i) { arg_name_indices[i] = GetStringTableIndexForString(trace_event->arg_name(i)); } @@ -300,7 +300,8 @@ class TraceEventDataSource::ThreadLocalEventSink { char phase = trace_event->phase(); new_trace_event->set_phase(phase); - for (size_t i = 0; i < trace_event->arg_size() && trace_event->arg_name(i); + for (int i = 0; + i < base::trace_event::kTraceMaxNumArgs && trace_event->arg_name(i); ++i) { auto type = trace_event->arg_type(i); auto* new_arg = new_trace_event->add_args(); diff --git a/chromium/skia/ext/event_tracer_impl.cc b/chromium/skia/ext/event_tracer_impl.cc index 71ed2d11d41..82d35a61e06 100644 --- a/chromium/skia/ext/event_tracer_impl.cc +++ b/chromium/skia/ext/event_tracer_impl.cc @@ -47,15 +47,13 @@ SkEventTracer::Handle const uint8_t* argTypes, const uint64_t* argValues, uint8_t flags) { - base::trace_event::TraceArguments args( - numArgs, argNames, argTypes, - reinterpret_cast<const unsigned long long*>(argValues)); base::trace_event::TraceEventHandle handle = TRACE_EVENT_API_ADD_TRACE_EVENT( phase, categoryEnabledFlag, name, trace_event_internal::kGlobalScope, id, - &args, flags); - SkEventTracer::Handle result; - memcpy(&result, &handle, sizeof(result)); - return result; + numArgs, argNames, argTypes, (const long long unsigned int*)argValues, + NULL, flags); + SkEventTracer::Handle result; + memcpy(&result, &handle, sizeof(result)); + return result; } void diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h b/chromium/third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h index 5d8d61d3cd9..97e1475fa58 100644 --- a/chromium/third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h +++ b/chromium/third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h @@ -11,14 +11,19 @@ #include "third_party/blink/renderer/platform/wtf/text/cstring.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" -// Conversion from CString to TraceValue so that trace arguments can be strings. -template <> -struct base::trace_event::TraceValue::Helper<WTF::CString> { - static constexpr unsigned char kType = TRACE_VALUE_TYPE_COPY_STRING; - static inline void SetValue(TraceValue* v, const WTF::CString& value) { - v->as_string = value.data(); - } -}; +namespace WTF { + +// CString version of SetTraceValue so that trace arguments can be strings. +static inline void SetTraceValue(const CString& arg, + unsigned char* type, + unsigned long long* value) { + trace_event_internal::TraceValueUnion type_value; + type_value.as_string = arg.data(); + *type = TRACE_VALUE_TYPE_COPY_STRING; + *value = type_value.as_uint; +} + +} // namespace WTF namespace blink { namespace trace_event { diff --git a/chromium/third_party/webrtc_overrides/init_webrtc.cc b/chromium/third_party/webrtc_overrides/init_webrtc.cc index db086b6f758..10df8b47eb1 100644 --- a/chromium/third_party/webrtc_overrides/init_webrtc.cc +++ b/chromium/third_party/webrtc_overrides/init_webrtc.cc @@ -28,11 +28,9 @@ void AddTraceEvent(char phase, const unsigned char* arg_types, const unsigned long long* arg_values, unsigned char flags) { - base::trace_event::TraceArguments args(num_args, arg_names, arg_types, - arg_values); - TRACE_EVENT_API_ADD_TRACE_EVENT(phase, category_group_enabled, name, - trace_event_internal::kGlobalScope, id, &args, - flags); + TRACE_EVENT_API_ADD_TRACE_EVENT( + phase, category_group_enabled, name, trace_event_internal::kGlobalScope, + id, num_args, arg_names, arg_types, arg_values, NULL, flags); } bool InitializeWebRtcModule() { diff --git a/chromium/ui/gl/angle_platform_impl.cc b/chromium/ui/gl/angle_platform_impl.cc index 4e144067721..4a0bc9aef25 100644 --- a/chromium/ui/gl/angle_platform_impl.cc +++ b/chromium/ui/gl/angle_platform_impl.cc @@ -66,13 +66,12 @@ TraceEventHandle ANGLEPlatformImpl_addTraceEvent( unsigned char flags) { base::TimeTicks timestamp_tt = base::TimeTicks() + base::TimeDelta::FromSecondsD(timestamp); - base::trace_event::TraceArguments args(num_args, arg_names, arg_types, - arg_values); base::trace_event::TraceEventHandle handle = TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( phase, category_group_enabled, name, trace_event_internal::kGlobalScope, id, trace_event_internal::kNoId, - base::PlatformThread::CurrentId(), timestamp_tt, &args, flags); + base::PlatformThread::CurrentId(), timestamp_tt, num_args, arg_names, + arg_types, arg_values, nullptr, flags); TraceEventHandle result; memcpy(&result, &handle, sizeof(result)); return result; |