heap-snapshot-generator.cc revision f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3
1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2013 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/profiler/heap-snapshot-generator.h" 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-stubs.h" 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/conversions.h" 9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/debug/debug.h" 10014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/objects-body-descriptors.h" 11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/profiler/allocation-tracker.h" 12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/profiler/heap-profiler.h" 13014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/profiler/heap-snapshot-generator-inl.h" 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 { 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal { 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapGraphEdge::HeapGraphEdge(Type type, const char* name, int from, int to) 20958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier : bit_field_(TypeField::encode(type) | FromIndexField::encode(from)), 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch to_index_(to), 22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch name_(name) { 23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(type == kContextVariable 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch || type == kProperty 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch || type == kInternal 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch || type == kShortcut 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch || type == kWeak); 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapGraphEdge::HeapGraphEdge(Type type, int index, int from, int to) 32958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier : bit_field_(TypeField::encode(type) | FromIndexField::encode(from)), 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch to_index_(to), 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch index_(index) { 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(type == kElement || type == kHidden); 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapGraphEdge::ReplaceToIndexWithEntry(HeapSnapshot* snapshot) { 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch to_entry_ = &snapshot->entries()[to_index_]; 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst int HeapEntry::kNoEntry = -1; 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapEntry::HeapEntry(HeapSnapshot* snapshot, 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Type type, 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* name, 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SnapshotObjectId id, 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch size_t self_size, 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned trace_node_id) 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : type_(type), 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch children_count_(0), 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch children_index_(-1), 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch self_size_(self_size), 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch snapshot_(snapshot), 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch name_(name), 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch id_(id), 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch trace_node_id_(trace_node_id) { } 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapEntry::SetNamedReference(HeapGraphEdge::Type type, 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* name, 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* entry) { 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapGraphEdge edge(type, name, this->index(), entry->index()); 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch snapshot_->edges().Add(edge); 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++children_count_; 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapEntry::SetIndexedReference(HeapGraphEdge::Type type, 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int index, 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* entry) { 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapGraphEdge edge(type, index, this->index(), entry->index()); 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch snapshot_->edges().Add(edge); 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++children_count_; 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapEntry::Print( 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* prefix, const char* edge_name, int max_depth, int indent) { 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(sizeof(unsigned) == sizeof(id())); 8313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch base::OS::Print("%6" PRIuS " @%6u %*c %s%s: ", self_size(), id(), indent, ' ', 8413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch prefix, edge_name); 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (type() != kString) { 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch base::OS::Print("%s %.40s\n", TypeAsString(), name_); 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch base::OS::Print("\""); 89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* c = name_; 90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while (*c && (c - name_) <= 40) { 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (*c != '\n') 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch base::OS::Print("%c", *c); 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch else 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch base::OS::Print("\\n"); 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++c; 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch base::OS::Print("\"\n"); 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (--max_depth == 0) return; 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Vector<HeapGraphEdge*> ch = children(); 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < ch.length(); ++i) { 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapGraphEdge& edge = *ch[i]; 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* edge_prefix = ""; 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmbeddedVector<char, 64> index; 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* edge_name = index.start(); 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (edge.type()) { 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case HeapGraphEdge::kContextVariable: 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch edge_prefix = "#"; 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch edge_name = edge.name(); 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case HeapGraphEdge::kElement: 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SNPrintF(index, "%d", edge.index()); 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case HeapGraphEdge::kInternal: 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch edge_prefix = "$"; 116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch edge_name = edge.name(); 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case HeapGraphEdge::kProperty: 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch edge_name = edge.name(); 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case HeapGraphEdge::kHidden: 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch edge_prefix = "$"; 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SNPrintF(index, "%d", edge.index()); 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case HeapGraphEdge::kShortcut: 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch edge_prefix = "^"; 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch edge_name = edge.name(); 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case HeapGraphEdge::kWeak: 130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch edge_prefix = "w"; 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch edge_name = edge.name(); 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SNPrintF(index, "!!! unknown edge type: %d ", edge.type()); 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch edge.to()->Print(edge_prefix, edge_name, max_depth, indent + 2); 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst char* HeapEntry::TypeAsString() { 142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (type()) { 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kHidden: return "/hidden/"; 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kObject: return "/object/"; 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kClosure: return "/closure/"; 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kString: return "/string/"; 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kCode: return "/code/"; 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kArray: return "/array/"; 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kRegExp: return "/regexp/"; 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kHeapNumber: return "/number/"; 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kNative: return "/native/"; 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kSynthetic: return "/synthetic/"; 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kConsString: return "/concatenated string/"; 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kSlicedString: return "/sliced string/"; 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kSymbol: return "/symbol/"; 156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case kSimdValue: return "/simd/"; 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: return "???"; 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// It is very important to keep objects that form a heap snapshot 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// as small as possible. 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace { // Avoid littering the global namespace. 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <size_t ptr_size> struct SnapshotSizeConstants; 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <> struct SnapshotSizeConstants<4> { 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kExpectedHeapGraphEdgeSize = 12; 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kExpectedHeapEntrySize = 28; 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <> struct SnapshotSizeConstants<8> { 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kExpectedHeapGraphEdgeSize = 24; 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kExpectedHeapEntrySize = 40; 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} // namespace 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochHeapSnapshot::HeapSnapshot(HeapProfiler* profiler) 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : profiler_(profiler), 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch root_index_(HeapEntry::kNoEntry), 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch gc_roots_index_(HeapEntry::kNoEntry), 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch max_snapshot_js_object_id_(0) { 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT( 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sizeof(HeapGraphEdge) == 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SnapshotSizeConstants<kPointerSize>::kExpectedHeapGraphEdgeSize); 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT( 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sizeof(HeapEntry) == 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SnapshotSizeConstants<kPointerSize>::kExpectedHeapEntrySize); 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch USE(SnapshotSizeConstants<4>::kExpectedHeapGraphEdgeSize); 193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch USE(SnapshotSizeConstants<4>::kExpectedHeapEntrySize); 194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch USE(SnapshotSizeConstants<8>::kExpectedHeapGraphEdgeSize); 195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch USE(SnapshotSizeConstants<8>::kExpectedHeapEntrySize); 196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < VisitorSynchronization::kNumberOfSyncTags; ++i) { 197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch gc_subroot_indexes_[i] = HeapEntry::kNoEntry; 198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshot::Delete() { 203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch profiler_->RemoveSnapshot(this); 204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch delete this; 205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshot::RememberLastJSObjectId() { 209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch max_snapshot_js_object_id_ = profiler_->heap_object_map()->last_assigned_id(); 210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshot::AddSyntheticRootEntries() { 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AddRootEntry(); 215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AddGcRootsEntry(); 216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SnapshotObjectId id = HeapObjectsMap::kGcRootsFirstSubrootId; 217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int tag = 0; tag < VisitorSynchronization::kNumberOfSyncTags; tag++) { 218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AddGcSubrootEntry(tag, id); 219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch id += HeapObjectsMap::kObjectIdStep; 220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(HeapObjectsMap::kFirstAvailableObjectId == id); 222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapEntry* HeapSnapshot::AddRootEntry() { 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(root_index_ == HeapEntry::kNoEntry); 227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(entries_.is_empty()); // Root entry must be the first one. 228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* entry = AddEntry(HeapEntry::kSynthetic, 229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "", 230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObjectsMap::kInternalRootObjectId, 231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 0, 232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 0); 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch root_index_ = entry->index(); 234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(root_index_ == 0); 235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return entry; 236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapEntry* HeapSnapshot::AddGcRootsEntry() { 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(gc_roots_index_ == HeapEntry::kNoEntry); 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* entry = AddEntry(HeapEntry::kSynthetic, 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "(GC roots)", 243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObjectsMap::kGcRootsObjectId, 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 0, 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 0); 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch gc_roots_index_ = entry->index(); 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return entry; 248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapEntry* HeapSnapshot::AddGcSubrootEntry(int tag, SnapshotObjectId id) { 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(gc_subroot_indexes_[tag] == HeapEntry::kNoEntry); 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(0 <= tag && tag < VisitorSynchronization::kNumberOfSyncTags); 254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* entry = AddEntry(HeapEntry::kSynthetic, 255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitorSynchronization::kTagNames[tag], id, 0, 0); 256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch gc_subroot_indexes_[tag] = entry->index(); 257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return entry; 258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type, 262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* name, 263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SnapshotObjectId id, 264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch size_t size, 265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned trace_node_id) { 266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry entry(this, type, name, id, size, trace_node_id); 267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_.Add(entry); 268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return &entries_.last(); 269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshot::FillChildren() { 273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(children().is_empty()); 274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch children().Allocate(edges().length()); 275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int children_index = 0; 276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < entries().length(); ++i) { 277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* entry = &entries()[i]; 278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch children_index = entry->set_children_index(children_index); 279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(edges().length() == children_index); 281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < edges().length(); ++i) { 282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapGraphEdge* edge = &edges()[i]; 283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch edge->ReplaceToIndexWithEntry(this); 284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch edge->from()->add_child(edge); 285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass FindEntryById { 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit FindEntryById(SnapshotObjectId id) : id_(id) { } 292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int operator()(HeapEntry* const* entry) { 293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((*entry)->id() == id_) return 0; 294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return (*entry)->id() < id_ ? -1 : 1; 295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SnapshotObjectId id_; 298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapEntry* HeapSnapshot::GetEntryById(SnapshotObjectId id) { 302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch List<HeapEntry*>* entries_by_id = GetSortedEntriesList(); 303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Perform a binary search by id. 304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int index = SortedListBSearch(*entries_by_id, FindEntryById(id)); 305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (index == -1) 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return NULL; 307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return entries_by_id->at(index); 308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<class T> 312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic int SortByIds(const T* entry1_ptr, 313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const T* entry2_ptr) { 314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((*entry1_ptr)->id() == (*entry2_ptr)->id()) return 0; 315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return (*entry1_ptr)->id() < (*entry2_ptr)->id() ? -1 : 1; 316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochList<HeapEntry*>* HeapSnapshot::GetSortedEntriesList() { 320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (sorted_entries_.is_empty()) { 321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sorted_entries_.Allocate(entries_.length()); 322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < entries_.length(); ++i) { 323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sorted_entries_[i] = &entries_[i]; 324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 325014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch sorted_entries_.Sort<int (*)(HeapEntry* const*, HeapEntry* const*)>( 326014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SortByIds); 327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return &sorted_entries_; 329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshot::Print(int max_depth) { 333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch root()->Print("", "", max_depth, 0); 334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochsize_t HeapSnapshot::RawSnapshotSize() const { 338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sizeof(*this) + 340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GetMemoryUsedByList(entries_) + 341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GetMemoryUsedByList(edges_) + 342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GetMemoryUsedByList(children_) + 343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GetMemoryUsedByList(sorted_entries_); 344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// We split IDs on evens for embedder objects (see 348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// HeapObjectsMap::GenerateId) and odds for native objects. 349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst SnapshotObjectId HeapObjectsMap::kInternalRootObjectId = 1; 350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst SnapshotObjectId HeapObjectsMap::kGcRootsObjectId = 351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObjectsMap::kInternalRootObjectId + HeapObjectsMap::kObjectIdStep; 352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst SnapshotObjectId HeapObjectsMap::kGcRootsFirstSubrootId = 353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObjectsMap::kGcRootsObjectId + HeapObjectsMap::kObjectIdStep; 354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst SnapshotObjectId HeapObjectsMap::kFirstAvailableObjectId = 355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObjectsMap::kGcRootsFirstSubrootId + 356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitorSynchronization::kNumberOfSyncTags * HeapObjectsMap::kObjectIdStep; 357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapObjectsMap::HeapObjectsMap(Heap* heap) 359f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch : next_id_(kFirstAvailableObjectId), heap_(heap) { 360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This dummy element solves a problem with entries_map_. 361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // When we do lookup in HashMap we see no difference between two cases: 362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // it has an entry with NULL as the value or it has created 363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // a new entry on the fly with NULL as the default value. 364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // With such dummy element we have a guaranty that all entries_map_ entries 365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // will have the value field grater than 0. 366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This fact is using in MoveObject method. 367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_.Add(EntryInfo(0, NULL, 0)); 368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool HeapObjectsMap::MoveObject(Address from, Address to, int object_size) { 372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(to != NULL); 373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(from != NULL); 374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (from == to) return false; 375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void* from_value = entries_map_.Remove(from, ComputePointerHash(from)); 376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (from_value == NULL) { 377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // It may occur that some untracked object moves to an address X and there 378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is a tracked object at that address. In this case we should remove the 379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // entry as we know that the object has died. 380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void* to_value = entries_map_.Remove(to, ComputePointerHash(to)); 381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (to_value != NULL) { 382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int to_entry_info_index = 383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<int>(reinterpret_cast<intptr_t>(to_value)); 384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_.at(to_entry_info_index).addr = NULL; 385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 38713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch base::HashMap::Entry* to_entry = 388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch entries_map_.LookupOrInsert(to, ComputePointerHash(to)); 389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (to_entry->value != NULL) { 390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We found the existing entry with to address for an old object. 391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Without this operation we will have two EntryInfo's with the same 392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // value in addr field. It is bad because later at RemoveDeadEntries 393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // one of this entry will be removed with the corresponding entries_map_ 394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // entry. 395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int to_entry_info_index = 396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<int>(reinterpret_cast<intptr_t>(to_entry->value)); 397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_.at(to_entry_info_index).addr = NULL; 398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int from_entry_info_index = 400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<int>(reinterpret_cast<intptr_t>(from_value)); 401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_.at(from_entry_info_index).addr = to; 402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Size of an object can change during its life, so to keep information 403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // about the object in entries_ consistent, we have to adjust size when the 404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // object is migrated. 405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_heap_profiler_trace_objects) { 406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrintF("Move object from %p to %p old size %6d new size %6d\n", 40713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch static_cast<void*>(from), static_cast<void*>(to), 40813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch entries_.at(from_entry_info_index).size, object_size); 409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_.at(from_entry_info_index).size = object_size; 411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch to_entry->value = from_value; 412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return from_value != NULL; 414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapObjectsMap::UpdateObjectSize(Address addr, int size) { 418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FindOrAddEntry(addr, size, false); 419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochSnapshotObjectId HeapObjectsMap::FindEntry(Address addr) { 42313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch base::HashMap::Entry* entry = 42413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch entries_map_.Lookup(addr, ComputePointerHash(addr)); 425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (entry == NULL) return 0; 426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int entry_index = static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); 427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EntryInfo& entry_info = entries_.at(entry_index); 428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy()); 429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return entry_info.id; 430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochSnapshotObjectId HeapObjectsMap::FindOrAddEntry(Address addr, 434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned int size, 435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool accessed) { 436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy()); 43713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch base::HashMap::Entry* entry = 438014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch entries_map_.LookupOrInsert(addr, ComputePointerHash(addr)); 439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (entry->value != NULL) { 440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int entry_index = 441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); 442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EntryInfo& entry_info = entries_.at(entry_index); 443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entry_info.accessed = accessed; 444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_heap_profiler_trace_objects) { 445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrintF("Update object size : %p with old size %d and new size %d\n", 44613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch static_cast<void*>(addr), entry_info.size, size); 447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entry_info.size = size; 449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return entry_info.id; 450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entry->value = reinterpret_cast<void*>(entries_.length()); 452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SnapshotObjectId id = next_id_; 453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch next_id_ += kObjectIdStep; 454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_.Add(EntryInfo(id, addr, size, accessed)); 455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy()); 456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return id; 457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapObjectsMap::StopHeapObjectsTracking() { 461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch time_intervals_.Clear(); 462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapObjectsMap::UpdateHeapObjectsMap() { 466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_heap_profiler_trace_objects) { 467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrintF("Begin HeapObjectsMap::UpdateHeapObjectsMap. map has %d entries.\n", 468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_map_.occupancy()); 469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap_->CollectAllGarbage(Heap::kMakeHeapIterableMask, 471f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GarbageCollectionReason::kHeapProfiler); 472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapIterator iterator(heap_); 473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (HeapObject* obj = iterator.next(); 474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch obj != NULL; 475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch obj = iterator.next()) { 476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FindOrAddEntry(obj->address(), obj->Size()); 477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_heap_profiler_trace_objects) { 478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrintF("Update object : %p %6d. Next address is %p\n", 47913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch static_cast<void*>(obj->address()), obj->Size(), 48013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch static_cast<void*>(obj->address() + obj->Size())); 481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RemoveDeadEntries(); 484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_heap_profiler_trace_objects) { 485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrintF("End HeapObjectsMap::UpdateHeapObjectsMap. map has %d entries.\n", 486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_map_.occupancy()); 487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace { 492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstruct HeapObjectInfo { 495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObjectInfo(HeapObject* obj, int expected_size) 496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : obj(obj), 497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch expected_size(expected_size) { 498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObject* obj; 501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int expected_size; 502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool IsValid() const { return expected_size == obj->Size(); } 504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Print() const { 506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expected_size == 0) { 507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrintF("Untracked object : %p %6d. Next address is %p\n", 50813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch static_cast<void*>(obj->address()), obj->Size(), 50913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch static_cast<void*>(obj->address() + obj->Size())); 510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->Size() != expected_size) { 51113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch PrintF("Wrong size %6d: %p %6d. Next address is %p\n", expected_size, 51213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch static_cast<void*>(obj->address()), obj->Size(), 51313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch static_cast<void*>(obj->address() + obj->Size())); 514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrintF("Good object : %p %6d. Next address is %p\n", 51613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch static_cast<void*>(obj->address()), expected_size, 51713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch static_cast<void*>(obj->address() + obj->Size())); 518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic int comparator(const HeapObjectInfo* a, const HeapObjectInfo* b) { 524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (a->obj < b->obj) return -1; 525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (a->obj > b->obj) return 1; 526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 0; 527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} // namespace 531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint HeapObjectsMap::FindUntrackedObjects() { 534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch List<HeapObjectInfo> heap_objects(1000); 535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapIterator iterator(heap_); 537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int untracked = 0; 538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (HeapObject* obj = iterator.next(); 539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch obj != NULL; 540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch obj = iterator.next()) { 54113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch base::HashMap::Entry* entry = 542014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch entries_map_.Lookup(obj->address(), ComputePointerHash(obj->address())); 543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (entry == NULL) { 544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++untracked; 545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_heap_profiler_trace_objects) { 546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap_objects.Add(HeapObjectInfo(obj, 0)); 547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int entry_index = static_cast<int>( 550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<intptr_t>(entry->value)); 551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EntryInfo& entry_info = entries_.at(entry_index); 552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_heap_profiler_trace_objects) { 553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap_objects.Add(HeapObjectInfo(obj, 554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<int>(entry_info.size))); 555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (obj->Size() != static_cast<int>(entry_info.size)) 556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++untracked; 557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK_EQ(obj->Size(), static_cast<int>(entry_info.size)); 559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_heap_profiler_trace_objects) { 563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrintF("\nBegin HeapObjectsMap::FindUntrackedObjects. %d entries in map.\n", 564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_map_.occupancy()); 565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap_objects.Sort(comparator); 566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int last_printed_object = -1; 567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool print_next_object = false; 568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < heap_objects.length(); ++i) { 569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const HeapObjectInfo& object_info = heap_objects[i]; 570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!object_info.IsValid()) { 571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++untracked; 572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (last_printed_object != i - 1) { 573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (i > 0) { 574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrintF("%d objects were skipped\n", i - 1 - last_printed_object); 575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap_objects[i - 1].Print(); 576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch object_info.Print(); 579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch last_printed_object = i; 580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch print_next_object = true; 581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (print_next_object) { 582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch object_info.Print(); 583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch print_next_object = false; 584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch last_printed_object = i; 585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (last_printed_object < heap_objects.length() - 1) { 588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrintF("Last %d objects were skipped\n", 589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap_objects.length() - 1 - last_printed_object); 590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrintF("End HeapObjectsMap::FindUntrackedObjects. %d entries in map.\n\n", 592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_map_.occupancy()); 593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return untracked; 595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 598014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochSnapshotObjectId HeapObjectsMap::PushHeapObjectsStats(OutputStream* stream, 599014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int64_t* timestamp_us) { 600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UpdateHeapObjectsMap(); 601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch time_intervals_.Add(TimeInterval(next_id_)); 602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int prefered_chunk_size = stream->GetChunkSize(); 603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch List<v8::HeapStatsUpdate> stats_buffer; 604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!entries_.is_empty()); 605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EntryInfo* entry_info = &entries_.first(); 606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EntryInfo* end_entry_info = &entries_.last() + 1; 607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int time_interval_index = 0; 608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch time_interval_index < time_intervals_.length(); 609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++time_interval_index) { 610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TimeInterval& time_interval = time_intervals_[time_interval_index]; 611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SnapshotObjectId time_interval_id = time_interval.id; 612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t entries_size = 0; 613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EntryInfo* start_entry_info = entry_info; 614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while (entry_info < end_entry_info && entry_info->id < time_interval_id) { 615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_size += entry_info->size; 616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++entry_info; 617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t entries_count = 619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<uint32_t>(entry_info - start_entry_info); 620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (time_interval.count != entries_count || 621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch time_interval.size != entries_size) { 622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stats_buffer.Add(v8::HeapStatsUpdate( 623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch time_interval_index, 624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch time_interval.count = entries_count, 625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch time_interval.size = entries_size)); 626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (stats_buffer.length() >= prefered_chunk_size) { 627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OutputStream::WriteResult result = stream->WriteHeapStatsChunk( 628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &stats_buffer.first(), stats_buffer.length()); 629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (result == OutputStream::kAbort) return last_assigned_id(); 630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stats_buffer.Clear(); 631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(entry_info == end_entry_info); 635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!stats_buffer.is_empty()) { 636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OutputStream::WriteResult result = stream->WriteHeapStatsChunk( 637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &stats_buffer.first(), stats_buffer.length()); 638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (result == OutputStream::kAbort) return last_assigned_id(); 639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stream->EndOfStream(); 641014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (timestamp_us) { 642014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch *timestamp_us = (time_intervals_.last().timestamp - 643014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch time_intervals_[0].timestamp).InMicroseconds(); 644014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return last_assigned_id(); 646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapObjectsMap::RemoveDeadEntries() { 650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(entries_.length() > 0 && 651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_.at(0).id == 0 && 652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_.at(0).addr == NULL); 653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int first_free_entry = 1; 654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 1; i < entries_.length(); ++i) { 655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EntryInfo& entry_info = entries_.at(i); 656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (entry_info.accessed) { 657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (first_free_entry != i) { 658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_.at(first_free_entry) = entry_info; 659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_.at(first_free_entry).accessed = false; 66113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch base::HashMap::Entry* entry = entries_map_.Lookup( 662014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch entry_info.addr, ComputePointerHash(entry_info.addr)); 663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(entry); 664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entry->value = reinterpret_cast<void*>(first_free_entry); 665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++first_free_entry; 666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (entry_info.addr) { 668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_map_.Remove(entry_info.addr, 669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ComputePointerHash(entry_info.addr)); 670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_.Rewind(first_free_entry); 674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(static_cast<uint32_t>(entries_.length()) - 1 == 675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_map_.occupancy()); 676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochSnapshotObjectId HeapObjectsMap::GenerateId(v8::RetainedObjectInfo* info) { 680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SnapshotObjectId id = static_cast<SnapshotObjectId>(info->GetHash()); 681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* label = info->GetLabel(); 682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch id ^= StringHasher::HashSequentialString(label, 683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<int>(strlen(label)), 684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap_->HashSeed()); 685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch intptr_t element_count = info->GetElementCount(); 686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (element_count != -1) 687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch id ^= ComputeIntegerHash(static_cast<uint32_t>(element_count), 688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::internal::kZeroHashSeed); 689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return id << 1; 690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochsize_t HeapObjectsMap::GetUsedMemorySize() const { 69413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return sizeof(*this) + 69513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch sizeof(base::HashMap::Entry) * entries_map_.capacity() + 69613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch GetMemoryUsedByList(entries_) + GetMemoryUsedByList(time_intervals_); 697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 699f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochHeapEntriesMap::HeapEntriesMap() : entries_() {} 700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint HeapEntriesMap::Map(HeapThing thing) { 70213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch base::HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing)); 703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (cache_entry == NULL) return HeapEntry::kNoEntry; 704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); 705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapEntriesMap::Pair(HeapThing thing, int entry) { 70913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch base::HashMap::Entry* cache_entry = 71013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch entries_.LookupOrInsert(thing, Hash(thing)); 711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(cache_entry->value == NULL); 712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cache_entry->value = reinterpret_cast<void*>(static_cast<intptr_t>(entry)); 713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 715f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochHeapObjectsSet::HeapObjectsSet() : entries_() {} 716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapObjectsSet::Clear() { 718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_.Clear(); 719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool HeapObjectsSet::Contains(Object* obj) { 723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!obj->IsHeapObject()) return false; 724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObject* object = HeapObject::cast(obj); 725014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return entries_.Lookup(object, HeapEntriesMap::Hash(object)) != NULL; 726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapObjectsSet::Insert(Object* obj) { 730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!obj->IsHeapObject()) return; 731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObject* object = HeapObject::cast(obj); 732014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch entries_.LookupOrInsert(object, HeapEntriesMap::Hash(object)); 733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst char* HeapObjectsSet::GetTag(Object* obj) { 737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObject* object = HeapObject::cast(obj); 73813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch base::HashMap::Entry* cache_entry = 739014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch entries_.Lookup(object, HeapEntriesMap::Hash(object)); 740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return cache_entry != NULL 741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? reinterpret_cast<const char*>(cache_entry->value) 742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : NULL; 743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 746f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochV8_NOINLINE void HeapObjectsSet::SetTag(Object* obj, const char* tag) { 747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!obj->IsHeapObject()) return; 748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObject* object = HeapObject::cast(obj); 74913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch base::HashMap::Entry* cache_entry = 750014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch entries_.LookupOrInsert(object, HeapEntriesMap::Hash(object)); 751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cache_entry->value = const_cast<char*>(tag); 752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochV8HeapExplorer::V8HeapExplorer( 756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapSnapshot* snapshot, 757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SnapshottingProgressReportingInterface* progress, 758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::HeapProfiler::ObjectNameResolver* resolver) 759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : heap_(snapshot->profiler()->heap_object_map()->heap()), 760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch snapshot_(snapshot), 761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch names_(snapshot_->profiler()->names()), 762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap_object_map_(snapshot_->profiler()->heap_object_map()), 763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch progress_(progress), 764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_(NULL), 765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch global_object_name_resolver_(resolver) { 766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochV8HeapExplorer::~V8HeapExplorer() { 770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapEntry* V8HeapExplorer::AllocateEntry(HeapThing ptr) { 774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return AddEntry(reinterpret_cast<HeapObject*>(ptr)); 775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapEntry* V8HeapExplorer::AddEntry(HeapObject* object) { 779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (object->IsJSFunction()) { 780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSFunction* func = JSFunction::cast(object); 781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SharedFunctionInfo* shared = func->shared(); 782014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const char* name = names_->GetName(String::cast(shared->name())); 783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return AddEntry(object, HeapEntry::kClosure, name); 784014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else if (object->IsJSBoundFunction()) { 785014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return AddEntry(object, HeapEntry::kClosure, "native_bind"); 786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (object->IsJSRegExp()) { 787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSRegExp* re = JSRegExp::cast(object); 788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return AddEntry(object, 789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry::kRegExp, 790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch names_->GetName(re->Pattern())); 791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (object->IsJSObject()) { 792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* name = names_->GetName( 793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GetConstructorName(JSObject::cast(object))); 794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (object->IsJSGlobalObject()) { 795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* tag = objects_tags_.GetTag(object); 796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (tag != NULL) { 797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch name = names_->GetFormatted("%s / %s", name, tag); 798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return AddEntry(object, HeapEntry::kObject, name); 801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (object->IsString()) { 802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch String* string = String::cast(object); 803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (string->IsConsString()) 804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return AddEntry(object, 805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry::kConsString, 806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "(concatenated string)"); 807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (string->IsSlicedString()) 808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return AddEntry(object, 809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry::kSlicedString, 810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "(sliced string)"); 811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return AddEntry(object, 812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry::kString, 813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch names_->GetName(String::cast(object))); 814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (object->IsSymbol()) { 815014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (Symbol::cast(object)->is_private()) 816014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return AddEntry(object, HeapEntry::kHidden, "private symbol"); 817014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch else 818014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return AddEntry(object, HeapEntry::kSymbol, "symbol"); 819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (object->IsCode()) { 820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return AddEntry(object, HeapEntry::kCode, ""); 821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (object->IsSharedFunctionInfo()) { 822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch String* name = String::cast(SharedFunctionInfo::cast(object)->name()); 823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return AddEntry(object, 824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry::kCode, 825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch names_->GetName(name)); 826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (object->IsScript()) { 827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object* name = Script::cast(object)->name(); 828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return AddEntry(object, 829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry::kCode, 830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch name->IsString() 831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? names_->GetName(String::cast(name)) 832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : ""); 833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (object->IsNativeContext()) { 834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return AddEntry(object, HeapEntry::kHidden, "system / NativeContext"); 835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (object->IsContext()) { 836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return AddEntry(object, HeapEntry::kObject, "system / Context"); 837014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else if (object->IsFixedArray() || object->IsFixedDoubleArray() || 838014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch object->IsByteArray()) { 839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return AddEntry(object, HeapEntry::kArray, ""); 840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (object->IsHeapNumber()) { 841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return AddEntry(object, HeapEntry::kHeapNumber, "number"); 842014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else if (object->IsSimd128Value()) { 843014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return AddEntry(object, HeapEntry::kSimdValue, "simd"); 844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return AddEntry(object, HeapEntry::kHidden, GetSystemEntryName(object)); 846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapEntry* V8HeapExplorer::AddEntry(HeapObject* object, 850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry::Type type, 851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* name) { 852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return AddEntry(object->address(), type, name, object->Size()); 853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapEntry* V8HeapExplorer::AddEntry(Address address, 857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry::Type type, 858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* name, 859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch size_t size) { 860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SnapshotObjectId object_id = heap_object_map_->FindOrAddEntry( 861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch address, static_cast<unsigned int>(size)); 862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned trace_node_id = 0; 863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (AllocationTracker* allocation_tracker = 864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch snapshot_->profiler()->allocation_tracker()) { 865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch trace_node_id = 866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch allocation_tracker->address_to_trace()->GetTraceNodeId(address); 867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return snapshot_->AddEntry(type, name, object_id, size, trace_node_id); 869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass SnapshotFiller { 873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries) 875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : snapshot_(snapshot), 876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch names_(snapshot->profiler()->names()), 877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_(entries) { } 878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) { 879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* entry = allocator->AllocateEntry(ptr); 880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_->Pair(ptr, entry->index()); 881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return entry; 882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* FindEntry(HeapThing ptr) { 884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int index = entries_->Map(ptr); 885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return index != HeapEntry::kNoEntry ? &snapshot_->entries()[index] : NULL; 886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* FindOrAddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) { 888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* entry = FindEntry(ptr); 889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return entry != NULL ? entry : AddEntry(ptr, allocator); 890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void SetIndexedReference(HeapGraphEdge::Type type, 892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int parent, 893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int index, 894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* child_entry) { 895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* parent_entry = &snapshot_->entries()[parent]; 896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch parent_entry->SetIndexedReference(type, index, child_entry); 897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void SetIndexedAutoIndexReference(HeapGraphEdge::Type type, 899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int parent, 900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* child_entry) { 901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* parent_entry = &snapshot_->entries()[parent]; 902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int index = parent_entry->children_count() + 1; 903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch parent_entry->SetIndexedReference(type, index, child_entry); 904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void SetNamedReference(HeapGraphEdge::Type type, 906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int parent, 907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* reference_name, 908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* child_entry) { 909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* parent_entry = &snapshot_->entries()[parent]; 910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch parent_entry->SetNamedReference(type, reference_name, child_entry); 911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void SetNamedAutoIndexReference(HeapGraphEdge::Type type, 913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int parent, 914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* child_entry) { 915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* parent_entry = &snapshot_->entries()[parent]; 916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int index = parent_entry->children_count() + 1; 917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch parent_entry->SetNamedReference( 918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch type, 919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch names_->GetName(index), 920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch child_entry); 921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapSnapshot* snapshot_; 925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StringsStorage* names_; 926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntriesMap* entries_; 927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst char* V8HeapExplorer::GetSystemEntryName(HeapObject* object) { 931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (object->map()->instance_type()) { 932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case MAP_TYPE: 933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (Map::cast(object)->instance_type()) { 934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define MAKE_STRING_MAP_CASE(instance_type, size, name, Name) \ 935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case instance_type: return "system / Map (" #Name ")"; 936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STRING_TYPE_LIST(MAKE_STRING_MAP_CASE) 937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef MAKE_STRING_MAP_CASE 938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: return "system / Map"; 939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case CELL_TYPE: return "system / Cell"; 941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case PROPERTY_CELL_TYPE: return "system / PropertyCell"; 942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case FOREIGN_TYPE: return "system / Foreign"; 943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case ODDBALL_TYPE: return "system / Oddball"; 944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define MAKE_STRUCT_CASE(NAME, Name, name) \ 945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case NAME##_TYPE: return "system / "#Name; 946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STRUCT_LIST(MAKE_STRUCT_CASE) 947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef MAKE_STRUCT_CASE 948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: return "system"; 949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint V8HeapExplorer::EstimateObjectsCount(HeapIterator* iterator) { 954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int objects_count = 0; 955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (HeapObject* obj = iterator->next(); 956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch obj != NULL; 957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch obj = iterator->next()) { 958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch objects_count++; 959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return objects_count; 961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass IndexedReferencesExtractor : public ObjectVisitor { 965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 966014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch IndexedReferencesExtractor(V8HeapExplorer* generator, HeapObject* parent_obj, 967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int parent) 968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : generator_(generator), 969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch parent_obj_(parent_obj), 970014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch parent_start_(HeapObject::RawField(parent_obj_, 0)), 971014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch parent_end_(HeapObject::RawField(parent_obj_, parent_obj_->Size())), 972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch parent_(parent), 973014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch next_index_(0) {} 974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void VisitCodeEntry(Address entry_address) override { 975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code* code = Code::cast(Code::GetObjectFromEntryAddress(entry_address)); 976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch generator_->SetInternalReference(parent_obj_, parent_, "code", code); 977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch generator_->TagCodeObject(code); 978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 979014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void VisitPointers(Object** start, Object** end) override { 980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (Object** p = start; p < end; p++) { 981f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch int index = static_cast<int>(p - HeapObject::RawField(parent_obj_, 0)); 982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++next_index_; 983014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // |p| could be outside of the object, e.g., while visiting RelocInfo of 984014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // code objects. 985014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (p >= parent_start_ && p < parent_end_ && generator_->marks_[index]) { 986014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch generator_->marks_[index] = false; 987014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch continue; 988014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 989f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch generator_->SetHiddenReference(parent_obj_, parent_, next_index_, *p, 990f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch index * kPointerSize); 991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch V8HeapExplorer* generator_; 996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObject* parent_obj_; 997014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Object** parent_start_; 998014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Object** parent_end_; 999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int parent_; 1000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int next_index_; 1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 1002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool V8HeapExplorer::ExtractReferencesPass1(int entry, HeapObject* obj) { 1005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (obj->IsFixedArray()) return false; // FixedArrays are processed on pass 2 1006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (obj->IsJSGlobalProxy()) { 1008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractJSGlobalProxyReferences(entry, JSGlobalProxy::cast(obj)); 1009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsJSArrayBuffer()) { 1010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractJSArrayBufferReferences(entry, JSArrayBuffer::cast(obj)); 1011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsJSObject()) { 1012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (obj->IsJSWeakSet()) { 1013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractJSWeakCollectionReferences(entry, JSWeakSet::cast(obj)); 1014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsJSWeakMap()) { 1015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractJSWeakCollectionReferences(entry, JSWeakMap::cast(obj)); 1016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsJSSet()) { 1017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractJSCollectionReferences(entry, JSSet::cast(obj)); 1018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsJSMap()) { 1019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractJSCollectionReferences(entry, JSMap::cast(obj)); 1020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractJSObjectReferences(entry, JSObject::cast(obj)); 1022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsString()) { 1023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractStringReferences(entry, String::cast(obj)); 1024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsSymbol()) { 1025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractSymbolReferences(entry, Symbol::cast(obj)); 1026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsMap()) { 1027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractMapReferences(entry, Map::cast(obj)); 1028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsSharedFunctionInfo()) { 1029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractSharedFunctionInfoReferences(entry, SharedFunctionInfo::cast(obj)); 1030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsScript()) { 1031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractScriptReferences(entry, Script::cast(obj)); 1032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsAccessorInfo()) { 1033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractAccessorInfoReferences(entry, AccessorInfo::cast(obj)); 1034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsAccessorPair()) { 1035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractAccessorPairReferences(entry, AccessorPair::cast(obj)); 1036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsCode()) { 1037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractCodeReferences(entry, Code::cast(obj)); 1038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsBox()) { 1039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractBoxReferences(entry, Box::cast(obj)); 1040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsCell()) { 1041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractCellReferences(entry, Cell::cast(obj)); 1042f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else if (obj->IsWeakCell()) { 1043f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ExtractWeakCellReferences(entry, WeakCell::cast(obj)); 1044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsPropertyCell()) { 1045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractPropertyCellReferences(entry, PropertyCell::cast(obj)); 1046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsAllocationSite()) { 1047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractAllocationSiteReferences(entry, AllocationSite::cast(obj)); 1048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return true; 1050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool V8HeapExplorer::ExtractReferencesPass2(int entry, HeapObject* obj) { 1054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!obj->IsFixedArray()) return false; 1055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (obj->IsContext()) { 1057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractContextReferences(entry, Context::cast(obj)); 1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractFixedArrayReferences(entry, FixedArray::cast(obj)); 1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return true; 1062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractJSGlobalProxyReferences( 1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int entry, JSGlobalProxy* proxy) { 1067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(proxy, entry, 1068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "native_context", proxy->native_context(), 1069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSGlobalProxy::kNativeContextOffset); 1070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractJSObjectReferences( 1074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int entry, JSObject* js_obj) { 1075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObject* obj = js_obj; 1076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractPropertyReferences(js_obj, entry); 1077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractElementReferences(js_obj, entry); 1078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractInternalReferences(js_obj, entry); 1079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrototypeIterator iter(heap_->isolate(), js_obj); 1080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetPropertyReference(obj, entry, heap_->proto_string(), iter.GetCurrent()); 1081014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (obj->IsJSBoundFunction()) { 1082014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JSBoundFunction* js_fun = JSBoundFunction::cast(obj); 1083014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TagObject(js_fun->bound_arguments(), "(bound arguments)"); 1084014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetInternalReference(js_fun, entry, "bindings", js_fun->bound_arguments(), 1085014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JSBoundFunction::kBoundArgumentsOffset); 1086f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetInternalReference(js_obj, entry, "bound_this", js_fun->bound_this(), 1087f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch JSBoundFunction::kBoundThisOffset); 1088f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetInternalReference(js_obj, entry, "bound_function", 1089f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch js_fun->bound_target_function(), 1090f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch JSBoundFunction::kBoundTargetFunctionOffset); 1091014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FixedArray* bindings = js_fun->bound_arguments(); 1092014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (int i = 0; i < bindings->length(); i++) { 1093014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const char* reference_name = names_->GetFormatted("bound_argument_%d", i); 1094014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetNativeBindReference(js_obj, entry, reference_name, bindings->get(i)); 1095014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1096014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else if (obj->IsJSFunction()) { 1097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSFunction* js_fun = JSFunction::cast(js_obj); 1098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object* proto_or_map = js_fun->prototype_or_initial_map(); 109913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (!proto_or_map->IsTheHole(heap_->isolate())) { 1100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!proto_or_map->IsMap()) { 1101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetPropertyReference( 1102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch obj, entry, 1103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap_->prototype_string(), proto_or_map, 1104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NULL, 1105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSFunction::kPrototypeOrInitialMapOffset); 1106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetPropertyReference( 1108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch obj, entry, 1109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap_->prototype_string(), js_fun->prototype()); 1110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference( 1111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch obj, entry, "initial_map", proto_or_map, 1112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSFunction::kPrototypeOrInitialMapOffset); 1113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SharedFunctionInfo* shared_info = js_fun->shared(); 1116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TagObject(js_fun->literals(), "(function literals)"); 1117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetInternalReference(js_fun, entry, "literals", js_fun->literals(), 1118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSFunction::kLiteralsOffset); 1119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(shared_info, "(shared function info)"); 1120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(js_fun, entry, 1121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "shared", shared_info, 1122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSFunction::kSharedFunctionInfoOffset); 1123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(js_fun->context(), "(context)"); 1124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(js_fun, entry, 1125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "context", js_fun->context(), 1126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSFunction::kContextOffset); 1127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Ensure no new weak references appeared in JSFunction. 1128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(JSFunction::kCodeEntryOffset == 1129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JSFunction::kNonWeakFieldsEndOffset); 1130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(JSFunction::kCodeEntryOffset + kPointerSize == 1131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JSFunction::kNextFunctionLinkOffset); 1132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(JSFunction::kNextFunctionLinkOffset + kPointerSize 1133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch == JSFunction::kSize); 1134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else if (obj->IsJSGlobalObject()) { 1135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JSGlobalObject* global_obj = JSGlobalObject::cast(obj); 1136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetInternalReference(global_obj, entry, "native_context", 1137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch global_obj->native_context(), 1138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JSGlobalObject::kNativeContextOffset); 1139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetInternalReference(global_obj, entry, "global_proxy", 1140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch global_obj->global_proxy(), 1141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JSGlobalObject::kGlobalProxyOffset); 1142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(JSGlobalObject::kSize - JSObject::kHeaderSize == 1143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2 * kPointerSize); 1144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsJSArrayBufferView()) { 1145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSArrayBufferView* view = JSArrayBufferView::cast(obj); 1146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(view, entry, "buffer", view->buffer(), 1147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSArrayBufferView::kBufferOffset); 1148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(js_obj->properties(), "(object properties)"); 1150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(obj, entry, 1151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "properties", js_obj->properties(), 1152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSObject::kPropertiesOffset); 1153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(js_obj->elements(), "(object elements)"); 1154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(obj, entry, 1155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "elements", js_obj->elements(), 1156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSObject::kElementsOffset); 1157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractStringReferences(int entry, String* string) { 1161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (string->IsConsString()) { 1162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ConsString* cs = ConsString::cast(string); 1163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(cs, entry, "first", cs->first(), 1164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ConsString::kFirstOffset); 1165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(cs, entry, "second", cs->second(), 1166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ConsString::kSecondOffset); 1167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (string->IsSlicedString()) { 1168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SlicedString* ss = SlicedString::cast(string); 1169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(ss, entry, "parent", ss->parent(), 1170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SlicedString::kParentOffset); 1171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractSymbolReferences(int entry, Symbol* symbol) { 1176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(symbol, entry, 1177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "name", symbol->name(), 1178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Symbol::kNameOffset); 1179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractJSCollectionReferences(int entry, 1183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSCollection* collection) { 1184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(collection, entry, "table", collection->table(), 1185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSCollection::kTableOffset); 1186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1188f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid V8HeapExplorer::ExtractJSWeakCollectionReferences(int entry, 1189f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch JSWeakCollection* obj) { 1190f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (obj->table()->IsHashTable()) { 1191f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ObjectHashTable* table = ObjectHashTable::cast(obj->table()); 1192f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch TagFixedArraySubType(table, JS_WEAK_COLLECTION_SUB_TYPE); 1193f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1194f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetInternalReference(obj, entry, "table", obj->table(), 1195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSWeakCollection::kTableOffset); 1196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractContextReferences(int entry, Context* context) { 1199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (context == context->declaration_context()) { 1200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ScopeInfo* scope_info = context->closure()->shared()->scope_info(); 1201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Add context allocated locals. 1202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int context_locals = scope_info->ContextLocalCount(); 1203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < context_locals; ++i) { 1204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch String* local_name = scope_info->ContextLocalName(i); 1205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int idx = Context::MIN_CONTEXT_SLOTS + i; 1206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetContextReference(context, entry, local_name, context->get(idx), 1207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Context::OffsetOfElementAt(idx)); 1208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (scope_info->HasFunctionName()) { 1210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch String* name = scope_info->FunctionName(); 1211f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch int idx = scope_info->FunctionContextSlotIndex(name); 1212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (idx >= 0) { 1213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetContextReference(context, entry, name, context->get(idx), 1214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Context::OffsetOfElementAt(idx)); 1215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define EXTRACT_CONTEXT_FIELD(index, type, name) \ 1220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (Context::index < Context::FIRST_WEAK_SLOT || \ 1221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Context::index == Context::MAP_CACHE_INDEX) { \ 1222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(context, entry, #name, context->get(Context::index), \ 1223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FixedArray::OffsetOfElementAt(Context::index)); \ 1224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { \ 1225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetWeakReference(context, entry, #name, context->get(Context::index), \ 1226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FixedArray::OffsetOfElementAt(Context::index)); \ 1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EXTRACT_CONTEXT_FIELD(CLOSURE_INDEX, JSFunction, closure); 1229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EXTRACT_CONTEXT_FIELD(PREVIOUS_INDEX, Context, previous); 1230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EXTRACT_CONTEXT_FIELD(EXTENSION_INDEX, HeapObject, extension); 1231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EXTRACT_CONTEXT_FIELD(NATIVE_CONTEXT_INDEX, Context, native_context); 1232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (context->IsNativeContext()) { 1233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(context->normalized_map_cache(), "(context norm. map cache)"); 1234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(context->embedder_data(), "(context data)"); 1235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch NATIVE_CONTEXT_FIELDS(EXTRACT_CONTEXT_FIELD) 1236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EXTRACT_CONTEXT_FIELD(OPTIMIZED_FUNCTIONS_LIST, unused, 1237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch optimized_functions_list); 1238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EXTRACT_CONTEXT_FIELD(OPTIMIZED_CODE_LIST, unused, optimized_code_list); 1239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EXTRACT_CONTEXT_FIELD(DEOPTIMIZED_CODE_LIST, unused, deoptimized_code_list); 1240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef EXTRACT_CONTEXT_FIELD 1241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(Context::OPTIMIZED_FUNCTIONS_LIST == 1242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Context::FIRST_WEAK_SLOT); 1243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(Context::NEXT_CONTEXT_LINK + 1 == 1244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Context::NATIVE_CONTEXT_SLOTS); 1245958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(Context::FIRST_WEAK_SLOT + 4 == 1246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Context::NATIVE_CONTEXT_SLOTS); 1247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractMapReferences(int entry, Map* map) { 1252014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Object* raw_transitions_or_prototype_info = map->raw_transitions(); 1253014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (TransitionArray::IsFullTransitionArray( 1254014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch raw_transitions_or_prototype_info)) { 1255014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TransitionArray* transitions = 1256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TransitionArray::cast(raw_transitions_or_prototype_info); 1257f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (map->CanTransition() && transitions->HasPrototypeTransitions()) { 1258f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch TagObject(transitions->GetPrototypeTransitions(), 1259f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "(prototype transitions)"); 1260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(transitions, "(transition array)"); 1263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetInternalReference(map, entry, "transitions", transitions, 1264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Map::kTransitionsOrPrototypeInfoOffset); 1265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else if (TransitionArray::IsSimpleTransition( 1266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch raw_transitions_or_prototype_info)) { 1267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TagObject(raw_transitions_or_prototype_info, "(transition)"); 1268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetInternalReference(map, entry, "transition", 1269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch raw_transitions_or_prototype_info, 1270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Map::kTransitionsOrPrototypeInfoOffset); 1271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else if (map->is_prototype_map()) { 1272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TagObject(raw_transitions_or_prototype_info, "prototype_info"); 1273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetInternalReference(map, entry, "prototype_info", 1274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch raw_transitions_or_prototype_info, 1275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Map::kTransitionsOrPrototypeInfoOffset); 1276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DescriptorArray* descriptors = map->instance_descriptors(); 1278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(descriptors, "(map descriptors)"); 1279f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetInternalReference(map, entry, "descriptors", descriptors, 1280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Map::kDescriptorsOffset); 1281f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetInternalReference(map, entry, "code_cache", map->code_cache(), 1282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Map::kCodeCacheOffset); 1283f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetInternalReference(map, entry, "prototype", map->prototype(), 1284f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Map::kPrototypeOffset); 1285f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#if V8_DOUBLE_FIELDS_UNBOXING 1286f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (FLAG_unbox_double_fields) { 1287f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetInternalReference(map, entry, "layout_descriptor", 1288f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch map->layout_descriptor(), 1289f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Map::kLayoutDescriptorOffset); 1290f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1291f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#endif 1292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Object* constructor_or_backpointer = map->constructor_or_backpointer(); 1293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (constructor_or_backpointer->IsMap()) { 1294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TagObject(constructor_or_backpointer, "(back pointer)"); 1295014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetInternalReference(map, entry, "back_pointer", constructor_or_backpointer, 1296014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Map::kConstructorOrBackPointerOffset); 1297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 1298014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetInternalReference(map, entry, "constructor", constructor_or_backpointer, 1299014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Map::kConstructorOrBackPointerOffset); 1300014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(map->dependent_code(), "(dependent code)"); 1302f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetInternalReference(map, entry, "dependent_code", map->dependent_code(), 1303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Map::kDependentCodeOffset); 1304f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch TagObject(map->weak_cell_cache(), "(weak cell)"); 1305f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetInternalReference(map, entry, "weak_cell_cache", map->weak_cell_cache(), 1306f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Map::kWeakCellCacheOffset); 1307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractSharedFunctionInfoReferences( 1311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int entry, SharedFunctionInfo* shared) { 1312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObject* obj = shared; 1313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch String* shared_name = shared->DebugName(); 1314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* name = NULL; 1315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (shared_name != *heap_->isolate()->factory()->empty_string()) { 1316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch name = names_->GetName(shared_name); 1317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(shared->code(), names_->GetFormatted("(code for %s)", name)); 1318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(shared->code(), names_->GetFormatted("(%s code)", 1320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code::Kind2String(shared->code()->kind()))); 1321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(obj, entry, 1324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "name", shared->name(), 1325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SharedFunctionInfo::kNameOffset); 1326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(obj, entry, 1327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "code", shared->code(), 1328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SharedFunctionInfo::kCodeOffset); 1329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(shared->scope_info(), "(function scope info)"); 1330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(obj, entry, 1331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "scope_info", shared->scope_info(), 1332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SharedFunctionInfo::kScopeInfoOffset); 1333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(obj, entry, 1334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "instance_class_name", shared->instance_class_name(), 1335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SharedFunctionInfo::kInstanceClassNameOffset); 1336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(obj, entry, 1337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "script", shared->script(), 1338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SharedFunctionInfo::kScriptOffset); 1339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* construct_stub_name = name ? 1340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch names_->GetFormatted("(construct stub code for %s)", name) : 1341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "(construct stub code)"; 1342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(shared->construct_stub(), construct_stub_name); 1343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(obj, entry, 1344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "construct_stub", shared->construct_stub(), 1345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SharedFunctionInfo::kConstructStubOffset); 1346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(obj, entry, 1347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "function_data", shared->function_data(), 1348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SharedFunctionInfo::kFunctionDataOffset); 1349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(obj, entry, 1350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "debug_info", shared->debug_info(), 1351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SharedFunctionInfo::kDebugInfoOffset); 13523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch SetInternalReference(obj, entry, "function_identifier", 13533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch shared->function_identifier(), 13543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch SharedFunctionInfo::kFunctionIdentifierOffset); 1355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(obj, entry, 1356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "optimized_code_map", shared->optimized_code_map(), 1357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SharedFunctionInfo::kOptimizedCodeMapOffset); 135813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch SetInternalReference(obj, entry, "feedback_metadata", 135913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch shared->feedback_metadata(), 136013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch SharedFunctionInfo::kFeedbackMetadataOffset); 1361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractScriptReferences(int entry, Script* script) { 1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObject* obj = script; 1366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(obj, entry, 1367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "source", script->source(), 1368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Script::kSourceOffset); 1369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(obj, entry, 1370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "name", script->name(), 1371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Script::kNameOffset); 1372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(obj, entry, 1373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "context_data", script->context_data(), 1374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Script::kContextOffset); 1375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(script->line_ends(), "(script line ends)"); 1376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(obj, entry, 1377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "line_ends", script->line_ends(), 1378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Script::kLineEndsOffset); 1379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractAccessorInfoReferences( 1383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int entry, AccessorInfo* accessor_info) { 1384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(accessor_info, entry, "name", accessor_info->name(), 1385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AccessorInfo::kNameOffset); 1386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(accessor_info, entry, "expected_receiver_type", 1387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch accessor_info->expected_receiver_type(), 1388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AccessorInfo::kExpectedReceiverTypeOffset); 1389109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (accessor_info->IsAccessorInfo()) { 1390109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch AccessorInfo* executable_accessor_info = AccessorInfo::cast(accessor_info); 1391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(executable_accessor_info, entry, "getter", 1392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch executable_accessor_info->getter(), 1393109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch AccessorInfo::kGetterOffset); 1394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(executable_accessor_info, entry, "setter", 1395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch executable_accessor_info->setter(), 1396109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch AccessorInfo::kSetterOffset); 1397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(executable_accessor_info, entry, "data", 1398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch executable_accessor_info->data(), 1399109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch AccessorInfo::kDataOffset); 1400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractAccessorPairReferences( 1405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int entry, AccessorPair* accessors) { 1406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(accessors, entry, "getter", accessors->getter(), 1407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AccessorPair::kGetterOffset); 1408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(accessors, entry, "setter", accessors->setter(), 1409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AccessorPair::kSetterOffset); 1410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::TagBuiltinCodeObject(Code* code, const char* name) { 1414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(code, names_->GetFormatted("(%s builtin)", name)); 1415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::TagCodeObject(Code* code) { 1419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (code->kind() == Code::STUB) { 1420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(code, names_->GetFormatted( 1421014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch "(%s code)", 1422014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CodeStub::MajorName(CodeStub::GetMajorKey(code)))); 1423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractCodeReferences(int entry, Code* code) { 1428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagCodeObject(code); 1429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(code->relocation_info(), "(code relocation info)"); 1430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(code, entry, 1431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "relocation_info", code->relocation_info(), 1432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code::kRelocationInfoOffset); 1433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(code, entry, 1434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "handler_table", code->handler_table(), 1435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code::kHandlerTableOffset); 1436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(code->deoptimization_data(), "(code deopt data)"); 1437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(code, entry, 1438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "deoptimization_data", code->deoptimization_data(), 1439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code::kDeoptimizationDataOffset); 1440f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch TagObject(code->source_position_table(), "(source position table)"); 1441f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetInternalReference(code, entry, "source_position_table", 1442f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch code->source_position_table(), 1443f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Code::kSourcePositionTableOffset); 1444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (code->kind() == Code::FUNCTION) { 1445f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetInternalReference(code, entry, "type_feedback_info", 1446f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch code->type_feedback_info(), 1447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code::kTypeFeedbackInfoOffset); 1448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1449f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetInternalReference(code, entry, "gc_metadata", code->gc_metadata(), 1450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code::kGCMetadataOffset); 1451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractBoxReferences(int entry, Box* box) { 1454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(box, entry, "value", box->value(), Box::kValueOffset); 1455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractCellReferences(int entry, Cell* cell) { 1458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(cell, entry, "value", cell->value(), Cell::kValueOffset); 1459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1461f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid V8HeapExplorer::ExtractWeakCellReferences(int entry, WeakCell* weak_cell) { 1462f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch TagObject(weak_cell, "(weak cell)"); 1463f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetWeakReference(weak_cell, entry, "value", weak_cell->value(), 1464f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch WeakCell::kValueOffset); 1465f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractPropertyCellReferences(int entry, 1468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PropertyCell* cell) { 1469014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetInternalReference(cell, entry, "value", cell->value(), 1470014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PropertyCell::kValueOffset); 1471f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch TagObject(cell->dependent_code(), "(dependent code)"); 1472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(cell, entry, "dependent_code", cell->dependent_code(), 1473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PropertyCell::kDependentCodeOffset); 1474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractAllocationSiteReferences(int entry, 1478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationSite* site) { 1479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(site, entry, "transition_info", site->transition_info(), 1480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationSite::kTransitionInfoOffset); 1481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(site, entry, "nested_site", site->nested_site(), 1482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationSite::kNestedSiteOffset); 1483f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch TagObject(site->dependent_code(), "(dependent code)"); 1484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(site, entry, "dependent_code", site->dependent_code(), 1485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationSite::kDependentCodeOffset); 1486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Do not visit weak_next as it is not visited by the StaticVisitor, 1487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // and we're not very interested in weak_next field here. 1488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(AllocationSite::kWeakNextOffset >= 1489109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch AllocationSite::kPointerFieldsEndOffset); 1490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass JSArrayBufferDataEntryAllocator : public HeapEntriesAllocator { 1494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 1495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSArrayBufferDataEntryAllocator(size_t size, V8HeapExplorer* explorer) 1496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : size_(size) 1497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch , explorer_(explorer) { 1498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual HeapEntry* AllocateEntry(HeapThing ptr) { 1500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return explorer_->AddEntry( 1501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<Address>(ptr), 1502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry::kNative, "system / JSArrayBufferData", size_); 1503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 1505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch size_t size_; 1506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch V8HeapExplorer* explorer_; 1507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 1508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractJSArrayBufferReferences( 1511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int entry, JSArrayBuffer* buffer) { 1512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Setup a reference to a native memory backing_store object. 1513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!buffer->backing_store()) 1514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 1515f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch size_t data_size = NumberToSize(buffer->byte_length()); 1516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSArrayBufferDataEntryAllocator allocator(data_size, this); 1517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* data_entry = 1518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->FindOrAddEntry(buffer->backing_store(), &allocator); 1519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->SetNamedReference(HeapGraphEdge::kInternal, 1520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entry, "backing_store", data_entry); 1521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractFixedArrayReferences(int entry, FixedArray* array) { 1524f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto it = array_types_.find(array); 1525f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (it == array_types_.end()) { 1526f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (int i = 0, l = array->length(); i < l; ++i) { 1527f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetInternalReference(array, entry, i, array->get(i), 1528f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch array->OffsetOfElementAt(i)); 1529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1530f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return; 1531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1532f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch switch (it->second) { 1533f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case JS_WEAK_COLLECTION_SUB_TYPE: 1534f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (int i = 0, l = array->length(); i < l; ++i) { 1535f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetWeakReference(array, entry, i, array->get(i), 1536f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch array->OffsetOfElementAt(i)); 1537f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1538f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 1539f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1540f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // TODO(alph): Add special processing for other types of FixedArrays. 1541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1542f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch default: 1543f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (int i = 0, l = array->length(); i < l; ++i) { 1544f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetInternalReference(array, entry, i, array->get(i), 1545f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch array->OffsetOfElementAt(i)); 1546f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1547f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 1548f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1549f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj, int entry) { 155213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Isolate* isolate = js_obj->GetIsolate(); 1553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (js_obj->HasFastProperties()) { 1554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DescriptorArray* descs = js_obj->map()->instance_descriptors(); 1555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int real_size = js_obj->map()->NumberOfOwnDescriptors(); 1556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < real_size; i++) { 1557958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PropertyDetails details = descs->GetDetails(i); 1558958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier switch (details.location()) { 1559014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case kField: { 1560958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Representation r = details.representation(); 1561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (r.IsSmi() || r.IsDouble()) break; 1562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Name* k = descs->GetKey(i); 1564958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FieldIndex field_index = FieldIndex::ForDescriptor(js_obj->map(), i); 1565958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Object* value = js_obj->RawFastPropertyAt(field_index); 1566958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int field_offset = 1567958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier field_index.is_inobject() ? field_index.offset() : -1; 1568958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1569bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch SetDataOrAccessorPropertyReference(details.kind(), js_obj, entry, k, 1570bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch value, NULL, field_offset); 1571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1573014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case kDescriptor: 1574958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier SetDataOrAccessorPropertyReference(details.kind(), js_obj, entry, 1575958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier descs->GetKey(i), 1576958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier descs->GetValue(i)); 1577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1580014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else if (js_obj->IsJSGlobalObject()) { 1581014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // We assume that global objects can only have slow properties. 1582014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch GlobalDictionary* dictionary = js_obj->global_dictionary(); 1583014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int length = dictionary->Capacity(); 1584014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (int i = 0; i < length; ++i) { 1585014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Object* k = dictionary->KeyAt(i); 158613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (dictionary->IsKey(isolate, k)) { 1587014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(dictionary->ValueAt(i)->IsPropertyCell()); 1588014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PropertyCell* cell = PropertyCell::cast(dictionary->ValueAt(i)); 1589014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Object* value = cell->value(); 1590014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PropertyDetails details = cell->property_details(); 1591014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetDataOrAccessorPropertyReference(details.kind(), js_obj, entry, 1592014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Name::cast(k), value); 1593014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1594014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionary* dictionary = js_obj->property_dictionary(); 1597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int length = dictionary->Capacity(); 1598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < length; ++i) { 1599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object* k = dictionary->KeyAt(i); 160013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (dictionary->IsKey(isolate, k)) { 1601014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Object* value = dictionary->ValueAt(i); 1602958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PropertyDetails details = dictionary->DetailsAt(i); 1603958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier SetDataOrAccessorPropertyReference(details.kind(), js_obj, entry, 1604958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Name::cast(k), value); 1605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1611958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid V8HeapExplorer::ExtractAccessorPairProperty(JSObject* js_obj, int entry, 1612958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Name* key, 1613958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Object* callback_obj, 1614958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int field_offset) { 1615958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (!callback_obj->IsAccessorPair()) return; 1616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AccessorPair* accessors = AccessorPair::cast(callback_obj); 1617958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier SetPropertyReference(js_obj, entry, key, accessors, NULL, field_offset); 1618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object* getter = accessors->getter(); 1619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!getter->IsOddball()) { 1620958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier SetPropertyReference(js_obj, entry, key, getter, "get %s"); 1621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object* setter = accessors->setter(); 1623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!setter->IsOddball()) { 1624958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier SetPropertyReference(js_obj, entry, key, setter, "set %s"); 1625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractElementReferences(JSObject* js_obj, int entry) { 163013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Isolate* isolate = js_obj->GetIsolate(); 1631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (js_obj->HasFastObjectElements()) { 1632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FixedArray* elements = FixedArray::cast(js_obj->elements()); 1633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int length = js_obj->IsJSArray() ? 1634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi::cast(JSArray::cast(js_obj)->length())->value() : 1635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch elements->length(); 1636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < length; ++i) { 163713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (!elements->get(i)->IsTheHole(isolate)) { 1638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetElementReference(js_obj, entry, i, elements->get(i)); 1639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (js_obj->HasDictionaryElements()) { 1642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SeededNumberDictionary* dictionary = js_obj->element_dictionary(); 1643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int length = dictionary->Capacity(); 1644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < length; ++i) { 1645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object* k = dictionary->KeyAt(i); 164613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (dictionary->IsKey(isolate, k)) { 1647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(k->IsNumber()); 1648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t index = static_cast<uint32_t>(k->Number()); 1649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetElementReference(js_obj, entry, index, dictionary->ValueAt(i)); 1650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractInternalReferences(JSObject* js_obj, int entry) { 1657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int length = js_obj->GetInternalFieldCount(); 1658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < length; ++i) { 1659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object* o = js_obj->GetInternalField(i); 1660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference( 1661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch js_obj, entry, i, o, js_obj->GetInternalFieldOffset(i)); 1662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochString* V8HeapExplorer::GetConstructorName(JSObject* object) { 1667014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Isolate* isolate = object->GetIsolate(); 1668014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (object->IsJSFunction()) return isolate->heap()->closure_string(); 1669014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DisallowHeapAllocation no_gc; 1670014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HandleScope scope(isolate); 1671014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return *JSReceiver::GetConstructorName(handle(object, isolate)); 1672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapEntry* V8HeapExplorer::GetEntry(Object* obj) { 1676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!obj->IsHeapObject()) return NULL; 1677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return filler_->FindOrAddEntry(obj, this); 1678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass RootsReferencesExtractor : public ObjectVisitor { 1682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 1683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch struct IndexTag { 1684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IndexTag(int index, VisitorSynchronization::SyncTag tag) 1685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : index(index), tag(tag) { } 1686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int index; 1687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitorSynchronization::SyncTag tag; 1688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 1689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 1691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit RootsReferencesExtractor(Heap* heap) 1692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : collecting_all_references_(false), 1693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch previous_reference_count_(0), 1694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap_(heap) { 1695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1697014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void VisitPointers(Object** start, Object** end) override { 1698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (collecting_all_references_) { 1699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (Object** p = start; p < end; p++) all_references_.Add(*p); 1700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (Object** p = start; p < end; p++) strong_references_.Add(*p); 1702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void SetCollectingAllReferences() { collecting_all_references_ = true; } 1706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void FillReferences(V8HeapExplorer* explorer) { 1708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(strong_references_.length() <= all_references_.length()); 1709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Builtins* builtins = heap_->isolate()->builtins(); 1710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int strong_index = 0, all_index = 0, tags_index = 0, builtin_index = 0; 1711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while (all_index < all_references_.length()) { 1712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_strong = strong_index < strong_references_.length() 1713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch && strong_references_[strong_index] == all_references_[all_index]; 1714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explorer->SetGcSubrootReference(reference_tags_[tags_index].tag, 1715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !is_strong, 1716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch all_references_[all_index]); 1717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (reference_tags_[tags_index].tag == 1718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitorSynchronization::kBuiltins) { 1719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(all_references_[all_index]->IsCode()); 1720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explorer->TagBuiltinCodeObject( 1721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code::cast(all_references_[all_index]), 1722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch builtins->name(builtin_index++)); 1723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++all_index; 1725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (is_strong) ++strong_index; 1726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (reference_tags_[tags_index].index == all_index) ++tags_index; 1727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1730014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void Synchronize(VisitorSynchronization::SyncTag tag) override { 1731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (collecting_all_references_ && 1732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch previous_reference_count_ != all_references_.length()) { 1733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch previous_reference_count_ = all_references_.length(); 1734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reference_tags_.Add(IndexTag(previous_reference_count_, tag)); 1735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 1739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool collecting_all_references_; 1740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch List<Object*> strong_references_; 1741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch List<Object*> all_references_; 1742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int previous_reference_count_; 1743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch List<IndexTag> reference_tags_; 1744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap* heap_; 1745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 1746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool V8HeapExplorer::IterateAndExtractReferences( 1749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SnapshotFiller* filler) { 1750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_ = filler; 1751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Create references to the synthetic roots. 1753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetRootGcRootsReference(); 1754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int tag = 0; tag < VisitorSynchronization::kNumberOfSyncTags; tag++) { 1755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetGcRootsReference(static_cast<VisitorSynchronization::SyncTag>(tag)); 1756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Make sure builtin code objects get their builtin tags 1759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // first. Otherwise a particular JSFunction object could set 1760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // its custom name to a generic builtin. 1761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RootsReferencesExtractor extractor(heap_); 1762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap_->IterateRoots(&extractor, VISIT_ONLY_STRONG); 1763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch extractor.SetCollectingAllReferences(); 1764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap_->IterateRoots(&extractor, VISIT_ALL); 1765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch extractor.FillReferences(this); 1766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We have to do two passes as sometimes FixedArrays are used 1768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to weakly hold their items, and it's impossible to distinguish 1769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // between these cases without processing the array owner first. 1770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool interrupted = 1771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IterateAndExtractSinglePass<&V8HeapExplorer::ExtractReferencesPass1>() || 1772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IterateAndExtractSinglePass<&V8HeapExplorer::ExtractReferencesPass2>(); 1773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (interrupted) { 1775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_ = NULL; 1776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return false; 1777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_ = NULL; 1780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return progress_->ProgressReport(true); 1781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<V8HeapExplorer::ExtractReferencesMethod extractor> 1785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool V8HeapExplorer::IterateAndExtractSinglePass() { 1786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Now iterate the whole heap. 1787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool interrupted = false; 1788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapIterator iterator(heap_, HeapIterator::kFilterUnreachable); 1789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Heap iteration with filtering must be finished in any case. 1790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (HeapObject* obj = iterator.next(); 1791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch obj != NULL; 1792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch obj = iterator.next(), progress_->ProgressStep()) { 1793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (interrupted) continue; 1794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1795014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch size_t max_pointer = obj->Size() / kPointerSize; 1796014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (max_pointer > marks_.size()) { 1797014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Clear the current bits. 1798014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch std::vector<bool>().swap(marks_); 1799014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Reallocate to right size. 1800014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch marks_.resize(max_pointer, false); 1801014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1802014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* heap_entry = GetEntry(obj); 1804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int entry = heap_entry->index(); 1805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((this->*extractor)(entry, obj)) { 1806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(obj, entry, 1807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "map", obj->map(), HeapObject::kMapOffset); 1808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Extract unvisited fields as hidden references and restore tags 1809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // of visited fields. 1810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IndexedReferencesExtractor refs_extractor(this, obj, entry); 1811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch obj->Iterate(&refs_extractor); 1812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!progress_->ProgressReport(false)) interrupted = true; 1815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return interrupted; 1817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool V8HeapExplorer::IsEssentialObject(Object* object) { 1821014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return object->IsHeapObject() && !object->IsOddball() && 1822014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch object != heap_->empty_byte_array() && 1823014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch object != heap_->empty_fixed_array() && 1824014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch object != heap_->empty_descriptor_array() && 1825f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch object != heap_->empty_type_feedback_vector() && 1826014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch object != heap_->fixed_array_map() && object != heap_->cell_map() && 1827014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch object != heap_->global_property_cell_map() && 1828014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch object != heap_->shared_function_info_map() && 1829014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch object != heap_->free_space_map() && 1830014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch object != heap_->one_pointer_filler_map() && 1831014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch object != heap_->two_pointer_filler_map(); 1832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1834f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochbool V8HeapExplorer::IsEssentialHiddenReference(Object* parent, 1835f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch int field_offset) { 1836f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (parent->IsAllocationSite() && 1837f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch field_offset == AllocationSite::kWeakNextOffset) 1838f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return false; 1839f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (parent->IsJSFunction() && 1840f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch field_offset == JSFunction::kNextFunctionLinkOffset) 1841f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return false; 1842f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (parent->IsCode() && field_offset == Code::kNextCodeLinkOffset) 1843f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return false; 1844f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (parent->IsContext() && 1845f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch field_offset == Context::OffsetOfElementAt(Context::NEXT_CONTEXT_LINK)) 1846f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return false; 1847f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (parent->IsWeakCell() && field_offset == WeakCell::kNextOffset) 1848f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return false; 1849f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return true; 1850f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::SetContextReference(HeapObject* parent_obj, 1853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int parent_entry, 1854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch String* reference_name, 1855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object* child_obj, 1856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int field_offset) { 1857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(parent_entry == GetEntry(parent_obj)->index()); 1858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* child_entry = GetEntry(child_obj); 1859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (child_entry != NULL) { 1860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->SetNamedReference(HeapGraphEdge::kContextVariable, 1861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch parent_entry, 1862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch names_->GetName(reference_name), 1863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch child_entry); 1864014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MarkVisitedField(parent_obj, field_offset); 1865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1869014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid V8HeapExplorer::MarkVisitedField(HeapObject* obj, int offset) { 1870014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (offset < 0) return; 1871014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int index = offset / kPointerSize; 1872014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!marks_[index]); 1873014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch marks_[index] = true; 1874014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 1875014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1876014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::SetNativeBindReference(HeapObject* parent_obj, 1878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int parent_entry, 1879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* reference_name, 1880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object* child_obj) { 1881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(parent_entry == GetEntry(parent_obj)->index()); 1882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* child_entry = GetEntry(child_obj); 1883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (child_entry != NULL) { 1884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->SetNamedReference(HeapGraphEdge::kShortcut, 1885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch parent_entry, 1886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reference_name, 1887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch child_entry); 1888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::SetElementReference(HeapObject* parent_obj, 1893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int parent_entry, 1894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int index, 1895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object* child_obj) { 1896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(parent_entry == GetEntry(parent_obj)->index()); 1897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* child_entry = GetEntry(child_obj); 1898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (child_entry != NULL) { 1899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->SetIndexedReference(HeapGraphEdge::kElement, 1900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch parent_entry, 1901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch index, 1902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch child_entry); 1903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::SetInternalReference(HeapObject* parent_obj, 1908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int parent_entry, 1909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* reference_name, 1910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object* child_obj, 1911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int field_offset) { 1912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(parent_entry == GetEntry(parent_obj)->index()); 1913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* child_entry = GetEntry(child_obj); 1914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (child_entry == NULL) return; 1915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IsEssentialObject(child_obj)) { 1916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->SetNamedReference(HeapGraphEdge::kInternal, 1917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch parent_entry, 1918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reference_name, 1919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch child_entry); 1920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1921014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MarkVisitedField(parent_obj, field_offset); 1922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::SetInternalReference(HeapObject* parent_obj, 1926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int parent_entry, 1927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int index, 1928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object* child_obj, 1929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int field_offset) { 1930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(parent_entry == GetEntry(parent_obj)->index()); 1931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* child_entry = GetEntry(child_obj); 1932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (child_entry == NULL) return; 1933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IsEssentialObject(child_obj)) { 1934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->SetNamedReference(HeapGraphEdge::kInternal, 1935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch parent_entry, 1936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch names_->GetName(index), 1937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch child_entry); 1938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1939014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MarkVisitedField(parent_obj, field_offset); 1940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::SetHiddenReference(HeapObject* parent_obj, 1943f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch int parent_entry, int index, 1944f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Object* child_obj, int field_offset) { 1945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(parent_entry == GetEntry(parent_obj)->index()); 1946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* child_entry = GetEntry(child_obj); 1947f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (child_entry != nullptr && IsEssentialObject(child_obj) && 1948f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch IsEssentialHiddenReference(parent_obj, field_offset)) { 1949f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch filler_->SetIndexedReference(HeapGraphEdge::kHidden, parent_entry, index, 1950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch child_entry); 1951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::SetWeakReference(HeapObject* parent_obj, 1956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int parent_entry, 1957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* reference_name, 1958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object* child_obj, 1959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int field_offset) { 1960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(parent_entry == GetEntry(parent_obj)->index()); 1961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* child_entry = GetEntry(child_obj); 1962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (child_entry == NULL) return; 1963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IsEssentialObject(child_obj)) { 1964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->SetNamedReference(HeapGraphEdge::kWeak, 1965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch parent_entry, 1966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reference_name, 1967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch child_entry); 1968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1969014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MarkVisitedField(parent_obj, field_offset); 1970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::SetWeakReference(HeapObject* parent_obj, 1974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int parent_entry, 1975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int index, 1976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object* child_obj, 1977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int field_offset) { 1978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(parent_entry == GetEntry(parent_obj)->index()); 1979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* child_entry = GetEntry(child_obj); 1980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (child_entry == NULL) return; 1981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IsEssentialObject(child_obj)) { 1982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->SetNamedReference(HeapGraphEdge::kWeak, 1983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch parent_entry, 1984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch names_->GetFormatted("%d", index), 1985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch child_entry); 1986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1987014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MarkVisitedField(parent_obj, field_offset); 1988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1991958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid V8HeapExplorer::SetDataOrAccessorPropertyReference( 1992958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PropertyKind kind, JSObject* parent_obj, int parent_entry, 1993958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Name* reference_name, Object* child_obj, const char* name_format_string, 1994958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int field_offset) { 1995014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (kind == kAccessor) { 1996958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ExtractAccessorPairProperty(parent_obj, parent_entry, reference_name, 1997958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier child_obj, field_offset); 1998958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } else { 1999958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier SetPropertyReference(parent_obj, parent_entry, reference_name, child_obj, 2000958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier name_format_string, field_offset); 2001958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 2002958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 2003958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2004958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 2005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::SetPropertyReference(HeapObject* parent_obj, 2006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int parent_entry, 2007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Name* reference_name, 2008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object* child_obj, 2009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* name_format_string, 2010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int field_offset) { 2011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(parent_entry == GetEntry(parent_obj)->index()); 2012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* child_entry = GetEntry(child_obj); 2013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (child_entry != NULL) { 2014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapGraphEdge::Type type = 2015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reference_name->IsSymbol() || String::cast(reference_name)->length() > 0 2016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? HeapGraphEdge::kProperty : HeapGraphEdge::kInternal; 2017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* name = name_format_string != NULL && reference_name->IsString() 2018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? names_->GetFormatted( 2019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch name_format_string, 2020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch String::cast(reference_name)->ToCString( 2021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL).get()) : 2022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch names_->GetName(reference_name); 2023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->SetNamedReference(type, 2025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch parent_entry, 2026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch name, 2027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch child_entry); 2028014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MarkVisitedField(parent_obj, field_offset); 2029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::SetRootGcRootsReference() { 2034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->SetIndexedAutoIndexReference( 2035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapGraphEdge::kElement, 2036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch snapshot_->root()->index(), 2037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch snapshot_->gc_roots()); 2038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::SetUserGlobalReference(Object* child_obj) { 2042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* child_entry = GetEntry(child_obj); 2043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(child_entry != NULL); 2044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->SetNamedAutoIndexReference( 2045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapGraphEdge::kShortcut, 2046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch snapshot_->root()->index(), 2047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch child_entry); 2048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::SetGcRootsReference(VisitorSynchronization::SyncTag tag) { 2052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->SetIndexedAutoIndexReference( 2053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapGraphEdge::kElement, 2054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch snapshot_->gc_roots()->index(), 2055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch snapshot_->gc_subroot(tag)); 2056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::SetGcSubrootReference( 2060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitorSynchronization::SyncTag tag, bool is_weak, Object* child_obj) { 2061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* child_entry = GetEntry(child_obj); 2062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (child_entry != NULL) { 2063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* name = GetStrongGcSubrootName(child_obj); 2064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (name != NULL) { 2065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->SetNamedReference( 2066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapGraphEdge::kInternal, 2067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch snapshot_->gc_subroot(tag)->index(), 2068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch name, 2069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch child_entry); 2070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (is_weak) { 2072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->SetNamedAutoIndexReference( 2073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapGraphEdge::kWeak, 2074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch snapshot_->gc_subroot(tag)->index(), 2075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch child_entry); 2076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->SetIndexedAutoIndexReference( 2078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapGraphEdge::kElement, 2079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch snapshot_->gc_subroot(tag)->index(), 2080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch child_entry); 2081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Add a shortcut to JS global object reference at snapshot root. 2085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (child_obj->IsNativeContext()) { 2086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Context* context = Context::cast(child_obj); 2087014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JSGlobalObject* global = context->global_object(); 2088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (global->IsJSGlobalObject()) { 2089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_debug_object = false; 2090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch is_debug_object = heap_->isolate()->debug()->IsDebugGlobal(global); 2091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!is_debug_object && !user_roots_.Contains(global)) { 2092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch user_roots_.Insert(global); 2093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetUserGlobalReference(global); 2094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst char* V8HeapExplorer::GetStrongGcSubrootName(Object* object) { 2102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (strong_gc_subroot_names_.is_empty()) { 2103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define NAME_ENTRY(name) strong_gc_subroot_names_.SetTag(heap_->name(), #name); 2104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define ROOT_NAME(type, name, camel_name) NAME_ENTRY(name) 2105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STRONG_ROOT_LIST(ROOT_NAME) 2106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef ROOT_NAME 2107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define STRUCT_MAP_NAME(NAME, Name, name) NAME_ENTRY(name##_map) 2108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STRUCT_LIST(STRUCT_MAP_NAME) 2109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef STRUCT_MAP_NAME 2110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define STRING_NAME(name, str) NAME_ENTRY(name) 2111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch INTERNALIZED_STRING_LIST(STRING_NAME) 2112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef STRING_NAME 2113958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#define SYMBOL_NAME(name) NAME_ENTRY(name) 2114958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PRIVATE_SYMBOL_LIST(SYMBOL_NAME) 2115958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#undef SYMBOL_NAME 2116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define SYMBOL_NAME(name, description) NAME_ENTRY(name) 2117958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PUBLIC_SYMBOL_LIST(SYMBOL_NAME) 2118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch WELL_KNOWN_SYMBOL_LIST(SYMBOL_NAME) 2119958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#undef SYMBOL_NAME 2120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef NAME_ENTRY 2121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(!strong_gc_subroot_names_.is_empty()); 2122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return strong_gc_subroot_names_.GetTag(object); 2124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::TagObject(Object* obj, const char* tag) { 2128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IsEssentialObject(obj)) { 2129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* entry = GetEntry(obj); 2130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (entry->name()[0] == '\0') { 2131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entry->set_name(tag); 2132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2136f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid V8HeapExplorer::TagFixedArraySubType(const FixedArray* array, 2137f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch FixedArraySubInstanceType type) { 2138f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(array_types_.find(array) == array_types_.end()); 2139f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch array_types_[array] = type; 2140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass GlobalObjectsEnumerator : public ObjectVisitor { 2143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 2144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void VisitPointers(Object** start, Object** end) override { 2145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (Object** p = start; p < end; p++) { 2146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((*p)->IsNativeContext()) { 2147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Context* context = Context::cast(*p); 2148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSObject* proxy = context->global_proxy(); 2149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (proxy->IsJSGlobalProxy()) { 2150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object* global = proxy->map()->prototype(); 2151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (global->IsJSGlobalObject()) { 2152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch objects_.Add(Handle<JSGlobalObject>(JSGlobalObject::cast(global))); 2153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int count() { return objects_.length(); } 2159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSGlobalObject>& at(int i) { return objects_[i]; } 2160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 2162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch List<Handle<JSGlobalObject> > objects_; 2163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 2164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Modifies heap. Must not be run during heap traversal. 2167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::TagGlobalObjects() { 2168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate = heap_->isolate(); 2169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HandleScope scope(isolate); 2170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GlobalObjectsEnumerator enumerator; 2171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate->global_handles()->IterateAllRoots(&enumerator); 2172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char** urls = NewArray<const char*>(enumerator.count()); 2173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0, l = enumerator.count(); i < l; ++i) { 2174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (global_object_name_resolver_) { 2175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HandleScope scope(isolate); 2176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<JSGlobalObject> global_obj = enumerator.at(i); 2177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch urls[i] = global_object_name_resolver_->GetName( 2178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Utils::ToLocal(Handle<JSObject>::cast(global_obj))); 2179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch urls[i] = NULL; 2181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DisallowHeapAllocation no_allocation; 2185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0, l = enumerator.count(); i < l; ++i) { 2186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch objects_tags_.SetTag(*enumerator.at(i), urls[i]); 2187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeleteArray(urls); 2190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass GlobalHandlesExtractor : public ObjectVisitor { 2194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 2195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit GlobalHandlesExtractor(NativeObjectsExplorer* explorer) 2196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : explorer_(explorer) {} 2197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ~GlobalHandlesExtractor() override {} 2198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void VisitPointers(Object** start, Object** end) override { UNREACHABLE(); } 2199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void VisitEmbedderReference(Object** p, uint16_t class_id) override { 2200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explorer_->VisitSubtreeWrapper(p, class_id); 2201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 2203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NativeObjectsExplorer* explorer_; 2204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 2205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass BasicHeapEntriesAllocator : public HeapEntriesAllocator { 2208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 2209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BasicHeapEntriesAllocator( 2210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapSnapshot* snapshot, 2211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry::Type entries_type) 2212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : snapshot_(snapshot), 2213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch names_(snapshot_->profiler()->names()), 2214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap_object_map_(snapshot_->profiler()->heap_object_map()), 2215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_type_(entries_type) { 2216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual HeapEntry* AllocateEntry(HeapThing ptr); 2218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 2219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapSnapshot* snapshot_; 2220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StringsStorage* names_; 2221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObjectsMap* heap_object_map_; 2222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry::Type entries_type_; 2223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 2224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapEntry* BasicHeapEntriesAllocator::AllocateEntry(HeapThing ptr) { 2227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::RetainedObjectInfo* info = reinterpret_cast<v8::RetainedObjectInfo*>(ptr); 2228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch intptr_t elements = info->GetElementCount(); 2229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch intptr_t size = info->GetSizeInBytes(); 2230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* name = elements != -1 2231bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch ? names_->GetFormatted("%s / %" V8PRIdPTR " entries", 2232bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch info->GetLabel(), elements) 2233bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch : names_->GetCopy(info->GetLabel()); 2234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return snapshot_->AddEntry( 2235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_type_, 2236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch name, 2237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap_object_map_->GenerateId(info), 2238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch size != -1 ? static_cast<int>(size) : 0, 2239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 0); 2240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochNativeObjectsExplorer::NativeObjectsExplorer( 2244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapSnapshot* snapshot, 2245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SnapshottingProgressReportingInterface* progress) 2246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : isolate_(snapshot->profiler()->heap_object_map()->heap()->isolate()), 2247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch snapshot_(snapshot), 2248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch names_(snapshot_->profiler()->names()), 2249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch embedder_queried_(false), 2250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch objects_by_info_(RetainedInfosMatch), 2251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch native_groups_(StringsMatch), 2252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_(NULL) { 2253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch synthetic_entries_allocator_ = 2254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch new BasicHeapEntriesAllocator(snapshot, HeapEntry::kSynthetic); 2255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch native_entries_allocator_ = 2256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch new BasicHeapEntriesAllocator(snapshot, HeapEntry::kNative); 2257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochNativeObjectsExplorer::~NativeObjectsExplorer() { 226113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch for (base::HashMap::Entry* p = objects_by_info_.Start(); p != NULL; 2262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch p = objects_by_info_.Next(p)) { 2263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::RetainedObjectInfo* info = 2264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<v8::RetainedObjectInfo*>(p->key); 2265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch info->Dispose(); 2266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch List<HeapObject*>* objects = 2267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<List<HeapObject*>* >(p->value); 2268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch delete objects; 2269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 227013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch for (base::HashMap::Entry* p = native_groups_.Start(); p != NULL; 2271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch p = native_groups_.Next(p)) { 2272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::RetainedObjectInfo* info = 2273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<v8::RetainedObjectInfo*>(p->value); 2274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch info->Dispose(); 2275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch delete synthetic_entries_allocator_; 2277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch delete native_entries_allocator_; 2278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint NativeObjectsExplorer::EstimateObjectsCount() { 2282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FillRetainedObjects(); 2283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return objects_by_info_.occupancy(); 2284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NativeObjectsExplorer::FillRetainedObjects() { 2288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (embedder_queried_) return; 2289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate = isolate_; 2290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const GCType major_gc_type = kGCTypeMarkSweepCompact; 2291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Record objects that are joined into ObjectGroups. 2292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate->heap()->CallGCPrologueCallbacks( 2293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch major_gc_type, kGCCallbackFlagConstructRetainedObjectInfos); 2294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch List<ObjectGroup*>* groups = isolate->global_handles()->object_groups(); 2295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < groups->length(); ++i) { 2296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ObjectGroup* group = groups->at(i); 2297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (group->info == NULL) continue; 2298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch List<HeapObject*>* list = GetListMaybeDisposeInfo(group->info); 2299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (size_t j = 0; j < group->length; ++j) { 2300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObject* obj = HeapObject::cast(*group->objects[j]); 2301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch list->Add(obj); 2302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch in_groups_.Insert(obj); 2303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch group->info = NULL; // Acquire info object ownership. 2305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate->global_handles()->RemoveObjectGroups(); 2307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate->heap()->CallGCEpilogueCallbacks(major_gc_type, kNoGCCallbackFlags); 2308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Record objects that are not in ObjectGroups, but have class ID. 2309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GlobalHandlesExtractor extractor(this); 2310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate->global_handles()->IterateAllRootsWithClassIds(&extractor); 2311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch embedder_queried_ = true; 2312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NativeObjectsExplorer::FillImplicitReferences() { 2316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate = isolate_; 2317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch List<ImplicitRefGroup*>* groups = 2318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate->global_handles()->implicit_ref_groups(); 2319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < groups->length(); ++i) { 2320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ImplicitRefGroup* group = groups->at(i); 2321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObject* parent = *group->parent; 2322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int parent_entry = 2323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->FindOrAddEntry(parent, native_entries_allocator_)->index(); 2324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(parent_entry != HeapEntry::kNoEntry); 2325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object*** children = group->children; 2326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (size_t j = 0; j < group->length; ++j) { 2327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object* child = *children[j]; 2328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* child_entry = 2329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->FindOrAddEntry(child, native_entries_allocator_); 2330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->SetNamedReference( 2331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapGraphEdge::kInternal, 2332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch parent_entry, 2333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "native", 2334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch child_entry); 2335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate->global_handles()->RemoveImplicitRefGroups(); 2338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochList<HeapObject*>* NativeObjectsExplorer::GetListMaybeDisposeInfo( 2341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::RetainedObjectInfo* info) { 234213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch base::HashMap::Entry* entry = 234313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch objects_by_info_.LookupOrInsert(info, InfoHash(info)); 2344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (entry->value != NULL) { 2345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch info->Dispose(); 2346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entry->value = new List<HeapObject*>(4); 2348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return reinterpret_cast<List<HeapObject*>* >(entry->value); 2350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool NativeObjectsExplorer::IterateAndExtractReferences( 2354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SnapshotFiller* filler) { 2355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_ = filler; 2356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FillRetainedObjects(); 2357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FillImplicitReferences(); 2358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (EstimateObjectsCount() > 0) { 235913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch for (base::HashMap::Entry* p = objects_by_info_.Start(); p != NULL; 2360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch p = objects_by_info_.Next(p)) { 2361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::RetainedObjectInfo* info = 2362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<v8::RetainedObjectInfo*>(p->key); 2363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetNativeRootReference(info); 2364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch List<HeapObject*>* objects = 2365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<List<HeapObject*>* >(p->value); 2366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < objects->length(); ++i) { 2367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetWrapperNativeReferences(objects->at(i), info); 2368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetRootNativeRootsReference(); 2371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_ = NULL; 2373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return true; 2374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass NativeGroupRetainedObjectInfo : public v8::RetainedObjectInfo { 2378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 2379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit NativeGroupRetainedObjectInfo(const char* label) 2380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : disposed_(false), 2381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch hash_(reinterpret_cast<intptr_t>(label)), 2382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch label_(label) { 2383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual ~NativeGroupRetainedObjectInfo() {} 2386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual void Dispose() { 2387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(!disposed_); 2388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch disposed_ = true; 2389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch delete this; 2390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual bool IsEquivalent(RetainedObjectInfo* other) { 2392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return hash_ == other->GetHash() && !strcmp(label_, other->GetLabel()); 2393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual intptr_t GetHash() { return hash_; } 2395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual const char* GetLabel() { return label_; } 2396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 2398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool disposed_; 2399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch intptr_t hash_; 2400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* label_; 2401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 2402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochNativeGroupRetainedObjectInfo* NativeObjectsExplorer::FindOrAddGroupInfo( 2405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* label) { 2406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* label_copy = names_->GetCopy(label); 2407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t hash = StringHasher::HashSequentialString( 2408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch label_copy, 2409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<int>(strlen(label_copy)), 2410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate_->heap()->HashSeed()); 241113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch base::HashMap::Entry* entry = 2412014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch native_groups_.LookupOrInsert(const_cast<char*>(label_copy), hash); 2413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (entry->value == NULL) { 2414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entry->value = new NativeGroupRetainedObjectInfo(label); 2415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return static_cast<NativeGroupRetainedObjectInfo*>(entry->value); 2417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NativeObjectsExplorer::SetNativeRootReference( 2421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::RetainedObjectInfo* info) { 2422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* child_entry = 2423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->FindOrAddEntry(info, native_entries_allocator_); 2424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(child_entry != NULL); 2425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NativeGroupRetainedObjectInfo* group_info = 2426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FindOrAddGroupInfo(info->GetGroupLabel()); 2427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* group_entry = 2428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->FindOrAddEntry(group_info, synthetic_entries_allocator_); 2429014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // |FindOrAddEntry| can move and resize the entries backing store. Reload 2430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // potentially-stale pointer. 2431014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch child_entry = filler_->FindEntry(info); 2432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->SetNamedAutoIndexReference( 2433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapGraphEdge::kInternal, 2434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch group_entry->index(), 2435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch child_entry); 2436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NativeObjectsExplorer::SetWrapperNativeReferences( 2440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObject* wrapper, v8::RetainedObjectInfo* info) { 2441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* wrapper_entry = filler_->FindEntry(wrapper); 2442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(wrapper_entry != NULL); 2443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* info_entry = 2444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->FindOrAddEntry(info, native_entries_allocator_); 2445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(info_entry != NULL); 2446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->SetNamedReference(HeapGraphEdge::kInternal, 2447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch wrapper_entry->index(), 2448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "native", 2449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch info_entry); 2450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->SetIndexedAutoIndexReference(HeapGraphEdge::kElement, 2451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch info_entry->index(), 2452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch wrapper_entry); 2453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NativeObjectsExplorer::SetRootNativeRootsReference() { 245713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch for (base::HashMap::Entry* entry = native_groups_.Start(); entry; 2458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entry = native_groups_.Next(entry)) { 2459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NativeGroupRetainedObjectInfo* group_info = 2460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<NativeGroupRetainedObjectInfo*>(entry->value); 2461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* group_entry = 2462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->FindOrAddEntry(group_info, native_entries_allocator_); 2463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(group_entry != NULL); 2464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->SetIndexedAutoIndexReference( 2465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapGraphEdge::kElement, 2466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch snapshot_->root()->index(), 2467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch group_entry); 2468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NativeObjectsExplorer::VisitSubtreeWrapper(Object** p, uint16_t class_id) { 2473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (in_groups_.Contains(*p)) return; 2474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate = isolate_; 2475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::RetainedObjectInfo* info = 2476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate->heap_profiler()->ExecuteWrapperClassCallback(class_id, p); 2477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (info == NULL) return; 2478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GetListMaybeDisposeInfo(info)->Add(HeapObject::cast(*p)); 2479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapSnapshotGenerator::HeapSnapshotGenerator( 2483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapSnapshot* snapshot, 2484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::ActivityControl* control, 2485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::HeapProfiler::ObjectNameResolver* resolver, 2486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap* heap) 2487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : snapshot_(snapshot), 2488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch control_(control), 2489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8_heap_explorer_(snapshot_, this, resolver), 2490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch dom_explorer_(snapshot_, this), 2491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap_(heap) { 2492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool HeapSnapshotGenerator::GenerateSnapshot() { 2496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8_heap_explorer_.TagGlobalObjects(); 2497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(1562) Profiler assumes that any object that is in the heap after 2499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // full GC is reachable from the root when computing dominators. 2500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This is not true for weakly reachable objects. 2501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // As a temporary solution we call GC twice. 2502f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch heap_->CollectAllGarbage(Heap::kMakeHeapIterableMask, 2503f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GarbageCollectionReason::kHeapProfiler); 2504f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch heap_->CollectAllGarbage(Heap::kMakeHeapIterableMask, 2505f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GarbageCollectionReason::kHeapProfiler); 2506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef VERIFY_HEAP 2508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap* debug_heap = heap_; 2509014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (FLAG_verify_heap) { 2510014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch debug_heap->Verify(); 2511014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 2513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetProgressTotal(2); // 2 passes. 2515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef VERIFY_HEAP 2517014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (FLAG_verify_heap) { 2518014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch debug_heap->Verify(); 2519014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 2521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch snapshot_->AddSyntheticRootEntries(); 2523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!FillReferences()) return false; 2525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch snapshot_->FillChildren(); 2527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch snapshot_->RememberLastJSObjectId(); 2528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch progress_counter_ = progress_total_; 2530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!ProgressReport(true)) return false; 2531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return true; 2532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshotGenerator::ProgressStep() { 2536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++progress_counter_; 2537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool HeapSnapshotGenerator::ProgressReport(bool force) { 2541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kProgressReportGranularity = 10000; 2542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (control_ != NULL 2543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch && (force || progress_counter_ % kProgressReportGranularity == 0)) { 2544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 2545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch control_->ReportProgressValue(progress_counter_, progress_total_) == 2546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::ActivityControl::kContinue; 2547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return true; 2549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshotGenerator::SetProgressTotal(int iterations_count) { 2553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (control_ == NULL) return; 2554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapIterator iterator(heap_, HeapIterator::kFilterUnreachable); 2555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch progress_total_ = iterations_count * ( 2556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8_heap_explorer_.EstimateObjectsCount(&iterator) + 2557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch dom_explorer_.EstimateObjectsCount()); 2558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch progress_counter_ = 0; 2559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool HeapSnapshotGenerator::FillReferences() { 2563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SnapshotFiller filler(snapshot_, &entries_); 2564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return v8_heap_explorer_.IterateAndExtractReferences(&filler) 2565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch && dom_explorer_.IterateAndExtractReferences(&filler); 2566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<int bytes> struct MaxDecimalDigitsIn; 2570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<> struct MaxDecimalDigitsIn<4> { 2571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kSigned = 11; 2572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kUnsigned = 10; 2573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 2574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<> struct MaxDecimalDigitsIn<8> { 2575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kSigned = 20; 2576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kUnsigned = 20; 2577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 2578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass OutputStreamWriter { 2581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 2582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit OutputStreamWriter(v8::OutputStream* stream) 2583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : stream_(stream), 2584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch chunk_size_(stream->GetChunkSize()), 2585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch chunk_(chunk_size_), 2586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch chunk_pos_(0), 2587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch aborted_(false) { 2588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(chunk_size_ > 0); 2589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool aborted() { return aborted_; } 2591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void AddCharacter(char c) { 2592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(c != '\0'); 2593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(chunk_pos_ < chunk_size_); 2594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch chunk_[chunk_pos_++] = c; 2595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MaybeWriteChunk(); 2596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void AddString(const char* s) { 2598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AddSubstring(s, StrLength(s)); 2599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void AddSubstring(const char* s, int n) { 2601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (n <= 0) return; 2602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(static_cast<size_t>(n) <= strlen(s)); 2603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* s_end = s + n; 2604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while (s < s_end) { 2605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int s_chunk_size = 2606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Min(chunk_size_ - chunk_pos_, static_cast<int>(s_end - s)); 2607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(s_chunk_size > 0); 2608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemCopy(chunk_.start() + chunk_pos_, s, s_chunk_size); 2609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch s += s_chunk_size; 2610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch chunk_pos_ += s_chunk_size; 2611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MaybeWriteChunk(); 2612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void AddNumber(unsigned n) { AddNumberImpl<unsigned>(n, "%u"); } 2615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Finalize() { 2616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (aborted_) return; 2617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(chunk_pos_ < chunk_size_); 2618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (chunk_pos_ != 0) { 2619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch WriteChunk(); 2620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stream_->EndOfStream(); 2622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 2625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template<typename T> 2626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void AddNumberImpl(T n, const char* format) { 2627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Buffer for the longest value plus trailing \0 2628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kMaxNumberSize = 2629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MaxDecimalDigitsIn<sizeof(T)>::kUnsigned + 1; 2630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (chunk_size_ - chunk_pos_ >= kMaxNumberSize) { 2631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int result = SNPrintF( 2632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch chunk_.SubVector(chunk_pos_, chunk_size_), format, n); 2633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(result != -1); 2634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch chunk_pos_ += result; 2635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MaybeWriteChunk(); 2636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmbeddedVector<char, kMaxNumberSize> buffer; 2638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int result = SNPrintF(buffer, format, n); 2639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch USE(result); 2640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(result != -1); 2641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AddString(buffer.start()); 2642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void MaybeWriteChunk() { 2645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(chunk_pos_ <= chunk_size_); 2646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (chunk_pos_ == chunk_size_) { 2647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch WriteChunk(); 2648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void WriteChunk() { 2651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (aborted_) return; 2652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (stream_->WriteAsciiChunk(chunk_.start(), chunk_pos_) == 2653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::OutputStream::kAbort) aborted_ = true; 2654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch chunk_pos_ = 0; 2655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::OutputStream* stream_; 2658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int chunk_size_; 2659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ScopedVector<char> chunk_; 2660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int chunk_pos_; 2661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool aborted_; 2662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 2663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// type, name|index, to_node. 2666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst int HeapSnapshotJSONSerializer::kEdgeFieldsCount = 3; 2667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// type, name, id, self_size, edge_count, trace_node_id. 2668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst int HeapSnapshotJSONSerializer::kNodeFieldsCount = 6; 2669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshotJSONSerializer::Serialize(v8::OutputStream* stream) { 2671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (AllocationTracker* allocation_tracker = 2672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch snapshot_->profiler()->allocation_tracker()) { 2673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch allocation_tracker->PrepareForSerialization(); 2674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(writer_ == NULL); 2676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_ = new OutputStreamWriter(stream); 2677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SerializeImpl(); 2678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch delete writer_; 2679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_ = NULL; 2680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshotJSONSerializer::SerializeImpl() { 2684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(0 == snapshot_->root()->index()); 2685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddCharacter('{'); 2686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString("\"snapshot\":{"); 2687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SerializeSnapshot(); 2688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (writer_->aborted()) return; 2689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString("},\n"); 2690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString("\"nodes\":["); 2691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SerializeNodes(); 2692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (writer_->aborted()) return; 2693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString("],\n"); 2694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString("\"edges\":["); 2695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SerializeEdges(); 2696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (writer_->aborted()) return; 2697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString("],\n"); 2698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString("\"trace_function_infos\":["); 2700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SerializeTraceNodeInfos(); 2701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (writer_->aborted()) return; 2702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString("],\n"); 2703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString("\"trace_tree\":["); 2704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SerializeTraceTree(); 2705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (writer_->aborted()) return; 2706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString("],\n"); 2707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2708014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch writer_->AddString("\"samples\":["); 2709014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SerializeSamples(); 2710014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (writer_->aborted()) return; 2711014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch writer_->AddString("],\n"); 2712014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString("\"strings\":["); 2714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SerializeStrings(); 2715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (writer_->aborted()) return; 2716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddCharacter(']'); 2717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddCharacter('}'); 2718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->Finalize(); 2719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint HeapSnapshotJSONSerializer::GetStringId(const char* s) { 272313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch base::HashMap::Entry* cache_entry = 2724014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch strings_.LookupOrInsert(const_cast<char*>(s), StringHash(s)); 2725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (cache_entry->value == NULL) { 2726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cache_entry->value = reinterpret_cast<void*>(next_string_id_++); 2727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); 2729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace { 2733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<size_t size> struct ToUnsigned; 2735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<> struct ToUnsigned<4> { 2737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch typedef uint32_t Type; 2738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 2739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<> struct ToUnsigned<8> { 2741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch typedef uint64_t Type; 2742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 2743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} // namespace 2745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<typename T> 2748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic int utoa_impl(T value, const Vector<char>& buffer, int buffer_pos) { 2749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(static_cast<T>(-1) > 0); // Check that T is unsigned 2750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int number_of_digits = 0; 2751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch T t = value; 2752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch do { 2753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++number_of_digits; 2754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } while (t /= 10); 2755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos += number_of_digits; 2757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int result = buffer_pos; 2758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch do { 2759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int last_digit = static_cast<int>(value % 10); 2760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[--buffer_pos] = '0' + last_digit; 2761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch value /= 10; 2762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } while (value); 2763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return result; 2764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<typename T> 2768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic int utoa(T value, const Vector<char>& buffer, int buffer_pos) { 2769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch typename ToUnsigned<sizeof(value)>::Type unsigned_value = value; 2770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(sizeof(value) == sizeof(unsigned_value)); 2771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return utoa_impl(unsigned_value, buffer, buffer_pos); 2772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge, 2776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool first_edge) { 2777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The buffer needs space for 3 unsigned ints, 3 commas, \n and \0 2778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kBufferSize = 2779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned * 3 + 3 + 2; // NOLINT 2780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmbeddedVector<char, kBufferSize> buffer; 2781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int edge_name_or_index = edge->type() == HeapGraphEdge::kElement 2782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch || edge->type() == HeapGraphEdge::kHidden 2783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? edge->index() : GetStringId(edge->name()); 2784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int buffer_pos = 0; 2785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!first_edge) { 2786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 2787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(edge->type(), buffer, buffer_pos); 2789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 2790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(edge_name_or_index, buffer, buffer_pos); 2791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 2792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(entry_index(edge->to()), buffer, buffer_pos); 2793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = '\n'; 2794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = '\0'; 2795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString(buffer.start()); 2796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshotJSONSerializer::SerializeEdges() { 2800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch List<HeapGraphEdge*>& edges = snapshot_->children(); 2801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < edges.length(); ++i) { 2802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(i == 0 || 2803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch edges[i - 1]->from()->index() <= edges[i]->from()->index()); 2804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SerializeEdge(edges[i], i == 0); 2805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (writer_->aborted()) return; 2806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry) { 2811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The buffer needs space for 4 unsigned ints, 1 size_t, 5 commas, \n and \0 2812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kBufferSize = 2813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5 * MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned // NOLINT 2814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch + MaxDecimalDigitsIn<sizeof(size_t)>::kUnsigned // NOLINT 2815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch + 6 + 1 + 1; 2816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmbeddedVector<char, kBufferSize> buffer; 2817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int buffer_pos = 0; 2818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (entry_index(entry) != 0) { 2819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 2820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(entry->type(), buffer, buffer_pos); 2822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 2823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(GetStringId(entry->name()), buffer, buffer_pos); 2824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 2825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(entry->id(), buffer, buffer_pos); 2826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 2827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(entry->self_size(), buffer, buffer_pos); 2828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 2829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(entry->children_count(), buffer, buffer_pos); 2830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 2831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(entry->trace_node_id(), buffer, buffer_pos); 2832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = '\n'; 2833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = '\0'; 2834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString(buffer.start()); 2835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshotJSONSerializer::SerializeNodes() { 2839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch List<HeapEntry>& entries = snapshot_->entries(); 2840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < entries.length(); ++i) { 2841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SerializeNode(&entries[i]); 2842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (writer_->aborted()) return; 2843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshotJSONSerializer::SerializeSnapshot() { 2848014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch writer_->AddString("\"meta\":"); 2849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The object describing node serialization layout. 2850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We use a set of macros to improve readability. 2851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define JSON_A(s) "[" s "]" 2852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define JSON_O(s) "{" s "}" 2853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define JSON_S(s) "\"" s "\"" 2854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString(JSON_O( 2855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("node_fields") ":" JSON_A( 2856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("type") "," 2857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("name") "," 2858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("id") "," 2859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("self_size") "," 2860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("edge_count") "," 2861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("trace_node_id")) "," 2862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("node_types") ":" JSON_A( 2863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_A( 2864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("hidden") "," 2865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("array") "," 2866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("string") "," 2867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("object") "," 2868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("code") "," 2869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("closure") "," 2870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("regexp") "," 2871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("number") "," 2872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("native") "," 2873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("synthetic") "," 2874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("concatenated string") "," 2875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("sliced string")) "," 2876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("string") "," 2877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("number") "," 2878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("number") "," 2879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("number") "," 2880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("number") "," 2881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("number")) "," 2882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("edge_fields") ":" JSON_A( 2883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("type") "," 2884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("name_or_index") "," 2885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("to_node")) "," 2886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("edge_types") ":" JSON_A( 2887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_A( 2888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("context") "," 2889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("element") "," 2890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("property") "," 2891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("internal") "," 2892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("hidden") "," 2893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("shortcut") "," 2894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("weak")) "," 2895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("string_or_number") "," 2896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("node")) "," 2897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("trace_function_info_fields") ":" JSON_A( 2898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("function_id") "," 2899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("name") "," 2900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("script_name") "," 2901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("script_id") "," 2902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("line") "," 2903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("column")) "," 2904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("trace_node_fields") ":" JSON_A( 2905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("id") "," 2906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("function_info_index") "," 2907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("count") "," 2908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("size") "," 2909014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JSON_S("children")) "," 2910014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JSON_S("sample_fields") ":" JSON_A( 2911014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JSON_S("timestamp_us") "," 2912014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JSON_S("last_assigned_id")))); 2913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef JSON_S 2914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef JSON_O 2915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef JSON_A 2916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString(",\"node_count\":"); 2917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddNumber(snapshot_->entries().length()); 2918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString(",\"edge_count\":"); 2919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddNumber(snapshot_->edges().length()); 2920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString(",\"trace_function_count\":"); 2921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t count = 0; 2922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationTracker* tracker = snapshot_->profiler()->allocation_tracker(); 2923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (tracker) { 2924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch count = tracker->function_info_list().length(); 2925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddNumber(count); 2927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void WriteUChar(OutputStreamWriter* w, unibrow::uchar u) { 2931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const char hex_chars[] = "0123456789ABCDEF"; 2932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch w->AddString("\\u"); 2933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch w->AddCharacter(hex_chars[(u >> 12) & 0xf]); 2934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch w->AddCharacter(hex_chars[(u >> 8) & 0xf]); 2935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch w->AddCharacter(hex_chars[(u >> 4) & 0xf]); 2936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch w->AddCharacter(hex_chars[u & 0xf]); 2937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshotJSONSerializer::SerializeTraceTree() { 2941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationTracker* tracker = snapshot_->profiler()->allocation_tracker(); 2942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!tracker) return; 2943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationTraceTree* traces = tracker->trace_tree(); 2944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SerializeTraceNode(traces->root()); 2945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshotJSONSerializer::SerializeTraceNode(AllocationTraceNode* node) { 2949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The buffer needs space for 4 unsigned ints, 4 commas, [ and \0 2950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kBufferSize = 2951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4 * MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned // NOLINT 2952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch + 4 + 1 + 1; 2953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmbeddedVector<char, kBufferSize> buffer; 2954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int buffer_pos = 0; 2955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(node->id(), buffer, buffer_pos); 2956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 2957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(node->function_info_index(), buffer, buffer_pos); 2958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 2959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(node->allocation_count(), buffer, buffer_pos); 2960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 2961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(node->allocation_size(), buffer, buffer_pos); 2962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 2963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = '['; 2964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = '\0'; 2965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString(buffer.start()); 2966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Vector<AllocationTraceNode*> children = node->children(); 2968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < children.length(); i++) { 2969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (i > 0) { 2970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddCharacter(','); 2971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SerializeTraceNode(children[i]); 2973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddCharacter(']'); 2975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 0-based position is converted to 1-based during the serialization. 2979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic int SerializePosition(int position, const Vector<char>& buffer, 2980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int buffer_pos) { 2981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (position == -1) { 2982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = '0'; 2983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(position >= 0); 2985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(static_cast<unsigned>(position + 1), buffer, buffer_pos); 2986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return buffer_pos; 2988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshotJSONSerializer::SerializeTraceNodeInfos() { 2992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationTracker* tracker = snapshot_->profiler()->allocation_tracker(); 2993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!tracker) return; 2994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The buffer needs space for 6 unsigned ints, 6 commas, \n and \0 2995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kBufferSize = 2996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6 * MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned // NOLINT 2997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch + 6 + 1 + 1; 2998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmbeddedVector<char, kBufferSize> buffer; 2999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const List<AllocationTracker::FunctionInfo*>& list = 3000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch tracker->function_info_list(); 3001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < list.length(); i++) { 3002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationTracker::FunctionInfo* info = list[i]; 3003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int buffer_pos = 0; 3004014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (i > 0) { 3005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 3006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(info->function_id, buffer, buffer_pos); 3008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 3009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(GetStringId(info->name), buffer, buffer_pos); 3010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 3011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(GetStringId(info->script_name), buffer, buffer_pos); 3012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 3013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The cast is safe because script id is a non-negative Smi. 3014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(static_cast<unsigned>(info->script_id), buffer, 3015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos); 3016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 3017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = SerializePosition(info->line, buffer, buffer_pos); 3018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 3019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = SerializePosition(info->column, buffer, buffer_pos); 3020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = '\n'; 3021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = '\0'; 3022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString(buffer.start()); 3023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3027014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid HeapSnapshotJSONSerializer::SerializeSamples() { 3028014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const List<HeapObjectsMap::TimeInterval>& samples = 3029014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch snapshot_->profiler()->heap_object_map()->samples(); 3030014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (samples.is_empty()) return; 3031014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch base::TimeTicks start_time = samples[0].timestamp; 3032014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // The buffer needs space for 2 unsigned ints, 2 commas, \n and \0 3033014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const int kBufferSize = MaxDecimalDigitsIn<sizeof( 3034014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch base::TimeDelta().InMicroseconds())>::kUnsigned + 3035014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MaxDecimalDigitsIn<sizeof(samples[0].id)>::kUnsigned + 3036014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2 + 1 + 1; 3037014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmbeddedVector<char, kBufferSize> buffer; 3038014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (int i = 0; i < samples.length(); i++) { 3039014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HeapObjectsMap::TimeInterval& sample = samples[i]; 3040014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int buffer_pos = 0; 3041014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (i > 0) { 3042014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch buffer[buffer_pos++] = ','; 3043014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 3044014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch base::TimeDelta time_delta = sample.timestamp - start_time; 3045014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch buffer_pos = utoa(time_delta.InMicroseconds(), buffer, buffer_pos); 3046014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch buffer[buffer_pos++] = ','; 3047014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch buffer_pos = utoa(sample.last_assigned_id(), buffer, buffer_pos); 3048014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch buffer[buffer_pos++] = '\n'; 3049014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch buffer[buffer_pos++] = '\0'; 3050014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch writer_->AddString(buffer.start()); 3051014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 3052014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 3053014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3054014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshotJSONSerializer::SerializeString(const unsigned char* s) { 3056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddCharacter('\n'); 3057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddCharacter('\"'); 3058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for ( ; *s != '\0'; ++s) { 3059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (*s) { 3060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case '\b': 3061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString("\\b"); 3062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch continue; 3063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case '\f': 3064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString("\\f"); 3065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch continue; 3066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case '\n': 3067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString("\\n"); 3068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch continue; 3069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case '\r': 3070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString("\\r"); 3071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch continue; 3072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case '\t': 3073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString("\\t"); 3074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch continue; 3075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case '\"': 3076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case '\\': 3077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddCharacter('\\'); 3078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddCharacter(*s); 3079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch continue; 3080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 3081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (*s > 31 && *s < 128) { 3082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddCharacter(*s); 3083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (*s <= 31) { 3084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Special character with no dedicated literal. 3085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch WriteUChar(writer_, *s); 3086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 3087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Convert UTF-8 into \u UTF-16 literal. 3088014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch size_t length = 1, cursor = 0; 3089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for ( ; length <= 4 && *(s + length) != '\0'; ++length) { } 3090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unibrow::uchar c = unibrow::Utf8::CalculateValue(s, length, &cursor); 3091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (c != unibrow::Utf8::kBadChar) { 3092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch WriteUChar(writer_, c); 3093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(cursor != 0); 3094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch s += cursor - 1; 3095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 3096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddCharacter('?'); 3097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddCharacter('\"'); 3102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshotJSONSerializer::SerializeStrings() { 3106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ScopedVector<const unsigned char*> sorted_strings( 3107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch strings_.occupancy() + 1); 310813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch for (base::HashMap::Entry* entry = strings_.Start(); entry != NULL; 3109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entry = strings_.Next(entry)) { 3110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int index = static_cast<int>(reinterpret_cast<uintptr_t>(entry->value)); 3111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sorted_strings[index] = reinterpret_cast<const unsigned char*>(entry->key); 3112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString("\"<dummy>\""); 3114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 1; i < sorted_strings.length(); ++i) { 3115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddCharacter(','); 3116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SerializeString(sorted_strings[i]); 3117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (writer_->aborted()) return; 3118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 3123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 3124