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

Side by Side Diff: base/trace_event/trace_event_argument.cc

Issue 1641513004: Update //base to chromium 9659b08ea5a34f889dc4166217f438095ddc10d2 (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 4 years, 10 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/trace_event/trace_event_argument.h" 5 #include "base/trace_event/trace_event_argument.h"
6 6
7 #include "base/json/json_writer.h" 7 #include "base/json/json_writer.h"
8 #include "base/trace_event/trace_event_memory_overhead.h"
8 #include "base/values.h" 9 #include "base/values.h"
9 10
10 namespace base { 11 namespace base {
11 namespace trace_event { 12 namespace trace_event {
12 13
13 TracedValue::TracedValue() : root_(new DictionaryValue()) { 14 namespace {
14 stack_.push_back(root_.get()); 15 const char kTypeStartDict = '{';
16 const char kTypeEndDict = '}';
17 const char kTypeStartArray = '[';
18 const char kTypeEndArray = ']';
19 const char kTypeBool = 'b';
20 const char kTypeInt = 'i';
21 const char kTypeDouble = 'd';
22 const char kTypeString = 's';
23 const char kTypeCStr = '*';
24
25 #ifndef NDEBUG
26 const bool kStackTypeDict = false;
27 const bool kStackTypeArray = true;
28 #define DCHECK_CURRENT_CONTAINER_IS(x) DCHECK_EQ(x, nesting_stack_.back())
29 #define DCHECK_CONTAINER_STACK_DEPTH_EQ(x) DCHECK_EQ(x, nesting_stack_.size())
30 #define DEBUG_PUSH_CONTAINER(x) nesting_stack_.push_back(x)
31 #define DEBUG_POP_CONTAINER() nesting_stack_.pop_back()
32 #else
33 #define DCHECK_CURRENT_CONTAINER_IS(x) \
34 do { \
35 } while (0)
36 #define DCHECK_CONTAINER_STACK_DEPTH_EQ(x) \
37 do { \
38 } while (0)
39 #define DEBUG_PUSH_CONTAINER(x) \
40 do { \
41 } while (0)
42 #define DEBUG_POP_CONTAINER() \
43 do { \
44 } while (0)
45 #endif
46
47 inline void WriteKeyNameAsRawPtr(Pickle& pickle, const char* ptr) {
48 pickle.WriteBytes(&kTypeCStr, 1);
49 pickle.WriteUInt64(static_cast<uint64>(reinterpret_cast<uintptr_t>(ptr)));
50 }
51
52 inline void WriteKeyNameAsStdString(Pickle& pickle, const std::string& str) {
53 pickle.WriteBytes(&kTypeString, 1);
54 pickle.WriteString(str);
55 }
56
57 std::string ReadKeyName(PickleIterator& pickle_iterator) {
58 const char* type = nullptr;
59 bool res = pickle_iterator.ReadBytes(&type, 1);
60 std::string key_name;
61 if (res && *type == kTypeCStr) {
62 uint64 ptr_value = 0;
63 res = pickle_iterator.ReadUInt64(&ptr_value);
64 key_name = reinterpret_cast<const char*>(static_cast<uintptr_t>(ptr_value));
65 } else if (res && *type == kTypeString) {
66 res = pickle_iterator.ReadString(&key_name);
67 }
68 DCHECK(res);
69 return key_name;
70 }
71 } // namespace
72
73 TracedValue::TracedValue() : TracedValue(0) {}
74
75 TracedValue::TracedValue(size_t capacity) {
76 DEBUG_PUSH_CONTAINER(kStackTypeDict);
77 if (capacity)
78 pickle_.Reserve(capacity);
15 } 79 }
16 80
17 TracedValue::~TracedValue() { 81 TracedValue::~TracedValue() {
18 DCHECK_EQ(1u, stack_.size()); 82 DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
83 DEBUG_POP_CONTAINER();
84 DCHECK_CONTAINER_STACK_DEPTH_EQ(0u);
19 } 85 }
20 86
21 void TracedValue::SetInteger(const char* name, int value) { 87 void TracedValue::SetInteger(const char* name, int value) {
22 GetCurrentDictionary()->SetInteger(name, value); 88 DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
89 pickle_.WriteBytes(&kTypeInt, 1);
90 pickle_.WriteInt(value);
91 WriteKeyNameAsRawPtr(pickle_, name);
92 }
93
94 void TracedValue::SetIntegerWithCopiedName(const std::string& name, int value) {
95 DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
96 pickle_.WriteBytes(&kTypeInt, 1);
97 pickle_.WriteInt(value);
98 WriteKeyNameAsStdString(pickle_, name);
23 } 99 }
24 100
25 void TracedValue::SetDouble(const char* name, double value) { 101 void TracedValue::SetDouble(const char* name, double value) {
26 GetCurrentDictionary()->SetDouble(name, value); 102 DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
103 pickle_.WriteBytes(&kTypeDouble, 1);
104 pickle_.WriteDouble(value);
105 WriteKeyNameAsRawPtr(pickle_, name);
106 }
107
108 void TracedValue::SetDoubleWithCopiedName(const std::string& name,
109 double value) {
110 DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
111 pickle_.WriteBytes(&kTypeDouble, 1);
112 pickle_.WriteDouble(value);
113 WriteKeyNameAsStdString(pickle_, name);
27 } 114 }
28 115
29 void TracedValue::SetBoolean(const char* name, bool value) { 116 void TracedValue::SetBoolean(const char* name, bool value) {
30 GetCurrentDictionary()->SetBoolean(name, value); 117 DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
118 pickle_.WriteBytes(&kTypeBool, 1);
119 pickle_.WriteBool(value);
120 WriteKeyNameAsRawPtr(pickle_, name);
121 }
122
123 void TracedValue::SetBooleanWithCopiedName(const std::string& name,
124 bool value) {
125 DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
126 pickle_.WriteBytes(&kTypeBool, 1);
127 pickle_.WriteBool(value);
128 WriteKeyNameAsStdString(pickle_, name);
31 } 129 }
32 130
33 void TracedValue::SetString(const char* name, const std::string& value) { 131 void TracedValue::SetString(const char* name, const std::string& value) {
34 GetCurrentDictionary()->SetString(name, value); 132 DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
35 } 133 pickle_.WriteBytes(&kTypeString, 1);
36 134 pickle_.WriteString(value);
37 void TracedValue::SetValue(const char* name, scoped_ptr<Value> value) { 135 WriteKeyNameAsRawPtr(pickle_, name);
38 GetCurrentDictionary()->Set(name, value.Pass()); 136 }
137
138 void TracedValue::SetStringWithCopiedName(const std::string& name,
139 const std::string& value) {
140 DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
141 pickle_.WriteBytes(&kTypeString, 1);
142 pickle_.WriteString(value);
143 WriteKeyNameAsStdString(pickle_, name);
144 }
145
146 void TracedValue::SetValue(const char* name, const TracedValue& value) {
147 DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
148 BeginDictionary(name);
149 pickle_.WriteBytes(value.pickle_.payload(),
150 static_cast<int>(value.pickle_.payload_size()));
151 EndDictionary();
152 }
153
154 void TracedValue::SetValueWithCopiedName(const std::string& name,
155 const TracedValue& value) {
156 DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
157 BeginDictionaryWithCopiedName(name);
158 pickle_.WriteBytes(value.pickle_.payload(),
159 static_cast<int>(value.pickle_.payload_size()));
160 EndDictionary();
39 } 161 }
40 162
41 void TracedValue::BeginDictionary(const char* name) { 163 void TracedValue::BeginDictionary(const char* name) {
42 DictionaryValue* dictionary = new DictionaryValue(); 164 DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
43 GetCurrentDictionary()->Set(name, make_scoped_ptr(dictionary)); 165 DEBUG_PUSH_CONTAINER(kStackTypeDict);
44 stack_.push_back(dictionary); 166 pickle_.WriteBytes(&kTypeStartDict, 1);
167 WriteKeyNameAsRawPtr(pickle_, name);
168 }
169
170 void TracedValue::BeginDictionaryWithCopiedName(const std::string& name) {
171 DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
172 DEBUG_PUSH_CONTAINER(kStackTypeDict);
173 pickle_.WriteBytes(&kTypeStartDict, 1);
174 WriteKeyNameAsStdString(pickle_, name);
45 } 175 }
46 176
47 void TracedValue::BeginArray(const char* name) { 177 void TracedValue::BeginArray(const char* name) {
48 ListValue* array = new ListValue(); 178 DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
49 GetCurrentDictionary()->Set(name, make_scoped_ptr(array)); 179 DEBUG_PUSH_CONTAINER(kStackTypeArray);
50 stack_.push_back(array); 180 pickle_.WriteBytes(&kTypeStartArray, 1);
181 WriteKeyNameAsRawPtr(pickle_, name);
182 }
183
184 void TracedValue::BeginArrayWithCopiedName(const std::string& name) {
185 DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
186 DEBUG_PUSH_CONTAINER(kStackTypeArray);
187 pickle_.WriteBytes(&kTypeStartArray, 1);
188 WriteKeyNameAsStdString(pickle_, name);
51 } 189 }
52 190
53 void TracedValue::EndDictionary() { 191 void TracedValue::EndDictionary() {
54 DCHECK_GT(stack_.size(), 1u); 192 DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
55 DCHECK(GetCurrentDictionary()); 193 DEBUG_POP_CONTAINER();
56 stack_.pop_back(); 194 pickle_.WriteBytes(&kTypeEndDict, 1);
57 } 195 }
58 196
59 void TracedValue::AppendInteger(int value) { 197 void TracedValue::AppendInteger(int value) {
60 GetCurrentArray()->AppendInteger(value); 198 DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
199 pickle_.WriteBytes(&kTypeInt, 1);
200 pickle_.WriteInt(value);
61 } 201 }
62 202
63 void TracedValue::AppendDouble(double value) { 203 void TracedValue::AppendDouble(double value) {
64 GetCurrentArray()->AppendDouble(value); 204 DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
205 pickle_.WriteBytes(&kTypeDouble, 1);
206 pickle_.WriteDouble(value);
65 } 207 }
66 208
67 void TracedValue::AppendBoolean(bool value) { 209 void TracedValue::AppendBoolean(bool value) {
68 GetCurrentArray()->AppendBoolean(value); 210 DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
211 pickle_.WriteBytes(&kTypeBool, 1);
212 pickle_.WriteBool(value);
69 } 213 }
70 214
71 void TracedValue::AppendString(const std::string& value) { 215 void TracedValue::AppendString(const std::string& value) {
72 GetCurrentArray()->AppendString(value); 216 DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
217 pickle_.WriteBytes(&kTypeString, 1);
218 pickle_.WriteString(value);
73 } 219 }
74 220
75 void TracedValue::BeginArray() { 221 void TracedValue::BeginArray() {
76 ListValue* array = new ListValue(); 222 DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
77 GetCurrentArray()->Append(array); 223 DEBUG_PUSH_CONTAINER(kStackTypeArray);
78 stack_.push_back(array); 224 pickle_.WriteBytes(&kTypeStartArray, 1);
79 } 225 }
80 226
81 void TracedValue::BeginDictionary() { 227 void TracedValue::BeginDictionary() {
82 DictionaryValue* dictionary = new DictionaryValue(); 228 DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
83 GetCurrentArray()->Append(dictionary); 229 DEBUG_PUSH_CONTAINER(kStackTypeDict);
84 stack_.push_back(dictionary); 230 pickle_.WriteBytes(&kTypeStartDict, 1);
85 } 231 }
86 232
87 void TracedValue::EndArray() { 233 void TracedValue::EndArray() {
88 DCHECK_GT(stack_.size(), 1u); 234 DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
89 DCHECK(GetCurrentArray()); 235 DEBUG_POP_CONTAINER();
90 stack_.pop_back(); 236 pickle_.WriteBytes(&kTypeEndArray, 1);
91 } 237 }
92 238
93 DictionaryValue* TracedValue::GetCurrentDictionary() { 239 void TracedValue::SetValue(const char* name, scoped_ptr<base::Value> value) {
94 DCHECK(!stack_.empty()); 240 SetBaseValueWithCopiedName(name, *value);
95 DictionaryValue* dictionary = NULL; 241 }
96 stack_.back()->GetAsDictionary(&dictionary); 242
97 DCHECK(dictionary); 243 void TracedValue::SetBaseValueWithCopiedName(const std::string& name,
98 return dictionary; 244 const base::Value& value) {
99 } 245 DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
100 246 switch (value.GetType()) {
101 ListValue* TracedValue::GetCurrentArray() { 247 case base::Value::TYPE_NULL:
102 DCHECK(!stack_.empty()); 248 case base::Value::TYPE_BINARY:
103 ListValue* list = NULL; 249 NOTREACHED();
104 stack_.back()->GetAsList(&list); 250 break;
105 DCHECK(list); 251
106 return list; 252 case base::Value::TYPE_BOOLEAN: {
253 bool bool_value;
254 value.GetAsBoolean(&bool_value);
255 SetBooleanWithCopiedName(name, bool_value);
256 } break;
257
258 case base::Value::TYPE_INTEGER: {
259 int int_value;
260 value.GetAsInteger(&int_value);
261 SetIntegerWithCopiedName(name, int_value);
262 } break;
263
264 case base::Value::TYPE_DOUBLE: {
265 double double_value;
266 value.GetAsDouble(&double_value);
267 SetDoubleWithCopiedName(name, double_value);
268 } break;
269
270 case base::Value::TYPE_STRING: {
271 const StringValue* string_value;
272 value.GetAsString(&string_value);
273 SetStringWithCopiedName(name, string_value->GetString());
274 } break;
275
276 case base::Value::TYPE_DICTIONARY: {
277 const DictionaryValue* dict_value;
278 value.GetAsDictionary(&dict_value);
279 BeginDictionaryWithCopiedName(name);
280 for (DictionaryValue::Iterator it(*dict_value); !it.IsAtEnd();
281 it.Advance()) {
282 SetBaseValueWithCopiedName(it.key(), it.value());
283 }
284 EndDictionary();
285 } break;
286
287 case base::Value::TYPE_LIST: {
288 const ListValue* list_value;
289 value.GetAsList(&list_value);
290 BeginArrayWithCopiedName(name);
291 for (base::Value* base_value : *list_value)
292 AppendBaseValue(*base_value);
293 EndArray();
294 } break;
295 }
296 }
297
298 void TracedValue::AppendBaseValue(const base::Value& value) {
299 DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
300 switch (value.GetType()) {
301 case base::Value::TYPE_NULL:
302 case base::Value::TYPE_BINARY:
303 NOTREACHED();
304 break;
305
306 case base::Value::TYPE_BOOLEAN: {
307 bool bool_value;
308 value.GetAsBoolean(&bool_value);
309 AppendBoolean(bool_value);
310 } break;
311
312 case base::Value::TYPE_INTEGER: {
313 int int_value;
314 value.GetAsInteger(&int_value);
315 AppendInteger(int_value);
316 } break;
317
318 case base::Value::TYPE_DOUBLE: {
319 double double_value;
320 value.GetAsDouble(&double_value);
321 AppendDouble(double_value);
322 } break;
323
324 case base::Value::TYPE_STRING: {
325 const StringValue* string_value;
326 value.GetAsString(&string_value);
327 AppendString(string_value->GetString());
328 } break;
329
330 case base::Value::TYPE_DICTIONARY: {
331 const DictionaryValue* dict_value;
332 value.GetAsDictionary(&dict_value);
333 BeginDictionary();
334 for (DictionaryValue::Iterator it(*dict_value); !it.IsAtEnd();
335 it.Advance()) {
336 SetBaseValueWithCopiedName(it.key(), it.value());
337 }
338 EndDictionary();
339 } break;
340
341 case base::Value::TYPE_LIST: {
342 const ListValue* list_value;
343 value.GetAsList(&list_value);
344 BeginArray();
345 for (base::Value* base_value : *list_value)
346 AppendBaseValue(*base_value);
347 EndArray();
348 } break;
349 }
350 }
351
352 scoped_ptr<base::Value> TracedValue::ToBaseValue() const {
353 scoped_ptr<DictionaryValue> root(new DictionaryValue);
354 DictionaryValue* cur_dict = root.get();
355 ListValue* cur_list = nullptr;
356 std::vector<Value*> stack;
357 PickleIterator it(pickle_);
358 const char* type;
359
360 while (it.ReadBytes(&type, 1)) {
361 DCHECK((cur_dict && !cur_list) || (cur_list && !cur_dict));
362 switch (*type) {
363 case kTypeStartDict: {
364 auto new_dict = new DictionaryValue();
365 if (cur_dict) {
366 cur_dict->Set(ReadKeyName(it), make_scoped_ptr(new_dict));
367 stack.push_back(cur_dict);
368 cur_dict = new_dict;
369 } else {
370 cur_list->Append(make_scoped_ptr(new_dict));
371 stack.push_back(cur_list);
372 cur_list = nullptr;
373 cur_dict = new_dict;
374 }
375 } break;
376
377 case kTypeEndArray:
378 case kTypeEndDict: {
379 if (stack.back()->GetAsDictionary(&cur_dict)) {
380 cur_list = nullptr;
381 } else if (stack.back()->GetAsList(&cur_list)) {
382 cur_dict = nullptr;
383 }
384 stack.pop_back();
385 } break;
386
387 case kTypeStartArray: {
388 auto new_list = new ListValue();
389 if (cur_dict) {
390 cur_dict->Set(ReadKeyName(it), make_scoped_ptr(new_list));
391 stack.push_back(cur_dict);
392 cur_dict = nullptr;
393 cur_list = new_list;
394 } else {
395 cur_list->Append(make_scoped_ptr(new_list));
396 stack.push_back(cur_list);
397 cur_list = new_list;
398 }
399 } break;
400
401 case kTypeBool: {
402 bool value;
403 CHECK(it.ReadBool(&value));
404 if (cur_dict) {
405 cur_dict->SetBoolean(ReadKeyName(it), value);
406 } else {
407 cur_list->AppendBoolean(value);
408 }
409 } break;
410
411 case kTypeInt: {
412 int value;
413 CHECK(it.ReadInt(&value));
414 if (cur_dict) {
415 cur_dict->SetInteger(ReadKeyName(it), value);
416 } else {
417 cur_list->AppendInteger(value);
418 }
419 } break;
420
421 case kTypeDouble: {
422 double value;
423 CHECK(it.ReadDouble(&value));
424 if (cur_dict) {
425 cur_dict->SetDouble(ReadKeyName(it), value);
426 } else {
427 cur_list->AppendDouble(value);
428 }
429 } break;
430
431 case kTypeString: {
432 std::string value;
433 CHECK(it.ReadString(&value));
434 if (cur_dict) {
435 cur_dict->SetString(ReadKeyName(it), value);
436 } else {
437 cur_list->AppendString(value);
438 }
439 } break;
440
441 default:
442 NOTREACHED();
443 }
444 }
445 DCHECK(stack.empty());
446 return root.Pass();
107 } 447 }
108 448
109 void TracedValue::AppendAsTraceFormat(std::string* out) const { 449 void TracedValue::AppendAsTraceFormat(std::string* out) const {
450 DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
451 DCHECK_CONTAINER_STACK_DEPTH_EQ(1u);
452
453 // TODO(primiano): this could be smarter, skip the ToBaseValue encoding and
454 // produce the JSON on its own. This will require refactoring JSONWriter
455 // to decouple the base::Value traversal from the JSON writing bits
110 std::string tmp; 456 std::string tmp;
111 JSONWriter::Write(*stack_.front(), &tmp); 457 JSONWriter::Write(*ToBaseValue(), &tmp);
112 *out += tmp; 458 *out += tmp;
113 DCHECK_EQ(1u, stack_.size()) << tmp; 459 }
460
461 void TracedValue::EstimateTraceMemoryOverhead(
462 TraceEventMemoryOverhead* overhead) {
463 overhead->Add("TracedValue",
464 pickle_.GetTotalAllocatedSize() /* allocated size */,
465 pickle_.size() /* resident size */);
114 } 466 }
115 467
116 } // namespace trace_event 468 } // namespace trace_event
117 } // namespace base 469 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698