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

Side by Side Diff: src/profile-generator.cc

Issue 3421009: Revision 2.4.4.... (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: '' Created 10 years, 3 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 | Annotate | Revision Log
« no previous file with comments | « src/profile-generator.h ('k') | src/runtime.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 13 matching lines...) Expand all
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #ifdef ENABLE_LOGGING_AND_PROFILING 28 #ifdef ENABLE_LOGGING_AND_PROFILING
29 29
30 #include "v8.h" 30 #include "v8.h"
31 #include "global-handles.h" 31 #include "global-handles.h"
32 #include "scopeinfo.h" 32 #include "scopeinfo.h"
33 #include "top.h" 33 #include "top.h"
34 #include "unicode.h"
34 #include "zone-inl.h" 35 #include "zone-inl.h"
35 36
36 #include "profile-generator-inl.h" 37 #include "profile-generator-inl.h"
37 38
38 namespace v8 { 39 namespace v8 {
39 namespace internal { 40 namespace internal {
40 41
41 42
42 TokenEnumerator::TokenEnumerator() 43 TokenEnumerator::TokenEnumerator()
43 : token_locations_(4), 44 : token_locations_(4),
(...skipping 2081 matching lines...) Expand 10 before | Expand all | Expand 10 after
2125 } 2126 }
2126 int add_child_index = 0, added_entry_index = 1; 2127 int add_child_index = 0, added_entry_index = 1;
2127 for (int i = 0; i < added_entries.length(); ++i) { 2128 for (int i = 0; i < added_entries.length(); ++i) {
2128 HeapEntry* entry = added_entries[i]; 2129 HeapEntry* entry = added_entries[i];
2129 if (entry->painted_reachable()) 2130 if (entry->painted_reachable())
2130 diff->AddAddedEntry(add_child_index++, added_entry_index++, entry); 2131 diff->AddAddedEntry(add_child_index++, added_entry_index++, entry);
2131 } 2132 }
2132 return diff; 2133 return diff;
2133 } 2134 }
2134 2135
2136
2137 class OutputStreamWriter {
2138 public:
2139 explicit OutputStreamWriter(v8::OutputStream* stream)
2140 : stream_(stream),
2141 chunk_size_(stream->GetChunkSize()),
2142 chunk_(chunk_size_),
2143 chunk_pos_(0),
2144 aborted_(false) {
2145 ASSERT(chunk_size_ > 0);
2146 }
2147 bool aborted() { return aborted_; }
2148 void AddCharacter(char c) {
2149 ASSERT(c != '\0');
2150 ASSERT(chunk_pos_ < chunk_size_);
2151 chunk_[chunk_pos_++] = c;
2152 MaybeWriteChunk();
2153 }
2154 void AddString(const char* s) {
2155 AddSubstring(s, StrLength(s));
2156 }
2157 void AddSubstring(const char* s, int n) {
2158 if (n <= 0) return;
2159 ASSERT(static_cast<size_t>(n) <= strlen(s));
2160 const char* s_end = s + n;
2161 while (s < s_end) {
2162 int s_chunk_size = Min(
2163 chunk_size_ - chunk_pos_, static_cast<int>(s_end - s));
2164 ASSERT(s_chunk_size > 0);
2165 memcpy(chunk_.start() + chunk_pos_, s, s_chunk_size);
2166 s += s_chunk_size;
2167 chunk_pos_ += s_chunk_size;
2168 MaybeWriteChunk();
2169 }
2170 }
2171 void AddNumber(int n) { AddNumberImpl<int>(n, "%d"); }
2172 void AddNumber(unsigned n) { AddNumberImpl<unsigned>(n, "%u"); }
2173 void AddNumber(uint64_t n) { AddNumberImpl<uint64_t>(n, "%llu"); }
2174 void Finalize() {
2175 if (aborted_) return;
2176 ASSERT(chunk_pos_ < chunk_size_);
2177 if (chunk_pos_ != 0) {
2178 WriteChunk();
2179 }
2180 stream_->EndOfStream();
2181 }
2182
2183 private:
2184 template<typename T>
2185 void AddNumberImpl(T n, const char* format) {
2186 ScopedVector<char> buffer(32);
2187 int result = OS::SNPrintF(buffer, format, n);
2188 USE(result);
2189 ASSERT(result != -1);
2190 AddString(buffer.start());
2191 }
2192 void MaybeWriteChunk() {
2193 ASSERT(chunk_pos_ <= chunk_size_);
2194 if (chunk_pos_ == chunk_size_) {
2195 WriteChunk();
2196 chunk_pos_ = 0;
2197 }
2198 }
2199 void WriteChunk() {
2200 if (aborted_) return;
2201 if (stream_->WriteAsciiChunk(chunk_.start(), chunk_pos_) ==
2202 v8::OutputStream::kAbort) aborted_ = true;
2203 }
2204
2205 v8::OutputStream* stream_;
2206 int chunk_size_;
2207 ScopedVector<char> chunk_;
2208 int chunk_pos_;
2209 bool aborted_;
2210 };
2211
2212 void HeapSnapshotJSONSerializer::Serialize(v8::OutputStream* stream) {
2213 ASSERT(writer_ == NULL);
2214 writer_ = new OutputStreamWriter(stream);
2215
2216 // Since nodes graph is cyclic, we need the first pass to enumerate
2217 // them. Strings can be serialized in one pass.
2218 EnumerateNodes();
2219 SerializeImpl();
2220
2221 delete writer_;
2222 writer_ = NULL;
2223 }
2224
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
2245 class HeapSnapshotJSONSerializerEnumerator {
2246 public:
2247 explicit HeapSnapshotJSONSerializerEnumerator(HeapSnapshotJSONSerializer* s)
2248 : s_(s) {
2249 }
2250 void Apply(HeapEntry** entry) {
2251 s_->GetNodeId(*entry);
2252 }
2253 private:
2254 HeapSnapshotJSONSerializer* s_;
2255 };
2256
2257 void HeapSnapshotJSONSerializer::EnumerateNodes() {
2258 GetNodeId(snapshot_->root()); // Make sure root gets the first id.
2259 HeapSnapshotJSONSerializerEnumerator iter(this);
2260 snapshot_->IterateEntries(&iter);
2261 }
2262
2263
2264 int HeapSnapshotJSONSerializer::GetNodeId(HeapEntry* entry) {
2265 HashMap::Entry* cache_entry = nodes_.Lookup(entry, ObjectHash(entry), true);
2266 if (cache_entry->value == NULL) {
2267 cache_entry->value = reinterpret_cast<void*>(next_node_id_++);
2268 }
2269 return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value));
2270 }
2271
2272
2273 int HeapSnapshotJSONSerializer::GetStringId(const char* s) {
2274 HashMap::Entry* cache_entry = strings_.Lookup(
2275 const_cast<char*>(s), ObjectHash(s), true);
2276 if (cache_entry->value == NULL) {
2277 cache_entry->value = reinterpret_cast<void*>(next_string_id_++);
2278 }
2279 return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value));
2280 }
2281
2282
2283 void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge) {
2284 writer_->AddCharacter(',');
2285 writer_->AddNumber(edge->type());
2286 writer_->AddCharacter(',');
2287 if (edge->type() == HeapGraphEdge::kElement) {
2288 writer_->AddNumber(edge->index());
2289 } else {
2290 writer_->AddNumber(GetStringId(edge->name()));
2291 }
2292 writer_->AddCharacter(',');
2293 writer_->AddNumber(GetNodeId(edge->to()));
2294 }
2295
2296
2297 void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry) {
2298 writer_->AddCharacter('\n');
2299 writer_->AddCharacter(',');
2300 writer_->AddNumber(entry->type());
2301 writer_->AddCharacter(',');
2302 writer_->AddNumber(GetStringId(entry->name()));
2303 writer_->AddCharacter(',');
2304 writer_->AddNumber(entry->id());
2305 writer_->AddCharacter(',');
2306 writer_->AddNumber(entry->self_size());
2307 Vector<HeapGraphEdge> children = entry->children();
2308 writer_->AddCharacter(',');
2309 writer_->AddNumber(children.length());
2310 for (int i = 0; i < children.length(); ++i) {
2311 SerializeEdge(&children[i]);
2312 if (writer_->aborted()) return;
2313 }
2314 }
2315
2316
2317 void HeapSnapshotJSONSerializer::SerializeNodes() {
2318 // The first (zero) item of nodes array is a JSON-ified object
2319 // describing node serialization layout.
2320 // We use a set of macros to improve readability.
2321 #define JSON_A(s) "["s"]"
2322 #define JSON_O(s) "{"s"}"
2323 #define JSON_S(s) "\\\""s"\\\""
2324 writer_->AddString("\"" JSON_O(
2325 JSON_S("fields") ":" JSON_A(
2326 JSON_S("type")
2327 "," JSON_S("name")
2328 "," JSON_S("id")
2329 "," JSON_S("self_size")
2330 "," JSON_S("children_count")
2331 "," JSON_S("children"))
2332 "," JSON_S("types") ":" JSON_A(
2333 JSON_A(
2334 JSON_S("internal")
2335 "," JSON_S("array")
2336 "," JSON_S("string")
2337 "," JSON_S("object")
2338 "," JSON_S("code")
2339 "," JSON_S("closure"))
2340 "," JSON_S("string")
2341 "," JSON_S("number")
2342 "," JSON_S("number")
2343 "," JSON_S("number")
2344 "," JSON_O(
2345 JSON_S("fields") ":" JSON_A(
2346 JSON_S("type")
2347 "," JSON_S("name_or_index")
2348 "," JSON_S("to_node"))
2349 "," JSON_S("types") ":" JSON_A(
2350 JSON_A(
2351 JSON_S("context")
2352 "," JSON_S("element")
2353 "," JSON_S("property")
2354 "," JSON_S("internal"))
2355 "," JSON_S("string_or_number")
2356 "," JSON_S("node"))))) "\"");
2357 #undef JSON_S
2358 #undef JSON_O
2359 #undef JSON_A
2360
2361 const int node_fields_count = 5; // type,name,id,self_size,children_count.
2362 const int edge_fields_count = 3; // type,name|index,to_node.
2363 List<HashMap::Entry*> sorted_nodes;
2364 SortHashMap(&nodes_, &sorted_nodes);
2365 // Rewrite node ids, so they refer to actual array positions.
2366 if (sorted_nodes.length() > 1) {
2367 // Nodes start from array index 1.
2368 int prev_value = 1;
2369 sorted_nodes[0]->value = reinterpret_cast<void*>(prev_value);
2370 for (int i = 1; i < sorted_nodes.length(); ++i) {
2371 HeapEntry* prev_heap_entry =
2372 reinterpret_cast<HeapEntry*>(sorted_nodes[i-1]->key);
2373 prev_value += node_fields_count +
2374 prev_heap_entry->children().length() * edge_fields_count;
2375 sorted_nodes[i]->value = reinterpret_cast<void*>(prev_value);
2376 }
2377 }
2378 for (int i = 0; i < sorted_nodes.length(); ++i) {
2379 SerializeNode(reinterpret_cast<HeapEntry*>(sorted_nodes[i]->key));
2380 if (writer_->aborted()) return;
2381 }
2382 }
2383
2384
2385 void HeapSnapshotJSONSerializer::SerializeSnapshot() {
2386 writer_->AddString("\"title\":\"");
2387 writer_->AddString(snapshot_->title());
2388 writer_->AddString("\"");
2389 writer_->AddString(",\"uid\":");
2390 writer_->AddNumber(snapshot_->uid());
2391 }
2392
2393
2394 static void WriteUChar(OutputStreamWriter* w, unibrow::uchar u) {
2395 static const char hex_chars[] = "0123456789ABCDEF";
2396 w->AddString("\\u");
2397 w->AddCharacter(hex_chars[(u >> 12) & 0xf]);
2398 w->AddCharacter(hex_chars[(u >> 8) & 0xf]);
2399 w->AddCharacter(hex_chars[(u >> 4) & 0xf]);
2400 w->AddCharacter(hex_chars[u & 0xf]);
2401 }
2402
2403 void HeapSnapshotJSONSerializer::SerializeString(const unsigned char* s) {
2404 writer_->AddCharacter('\n');
2405 writer_->AddCharacter('\"');
2406 for ( ; *s != '\0'; ++s) {
2407 switch (*s) {
2408 case '\b':
2409 writer_->AddString("\\b");
2410 continue;
2411 case '\f':
2412 writer_->AddString("\\f");
2413 continue;
2414 case '\n':
2415 writer_->AddString("\\n");
2416 continue;
2417 case '\r':
2418 writer_->AddString("\\r");
2419 continue;
2420 case '\t':
2421 writer_->AddString("\\t");
2422 continue;
2423 case '\"':
2424 case '\\':
2425 writer_->AddCharacter('\\');
2426 writer_->AddCharacter(*s);
2427 continue;
2428 default:
2429 if (*s > 31 && *s < 128) {
2430 writer_->AddCharacter(*s);
2431 } else if (*s <= 31) {
2432 // Special character with no dedicated literal.
2433 WriteUChar(writer_, *s);
2434 } else {
2435 // Convert UTF-8 into \u UTF-16 literal.
2436 unsigned length = 1, cursor = 0;
2437 for ( ; length <= 4 && *(s + length) != '\0'; ++length) { }
2438 unibrow::uchar c = unibrow::Utf8::CalculateValue(s, length, &cursor);
2439 if (c != unibrow::Utf8::kBadChar) {
2440 WriteUChar(writer_, c);
2441 ASSERT(cursor != 0);
2442 s += cursor - 1;
2443 } else {
2444 writer_->AddCharacter('?');
2445 }
2446 }
2447 }
2448 }
2449 writer_->AddCharacter('\"');
2450 }
2451
2452
2453 void HeapSnapshotJSONSerializer::SerializeStrings() {
2454 List<HashMap::Entry*> sorted_strings;
2455 SortHashMap(&strings_, &sorted_strings);
2456 writer_->AddString("\"<dummy>\"");
2457 for (int i = 0; i < sorted_strings.length(); ++i) {
2458 writer_->AddCharacter(',');
2459 SerializeString(
2460 reinterpret_cast<const unsigned char*>(sorted_strings[i]->key));
2461 if (writer_->aborted()) return;
2462 }
2463 }
2464
2465
2466 template<typename T>
2467 inline static int SortUsingEntryValue(const T* x, const T* y) {
2468 uintptr_t x_uint = reinterpret_cast<uintptr_t>((*x)->value);
2469 uintptr_t y_uint = reinterpret_cast<uintptr_t>((*y)->value);
2470 if (x_uint > y_uint) {
2471 return 1;
2472 } else if (x_uint == y_uint) {
2473 return 0;
2474 } else {
2475 return -1;
2476 }
2477 }
2478
2479
2480 void HeapSnapshotJSONSerializer::SortHashMap(
2481 HashMap* map, List<HashMap::Entry*>* sorted_entries) {
2482 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p))
2483 sorted_entries->Add(p);
2484 sorted_entries->Sort(SortUsingEntryValue);
2485 }
2486
2135 } } // namespace v8::internal 2487 } } // namespace v8::internal
2136 2488
2137 #endif // ENABLE_LOGGING_AND_PROFILING 2489 #endif // ENABLE_LOGGING_AND_PROFILING
OLDNEW
« no previous file with comments | « src/profile-generator.h ('k') | src/runtime.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698