OLD | NEW |
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 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
66 to_entry_ = &snapshot->entries()[to_index_]; | 66 to_entry_ = &snapshot->entries()[to_index_]; |
67 } | 67 } |
68 | 68 |
69 | 69 |
70 const int HeapEntry::kNoEntry = -1; | 70 const int HeapEntry::kNoEntry = -1; |
71 | 71 |
72 HeapEntry::HeapEntry(HeapSnapshot* snapshot, | 72 HeapEntry::HeapEntry(HeapSnapshot* snapshot, |
73 Type type, | 73 Type type, |
74 const char* name, | 74 const char* name, |
75 SnapshotObjectId id, | 75 SnapshotObjectId id, |
76 int self_size) | 76 size_t self_size) |
77 : type_(type), | 77 : type_(type), |
78 children_count_(0), | 78 children_count_(0), |
79 children_index_(-1), | 79 children_index_(-1), |
80 self_size_(self_size), | 80 self_size_(self_size), |
81 id_(id), | 81 id_(id), |
82 snapshot_(snapshot), | 82 snapshot_(snapshot), |
83 name_(name) { } | 83 name_(name) { } |
84 | 84 |
85 | 85 |
86 void HeapEntry::SetNamedReference(HeapGraphEdge::Type type, | 86 void HeapEntry::SetNamedReference(HeapGraphEdge::Type type, |
(...skipping 10 matching lines...) Expand all Loading... |
97 HeapEntry* entry) { | 97 HeapEntry* entry) { |
98 HeapGraphEdge edge(type, index, this->index(), entry->index()); | 98 HeapGraphEdge edge(type, index, this->index(), entry->index()); |
99 snapshot_->edges().Add(edge); | 99 snapshot_->edges().Add(edge); |
100 ++children_count_; | 100 ++children_count_; |
101 } | 101 } |
102 | 102 |
103 | 103 |
104 void HeapEntry::Print( | 104 void HeapEntry::Print( |
105 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) { |
106 STATIC_CHECK(sizeof(unsigned) == sizeof(id())); | 106 STATIC_CHECK(sizeof(unsigned) == sizeof(id())); |
107 OS::Print("%6d @%6u %*c %s%s: ", | 107 OS::Print("%6"V8PRIuPTR" @%6u %*c %s%s: ", |
108 self_size(), id(), indent, ' ', prefix, edge_name); | 108 self_size(), id(), indent, ' ', prefix, edge_name); |
109 if (type() != kString) { | 109 if (type() != kString) { |
110 OS::Print("%s %.40s\n", TypeAsString(), name_); | 110 OS::Print("%s %.40s\n", TypeAsString(), name_); |
111 } else { | 111 } else { |
112 OS::Print("\""); | 112 OS::Print("\""); |
113 const char* c = name_; | 113 const char* c = name_; |
114 while (*c && (c - name_) <= 40) { | 114 while (*c && (c - name_) <= 40) { |
115 if (*c != '\n') | 115 if (*c != '\n') |
116 OS::Print("%c", *c); | 116 OS::Print("%c", *c); |
117 else | 117 else |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
187 | 187 |
188 template <size_t ptr_size> struct SnapshotSizeConstants; | 188 template <size_t ptr_size> struct SnapshotSizeConstants; |
189 | 189 |
190 template <> struct SnapshotSizeConstants<4> { | 190 template <> struct SnapshotSizeConstants<4> { |
191 static const int kExpectedHeapGraphEdgeSize = 12; | 191 static const int kExpectedHeapGraphEdgeSize = 12; |
192 static const int kExpectedHeapEntrySize = 24; | 192 static const int kExpectedHeapEntrySize = 24; |
193 }; | 193 }; |
194 | 194 |
195 template <> struct SnapshotSizeConstants<8> { | 195 template <> struct SnapshotSizeConstants<8> { |
196 static const int kExpectedHeapGraphEdgeSize = 24; | 196 static const int kExpectedHeapGraphEdgeSize = 24; |
197 static const int kExpectedHeapEntrySize = 32; | 197 static const int kExpectedHeapEntrySize = 40; |
198 }; | 198 }; |
199 | 199 |
200 } // namespace | 200 } // namespace |
201 | 201 |
202 | 202 |
203 HeapSnapshot::HeapSnapshot(HeapProfiler* profiler, | 203 HeapSnapshot::HeapSnapshot(HeapProfiler* profiler, |
204 const char* title, | 204 const char* title, |
205 unsigned uid) | 205 unsigned uid) |
206 : profiler_(profiler), | 206 : profiler_(profiler), |
207 title_(title), | 207 title_(title), |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 HeapObjectsMap::GetNthGcSubrootId(tag), | 270 HeapObjectsMap::GetNthGcSubrootId(tag), |
271 0); | 271 0); |
272 gc_subroot_indexes_[tag] = entry->index(); | 272 gc_subroot_indexes_[tag] = entry->index(); |
273 return entry; | 273 return entry; |
274 } | 274 } |
275 | 275 |
276 | 276 |
277 HeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type, | 277 HeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type, |
278 const char* name, | 278 const char* name, |
279 SnapshotObjectId id, | 279 SnapshotObjectId id, |
280 int size) { | 280 size_t size) { |
281 HeapEntry entry(this, type, name, id, size); | 281 HeapEntry entry(this, type, name, id, size); |
282 entries_.Add(entry); | 282 entries_.Add(entry); |
283 return &entries_.last(); | 283 return &entries_.last(); |
284 } | 284 } |
285 | 285 |
286 | 286 |
287 void HeapSnapshot::FillChildren() { | 287 void HeapSnapshot::FillChildren() { |
288 ASSERT(children().is_empty()); | 288 ASSERT(children().is_empty()); |
289 children().Allocate(edges().length()); | 289 children().Allocate(edges().length()); |
290 int children_index = 0; | 290 int children_index = 0; |
(...skipping 609 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
900 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object, | 900 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object, |
901 HeapEntry::Type type, | 901 HeapEntry::Type type, |
902 const char* name) { | 902 const char* name) { |
903 return AddEntry(object->address(), type, name, object->Size()); | 903 return AddEntry(object->address(), type, name, object->Size()); |
904 } | 904 } |
905 | 905 |
906 | 906 |
907 HeapEntry* V8HeapExplorer::AddEntry(Address address, | 907 HeapEntry* V8HeapExplorer::AddEntry(Address address, |
908 HeapEntry::Type type, | 908 HeapEntry::Type type, |
909 const char* name, | 909 const char* name, |
910 int size) { | 910 size_t size) { |
911 SnapshotObjectId object_id = heap_object_map_->FindOrAddEntry(address, size); | 911 SnapshotObjectId object_id = heap_object_map_->FindOrAddEntry(address, size); |
912 return snapshot_->AddEntry(type, name, object_id, size); | 912 return snapshot_->AddEntry(type, name, object_id, size); |
913 } | 913 } |
914 | 914 |
915 | 915 |
916 class GcSubrootsEnumerator : public ObjectVisitor { | 916 class GcSubrootsEnumerator : public ObjectVisitor { |
917 public: | 917 public: |
918 GcSubrootsEnumerator( | 918 GcSubrootsEnumerator( |
919 SnapshotFillerInterface* filler, V8HeapExplorer* explorer) | 919 SnapshotFillerInterface* filler, V8HeapExplorer* explorer) |
920 : filler_(filler), | 920 : filler_(filler), |
(...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1451 AllocationSite::kDependentCodeOffset); | 1451 AllocationSite::kDependentCodeOffset); |
1452 // Do not visit weak_next as it is not visited by the StaticVisitor, | 1452 // Do not visit weak_next as it is not visited by the StaticVisitor, |
1453 // and we're not very interested in weak_next field here. | 1453 // and we're not very interested in weak_next field here. |
1454 STATIC_CHECK(AllocationSite::kWeakNextOffset >= | 1454 STATIC_CHECK(AllocationSite::kWeakNextOffset >= |
1455 AllocationSite::BodyDescriptor::kEndOffset); | 1455 AllocationSite::BodyDescriptor::kEndOffset); |
1456 } | 1456 } |
1457 | 1457 |
1458 | 1458 |
1459 class JSArrayBufferDataEntryAllocator : public HeapEntriesAllocator { | 1459 class JSArrayBufferDataEntryAllocator : public HeapEntriesAllocator { |
1460 public: | 1460 public: |
1461 JSArrayBufferDataEntryAllocator(int size, V8HeapExplorer* explorer) | 1461 JSArrayBufferDataEntryAllocator(size_t size, V8HeapExplorer* explorer) |
1462 : size_(size) | 1462 : size_(size) |
1463 , explorer_(explorer) { | 1463 , explorer_(explorer) { |
1464 } | 1464 } |
1465 virtual HeapEntry* AllocateEntry(HeapThing ptr) { | 1465 virtual HeapEntry* AllocateEntry(HeapThing ptr) { |
1466 return explorer_->AddEntry( | 1466 return explorer_->AddEntry( |
1467 static_cast<Address>(ptr), | 1467 static_cast<Address>(ptr), |
1468 HeapEntry::kNative, "system / JSArrayBufferData", size_); | 1468 HeapEntry::kNative, "system / JSArrayBufferData", size_); |
1469 } | 1469 } |
1470 private: | 1470 private: |
1471 int size_; | 1471 size_t size_; |
1472 V8HeapExplorer* explorer_; | 1472 V8HeapExplorer* explorer_; |
1473 }; | 1473 }; |
1474 | 1474 |
1475 | 1475 |
1476 void V8HeapExplorer::ExtractJSArrayBufferReferences( | 1476 void V8HeapExplorer::ExtractJSArrayBufferReferences( |
1477 int entry, JSArrayBuffer* buffer) { | 1477 int entry, JSArrayBuffer* buffer) { |
1478 SetWeakReference(buffer, entry, "weak_next", buffer->weak_next(), | 1478 SetWeakReference(buffer, entry, "weak_next", buffer->weak_next(), |
1479 JSArrayBuffer::kWeakNextOffset); | 1479 JSArrayBuffer::kWeakNextOffset); |
1480 SetWeakReference(buffer, entry, | 1480 SetWeakReference(buffer, entry, |
1481 "weak_first_view", buffer->weak_first_view(), | 1481 "weak_first_view", buffer->weak_first_view(), |
1482 JSArrayBuffer::kWeakFirstViewOffset); | 1482 JSArrayBuffer::kWeakFirstViewOffset); |
1483 // Setup a reference to a native memory backing_store object. | 1483 // Setup a reference to a native memory backing_store object. |
1484 if (!buffer->backing_store()) | 1484 if (!buffer->backing_store()) |
1485 return; | 1485 return; |
1486 size_t data_size = NumberToSize(heap_->isolate(), buffer->byte_length()); | 1486 size_t data_size = NumberToSize(heap_->isolate(), buffer->byte_length()); |
1487 CHECK(data_size <= static_cast<size_t>(kMaxInt)); | 1487 JSArrayBufferDataEntryAllocator allocator(data_size, this); |
1488 JSArrayBufferDataEntryAllocator allocator(static_cast<int>(data_size), this); | |
1489 HeapEntry* data_entry = | 1488 HeapEntry* data_entry = |
1490 filler_->FindOrAddEntry(buffer->backing_store(), &allocator); | 1489 filler_->FindOrAddEntry(buffer->backing_store(), &allocator); |
1491 filler_->SetNamedReference(HeapGraphEdge::kInternal, | 1490 filler_->SetNamedReference(HeapGraphEdge::kInternal, |
1492 entry, "backing_store", data_entry); | 1491 entry, "backing_store", data_entry); |
1493 } | 1492 } |
1494 | 1493 |
1495 | 1494 |
1496 void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj, int entry) { | 1495 void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj, int entry) { |
1497 if (!js_obj->IsJSFunction()) return; | 1496 if (!js_obj->IsJSFunction()) return; |
1498 | 1497 |
(...skipping 1196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2695 int HeapSnapshotJSONSerializer::GetStringId(const char* s) { | 2694 int HeapSnapshotJSONSerializer::GetStringId(const char* s) { |
2696 HashMap::Entry* cache_entry = strings_.Lookup( | 2695 HashMap::Entry* cache_entry = strings_.Lookup( |
2697 const_cast<char*>(s), StringHash(s), true); | 2696 const_cast<char*>(s), StringHash(s), true); |
2698 if (cache_entry->value == NULL) { | 2697 if (cache_entry->value == NULL) { |
2699 cache_entry->value = reinterpret_cast<void*>(next_string_id_++); | 2698 cache_entry->value = reinterpret_cast<void*>(next_string_id_++); |
2700 } | 2699 } |
2701 return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); | 2700 return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); |
2702 } | 2701 } |
2703 | 2702 |
2704 | 2703 |
2705 static int utoa(unsigned value, const Vector<char>& buffer, int buffer_pos) { | 2704 namespace { |
| 2705 |
| 2706 template<size_t size> struct ToUnsigned; |
| 2707 |
| 2708 template<> struct ToUnsigned<4> { |
| 2709 typedef uint32_t Type; |
| 2710 }; |
| 2711 |
| 2712 template<> struct ToUnsigned<8> { |
| 2713 typedef uint64_t Type; |
| 2714 }; |
| 2715 |
| 2716 } // namespace |
| 2717 |
| 2718 |
| 2719 template<typename T> |
| 2720 static int utoa_impl(T value, const Vector<char>& buffer, int buffer_pos) { |
| 2721 STATIC_CHECK(static_cast<T>(-1) > 0); // Check that T is unsigned |
2706 int number_of_digits = 0; | 2722 int number_of_digits = 0; |
2707 unsigned t = value; | 2723 T t = value; |
2708 do { | 2724 do { |
2709 ++number_of_digits; | 2725 ++number_of_digits; |
2710 } while (t /= 10); | 2726 } while (t /= 10); |
2711 | 2727 |
2712 buffer_pos += number_of_digits; | 2728 buffer_pos += number_of_digits; |
2713 int result = buffer_pos; | 2729 int result = buffer_pos; |
2714 do { | 2730 do { |
2715 int last_digit = value % 10; | 2731 int last_digit = static_cast<int>(value % 10); |
2716 buffer[--buffer_pos] = '0' + last_digit; | 2732 buffer[--buffer_pos] = '0' + last_digit; |
2717 value /= 10; | 2733 value /= 10; |
2718 } while (value); | 2734 } while (value); |
2719 return result; | 2735 return result; |
2720 } | 2736 } |
2721 | 2737 |
2722 | 2738 |
| 2739 template<typename T> |
| 2740 static int utoa(T value, const Vector<char>& buffer, int buffer_pos) { |
| 2741 typename ToUnsigned<sizeof(value)>::Type unsigned_value = value; |
| 2742 STATIC_CHECK(sizeof(value) == sizeof(unsigned_value)); |
| 2743 return utoa_impl(unsigned_value, buffer, buffer_pos); |
| 2744 } |
| 2745 |
| 2746 |
2723 void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge, | 2747 void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge, |
2724 bool first_edge) { | 2748 bool first_edge) { |
2725 // The buffer needs space for 3 unsigned ints, 3 commas, \n and \0 | 2749 // The buffer needs space for 3 unsigned ints, 3 commas, \n and \0 |
2726 static const int kBufferSize = | 2750 static const int kBufferSize = |
2727 MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned * 3 + 3 + 2; // NOLINT | 2751 MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned * 3 + 3 + 2; // NOLINT |
2728 EmbeddedVector<char, kBufferSize> buffer; | 2752 EmbeddedVector<char, kBufferSize> buffer; |
2729 int edge_name_or_index = edge->type() == HeapGraphEdge::kElement | 2753 int edge_name_or_index = edge->type() == HeapGraphEdge::kElement |
2730 || edge->type() == HeapGraphEdge::kHidden | 2754 || edge->type() == HeapGraphEdge::kHidden |
2731 ? edge->index() : GetStringId(edge->name()); | 2755 ? edge->index() : GetStringId(edge->name()); |
2732 int buffer_pos = 0; | 2756 int buffer_pos = 0; |
(...skipping 16 matching lines...) Expand all Loading... |
2749 for (int i = 0; i < edges.length(); ++i) { | 2773 for (int i = 0; i < edges.length(); ++i) { |
2750 ASSERT(i == 0 || | 2774 ASSERT(i == 0 || |
2751 edges[i - 1]->from()->index() <= edges[i]->from()->index()); | 2775 edges[i - 1]->from()->index() <= edges[i]->from()->index()); |
2752 SerializeEdge(edges[i], i == 0); | 2776 SerializeEdge(edges[i], i == 0); |
2753 if (writer_->aborted()) return; | 2777 if (writer_->aborted()) return; |
2754 } | 2778 } |
2755 } | 2779 } |
2756 | 2780 |
2757 | 2781 |
2758 void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry) { | 2782 void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry) { |
2759 // The buffer needs space for 5 unsigned ints, 5 commas, \n and \0 | 2783 // The buffer needs space for 4 unsigned ints, 1 size_t, 5 commas, \n and \0 |
2760 static const int kBufferSize = | 2784 static const int kBufferSize = |
2761 5 * MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned // NOLINT | 2785 4 * MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned // NOLINT |
| 2786 + MaxDecimalDigitsIn<sizeof(size_t)>::kUnsigned // NOLINT |
2762 + 5 + 1 + 1; | 2787 + 5 + 1 + 1; |
2763 EmbeddedVector<char, kBufferSize> buffer; | 2788 EmbeddedVector<char, kBufferSize> buffer; |
2764 int buffer_pos = 0; | 2789 int buffer_pos = 0; |
2765 if (entry_index(entry) != 0) { | 2790 if (entry_index(entry) != 0) { |
2766 buffer[buffer_pos++] = ','; | 2791 buffer[buffer_pos++] = ','; |
2767 } | 2792 } |
2768 buffer_pos = utoa(entry->type(), buffer, buffer_pos); | 2793 buffer_pos = utoa(entry->type(), buffer, buffer_pos); |
2769 buffer[buffer_pos++] = ','; | 2794 buffer[buffer_pos++] = ','; |
2770 buffer_pos = utoa(GetStringId(entry->name()), buffer, buffer_pos); | 2795 buffer_pos = utoa(GetStringId(entry->name()), buffer, buffer_pos); |
2771 buffer[buffer_pos++] = ','; | 2796 buffer[buffer_pos++] = ','; |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3039 writer_->AddString("\"<dummy>\""); | 3064 writer_->AddString("\"<dummy>\""); |
3040 for (int i = 1; i < sorted_strings.length(); ++i) { | 3065 for (int i = 1; i < sorted_strings.length(); ++i) { |
3041 writer_->AddCharacter(','); | 3066 writer_->AddCharacter(','); |
3042 SerializeString(sorted_strings[i]); | 3067 SerializeString(sorted_strings[i]); |
3043 if (writer_->aborted()) return; | 3068 if (writer_->aborted()) return; |
3044 } | 3069 } |
3045 } | 3070 } |
3046 | 3071 |
3047 | 3072 |
3048 } } // namespace v8::internal | 3073 } } // namespace v8::internal |
OLD | NEW |