OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 2122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2133 return diff; | 2133 return diff; |
2134 } | 2134 } |
2135 | 2135 |
2136 | 2136 |
2137 class OutputStreamWriter { | 2137 class OutputStreamWriter { |
2138 public: | 2138 public: |
2139 explicit OutputStreamWriter(v8::OutputStream* stream) | 2139 explicit OutputStreamWriter(v8::OutputStream* stream) |
2140 : stream_(stream), | 2140 : stream_(stream), |
2141 chunk_size_(stream->GetChunkSize()), | 2141 chunk_size_(stream->GetChunkSize()), |
2142 chunk_(chunk_size_), | 2142 chunk_(chunk_size_), |
2143 chunk_pos_(0) { | 2143 chunk_pos_(0), |
| 2144 aborted_(false) { |
2144 ASSERT(chunk_size_ > 0); | 2145 ASSERT(chunk_size_ > 0); |
2145 } | 2146 } |
| 2147 bool aborted() { return aborted_; } |
2146 void AddCharacter(char c) { | 2148 void AddCharacter(char c) { |
2147 ASSERT(c != '\0'); | 2149 ASSERT(c != '\0'); |
2148 ASSERT(chunk_pos_ < chunk_size_); | 2150 ASSERT(chunk_pos_ < chunk_size_); |
2149 chunk_[chunk_pos_++] = c; | 2151 chunk_[chunk_pos_++] = c; |
2150 MaybeWriteChunk(); | 2152 MaybeWriteChunk(); |
2151 } | 2153 } |
2152 void AddString(const char* s) { | 2154 void AddString(const char* s) { |
2153 AddSubstring(s, StrLength(s)); | 2155 AddSubstring(s, StrLength(s)); |
2154 } | 2156 } |
2155 void AddSubstring(const char* s, int n) { | 2157 void AddSubstring(const char* s, int n) { |
2156 if (n <= 0) return; | 2158 if (n <= 0) return; |
2157 ASSERT(static_cast<size_t>(n) <= strlen(s)); | 2159 ASSERT(static_cast<size_t>(n) <= strlen(s)); |
2158 const char* s_end = s + n; | 2160 const char* s_end = s + n; |
2159 while (s < s_end) { | 2161 while (s < s_end) { |
2160 int s_chunk_size = Min( | 2162 int s_chunk_size = Min( |
2161 chunk_size_ - chunk_pos_, static_cast<int>(s_end - s)); | 2163 chunk_size_ - chunk_pos_, static_cast<int>(s_end - s)); |
2162 ASSERT(s_chunk_size > 0); | 2164 ASSERT(s_chunk_size > 0); |
2163 memcpy(chunk_.start() + chunk_pos_, s, s_chunk_size); | 2165 memcpy(chunk_.start() + chunk_pos_, s, s_chunk_size); |
2164 s += s_chunk_size; | 2166 s += s_chunk_size; |
2165 chunk_pos_ += s_chunk_size; | 2167 chunk_pos_ += s_chunk_size; |
2166 MaybeWriteChunk(); | 2168 MaybeWriteChunk(); |
2167 } | 2169 } |
2168 } | 2170 } |
2169 void AddNumber(int n) { AddNumberImpl<int>(n, "%d"); } | 2171 void AddNumber(int n) { AddNumberImpl<int>(n, "%d"); } |
2170 void AddNumber(unsigned n) { AddNumberImpl<unsigned>(n, "%u"); } | 2172 void AddNumber(unsigned n) { AddNumberImpl<unsigned>(n, "%u"); } |
2171 void AddNumber(uint64_t n) { AddNumberImpl<uint64_t>(n, "%llu"); } | 2173 void AddNumber(uint64_t n) { AddNumberImpl<uint64_t>(n, "%llu"); } |
2172 void Finalize() { | 2174 void Finalize() { |
| 2175 if (aborted_) return; |
2173 ASSERT(chunk_pos_ < chunk_size_); | 2176 ASSERT(chunk_pos_ < chunk_size_); |
2174 if (chunk_pos_ != 0) { | 2177 if (chunk_pos_ != 0) { |
2175 WriteChunk(); | 2178 WriteChunk(); |
2176 } | 2179 } |
2177 stream_->EndOfStream(); | 2180 stream_->EndOfStream(); |
2178 } | 2181 } |
2179 | 2182 |
2180 private: | 2183 private: |
2181 template<typename T> | 2184 template<typename T> |
2182 void AddNumberImpl(T n, const char* format) { | 2185 void AddNumberImpl(T n, const char* format) { |
2183 ScopedVector<char> buffer(32); | 2186 ScopedVector<char> buffer(32); |
2184 int result = OS::SNPrintF(buffer, format, n); | 2187 int result = OS::SNPrintF(buffer, format, n); |
2185 USE(result); | 2188 USE(result); |
2186 ASSERT(result != -1); | 2189 ASSERT(result != -1); |
2187 AddString(buffer.start()); | 2190 AddString(buffer.start()); |
2188 } | 2191 } |
2189 void MaybeWriteChunk() { | 2192 void MaybeWriteChunk() { |
2190 ASSERT(chunk_pos_ <= chunk_size_); | 2193 ASSERT(chunk_pos_ <= chunk_size_); |
2191 if (chunk_pos_ == chunk_size_) { | 2194 if (chunk_pos_ == chunk_size_) { |
2192 WriteChunk(); | 2195 WriteChunk(); |
2193 chunk_pos_ = 0; | 2196 chunk_pos_ = 0; |
2194 } | 2197 } |
2195 } | 2198 } |
2196 void WriteChunk() { | 2199 void WriteChunk() { |
2197 stream_->WriteAsciiChunk(chunk_.start(), chunk_pos_); | 2200 if (aborted_) return; |
| 2201 if (stream_->WriteAsciiChunk(chunk_.start(), chunk_pos_) == |
| 2202 v8::OutputStream::kAbort) aborted_ = true; |
2198 } | 2203 } |
2199 | 2204 |
2200 v8::OutputStream* stream_; | 2205 v8::OutputStream* stream_; |
2201 int chunk_size_; | 2206 int chunk_size_; |
2202 ScopedVector<char> chunk_; | 2207 ScopedVector<char> chunk_; |
2203 int chunk_pos_; | 2208 int chunk_pos_; |
| 2209 bool aborted_; |
2204 }; | 2210 }; |
2205 | 2211 |
2206 void HeapSnapshotJSONSerializer::Serialize(v8::OutputStream* stream) { | 2212 void HeapSnapshotJSONSerializer::Serialize(v8::OutputStream* stream) { |
2207 ASSERT(writer_ == NULL); | 2213 ASSERT(writer_ == NULL); |
2208 writer_ = new OutputStreamWriter(stream); | 2214 writer_ = new OutputStreamWriter(stream); |
2209 | 2215 |
2210 // Since nodes graph is cyclic, we need the first pass to enumerate | 2216 // Since nodes graph is cyclic, we need the first pass to enumerate |
2211 // them. Strings can be serialized in one pass. | 2217 // them. Strings can be serialized in one pass. |
2212 EnumerateNodes(); | 2218 EnumerateNodes(); |
2213 | 2219 SerializeImpl(); |
2214 writer_->AddCharacter('{'); | 2220 |
2215 writer_->AddString("\"snapshot\":{"); | |
2216 SerializeSnapshot(); | |
2217 writer_->AddString("},\n"); | |
2218 writer_->AddString("\"nodes\":["); | |
2219 SerializeNodes(); | |
2220 writer_->AddString("],\n"); | |
2221 writer_->AddString("\"strings\":["); | |
2222 SerializeStrings(); | |
2223 writer_->AddCharacter(']'); | |
2224 writer_->AddCharacter('}'); | |
2225 writer_->Finalize(); | |
2226 | |
2227 delete writer_; | 2221 delete writer_; |
2228 writer_ = NULL; | 2222 writer_ = NULL; |
2229 } | 2223 } |
2230 | 2224 |
2231 | 2225 |
| 2226 void HeapSnapshotJSONSerializer::SerializeImpl() { |
| 2227 writer_->AddCharacter('{'); |
| 2228 writer_->AddString("\"snapshot\":{"); |
| 2229 SerializeSnapshot(); |
| 2230 if (writer_->aborted()) return; |
| 2231 writer_->AddString("},\n"); |
| 2232 writer_->AddString("\"nodes\":["); |
| 2233 SerializeNodes(); |
| 2234 if (writer_->aborted()) return; |
| 2235 writer_->AddString("],\n"); |
| 2236 writer_->AddString("\"strings\":["); |
| 2237 SerializeStrings(); |
| 2238 if (writer_->aborted()) return; |
| 2239 writer_->AddCharacter(']'); |
| 2240 writer_->AddCharacter('}'); |
| 2241 writer_->Finalize(); |
| 2242 } |
| 2243 |
| 2244 |
2232 class HeapSnapshotJSONSerializerEnumerator { | 2245 class HeapSnapshotJSONSerializerEnumerator { |
2233 public: | 2246 public: |
2234 explicit HeapSnapshotJSONSerializerEnumerator(HeapSnapshotJSONSerializer* s) | 2247 explicit HeapSnapshotJSONSerializerEnumerator(HeapSnapshotJSONSerializer* s) |
2235 : s_(s) { | 2248 : s_(s) { |
2236 } | 2249 } |
2237 void Apply(HeapEntry** entry) { | 2250 void Apply(HeapEntry** entry) { |
2238 s_->GetNodeId(*entry); | 2251 s_->GetNodeId(*entry); |
2239 } | 2252 } |
2240 private: | 2253 private: |
2241 HeapSnapshotJSONSerializer* s_; | 2254 HeapSnapshotJSONSerializer* s_; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2289 writer_->AddNumber(GetStringId(entry->name())); | 2302 writer_->AddNumber(GetStringId(entry->name())); |
2290 writer_->AddCharacter(','); | 2303 writer_->AddCharacter(','); |
2291 writer_->AddNumber(entry->id()); | 2304 writer_->AddNumber(entry->id()); |
2292 writer_->AddCharacter(','); | 2305 writer_->AddCharacter(','); |
2293 writer_->AddNumber(entry->self_size()); | 2306 writer_->AddNumber(entry->self_size()); |
2294 Vector<HeapGraphEdge> children = entry->children(); | 2307 Vector<HeapGraphEdge> children = entry->children(); |
2295 writer_->AddCharacter(','); | 2308 writer_->AddCharacter(','); |
2296 writer_->AddNumber(children.length()); | 2309 writer_->AddNumber(children.length()); |
2297 for (int i = 0; i < children.length(); ++i) { | 2310 for (int i = 0; i < children.length(); ++i) { |
2298 SerializeEdge(&children[i]); | 2311 SerializeEdge(&children[i]); |
| 2312 if (writer_->aborted()) return; |
2299 } | 2313 } |
2300 } | 2314 } |
2301 | 2315 |
2302 | 2316 |
2303 void HeapSnapshotJSONSerializer::SerializeNodes() { | 2317 void HeapSnapshotJSONSerializer::SerializeNodes() { |
2304 // The first (zero) item of nodes array is a JSON-ified object | 2318 // The first (zero) item of nodes array is a JSON-ified object |
2305 // describing node serialization layout. | 2319 // describing node serialization layout. |
2306 // We use a set of macros to improve readability. | 2320 // We use a set of macros to improve readability. |
2307 #define JSON_A(s) "["s"]" | 2321 #define JSON_A(s) "["s"]" |
2308 #define JSON_O(s) "{"s"}" | 2322 #define JSON_O(s) "{"s"}" |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2356 for (int i = 1; i < sorted_nodes.length(); ++i) { | 2370 for (int i = 1; i < sorted_nodes.length(); ++i) { |
2357 HeapEntry* prev_heap_entry = | 2371 HeapEntry* prev_heap_entry = |
2358 reinterpret_cast<HeapEntry*>(sorted_nodes[i-1]->key); | 2372 reinterpret_cast<HeapEntry*>(sorted_nodes[i-1]->key); |
2359 prev_value += node_fields_count + | 2373 prev_value += node_fields_count + |
2360 prev_heap_entry->children().length() * edge_fields_count; | 2374 prev_heap_entry->children().length() * edge_fields_count; |
2361 sorted_nodes[i]->value = reinterpret_cast<void*>(prev_value); | 2375 sorted_nodes[i]->value = reinterpret_cast<void*>(prev_value); |
2362 } | 2376 } |
2363 } | 2377 } |
2364 for (int i = 0; i < sorted_nodes.length(); ++i) { | 2378 for (int i = 0; i < sorted_nodes.length(); ++i) { |
2365 SerializeNode(reinterpret_cast<HeapEntry*>(sorted_nodes[i]->key)); | 2379 SerializeNode(reinterpret_cast<HeapEntry*>(sorted_nodes[i]->key)); |
| 2380 if (writer_->aborted()) return; |
2366 } | 2381 } |
2367 } | 2382 } |
2368 | 2383 |
2369 | 2384 |
2370 void HeapSnapshotJSONSerializer::SerializeSnapshot() { | 2385 void HeapSnapshotJSONSerializer::SerializeSnapshot() { |
2371 writer_->AddString("\"title\":\""); | 2386 writer_->AddString("\"title\":\""); |
2372 writer_->AddString(snapshot_->title()); | 2387 writer_->AddString(snapshot_->title()); |
2373 writer_->AddString("\""); | 2388 writer_->AddString("\""); |
2374 writer_->AddString(",\"uid\":"); | 2389 writer_->AddString(",\"uid\":"); |
2375 writer_->AddNumber(snapshot_->uid()); | 2390 writer_->AddNumber(snapshot_->uid()); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2436 | 2451 |
2437 | 2452 |
2438 void HeapSnapshotJSONSerializer::SerializeStrings() { | 2453 void HeapSnapshotJSONSerializer::SerializeStrings() { |
2439 List<HashMap::Entry*> sorted_strings; | 2454 List<HashMap::Entry*> sorted_strings; |
2440 SortHashMap(&strings_, &sorted_strings); | 2455 SortHashMap(&strings_, &sorted_strings); |
2441 writer_->AddString("\"<dummy>\""); | 2456 writer_->AddString("\"<dummy>\""); |
2442 for (int i = 0; i < sorted_strings.length(); ++i) { | 2457 for (int i = 0; i < sorted_strings.length(); ++i) { |
2443 writer_->AddCharacter(','); | 2458 writer_->AddCharacter(','); |
2444 SerializeString( | 2459 SerializeString( |
2445 reinterpret_cast<const unsigned char*>(sorted_strings[i]->key)); | 2460 reinterpret_cast<const unsigned char*>(sorted_strings[i]->key)); |
| 2461 if (writer_->aborted()) return; |
2446 } | 2462 } |
2447 } | 2463 } |
2448 | 2464 |
2449 | 2465 |
2450 template<typename T> | 2466 template<typename T> |
2451 inline static int SortUsingEntryValue(const T* x, const T* y) { | 2467 inline static int SortUsingEntryValue(const T* x, const T* y) { |
2452 return reinterpret_cast<intptr_t>((*x)->value) - | 2468 return reinterpret_cast<intptr_t>((*x)->value) - |
2453 reinterpret_cast<intptr_t>((*y)->value); | 2469 reinterpret_cast<intptr_t>((*y)->value); |
2454 } | 2470 } |
2455 | 2471 |
2456 void HeapSnapshotJSONSerializer::SortHashMap( | 2472 void HeapSnapshotJSONSerializer::SortHashMap( |
2457 HashMap* map, List<HashMap::Entry*>* sorted_entries) { | 2473 HashMap* map, List<HashMap::Entry*>* sorted_entries) { |
2458 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) | 2474 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) |
2459 sorted_entries->Add(p); | 2475 sorted_entries->Add(p); |
2460 sorted_entries->Sort(SortUsingEntryValue); | 2476 sorted_entries->Sort(SortUsingEntryValue); |
2461 } | 2477 } |
2462 | 2478 |
2463 } } // namespace v8::internal | 2479 } } // namespace v8::internal |
2464 | 2480 |
2465 #endif // ENABLE_LOGGING_AND_PROFILING | 2481 #endif // ENABLE_LOGGING_AND_PROFILING |
OLD | NEW |