1 // Copyright 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.
7 #include "platform/TracedValue.h"
9 #include "platform/Decimal.h"
10 #include "platform/JSONValues.h"
11 #include "wtf/HashMap.h"
12 #include "wtf/text/StringBuilder.h"
13 #include "wtf/text/StringHash.h"
19 String
threadSafeCopy(const String
& string
)
21 RefPtr
<StringImpl
> copy(string
.impl());
22 if (string
.isSafeToSendToAnotherThread())
24 return string
.isolatedCopy();
29 // InternalValue and its subclasses are JSON like objects which TracedValue
30 // internally uses. We don't use JSONValues because we want to count how much
31 // memory TracedValue uses.
32 // TODO(bashi): InternalValue should use an allocator which counts allocation
33 // size as tracing overhead.
34 class InternalValue
: public RefCounted
<InternalValue
> {
44 virtual ~InternalValue() { }
50 virtual void toJSON(StringBuilder
* builder
)
56 class TracedNumberValue
: public InternalValue
{
58 static PassRefPtr
<TracedNumberValue
> create(double value
)
60 return adoptRef(new TracedNumberValue(value
));
62 virtual ~TracedNumberValue() { }
63 virtual Type
type() { return TypeNumber
; }
64 virtual void toJSON(StringBuilder
* builder
)
66 builder
->append(Decimal::fromDouble(m_value
).toString());
70 explicit TracedNumberValue(double value
) : m_value(value
) { }
74 class TracedBooleanValue
: public InternalValue
{
76 static PassRefPtr
<TracedBooleanValue
> create(bool value
)
78 return adoptRef(new TracedBooleanValue(value
));
80 virtual ~TracedBooleanValue() { }
81 virtual Type
type() { return TypeBoolean
; }
82 virtual void toJSON(StringBuilder
* builder
)
84 builder
->append(m_value
? "true" : "false");
88 explicit TracedBooleanValue(bool value
) : m_value(value
) { }
92 class TracedStringValue
: public InternalValue
{
94 static PassRefPtr
<TracedStringValue
> create(String value
)
96 return adoptRef(new TracedStringValue(value
));
98 virtual ~TracedStringValue() { }
99 virtual Type
type() { return TypeString
; }
100 virtual void toJSON(StringBuilder
* builder
)
102 doubleQuoteStringForJSON(m_value
, builder
);
106 explicit TracedStringValue(String value
) : m_value(threadSafeCopy(value
)) { }
110 class TracedArrayValue
: public InternalValue
{
112 static PassRefPtr
<TracedArrayValue
> create()
114 return adoptRef(new TracedArrayValue());
116 virtual ~TracedArrayValue() { }
117 virtual Type
type() { return TypeArray
; }
118 virtual void toJSON(StringBuilder
* builder
)
120 builder
->append('[');
121 for (TracedValueVector::const_iterator it
= m_value
.begin(); it
!= m_value
.end(); ++it
) {
122 if (it
!= m_value
.begin())
123 builder
->append(',');
124 (*it
)->toJSON(builder
);
126 builder
->append(']');
128 void push(PassRefPtr
<InternalValue
> value
) { m_value
.append(value
); }
131 TracedArrayValue() { }
132 TracedValueVector m_value
;
135 class TracedDictionaryValue
: public InternalValue
{
137 static PassRefPtr
<TracedDictionaryValue
> create()
139 return adoptRef(new TracedDictionaryValue());
141 virtual ~TracedDictionaryValue() { }
142 virtual Type
type() { return TypeDictionary
; }
143 virtual void toJSON(StringBuilder
* builder
)
145 builder
->append('{');
146 for (size_t i
= 0; i
< m_order
.size(); ++i
) {
147 TracedValueHashMap::const_iterator it
= m_value
.find(m_order
[i
]);
149 builder
->append(',');
150 doubleQuoteStringForJSON(it
->key
, builder
);
151 builder
->append(':');
152 it
->value
->toJSON(builder
);
154 builder
->append('}');
156 void set(const char* name
, PassRefPtr
<InternalValue
> value
)
158 String nameString
= String(name
);
159 if (m_value
.set(nameString
, value
).isNewEntry
)
160 m_order
.append(nameString
);
164 TracedDictionaryValue() { }
165 TracedValueHashMap m_value
;
166 Vector
<String
> m_order
;
169 PassRefPtr
<TracedValue
> TracedValue::create()
171 return adoptRef(new TracedValue());
174 TracedValue::TracedValue()
176 m_stack
.append(TracedDictionaryValue::create());
179 TracedValue::~TracedValue()
181 ASSERT(m_stack
.size() == 1);
184 void TracedValue::setInteger(const char* name
, int value
)
186 currentDictionary()->set(name
, TracedNumberValue::create(value
));
189 void TracedValue::setDouble(const char* name
, double value
)
191 currentDictionary()->set(name
, TracedNumberValue::create(value
));
194 void TracedValue::setBoolean(const char* name
, bool value
)
196 currentDictionary()->set(name
, TracedBooleanValue::create(value
));
199 void TracedValue::setString(const char* name
, const String
& value
)
201 currentDictionary()->set(name
, TracedStringValue::create(value
));
204 void TracedValue::beginDictionary(const char* name
)
206 RefPtr
<TracedDictionaryValue
> dictionary
= TracedDictionaryValue::create();
207 currentDictionary()->set(name
, dictionary
);
208 m_stack
.append(dictionary
);
211 void TracedValue::beginArray(const char* name
)
213 RefPtr
<TracedArrayValue
> array
= TracedArrayValue::create();
214 currentDictionary()->set(name
, array
);
215 m_stack
.append(array
);
218 void TracedValue::endDictionary()
220 ASSERT(m_stack
.size() > 1);
221 ASSERT(currentDictionary());
222 m_stack
.removeLast();
225 void TracedValue::pushInteger(int value
)
227 currentArray()->push(TracedNumberValue::create(value
));
230 void TracedValue::pushDouble(double value
)
232 currentArray()->push(TracedNumberValue::create(value
));
235 void TracedValue::pushBoolean(bool value
)
237 currentArray()->push(TracedBooleanValue::create(value
));
240 void TracedValue::pushString(const String
& value
)
242 currentArray()->push(TracedStringValue::create(value
));
245 void TracedValue::beginArray()
247 RefPtr
<TracedArrayValue
> array
= TracedArrayValue::create();
248 currentArray()->push(array
);
249 m_stack
.append(array
);
252 void TracedValue::beginDictionary()
254 RefPtr
<TracedDictionaryValue
> dictionary
= TracedDictionaryValue::create();
255 currentArray()->push(dictionary
);
256 m_stack
.append(dictionary
);
259 void TracedValue::endArray()
261 ASSERT(m_stack
.size() > 1);
262 ASSERT(currentArray());
263 m_stack
.removeLast();
266 String
TracedValue::asTraceFormat() const
268 ASSERT(m_stack
.size() == 1);
269 StringBuilder builder
;
270 m_stack
.first()->toJSON(&builder
);
271 return builder
.toString();
274 TracedDictionaryValue
* TracedValue::currentDictionary() const
276 ASSERT(!m_stack
.isEmpty());
277 ASSERT(m_stack
.last()->type() == InternalValue::TypeDictionary
);
278 return static_cast<TracedDictionaryValue
*>(m_stack
.last().get());
281 TracedArrayValue
* TracedValue::currentArray() const
283 ASSERT(!m_stack
.isEmpty());
284 ASSERT(m_stack
.last()->type() == InternalValue::TypeArray
);
285 return static_cast<TracedArrayValue
*>(m_stack
.last().get());