| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "v8.h" | 5 #include "v8.h" |
| 6 | 6 |
| 7 #include "heap-snapshot-generator-inl.h" | 7 #include "heap-snapshot-generator-inl.h" |
| 8 | 8 |
| 9 #include "allocation-tracker.h" | 9 #include "allocation-tracker.h" |
| 10 #include "code-stubs.h" | 10 #include "code-stubs.h" |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 75 int index, | 75 int index, |
| 76 HeapEntry* entry) { | 76 HeapEntry* entry) { |
| 77 HeapGraphEdge edge(type, index, this->index(), entry->index()); | 77 HeapGraphEdge edge(type, index, this->index(), entry->index()); |
| 78 snapshot_->edges().Add(edge); | 78 snapshot_->edges().Add(edge); |
| 79 ++children_count_; | 79 ++children_count_; |
| 80 } | 80 } |
| 81 | 81 |
| 82 | 82 |
| 83 void HeapEntry::Print( | 83 void HeapEntry::Print( |
| 84 const char* prefix, const char* edge_name, int max_depth, int indent) { | 84 const char* prefix, const char* edge_name, int max_depth, int indent) { |
| 85 STATIC_CHECK(sizeof(unsigned) == sizeof(id())); | 85 STATIC_ASSERT(sizeof(unsigned) == sizeof(id())); |
| 86 OS::Print("%6" V8PRIuPTR " @%6u %*c %s%s: ", | 86 OS::Print("%6" V8PRIuPTR " @%6u %*c %s%s: ", |
| 87 self_size(), id(), indent, ' ', prefix, edge_name); | 87 self_size(), id(), indent, ' ', prefix, edge_name); |
| 88 if (type() != kString) { | 88 if (type() != kString) { |
| 89 OS::Print("%s %.40s\n", TypeAsString(), name_); | 89 OS::Print("%s %.40s\n", TypeAsString(), name_); |
| 90 } else { | 90 } else { |
| 91 OS::Print("\""); | 91 OS::Print("\""); |
| 92 const char* c = name_; | 92 const char* c = name_; |
| 93 while (*c && (c - name_) <= 40) { | 93 while (*c && (c - name_) <= 40) { |
| 94 if (*c != '\n') | 94 if (*c != '\n') |
| 95 OS::Print("%c", *c); | 95 OS::Print("%c", *c); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 183 HeapSnapshot::HeapSnapshot(HeapProfiler* profiler, | 183 HeapSnapshot::HeapSnapshot(HeapProfiler* profiler, |
| 184 const char* title, | 184 const char* title, |
| 185 unsigned uid) | 185 unsigned uid) |
| 186 : profiler_(profiler), | 186 : profiler_(profiler), |
| 187 title_(title), | 187 title_(title), |
| 188 uid_(uid), | 188 uid_(uid), |
| 189 root_index_(HeapEntry::kNoEntry), | 189 root_index_(HeapEntry::kNoEntry), |
| 190 gc_roots_index_(HeapEntry::kNoEntry), | 190 gc_roots_index_(HeapEntry::kNoEntry), |
| 191 natives_root_index_(HeapEntry::kNoEntry), | 191 natives_root_index_(HeapEntry::kNoEntry), |
| 192 max_snapshot_js_object_id_(0) { | 192 max_snapshot_js_object_id_(0) { |
| 193 STATIC_CHECK( | 193 STATIC_ASSERT( |
| 194 sizeof(HeapGraphEdge) == | 194 sizeof(HeapGraphEdge) == |
| 195 SnapshotSizeConstants<kPointerSize>::kExpectedHeapGraphEdgeSize); | 195 SnapshotSizeConstants<kPointerSize>::kExpectedHeapGraphEdgeSize); |
| 196 STATIC_CHECK( | 196 STATIC_ASSERT( |
| 197 sizeof(HeapEntry) == | 197 sizeof(HeapEntry) == |
| 198 SnapshotSizeConstants<kPointerSize>::kExpectedHeapEntrySize); | 198 SnapshotSizeConstants<kPointerSize>::kExpectedHeapEntrySize); |
| 199 USE(SnapshotSizeConstants<4>::kExpectedHeapGraphEdgeSize); | 199 USE(SnapshotSizeConstants<4>::kExpectedHeapGraphEdgeSize); |
| 200 USE(SnapshotSizeConstants<4>::kExpectedHeapEntrySize); | 200 USE(SnapshotSizeConstants<4>::kExpectedHeapEntrySize); |
| 201 USE(SnapshotSizeConstants<8>::kExpectedHeapGraphEdgeSize); | 201 USE(SnapshotSizeConstants<8>::kExpectedHeapGraphEdgeSize); |
| 202 USE(SnapshotSizeConstants<8>::kExpectedHeapEntrySize); | 202 USE(SnapshotSizeConstants<8>::kExpectedHeapEntrySize); |
| 203 for (int i = 0; i < VisitorSynchronization::kNumberOfSyncTags; ++i) { | 203 for (int i = 0; i < VisitorSynchronization::kNumberOfSyncTags; ++i) { |
| 204 gc_subroot_indexes_[i] = HeapEntry::kNoEntry; | 204 gc_subroot_indexes_[i] = HeapEntry::kNoEntry; |
| 205 } | 205 } |
| 206 } | 206 } |
| (...skipping 986 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1193 SetInternalReference(js_fun, entry, | 1193 SetInternalReference(js_fun, entry, |
| 1194 "shared", shared_info, | 1194 "shared", shared_info, |
| 1195 JSFunction::kSharedFunctionInfoOffset); | 1195 JSFunction::kSharedFunctionInfoOffset); |
| 1196 TagObject(js_fun->context(), "(context)"); | 1196 TagObject(js_fun->context(), "(context)"); |
| 1197 SetInternalReference(js_fun, entry, | 1197 SetInternalReference(js_fun, entry, |
| 1198 "context", js_fun->context(), | 1198 "context", js_fun->context(), |
| 1199 JSFunction::kContextOffset); | 1199 JSFunction::kContextOffset); |
| 1200 SetWeakReference(js_fun, entry, | 1200 SetWeakReference(js_fun, entry, |
| 1201 "next_function_link", js_fun->next_function_link(), | 1201 "next_function_link", js_fun->next_function_link(), |
| 1202 JSFunction::kNextFunctionLinkOffset); | 1202 JSFunction::kNextFunctionLinkOffset); |
| 1203 STATIC_CHECK(JSFunction::kNextFunctionLinkOffset | 1203 STATIC_ASSERT(JSFunction::kNextFunctionLinkOffset |
| 1204 == JSFunction::kNonWeakFieldsEndOffset); | 1204 == JSFunction::kNonWeakFieldsEndOffset); |
| 1205 STATIC_CHECK(JSFunction::kNextFunctionLinkOffset + kPointerSize | 1205 STATIC_ASSERT(JSFunction::kNextFunctionLinkOffset + kPointerSize |
| 1206 == JSFunction::kSize); | 1206 == JSFunction::kSize); |
| 1207 } else if (obj->IsGlobalObject()) { | 1207 } else if (obj->IsGlobalObject()) { |
| 1208 GlobalObject* global_obj = GlobalObject::cast(obj); | 1208 GlobalObject* global_obj = GlobalObject::cast(obj); |
| 1209 SetInternalReference(global_obj, entry, | 1209 SetInternalReference(global_obj, entry, |
| 1210 "builtins", global_obj->builtins(), | 1210 "builtins", global_obj->builtins(), |
| 1211 GlobalObject::kBuiltinsOffset); | 1211 GlobalObject::kBuiltinsOffset); |
| 1212 SetInternalReference(global_obj, entry, | 1212 SetInternalReference(global_obj, entry, |
| 1213 "native_context", global_obj->native_context(), | 1213 "native_context", global_obj->native_context(), |
| 1214 GlobalObject::kNativeContextOffset); | 1214 GlobalObject::kNativeContextOffset); |
| 1215 SetInternalReference(global_obj, entry, | 1215 SetInternalReference(global_obj, entry, |
| 1216 "global_context", global_obj->global_context(), | 1216 "global_context", global_obj->global_context(), |
| 1217 GlobalObject::kGlobalContextOffset); | 1217 GlobalObject::kGlobalContextOffset); |
| 1218 SetInternalReference(global_obj, entry, | 1218 SetInternalReference(global_obj, entry, |
| 1219 "global_receiver", global_obj->global_receiver(), | 1219 "global_receiver", global_obj->global_receiver(), |
| 1220 GlobalObject::kGlobalReceiverOffset); | 1220 GlobalObject::kGlobalReceiverOffset); |
| 1221 STATIC_CHECK(GlobalObject::kHeaderSize - JSObject::kHeaderSize == | 1221 STATIC_ASSERT(GlobalObject::kHeaderSize - JSObject::kHeaderSize == |
| 1222 4 * kPointerSize); | 1222 4 * kPointerSize); |
| 1223 } else if (obj->IsJSArrayBufferView()) { | 1223 } else if (obj->IsJSArrayBufferView()) { |
| 1224 JSArrayBufferView* view = JSArrayBufferView::cast(obj); | 1224 JSArrayBufferView* view = JSArrayBufferView::cast(obj); |
| 1225 SetInternalReference(view, entry, "buffer", view->buffer(), | 1225 SetInternalReference(view, entry, "buffer", view->buffer(), |
| 1226 JSArrayBufferView::kBufferOffset); | 1226 JSArrayBufferView::kBufferOffset); |
| 1227 SetWeakReference(view, entry, "weak_next", view->weak_next(), | 1227 SetWeakReference(view, entry, "weak_next", view->weak_next(), |
| 1228 JSArrayBufferView::kWeakNextOffset); | 1228 JSArrayBufferView::kWeakNextOffset); |
| 1229 } | 1229 } |
| 1230 TagObject(js_obj->properties(), "(object properties)"); | 1230 TagObject(js_obj->properties(), "(object properties)"); |
| 1231 SetInternalReference(obj, entry, | 1231 SetInternalReference(obj, entry, |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1310 TagObject(context->normalized_map_cache(), "(context norm. map cache)"); | 1310 TagObject(context->normalized_map_cache(), "(context norm. map cache)"); |
| 1311 TagObject(context->runtime_context(), "(runtime context)"); | 1311 TagObject(context->runtime_context(), "(runtime context)"); |
| 1312 TagObject(context->embedder_data(), "(context data)"); | 1312 TagObject(context->embedder_data(), "(context data)"); |
| 1313 NATIVE_CONTEXT_FIELDS(EXTRACT_CONTEXT_FIELD); | 1313 NATIVE_CONTEXT_FIELDS(EXTRACT_CONTEXT_FIELD); |
| 1314 EXTRACT_CONTEXT_FIELD(OPTIMIZED_FUNCTIONS_LIST, unused, | 1314 EXTRACT_CONTEXT_FIELD(OPTIMIZED_FUNCTIONS_LIST, unused, |
| 1315 optimized_functions_list); | 1315 optimized_functions_list); |
| 1316 EXTRACT_CONTEXT_FIELD(OPTIMIZED_CODE_LIST, unused, optimized_code_list); | 1316 EXTRACT_CONTEXT_FIELD(OPTIMIZED_CODE_LIST, unused, optimized_code_list); |
| 1317 EXTRACT_CONTEXT_FIELD(DEOPTIMIZED_CODE_LIST, unused, deoptimized_code_list); | 1317 EXTRACT_CONTEXT_FIELD(DEOPTIMIZED_CODE_LIST, unused, deoptimized_code_list); |
| 1318 EXTRACT_CONTEXT_FIELD(NEXT_CONTEXT_LINK, unused, next_context_link); | 1318 EXTRACT_CONTEXT_FIELD(NEXT_CONTEXT_LINK, unused, next_context_link); |
| 1319 #undef EXTRACT_CONTEXT_FIELD | 1319 #undef EXTRACT_CONTEXT_FIELD |
| 1320 STATIC_CHECK(Context::OPTIMIZED_FUNCTIONS_LIST == Context::FIRST_WEAK_SLOT); | 1320 STATIC_ASSERT(Context::OPTIMIZED_FUNCTIONS_LIST == |
| 1321 STATIC_CHECK(Context::NEXT_CONTEXT_LINK + 1 | 1321 Context::FIRST_WEAK_SLOT); |
| 1322 == Context::NATIVE_CONTEXT_SLOTS); | 1322 STATIC_ASSERT(Context::NEXT_CONTEXT_LINK + 1 == |
| 1323 STATIC_CHECK(Context::FIRST_WEAK_SLOT + 5 == Context::NATIVE_CONTEXT_SLOTS); | 1323 Context::NATIVE_CONTEXT_SLOTS); |
| 1324 STATIC_ASSERT(Context::FIRST_WEAK_SLOT + 5 == |
| 1325 Context::NATIVE_CONTEXT_SLOTS); |
| 1324 } | 1326 } |
| 1325 } | 1327 } |
| 1326 | 1328 |
| 1327 | 1329 |
| 1328 void V8HeapExplorer::ExtractMapReferences(int entry, Map* map) { | 1330 void V8HeapExplorer::ExtractMapReferences(int entry, Map* map) { |
| 1329 if (map->HasTransitionArray()) { | 1331 if (map->HasTransitionArray()) { |
| 1330 TransitionArray* transitions = map->transitions(); | 1332 TransitionArray* transitions = map->transitions(); |
| 1331 int transitions_entry = GetEntry(transitions)->index(); | 1333 int transitions_entry = GetEntry(transitions)->index(); |
| 1332 Object* back_pointer = transitions->back_pointer_storage(); | 1334 Object* back_pointer = transitions->back_pointer_storage(); |
| 1333 TagObject(back_pointer, "(back pointer)"); | 1335 TagObject(back_pointer, "(back pointer)"); |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1548 AllocationSite* site) { | 1550 AllocationSite* site) { |
| 1549 SetInternalReference(site, entry, "transition_info", site->transition_info(), | 1551 SetInternalReference(site, entry, "transition_info", site->transition_info(), |
| 1550 AllocationSite::kTransitionInfoOffset); | 1552 AllocationSite::kTransitionInfoOffset); |
| 1551 SetInternalReference(site, entry, "nested_site", site->nested_site(), | 1553 SetInternalReference(site, entry, "nested_site", site->nested_site(), |
| 1552 AllocationSite::kNestedSiteOffset); | 1554 AllocationSite::kNestedSiteOffset); |
| 1553 MarkAsWeakContainer(site->dependent_code()); | 1555 MarkAsWeakContainer(site->dependent_code()); |
| 1554 SetInternalReference(site, entry, "dependent_code", site->dependent_code(), | 1556 SetInternalReference(site, entry, "dependent_code", site->dependent_code(), |
| 1555 AllocationSite::kDependentCodeOffset); | 1557 AllocationSite::kDependentCodeOffset); |
| 1556 // Do not visit weak_next as it is not visited by the StaticVisitor, | 1558 // Do not visit weak_next as it is not visited by the StaticVisitor, |
| 1557 // and we're not very interested in weak_next field here. | 1559 // and we're not very interested in weak_next field here. |
| 1558 STATIC_CHECK(AllocationSite::kWeakNextOffset >= | 1560 STATIC_ASSERT(AllocationSite::kWeakNextOffset >= |
| 1559 AllocationSite::BodyDescriptor::kEndOffset); | 1561 AllocationSite::BodyDescriptor::kEndOffset); |
| 1560 } | 1562 } |
| 1561 | 1563 |
| 1562 | 1564 |
| 1563 class JSArrayBufferDataEntryAllocator : public HeapEntriesAllocator { | 1565 class JSArrayBufferDataEntryAllocator : public HeapEntriesAllocator { |
| 1564 public: | 1566 public: |
| 1565 JSArrayBufferDataEntryAllocator(size_t size, V8HeapExplorer* explorer) | 1567 JSArrayBufferDataEntryAllocator(size_t size, V8HeapExplorer* explorer) |
| 1566 : size_(size) | 1568 : size_(size) |
| 1567 , explorer_(explorer) { | 1569 , explorer_(explorer) { |
| 1568 } | 1570 } |
| (...skipping 1246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2815 | 2817 |
| 2816 template<> struct ToUnsigned<8> { | 2818 template<> struct ToUnsigned<8> { |
| 2817 typedef uint64_t Type; | 2819 typedef uint64_t Type; |
| 2818 }; | 2820 }; |
| 2819 | 2821 |
| 2820 } // namespace | 2822 } // namespace |
| 2821 | 2823 |
| 2822 | 2824 |
| 2823 template<typename T> | 2825 template<typename T> |
| 2824 static int utoa_impl(T value, const Vector<char>& buffer, int buffer_pos) { | 2826 static int utoa_impl(T value, const Vector<char>& buffer, int buffer_pos) { |
| 2825 STATIC_CHECK(static_cast<T>(-1) > 0); // Check that T is unsigned | 2827 STATIC_ASSERT(static_cast<T>(-1) > 0); // Check that T is unsigned |
| 2826 int number_of_digits = 0; | 2828 int number_of_digits = 0; |
| 2827 T t = value; | 2829 T t = value; |
| 2828 do { | 2830 do { |
| 2829 ++number_of_digits; | 2831 ++number_of_digits; |
| 2830 } while (t /= 10); | 2832 } while (t /= 10); |
| 2831 | 2833 |
| 2832 buffer_pos += number_of_digits; | 2834 buffer_pos += number_of_digits; |
| 2833 int result = buffer_pos; | 2835 int result = buffer_pos; |
| 2834 do { | 2836 do { |
| 2835 int last_digit = static_cast<int>(value % 10); | 2837 int last_digit = static_cast<int>(value % 10); |
| 2836 buffer[--buffer_pos] = '0' + last_digit; | 2838 buffer[--buffer_pos] = '0' + last_digit; |
| 2837 value /= 10; | 2839 value /= 10; |
| 2838 } while (value); | 2840 } while (value); |
| 2839 return result; | 2841 return result; |
| 2840 } | 2842 } |
| 2841 | 2843 |
| 2842 | 2844 |
| 2843 template<typename T> | 2845 template<typename T> |
| 2844 static int utoa(T value, const Vector<char>& buffer, int buffer_pos) { | 2846 static int utoa(T value, const Vector<char>& buffer, int buffer_pos) { |
| 2845 typename ToUnsigned<sizeof(value)>::Type unsigned_value = value; | 2847 typename ToUnsigned<sizeof(value)>::Type unsigned_value = value; |
| 2846 STATIC_CHECK(sizeof(value) == sizeof(unsigned_value)); | 2848 STATIC_ASSERT(sizeof(value) == sizeof(unsigned_value)); |
| 2847 return utoa_impl(unsigned_value, buffer, buffer_pos); | 2849 return utoa_impl(unsigned_value, buffer, buffer_pos); |
| 2848 } | 2850 } |
| 2849 | 2851 |
| 2850 | 2852 |
| 2851 void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge, | 2853 void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge, |
| 2852 bool first_edge) { | 2854 bool first_edge) { |
| 2853 // The buffer needs space for 3 unsigned ints, 3 commas, \n and \0 | 2855 // The buffer needs space for 3 unsigned ints, 3 commas, \n and \0 |
| 2854 static const int kBufferSize = | 2856 static const int kBufferSize = |
| 2855 MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned * 3 + 3 + 2; // NOLINT | 2857 MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned * 3 + 3 + 2; // NOLINT |
| 2856 EmbeddedVector<char, kBufferSize> buffer; | 2858 EmbeddedVector<char, kBufferSize> buffer; |
| (...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3167 writer_->AddString("\"<dummy>\""); | 3169 writer_->AddString("\"<dummy>\""); |
| 3168 for (int i = 1; i < sorted_strings.length(); ++i) { | 3170 for (int i = 1; i < sorted_strings.length(); ++i) { |
| 3169 writer_->AddCharacter(','); | 3171 writer_->AddCharacter(','); |
| 3170 SerializeString(sorted_strings[i]); | 3172 SerializeString(sorted_strings[i]); |
| 3171 if (writer_->aborted()) return; | 3173 if (writer_->aborted()) return; |
| 3172 } | 3174 } |
| 3173 } | 3175 } |
| 3174 | 3176 |
| 3175 | 3177 |
| 3176 } } // namespace v8::internal | 3178 } } // namespace v8::internal |
| OLD | NEW |