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

Side by Side Diff: src/heap-snapshot-generator.cc

Issue 185653004: Experimental parser: merge to r19637 (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/heap-snapshot-generator.h ('k') | src/hydrogen.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 16 matching lines...) Expand all
27 27
28 #include "v8.h" 28 #include "v8.h"
29 29
30 #include "heap-snapshot-generator-inl.h" 30 #include "heap-snapshot-generator-inl.h"
31 31
32 #include "allocation-tracker.h" 32 #include "allocation-tracker.h"
33 #include "code-stubs.h" 33 #include "code-stubs.h"
34 #include "heap-profiler.h" 34 #include "heap-profiler.h"
35 #include "debug.h" 35 #include "debug.h"
36 #include "types.h" 36 #include "types.h"
37 #include "v8conversions.h"
37 38
38 namespace v8 { 39 namespace v8 {
39 namespace internal { 40 namespace internal {
40 41
41 42
42 HeapGraphEdge::HeapGraphEdge(Type type, const char* name, int from, int to) 43 HeapGraphEdge::HeapGraphEdge(Type type, const char* name, int from, int to)
43 : type_(type), 44 : type_(type),
44 from_index_(from), 45 from_index_(from),
45 to_index_(to), 46 to_index_(to),
46 name_(name) { 47 name_(name) {
47 ASSERT(type == kContextVariable 48 ASSERT(type == kContextVariable
48 || type == kProperty 49 || type == kProperty
49 || type == kInternal 50 || type == kInternal
50 || type == kShortcut); 51 || type == kShortcut
52 || type == kWeak);
51 } 53 }
52 54
53 55
54 HeapGraphEdge::HeapGraphEdge(Type type, int index, int from, int to) 56 HeapGraphEdge::HeapGraphEdge(Type type, int index, int from, int to)
55 : type_(type), 57 : type_(type),
56 from_index_(from), 58 from_index_(from),
57 to_index_(to), 59 to_index_(to),
58 index_(index) { 60 index_(index) {
59 ASSERT(type == kElement || type == kHidden || type == kWeak); 61 ASSERT(type == kElement || type == kHidden);
60 } 62 }
61 63
62 64
63 void HeapGraphEdge::ReplaceToIndexWithEntry(HeapSnapshot* snapshot) { 65 void HeapGraphEdge::ReplaceToIndexWithEntry(HeapSnapshot* snapshot) {
64 to_entry_ = &snapshot->entries()[to_index_]; 66 to_entry_ = &snapshot->entries()[to_index_];
65 } 67 }
66 68
67 69
68 const int HeapEntry::kNoEntry = -1; 70 const int HeapEntry::kNoEntry = -1;
69 71
70 HeapEntry::HeapEntry(HeapSnapshot* snapshot, 72 HeapEntry::HeapEntry(HeapSnapshot* snapshot,
71 Type type, 73 Type type,
72 const char* name, 74 const char* name,
73 SnapshotObjectId id, 75 SnapshotObjectId id,
74 int self_size) 76 size_t self_size)
75 : type_(type), 77 : type_(type),
76 children_count_(0), 78 children_count_(0),
77 children_index_(-1), 79 children_index_(-1),
78 self_size_(self_size), 80 self_size_(self_size),
79 id_(id), 81 id_(id),
80 snapshot_(snapshot), 82 snapshot_(snapshot),
81 name_(name) { } 83 name_(name) { }
82 84
83 85
84 void HeapEntry::SetNamedReference(HeapGraphEdge::Type type, 86 void HeapEntry::SetNamedReference(HeapGraphEdge::Type type,
(...skipping 10 matching lines...) Expand all
95 HeapEntry* entry) { 97 HeapEntry* entry) {
96 HeapGraphEdge edge(type, index, this->index(), entry->index()); 98 HeapGraphEdge edge(type, index, this->index(), entry->index());
97 snapshot_->edges().Add(edge); 99 snapshot_->edges().Add(edge);
98 ++children_count_; 100 ++children_count_;
99 } 101 }
100 102
101 103
102 void HeapEntry::Print( 104 void HeapEntry::Print(
103 const char* prefix, const char* edge_name, int max_depth, int indent) { 105 const char* prefix, const char* edge_name, int max_depth, int indent) {
104 STATIC_CHECK(sizeof(unsigned) == sizeof(id())); 106 STATIC_CHECK(sizeof(unsigned) == sizeof(id()));
105 OS::Print("%6d @%6u %*c %s%s: ", 107 OS::Print("%6" V8PRIuPTR " @%6u %*c %s%s: ",
106 self_size(), id(), indent, ' ', prefix, edge_name); 108 self_size(), id(), indent, ' ', prefix, edge_name);
107 if (type() != kString) { 109 if (type() != kString) {
108 OS::Print("%s %.40s\n", TypeAsString(), name_); 110 OS::Print("%s %.40s\n", TypeAsString(), name_);
109 } else { 111 } else {
110 OS::Print("\""); 112 OS::Print("\"");
111 const char* c = name_; 113 const char* c = name_;
112 while (*c && (c - name_) <= 40) { 114 while (*c && (c - name_) <= 40) {
113 if (*c != '\n') 115 if (*c != '\n')
114 OS::Print("%c", *c); 116 OS::Print("%c", *c);
115 else 117 else
(...skipping 27 matching lines...) Expand all
143 case HeapGraphEdge::kHidden: 145 case HeapGraphEdge::kHidden:
144 edge_prefix = "$"; 146 edge_prefix = "$";
145 OS::SNPrintF(index, "%d", edge.index()); 147 OS::SNPrintF(index, "%d", edge.index());
146 break; 148 break;
147 case HeapGraphEdge::kShortcut: 149 case HeapGraphEdge::kShortcut:
148 edge_prefix = "^"; 150 edge_prefix = "^";
149 edge_name = edge.name(); 151 edge_name = edge.name();
150 break; 152 break;
151 case HeapGraphEdge::kWeak: 153 case HeapGraphEdge::kWeak:
152 edge_prefix = "w"; 154 edge_prefix = "w";
153 OS::SNPrintF(index, "%d", edge.index()); 155 edge_name = edge.name();
154 break; 156 break;
155 default: 157 default:
156 OS::SNPrintF(index, "!!! unknown edge type: %d ", edge.type()); 158 OS::SNPrintF(index, "!!! unknown edge type: %d ", edge.type());
157 } 159 }
158 edge.to()->Print(edge_prefix, edge_name, max_depth, indent + 2); 160 edge.to()->Print(edge_prefix, edge_name, max_depth, indent + 2);
159 } 161 }
160 } 162 }
161 163
162 164
163 const char* HeapEntry::TypeAsString() { 165 const char* HeapEntry::TypeAsString() {
(...skipping 21 matching lines...) Expand all
185 187
186 template <size_t ptr_size> struct SnapshotSizeConstants; 188 template <size_t ptr_size> struct SnapshotSizeConstants;
187 189
188 template <> struct SnapshotSizeConstants<4> { 190 template <> struct SnapshotSizeConstants<4> {
189 static const int kExpectedHeapGraphEdgeSize = 12; 191 static const int kExpectedHeapGraphEdgeSize = 12;
190 static const int kExpectedHeapEntrySize = 24; 192 static const int kExpectedHeapEntrySize = 24;
191 }; 193 };
192 194
193 template <> struct SnapshotSizeConstants<8> { 195 template <> struct SnapshotSizeConstants<8> {
194 static const int kExpectedHeapGraphEdgeSize = 24; 196 static const int kExpectedHeapGraphEdgeSize = 24;
195 static const int kExpectedHeapEntrySize = 32; 197 static const int kExpectedHeapEntrySize = 40;
196 }; 198 };
197 199
198 } // namespace 200 } // namespace
199 201
200 202
201 HeapSnapshot::HeapSnapshot(HeapProfiler* profiler, 203 HeapSnapshot::HeapSnapshot(HeapProfiler* profiler,
202 const char* title, 204 const char* title,
203 unsigned uid) 205 unsigned uid)
204 : profiler_(profiler), 206 : profiler_(profiler),
205 title_(title), 207 title_(title),
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
268 HeapObjectsMap::GetNthGcSubrootId(tag), 270 HeapObjectsMap::GetNthGcSubrootId(tag),
269 0); 271 0);
270 gc_subroot_indexes_[tag] = entry->index(); 272 gc_subroot_indexes_[tag] = entry->index();
271 return entry; 273 return entry;
272 } 274 }
273 275
274 276
275 HeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type, 277 HeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type,
276 const char* name, 278 const char* name,
277 SnapshotObjectId id, 279 SnapshotObjectId id,
278 int size) { 280 size_t size) {
279 HeapEntry entry(this, type, name, id, size); 281 HeapEntry entry(this, type, name, id, size);
280 entries_.Add(entry); 282 entries_.Add(entry);
281 return &entries_.last(); 283 return &entries_.last();
282 } 284 }
283 285
284 286
285 void HeapSnapshot::FillChildren() { 287 void HeapSnapshot::FillChildren() {
286 ASSERT(children().is_empty()); 288 ASSERT(children().is_empty());
287 children().Allocate(edges().length()); 289 children().Allocate(edges().length());
288 int children_index = 0; 290 int children_index = 0;
(...skipping 602 matching lines...) Expand 10 before | Expand all | Expand 10 after
891 } else if (object->IsHeapNumber()) { 893 } else if (object->IsHeapNumber()) {
892 return AddEntry(object, HeapEntry::kHeapNumber, "number"); 894 return AddEntry(object, HeapEntry::kHeapNumber, "number");
893 } 895 }
894 return AddEntry(object, HeapEntry::kHidden, GetSystemEntryName(object)); 896 return AddEntry(object, HeapEntry::kHidden, GetSystemEntryName(object));
895 } 897 }
896 898
897 899
898 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object, 900 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object,
899 HeapEntry::Type type, 901 HeapEntry::Type type,
900 const char* name) { 902 const char* name) {
901 int object_size = object->Size(); 903 return AddEntry(object->address(), type, name, object->Size());
902 SnapshotObjectId object_id =
903 heap_object_map_->FindOrAddEntry(object->address(), object_size);
904 return snapshot_->AddEntry(type, name, object_id, object_size);
905 } 904 }
906 905
907 906
907 HeapEntry* V8HeapExplorer::AddEntry(Address address,
908 HeapEntry::Type type,
909 const char* name,
910 size_t size) {
911 SnapshotObjectId object_id = heap_object_map_->FindOrAddEntry(
912 address, static_cast<unsigned int>(size));
913 return snapshot_->AddEntry(type, name, object_id, size);
914 }
915
916
908 class GcSubrootsEnumerator : public ObjectVisitor { 917 class GcSubrootsEnumerator : public ObjectVisitor {
909 public: 918 public:
910 GcSubrootsEnumerator( 919 GcSubrootsEnumerator(
911 SnapshotFillerInterface* filler, V8HeapExplorer* explorer) 920 SnapshotFillerInterface* filler, V8HeapExplorer* explorer)
912 : filler_(filler), 921 : filler_(filler),
913 explorer_(explorer), 922 explorer_(explorer),
914 previous_object_count_(0), 923 previous_object_count_(0),
915 object_count_(0) { 924 object_count_(0) {
916 } 925 }
917 void VisitPointers(Object** start, Object** end) { 926 void VisitPointers(Object** start, Object** end) {
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
984 parent_(parent), 993 parent_(parent),
985 next_index_(0) { 994 next_index_(0) {
986 } 995 }
987 void VisitCodeEntry(Address entry_address) { 996 void VisitCodeEntry(Address entry_address) {
988 Code* code = Code::cast(Code::GetObjectFromEntryAddress(entry_address)); 997 Code* code = Code::cast(Code::GetObjectFromEntryAddress(entry_address));
989 generator_->SetInternalReference(parent_obj_, parent_, "code", code); 998 generator_->SetInternalReference(parent_obj_, parent_, "code", code);
990 generator_->TagCodeObject(code); 999 generator_->TagCodeObject(code);
991 } 1000 }
992 void VisitPointers(Object** start, Object** end) { 1001 void VisitPointers(Object** start, Object** end) {
993 for (Object** p = start; p < end; p++) { 1002 for (Object** p = start; p < end; p++) {
1003 ++next_index_;
994 if (CheckVisitedAndUnmark(p)) continue; 1004 if (CheckVisitedAndUnmark(p)) continue;
995 generator_->SetHiddenReference(parent_obj_, parent_, next_index_++, *p); 1005 generator_->SetHiddenReference(parent_obj_, parent_, next_index_, *p);
996 } 1006 }
997 } 1007 }
998 static void MarkVisitedField(HeapObject* obj, int offset) { 1008 static void MarkVisitedField(HeapObject* obj, int offset) {
999 if (offset < 0) return; 1009 if (offset < 0) return;
1000 Address field = obj->address() + offset; 1010 Address field = obj->address() + offset;
1001 ASSERT(!Memory::Object_at(field)->IsFailure()); 1011 ASSERT(!Memory::Object_at(field)->IsFailure());
1002 ASSERT(Memory::Object_at(field)->IsHeapObject()); 1012 ASSERT(Memory::Object_at(field)->IsHeapObject());
1003 *field |= kFailureTag; 1013 *field |= kFailureTag;
1004 } 1014 }
1005 1015
(...skipping 14 matching lines...) Expand all
1020 }; 1030 };
1021 1031
1022 1032
1023 void V8HeapExplorer::ExtractReferences(HeapObject* obj) { 1033 void V8HeapExplorer::ExtractReferences(HeapObject* obj) {
1024 HeapEntry* heap_entry = GetEntry(obj); 1034 HeapEntry* heap_entry = GetEntry(obj);
1025 if (heap_entry == NULL) return; // No interest in this object. 1035 if (heap_entry == NULL) return; // No interest in this object.
1026 int entry = heap_entry->index(); 1036 int entry = heap_entry->index();
1027 1037
1028 if (obj->IsJSGlobalProxy()) { 1038 if (obj->IsJSGlobalProxy()) {
1029 ExtractJSGlobalProxyReferences(entry, JSGlobalProxy::cast(obj)); 1039 ExtractJSGlobalProxyReferences(entry, JSGlobalProxy::cast(obj));
1040 } else if (obj->IsJSArrayBuffer()) {
1041 ExtractJSArrayBufferReferences(entry, JSArrayBuffer::cast(obj));
1030 } else if (obj->IsJSObject()) { 1042 } else if (obj->IsJSObject()) {
1031 ExtractJSObjectReferences(entry, JSObject::cast(obj)); 1043 ExtractJSObjectReferences(entry, JSObject::cast(obj));
1032 } else if (obj->IsString()) { 1044 } else if (obj->IsString()) {
1033 ExtractStringReferences(entry, String::cast(obj)); 1045 ExtractStringReferences(entry, String::cast(obj));
1034 } else if (obj->IsContext()) { 1046 } else if (obj->IsContext()) {
1035 ExtractContextReferences(entry, Context::cast(obj)); 1047 ExtractContextReferences(entry, Context::cast(obj));
1036 } else if (obj->IsMap()) { 1048 } else if (obj->IsMap()) {
1037 ExtractMapReferences(entry, Map::cast(obj)); 1049 ExtractMapReferences(entry, Map::cast(obj));
1038 } else if (obj->IsSharedFunctionInfo()) { 1050 } else if (obj->IsSharedFunctionInfo()) {
1039 ExtractSharedFunctionInfoReferences(entry, SharedFunctionInfo::cast(obj)); 1051 ExtractSharedFunctionInfoReferences(entry, SharedFunctionInfo::cast(obj));
1040 } else if (obj->IsScript()) { 1052 } else if (obj->IsScript()) {
1041 ExtractScriptReferences(entry, Script::cast(obj)); 1053 ExtractScriptReferences(entry, Script::cast(obj));
1042 } else if (obj->IsAccessorPair()) { 1054 } else if (obj->IsAccessorPair()) {
1043 ExtractAccessorPairReferences(entry, AccessorPair::cast(obj)); 1055 ExtractAccessorPairReferences(entry, AccessorPair::cast(obj));
1044 } else if (obj->IsCodeCache()) { 1056 } else if (obj->IsCodeCache()) {
1045 ExtractCodeCacheReferences(entry, CodeCache::cast(obj)); 1057 ExtractCodeCacheReferences(entry, CodeCache::cast(obj));
1046 } else if (obj->IsCode()) { 1058 } else if (obj->IsCode()) {
1047 ExtractCodeReferences(entry, Code::cast(obj)); 1059 ExtractCodeReferences(entry, Code::cast(obj));
1060 } else if (obj->IsBox()) {
1061 ExtractBoxReferences(entry, Box::cast(obj));
1048 } else if (obj->IsCell()) { 1062 } else if (obj->IsCell()) {
1049 ExtractCellReferences(entry, Cell::cast(obj)); 1063 ExtractCellReferences(entry, Cell::cast(obj));
1050 } else if (obj->IsPropertyCell()) { 1064 } else if (obj->IsPropertyCell()) {
1051 ExtractPropertyCellReferences(entry, PropertyCell::cast(obj)); 1065 ExtractPropertyCellReferences(entry, PropertyCell::cast(obj));
1052 } else if (obj->IsAllocationSite()) { 1066 } else if (obj->IsAllocationSite()) {
1053 ExtractAllocationSiteReferences(entry, AllocationSite::cast(obj)); 1067 ExtractAllocationSiteReferences(entry, AllocationSite::cast(obj));
1054 } 1068 }
1055 SetInternalReference(obj, entry, "map", obj->map(), HeapObject::kMapOffset); 1069 SetInternalReference(obj, entry, "map", obj->map(), HeapObject::kMapOffset);
1056 1070
1057 // Extract unvisited fields as hidden references and restore tags 1071 // Extract unvisited fields as hidden references and restore tags
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1107 js_fun->literals_or_bindings(), 1121 js_fun->literals_or_bindings(),
1108 JSFunction::kLiteralsOffset); 1122 JSFunction::kLiteralsOffset);
1109 TagObject(shared_info, "(shared function info)"); 1123 TagObject(shared_info, "(shared function info)");
1110 SetInternalReference(js_fun, entry, 1124 SetInternalReference(js_fun, entry,
1111 "shared", shared_info, 1125 "shared", shared_info,
1112 JSFunction::kSharedFunctionInfoOffset); 1126 JSFunction::kSharedFunctionInfoOffset);
1113 TagObject(js_fun->context(), "(context)"); 1127 TagObject(js_fun->context(), "(context)");
1114 SetInternalReference(js_fun, entry, 1128 SetInternalReference(js_fun, entry,
1115 "context", js_fun->context(), 1129 "context", js_fun->context(),
1116 JSFunction::kContextOffset); 1130 JSFunction::kContextOffset);
1117 for (int i = JSFunction::kNonWeakFieldsEndOffset; 1131 SetWeakReference(js_fun, entry,
1118 i < JSFunction::kSize; 1132 "next_function_link", js_fun->next_function_link(),
1119 i += kPointerSize) { 1133 JSFunction::kNextFunctionLinkOffset);
1120 SetWeakReference(js_fun, entry, i, *HeapObject::RawField(js_fun, i), i); 1134 STATIC_CHECK(JSFunction::kNextFunctionLinkOffset
1121 } 1135 == JSFunction::kNonWeakFieldsEndOffset);
1136 STATIC_CHECK(JSFunction::kNextFunctionLinkOffset + kPointerSize
1137 == JSFunction::kSize);
1122 } else if (obj->IsGlobalObject()) { 1138 } else if (obj->IsGlobalObject()) {
1123 GlobalObject* global_obj = GlobalObject::cast(obj); 1139 GlobalObject* global_obj = GlobalObject::cast(obj);
1124 SetInternalReference(global_obj, entry, 1140 SetInternalReference(global_obj, entry,
1125 "builtins", global_obj->builtins(), 1141 "builtins", global_obj->builtins(),
1126 GlobalObject::kBuiltinsOffset); 1142 GlobalObject::kBuiltinsOffset);
1127 SetInternalReference(global_obj, entry, 1143 SetInternalReference(global_obj, entry,
1128 "native_context", global_obj->native_context(), 1144 "native_context", global_obj->native_context(),
1129 GlobalObject::kNativeContextOffset); 1145 GlobalObject::kNativeContextOffset);
1130 SetInternalReference(global_obj, entry, 1146 SetInternalReference(global_obj, entry,
1147 "global_context", global_obj->global_context(),
1148 GlobalObject::kGlobalContextOffset);
1149 SetInternalReference(global_obj, entry,
1131 "global_receiver", global_obj->global_receiver(), 1150 "global_receiver", global_obj->global_receiver(),
1132 GlobalObject::kGlobalReceiverOffset); 1151 GlobalObject::kGlobalReceiverOffset);
1152 STATIC_CHECK(GlobalObject::kHeaderSize - JSObject::kHeaderSize ==
1153 4 * kPointerSize);
1154 } else if (obj->IsJSArrayBufferView()) {
1155 JSArrayBufferView* view = JSArrayBufferView::cast(obj);
1156 SetInternalReference(view, entry, "buffer", view->buffer(),
1157 JSArrayBufferView::kBufferOffset);
1158 SetWeakReference(view, entry, "weak_next", view->weak_next(),
1159 JSArrayBufferView::kWeakNextOffset);
1133 } 1160 }
1134 TagObject(js_obj->properties(), "(object properties)"); 1161 TagObject(js_obj->properties(), "(object properties)");
1135 SetInternalReference(obj, entry, 1162 SetInternalReference(obj, entry,
1136 "properties", js_obj->properties(), 1163 "properties", js_obj->properties(),
1137 JSObject::kPropertiesOffset); 1164 JSObject::kPropertiesOffset);
1138 TagObject(js_obj->elements(), "(object elements)"); 1165 TagObject(js_obj->elements(), "(object elements)");
1139 SetInternalReference(obj, entry, 1166 SetInternalReference(obj, entry,
1140 "elements", js_obj->elements(), 1167 "elements", js_obj->elements(),
1141 JSObject::kElementsOffset); 1168 JSObject::kElementsOffset);
1142 } 1169 }
(...skipping 30 matching lines...) Expand all
1173 VariableMode mode; 1200 VariableMode mode;
1174 int idx = scope_info->FunctionContextSlotIndex(name, &mode); 1201 int idx = scope_info->FunctionContextSlotIndex(name, &mode);
1175 if (idx >= 0) { 1202 if (idx >= 0) {
1176 SetContextReference(context, entry, name, context->get(idx), 1203 SetContextReference(context, entry, name, context->get(idx),
1177 Context::OffsetOfElementAt(idx)); 1204 Context::OffsetOfElementAt(idx));
1178 } 1205 }
1179 } 1206 }
1180 } 1207 }
1181 1208
1182 #define EXTRACT_CONTEXT_FIELD(index, type, name) \ 1209 #define EXTRACT_CONTEXT_FIELD(index, type, name) \
1183 SetInternalReference(context, entry, #name, context->get(Context::index), \ 1210 if (Context::index < Context::FIRST_WEAK_SLOT) { \
1184 FixedArray::OffsetOfElementAt(Context::index)); 1211 SetInternalReference(context, entry, #name, context->get(Context::index), \
1212 FixedArray::OffsetOfElementAt(Context::index)); \
1213 } else { \
1214 SetWeakReference(context, entry, #name, context->get(Context::index), \
1215 FixedArray::OffsetOfElementAt(Context::index)); \
1216 }
1185 EXTRACT_CONTEXT_FIELD(CLOSURE_INDEX, JSFunction, closure); 1217 EXTRACT_CONTEXT_FIELD(CLOSURE_INDEX, JSFunction, closure);
1186 EXTRACT_CONTEXT_FIELD(PREVIOUS_INDEX, Context, previous); 1218 EXTRACT_CONTEXT_FIELD(PREVIOUS_INDEX, Context, previous);
1187 EXTRACT_CONTEXT_FIELD(EXTENSION_INDEX, Object, extension); 1219 EXTRACT_CONTEXT_FIELD(EXTENSION_INDEX, Object, extension);
1188 EXTRACT_CONTEXT_FIELD(GLOBAL_OBJECT_INDEX, GlobalObject, global); 1220 EXTRACT_CONTEXT_FIELD(GLOBAL_OBJECT_INDEX, GlobalObject, global);
1189 if (context->IsNativeContext()) { 1221 if (context->IsNativeContext()) {
1190 TagObject(context->jsfunction_result_caches(), 1222 TagObject(context->jsfunction_result_caches(),
1191 "(context func. result caches)"); 1223 "(context func. result caches)");
1192 TagObject(context->normalized_map_cache(), "(context norm. map cache)"); 1224 TagObject(context->normalized_map_cache(), "(context norm. map cache)");
1193 TagObject(context->runtime_context(), "(runtime context)"); 1225 TagObject(context->runtime_context(), "(runtime context)");
1194 TagObject(context->embedder_data(), "(context data)"); 1226 TagObject(context->embedder_data(), "(context data)");
1195 NATIVE_CONTEXT_FIELDS(EXTRACT_CONTEXT_FIELD); 1227 NATIVE_CONTEXT_FIELDS(EXTRACT_CONTEXT_FIELD);
1228 EXTRACT_CONTEXT_FIELD(OPTIMIZED_FUNCTIONS_LIST, unused,
1229 optimized_functions_list);
1230 EXTRACT_CONTEXT_FIELD(OPTIMIZED_CODE_LIST, unused, optimized_code_list);
1231 EXTRACT_CONTEXT_FIELD(DEOPTIMIZED_CODE_LIST, unused, deoptimized_code_list);
1232 EXTRACT_CONTEXT_FIELD(NEXT_CONTEXT_LINK, unused, next_context_link);
1196 #undef EXTRACT_CONTEXT_FIELD 1233 #undef EXTRACT_CONTEXT_FIELD
1197 for (int i = Context::FIRST_WEAK_SLOT; 1234 STATIC_CHECK(Context::OPTIMIZED_FUNCTIONS_LIST == Context::FIRST_WEAK_SLOT);
1198 i < Context::NATIVE_CONTEXT_SLOTS; 1235 STATIC_CHECK(Context::NEXT_CONTEXT_LINK + 1
1199 ++i) { 1236 == Context::NATIVE_CONTEXT_SLOTS);
1200 SetWeakReference(context, entry, i, context->get(i), 1237 STATIC_CHECK(Context::FIRST_WEAK_SLOT + 5 == Context::NATIVE_CONTEXT_SLOTS);
1201 FixedArray::OffsetOfElementAt(i));
1202 }
1203 } 1238 }
1204 } 1239 }
1205 1240
1206 1241
1207 void V8HeapExplorer::ExtractMapReferences(int entry, Map* map) { 1242 void V8HeapExplorer::ExtractMapReferences(int entry, Map* map) {
1208 if (map->HasTransitionArray()) { 1243 if (map->HasTransitionArray()) {
1209 TransitionArray* transitions = map->transitions(); 1244 TransitionArray* transitions = map->transitions();
1210 int transitions_entry = GetEntry(transitions)->index(); 1245 int transitions_entry = GetEntry(transitions)->index();
1211 Object* back_pointer = transitions->back_pointer_storage(); 1246 Object* back_pointer = transitions->back_pointer_storage();
1212 TagObject(back_pointer, "(back pointer)"); 1247 TagObject(back_pointer, "(back pointer)");
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
1286 SetInternalReference(obj, entry, 1321 SetInternalReference(obj, entry,
1287 "debug_info", shared->debug_info(), 1322 "debug_info", shared->debug_info(),
1288 SharedFunctionInfo::kDebugInfoOffset); 1323 SharedFunctionInfo::kDebugInfoOffset);
1289 SetInternalReference(obj, entry, 1324 SetInternalReference(obj, entry,
1290 "inferred_name", shared->inferred_name(), 1325 "inferred_name", shared->inferred_name(),
1291 SharedFunctionInfo::kInferredNameOffset); 1326 SharedFunctionInfo::kInferredNameOffset);
1292 SetInternalReference(obj, entry, 1327 SetInternalReference(obj, entry,
1293 "optimized_code_map", shared->optimized_code_map(), 1328 "optimized_code_map", shared->optimized_code_map(),
1294 SharedFunctionInfo::kOptimizedCodeMapOffset); 1329 SharedFunctionInfo::kOptimizedCodeMapOffset);
1295 SetWeakReference(obj, entry, 1330 SetWeakReference(obj, entry,
1296 1, shared->initial_map(), 1331 "initial_map", shared->initial_map(),
1297 SharedFunctionInfo::kInitialMapOffset); 1332 SharedFunctionInfo::kInitialMapOffset);
1298 } 1333 }
1299 1334
1300 1335
1301 void V8HeapExplorer::ExtractScriptReferences(int entry, Script* script) { 1336 void V8HeapExplorer::ExtractScriptReferences(int entry, Script* script) {
1302 HeapObject* obj = script; 1337 HeapObject* obj = script;
1303 SetInternalReference(obj, entry, 1338 SetInternalReference(obj, entry,
1304 "source", script->source(), 1339 "source", script->source(),
1305 Script::kSourceOffset); 1340 Script::kSourceOffset);
1306 SetInternalReference(obj, entry, 1341 SetInternalReference(obj, entry,
(...skipping 27 matching lines...) Expand all
1334 SetInternalReference(code_cache, entry, 1369 SetInternalReference(code_cache, entry,
1335 "default_cache", code_cache->default_cache(), 1370 "default_cache", code_cache->default_cache(),
1336 CodeCache::kDefaultCacheOffset); 1371 CodeCache::kDefaultCacheOffset);
1337 TagObject(code_cache->normal_type_cache(), "(code type cache)"); 1372 TagObject(code_cache->normal_type_cache(), "(code type cache)");
1338 SetInternalReference(code_cache, entry, 1373 SetInternalReference(code_cache, entry,
1339 "type_cache", code_cache->normal_type_cache(), 1374 "type_cache", code_cache->normal_type_cache(),
1340 CodeCache::kNormalTypeCacheOffset); 1375 CodeCache::kNormalTypeCacheOffset);
1341 } 1376 }
1342 1377
1343 1378
1344 void V8HeapExplorer::TagCodeObject(Code* code, const char* external_name) { 1379 void V8HeapExplorer::TagBuiltinCodeObject(Code* code, const char* name) {
1345 TagObject(code, names_->GetFormatted("(%s code)", external_name)); 1380 TagObject(code, names_->GetFormatted("(%s builtin)", name));
1346 } 1381 }
1347 1382
1348 1383
1349 void V8HeapExplorer::TagCodeObject(Code* code) { 1384 void V8HeapExplorer::TagCodeObject(Code* code) {
1350 if (code->kind() == Code::STUB) { 1385 if (code->kind() == Code::STUB) {
1351 TagObject(code, names_->GetFormatted( 1386 TagObject(code, names_->GetFormatted(
1352 "(%s code)", CodeStub::MajorName( 1387 "(%s code)", CodeStub::MajorName(
1353 static_cast<CodeStub::Major>(code->major_key()), true))); 1388 static_cast<CodeStub::Major>(code->major_key()), true)));
1354 } 1389 }
1355 } 1390 }
(...skipping 16 matching lines...) Expand all
1372 SetInternalReference(code, entry, 1407 SetInternalReference(code, entry,
1373 "type_feedback_info", code->type_feedback_info(), 1408 "type_feedback_info", code->type_feedback_info(),
1374 Code::kTypeFeedbackInfoOffset); 1409 Code::kTypeFeedbackInfoOffset);
1375 } 1410 }
1376 SetInternalReference(code, entry, 1411 SetInternalReference(code, entry,
1377 "gc_metadata", code->gc_metadata(), 1412 "gc_metadata", code->gc_metadata(),
1378 Code::kGCMetadataOffset); 1413 Code::kGCMetadataOffset);
1379 SetInternalReference(code, entry, 1414 SetInternalReference(code, entry,
1380 "constant_pool", code->constant_pool(), 1415 "constant_pool", code->constant_pool(),
1381 Code::kConstantPoolOffset); 1416 Code::kConstantPoolOffset);
1417 if (code->kind() == Code::OPTIMIZED_FUNCTION) {
1418 SetWeakReference(code, entry,
1419 "next_code_link", code->next_code_link(),
1420 Code::kNextCodeLinkOffset);
1421 }
1382 } 1422 }
1383 1423
1384 1424
1425 void V8HeapExplorer::ExtractBoxReferences(int entry, Box* box) {
1426 SetInternalReference(box, entry, "value", box->value(), Box::kValueOffset);
1427 }
1428
1429
1385 void V8HeapExplorer::ExtractCellReferences(int entry, Cell* cell) { 1430 void V8HeapExplorer::ExtractCellReferences(int entry, Cell* cell) {
1386 SetInternalReference(cell, entry, "value", cell->value(), Cell::kValueOffset); 1431 SetInternalReference(cell, entry, "value", cell->value(), Cell::kValueOffset);
1387 } 1432 }
1388 1433
1389 1434
1390 void V8HeapExplorer::ExtractPropertyCellReferences(int entry, 1435 void V8HeapExplorer::ExtractPropertyCellReferences(int entry,
1391 PropertyCell* cell) { 1436 PropertyCell* cell) {
1392 ExtractCellReferences(entry, cell); 1437 ExtractCellReferences(entry, cell);
1393 SetInternalReference(cell, entry, "type", cell->type(), 1438 SetInternalReference(cell, entry, "type", cell->type(),
1394 PropertyCell::kTypeOffset); 1439 PropertyCell::kTypeOffset);
1395 SetInternalReference(cell, entry, "dependent_code", cell->dependent_code(), 1440 SetInternalReference(cell, entry, "dependent_code", cell->dependent_code(),
1396 PropertyCell::kDependentCodeOffset); 1441 PropertyCell::kDependentCodeOffset);
1397 } 1442 }
1398 1443
1399 1444
1400 void V8HeapExplorer::ExtractAllocationSiteReferences(int entry, 1445 void V8HeapExplorer::ExtractAllocationSiteReferences(int entry,
1401 AllocationSite* site) { 1446 AllocationSite* site) {
1402 SetInternalReference(site, entry, "transition_info", site->transition_info(), 1447 SetInternalReference(site, entry, "transition_info", site->transition_info(),
1403 AllocationSite::kTransitionInfoOffset); 1448 AllocationSite::kTransitionInfoOffset);
1404 SetInternalReference(site, entry, "nested_site", site->nested_site(), 1449 SetInternalReference(site, entry, "nested_site", site->nested_site(),
1405 AllocationSite::kNestedSiteOffset); 1450 AllocationSite::kNestedSiteOffset);
1406 SetInternalReference(site, entry, "pretenure_data",
1407 site->pretenure_data(),
1408 AllocationSite::kPretenureDataOffset);
1409 SetInternalReference(site, entry, "pretenure_create_count",
1410 site->pretenure_create_count(),
1411 AllocationSite::kPretenureCreateCountOffset);
1412 SetInternalReference(site, entry, "dependent_code", site->dependent_code(), 1451 SetInternalReference(site, entry, "dependent_code", site->dependent_code(),
1413 AllocationSite::kDependentCodeOffset); 1452 AllocationSite::kDependentCodeOffset);
1453 // Do not visit weak_next as it is not visited by the StaticVisitor,
1454 // and we're not very interested in weak_next field here.
1455 STATIC_CHECK(AllocationSite::kWeakNextOffset >=
1456 AllocationSite::BodyDescriptor::kEndOffset);
1414 } 1457 }
1415 1458
1416 1459
1460 class JSArrayBufferDataEntryAllocator : public HeapEntriesAllocator {
1461 public:
1462 JSArrayBufferDataEntryAllocator(size_t size, V8HeapExplorer* explorer)
1463 : size_(size)
1464 , explorer_(explorer) {
1465 }
1466 virtual HeapEntry* AllocateEntry(HeapThing ptr) {
1467 return explorer_->AddEntry(
1468 static_cast<Address>(ptr),
1469 HeapEntry::kNative, "system / JSArrayBufferData", size_);
1470 }
1471 private:
1472 size_t size_;
1473 V8HeapExplorer* explorer_;
1474 };
1475
1476
1477 void V8HeapExplorer::ExtractJSArrayBufferReferences(
1478 int entry, JSArrayBuffer* buffer) {
1479 SetWeakReference(buffer, entry, "weak_next", buffer->weak_next(),
1480 JSArrayBuffer::kWeakNextOffset);
1481 SetWeakReference(buffer, entry,
1482 "weak_first_view", buffer->weak_first_view(),
1483 JSArrayBuffer::kWeakFirstViewOffset);
1484 // Setup a reference to a native memory backing_store object.
1485 if (!buffer->backing_store())
1486 return;
1487 size_t data_size = NumberToSize(heap_->isolate(), buffer->byte_length());
1488 JSArrayBufferDataEntryAllocator allocator(data_size, this);
1489 HeapEntry* data_entry =
1490 filler_->FindOrAddEntry(buffer->backing_store(), &allocator);
1491 filler_->SetNamedReference(HeapGraphEdge::kInternal,
1492 entry, "backing_store", data_entry);
1493 }
1494
1495
1417 void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj, int entry) { 1496 void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj, int entry) {
1418 if (!js_obj->IsJSFunction()) return; 1497 if (!js_obj->IsJSFunction()) return;
1419 1498
1420 JSFunction* func = JSFunction::cast(js_obj); 1499 JSFunction* func = JSFunction::cast(js_obj);
1421 if (func->shared()->bound()) { 1500 if (func->shared()->bound()) {
1422 FixedArray* bindings = func->function_bindings(); 1501 FixedArray* bindings = func->function_bindings();
1423 SetNativeBindReference(js_obj, entry, "bound_this", 1502 SetNativeBindReference(js_obj, entry, "bound_this",
1424 bindings->get(JSFunction::kBoundThisIndex)); 1503 bindings->get(JSFunction::kBoundThisIndex));
1425 SetNativeBindReference(js_obj, entry, "bound_function", 1504 SetNativeBindReference(js_obj, entry, "bound_function",
1426 bindings->get(JSFunction::kBoundFunctionIndex)); 1505 bindings->get(JSFunction::kBoundFunctionIndex));
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
1628 void SetCollectingAllReferences() { collecting_all_references_ = true; } 1707 void SetCollectingAllReferences() { collecting_all_references_ = true; }
1629 1708
1630 void FillReferences(V8HeapExplorer* explorer) { 1709 void FillReferences(V8HeapExplorer* explorer) {
1631 ASSERT(strong_references_.length() <= all_references_.length()); 1710 ASSERT(strong_references_.length() <= all_references_.length());
1632 Builtins* builtins = heap_->isolate()->builtins(); 1711 Builtins* builtins = heap_->isolate()->builtins();
1633 for (int i = 0; i < reference_tags_.length(); ++i) { 1712 for (int i = 0; i < reference_tags_.length(); ++i) {
1634 explorer->SetGcRootsReference(reference_tags_[i].tag); 1713 explorer->SetGcRootsReference(reference_tags_[i].tag);
1635 } 1714 }
1636 int strong_index = 0, all_index = 0, tags_index = 0, builtin_index = 0; 1715 int strong_index = 0, all_index = 0, tags_index = 0, builtin_index = 0;
1637 while (all_index < all_references_.length()) { 1716 while (all_index < all_references_.length()) {
1638 if (strong_index < strong_references_.length() && 1717 bool is_strong = strong_index < strong_references_.length()
1639 strong_references_[strong_index] == all_references_[all_index]) { 1718 && strong_references_[strong_index] == all_references_[all_index];
1640 explorer->SetGcSubrootReference(reference_tags_[tags_index].tag, 1719 explorer->SetGcSubrootReference(reference_tags_[tags_index].tag,
1641 false, 1720 !is_strong,
1642 all_references_[all_index]); 1721 all_references_[all_index]);
1643 ++strong_index;
1644 } else {
1645 explorer->SetGcSubrootReference(reference_tags_[tags_index].tag,
1646 true,
1647 all_references_[all_index]);
1648 }
1649 if (reference_tags_[tags_index].tag == 1722 if (reference_tags_[tags_index].tag ==
1650 VisitorSynchronization::kBuiltins) { 1723 VisitorSynchronization::kBuiltins) {
1651 ASSERT(all_references_[all_index]->IsCode()); 1724 ASSERT(all_references_[all_index]->IsCode());
1652 explorer->TagCodeObject(Code::cast(all_references_[all_index]), 1725 explorer->TagBuiltinCodeObject(
1726 Code::cast(all_references_[all_index]),
1653 builtins->name(builtin_index++)); 1727 builtins->name(builtin_index++));
1654 } 1728 }
1655 ++all_index; 1729 ++all_index;
1730 if (is_strong) ++strong_index;
1656 if (reference_tags_[tags_index].index == all_index) ++tags_index; 1731 if (reference_tags_[tags_index].index == all_index) ++tags_index;
1657 } 1732 }
1658 } 1733 }
1659 1734
1660 void Synchronize(VisitorSynchronization::SyncTag tag) { 1735 void Synchronize(VisitorSynchronization::SyncTag tag) {
1661 if (collecting_all_references_ && 1736 if (collecting_all_references_ &&
1662 previous_reference_count_ != all_references_.length()) { 1737 previous_reference_count_ != all_references_.length()) {
1663 previous_reference_count_ = all_references_.length(); 1738 previous_reference_count_ = all_references_.length();
1664 reference_tags_.Add(IndexTag(previous_reference_count_, tag)); 1739 reference_tags_.Add(IndexTag(previous_reference_count_, tag));
1665 } 1740 }
1666 } 1741 }
1667 1742
1668 private: 1743 private:
1669 bool collecting_all_references_; 1744 bool collecting_all_references_;
1670 List<Object*> strong_references_; 1745 List<Object*> strong_references_;
1671 List<Object*> all_references_; 1746 List<Object*> all_references_;
1672 int previous_reference_count_; 1747 int previous_reference_count_;
1673 List<IndexTag> reference_tags_; 1748 List<IndexTag> reference_tags_;
1674 Heap* heap_; 1749 Heap* heap_;
1675 }; 1750 };
1676 1751
1677 1752
1678 bool V8HeapExplorer::IterateAndExtractReferences( 1753 bool V8HeapExplorer::IterateAndExtractReferences(
1679 SnapshotFillerInterface* filler) { 1754 SnapshotFillerInterface* filler) {
1755 filler_ = filler;
1756
1757 // Make sure builtin code objects get their builtin tags
1758 // first. Otherwise a particular JSFunction object could set
1759 // its custom name to a generic builtin.
1760 SetRootGcRootsReference();
1761 RootsReferencesExtractor extractor(heap_);
1762 heap_->IterateRoots(&extractor, VISIT_ONLY_STRONG);
1763 extractor.SetCollectingAllReferences();
1764 heap_->IterateRoots(&extractor, VISIT_ALL);
1765 extractor.FillReferences(this);
1766
1767 // Now iterate the whole heap.
1768 bool interrupted = false;
1680 HeapIterator iterator(heap_, HeapIterator::kFilterUnreachable); 1769 HeapIterator iterator(heap_, HeapIterator::kFilterUnreachable);
1681
1682 filler_ = filler;
1683 bool interrupted = false;
1684
1685 // Heap iteration with filtering must be finished in any case. 1770 // Heap iteration with filtering must be finished in any case.
1686 for (HeapObject* obj = iterator.next(); 1771 for (HeapObject* obj = iterator.next();
1687 obj != NULL; 1772 obj != NULL;
1688 obj = iterator.next(), progress_->ProgressStep()) { 1773 obj = iterator.next(), progress_->ProgressStep()) {
1689 if (!interrupted) { 1774 if (!interrupted) {
1690 ExtractReferences(obj); 1775 ExtractReferences(obj);
1691 if (!progress_->ProgressReport(false)) interrupted = true; 1776 if (!progress_->ProgressReport(false)) interrupted = true;
1692 } 1777 }
1693 } 1778 }
1694 if (interrupted) { 1779 if (interrupted) {
1695 filler_ = NULL; 1780 filler_ = NULL;
1696 return false; 1781 return false;
1697 } 1782 }
1698 1783
1699 SetRootGcRootsReference();
1700 RootsReferencesExtractor extractor(heap_);
1701 heap_->IterateRoots(&extractor, VISIT_ONLY_STRONG);
1702 extractor.SetCollectingAllReferences();
1703 heap_->IterateRoots(&extractor, VISIT_ALL);
1704 extractor.FillReferences(this);
1705 filler_ = NULL; 1784 filler_ = NULL;
1706 return progress_->ProgressReport(true); 1785 return progress_->ProgressReport(true);
1707 } 1786 }
1708 1787
1709 1788
1710 bool V8HeapExplorer::IsEssentialObject(Object* object) { 1789 bool V8HeapExplorer::IsEssentialObject(Object* object) {
1711 return object->IsHeapObject() 1790 return object->IsHeapObject()
1712 && !object->IsOddball() 1791 && !object->IsOddball()
1713 && object != heap_->empty_byte_array() 1792 && object != heap_->empty_byte_array()
1714 && object != heap_->empty_fixed_array() 1793 && object != heap_->empty_fixed_array()
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
1816 filler_->SetIndexedReference(HeapGraphEdge::kHidden, 1895 filler_->SetIndexedReference(HeapGraphEdge::kHidden,
1817 parent_entry, 1896 parent_entry,
1818 index, 1897 index,
1819 child_entry); 1898 child_entry);
1820 } 1899 }
1821 } 1900 }
1822 1901
1823 1902
1824 void V8HeapExplorer::SetWeakReference(HeapObject* parent_obj, 1903 void V8HeapExplorer::SetWeakReference(HeapObject* parent_obj,
1825 int parent_entry, 1904 int parent_entry,
1826 int index, 1905 const char* reference_name,
1827 Object* child_obj, 1906 Object* child_obj,
1828 int field_offset) { 1907 int field_offset) {
1829 ASSERT(parent_entry == GetEntry(parent_obj)->index()); 1908 ASSERT(parent_entry == GetEntry(parent_obj)->index());
1830 HeapEntry* child_entry = GetEntry(child_obj); 1909 HeapEntry* child_entry = GetEntry(child_obj);
1831 if (child_entry == NULL) return; 1910 if (child_entry == NULL) return;
1832 if (IsEssentialObject(child_obj)) { 1911 if (IsEssentialObject(child_obj)) {
1833 filler_->SetIndexedReference(HeapGraphEdge::kWeak, 1912 filler_->SetNamedReference(HeapGraphEdge::kWeak,
1834 parent_entry, 1913 parent_entry,
1835 index, 1914 reference_name,
1836 child_entry); 1915 child_entry);
1837 } 1916 }
1838 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset); 1917 IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset);
1839 } 1918 }
1840 1919
1841 1920
1842 void V8HeapExplorer::SetPropertyReference(HeapObject* parent_obj, 1921 void V8HeapExplorer::SetPropertyReference(HeapObject* parent_obj,
1843 int parent_entry, 1922 int parent_entry,
1844 Name* reference_name, 1923 Name* reference_name,
1845 Object* child_obj, 1924 Object* child_obj,
1846 const char* name_format_string, 1925 const char* name_format_string,
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1898 HeapEntry* child_entry = GetEntry(child_obj); 1977 HeapEntry* child_entry = GetEntry(child_obj);
1899 if (child_entry != NULL) { 1978 if (child_entry != NULL) {
1900 const char* name = GetStrongGcSubrootName(child_obj); 1979 const char* name = GetStrongGcSubrootName(child_obj);
1901 if (name != NULL) { 1980 if (name != NULL) {
1902 filler_->SetNamedReference( 1981 filler_->SetNamedReference(
1903 HeapGraphEdge::kInternal, 1982 HeapGraphEdge::kInternal,
1904 snapshot_->gc_subroot(tag)->index(), 1983 snapshot_->gc_subroot(tag)->index(),
1905 name, 1984 name,
1906 child_entry); 1985 child_entry);
1907 } else { 1986 } else {
1908 filler_->SetIndexedAutoIndexReference( 1987 if (is_weak) {
1909 is_weak ? HeapGraphEdge::kWeak : HeapGraphEdge::kElement, 1988 filler_->SetNamedAutoIndexReference(
1910 snapshot_->gc_subroot(tag)->index(), 1989 HeapGraphEdge::kWeak,
1911 child_entry); 1990 snapshot_->gc_subroot(tag)->index(),
1991 child_entry);
1992 } else {
1993 filler_->SetIndexedAutoIndexReference(
1994 HeapGraphEdge::kElement,
1995 snapshot_->gc_subroot(tag)->index(),
1996 child_entry);
1997 }
1912 } 1998 }
1913 1999
1914 // Add a shortcut to JS global object reference at snapshot root. 2000 // Add a shortcut to JS global object reference at snapshot root.
1915 if (child_obj->IsNativeContext()) { 2001 if (child_obj->IsNativeContext()) {
1916 Context* context = Context::cast(child_obj); 2002 Context* context = Context::cast(child_obj);
1917 GlobalObject* global = context->global_object(); 2003 GlobalObject* global = context->global_object();
1918 if (global->IsJSGlobalObject()) { 2004 if (global->IsJSGlobalObject()) {
1919 bool is_debug_object = false; 2005 bool is_debug_object = false;
1920 #ifdef ENABLE_DEBUGGER_SUPPORT 2006 #ifdef ENABLE_DEBUGGER_SUPPORT
1921 is_debug_object = heap_->isolate()->debug()->IsDebugGlobal(global); 2007 is_debug_object = heap_->isolate()->debug()->IsDebugGlobal(global);
(...skipping 687 matching lines...) Expand 10 before | Expand all | Expand 10 after
2609 int HeapSnapshotJSONSerializer::GetStringId(const char* s) { 2695 int HeapSnapshotJSONSerializer::GetStringId(const char* s) {
2610 HashMap::Entry* cache_entry = strings_.Lookup( 2696 HashMap::Entry* cache_entry = strings_.Lookup(
2611 const_cast<char*>(s), StringHash(s), true); 2697 const_cast<char*>(s), StringHash(s), true);
2612 if (cache_entry->value == NULL) { 2698 if (cache_entry->value == NULL) {
2613 cache_entry->value = reinterpret_cast<void*>(next_string_id_++); 2699 cache_entry->value = reinterpret_cast<void*>(next_string_id_++);
2614 } 2700 }
2615 return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); 2701 return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value));
2616 } 2702 }
2617 2703
2618 2704
2619 static int utoa(unsigned value, const Vector<char>& buffer, int buffer_pos) { 2705 namespace {
2706
2707 template<size_t size> struct ToUnsigned;
2708
2709 template<> struct ToUnsigned<4> {
2710 typedef uint32_t Type;
2711 };
2712
2713 template<> struct ToUnsigned<8> {
2714 typedef uint64_t Type;
2715 };
2716
2717 } // namespace
2718
2719
2720 template<typename T>
2721 static int utoa_impl(T value, const Vector<char>& buffer, int buffer_pos) {
2722 STATIC_CHECK(static_cast<T>(-1) > 0); // Check that T is unsigned
2620 int number_of_digits = 0; 2723 int number_of_digits = 0;
2621 unsigned t = value; 2724 T t = value;
2622 do { 2725 do {
2623 ++number_of_digits; 2726 ++number_of_digits;
2624 } while (t /= 10); 2727 } while (t /= 10);
2625 2728
2626 buffer_pos += number_of_digits; 2729 buffer_pos += number_of_digits;
2627 int result = buffer_pos; 2730 int result = buffer_pos;
2628 do { 2731 do {
2629 int last_digit = value % 10; 2732 int last_digit = static_cast<int>(value % 10);
2630 buffer[--buffer_pos] = '0' + last_digit; 2733 buffer[--buffer_pos] = '0' + last_digit;
2631 value /= 10; 2734 value /= 10;
2632 } while (value); 2735 } while (value);
2633 return result; 2736 return result;
2634 } 2737 }
2635 2738
2636 2739
2740 template<typename T>
2741 static int utoa(T value, const Vector<char>& buffer, int buffer_pos) {
2742 typename ToUnsigned<sizeof(value)>::Type unsigned_value = value;
2743 STATIC_CHECK(sizeof(value) == sizeof(unsigned_value));
2744 return utoa_impl(unsigned_value, buffer, buffer_pos);
2745 }
2746
2747
2637 void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge, 2748 void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge,
2638 bool first_edge) { 2749 bool first_edge) {
2639 // The buffer needs space for 3 unsigned ints, 3 commas, \n and \0 2750 // The buffer needs space for 3 unsigned ints, 3 commas, \n and \0
2640 static const int kBufferSize = 2751 static const int kBufferSize =
2641 MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned * 3 + 3 + 2; // NOLINT 2752 MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned * 3 + 3 + 2; // NOLINT
2642 EmbeddedVector<char, kBufferSize> buffer; 2753 EmbeddedVector<char, kBufferSize> buffer;
2643 int edge_name_or_index = edge->type() == HeapGraphEdge::kElement 2754 int edge_name_or_index = edge->type() == HeapGraphEdge::kElement
2644 || edge->type() == HeapGraphEdge::kHidden 2755 || edge->type() == HeapGraphEdge::kHidden
2645 || edge->type() == HeapGraphEdge::kWeak
2646 ? edge->index() : GetStringId(edge->name()); 2756 ? edge->index() : GetStringId(edge->name());
2647 int buffer_pos = 0; 2757 int buffer_pos = 0;
2648 if (!first_edge) { 2758 if (!first_edge) {
2649 buffer[buffer_pos++] = ','; 2759 buffer[buffer_pos++] = ',';
2650 } 2760 }
2651 buffer_pos = utoa(edge->type(), buffer, buffer_pos); 2761 buffer_pos = utoa(edge->type(), buffer, buffer_pos);
2652 buffer[buffer_pos++] = ','; 2762 buffer[buffer_pos++] = ',';
2653 buffer_pos = utoa(edge_name_or_index, buffer, buffer_pos); 2763 buffer_pos = utoa(edge_name_or_index, buffer, buffer_pos);
2654 buffer[buffer_pos++] = ','; 2764 buffer[buffer_pos++] = ',';
2655 buffer_pos = utoa(entry_index(edge->to()), buffer, buffer_pos); 2765 buffer_pos = utoa(entry_index(edge->to()), buffer, buffer_pos);
2656 buffer[buffer_pos++] = '\n'; 2766 buffer[buffer_pos++] = '\n';
2657 buffer[buffer_pos++] = '\0'; 2767 buffer[buffer_pos++] = '\0';
2658 writer_->AddString(buffer.start()); 2768 writer_->AddString(buffer.start());
2659 } 2769 }
2660 2770
2661 2771
2662 void HeapSnapshotJSONSerializer::SerializeEdges() { 2772 void HeapSnapshotJSONSerializer::SerializeEdges() {
2663 List<HeapGraphEdge*>& edges = snapshot_->children(); 2773 List<HeapGraphEdge*>& edges = snapshot_->children();
2664 for (int i = 0; i < edges.length(); ++i) { 2774 for (int i = 0; i < edges.length(); ++i) {
2665 ASSERT(i == 0 || 2775 ASSERT(i == 0 ||
2666 edges[i - 1]->from()->index() <= edges[i]->from()->index()); 2776 edges[i - 1]->from()->index() <= edges[i]->from()->index());
2667 SerializeEdge(edges[i], i == 0); 2777 SerializeEdge(edges[i], i == 0);
2668 if (writer_->aborted()) return; 2778 if (writer_->aborted()) return;
2669 } 2779 }
2670 } 2780 }
2671 2781
2672 2782
2673 void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry) { 2783 void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry) {
2674 // The buffer needs space for 5 unsigned ints, 5 commas, \n and \0 2784 // The buffer needs space for 4 unsigned ints, 1 size_t, 5 commas, \n and \0
2675 static const int kBufferSize = 2785 static const int kBufferSize =
2676 5 * MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned // NOLINT 2786 4 * MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned // NOLINT
2787 + MaxDecimalDigitsIn<sizeof(size_t)>::kUnsigned // NOLINT
2677 + 5 + 1 + 1; 2788 + 5 + 1 + 1;
2678 EmbeddedVector<char, kBufferSize> buffer; 2789 EmbeddedVector<char, kBufferSize> buffer;
2679 int buffer_pos = 0; 2790 int buffer_pos = 0;
2680 if (entry_index(entry) != 0) { 2791 if (entry_index(entry) != 0) {
2681 buffer[buffer_pos++] = ','; 2792 buffer[buffer_pos++] = ',';
2682 } 2793 }
2683 buffer_pos = utoa(entry->type(), buffer, buffer_pos); 2794 buffer_pos = utoa(entry->type(), buffer, buffer_pos);
2684 buffer[buffer_pos++] = ','; 2795 buffer[buffer_pos++] = ',';
2685 buffer_pos = utoa(GetStringId(entry->name()), buffer, buffer_pos); 2796 buffer_pos = utoa(GetStringId(entry->name()), buffer, buffer_pos);
2686 buffer[buffer_pos++] = ','; 2797 buffer[buffer_pos++] = ',';
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after
2954 writer_->AddString("\"<dummy>\""); 3065 writer_->AddString("\"<dummy>\"");
2955 for (int i = 1; i < sorted_strings.length(); ++i) { 3066 for (int i = 1; i < sorted_strings.length(); ++i) {
2956 writer_->AddCharacter(','); 3067 writer_->AddCharacter(',');
2957 SerializeString(sorted_strings[i]); 3068 SerializeString(sorted_strings[i]);
2958 if (writer_->aborted()) return; 3069 if (writer_->aborted()) return;
2959 } 3070 }
2960 } 3071 }
2961 3072
2962 3073
2963 } } // namespace v8::internal 3074 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/heap-snapshot-generator.h ('k') | src/hydrogen.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698