Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(656)

Unified Diff: base/debug/trace_event_value.cc

Issue 19642005: Make TracedValue lower overhead. Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: base/debug/trace_event_value.cc
diff --git a/base/debug/trace_event_value.cc b/base/debug/trace_event_value.cc
new file mode 100644
index 0000000000000000000000000000000000000000..e907d652f91ab393f9a33ee3cd64f8c8772d1875
--- /dev/null
+++ b/base/debug/trace_event_value.cc
@@ -0,0 +1,290 @@
+// Copyright (c) 2013 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/debug/trace_event_value.h"
+#include "base/json/json_writer.h"
+#include "base/json/string_escape.h"
+#include "base/strings/stringprintf.h"
+
+namespace base {
+namespace debug {
+
+TracedValue::TracedValue() {
+}
+
+TracedValue::~TracedValue() {
+}
+
+void TracedValue::AppendAsTraceFormat(std::string* out) const {
+ // Used to keep track of the opening opcode.
+ std::stack<Opcode> begin_opcode_stack;
+ // This is needed in case of nested structures.
+ std::stack<int> element_count_stack;
+ PickleIterator iter(pickle_);
+
+ int opcode;
+ bool read_succeeded = pickle_.ReadInt(&iter, &opcode);
+ while (read_succeeded) {
+ // Append comma if necessary.
+ if (!begin_opcode_stack.empty()) {
+ DCHECK(!element_count_stack.empty());
+ AppendComma(out, begin_opcode_stack.top(),
+ static_cast<Opcode>(opcode), &element_count_stack.top());
+ }
+
+ switch (opcode) {
+ case BEGIN_ARRAY:
+ case BEGIN_DICTIONARY:
+ {
+ // Initialize the count for the current datastructure.
+ element_count_stack.push(0);
+ begin_opcode_stack.push(static_cast<Opcode>(opcode));
+ StringAppendF(out, opcode == BEGIN_DICTIONARY ? "{" : "[");
+ break;
+ }
+ case END_DICTIONARY:
+ case END_ARRAY:
+ {
+ begin_opcode_stack.pop();
+ element_count_stack.pop();
+ StringAppendF(out, opcode == END_DICTIONARY ? "}" : "]");
+ break;
+ }
+ case KEY_AS_RAW_POINTER:
+ {
+ AppendKeyAsRawPointer(out, &iter);
+ break;
+ }
+ case VALUE_AS_RAW_POINTER:
+ {
+ AppendValueAsRawPointer(out, &iter);
+ break;
+ }
+ case VALUE_AS_STRING:
+ {
+ AppendValueAsString(out, &iter);
+ break;
+ }
+ case INT32_VALUE:
+ {
+ AppendValueAsInt32(out, &iter);
+ break;
+ }
+ case INT64_VALUE:
+ {
+ AppendValueAsInt64(out, &iter);
+ break;
+ }
+ case UINT32_VALUE:
+ {
+ AppendValueAsUInt32(out, &iter);
+ break;
+ }
+ case UINT64_VALUE:
+ {
+ AppendValueAsUInt64(out, &iter);
+ break;
+ }
+ case FLOAT_VALUE:
+ {
+ AppendValueAsFloat(out, &iter);
+ break;
+ }
+ case BOOL_VALUE:
+ {
+ AppendValueAsBool(out, &iter);
+ break;
+ }
+ default:
+ NOTREACHED() << "Don't know what to write, opcode=" << opcode;
+ }
+ read_succeeded = pickle_.ReadInt(&iter, &opcode);
+ }
+ DCHECK(begin_opcode_stack.empty());
+}
+
+void TracedValue::BeginDictionary() {
+ begin_opcodes_.push(BEGIN_DICTIONARY);
+ pickle_.WriteInt(BEGIN_DICTIONARY);
+}
+
+void TracedValue::PushDictionary(const char* key_in_parent_dict) {
+ // Named dictionaries are properties of dictionaries, the name is the key.
dsinclair 2013/08/08 14:07:28 The DCHECK_EQ(BEGIN_DICTIONARY, begin_opcodes_.to
rterrazas 2013/08/11 21:05:08 Done.
+ PushKeyToPickle(key_in_parent_dict);
+ begin_opcodes_.push(BEGIN_DICTIONARY);
+ pickle_.WriteInt(BEGIN_DICTIONARY);
+}
+
+void TracedValue::EndDictionary() {
+ DCHECK_EQ(BEGIN_DICTIONARY, begin_opcodes_.top());
+ begin_opcodes_.pop();
+ pickle_.WriteInt(END_DICTIONARY);
+}
+
+void TracedValue::BeginArray() {
+ begin_opcodes_.push(BEGIN_ARRAY);
+ pickle_.WriteInt(BEGIN_ARRAY);
+}
+
+void TracedValue::PushArray(const char* key_in_parent_dict) {
+ // Named arrays are properties of dictionaries, and the key of such property
+ // is key_in_parent_dict.
+ DCHECK_EQ(BEGIN_DICTIONARY, begin_opcodes_.top());
+ PushKeyToPickle(key_in_parent_dict);
+ begin_opcodes_.push(BEGIN_ARRAY);
+ pickle_.WriteInt(BEGIN_ARRAY);
+}
+
+void TracedValue::EndArray() {
+ DCHECK_EQ(BEGIN_ARRAY, begin_opcodes_.top());
+ begin_opcodes_.pop();
+
+ pickle_.WriteInt(END_ARRAY);
+}
+
+// These methods push stuff in the pickle either in dictionary or array
+// blocks, it's the up to the publicaly exposed caller to check the state.
+void TracedValue::PushKeyToPickle(const char* key) {
+ pickle_.WriteInt(KEY_AS_RAW_POINTER);
+ uintptr_t key_ptr = reinterpret_cast<uintptr_t>(key);
+ pickle_.WriteUIntPtr(key_ptr);
+}
+
+void TracedValue::PushValueToPickle(const char* value) {
+ pickle_.WriteInt(VALUE_AS_RAW_POINTER);
+ uintptr_t value_ptr = reinterpret_cast<uintptr_t>(value);
+ pickle_.WriteUIntPtr(value_ptr);
+}
+
+void TracedValue::PushValueToPickle(const std::string& value) {
+ pickle_.WriteInt(VALUE_AS_STRING);
+ pickle_.WriteString(value);
+}
+
+void TracedValue::PushValueToPickle(int value) {
+ pickle_.WriteInt(INT32_VALUE);
+ pickle_.WriteInt(value);
+}
+
+void TracedValue::PushValueToPickle(int64 value) {
+ pickle_.WriteInt(INT64_VALUE);
+ pickle_.WriteInt64(value);
+}
+
+void TracedValue::PushValueToPickle(uint32 value) {
+ pickle_.WriteInt(UINT32_VALUE);
+ pickle_.WriteUInt32(value);
+}
+
+void TracedValue::PushValueToPickle(uint64 value) {
+ pickle_.WriteInt(UINT64_VALUE);
+ pickle_.WriteUInt64(value);
+}
+
+void TracedValue::PushValueToPickle(float value) {
+ pickle_.WriteInt(FLOAT_VALUE);
+ pickle_.WriteFloat(value);
+}
+
+void TracedValue::PushValueToPickle(bool value) {
+ pickle_.WriteInt(BOOL_VALUE);
+ pickle_.WriteBool(value);
+}
+
+void TracedValue::PushValueToPickle(const TracedObject& value) {
+ // The definition of what gets pushed is in the implementation of
+ // TracedObject::PushInto().
+ value.PushInto(this);
+}
+
+// Helper methods used in AppendAsTraceFormat()
+void TracedValue::AppendKeyAsRawPointer(std::string* out,
+ PickleIterator* iter) const {
+ uintptr_t out_ptr;
+ pickle_.ReadUIntPtr(iter, &out_ptr);
+ const char* key = reinterpret_cast<char*>(out_ptr);
+ JsonDoubleQuote(std::string(key), true, out);
+ out->append(":");
+}
+
+void TracedValue::AppendValueAsRawPointer(std::string* out,
+ PickleIterator* iter) const {
+ uintptr_t out_ptr;
+ pickle_.ReadUIntPtr(iter, &out_ptr);
+ const char* value = reinterpret_cast<char*>(out_ptr);
+ JsonDoubleQuote(std::string(value), true, out);
+}
+
+void TracedValue::AppendValueAsString(std::string* out,
+ PickleIterator* iter) const {
+ std::string out_string;
+ pickle_.ReadString(iter, &out_string);
+ JsonDoubleQuote(out_string, true, out);
+}
+
+void TracedValue::AppendValueAsInt32(std::string* out,
+ PickleIterator* iter) const {
+ int out_int;
+ pickle_.ReadInt(iter, &out_int);
+ StringAppendF(out, "%d", out_int);
+}
+
+void TracedValue::AppendValueAsInt64(std::string* out,
+ PickleIterator* iter) const {
+ int64 out_int64;
+ pickle_.ReadInt64(iter, &out_int64);
+ StringAppendF(out, "%" PRId64, out_int64);
+}
+
+
+void TracedValue::AppendValueAsUInt32(std::string* out,
+ PickleIterator* iter) const {
+ uint32 out_uint32;
+ pickle_.ReadUInt32(iter, &out_uint32);
+ StringAppendF(out, "%u", out_uint32);
+}
+
+void TracedValue::AppendValueAsUInt64(std::string* out,
+ PickleIterator* iter) const {
+ uint64 out_uint64;
+ pickle_.ReadUInt64(iter, &out_uint64);
+ StringAppendF(out, "%" PRIu64, out_uint64);
+}
+
+void TracedValue::AppendValueAsFloat(std::string* out,
+ PickleIterator* iter) const {
+ float out_float;
+ pickle_.ReadFloat(iter, &out_float);
+ out->append(base::JSONWriter::DoubleToFormattedString(out_float, false));
+}
+
+void TracedValue::AppendValueAsBool(std::string* out,
+ PickleIterator* iter) const {
+ bool out_bool;
+ pickle_.ReadBool(iter, &out_bool);
+ StringAppendF(out, "%s", out_bool ? "true" : "false");
+}
+
+// Static.
+void TracedValue::AppendComma(std::string* out, Opcode begin_opcode,
+ Opcode current_opcode, int* element_count) {
+ // For arrays, we want to append a comma when the element count within
+ // the array is greater than zero and we are not about to close the array.
+ if (begin_opcode == BEGIN_ARRAY && current_opcode != END_ARRAY &&
+ (*element_count)++ > 0) {
+ StringAppendF(out, ",");
+ return;
+ }
+ // For dictionaries, we want to append a comma when the element count within
+ // the dictionary is greater than zero AND we're about to append is a key.
+ if (begin_opcode == BEGIN_DICTIONARY &&
+ current_opcode == KEY_AS_RAW_POINTER &&
+ (*element_count)++ > 0) {
+ StringAppendF(out, ",");
+ }
+}
+
+} // namespace debug
+} // namespace base
+

Powered by Google App Engine
This is Rietveld 408576698