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 762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include <utility> 862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/api.h" 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-stubs.h" 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/conversions.h" 12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/debug/debug.h" 1362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/layout-descriptor.h" 14014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/objects-body-descriptors.h" 1562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/objects-inl.h" 16014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/profiler/allocation-tracker.h" 17014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/profiler/heap-profiler.h" 18014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/profiler/heap-snapshot-generator-inl.h" 1962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/prototype.h" 2062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/transitions.h" 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 { 23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal { 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapGraphEdge::HeapGraphEdge(Type type, const char* name, int from, int to) 27958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier : bit_field_(TypeField::encode(type) | FromIndexField::encode(from)), 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch to_index_(to), 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch name_(name) { 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(type == kContextVariable 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch || type == kProperty 32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch || type == kInternal 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch || type == kShortcut 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch || type == kWeak); 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapGraphEdge::HeapGraphEdge(Type type, int index, int from, int to) 39958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier : bit_field_(TypeField::encode(type) | FromIndexField::encode(from)), 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch to_index_(to), 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch index_(index) { 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(type == kElement || type == kHidden); 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapGraphEdge::ReplaceToIndexWithEntry(HeapSnapshot* snapshot) { 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch to_entry_ = &snapshot->entries()[to_index_]; 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst int HeapEntry::kNoEntry = -1; 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapEntry::HeapEntry(HeapSnapshot* snapshot, 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Type type, 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* name, 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SnapshotObjectId id, 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch size_t self_size, 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned trace_node_id) 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : type_(type), 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch children_count_(0), 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch children_index_(-1), 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch self_size_(self_size), 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch snapshot_(snapshot), 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch name_(name), 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch id_(id), 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch trace_node_id_(trace_node_id) { } 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapEntry::SetNamedReference(HeapGraphEdge::Type type, 70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* name, 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* entry) { 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapGraphEdge edge(type, name, this->index(), entry->index()); 7362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch snapshot_->edges().push_back(edge); 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++children_count_; 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapEntry::SetIndexedReference(HeapGraphEdge::Type type, 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int index, 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* entry) { 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapGraphEdge edge(type, index, this->index(), entry->index()); 8262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch snapshot_->edges().push_back(edge); 83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++children_count_; 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapEntry::Print( 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* prefix, const char* edge_name, int max_depth, int indent) { 89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(sizeof(unsigned) == sizeof(id())); 9013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch base::OS::Print("%6" PRIuS " @%6u %*c %s%s: ", self_size(), id(), indent, ' ', 9113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch prefix, edge_name); 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (type() != kString) { 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch base::OS::Print("%s %.40s\n", TypeAsString(), name_); 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch base::OS::Print("\""); 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* c = name_; 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while (*c && (c - name_) <= 40) { 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (*c != '\n') 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch base::OS::Print("%c", *c); 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch else 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch base::OS::Print("\\n"); 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++c; 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch base::OS::Print("\"\n"); 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (--max_depth == 0) return; 10762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch for (auto i = children_begin(); i != children_end(); ++i) { 10862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch HeapGraphEdge& edge = **i; 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* edge_prefix = ""; 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmbeddedVector<char, 64> index; 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* edge_name = index.start(); 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (edge.type()) { 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case HeapGraphEdge::kContextVariable: 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch edge_prefix = "#"; 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch edge_name = edge.name(); 116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case HeapGraphEdge::kElement: 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SNPrintF(index, "%d", edge.index()); 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case HeapGraphEdge::kInternal: 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch edge_prefix = "$"; 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch edge_name = edge.name(); 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case HeapGraphEdge::kProperty: 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch edge_name = edge.name(); 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case HeapGraphEdge::kHidden: 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch edge_prefix = "$"; 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SNPrintF(index, "%d", edge.index()); 130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case HeapGraphEdge::kShortcut: 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch edge_prefix = "^"; 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch edge_name = edge.name(); 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case HeapGraphEdge::kWeak: 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch edge_prefix = "w"; 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch edge_name = edge.name(); 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SNPrintF(index, "!!! unknown edge type: %d ", edge.type()); 141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch edge.to()->Print(edge_prefix, edge_name, max_depth, indent + 2); 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst char* HeapEntry::TypeAsString() { 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (type()) { 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kHidden: return "/hidden/"; 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kObject: return "/object/"; 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kClosure: return "/closure/"; 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kString: return "/string/"; 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kCode: return "/code/"; 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kArray: return "/array/"; 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kRegExp: return "/regexp/"; 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kHeapNumber: return "/number/"; 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kNative: return "/native/"; 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kSynthetic: return "/synthetic/"; 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kConsString: return "/concatenated string/"; 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kSlicedString: return "/sliced string/"; 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case kSymbol: return "/symbol/"; 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: return "???"; 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// It is very important to keep objects that form a heap snapshot 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// as small as possible. 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace { // Avoid littering the global namespace. 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <size_t ptr_size> struct SnapshotSizeConstants; 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <> struct SnapshotSizeConstants<4> { 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kExpectedHeapGraphEdgeSize = 12; 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kExpectedHeapEntrySize = 28; 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <> struct SnapshotSizeConstants<8> { 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kExpectedHeapGraphEdgeSize = 24; 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kExpectedHeapEntrySize = 40; 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} // namespace 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochHeapSnapshot::HeapSnapshot(HeapProfiler* profiler) 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : profiler_(profiler), 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch root_index_(HeapEntry::kNoEntry), 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch gc_roots_index_(HeapEntry::kNoEntry), 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch max_snapshot_js_object_id_(0) { 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT( 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sizeof(HeapGraphEdge) == 193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SnapshotSizeConstants<kPointerSize>::kExpectedHeapGraphEdgeSize); 194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT( 195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sizeof(HeapEntry) == 196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SnapshotSizeConstants<kPointerSize>::kExpectedHeapEntrySize); 197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch USE(SnapshotSizeConstants<4>::kExpectedHeapGraphEdgeSize); 198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch USE(SnapshotSizeConstants<4>::kExpectedHeapEntrySize); 199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch USE(SnapshotSizeConstants<8>::kExpectedHeapGraphEdgeSize); 200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch USE(SnapshotSizeConstants<8>::kExpectedHeapEntrySize); 201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < VisitorSynchronization::kNumberOfSyncTags; ++i) { 202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch gc_subroot_indexes_[i] = HeapEntry::kNoEntry; 203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshot::Delete() { 208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch profiler_->RemoveSnapshot(this); 209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch delete this; 210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshot::RememberLastJSObjectId() { 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch max_snapshot_js_object_id_ = profiler_->heap_object_map()->last_assigned_id(); 215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshot::AddSyntheticRootEntries() { 219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AddRootEntry(); 220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AddGcRootsEntry(); 221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SnapshotObjectId id = HeapObjectsMap::kGcRootsFirstSubrootId; 222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int tag = 0; tag < VisitorSynchronization::kNumberOfSyncTags; tag++) { 223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AddGcSubrootEntry(tag, id); 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch id += HeapObjectsMap::kObjectIdStep; 225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(HeapObjectsMap::kFirstAvailableObjectId == id); 227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapEntry* HeapSnapshot::AddRootEntry() { 231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(root_index_ == HeapEntry::kNoEntry); 232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(entries_.is_empty()); // Root entry must be the first one. 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* entry = AddEntry(HeapEntry::kSynthetic, 234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "", 235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObjectsMap::kInternalRootObjectId, 236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 0, 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 0); 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch root_index_ = entry->index(); 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(root_index_ == 0); 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return entry; 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapEntry* HeapSnapshot::AddGcRootsEntry() { 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(gc_roots_index_ == HeapEntry::kNoEntry); 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* entry = AddEntry(HeapEntry::kSynthetic, 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "(GC roots)", 248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObjectsMap::kGcRootsObjectId, 249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 0, 250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 0); 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch gc_roots_index_ = entry->index(); 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return entry; 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapEntry* HeapSnapshot::AddGcSubrootEntry(int tag, SnapshotObjectId id) { 257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(gc_subroot_indexes_[tag] == HeapEntry::kNoEntry); 258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(0 <= tag && tag < VisitorSynchronization::kNumberOfSyncTags); 259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* entry = AddEntry(HeapEntry::kSynthetic, 260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitorSynchronization::kTagNames[tag], id, 0, 0); 261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch gc_subroot_indexes_[tag] = entry->index(); 262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return entry; 263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type, 267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* name, 268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SnapshotObjectId id, 269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch size_t size, 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned trace_node_id) { 271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry entry(this, type, name, id, size, trace_node_id); 272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_.Add(entry); 273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return &entries_.last(); 274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshot::FillChildren() { 27862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK(children().empty()); 27962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch children().resize(edges().size()); 280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int children_index = 0; 281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < entries().length(); ++i) { 282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* entry = &entries()[i]; 283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch children_index = entry->set_children_index(children_index); 284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 28562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_EQ(edges().size(), static_cast<size_t>(children_index)); 28662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch for (size_t i = 0; i < edges().size(); ++i) { 287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapGraphEdge* edge = &edges()[i]; 288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch edge->ReplaceToIndexWithEntry(this); 289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch edge->from()->add_child(edge); 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass FindEntryById { 295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit FindEntryById(SnapshotObjectId id) : id_(id) { } 297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int operator()(HeapEntry* const* entry) { 298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((*entry)->id() == id_) return 0; 299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return (*entry)->id() < id_ ? -1 : 1; 300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SnapshotObjectId id_; 303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapEntry* HeapSnapshot::GetEntryById(SnapshotObjectId id) { 307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch List<HeapEntry*>* entries_by_id = GetSortedEntriesList(); 308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Perform a binary search by id. 309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int index = SortedListBSearch(*entries_by_id, FindEntryById(id)); 310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (index == -1) 311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return NULL; 312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return entries_by_id->at(index); 313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<class T> 317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic int SortByIds(const T* entry1_ptr, 318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const T* entry2_ptr) { 319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((*entry1_ptr)->id() == (*entry2_ptr)->id()) return 0; 320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return (*entry1_ptr)->id() < (*entry2_ptr)->id() ? -1 : 1; 321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochList<HeapEntry*>* HeapSnapshot::GetSortedEntriesList() { 325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (sorted_entries_.is_empty()) { 326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sorted_entries_.Allocate(entries_.length()); 327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < entries_.length(); ++i) { 328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sorted_entries_[i] = &entries_[i]; 329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 330014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch sorted_entries_.Sort<int (*)(HeapEntry* const*, HeapEntry* const*)>( 331014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SortByIds); 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return &sorted_entries_; 334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshot::Print(int max_depth) { 338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch root()->Print("", "", max_depth, 0); 339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochsize_t HeapSnapshot::RawSnapshotSize() const { 34362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return sizeof(*this) + GetMemoryUsedByList(entries_) + 34462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch edges_.size() * sizeof(decltype(edges_)::value_type) + 34562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch children_.size() * sizeof(decltype(children_)::value_type) + 34662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GetMemoryUsedByList(sorted_entries_); 347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// We split IDs on evens for embedder objects (see 351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// HeapObjectsMap::GenerateId) and odds for native objects. 352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst SnapshotObjectId HeapObjectsMap::kInternalRootObjectId = 1; 353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst SnapshotObjectId HeapObjectsMap::kGcRootsObjectId = 354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObjectsMap::kInternalRootObjectId + HeapObjectsMap::kObjectIdStep; 355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst SnapshotObjectId HeapObjectsMap::kGcRootsFirstSubrootId = 356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObjectsMap::kGcRootsObjectId + HeapObjectsMap::kObjectIdStep; 357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst SnapshotObjectId HeapObjectsMap::kFirstAvailableObjectId = 358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObjectsMap::kGcRootsFirstSubrootId + 359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitorSynchronization::kNumberOfSyncTags * HeapObjectsMap::kObjectIdStep; 360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapObjectsMap::HeapObjectsMap(Heap* heap) 362f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch : next_id_(kFirstAvailableObjectId), heap_(heap) { 363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This dummy element solves a problem with entries_map_. 364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // When we do lookup in HashMap we see no difference between two cases: 365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // it has an entry with NULL as the value or it has created 366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // a new entry on the fly with NULL as the default value. 367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // With such dummy element we have a guaranty that all entries_map_ entries 368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // will have the value field grater than 0. 369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This fact is using in MoveObject method. 370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_.Add(EntryInfo(0, NULL, 0)); 371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool HeapObjectsMap::MoveObject(Address from, Address to, int object_size) { 375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(to != NULL); 376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(from != NULL); 377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (from == to) return false; 378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void* from_value = entries_map_.Remove(from, ComputePointerHash(from)); 379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (from_value == NULL) { 380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // It may occur that some untracked object moves to an address X and there 381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is a tracked object at that address. In this case we should remove the 382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // entry as we know that the object has died. 383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void* to_value = entries_map_.Remove(to, ComputePointerHash(to)); 384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (to_value != NULL) { 385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int to_entry_info_index = 386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<int>(reinterpret_cast<intptr_t>(to_value)); 387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_.at(to_entry_info_index).addr = NULL; 388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 39013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch base::HashMap::Entry* to_entry = 391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch entries_map_.LookupOrInsert(to, ComputePointerHash(to)); 392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (to_entry->value != NULL) { 393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We found the existing entry with to address for an old object. 394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Without this operation we will have two EntryInfo's with the same 395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // value in addr field. It is bad because later at RemoveDeadEntries 396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // one of this entry will be removed with the corresponding entries_map_ 397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // entry. 398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int to_entry_info_index = 399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<int>(reinterpret_cast<intptr_t>(to_entry->value)); 400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_.at(to_entry_info_index).addr = NULL; 401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int from_entry_info_index = 403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<int>(reinterpret_cast<intptr_t>(from_value)); 404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_.at(from_entry_info_index).addr = to; 405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Size of an object can change during its life, so to keep information 406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // about the object in entries_ consistent, we have to adjust size when the 407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // object is migrated. 408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_heap_profiler_trace_objects) { 409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrintF("Move object from %p to %p old size %6d new size %6d\n", 41013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch static_cast<void*>(from), static_cast<void*>(to), 41113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch entries_.at(from_entry_info_index).size, object_size); 412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_.at(from_entry_info_index).size = object_size; 414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch to_entry->value = from_value; 415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return from_value != NULL; 417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapObjectsMap::UpdateObjectSize(Address addr, int size) { 421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FindOrAddEntry(addr, size, false); 422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochSnapshotObjectId HeapObjectsMap::FindEntry(Address addr) { 42613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch base::HashMap::Entry* entry = 42713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch entries_map_.Lookup(addr, ComputePointerHash(addr)); 428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (entry == NULL) return 0; 429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int entry_index = static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); 430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EntryInfo& entry_info = entries_.at(entry_index); 431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy()); 432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return entry_info.id; 433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochSnapshotObjectId HeapObjectsMap::FindOrAddEntry(Address addr, 437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned int size, 438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool accessed) { 439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy()); 44013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch base::HashMap::Entry* entry = 441014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch entries_map_.LookupOrInsert(addr, ComputePointerHash(addr)); 442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (entry->value != NULL) { 443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int entry_index = 444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); 445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EntryInfo& entry_info = entries_.at(entry_index); 446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entry_info.accessed = accessed; 447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_heap_profiler_trace_objects) { 448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrintF("Update object size : %p with old size %d and new size %d\n", 44913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch static_cast<void*>(addr), entry_info.size, size); 450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entry_info.size = size; 452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return entry_info.id; 453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entry->value = reinterpret_cast<void*>(entries_.length()); 455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SnapshotObjectId id = next_id_; 456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch next_id_ += kObjectIdStep; 457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_.Add(EntryInfo(id, addr, size, accessed)); 458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(static_cast<uint32_t>(entries_.length()) > entries_map_.occupancy()); 459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return id; 460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapObjectsMap::StopHeapObjectsTracking() { 464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch time_intervals_.Clear(); 465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapObjectsMap::UpdateHeapObjectsMap() { 469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_heap_profiler_trace_objects) { 470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrintF("Begin HeapObjectsMap::UpdateHeapObjectsMap. map has %d entries.\n", 471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_map_.occupancy()); 472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap_->CollectAllGarbage(Heap::kMakeHeapIterableMask, 474f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GarbageCollectionReason::kHeapProfiler); 475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapIterator iterator(heap_); 476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (HeapObject* obj = iterator.next(); 477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch obj != NULL; 478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch obj = iterator.next()) { 479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FindOrAddEntry(obj->address(), obj->Size()); 480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_heap_profiler_trace_objects) { 481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrintF("Update object : %p %6d. Next address is %p\n", 48213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch static_cast<void*>(obj->address()), obj->Size(), 48313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch static_cast<void*>(obj->address() + obj->Size())); 484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RemoveDeadEntries(); 487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_heap_profiler_trace_objects) { 488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrintF("End HeapObjectsMap::UpdateHeapObjectsMap. map has %d entries.\n", 489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_map_.occupancy()); 490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace { 495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstruct HeapObjectInfo { 498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObjectInfo(HeapObject* obj, int expected_size) 499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : obj(obj), 500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch expected_size(expected_size) { 501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObject* obj; 504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int expected_size; 505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool IsValid() const { return expected_size == obj->Size(); } 507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Print() const { 509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expected_size == 0) { 510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrintF("Untracked object : %p %6d. Next address is %p\n", 51113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch static_cast<void*>(obj->address()), obj->Size(), 51213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch static_cast<void*>(obj->address() + obj->Size())); 513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->Size() != expected_size) { 51413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch PrintF("Wrong size %6d: %p %6d. Next address is %p\n", expected_size, 51513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch static_cast<void*>(obj->address()), obj->Size(), 51613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch static_cast<void*>(obj->address() + obj->Size())); 517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrintF("Good object : %p %6d. Next address is %p\n", 51913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch static_cast<void*>(obj->address()), expected_size, 52013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch static_cast<void*>(obj->address() + obj->Size())); 521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic int comparator(const HeapObjectInfo* a, const HeapObjectInfo* b) { 527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (a->obj < b->obj) return -1; 528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (a->obj > b->obj) return 1; 529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 0; 530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} // namespace 534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint HeapObjectsMap::FindUntrackedObjects() { 537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch List<HeapObjectInfo> heap_objects(1000); 538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapIterator iterator(heap_); 540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int untracked = 0; 541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (HeapObject* obj = iterator.next(); 542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch obj != NULL; 543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch obj = iterator.next()) { 54413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch base::HashMap::Entry* entry = 545014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch entries_map_.Lookup(obj->address(), ComputePointerHash(obj->address())); 546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (entry == NULL) { 547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++untracked; 548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_heap_profiler_trace_objects) { 549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap_objects.Add(HeapObjectInfo(obj, 0)); 550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int entry_index = static_cast<int>( 553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<intptr_t>(entry->value)); 554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EntryInfo& entry_info = entries_.at(entry_index); 555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_heap_profiler_trace_objects) { 556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap_objects.Add(HeapObjectInfo(obj, 557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<int>(entry_info.size))); 558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (obj->Size() != static_cast<int>(entry_info.size)) 559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++untracked; 560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK_EQ(obj->Size(), static_cast<int>(entry_info.size)); 562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_heap_profiler_trace_objects) { 566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrintF("\nBegin HeapObjectsMap::FindUntrackedObjects. %d entries in map.\n", 567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_map_.occupancy()); 568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap_objects.Sort(comparator); 569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int last_printed_object = -1; 570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool print_next_object = false; 571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < heap_objects.length(); ++i) { 572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const HeapObjectInfo& object_info = heap_objects[i]; 573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!object_info.IsValid()) { 574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++untracked; 575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (last_printed_object != i - 1) { 576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (i > 0) { 577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrintF("%d objects were skipped\n", i - 1 - last_printed_object); 578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap_objects[i - 1].Print(); 579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch object_info.Print(); 582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch last_printed_object = i; 583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch print_next_object = true; 584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (print_next_object) { 585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch object_info.Print(); 586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch print_next_object = false; 587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch last_printed_object = i; 588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (last_printed_object < heap_objects.length() - 1) { 591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrintF("Last %d objects were skipped\n", 592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap_objects.length() - 1 - last_printed_object); 593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrintF("End HeapObjectsMap::FindUntrackedObjects. %d entries in map.\n\n", 595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_map_.occupancy()); 596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return untracked; 598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 601014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochSnapshotObjectId HeapObjectsMap::PushHeapObjectsStats(OutputStream* stream, 602014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int64_t* timestamp_us) { 603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UpdateHeapObjectsMap(); 604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch time_intervals_.Add(TimeInterval(next_id_)); 605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int prefered_chunk_size = stream->GetChunkSize(); 606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch List<v8::HeapStatsUpdate> stats_buffer; 607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!entries_.is_empty()); 608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EntryInfo* entry_info = &entries_.first(); 609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EntryInfo* end_entry_info = &entries_.last() + 1; 610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int time_interval_index = 0; 611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch time_interval_index < time_intervals_.length(); 612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++time_interval_index) { 613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TimeInterval& time_interval = time_intervals_[time_interval_index]; 614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SnapshotObjectId time_interval_id = time_interval.id; 615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t entries_size = 0; 616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EntryInfo* start_entry_info = entry_info; 617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while (entry_info < end_entry_info && entry_info->id < time_interval_id) { 618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_size += entry_info->size; 619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++entry_info; 620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t entries_count = 622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<uint32_t>(entry_info - start_entry_info); 623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (time_interval.count != entries_count || 624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch time_interval.size != entries_size) { 625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stats_buffer.Add(v8::HeapStatsUpdate( 626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch time_interval_index, 627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch time_interval.count = entries_count, 628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch time_interval.size = entries_size)); 629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (stats_buffer.length() >= prefered_chunk_size) { 630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OutputStream::WriteResult result = stream->WriteHeapStatsChunk( 631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &stats_buffer.first(), stats_buffer.length()); 632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (result == OutputStream::kAbort) return last_assigned_id(); 633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stats_buffer.Clear(); 634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(entry_info == end_entry_info); 638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!stats_buffer.is_empty()) { 639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OutputStream::WriteResult result = stream->WriteHeapStatsChunk( 640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &stats_buffer.first(), stats_buffer.length()); 641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (result == OutputStream::kAbort) return last_assigned_id(); 642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stream->EndOfStream(); 644014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (timestamp_us) { 645014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch *timestamp_us = (time_intervals_.last().timestamp - 646014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch time_intervals_[0].timestamp).InMicroseconds(); 647014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return last_assigned_id(); 649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapObjectsMap::RemoveDeadEntries() { 653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(entries_.length() > 0 && 654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_.at(0).id == 0 && 655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_.at(0).addr == NULL); 656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int first_free_entry = 1; 657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 1; i < entries_.length(); ++i) { 658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EntryInfo& entry_info = entries_.at(i); 659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (entry_info.accessed) { 660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (first_free_entry != i) { 661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_.at(first_free_entry) = entry_info; 662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_.at(first_free_entry).accessed = false; 66413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch base::HashMap::Entry* entry = entries_map_.Lookup( 665014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch entry_info.addr, ComputePointerHash(entry_info.addr)); 666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(entry); 667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entry->value = reinterpret_cast<void*>(first_free_entry); 668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++first_free_entry; 669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (entry_info.addr) { 671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_map_.Remove(entry_info.addr, 672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ComputePointerHash(entry_info.addr)); 673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_.Rewind(first_free_entry); 677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(static_cast<uint32_t>(entries_.length()) - 1 == 678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_map_.occupancy()); 679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochSnapshotObjectId HeapObjectsMap::GenerateId(v8::RetainedObjectInfo* info) { 683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SnapshotObjectId id = static_cast<SnapshotObjectId>(info->GetHash()); 684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* label = info->GetLabel(); 685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch id ^= StringHasher::HashSequentialString(label, 686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<int>(strlen(label)), 687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap_->HashSeed()); 688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch intptr_t element_count = info->GetElementCount(); 689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (element_count != -1) 690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch id ^= ComputeIntegerHash(static_cast<uint32_t>(element_count), 691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::internal::kZeroHashSeed); 692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return id << 1; 693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochsize_t HeapObjectsMap::GetUsedMemorySize() const { 69713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return sizeof(*this) + 69813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch sizeof(base::HashMap::Entry) * entries_map_.capacity() + 69913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch GetMemoryUsedByList(entries_) + GetMemoryUsedByList(time_intervals_); 700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 702f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochHeapEntriesMap::HeapEntriesMap() : entries_() {} 703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint HeapEntriesMap::Map(HeapThing thing) { 70513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch base::HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing)); 706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (cache_entry == NULL) return HeapEntry::kNoEntry; 707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); 708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapEntriesMap::Pair(HeapThing thing, int entry) { 71213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch base::HashMap::Entry* cache_entry = 71313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch entries_.LookupOrInsert(thing, Hash(thing)); 714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(cache_entry->value == NULL); 715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cache_entry->value = reinterpret_cast<void*>(static_cast<intptr_t>(entry)); 716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 718f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochHeapObjectsSet::HeapObjectsSet() : entries_() {} 719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapObjectsSet::Clear() { 721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_.Clear(); 722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool HeapObjectsSet::Contains(Object* obj) { 726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!obj->IsHeapObject()) return false; 727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObject* object = HeapObject::cast(obj); 728014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return entries_.Lookup(object, HeapEntriesMap::Hash(object)) != NULL; 729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapObjectsSet::Insert(Object* obj) { 733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!obj->IsHeapObject()) return; 734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObject* object = HeapObject::cast(obj); 735014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch entries_.LookupOrInsert(object, HeapEntriesMap::Hash(object)); 736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst char* HeapObjectsSet::GetTag(Object* obj) { 740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObject* object = HeapObject::cast(obj); 74113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch base::HashMap::Entry* cache_entry = 742014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch entries_.Lookup(object, HeapEntriesMap::Hash(object)); 743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return cache_entry != NULL 744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? reinterpret_cast<const char*>(cache_entry->value) 745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : NULL; 746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 749f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochV8_NOINLINE void HeapObjectsSet::SetTag(Object* obj, const char* tag) { 750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!obj->IsHeapObject()) return; 751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObject* object = HeapObject::cast(obj); 75213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch base::HashMap::Entry* cache_entry = 753014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch entries_.LookupOrInsert(object, HeapEntriesMap::Hash(object)); 754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cache_entry->value = const_cast<char*>(tag); 755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochV8HeapExplorer::V8HeapExplorer( 759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapSnapshot* snapshot, 760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SnapshottingProgressReportingInterface* progress, 761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::HeapProfiler::ObjectNameResolver* resolver) 762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : heap_(snapshot->profiler()->heap_object_map()->heap()), 763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch snapshot_(snapshot), 764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch names_(snapshot_->profiler()->names()), 765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap_object_map_(snapshot_->profiler()->heap_object_map()), 766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch progress_(progress), 767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_(NULL), 768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch global_object_name_resolver_(resolver) { 769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochV8HeapExplorer::~V8HeapExplorer() { 773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapEntry* V8HeapExplorer::AllocateEntry(HeapThing ptr) { 777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return AddEntry(reinterpret_cast<HeapObject*>(ptr)); 778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapEntry* V8HeapExplorer::AddEntry(HeapObject* object) { 782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (object->IsJSFunction()) { 783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSFunction* func = JSFunction::cast(object); 784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SharedFunctionInfo* shared = func->shared(); 785014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const char* name = names_->GetName(String::cast(shared->name())); 786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return AddEntry(object, HeapEntry::kClosure, name); 787014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else if (object->IsJSBoundFunction()) { 788014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return AddEntry(object, HeapEntry::kClosure, "native_bind"); 789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (object->IsJSRegExp()) { 790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSRegExp* re = JSRegExp::cast(object); 791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return AddEntry(object, 792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry::kRegExp, 793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch names_->GetName(re->Pattern())); 794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (object->IsJSObject()) { 795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* name = names_->GetName( 796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GetConstructorName(JSObject::cast(object))); 797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (object->IsJSGlobalObject()) { 798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* tag = objects_tags_.GetTag(object); 799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (tag != NULL) { 800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch name = names_->GetFormatted("%s / %s", name, tag); 801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return AddEntry(object, HeapEntry::kObject, name); 804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (object->IsString()) { 805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch String* string = String::cast(object); 806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (string->IsConsString()) 807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return AddEntry(object, 808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry::kConsString, 809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "(concatenated string)"); 810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (string->IsSlicedString()) 811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return AddEntry(object, 812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry::kSlicedString, 813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "(sliced string)"); 814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return AddEntry(object, 815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry::kString, 816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch names_->GetName(String::cast(object))); 817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (object->IsSymbol()) { 818014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (Symbol::cast(object)->is_private()) 819014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return AddEntry(object, HeapEntry::kHidden, "private symbol"); 820014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch else 821014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return AddEntry(object, HeapEntry::kSymbol, "symbol"); 822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (object->IsCode()) { 823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return AddEntry(object, HeapEntry::kCode, ""); 824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (object->IsSharedFunctionInfo()) { 825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch String* name = String::cast(SharedFunctionInfo::cast(object)->name()); 826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return AddEntry(object, 827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry::kCode, 828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch names_->GetName(name)); 829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (object->IsScript()) { 830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object* name = Script::cast(object)->name(); 831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return AddEntry(object, 832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry::kCode, 833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch name->IsString() 834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? names_->GetName(String::cast(name)) 835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : ""); 836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (object->IsNativeContext()) { 837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return AddEntry(object, HeapEntry::kHidden, "system / NativeContext"); 838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (object->IsContext()) { 839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return AddEntry(object, HeapEntry::kObject, "system / Context"); 840014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else if (object->IsFixedArray() || object->IsFixedDoubleArray() || 841014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch object->IsByteArray()) { 842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return AddEntry(object, HeapEntry::kArray, ""); 843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (object->IsHeapNumber()) { 844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return AddEntry(object, HeapEntry::kHeapNumber, "number"); 845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return AddEntry(object, HeapEntry::kHidden, GetSystemEntryName(object)); 847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapEntry* V8HeapExplorer::AddEntry(HeapObject* object, 851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry::Type type, 852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* name) { 853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return AddEntry(object->address(), type, name, object->Size()); 854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapEntry* V8HeapExplorer::AddEntry(Address address, 858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry::Type type, 859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* name, 860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch size_t size) { 861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SnapshotObjectId object_id = heap_object_map_->FindOrAddEntry( 862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch address, static_cast<unsigned int>(size)); 863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned trace_node_id = 0; 864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (AllocationTracker* allocation_tracker = 865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch snapshot_->profiler()->allocation_tracker()) { 866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch trace_node_id = 867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch allocation_tracker->address_to_trace()->GetTraceNodeId(address); 868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return snapshot_->AddEntry(type, name, object_id, size, trace_node_id); 870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass SnapshotFiller { 874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries) 876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : snapshot_(snapshot), 877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch names_(snapshot->profiler()->names()), 878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_(entries) { } 879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) { 880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* entry = allocator->AllocateEntry(ptr); 881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entries_->Pair(ptr, entry->index()); 882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return entry; 883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* FindEntry(HeapThing ptr) { 885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int index = entries_->Map(ptr); 886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return index != HeapEntry::kNoEntry ? &snapshot_->entries()[index] : NULL; 887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* FindOrAddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) { 889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* entry = FindEntry(ptr); 890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return entry != NULL ? entry : AddEntry(ptr, allocator); 891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void SetIndexedReference(HeapGraphEdge::Type type, 893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int parent, 894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int index, 895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* child_entry) { 896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* parent_entry = &snapshot_->entries()[parent]; 897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch parent_entry->SetIndexedReference(type, index, child_entry); 898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void SetIndexedAutoIndexReference(HeapGraphEdge::Type type, 900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int parent, 901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* child_entry) { 902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* parent_entry = &snapshot_->entries()[parent]; 903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int index = parent_entry->children_count() + 1; 904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch parent_entry->SetIndexedReference(type, index, child_entry); 905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void SetNamedReference(HeapGraphEdge::Type type, 907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int parent, 908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* reference_name, 909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* child_entry) { 910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* parent_entry = &snapshot_->entries()[parent]; 911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch parent_entry->SetNamedReference(type, reference_name, child_entry); 912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void SetNamedAutoIndexReference(HeapGraphEdge::Type type, 914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int parent, 915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* child_entry) { 916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* parent_entry = &snapshot_->entries()[parent]; 917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int index = parent_entry->children_count() + 1; 918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch parent_entry->SetNamedReference( 919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch type, 920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch names_->GetName(index), 921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch child_entry); 922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapSnapshot* snapshot_; 926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StringsStorage* names_; 927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntriesMap* entries_; 928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst char* V8HeapExplorer::GetSystemEntryName(HeapObject* object) { 932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (object->map()->instance_type()) { 933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case MAP_TYPE: 934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (Map::cast(object)->instance_type()) { 935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define MAKE_STRING_MAP_CASE(instance_type, size, name, Name) \ 936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case instance_type: return "system / Map (" #Name ")"; 937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STRING_TYPE_LIST(MAKE_STRING_MAP_CASE) 938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef MAKE_STRING_MAP_CASE 939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: return "system / Map"; 940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case CELL_TYPE: return "system / Cell"; 942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case PROPERTY_CELL_TYPE: return "system / PropertyCell"; 943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case FOREIGN_TYPE: return "system / Foreign"; 944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case ODDBALL_TYPE: return "system / Oddball"; 945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define MAKE_STRUCT_CASE(NAME, Name, name) \ 946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case NAME##_TYPE: return "system / "#Name; 947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STRUCT_LIST(MAKE_STRUCT_CASE) 948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef MAKE_STRUCT_CASE 949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: return "system"; 950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint V8HeapExplorer::EstimateObjectsCount(HeapIterator* iterator) { 955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int objects_count = 0; 956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (HeapObject* obj = iterator->next(); 957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch obj != NULL; 958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch obj = iterator->next()) { 959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch objects_count++; 960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return objects_count; 962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass IndexedReferencesExtractor : public ObjectVisitor { 966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 967014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch IndexedReferencesExtractor(V8HeapExplorer* generator, HeapObject* parent_obj, 968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int parent) 969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : generator_(generator), 970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch parent_obj_(parent_obj), 971014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch parent_start_(HeapObject::RawField(parent_obj_, 0)), 972014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch parent_end_(HeapObject::RawField(parent_obj_, parent_obj_->Size())), 973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch parent_(parent), 974014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch next_index_(0) {} 975014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void VisitCodeEntry(Address entry_address) override { 976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code* code = Code::cast(Code::GetObjectFromEntryAddress(entry_address)); 977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch generator_->SetInternalReference(parent_obj_, parent_, "code", code); 978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch generator_->TagCodeObject(code); 979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 980014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void VisitPointers(Object** start, Object** end) override { 981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (Object** p = start; p < end; p++) { 982f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch int index = static_cast<int>(p - HeapObject::RawField(parent_obj_, 0)); 983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++next_index_; 984014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // |p| could be outside of the object, e.g., while visiting RelocInfo of 985014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // code objects. 986014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (p >= parent_start_ && p < parent_end_ && generator_->marks_[index]) { 987014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch generator_->marks_[index] = false; 988014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch continue; 989014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 990f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch generator_->SetHiddenReference(parent_obj_, parent_, next_index_, *p, 991f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch index * kPointerSize); 992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch V8HeapExplorer* generator_; 997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObject* parent_obj_; 998014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Object** parent_start_; 999014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Object** parent_end_; 1000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int parent_; 1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int next_index_; 1002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 1003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool V8HeapExplorer::ExtractReferencesPass1(int entry, HeapObject* obj) { 1006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (obj->IsFixedArray()) return false; // FixedArrays are processed on pass 2 1007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (obj->IsJSGlobalProxy()) { 1009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractJSGlobalProxyReferences(entry, JSGlobalProxy::cast(obj)); 1010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsJSArrayBuffer()) { 1011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractJSArrayBufferReferences(entry, JSArrayBuffer::cast(obj)); 1012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsJSObject()) { 1013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (obj->IsJSWeakSet()) { 1014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractJSWeakCollectionReferences(entry, JSWeakSet::cast(obj)); 1015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsJSWeakMap()) { 1016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractJSWeakCollectionReferences(entry, JSWeakMap::cast(obj)); 1017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsJSSet()) { 1018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractJSCollectionReferences(entry, JSSet::cast(obj)); 1019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsJSMap()) { 1020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractJSCollectionReferences(entry, JSMap::cast(obj)); 1021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractJSObjectReferences(entry, JSObject::cast(obj)); 1023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsString()) { 1024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractStringReferences(entry, String::cast(obj)); 1025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsSymbol()) { 1026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractSymbolReferences(entry, Symbol::cast(obj)); 1027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsMap()) { 1028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractMapReferences(entry, Map::cast(obj)); 1029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsSharedFunctionInfo()) { 1030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractSharedFunctionInfoReferences(entry, SharedFunctionInfo::cast(obj)); 1031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsScript()) { 1032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractScriptReferences(entry, Script::cast(obj)); 1033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsAccessorInfo()) { 1034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractAccessorInfoReferences(entry, AccessorInfo::cast(obj)); 1035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsAccessorPair()) { 1036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractAccessorPairReferences(entry, AccessorPair::cast(obj)); 1037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsCode()) { 1038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractCodeReferences(entry, Code::cast(obj)); 1039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsCell()) { 1040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractCellReferences(entry, Cell::cast(obj)); 1041f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } else if (obj->IsWeakCell()) { 1042f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ExtractWeakCellReferences(entry, WeakCell::cast(obj)); 1043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsPropertyCell()) { 1044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractPropertyCellReferences(entry, PropertyCell::cast(obj)); 1045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsAllocationSite()) { 1046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractAllocationSiteReferences(entry, AllocationSite::cast(obj)); 1047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return true; 1049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool V8HeapExplorer::ExtractReferencesPass2(int entry, HeapObject* obj) { 1053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!obj->IsFixedArray()) return false; 1054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (obj->IsContext()) { 1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractContextReferences(entry, Context::cast(obj)); 1057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractFixedArrayReferences(entry, FixedArray::cast(obj)); 1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return true; 1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractJSGlobalProxyReferences( 1065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int entry, JSGlobalProxy* proxy) { 1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(proxy, entry, 1067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "native_context", proxy->native_context(), 1068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSGlobalProxy::kNativeContextOffset); 1069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractJSObjectReferences( 1073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int entry, JSObject* js_obj) { 1074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObject* obj = js_obj; 1075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractPropertyReferences(js_obj, entry); 1076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractElementReferences(js_obj, entry); 1077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtractInternalReferences(js_obj, entry); 1078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrototypeIterator iter(heap_->isolate(), js_obj); 1079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetPropertyReference(obj, entry, heap_->proto_string(), iter.GetCurrent()); 1080014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (obj->IsJSBoundFunction()) { 1081014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JSBoundFunction* js_fun = JSBoundFunction::cast(obj); 1082014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TagObject(js_fun->bound_arguments(), "(bound arguments)"); 1083014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetInternalReference(js_fun, entry, "bindings", js_fun->bound_arguments(), 1084014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JSBoundFunction::kBoundArgumentsOffset); 1085f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetInternalReference(js_obj, entry, "bound_this", js_fun->bound_this(), 1086f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch JSBoundFunction::kBoundThisOffset); 1087f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetInternalReference(js_obj, entry, "bound_function", 1088f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch js_fun->bound_target_function(), 1089f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch JSBoundFunction::kBoundTargetFunctionOffset); 1090014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FixedArray* bindings = js_fun->bound_arguments(); 1091014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (int i = 0; i < bindings->length(); i++) { 1092014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const char* reference_name = names_->GetFormatted("bound_argument_%d", i); 1093014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetNativeBindReference(js_obj, entry, reference_name, bindings->get(i)); 1094014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1095014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else if (obj->IsJSFunction()) { 1096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSFunction* js_fun = JSFunction::cast(js_obj); 1097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object* proto_or_map = js_fun->prototype_or_initial_map(); 109813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (!proto_or_map->IsTheHole(heap_->isolate())) { 1099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!proto_or_map->IsMap()) { 1100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetPropertyReference( 1101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch obj, entry, 1102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap_->prototype_string(), proto_or_map, 1103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NULL, 1104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSFunction::kPrototypeOrInitialMapOffset); 1105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetPropertyReference( 1107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch obj, entry, 1108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap_->prototype_string(), js_fun->prototype()); 1109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference( 1110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch obj, entry, "initial_map", proto_or_map, 1111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSFunction::kPrototypeOrInitialMapOffset); 1112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SharedFunctionInfo* shared_info = js_fun->shared(); 111562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch TagObject(js_fun->feedback_vector_cell(), 111662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch "(function feedback vector cell)"); 111762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SetInternalReference(js_fun, entry, "feedback_vector_cell", 111862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch js_fun->feedback_vector_cell(), 111962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch JSFunction::kFeedbackVectorOffset); 1120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(shared_info, "(shared function info)"); 1121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(js_fun, entry, 1122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "shared", shared_info, 1123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSFunction::kSharedFunctionInfoOffset); 1124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(js_fun->context(), "(context)"); 1125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(js_fun, entry, 1126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "context", js_fun->context(), 1127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSFunction::kContextOffset); 1128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Ensure no new weak references appeared in JSFunction. 1129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(JSFunction::kCodeEntryOffset == 1130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JSFunction::kNonWeakFieldsEndOffset); 1131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(JSFunction::kCodeEntryOffset + kPointerSize == 1132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JSFunction::kNextFunctionLinkOffset); 1133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(JSFunction::kNextFunctionLinkOffset + kPointerSize 1134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch == JSFunction::kSize); 1135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else if (obj->IsJSGlobalObject()) { 1136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JSGlobalObject* global_obj = JSGlobalObject::cast(obj); 1137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetInternalReference(global_obj, entry, "native_context", 1138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch global_obj->native_context(), 1139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JSGlobalObject::kNativeContextOffset); 1140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetInternalReference(global_obj, entry, "global_proxy", 1141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch global_obj->global_proxy(), 1142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JSGlobalObject::kGlobalProxyOffset); 1143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(JSGlobalObject::kSize - JSObject::kHeaderSize == 1144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2 * kPointerSize); 1145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (obj->IsJSArrayBufferView()) { 1146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSArrayBufferView* view = JSArrayBufferView::cast(obj); 1147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(view, entry, "buffer", view->buffer(), 1148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSArrayBufferView::kBufferOffset); 1149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(js_obj->properties(), "(object properties)"); 1151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(obj, entry, 1152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "properties", js_obj->properties(), 1153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSObject::kPropertiesOffset); 1154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(js_obj->elements(), "(object elements)"); 1155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(obj, entry, 1156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "elements", js_obj->elements(), 1157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSObject::kElementsOffset); 1158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractStringReferences(int entry, String* string) { 1162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (string->IsConsString()) { 1163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ConsString* cs = ConsString::cast(string); 1164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(cs, entry, "first", cs->first(), 1165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ConsString::kFirstOffset); 1166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(cs, entry, "second", cs->second(), 1167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ConsString::kSecondOffset); 1168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (string->IsSlicedString()) { 1169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SlicedString* ss = SlicedString::cast(string); 1170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(ss, entry, "parent", ss->parent(), 1171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SlicedString::kParentOffset); 117262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } else if (string->IsThinString()) { 117362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ThinString* ts = ThinString::cast(string); 117462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch SetInternalReference(ts, entry, "actual", ts->actual(), 117562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ThinString::kActualOffset); 1176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractSymbolReferences(int entry, Symbol* symbol) { 1181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(symbol, entry, 1182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "name", symbol->name(), 1183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Symbol::kNameOffset); 1184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractJSCollectionReferences(int entry, 1188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSCollection* collection) { 1189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(collection, entry, "table", collection->table(), 1190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSCollection::kTableOffset); 1191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1193f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid V8HeapExplorer::ExtractJSWeakCollectionReferences(int entry, 1194f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch JSWeakCollection* obj) { 1195f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (obj->table()->IsHashTable()) { 1196f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch ObjectHashTable* table = ObjectHashTable::cast(obj->table()); 1197f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch TagFixedArraySubType(table, JS_WEAK_COLLECTION_SUB_TYPE); 1198f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1199f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetInternalReference(obj, entry, "table", obj->table(), 1200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSWeakCollection::kTableOffset); 1201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractContextReferences(int entry, Context* context) { 1204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (context == context->declaration_context()) { 1205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ScopeInfo* scope_info = context->closure()->shared()->scope_info(); 1206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Add context allocated locals. 1207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int context_locals = scope_info->ContextLocalCount(); 1208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < context_locals; ++i) { 1209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch String* local_name = scope_info->ContextLocalName(i); 1210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int idx = Context::MIN_CONTEXT_SLOTS + i; 1211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetContextReference(context, entry, local_name, context->get(idx), 1212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Context::OffsetOfElementAt(idx)); 1213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (scope_info->HasFunctionName()) { 1215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch String* name = scope_info->FunctionName(); 1216f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch int idx = scope_info->FunctionContextSlotIndex(name); 1217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (idx >= 0) { 1218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetContextReference(context, entry, name, context->get(idx), 1219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Context::OffsetOfElementAt(idx)); 1220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define EXTRACT_CONTEXT_FIELD(index, type, name) \ 1225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (Context::index < Context::FIRST_WEAK_SLOT || \ 1226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Context::index == Context::MAP_CACHE_INDEX) { \ 1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(context, entry, #name, context->get(Context::index), \ 1228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FixedArray::OffsetOfElementAt(Context::index)); \ 1229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { \ 1230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetWeakReference(context, entry, #name, context->get(Context::index), \ 1231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FixedArray::OffsetOfElementAt(Context::index)); \ 1232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EXTRACT_CONTEXT_FIELD(CLOSURE_INDEX, JSFunction, closure); 1234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EXTRACT_CONTEXT_FIELD(PREVIOUS_INDEX, Context, previous); 1235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EXTRACT_CONTEXT_FIELD(EXTENSION_INDEX, HeapObject, extension); 1236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EXTRACT_CONTEXT_FIELD(NATIVE_CONTEXT_INDEX, Context, native_context); 1237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (context->IsNativeContext()) { 1238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(context->normalized_map_cache(), "(context norm. map cache)"); 1239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(context->embedder_data(), "(context data)"); 1240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch NATIVE_CONTEXT_FIELDS(EXTRACT_CONTEXT_FIELD) 1241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EXTRACT_CONTEXT_FIELD(OPTIMIZED_FUNCTIONS_LIST, unused, 1242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch optimized_functions_list); 1243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EXTRACT_CONTEXT_FIELD(OPTIMIZED_CODE_LIST, unused, optimized_code_list); 1244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EXTRACT_CONTEXT_FIELD(DEOPTIMIZED_CODE_LIST, unused, deoptimized_code_list); 1245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef EXTRACT_CONTEXT_FIELD 1246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(Context::OPTIMIZED_FUNCTIONS_LIST == 1247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Context::FIRST_WEAK_SLOT); 1248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(Context::NEXT_CONTEXT_LINK + 1 == 1249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Context::NATIVE_CONTEXT_SLOTS); 1250958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier STATIC_ASSERT(Context::FIRST_WEAK_SLOT + 4 == 1251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Context::NATIVE_CONTEXT_SLOTS); 1252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractMapReferences(int entry, Map* map) { 1257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Object* raw_transitions_or_prototype_info = map->raw_transitions(); 1258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (TransitionArray::IsFullTransitionArray( 1259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch raw_transitions_or_prototype_info)) { 1260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TransitionArray* transitions = 1261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TransitionArray::cast(raw_transitions_or_prototype_info); 1262f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (map->CanTransition() && transitions->HasPrototypeTransitions()) { 1263f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch TagObject(transitions->GetPrototypeTransitions(), 1264f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch "(prototype transitions)"); 1265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(transitions, "(transition array)"); 1268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetInternalReference(map, entry, "transitions", transitions, 1269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Map::kTransitionsOrPrototypeInfoOffset); 1270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else if (TransitionArray::IsSimpleTransition( 1271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch raw_transitions_or_prototype_info)) { 1272014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TagObject(raw_transitions_or_prototype_info, "(transition)"); 1273014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetInternalReference(map, entry, "transition", 1274014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch raw_transitions_or_prototype_info, 1275014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Map::kTransitionsOrPrototypeInfoOffset); 1276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else if (map->is_prototype_map()) { 1277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TagObject(raw_transitions_or_prototype_info, "prototype_info"); 1278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetInternalReference(map, entry, "prototype_info", 1279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch raw_transitions_or_prototype_info, 1280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Map::kTransitionsOrPrototypeInfoOffset); 1281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DescriptorArray* descriptors = map->instance_descriptors(); 1283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(descriptors, "(map descriptors)"); 1284f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetInternalReference(map, entry, "descriptors", descriptors, 1285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Map::kDescriptorsOffset); 1286f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetInternalReference(map, entry, "code_cache", map->code_cache(), 1287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Map::kCodeCacheOffset); 1288f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetInternalReference(map, entry, "prototype", map->prototype(), 1289f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Map::kPrototypeOffset); 1290f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#if V8_DOUBLE_FIELDS_UNBOXING 1291f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (FLAG_unbox_double_fields) { 1292f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetInternalReference(map, entry, "layout_descriptor", 1293f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch map->layout_descriptor(), 1294f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Map::kLayoutDescriptorOffset); 1295f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1296f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#endif 1297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Object* constructor_or_backpointer = map->constructor_or_backpointer(); 1298014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (constructor_or_backpointer->IsMap()) { 1299014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TagObject(constructor_or_backpointer, "(back pointer)"); 1300014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetInternalReference(map, entry, "back_pointer", constructor_or_backpointer, 1301014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Map::kConstructorOrBackPointerOffset); 1302014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 1303014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetInternalReference(map, entry, "constructor", constructor_or_backpointer, 1304014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Map::kConstructorOrBackPointerOffset); 1305014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(map->dependent_code(), "(dependent code)"); 1307f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetInternalReference(map, entry, "dependent_code", map->dependent_code(), 1308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Map::kDependentCodeOffset); 1309f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch TagObject(map->weak_cell_cache(), "(weak cell)"); 1310f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetInternalReference(map, entry, "weak_cell_cache", map->weak_cell_cache(), 1311f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Map::kWeakCellCacheOffset); 1312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractSharedFunctionInfoReferences( 1316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int entry, SharedFunctionInfo* shared) { 1317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObject* obj = shared; 1318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch String* shared_name = shared->DebugName(); 1319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* name = NULL; 1320c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch if (shared_name != heap_->empty_string()) { 1321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch name = names_->GetName(shared_name); 1322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(shared->code(), names_->GetFormatted("(code for %s)", name)); 1323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(shared->code(), names_->GetFormatted("(%s code)", 1325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code::Kind2String(shared->code()->kind()))); 1326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(obj, entry, 1329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "name", shared->name(), 1330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SharedFunctionInfo::kNameOffset); 1331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(obj, entry, 1332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "code", shared->code(), 1333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SharedFunctionInfo::kCodeOffset); 1334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(shared->scope_info(), "(function scope info)"); 1335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(obj, entry, 1336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "scope_info", shared->scope_info(), 1337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SharedFunctionInfo::kScopeInfoOffset); 1338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(obj, entry, 1339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "instance_class_name", shared->instance_class_name(), 1340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SharedFunctionInfo::kInstanceClassNameOffset); 1341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(obj, entry, 1342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "script", shared->script(), 1343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SharedFunctionInfo::kScriptOffset); 1344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* construct_stub_name = name ? 1345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch names_->GetFormatted("(construct stub code for %s)", name) : 1346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "(construct stub code)"; 1347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(shared->construct_stub(), construct_stub_name); 1348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(obj, entry, 1349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "construct_stub", shared->construct_stub(), 1350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SharedFunctionInfo::kConstructStubOffset); 1351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(obj, entry, 1352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "function_data", shared->function_data(), 1353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SharedFunctionInfo::kFunctionDataOffset); 1354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(obj, entry, 1355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "debug_info", shared->debug_info(), 1356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SharedFunctionInfo::kDebugInfoOffset); 13573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch SetInternalReference(obj, entry, "function_identifier", 13583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch shared->function_identifier(), 13593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch SharedFunctionInfo::kFunctionIdentifierOffset); 1360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(obj, entry, 1361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "optimized_code_map", shared->optimized_code_map(), 1362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SharedFunctionInfo::kOptimizedCodeMapOffset); 136313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch SetInternalReference(obj, entry, "feedback_metadata", 136413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch shared->feedback_metadata(), 136513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch SharedFunctionInfo::kFeedbackMetadataOffset); 1366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractScriptReferences(int entry, Script* script) { 1370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObject* obj = script; 1371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(obj, entry, 1372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "source", script->source(), 1373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Script::kSourceOffset); 1374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(obj, entry, 1375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "name", script->name(), 1376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Script::kNameOffset); 1377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(obj, entry, 1378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "context_data", script->context_data(), 1379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Script::kContextOffset); 1380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(script->line_ends(), "(script line ends)"); 1381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(obj, entry, 1382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "line_ends", script->line_ends(), 1383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Script::kLineEndsOffset); 1384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractAccessorInfoReferences( 1388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int entry, AccessorInfo* accessor_info) { 1389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(accessor_info, entry, "name", accessor_info->name(), 1390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AccessorInfo::kNameOffset); 1391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(accessor_info, entry, "expected_receiver_type", 1392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch accessor_info->expected_receiver_type(), 1393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AccessorInfo::kExpectedReceiverTypeOffset); 1394109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch if (accessor_info->IsAccessorInfo()) { 1395109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch AccessorInfo* executable_accessor_info = AccessorInfo::cast(accessor_info); 1396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(executable_accessor_info, entry, "getter", 1397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch executable_accessor_info->getter(), 1398109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch AccessorInfo::kGetterOffset); 1399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(executable_accessor_info, entry, "setter", 1400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch executable_accessor_info->setter(), 1401109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch AccessorInfo::kSetterOffset); 1402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(executable_accessor_info, entry, "data", 1403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch executable_accessor_info->data(), 1404109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch AccessorInfo::kDataOffset); 1405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractAccessorPairReferences( 1410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int entry, AccessorPair* accessors) { 1411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(accessors, entry, "getter", accessors->getter(), 1412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AccessorPair::kGetterOffset); 1413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(accessors, entry, "setter", accessors->setter(), 1414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AccessorPair::kSetterOffset); 1415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::TagBuiltinCodeObject(Code* code, const char* name) { 1419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(code, names_->GetFormatted("(%s builtin)", name)); 1420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::TagCodeObject(Code* code) { 1424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (code->kind() == Code::STUB) { 1425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(code, names_->GetFormatted( 1426014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch "(%s code)", 1427014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CodeStub::MajorName(CodeStub::GetMajorKey(code)))); 1428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractCodeReferences(int entry, Code* code) { 1433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagCodeObject(code); 1434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(code->relocation_info(), "(code relocation info)"); 1435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(code, entry, 1436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "relocation_info", code->relocation_info(), 1437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code::kRelocationInfoOffset); 1438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(code, entry, 1439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "handler_table", code->handler_table(), 1440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code::kHandlerTableOffset); 1441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TagObject(code->deoptimization_data(), "(code deopt data)"); 1442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(code, entry, 1443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "deoptimization_data", code->deoptimization_data(), 1444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code::kDeoptimizationDataOffset); 1445f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch TagObject(code->source_position_table(), "(source position table)"); 1446f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetInternalReference(code, entry, "source_position_table", 1447f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch code->source_position_table(), 1448f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch Code::kSourcePositionTableOffset); 1449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (code->kind() == Code::FUNCTION) { 1450f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetInternalReference(code, entry, "type_feedback_info", 1451f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch code->type_feedback_info(), 1452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code::kTypeFeedbackInfoOffset); 1453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1454f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetInternalReference(code, entry, "gc_metadata", code->gc_metadata(), 1455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code::kGCMetadataOffset); 1456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractCellReferences(int entry, Cell* cell) { 1459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(cell, entry, "value", cell->value(), Cell::kValueOffset); 1460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1462f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid V8HeapExplorer::ExtractWeakCellReferences(int entry, WeakCell* weak_cell) { 1463f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch TagObject(weak_cell, "(weak cell)"); 1464f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetWeakReference(weak_cell, entry, "value", weak_cell->value(), 1465f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch WeakCell::kValueOffset); 1466f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractPropertyCellReferences(int entry, 1469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PropertyCell* cell) { 1470014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetInternalReference(cell, entry, "value", cell->value(), 1471014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PropertyCell::kValueOffset); 1472f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch TagObject(cell->dependent_code(), "(dependent code)"); 1473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(cell, entry, "dependent_code", cell->dependent_code(), 1474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PropertyCell::kDependentCodeOffset); 1475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractAllocationSiteReferences(int entry, 1479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationSite* site) { 1480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(site, entry, "transition_info", site->transition_info(), 1481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationSite::kTransitionInfoOffset); 1482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(site, entry, "nested_site", site->nested_site(), 1483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationSite::kNestedSiteOffset); 1484f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch TagObject(site->dependent_code(), "(dependent code)"); 1485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(site, entry, "dependent_code", site->dependent_code(), 1486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationSite::kDependentCodeOffset); 1487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Do not visit weak_next as it is not visited by the StaticVisitor, 1488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // and we're not very interested in weak_next field here. 1489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(AllocationSite::kWeakNextOffset >= 1490109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch AllocationSite::kPointerFieldsEndOffset); 1491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass JSArrayBufferDataEntryAllocator : public HeapEntriesAllocator { 1495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 1496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSArrayBufferDataEntryAllocator(size_t size, V8HeapExplorer* explorer) 1497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : size_(size) 1498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch , explorer_(explorer) { 1499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual HeapEntry* AllocateEntry(HeapThing ptr) { 1501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return explorer_->AddEntry( 1502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<Address>(ptr), 1503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry::kNative, "system / JSArrayBufferData", size_); 1504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 1506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch size_t size_; 1507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch V8HeapExplorer* explorer_; 1508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 1509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractJSArrayBufferReferences( 1512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int entry, JSArrayBuffer* buffer) { 1513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Setup a reference to a native memory backing_store object. 1514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!buffer->backing_store()) 1515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 1516f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch size_t data_size = NumberToSize(buffer->byte_length()); 1517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSArrayBufferDataEntryAllocator allocator(data_size, this); 1518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* data_entry = 1519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->FindOrAddEntry(buffer->backing_store(), &allocator); 1520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->SetNamedReference(HeapGraphEdge::kInternal, 1521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entry, "backing_store", data_entry); 1522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractFixedArrayReferences(int entry, FixedArray* array) { 1525f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch auto it = array_types_.find(array); 1526f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch if (it == array_types_.end()) { 1527f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (int i = 0, l = array->length(); i < l; ++i) { 1528f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetInternalReference(array, entry, i, array->get(i), 1529f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch array->OffsetOfElementAt(i)); 1530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1531f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return; 1532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1533f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch switch (it->second) { 1534f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch case JS_WEAK_COLLECTION_SUB_TYPE: 1535f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (int i = 0, l = array->length(); i < l; ++i) { 1536f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetWeakReference(array, entry, i, array->get(i), 1537f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch array->OffsetOfElementAt(i)); 1538f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1539f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 1540f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch 1541f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch // TODO(alph): Add special processing for other types of FixedArrays. 1542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1543f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch default: 1544f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch for (int i = 0, l = array->length(); i < l; ++i) { 1545f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch SetInternalReference(array, entry, i, array->get(i), 1546f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch array->OffsetOfElementAt(i)); 1547f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1548f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch break; 1549f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch } 1550f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj, int entry) { 155313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Isolate* isolate = js_obj->GetIsolate(); 1554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (js_obj->HasFastProperties()) { 1555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DescriptorArray* descs = js_obj->map()->instance_descriptors(); 1556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int real_size = js_obj->map()->NumberOfOwnDescriptors(); 1557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < real_size; i++) { 1558958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PropertyDetails details = descs->GetDetails(i); 1559958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier switch (details.location()) { 1560014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case kField: { 1561958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Representation r = details.representation(); 1562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (r.IsSmi() || r.IsDouble()) break; 1563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Name* k = descs->GetKey(i); 1565958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FieldIndex field_index = FieldIndex::ForDescriptor(js_obj->map(), i); 1566958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Object* value = js_obj->RawFastPropertyAt(field_index); 1567958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int field_offset = 1568958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier field_index.is_inobject() ? field_index.offset() : -1; 1569958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1570bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch SetDataOrAccessorPropertyReference(details.kind(), js_obj, entry, k, 1571bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch value, NULL, field_offset); 1572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1574014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch case kDescriptor: 1575958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier SetDataOrAccessorPropertyReference(details.kind(), js_obj, entry, 1576958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier descs->GetKey(i), 1577958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier descs->GetValue(i)); 1578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1581014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else if (js_obj->IsJSGlobalObject()) { 1582014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // We assume that global objects can only have slow properties. 1583014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch GlobalDictionary* dictionary = js_obj->global_dictionary(); 1584014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int length = dictionary->Capacity(); 1585014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (int i = 0; i < length; ++i) { 1586014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Object* k = dictionary->KeyAt(i); 158713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (dictionary->IsKey(isolate, k)) { 1588014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(dictionary->ValueAt(i)->IsPropertyCell()); 1589014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PropertyCell* cell = PropertyCell::cast(dictionary->ValueAt(i)); 1590014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Object* value = cell->value(); 1591014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PropertyDetails details = cell->property_details(); 1592014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetDataOrAccessorPropertyReference(details.kind(), js_obj, entry, 1593014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Name::cast(k), value); 1594014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1595014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionary* dictionary = js_obj->property_dictionary(); 1598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int length = dictionary->Capacity(); 1599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < length; ++i) { 1600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object* k = dictionary->KeyAt(i); 160113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (dictionary->IsKey(isolate, k)) { 1602014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Object* value = dictionary->ValueAt(i); 1603958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier PropertyDetails details = dictionary->DetailsAt(i); 1604958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier SetDataOrAccessorPropertyReference(details.kind(), js_obj, entry, 1605958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Name::cast(k), value); 1606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1612958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid V8HeapExplorer::ExtractAccessorPairProperty(JSObject* js_obj, int entry, 1613958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Name* key, 1614958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Object* callback_obj, 1615958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int field_offset) { 1616958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (!callback_obj->IsAccessorPair()) return; 1617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AccessorPair* accessors = AccessorPair::cast(callback_obj); 1618958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier SetPropertyReference(js_obj, entry, key, accessors, NULL, field_offset); 1619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object* getter = accessors->getter(); 1620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!getter->IsOddball()) { 1621958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier SetPropertyReference(js_obj, entry, key, getter, "get %s"); 1622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object* setter = accessors->setter(); 1624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!setter->IsOddball()) { 1625958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier SetPropertyReference(js_obj, entry, key, setter, "set %s"); 1626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractElementReferences(JSObject* js_obj, int entry) { 163113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Isolate* isolate = js_obj->GetIsolate(); 1632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (js_obj->HasFastObjectElements()) { 1633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FixedArray* elements = FixedArray::cast(js_obj->elements()); 1634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int length = js_obj->IsJSArray() ? 1635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi::cast(JSArray::cast(js_obj)->length())->value() : 1636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch elements->length(); 1637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < length; ++i) { 163813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (!elements->get(i)->IsTheHole(isolate)) { 1639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetElementReference(js_obj, entry, i, elements->get(i)); 1640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (js_obj->HasDictionaryElements()) { 1643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SeededNumberDictionary* dictionary = js_obj->element_dictionary(); 1644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int length = dictionary->Capacity(); 1645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < length; ++i) { 1646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object* k = dictionary->KeyAt(i); 164713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (dictionary->IsKey(isolate, k)) { 1648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(k->IsNumber()); 1649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t index = static_cast<uint32_t>(k->Number()); 1650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetElementReference(js_obj, entry, index, dictionary->ValueAt(i)); 1651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid V8HeapExplorer::ExtractInternalReferences(JSObject* js_obj, int entry) { 1658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int length = js_obj->GetInternalFieldCount(); 1659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < length; ++i) { 1660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object* o = js_obj->GetInternalField(i); 1661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference( 1662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch js_obj, entry, i, o, js_obj->GetInternalFieldOffset(i)); 1663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochString* V8HeapExplorer::GetConstructorName(JSObject* object) { 1668014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Isolate* isolate = object->GetIsolate(); 1669014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (object->IsJSFunction()) return isolate->heap()->closure_string(); 1670014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DisallowHeapAllocation no_gc; 1671014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HandleScope scope(isolate); 1672014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return *JSReceiver::GetConstructorName(handle(object, isolate)); 1673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapEntry* V8HeapExplorer::GetEntry(Object* obj) { 1677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!obj->IsHeapObject()) return NULL; 1678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return filler_->FindOrAddEntry(obj, this); 1679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass RootsReferencesExtractor : public ObjectVisitor { 1683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 1684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch struct IndexTag { 1685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IndexTag(int index, VisitorSynchronization::SyncTag tag) 1686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : index(index), tag(tag) { } 1687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int index; 1688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitorSynchronization::SyncTag tag; 1689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 1690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 1692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit RootsReferencesExtractor(Heap* heap) 1693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : collecting_all_references_(false), 1694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch previous_reference_count_(0), 1695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap_(heap) { 1696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1698014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void VisitPointers(Object** start, Object** end) override { 1699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (collecting_all_references_) { 1700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (Object** p = start; p < end; p++) all_references_.Add(*p); 1701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (Object** p = start; p < end; p++) strong_references_.Add(*p); 1703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void SetCollectingAllReferences() { collecting_all_references_ = true; } 1707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void FillReferences(V8HeapExplorer* explorer) { 1709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(strong_references_.length() <= all_references_.length()); 1710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Builtins* builtins = heap_->isolate()->builtins(); 1711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int strong_index = 0, all_index = 0, tags_index = 0, builtin_index = 0; 1712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while (all_index < all_references_.length()) { 1713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_strong = strong_index < strong_references_.length() 1714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch && strong_references_[strong_index] == all_references_[all_index]; 1715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explorer->SetGcSubrootReference(reference_tags_[tags_index].tag, 1716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !is_strong, 1717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch all_references_[all_index]); 1718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (reference_tags_[tags_index].tag == 1719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitorSynchronization::kBuiltins) { 1720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(all_references_[all_index]->IsCode()); 1721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explorer->TagBuiltinCodeObject( 1722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code::cast(all_references_[all_index]), 1723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch builtins->name(builtin_index++)); 1724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++all_index; 1726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (is_strong) ++strong_index; 1727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (reference_tags_[tags_index].index == all_index) ++tags_index; 1728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1731014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void Synchronize(VisitorSynchronization::SyncTag tag) override { 1732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (collecting_all_references_ && 1733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch previous_reference_count_ != all_references_.length()) { 1734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch previous_reference_count_ = all_references_.length(); 1735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reference_tags_.Add(IndexTag(previous_reference_count_, tag)); 1736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 1740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool collecting_all_references_; 1741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch List<Object*> strong_references_; 1742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch List<Object*> all_references_; 1743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int previous_reference_count_; 1744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch List<IndexTag> reference_tags_; 1745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap* heap_; 1746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 1747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool V8HeapExplorer::IterateAndExtractReferences( 1750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SnapshotFiller* filler) { 1751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_ = filler; 1752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Create references to the synthetic roots. 1754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetRootGcRootsReference(); 1755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int tag = 0; tag < VisitorSynchronization::kNumberOfSyncTags; tag++) { 1756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetGcRootsReference(static_cast<VisitorSynchronization::SyncTag>(tag)); 1757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Make sure builtin code objects get their builtin tags 1760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // first. Otherwise a particular JSFunction object could set 1761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // its custom name to a generic builtin. 1762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RootsReferencesExtractor extractor(heap_); 1763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap_->IterateRoots(&extractor, VISIT_ONLY_STRONG); 1764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch extractor.SetCollectingAllReferences(); 1765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap_->IterateRoots(&extractor, VISIT_ALL); 1766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch extractor.FillReferences(this); 1767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We have to do two passes as sometimes FixedArrays are used 1769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to weakly hold their items, and it's impossible to distinguish 1770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // between these cases without processing the array owner first. 1771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool interrupted = 1772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IterateAndExtractSinglePass<&V8HeapExplorer::ExtractReferencesPass1>() || 1773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IterateAndExtractSinglePass<&V8HeapExplorer::ExtractReferencesPass2>(); 1774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (interrupted) { 1776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_ = NULL; 1777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return false; 1778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_ = NULL; 1781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return progress_->ProgressReport(true); 1782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<V8HeapExplorer::ExtractReferencesMethod extractor> 1786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool V8HeapExplorer::IterateAndExtractSinglePass() { 1787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Now iterate the whole heap. 1788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool interrupted = false; 1789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapIterator iterator(heap_, HeapIterator::kFilterUnreachable); 1790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Heap iteration with filtering must be finished in any case. 1791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (HeapObject* obj = iterator.next(); 1792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch obj != NULL; 1793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch obj = iterator.next(), progress_->ProgressStep()) { 1794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (interrupted) continue; 1795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1796014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch size_t max_pointer = obj->Size() / kPointerSize; 1797014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (max_pointer > marks_.size()) { 1798014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Clear the current bits. 1799014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch std::vector<bool>().swap(marks_); 1800014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Reallocate to right size. 1801014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch marks_.resize(max_pointer, false); 1802014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1803014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* heap_entry = GetEntry(obj); 1805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int entry = heap_entry->index(); 1806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((this->*extractor)(entry, obj)) { 1807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInternalReference(obj, entry, 1808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "map", obj->map(), HeapObject::kMapOffset); 1809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Extract unvisited fields as hidden references and restore tags 1810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // of visited fields. 1811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IndexedReferencesExtractor refs_extractor(this, obj, entry); 1812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch obj->Iterate(&refs_extractor); 1813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!progress_->ProgressReport(false)) interrupted = true; 1816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return interrupted; 1818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool V8HeapExplorer::IsEssentialObject(Object* object) { 1822014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return object->IsHeapObject() && !object->IsOddball() && 1823014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch object != heap_->empty_byte_array() && 1824014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch object != heap_->empty_fixed_array() && 1825014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch object != heap_->empty_descriptor_array() && 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; 228962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch v8::HandleScope scope(reinterpret_cast<v8::Isolate*>(isolate_)); 229062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch v8::HeapProfiler::RetainerInfos infos = 229162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch snapshot_->profiler()->GetRetainerInfos(isolate_); 229262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch for (auto& pair : infos.groups) { 229362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch List<HeapObject*>* list = GetListMaybeDisposeInfo(pair.first); 229462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch for (auto& persistent : pair.second) { 229562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (persistent->IsEmpty()) continue; 229662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 229762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Handle<Object> object = v8::Utils::OpenHandle( 229862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch *persistent->Get(reinterpret_cast<v8::Isolate*>(isolate_))); 229962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK(!object.is_null()); 230062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch HeapObject* heap_object = HeapObject::cast(*object); 230162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch list->Add(heap_object); 230262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch in_groups_.Insert(heap_object); 2303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 230562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 2306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Record objects that are not in ObjectGroups, but have class ID. 2307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GlobalHandlesExtractor extractor(this); 230862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch isolate_->global_handles()->IterateAllRootsWithClassIds(&extractor); 230962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 231062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch edges_ = std::move(infos.edges); 2311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch embedder_queried_ = true; 2312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 231462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid NativeObjectsExplorer::FillEdges() { 231562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch v8::HandleScope scope(reinterpret_cast<v8::Isolate*>(isolate_)); 231662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch // Fill in actual edges found. 231762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch for (auto& pair : edges_) { 231862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (pair.first->IsEmpty() || pair.second->IsEmpty()) continue; 2319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 232062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Handle<Object> parent_object = v8::Utils::OpenHandle( 232162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch *pair.first->Get(reinterpret_cast<v8::Isolate*>(isolate_))); 232262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch HeapObject* parent = HeapObject::cast(*parent_object); 2323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int parent_entry = 2324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->FindOrAddEntry(parent, native_entries_allocator_)->index(); 2325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(parent_entry != HeapEntry::kNoEntry); 232662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Handle<Object> child_object = v8::Utils::OpenHandle( 232762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch *pair.second->Get(reinterpret_cast<v8::Isolate*>(isolate_))); 232862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch HeapObject* child = HeapObject::cast(*child_object); 232962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch HeapEntry* child_entry = 233062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch filler_->FindOrAddEntry(child, native_entries_allocator_); 233162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch filler_->SetNamedReference(HeapGraphEdge::kInternal, parent_entry, "native", 233262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch child_entry); 2333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 233462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch edges_.clear(); 2335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochList<HeapObject*>* NativeObjectsExplorer::GetListMaybeDisposeInfo( 2338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::RetainedObjectInfo* info) { 233913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch base::HashMap::Entry* entry = 234013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch objects_by_info_.LookupOrInsert(info, InfoHash(info)); 2341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (entry->value != NULL) { 2342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch info->Dispose(); 2343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entry->value = new List<HeapObject*>(4); 2345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return reinterpret_cast<List<HeapObject*>* >(entry->value); 2347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool NativeObjectsExplorer::IterateAndExtractReferences( 2351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SnapshotFiller* filler) { 2352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_ = filler; 2353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FillRetainedObjects(); 235462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch FillEdges(); 2355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (EstimateObjectsCount() > 0) { 235613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch for (base::HashMap::Entry* p = objects_by_info_.Start(); p != NULL; 2357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch p = objects_by_info_.Next(p)) { 2358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::RetainedObjectInfo* info = 2359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<v8::RetainedObjectInfo*>(p->key); 2360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetNativeRootReference(info); 2361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch List<HeapObject*>* objects = 2362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<List<HeapObject*>* >(p->value); 2363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < objects->length(); ++i) { 2364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetWrapperNativeReferences(objects->at(i), info); 2365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetRootNativeRootsReference(); 2368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_ = NULL; 2370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return true; 2371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass NativeGroupRetainedObjectInfo : public v8::RetainedObjectInfo { 2375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 2376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit NativeGroupRetainedObjectInfo(const char* label) 2377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : disposed_(false), 2378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch hash_(reinterpret_cast<intptr_t>(label)), 2379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch label_(label) { 2380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual ~NativeGroupRetainedObjectInfo() {} 2383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual void Dispose() { 2384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(!disposed_); 2385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch disposed_ = true; 2386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch delete this; 2387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual bool IsEquivalent(RetainedObjectInfo* other) { 2389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return hash_ == other->GetHash() && !strcmp(label_, other->GetLabel()); 2390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual intptr_t GetHash() { return hash_; } 2392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual const char* GetLabel() { return label_; } 2393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 2395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool disposed_; 2396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch intptr_t hash_; 2397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* label_; 2398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 2399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochNativeGroupRetainedObjectInfo* NativeObjectsExplorer::FindOrAddGroupInfo( 2402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* label) { 2403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* label_copy = names_->GetCopy(label); 2404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t hash = StringHasher::HashSequentialString( 2405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch label_copy, 2406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<int>(strlen(label_copy)), 2407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate_->heap()->HashSeed()); 240813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch base::HashMap::Entry* entry = 2409014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch native_groups_.LookupOrInsert(const_cast<char*>(label_copy), hash); 2410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (entry->value == NULL) { 2411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entry->value = new NativeGroupRetainedObjectInfo(label); 2412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return static_cast<NativeGroupRetainedObjectInfo*>(entry->value); 2414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NativeObjectsExplorer::SetNativeRootReference( 2418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::RetainedObjectInfo* info) { 2419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* child_entry = 2420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->FindOrAddEntry(info, native_entries_allocator_); 2421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(child_entry != NULL); 2422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NativeGroupRetainedObjectInfo* group_info = 2423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FindOrAddGroupInfo(info->GetGroupLabel()); 2424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* group_entry = 2425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->FindOrAddEntry(group_info, synthetic_entries_allocator_); 2426014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // |FindOrAddEntry| can move and resize the entries backing store. Reload 2427014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // potentially-stale pointer. 2428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch child_entry = filler_->FindEntry(info); 2429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->SetNamedAutoIndexReference( 2430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapGraphEdge::kInternal, 2431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch group_entry->index(), 2432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch child_entry); 2433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NativeObjectsExplorer::SetWrapperNativeReferences( 2437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObject* wrapper, v8::RetainedObjectInfo* info) { 2438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* wrapper_entry = filler_->FindEntry(wrapper); 2439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(wrapper_entry != NULL); 2440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* info_entry = 2441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->FindOrAddEntry(info, native_entries_allocator_); 2442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(info_entry != NULL); 2443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->SetNamedReference(HeapGraphEdge::kInternal, 2444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch wrapper_entry->index(), 2445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "native", 2446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch info_entry); 2447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->SetIndexedAutoIndexReference(HeapGraphEdge::kElement, 2448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch info_entry->index(), 2449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch wrapper_entry); 2450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NativeObjectsExplorer::SetRootNativeRootsReference() { 245413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch for (base::HashMap::Entry* entry = native_groups_.Start(); entry; 2455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entry = native_groups_.Next(entry)) { 2456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NativeGroupRetainedObjectInfo* group_info = 2457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<NativeGroupRetainedObjectInfo*>(entry->value); 2458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapEntry* group_entry = 2459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->FindOrAddEntry(group_info, native_entries_allocator_); 2460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(group_entry != NULL); 2461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch filler_->SetIndexedAutoIndexReference( 2462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapGraphEdge::kElement, 2463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch snapshot_->root()->index(), 2464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch group_entry); 2465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid NativeObjectsExplorer::VisitSubtreeWrapper(Object** p, uint16_t class_id) { 2470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (in_groups_.Contains(*p)) return; 2471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate = isolate_; 2472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::RetainedObjectInfo* info = 2473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate->heap_profiler()->ExecuteWrapperClassCallback(class_id, p); 2474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (info == NULL) return; 2475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GetListMaybeDisposeInfo(info)->Add(HeapObject::cast(*p)); 2476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHeapSnapshotGenerator::HeapSnapshotGenerator( 2480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapSnapshot* snapshot, 2481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::ActivityControl* control, 2482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::HeapProfiler::ObjectNameResolver* resolver, 2483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap* heap) 2484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : snapshot_(snapshot), 2485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch control_(control), 2486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8_heap_explorer_(snapshot_, this, resolver), 2487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch dom_explorer_(snapshot_, this), 2488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap_(heap) { 2489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 249162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochnamespace { 249262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochclass NullContextScope { 249362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch public: 249462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch explicit NullContextScope(Isolate* isolate) 249562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch : isolate_(isolate), prev_(isolate->context()) { 249662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch isolate_->set_context(nullptr); 249762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 249862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ~NullContextScope() { isolate_->set_context(prev_); } 249962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 250062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch private: 250162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Isolate* isolate_; 250262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Context* prev_; 250362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}; 250462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} // namespace 2505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool HeapSnapshotGenerator::GenerateSnapshot() { 2507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8_heap_explorer_.TagGlobalObjects(); 2508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(1562) Profiler assumes that any object that is in the heap after 2510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // full GC is reachable from the root when computing dominators. 2511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This is not true for weakly reachable objects. 2512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // As a temporary solution we call GC twice. 2513f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch heap_->CollectAllGarbage(Heap::kMakeHeapIterableMask, 2514f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GarbageCollectionReason::kHeapProfiler); 2515f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch heap_->CollectAllGarbage(Heap::kMakeHeapIterableMask, 2516f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch GarbageCollectionReason::kHeapProfiler); 2517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 251862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch NullContextScope null_context_scope(heap_->isolate()); 251962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 2520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef VERIFY_HEAP 2521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap* debug_heap = heap_; 2522014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (FLAG_verify_heap) { 2523014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch debug_heap->Verify(); 2524014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 2526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetProgressTotal(2); // 2 passes. 2528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef VERIFY_HEAP 2530014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (FLAG_verify_heap) { 2531014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch debug_heap->Verify(); 2532014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 2534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch snapshot_->AddSyntheticRootEntries(); 2536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!FillReferences()) return false; 2538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch snapshot_->FillChildren(); 2540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch snapshot_->RememberLastJSObjectId(); 2541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch progress_counter_ = progress_total_; 2543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!ProgressReport(true)) return false; 2544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return true; 2545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshotGenerator::ProgressStep() { 2549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++progress_counter_; 2550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool HeapSnapshotGenerator::ProgressReport(bool force) { 2554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kProgressReportGranularity = 10000; 2555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (control_ != NULL 2556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch && (force || progress_counter_ % kProgressReportGranularity == 0)) { 2557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 2558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch control_->ReportProgressValue(progress_counter_, progress_total_) == 2559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::ActivityControl::kContinue; 2560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return true; 2562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshotGenerator::SetProgressTotal(int iterations_count) { 2566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (control_ == NULL) return; 2567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapIterator iterator(heap_, HeapIterator::kFilterUnreachable); 2568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch progress_total_ = iterations_count * ( 2569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8_heap_explorer_.EstimateObjectsCount(&iterator) + 2570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch dom_explorer_.EstimateObjectsCount()); 2571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch progress_counter_ = 0; 2572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool HeapSnapshotGenerator::FillReferences() { 2576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SnapshotFiller filler(snapshot_, &entries_); 2577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return v8_heap_explorer_.IterateAndExtractReferences(&filler) 2578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch && dom_explorer_.IterateAndExtractReferences(&filler); 2579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<int bytes> struct MaxDecimalDigitsIn; 2583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<> struct MaxDecimalDigitsIn<4> { 2584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kSigned = 11; 2585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kUnsigned = 10; 2586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 2587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<> struct MaxDecimalDigitsIn<8> { 2588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kSigned = 20; 2589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kUnsigned = 20; 2590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 2591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass OutputStreamWriter { 2594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 2595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit OutputStreamWriter(v8::OutputStream* stream) 2596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : stream_(stream), 2597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch chunk_size_(stream->GetChunkSize()), 2598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch chunk_(chunk_size_), 2599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch chunk_pos_(0), 2600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch aborted_(false) { 2601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(chunk_size_ > 0); 2602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool aborted() { return aborted_; } 2604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void AddCharacter(char c) { 2605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(c != '\0'); 2606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(chunk_pos_ < chunk_size_); 2607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch chunk_[chunk_pos_++] = c; 2608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MaybeWriteChunk(); 2609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void AddString(const char* s) { 2611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AddSubstring(s, StrLength(s)); 2612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void AddSubstring(const char* s, int n) { 2614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (n <= 0) return; 2615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(static_cast<size_t>(n) <= strlen(s)); 2616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* s_end = s + n; 2617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while (s < s_end) { 2618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int s_chunk_size = 2619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Min(chunk_size_ - chunk_pos_, static_cast<int>(s_end - s)); 2620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(s_chunk_size > 0); 2621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemCopy(chunk_.start() + chunk_pos_, s, s_chunk_size); 2622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch s += s_chunk_size; 2623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch chunk_pos_ += s_chunk_size; 2624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MaybeWriteChunk(); 2625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void AddNumber(unsigned n) { AddNumberImpl<unsigned>(n, "%u"); } 2628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Finalize() { 2629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (aborted_) return; 2630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(chunk_pos_ < chunk_size_); 2631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (chunk_pos_ != 0) { 2632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch WriteChunk(); 2633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch stream_->EndOfStream(); 2635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 2638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template<typename T> 2639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void AddNumberImpl(T n, const char* format) { 2640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Buffer for the longest value plus trailing \0 2641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kMaxNumberSize = 2642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MaxDecimalDigitsIn<sizeof(T)>::kUnsigned + 1; 2643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (chunk_size_ - chunk_pos_ >= kMaxNumberSize) { 2644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int result = SNPrintF( 2645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch chunk_.SubVector(chunk_pos_, chunk_size_), format, n); 2646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(result != -1); 2647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch chunk_pos_ += result; 2648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MaybeWriteChunk(); 2649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmbeddedVector<char, kMaxNumberSize> buffer; 2651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int result = SNPrintF(buffer, format, n); 2652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch USE(result); 2653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(result != -1); 2654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AddString(buffer.start()); 2655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void MaybeWriteChunk() { 2658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(chunk_pos_ <= chunk_size_); 2659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (chunk_pos_ == chunk_size_) { 2660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch WriteChunk(); 2661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void WriteChunk() { 2664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (aborted_) return; 2665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (stream_->WriteAsciiChunk(chunk_.start(), chunk_pos_) == 2666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::OutputStream::kAbort) aborted_ = true; 2667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch chunk_pos_ = 0; 2668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch v8::OutputStream* stream_; 2671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int chunk_size_; 2672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ScopedVector<char> chunk_; 2673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int chunk_pos_; 2674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool aborted_; 2675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 2676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// type, name|index, to_node. 2679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst int HeapSnapshotJSONSerializer::kEdgeFieldsCount = 3; 2680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// type, name, id, self_size, edge_count, trace_node_id. 2681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst int HeapSnapshotJSONSerializer::kNodeFieldsCount = 6; 2682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshotJSONSerializer::Serialize(v8::OutputStream* stream) { 2684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (AllocationTracker* allocation_tracker = 2685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch snapshot_->profiler()->allocation_tracker()) { 2686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch allocation_tracker->PrepareForSerialization(); 2687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(writer_ == NULL); 2689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_ = new OutputStreamWriter(stream); 2690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SerializeImpl(); 2691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch delete writer_; 2692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_ = NULL; 2693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshotJSONSerializer::SerializeImpl() { 2697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(0 == snapshot_->root()->index()); 2698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddCharacter('{'); 2699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString("\"snapshot\":{"); 2700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SerializeSnapshot(); 2701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (writer_->aborted()) return; 2702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString("},\n"); 2703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString("\"nodes\":["); 2704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SerializeNodes(); 2705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (writer_->aborted()) return; 2706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString("],\n"); 2707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString("\"edges\":["); 2708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SerializeEdges(); 2709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (writer_->aborted()) return; 2710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString("],\n"); 2711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString("\"trace_function_infos\":["); 2713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SerializeTraceNodeInfos(); 2714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (writer_->aborted()) return; 2715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString("],\n"); 2716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString("\"trace_tree\":["); 2717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SerializeTraceTree(); 2718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (writer_->aborted()) return; 2719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString("],\n"); 2720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2721014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch writer_->AddString("\"samples\":["); 2722014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SerializeSamples(); 2723014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (writer_->aborted()) return; 2724014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch writer_->AddString("],\n"); 2725014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString("\"strings\":["); 2727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SerializeStrings(); 2728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (writer_->aborted()) return; 2729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddCharacter(']'); 2730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddCharacter('}'); 2731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->Finalize(); 2732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint HeapSnapshotJSONSerializer::GetStringId(const char* s) { 273613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch base::HashMap::Entry* cache_entry = 2737014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch strings_.LookupOrInsert(const_cast<char*>(s), StringHash(s)); 2738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (cache_entry->value == NULL) { 2739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cache_entry->value = reinterpret_cast<void*>(next_string_id_++); 2740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); 2742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace { 2746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<size_t size> struct ToUnsigned; 2748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<> struct ToUnsigned<4> { 2750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch typedef uint32_t Type; 2751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 2752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<> struct ToUnsigned<8> { 2754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch typedef uint64_t Type; 2755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 2756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} // namespace 2758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<typename T> 2761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic int utoa_impl(T value, const Vector<char>& buffer, int buffer_pos) { 2762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(static_cast<T>(-1) > 0); // Check that T is unsigned 2763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int number_of_digits = 0; 2764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch T t = value; 2765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch do { 2766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++number_of_digits; 2767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } while (t /= 10); 2768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos += number_of_digits; 2770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int result = buffer_pos; 2771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch do { 2772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int last_digit = static_cast<int>(value % 10); 2773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[--buffer_pos] = '0' + last_digit; 2774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch value /= 10; 2775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } while (value); 2776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return result; 2777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<typename T> 2781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic int utoa(T value, const Vector<char>& buffer, int buffer_pos) { 2782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch typename ToUnsigned<sizeof(value)>::Type unsigned_value = value; 2783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(sizeof(value) == sizeof(unsigned_value)); 2784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return utoa_impl(unsigned_value, buffer, buffer_pos); 2785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge, 2789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool first_edge) { 2790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The buffer needs space for 3 unsigned ints, 3 commas, \n and \0 2791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kBufferSize = 2792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned * 3 + 3 + 2; // NOLINT 2793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmbeddedVector<char, kBufferSize> buffer; 2794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int edge_name_or_index = edge->type() == HeapGraphEdge::kElement 2795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch || edge->type() == HeapGraphEdge::kHidden 2796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? edge->index() : GetStringId(edge->name()); 2797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int buffer_pos = 0; 2798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!first_edge) { 2799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 2800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(edge->type(), buffer, buffer_pos); 2802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 2803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(edge_name_or_index, buffer, buffer_pos); 2804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 2805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(entry_index(edge->to()), buffer, buffer_pos); 2806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = '\n'; 2807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = '\0'; 2808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString(buffer.start()); 2809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshotJSONSerializer::SerializeEdges() { 281362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch std::deque<HeapGraphEdge*>& edges = snapshot_->children(); 281462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch for (size_t i = 0; i < edges.size(); ++i) { 2815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(i == 0 || 2816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch edges[i - 1]->from()->index() <= edges[i]->from()->index()); 2817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SerializeEdge(edges[i], i == 0); 2818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (writer_->aborted()) return; 2819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry) { 2824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The buffer needs space for 4 unsigned ints, 1 size_t, 5 commas, \n and \0 2825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kBufferSize = 2826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5 * MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned // NOLINT 2827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch + MaxDecimalDigitsIn<sizeof(size_t)>::kUnsigned // NOLINT 2828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch + 6 + 1 + 1; 2829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmbeddedVector<char, kBufferSize> buffer; 2830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int buffer_pos = 0; 2831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (entry_index(entry) != 0) { 2832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 2833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(entry->type(), buffer, buffer_pos); 2835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 2836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(GetStringId(entry->name()), buffer, buffer_pos); 2837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 2838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(entry->id(), buffer, buffer_pos); 2839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 2840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(entry->self_size(), buffer, buffer_pos); 2841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 2842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(entry->children_count(), buffer, buffer_pos); 2843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 2844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(entry->trace_node_id(), buffer, buffer_pos); 2845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = '\n'; 2846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = '\0'; 2847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString(buffer.start()); 2848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshotJSONSerializer::SerializeNodes() { 2852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch List<HeapEntry>& entries = snapshot_->entries(); 2853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < entries.length(); ++i) { 2854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SerializeNode(&entries[i]); 2855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (writer_->aborted()) return; 2856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshotJSONSerializer::SerializeSnapshot() { 2861014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch writer_->AddString("\"meta\":"); 2862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The object describing node serialization layout. 2863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We use a set of macros to improve readability. 2864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define JSON_A(s) "[" s "]" 2865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define JSON_O(s) "{" s "}" 2866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define JSON_S(s) "\"" s "\"" 2867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString(JSON_O( 2868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("node_fields") ":" JSON_A( 2869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("type") "," 2870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("name") "," 2871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("id") "," 2872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("self_size") "," 2873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("edge_count") "," 2874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("trace_node_id")) "," 2875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("node_types") ":" JSON_A( 2876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_A( 2877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("hidden") "," 2878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("array") "," 2879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("string") "," 2880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("object") "," 2881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("code") "," 2882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("closure") "," 2883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("regexp") "," 2884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("number") "," 2885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("native") "," 2886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("synthetic") "," 2887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("concatenated string") "," 2888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("sliced string")) "," 2889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("string") "," 2890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("number") "," 2891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("number") "," 2892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("number") "," 2893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("number") "," 2894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("number")) "," 2895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("edge_fields") ":" JSON_A( 2896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("type") "," 2897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("name_or_index") "," 2898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("to_node")) "," 2899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("edge_types") ":" JSON_A( 2900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_A( 2901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("context") "," 2902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("element") "," 2903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("property") "," 2904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("internal") "," 2905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("hidden") "," 2906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("shortcut") "," 2907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("weak")) "," 2908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("string_or_number") "," 2909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("node")) "," 2910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("trace_function_info_fields") ":" JSON_A( 2911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("function_id") "," 2912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("name") "," 2913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("script_name") "," 2914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("script_id") "," 2915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("line") "," 2916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("column")) "," 2917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("trace_node_fields") ":" JSON_A( 2918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("id") "," 2919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("function_info_index") "," 2920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("count") "," 2921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSON_S("size") "," 2922014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JSON_S("children")) "," 2923014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JSON_S("sample_fields") ":" JSON_A( 2924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JSON_S("timestamp_us") "," 2925014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch JSON_S("last_assigned_id")))); 2926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef JSON_S 2927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef JSON_O 2928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef JSON_A 2929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString(",\"node_count\":"); 2930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddNumber(snapshot_->entries().length()); 2931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString(",\"edge_count\":"); 293262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch writer_->AddNumber(static_cast<double>(snapshot_->edges().size())); 2933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString(",\"trace_function_count\":"); 2934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t count = 0; 2935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationTracker* tracker = snapshot_->profiler()->allocation_tracker(); 2936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (tracker) { 2937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch count = tracker->function_info_list().length(); 2938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddNumber(count); 2940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void WriteUChar(OutputStreamWriter* w, unibrow::uchar u) { 2944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const char hex_chars[] = "0123456789ABCDEF"; 2945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch w->AddString("\\u"); 2946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch w->AddCharacter(hex_chars[(u >> 12) & 0xf]); 2947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch w->AddCharacter(hex_chars[(u >> 8) & 0xf]); 2948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch w->AddCharacter(hex_chars[(u >> 4) & 0xf]); 2949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch w->AddCharacter(hex_chars[u & 0xf]); 2950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshotJSONSerializer::SerializeTraceTree() { 2954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationTracker* tracker = snapshot_->profiler()->allocation_tracker(); 2955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!tracker) return; 2956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationTraceTree* traces = tracker->trace_tree(); 2957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SerializeTraceNode(traces->root()); 2958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshotJSONSerializer::SerializeTraceNode(AllocationTraceNode* node) { 2962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The buffer needs space for 4 unsigned ints, 4 commas, [ and \0 2963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kBufferSize = 2964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4 * MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned // NOLINT 2965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch + 4 + 1 + 1; 2966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmbeddedVector<char, kBufferSize> buffer; 2967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int buffer_pos = 0; 2968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(node->id(), buffer, buffer_pos); 2969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 2970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(node->function_info_index(), buffer, buffer_pos); 2971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 2972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(node->allocation_count(), buffer, buffer_pos); 2973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 2974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(node->allocation_size(), buffer, buffer_pos); 2975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 2976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = '['; 2977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = '\0'; 2978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString(buffer.start()); 2979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Vector<AllocationTraceNode*> children = node->children(); 2981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < children.length(); i++) { 2982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (i > 0) { 2983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddCharacter(','); 2984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SerializeTraceNode(children[i]); 2986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddCharacter(']'); 2988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 0-based position is converted to 1-based during the serialization. 2992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic int SerializePosition(int position, const Vector<char>& buffer, 2993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int buffer_pos) { 2994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (position == -1) { 2995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = '0'; 2996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(position >= 0); 2998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(static_cast<unsigned>(position + 1), buffer, buffer_pos); 2999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return buffer_pos; 3001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshotJSONSerializer::SerializeTraceNodeInfos() { 3005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationTracker* tracker = snapshot_->profiler()->allocation_tracker(); 3006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!tracker) return; 3007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The buffer needs space for 6 unsigned ints, 6 commas, \n and \0 3008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kBufferSize = 3009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6 * MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned // NOLINT 3010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch + 6 + 1 + 1; 3011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmbeddedVector<char, kBufferSize> buffer; 3012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const List<AllocationTracker::FunctionInfo*>& list = 3013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch tracker->function_info_list(); 3014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < list.length(); i++) { 3015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationTracker::FunctionInfo* info = list[i]; 3016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int buffer_pos = 0; 3017014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (i > 0) { 3018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 3019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(info->function_id, buffer, buffer_pos); 3021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 3022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(GetStringId(info->name), buffer, buffer_pos); 3023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 3024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(GetStringId(info->script_name), buffer, buffer_pos); 3025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 3026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The cast is safe because script id is a non-negative Smi. 3027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = utoa(static_cast<unsigned>(info->script_id), buffer, 3028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos); 3029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 3030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = SerializePosition(info->line, buffer, buffer_pos); 3031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = ','; 3032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_pos = SerializePosition(info->column, buffer, buffer_pos); 3033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = '\n'; 3034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer[buffer_pos++] = '\0'; 3035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString(buffer.start()); 3036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3040014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid HeapSnapshotJSONSerializer::SerializeSamples() { 3041014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const List<HeapObjectsMap::TimeInterval>& samples = 3042014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch snapshot_->profiler()->heap_object_map()->samples(); 3043014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (samples.is_empty()) return; 3044014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch base::TimeTicks start_time = samples[0].timestamp; 3045014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // The buffer needs space for 2 unsigned ints, 2 commas, \n and \0 3046014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const int kBufferSize = MaxDecimalDigitsIn<sizeof( 3047014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch base::TimeDelta().InMicroseconds())>::kUnsigned + 3048014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch MaxDecimalDigitsIn<sizeof(samples[0].id)>::kUnsigned + 3049014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2 + 1 + 1; 3050014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmbeddedVector<char, kBufferSize> buffer; 3051014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (int i = 0; i < samples.length(); i++) { 3052014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HeapObjectsMap::TimeInterval& sample = samples[i]; 3053014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int buffer_pos = 0; 3054014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (i > 0) { 3055014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch buffer[buffer_pos++] = ','; 3056014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 3057014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch base::TimeDelta time_delta = sample.timestamp - start_time; 3058014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch buffer_pos = utoa(time_delta.InMicroseconds(), buffer, buffer_pos); 3059014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch buffer[buffer_pos++] = ','; 3060014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch buffer_pos = utoa(sample.last_assigned_id(), buffer, buffer_pos); 3061014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch buffer[buffer_pos++] = '\n'; 3062014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch buffer[buffer_pos++] = '\0'; 3063014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch writer_->AddString(buffer.start()); 3064014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 3065014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 3066014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3067014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 3068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshotJSONSerializer::SerializeString(const unsigned char* s) { 3069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddCharacter('\n'); 3070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddCharacter('\"'); 3071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for ( ; *s != '\0'; ++s) { 3072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (*s) { 3073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case '\b': 3074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString("\\b"); 3075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch continue; 3076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case '\f': 3077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString("\\f"); 3078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch continue; 3079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case '\n': 3080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString("\\n"); 3081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch continue; 3082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case '\r': 3083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString("\\r"); 3084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch continue; 3085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case '\t': 3086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString("\\t"); 3087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch continue; 3088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case '\"': 3089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case '\\': 3090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddCharacter('\\'); 3091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddCharacter(*s); 3092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch continue; 3093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 3094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (*s > 31 && *s < 128) { 3095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddCharacter(*s); 3096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (*s <= 31) { 3097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Special character with no dedicated literal. 3098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch WriteUChar(writer_, *s); 3099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 3100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Convert UTF-8 into \u UTF-16 literal. 3101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch size_t length = 1, cursor = 0; 3102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for ( ; length <= 4 && *(s + length) != '\0'; ++length) { } 3103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unibrow::uchar c = unibrow::Utf8::CalculateValue(s, length, &cursor); 3104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (c != unibrow::Utf8::kBadChar) { 3105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch WriteUChar(writer_, c); 3106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(cursor != 0); 3107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch s += cursor - 1; 3108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 3109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddCharacter('?'); 3110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddCharacter('\"'); 3115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HeapSnapshotJSONSerializer::SerializeStrings() { 3119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ScopedVector<const unsigned char*> sorted_strings( 3120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch strings_.occupancy() + 1); 312113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch for (base::HashMap::Entry* entry = strings_.Start(); entry != NULL; 3122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch entry = strings_.Next(entry)) { 3123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int index = static_cast<int>(reinterpret_cast<uintptr_t>(entry->value)); 3124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sorted_strings[index] = reinterpret_cast<const unsigned char*>(entry->key); 3125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddString("\"<dummy>\""); 3127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 1; i < sorted_strings.length(); ++i) { 3128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch writer_->AddCharacter(','); 3129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SerializeString(sorted_strings[i]); 3130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (writer_->aborted()) return; 3131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 3136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 3137