Line data Source code
1 : // Copyright 2016 the V8 project 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 :
5 : #include "src/tracing/traced-value.h"
6 :
7 : #include "src/base/platform/platform.h"
8 : #include "src/conversions.h"
9 : #include "src/vector.h"
10 :
11 : namespace v8 {
12 : namespace tracing {
13 :
14 : namespace {
15 :
16 : #define DCHECK_CURRENT_CONTAINER_IS(x) DCHECK_EQ(x, nesting_stack_.back())
17 : #define DCHECK_CONTAINER_STACK_DEPTH_EQ(x) DCHECK_EQ(x, nesting_stack_.size())
18 : #ifdef DEBUG
19 : const bool kStackTypeDict = false;
20 : const bool kStackTypeArray = true;
21 : #define DEBUG_PUSH_CONTAINER(x) nesting_stack_.push_back(x)
22 : #define DEBUG_POP_CONTAINER() nesting_stack_.pop_back()
23 : #else
24 : #define DEBUG_PUSH_CONTAINER(x) ((void)0)
25 : #define DEBUG_POP_CONTAINER() ((void)0)
26 : #endif
27 :
28 5579 : void EscapeAndAppendString(const char* value, std::string* result) {
29 : *result += '"';
30 60707 : while (*value) {
31 55128 : unsigned char c = *value++;
32 55128 : switch (c) {
33 : case '\b':
34 : *result += "\\b";
35 : break;
36 : case '\f':
37 : *result += "\\f";
38 : break;
39 : case '\n':
40 : *result += "\\n";
41 : break;
42 : case '\r':
43 : *result += "\\r";
44 : break;
45 : case '\t':
46 : *result += "\\t";
47 : break;
48 : case '\"':
49 : *result += "\\\"";
50 : break;
51 : case '\\':
52 : *result += "\\\\";
53 : break;
54 : default:
55 55063 : if (c < '\x20' || c == '\x7F') {
56 : char number_buffer[8];
57 140 : base::OS::SNPrintF(number_buffer, arraysize(number_buffer), "\\u%04X",
58 140 : static_cast<unsigned>(c));
59 : *result += number_buffer;
60 : } else {
61 : *result += c;
62 : }
63 : }
64 : }
65 : *result += '"';
66 5579 : }
67 :
68 : } // namespace
69 :
70 3377 : std::unique_ptr<TracedValue> TracedValue::Create() {
71 6754 : return std::unique_ptr<TracedValue>(new TracedValue());
72 : }
73 :
74 6754 : TracedValue::TracedValue() : first_item_(true) {
75 : DEBUG_PUSH_CONTAINER(kStackTypeDict);
76 0 : }
77 :
78 6754 : TracedValue::~TracedValue() {
79 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
80 : DEBUG_POP_CONTAINER();
81 : DCHECK_CONTAINER_STACK_DEPTH_EQ(0u);
82 3377 : }
83 :
84 17978 : void TracedValue::SetInteger(const char* name, int value) {
85 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
86 17978 : WriteName(name);
87 35956 : data_ += std::to_string(value);
88 17978 : }
89 :
90 2360 : void TracedValue::SetDouble(const char* name, double value) {
91 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
92 2360 : WriteName(name);
93 : i::EmbeddedVector<char, 100> buffer;
94 2360 : data_ += DoubleToCString(value, buffer);
95 2360 : }
96 :
97 20 : void TracedValue::SetBoolean(const char* name, bool value) {
98 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
99 20 : WriteName(name);
100 20 : data_ += value ? "true" : "false";
101 20 : }
102 :
103 5569 : void TracedValue::SetString(const char* name, const char* value) {
104 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
105 5569 : WriteName(name);
106 5569 : EscapeAndAppendString(value, &data_);
107 5569 : }
108 :
109 6075 : void TracedValue::BeginDictionary(const char* name) {
110 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
111 : DEBUG_PUSH_CONTAINER(kStackTypeDict);
112 6075 : WriteName(name);
113 6075 : data_ += '{';
114 6075 : first_item_ = true;
115 6075 : }
116 :
117 1531 : void TracedValue::BeginArray(const char* name) {
118 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
119 : DEBUG_PUSH_CONTAINER(kStackTypeArray);
120 1531 : WriteName(name);
121 1531 : data_ += '[';
122 1531 : first_item_ = true;
123 1531 : }
124 :
125 24932 : void TracedValue::AppendInteger(int value) {
126 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
127 : WriteComma();
128 49864 : data_ += std::to_string(value);
129 24932 : }
130 :
131 0 : void TracedValue::AppendDouble(double value) {
132 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
133 : WriteComma();
134 : i::EmbeddedVector<char, 100> buffer;
135 0 : data_ += DoubleToCString(value, buffer);
136 0 : }
137 :
138 5 : void TracedValue::AppendBoolean(bool value) {
139 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
140 : WriteComma();
141 5 : data_ += value ? "true" : "false";
142 5 : }
143 :
144 10 : void TracedValue::AppendString(const char* value) {
145 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
146 : WriteComma();
147 10 : EscapeAndAppendString(value, &data_);
148 10 : }
149 :
150 5087 : void TracedValue::BeginDictionary() {
151 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
152 : DEBUG_PUSH_CONTAINER(kStackTypeDict);
153 : WriteComma();
154 5087 : data_ += '{';
155 5087 : first_item_ = true;
156 5087 : }
157 :
158 5 : void TracedValue::BeginArray() {
159 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
160 : DEBUG_PUSH_CONTAINER(kStackTypeArray);
161 : WriteComma();
162 5 : data_ += '[';
163 5 : first_item_ = true;
164 5 : }
165 :
166 11162 : void TracedValue::EndDictionary() {
167 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict);
168 : DEBUG_POP_CONTAINER();
169 11162 : data_ += '}';
170 11162 : first_item_ = false;
171 11162 : }
172 :
173 1536 : void TracedValue::EndArray() {
174 : DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray);
175 : DEBUG_POP_CONTAINER();
176 1536 : data_ += ']';
177 1536 : first_item_ = false;
178 1536 : }
179 :
180 0 : void TracedValue::WriteComma() {
181 63572 : if (first_item_) {
182 16051 : first_item_ = false;
183 : } else {
184 47521 : data_ += ',';
185 : }
186 0 : }
187 :
188 33533 : void TracedValue::WriteName(const char* name) {
189 : WriteComma();
190 33533 : data_ += '"';
191 : data_ += name;
192 : data_ += "\":";
193 33533 : }
194 :
195 49 : void TracedValue::AppendAsTraceFormat(std::string* out) const {
196 : *out += '{';
197 : *out += data_;
198 : *out += '}';
199 49 : }
200 :
201 : } // namespace tracing
202 120216 : } // namespace v8
|