traced_value.cc 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934
  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
  3. // found in the LICENSE file.
  4. #include "base/trace_event/traced_value.h"
  5. #include <inttypes.h>
  6. #include <stdint.h>
  7. #include <atomic>
  8. #include <utility>
  9. #include "base/bits.h"
  10. #include "base/containers/circular_deque.h"
  11. #include "base/json/json_writer.h"
  12. #include "base/json/string_escape.h"
  13. #include "base/memory/ptr_util.h"
  14. #include "base/notreached.h"
  15. #include "base/pickle.h"
  16. #include "base/strings/stringprintf.h"
  17. #include "base/trace_event/trace_event.h"
  18. #include "base/trace_event/trace_event_impl.h"
  19. #include "base/trace_event/trace_event_memory_overhead.h"
  20. #include "base/trace_event/trace_log.h"
  21. #include "base/values.h"
  22. namespace base {
  23. namespace trace_event {
  24. namespace {
  25. const char kTypeStartDict = '{';
  26. const char kTypeEndDict = '}';
  27. const char kTypeStartArray = '[';
  28. const char kTypeEndArray = ']';
  29. const char kTypeBool = 'b';
  30. const char kTypeInt = 'i';
  31. const char kTypeDouble = 'd';
  32. const char kTypeString = 's';
  33. const char kTypeCStr = '*'; // only used for key names
  34. std::atomic<TracedValue::WriterFactoryCallback> g_writer_factory_callback;
  35. #ifndef NDEBUG
  36. const bool kStackTypeDict = false;
  37. const bool kStackTypeArray = true;
  38. #define DCHECK_CURRENT_CONTAINER_IS(x) DCHECK_EQ(x, nesting_stack_.back())
  39. #define DCHECK_CONTAINER_STACK_DEPTH_EQ(x) DCHECK_EQ(x, nesting_stack_.size())
  40. #define DEBUG_PUSH_CONTAINER(x) nesting_stack_.push_back(x)
  41. #define DEBUG_POP_CONTAINER() nesting_stack_.pop_back()
  42. #else
  43. #define DCHECK_CURRENT_CONTAINER_IS(x) \
  44. do { \
  45. } while (0)
  46. #define DCHECK_CONTAINER_STACK_DEPTH_EQ(x) \
  47. do { \
  48. } while (0)
  49. #define DEBUG_PUSH_CONTAINER(x) \
  50. do { \
  51. } while (0)
  52. #define DEBUG_POP_CONTAINER() \
  53. do { \
  54. } while (0)
  55. #endif
  56. inline void WriteKeyNameAsRawPtr(Pickle& pickle, const char* ptr) {
  57. pickle.WriteBytes(&kTypeCStr, 1);
  58. pickle.WriteUInt64(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(ptr)));
  59. }
  60. inline void WriteKeyNameWithCopy(Pickle& pickle, base::StringPiece str) {
  61. pickle.WriteBytes(&kTypeString, 1);
  62. pickle.WriteString(str);
  63. }
  64. std::string ReadKeyName(PickleIterator& pickle_iterator) {
  65. const char* type = nullptr;
  66. bool res = pickle_iterator.ReadBytes(&type, 1);
  67. std::string key_name;
  68. if (res && *type == kTypeCStr) {
  69. uint64_t ptr_value = 0;
  70. res = pickle_iterator.ReadUInt64(&ptr_value);
  71. key_name = reinterpret_cast<const char*>(static_cast<uintptr_t>(ptr_value));
  72. } else if (res && *type == kTypeString) {
  73. res = pickle_iterator.ReadString(&key_name);
  74. }
  75. DCHECK(res);
  76. return key_name;
  77. }
  78. class PickleWriter final : public TracedValue::Writer {
  79. public:
  80. explicit PickleWriter(size_t capacity) {
  81. if (capacity) {
  82. pickle_.Reserve(capacity);
  83. }
  84. }
  85. bool IsPickleWriter() const override { return true; }
  86. bool IsProtoWriter() const override { return false; }
  87. void SetInteger(const char* name, int value) override {
  88. pickle_.WriteBytes(&kTypeInt, 1);
  89. pickle_.WriteInt(value);
  90. WriteKeyNameAsRawPtr(pickle_, name);
  91. }
  92. void SetIntegerWithCopiedName(base::StringPiece name, int value) override {
  93. pickle_.WriteBytes(&kTypeInt, 1);
  94. pickle_.WriteInt(value);
  95. WriteKeyNameWithCopy(pickle_, name);
  96. }
  97. void SetDouble(const char* name, double value) override {
  98. pickle_.WriteBytes(&kTypeDouble, 1);
  99. pickle_.WriteDouble(value);
  100. WriteKeyNameAsRawPtr(pickle_, name);
  101. }
  102. void SetDoubleWithCopiedName(base::StringPiece name, double value) override {
  103. pickle_.WriteBytes(&kTypeDouble, 1);
  104. pickle_.WriteDouble(value);
  105. WriteKeyNameWithCopy(pickle_, name);
  106. }
  107. void SetBoolean(const char* name, bool value) override {
  108. pickle_.WriteBytes(&kTypeBool, 1);
  109. pickle_.WriteBool(value);
  110. WriteKeyNameAsRawPtr(pickle_, name);
  111. }
  112. void SetBooleanWithCopiedName(base::StringPiece name, bool value) override {
  113. pickle_.WriteBytes(&kTypeBool, 1);
  114. pickle_.WriteBool(value);
  115. WriteKeyNameWithCopy(pickle_, name);
  116. }
  117. void SetString(const char* name, base::StringPiece value) override {
  118. pickle_.WriteBytes(&kTypeString, 1);
  119. pickle_.WriteString(value);
  120. WriteKeyNameAsRawPtr(pickle_, name);
  121. }
  122. void SetStringWithCopiedName(base::StringPiece name,
  123. base::StringPiece value) override {
  124. pickle_.WriteBytes(&kTypeString, 1);
  125. pickle_.WriteString(value);
  126. WriteKeyNameWithCopy(pickle_, name);
  127. }
  128. void SetValue(const char* name, Writer* value) override {
  129. DCHECK(value->IsPickleWriter());
  130. const PickleWriter* pickle_writer = static_cast<const PickleWriter*>(value);
  131. BeginDictionary(name);
  132. pickle_.WriteBytes(pickle_writer->pickle_.payload(),
  133. pickle_writer->pickle_.payload_size());
  134. EndDictionary();
  135. }
  136. void SetValueWithCopiedName(base::StringPiece name, Writer* value) override {
  137. DCHECK(value->IsPickleWriter());
  138. const PickleWriter* pickle_writer = static_cast<const PickleWriter*>(value);
  139. BeginDictionaryWithCopiedName(name);
  140. pickle_.WriteBytes(pickle_writer->pickle_.payload(),
  141. pickle_writer->pickle_.payload_size());
  142. EndDictionary();
  143. }
  144. void BeginArray() override { pickle_.WriteBytes(&kTypeStartArray, 1); }
  145. void BeginDictionary() override { pickle_.WriteBytes(&kTypeStartDict, 1); }
  146. void BeginDictionary(const char* name) override {
  147. pickle_.WriteBytes(&kTypeStartDict, 1);
  148. WriteKeyNameAsRawPtr(pickle_, name);
  149. }
  150. void BeginDictionaryWithCopiedName(base::StringPiece name) override {
  151. pickle_.WriteBytes(&kTypeStartDict, 1);
  152. WriteKeyNameWithCopy(pickle_, name);
  153. }
  154. void BeginArray(const char* name) override {
  155. pickle_.WriteBytes(&kTypeStartArray, 1);
  156. WriteKeyNameAsRawPtr(pickle_, name);
  157. }
  158. void BeginArrayWithCopiedName(base::StringPiece name) override {
  159. pickle_.WriteBytes(&kTypeStartArray, 1);
  160. WriteKeyNameWithCopy(pickle_, name);
  161. }
  162. void EndDictionary() override { pickle_.WriteBytes(&kTypeEndDict, 1); }
  163. void EndArray() override { pickle_.WriteBytes(&kTypeEndArray, 1); }
  164. void AppendInteger(int value) override {
  165. pickle_.WriteBytes(&kTypeInt, 1);
  166. pickle_.WriteInt(value);
  167. }
  168. void AppendDouble(double value) override {
  169. pickle_.WriteBytes(&kTypeDouble, 1);
  170. pickle_.WriteDouble(value);
  171. }
  172. void AppendBoolean(bool value) override {
  173. pickle_.WriteBytes(&kTypeBool, 1);
  174. pickle_.WriteBool(value);
  175. }
  176. void AppendString(base::StringPiece value) override {
  177. pickle_.WriteBytes(&kTypeString, 1);
  178. pickle_.WriteString(value);
  179. }
  180. void AppendAsTraceFormat(std::string* out) const override {
  181. struct State {
  182. enum Type { kTypeDict, kTypeArray };
  183. Type type;
  184. bool needs_comma;
  185. };
  186. auto maybe_append_key_name = [](State current_state, PickleIterator* it,
  187. std::string* out) {
  188. if (current_state.type == State::kTypeDict) {
  189. EscapeJSONString(ReadKeyName(*it), true, out);
  190. out->append(":");
  191. }
  192. };
  193. base::circular_deque<State> state_stack;
  194. out->append("{");
  195. state_stack.push_back({State::kTypeDict});
  196. PickleIterator it(pickle_);
  197. for (const char* type; it.ReadBytes(&type, 1);) {
  198. switch (*type) {
  199. case kTypeEndDict:
  200. out->append("}");
  201. state_stack.pop_back();
  202. continue;
  203. case kTypeEndArray:
  204. out->append("]");
  205. state_stack.pop_back();
  206. continue;
  207. }
  208. // Use an index so it will stay valid across resizes.
  209. size_t current_state_index = state_stack.size() - 1;
  210. if (state_stack[current_state_index].needs_comma) {
  211. out->append(",");
  212. }
  213. switch (*type) {
  214. case kTypeStartDict: {
  215. maybe_append_key_name(state_stack[current_state_index], &it, out);
  216. out->append("{");
  217. state_stack.push_back({State::kTypeDict});
  218. break;
  219. }
  220. case kTypeStartArray: {
  221. maybe_append_key_name(state_stack[current_state_index], &it, out);
  222. out->append("[");
  223. state_stack.push_back({State::kTypeArray});
  224. break;
  225. }
  226. case kTypeBool: {
  227. TraceEvent::TraceValue json_value;
  228. CHECK(it.ReadBool(&json_value.as_bool));
  229. maybe_append_key_name(state_stack[current_state_index], &it, out);
  230. json_value.AppendAsJSON(TRACE_VALUE_TYPE_BOOL, out);
  231. break;
  232. }
  233. case kTypeInt: {
  234. int value;
  235. CHECK(it.ReadInt(&value));
  236. maybe_append_key_name(state_stack[current_state_index], &it, out);
  237. TraceEvent::TraceValue json_value;
  238. json_value.as_int = value;
  239. json_value.AppendAsJSON(TRACE_VALUE_TYPE_INT, out);
  240. break;
  241. }
  242. case kTypeDouble: {
  243. TraceEvent::TraceValue json_value;
  244. CHECK(it.ReadDouble(&json_value.as_double));
  245. maybe_append_key_name(state_stack[current_state_index], &it, out);
  246. json_value.AppendAsJSON(TRACE_VALUE_TYPE_DOUBLE, out);
  247. break;
  248. }
  249. case kTypeString: {
  250. std::string value;
  251. CHECK(it.ReadString(&value));
  252. maybe_append_key_name(state_stack[current_state_index], &it, out);
  253. TraceEvent::TraceValue json_value;
  254. json_value.as_string = value.c_str();
  255. json_value.AppendAsJSON(TRACE_VALUE_TYPE_STRING, out);
  256. break;
  257. }
  258. default:
  259. NOTREACHED();
  260. }
  261. state_stack[current_state_index].needs_comma = true;
  262. }
  263. out->append("}");
  264. state_stack.pop_back();
  265. DCHECK(state_stack.empty());
  266. }
  267. void EstimateTraceMemoryOverhead(
  268. TraceEventMemoryOverhead* overhead) override {
  269. overhead->Add(TraceEventMemoryOverhead::kTracedValue,
  270. /* allocated size */
  271. pickle_.GetTotalAllocatedSize(),
  272. /* resident size */
  273. pickle_.size());
  274. }
  275. std::unique_ptr<base::Value> ToBaseValue() const {
  276. base::Value root(base::Value::Type::DICTIONARY);
  277. Value* cur_dict = &root;
  278. Value* cur_list = nullptr;
  279. std::vector<Value*> stack;
  280. PickleIterator it(pickle_);
  281. const char* type;
  282. while (it.ReadBytes(&type, 1)) {
  283. DCHECK((cur_dict && !cur_list) || (cur_list && !cur_dict));
  284. switch (*type) {
  285. case kTypeStartDict: {
  286. base::Value new_dict(base::Value::Type::DICTIONARY);
  287. if (cur_dict) {
  288. stack.push_back(cur_dict);
  289. cur_dict = cur_dict->SetKey(ReadKeyName(it), std::move(new_dict));
  290. } else {
  291. cur_list->Append(std::move(new_dict));
  292. // |new_dict| is invalidated at this point, so |cur_dict| needs to
  293. // be reset.
  294. cur_dict = &cur_list->GetListDeprecated().back();
  295. stack.push_back(cur_list);
  296. cur_list = nullptr;
  297. }
  298. } break;
  299. case kTypeEndArray:
  300. case kTypeEndDict: {
  301. if (stack.back()->is_dict()) {
  302. cur_dict = stack.back();
  303. cur_list = nullptr;
  304. } else if (stack.back()->is_list()) {
  305. cur_list = stack.back();
  306. cur_dict = nullptr;
  307. }
  308. stack.pop_back();
  309. } break;
  310. case kTypeStartArray: {
  311. base::Value new_list(base::Value::Type::LIST);
  312. if (cur_dict) {
  313. stack.push_back(cur_dict);
  314. cur_list = cur_dict->SetKey(ReadKeyName(it), std::move(new_list));
  315. cur_dict = nullptr;
  316. } else {
  317. cur_list->Append(std::move(new_list));
  318. stack.push_back(cur_list);
  319. // |cur_list| is invalidated at this point by the Append, so it
  320. // needs to be reset.
  321. cur_list = &cur_list->GetListDeprecated().back();
  322. }
  323. } break;
  324. case kTypeBool: {
  325. bool value;
  326. CHECK(it.ReadBool(&value));
  327. if (cur_dict) {
  328. cur_dict->SetBoolKey(ReadKeyName(it), value);
  329. } else {
  330. cur_list->Append(value);
  331. }
  332. } break;
  333. case kTypeInt: {
  334. int value;
  335. CHECK(it.ReadInt(&value));
  336. if (cur_dict) {
  337. cur_dict->SetIntKey(ReadKeyName(it), value);
  338. } else {
  339. cur_list->Append(value);
  340. }
  341. } break;
  342. case kTypeDouble: {
  343. TraceEvent::TraceValue trace_value;
  344. CHECK(it.ReadDouble(&trace_value.as_double));
  345. Value base_value;
  346. if (!std::isfinite(trace_value.as_double)) {
  347. // base::Value doesn't support nan and infinity values. Use strings
  348. // for them instead. This follows the same convention in
  349. // AppendAsTraceFormat(), supported by TraceValue::Append*().
  350. std::string value_string;
  351. trace_value.AppendAsString(TRACE_VALUE_TYPE_DOUBLE, &value_string);
  352. base_value = Value(value_string);
  353. } else {
  354. base_value = Value(trace_value.as_double);
  355. }
  356. if (cur_dict) {
  357. cur_dict->SetKey(ReadKeyName(it), std::move(base_value));
  358. } else {
  359. cur_list->Append(std::move(base_value));
  360. }
  361. } break;
  362. case kTypeString: {
  363. std::string value;
  364. CHECK(it.ReadString(&value));
  365. if (cur_dict) {
  366. cur_dict->SetStringKey(ReadKeyName(it), std::move(value));
  367. } else {
  368. cur_list->Append(std::move(value));
  369. }
  370. } break;
  371. default:
  372. NOTREACHED();
  373. }
  374. }
  375. DCHECK(stack.empty());
  376. return base::Value::ToUniquePtrValue(std::move(root));
  377. }
  378. private:
  379. Pickle pickle_;
  380. };
  381. std::unique_ptr<TracedValue::Writer> CreateWriter(size_t capacity) {
  382. TracedValue::WriterFactoryCallback callback =
  383. g_writer_factory_callback.load(std::memory_order_relaxed);
  384. if (callback) {
  385. return callback(capacity);
  386. }
  387. return std::make_unique<PickleWriter>(capacity);
  388. }
  389. } // namespace
  390. bool TracedValue::Writer::AppendToProto(ProtoAppender* appender) {
  391. return false;
  392. }
  393. // static
  394. void TracedValue::SetWriterFactoryCallback(WriterFactoryCallback callback) {
  395. g_writer_factory_callback.store(callback);
  396. }
  397. TracedValue::TracedValue(size_t capacity)
  398. : TracedValue(capacity, /*forced_json*/ false) {}
  399. TracedValue::TracedValue(size_t capacity, bool forced_json) {
  400. DEBUG_PUSH_CONTAINER(kStackTypeDict);
  401. writer_ = forced_json ? std::make_unique<PickleWriter>(capacity)
  402. : CreateWriter(capacity);
  403. }
  404. TracedValue::~TracedValue() {
  405. DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
  406. DEBUG_POP_CONTAINER();
  407. DCHECK_CONTAINER_STACK_DEPTH_EQ(0u);
  408. }
  409. void TracedValue::SetInteger(const char* name, int value) {
  410. DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
  411. writer_->SetInteger(name, value);
  412. }
  413. void TracedValue::SetIntegerWithCopiedName(base::StringPiece name, int value) {
  414. DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
  415. writer_->SetIntegerWithCopiedName(name, value);
  416. }
  417. void TracedValue::SetDouble(const char* name, double value) {
  418. DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
  419. writer_->SetDouble(name, value);
  420. }
  421. void TracedValue::SetDoubleWithCopiedName(base::StringPiece name,
  422. double value) {
  423. DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
  424. writer_->SetDoubleWithCopiedName(name, value);
  425. }
  426. void TracedValue::SetBoolean(const char* name, bool value) {
  427. DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
  428. writer_->SetBoolean(name, value);
  429. }
  430. void TracedValue::SetBooleanWithCopiedName(base::StringPiece name, bool value) {
  431. DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
  432. writer_->SetBooleanWithCopiedName(name, value);
  433. }
  434. void TracedValue::SetString(const char* name, base::StringPiece value) {
  435. DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
  436. writer_->SetString(name, value);
  437. }
  438. void TracedValue::SetStringWithCopiedName(base::StringPiece name,
  439. base::StringPiece value) {
  440. DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
  441. writer_->SetStringWithCopiedName(name, value);
  442. }
  443. void TracedValue::SetValue(const char* name, TracedValue* value) {
  444. DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
  445. writer_->SetValue(name, value->writer_.get());
  446. }
  447. void TracedValue::SetValueWithCopiedName(base::StringPiece name,
  448. TracedValue* value) {
  449. DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
  450. writer_->SetValueWithCopiedName(name, value->writer_.get());
  451. }
  452. namespace {
  453. // TODO(altimin): Add native support for pointers for nested values in
  454. // DebugAnnotation proto.
  455. std::string PointerToString(void* value) {
  456. return base::StringPrintf(
  457. "0x%" PRIx64, static_cast<uint64_t>(reinterpret_cast<uintptr_t>(value)));
  458. }
  459. } // namespace
  460. void TracedValue::SetPointer(const char* name, void* value) {
  461. DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
  462. writer_->SetString(name, PointerToString(value));
  463. }
  464. void TracedValue::SetPointerWithCopiedName(base::StringPiece name,
  465. void* value) {
  466. DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
  467. writer_->SetStringWithCopiedName(name, PointerToString(value));
  468. }
  469. void TracedValue::BeginDictionary(const char* name) {
  470. DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
  471. DEBUG_PUSH_CONTAINER(kStackTypeDict);
  472. writer_->BeginDictionary(name);
  473. }
  474. void TracedValue::BeginDictionaryWithCopiedName(base::StringPiece name) {
  475. DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
  476. DEBUG_PUSH_CONTAINER(kStackTypeDict);
  477. writer_->BeginDictionaryWithCopiedName(name);
  478. }
  479. void TracedValue::BeginArray(const char* name) {
  480. DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
  481. DEBUG_PUSH_CONTAINER(kStackTypeArray);
  482. writer_->BeginArray(name);
  483. }
  484. void TracedValue::BeginArrayWithCopiedName(base::StringPiece name) {
  485. DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
  486. DEBUG_PUSH_CONTAINER(kStackTypeArray);
  487. writer_->BeginArrayWithCopiedName(name);
  488. }
  489. void TracedValue::AppendInteger(int value) {
  490. DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
  491. writer_->AppendInteger(value);
  492. }
  493. void TracedValue::AppendDouble(double value) {
  494. DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
  495. writer_->AppendDouble(value);
  496. }
  497. void TracedValue::AppendBoolean(bool value) {
  498. DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
  499. writer_->AppendBoolean(value);
  500. }
  501. void TracedValue::AppendString(base::StringPiece value) {
  502. DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
  503. writer_->AppendString(value);
  504. }
  505. void TracedValue::AppendPointer(void* value) {
  506. DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
  507. writer_->AppendString(PointerToString(value));
  508. }
  509. void TracedValue::BeginArray() {
  510. DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
  511. DEBUG_PUSH_CONTAINER(kStackTypeArray);
  512. writer_->BeginArray();
  513. }
  514. void TracedValue::BeginDictionary() {
  515. DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
  516. DEBUG_PUSH_CONTAINER(kStackTypeDict);
  517. writer_->BeginDictionary();
  518. }
  519. void TracedValue::EndArray() {
  520. DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
  521. DEBUG_POP_CONTAINER();
  522. writer_->EndArray();
  523. }
  524. void TracedValue::EndDictionary() {
  525. DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
  526. DEBUG_POP_CONTAINER();
  527. writer_->EndDictionary();
  528. }
  529. std::unique_ptr<base::Value> TracedValue::ToBaseValue() const {
  530. DCHECK(writer_->IsPickleWriter());
  531. return static_cast<const PickleWriter*>(writer_.get())->ToBaseValue();
  532. }
  533. void TracedValue::AppendAsTraceFormat(std::string* out) const {
  534. DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
  535. DCHECK_CONTAINER_STACK_DEPTH_EQ(1u);
  536. writer_->AppendAsTraceFormat(out);
  537. }
  538. bool TracedValue::AppendToProto(ProtoAppender* appender) {
  539. return writer_->AppendToProto(appender);
  540. }
  541. void TracedValue::EstimateTraceMemoryOverhead(
  542. TraceEventMemoryOverhead* overhead) {
  543. writer_->EstimateTraceMemoryOverhead(overhead);
  544. }
  545. TracedValue::Array::Array(const std::initializer_list<ArrayItem> items) {
  546. items_ = std::move(items);
  547. }
  548. TracedValue::Array::Array(TracedValue::Array&& other) {
  549. items_ = std::move(other.items_);
  550. }
  551. void TracedValue::Array::WriteToValue(TracedValue* value) const {
  552. for (const auto& item : items_) {
  553. item.WriteToValue(value);
  554. }
  555. }
  556. TracedValue::Dictionary::Dictionary(
  557. const std::initializer_list<DictionaryItem> items) {
  558. items_ = items;
  559. }
  560. TracedValue::Dictionary::Dictionary(TracedValue::Dictionary&& other) {
  561. items_ = std::move(other.items_);
  562. }
  563. void TracedValue::Dictionary::WriteToValue(TracedValue* value) const {
  564. for (const auto& item : items_) {
  565. item.WriteToValue(value);
  566. }
  567. }
  568. TracedValue::ValueHolder::ValueHolder(int value) {
  569. kept_value_.int_value = value;
  570. kept_value_type_ = KeptValueType::kIntType;
  571. }
  572. TracedValue::ValueHolder::ValueHolder(double value) {
  573. kept_value_.double_value = value;
  574. kept_value_type_ = KeptValueType::kDoubleType;
  575. }
  576. TracedValue::ValueHolder::ValueHolder(bool value) {
  577. kept_value_.bool_value = value;
  578. kept_value_type_ = KeptValueType::kBoolType;
  579. }
  580. TracedValue::ValueHolder::ValueHolder(base::StringPiece value) {
  581. kept_value_.string_piece_value = value;
  582. kept_value_type_ = KeptValueType::kStringPieceType;
  583. }
  584. TracedValue::ValueHolder::ValueHolder(std::string value) {
  585. new (&kept_value_.std_string_value) std::string(std::move(value));
  586. kept_value_type_ = KeptValueType::kStdStringType;
  587. }
  588. TracedValue::ValueHolder::ValueHolder(void* value) {
  589. kept_value_.void_ptr_value = value;
  590. kept_value_type_ = KeptValueType::kVoidPtrType;
  591. }
  592. TracedValue::ValueHolder::ValueHolder(const char* value) {
  593. kept_value_.string_piece_value = value;
  594. kept_value_type_ = KeptValueType::kStringPieceType;
  595. }
  596. TracedValue::ValueHolder::ValueHolder(TracedValue::Dictionary& value) {
  597. new (&kept_value_.dictionary_value) TracedValue::Dictionary(std::move(value));
  598. kept_value_type_ = KeptValueType::kDictionaryType;
  599. }
  600. TracedValue::ValueHolder::ValueHolder(TracedValue::Array& value) {
  601. new (&kept_value_.array_value) TracedValue::Array(std::move(value));
  602. kept_value_type_ = KeptValueType::kArrayType;
  603. }
  604. TracedValue::ValueHolder::ValueHolder(TracedValue::ValueHolder&& other) {
  605. // Remember to call a destructor if necessary.
  606. if (kept_value_type_ == KeptValueType::kStdStringType) {
  607. delete (&kept_value_.std_string_value);
  608. }
  609. switch (other.kept_value_type_) {
  610. case KeptValueType::kIntType: {
  611. kept_value_.int_value = other.kept_value_.int_value;
  612. break;
  613. }
  614. case KeptValueType::kDoubleType: {
  615. kept_value_.double_value = other.kept_value_.double_value;
  616. break;
  617. }
  618. case KeptValueType::kBoolType: {
  619. kept_value_.bool_value = other.kept_value_.bool_value;
  620. break;
  621. }
  622. case KeptValueType::kStringPieceType: {
  623. kept_value_.string_piece_value = other.kept_value_.string_piece_value;
  624. break;
  625. }
  626. case KeptValueType::kStdStringType: {
  627. new (&kept_value_.std_string_value)
  628. std::string(std::move(other.kept_value_.std_string_value));
  629. break;
  630. }
  631. case KeptValueType::kVoidPtrType: {
  632. kept_value_.void_ptr_value = other.kept_value_.void_ptr_value;
  633. break;
  634. }
  635. case KeptValueType::kArrayType: {
  636. new (&kept_value_.array_value)
  637. TracedValue::Array(std::move(other.kept_value_.array_value));
  638. break;
  639. }
  640. case KeptValueType::kDictionaryType: {
  641. new (&kept_value_.dictionary_value) TracedValue::Dictionary(
  642. std::move(other.kept_value_.dictionary_value));
  643. break;
  644. }
  645. }
  646. kept_value_type_ = other.kept_value_type_;
  647. }
  648. void TracedValue::ValueHolder::WriteToValue(TracedValue* value) const {
  649. switch (kept_value_type_) {
  650. case KeptValueType::kIntType: {
  651. value->AppendInteger(kept_value_.int_value);
  652. break;
  653. }
  654. case KeptValueType::kDoubleType: {
  655. value->AppendDouble(kept_value_.double_value);
  656. break;
  657. }
  658. case KeptValueType::kBoolType: {
  659. value->AppendBoolean(kept_value_.bool_value);
  660. break;
  661. }
  662. case KeptValueType::kStringPieceType: {
  663. value->AppendString(kept_value_.string_piece_value);
  664. break;
  665. }
  666. case KeptValueType::kStdStringType: {
  667. value->AppendString(kept_value_.std_string_value);
  668. break;
  669. }
  670. case KeptValueType::kVoidPtrType: {
  671. value->AppendPointer(kept_value_.void_ptr_value);
  672. break;
  673. }
  674. case KeptValueType::kArrayType: {
  675. value->BeginArray();
  676. kept_value_.array_value.WriteToValue(value);
  677. value->EndArray();
  678. break;
  679. }
  680. case KeptValueType::kDictionaryType: {
  681. value->BeginDictionary();
  682. kept_value_.dictionary_value.WriteToValue(value);
  683. value->EndDictionary();
  684. break;
  685. }
  686. }
  687. }
  688. void TracedValue::ValueHolder::WriteToValue(const char* name,
  689. TracedValue* value) const {
  690. switch (kept_value_type_) {
  691. case KeptValueType::kIntType: {
  692. value->SetInteger(name, kept_value_.int_value);
  693. break;
  694. }
  695. case KeptValueType::kDoubleType: {
  696. value->SetDouble(name, kept_value_.double_value);
  697. break;
  698. }
  699. case KeptValueType::kBoolType: {
  700. value->SetBoolean(name, kept_value_.bool_value);
  701. break;
  702. }
  703. case KeptValueType::kStringPieceType: {
  704. value->SetString(name, kept_value_.string_piece_value);
  705. break;
  706. }
  707. case KeptValueType::kStdStringType: {
  708. value->SetString(name, kept_value_.std_string_value);
  709. break;
  710. }
  711. case KeptValueType::kVoidPtrType: {
  712. value->SetPointer(name, kept_value_.void_ptr_value);
  713. break;
  714. }
  715. case KeptValueType::kArrayType: {
  716. value->BeginArray(name);
  717. kept_value_.array_value.WriteToValue(value);
  718. value->EndArray();
  719. break;
  720. }
  721. case KeptValueType::kDictionaryType: {
  722. value->BeginDictionary(name);
  723. kept_value_.dictionary_value.WriteToValue(value);
  724. value->EndDictionary();
  725. break;
  726. }
  727. }
  728. }
  729. void TracedValue::ArrayItem::WriteToValue(TracedValue* value) const {
  730. ValueHolder::WriteToValue(value);
  731. }
  732. void TracedValue::DictionaryItem::WriteToValue(TracedValue* value) const {
  733. ValueHolder::WriteToValue(name_, value);
  734. }
  735. std::unique_ptr<TracedValue> TracedValue::Build(
  736. const std::initializer_list<DictionaryItem> items) {
  737. std::unique_ptr<TracedValue> value(new TracedValue());
  738. for (const auto& item : items) {
  739. item.WriteToValue(value.get());
  740. }
  741. return value;
  742. }
  743. std::string TracedValueJSON::ToJSON() const {
  744. std::string result;
  745. AppendAsTraceFormat(&result);
  746. return result;
  747. }
  748. std::string TracedValueJSON::ToFormattedJSON() const {
  749. std::string str;
  750. base::JSONWriter::WriteWithOptions(
  751. *ToBaseValue(),
  752. base::JSONWriter::OPTIONS_OMIT_DOUBLE_TYPE_PRESERVATION |
  753. base::JSONWriter::OPTIONS_PRETTY_PRINT,
  754. &str);
  755. return str;
  756. }
  757. TracedValue::ArrayScope::ArrayScope(TracedValue* value) : value_(value) {}
  758. TracedValue::ArrayScope::~ArrayScope() {
  759. value_->EndArray();
  760. }
  761. TracedValue::ArrayScope TracedValue::AppendArrayScoped() {
  762. BeginArray();
  763. return TracedValue::ArrayScope(this);
  764. }
  765. TracedValue::ArrayScope TracedValue::BeginArrayScoped(const char* name) {
  766. BeginArray(name);
  767. return TracedValue::ArrayScope(this);
  768. }
  769. TracedValue::ArrayScope TracedValue::BeginArrayScopedWithCopiedName(
  770. base::StringPiece name) {
  771. BeginArrayWithCopiedName(name);
  772. return TracedValue::ArrayScope(this);
  773. }
  774. TracedValue::DictionaryScope::DictionaryScope(TracedValue* value)
  775. : value_(value) {}
  776. TracedValue::DictionaryScope::~DictionaryScope() {
  777. value_->EndDictionary();
  778. }
  779. TracedValue::DictionaryScope TracedValue::AppendDictionaryScoped() {
  780. BeginDictionary();
  781. return TracedValue::DictionaryScope(this);
  782. }
  783. TracedValue::DictionaryScope TracedValue::BeginDictionaryScoped(
  784. const char* name) {
  785. BeginDictionary(name);
  786. return TracedValue::DictionaryScope(this);
  787. }
  788. TracedValue::DictionaryScope TracedValue::BeginDictionaryScopedWithCopiedName(
  789. base::StringPiece name) {
  790. BeginDictionaryWithCopiedName(name);
  791. return TracedValue::DictionaryScope(this);
  792. }
  793. } // namespace trace_event
  794. } // namespace base