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 537 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1458 | 1458 |
1459 void V8HeapExplorer::ExtractJSArrayBufferReferences( | 1459 void V8HeapExplorer::ExtractJSArrayBufferReferences( |
1460 int entry, JSArrayBuffer* buffer) { | 1460 int entry, JSArrayBuffer* buffer) { |
1461 SetWeakReference(buffer, entry, "weak_next", buffer->weak_next(), | 1461 SetWeakReference(buffer, entry, "weak_next", buffer->weak_next(), |
1462 JSArrayBuffer::kWeakNextOffset); | 1462 JSArrayBuffer::kWeakNextOffset); |
1463 SetWeakReference(buffer, entry, | 1463 SetWeakReference(buffer, entry, |
1464 "weak_first_view", buffer->weak_first_view(), | 1464 "weak_first_view", buffer->weak_first_view(), |
1465 JSArrayBuffer::kWeakFirstViewOffset); | 1465 JSArrayBuffer::kWeakFirstViewOffset); |
1466 // Setup a reference to a native memory backing_store object. | 1466 // Setup a reference to a native memory backing_store object. |
1467 size_t data_size = NumberToSize(heap_->isolate(), buffer->byte_length()); | 1467 size_t data_size = NumberToSize(heap_->isolate(), buffer->byte_length()); |
1468 CHECK(data_size <= static_cast<size_t>(kMaxInt)); | |
1469 HeapEntry* data_entry = AddEntry( | 1468 HeapEntry* data_entry = AddEntry( |
1470 static_cast<Address>(buffer->backing_store()), | 1469 static_cast<Address>(buffer->backing_store()), |
1471 HeapEntry::kNative, "system / ArrayBufferData", | 1470 HeapEntry::kNative, "system / ArrayBufferData", data_size); |
1472 static_cast<int>(data_size)); | |
1473 filler_->SetNamedReference(HeapGraphEdge::kInternal, | 1471 filler_->SetNamedReference(HeapGraphEdge::kInternal, |
1474 entry, "backing_store", data_entry); | 1472 entry, "backing_store", data_entry); |
1475 } | 1473 } |
1476 | 1474 |
1477 | 1475 |
1478 void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj, int entry) { | 1476 void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj, int entry) { |
1479 if (!js_obj->IsJSFunction()) return; | 1477 if (!js_obj->IsJSFunction()) return; |
1480 | 1478 |
1481 JSFunction* func = JSFunction::cast(js_obj); | 1479 JSFunction* func = JSFunction::cast(js_obj); |
1482 if (func->shared()->bound()) { | 1480 if (func->shared()->bound()) { |
(...skipping 1194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2677 int HeapSnapshotJSONSerializer::GetStringId(const char* s) { | 2675 int HeapSnapshotJSONSerializer::GetStringId(const char* s) { |
2678 HashMap::Entry* cache_entry = strings_.Lookup( | 2676 HashMap::Entry* cache_entry = strings_.Lookup( |
2679 const_cast<char*>(s), StringHash(s), true); | 2677 const_cast<char*>(s), StringHash(s), true); |
2680 if (cache_entry->value == NULL) { | 2678 if (cache_entry->value == NULL) { |
2681 cache_entry->value = reinterpret_cast<void*>(next_string_id_++); | 2679 cache_entry->value = reinterpret_cast<void*>(next_string_id_++); |
2682 } | 2680 } |
2683 return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); | 2681 return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); |
2684 } | 2682 } |
2685 | 2683 |
2686 | 2684 |
2687 static int utoa(unsigned value, const Vector<char>& buffer, int buffer_pos) { | 2685 namespace { |
| 2686 |
| 2687 template<size_t size> struct ToUnsigned; |
| 2688 |
| 2689 template<> struct ToUnsigned<4> { |
| 2690 typedef uint32_t Type; |
| 2691 }; |
| 2692 |
| 2693 template<> struct ToUnsigned<8> { |
| 2694 typedef uint64_t Type; |
| 2695 }; |
| 2696 |
| 2697 } // namespace |
| 2698 |
| 2699 |
| 2700 template<typename T> |
| 2701 static int utoa_impl(T value, const Vector<char>& buffer, int buffer_pos) { |
| 2702 STATIC_CHECK(static_cast<T>(-1) > 0); // Check that T is unsigned |
2688 int number_of_digits = 0; | 2703 int number_of_digits = 0; |
2689 unsigned t = value; | 2704 T t = value; |
2690 do { | 2705 do { |
2691 ++number_of_digits; | 2706 ++number_of_digits; |
2692 } while (t /= 10); | 2707 } while (t /= 10); |
2693 | 2708 |
2694 buffer_pos += number_of_digits; | 2709 buffer_pos += number_of_digits; |
2695 int result = buffer_pos; | 2710 int result = buffer_pos; |
2696 do { | 2711 do { |
2697 int last_digit = value % 10; | 2712 int last_digit = static_cast<int>(value % 10); |
2698 buffer[--buffer_pos] = '0' + last_digit; | 2713 buffer[--buffer_pos] = '0' + last_digit; |
2699 value /= 10; | 2714 value /= 10; |
2700 } while (value); | 2715 } while (value); |
2701 return result; | 2716 return result; |
2702 } | 2717 } |
2703 | 2718 |
2704 | 2719 |
| 2720 template<typename T> |
| 2721 static int utoa(T value, const Vector<char>& buffer, int buffer_pos) { |
| 2722 typename ToUnsigned<sizeof(value)>::Type unsigned_value = value; |
| 2723 STATIC_CHECK(sizeof(value) == sizeof(unsigned_value)); |
| 2724 return utoa_impl(unsigned_value, buffer, buffer_pos); |
| 2725 } |
| 2726 |
| 2727 |
2705 void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge, | 2728 void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge, |
2706 bool first_edge) { | 2729 bool first_edge) { |
2707 // The buffer needs space for 3 unsigned ints, 3 commas, \n and \0 | 2730 // The buffer needs space for 3 unsigned ints, 3 commas, \n and \0 |
2708 static const int kBufferSize = | 2731 static const int kBufferSize = |
2709 MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned * 3 + 3 + 2; // NOLINT | 2732 MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned * 3 + 3 + 2; // NOLINT |
2710 EmbeddedVector<char, kBufferSize> buffer; | 2733 EmbeddedVector<char, kBufferSize> buffer; |
2711 int edge_name_or_index = edge->type() == HeapGraphEdge::kElement | 2734 int edge_name_or_index = edge->type() == HeapGraphEdge::kElement |
2712 || edge->type() == HeapGraphEdge::kHidden | 2735 || edge->type() == HeapGraphEdge::kHidden |
2713 ? edge->index() : GetStringId(edge->name()); | 2736 ? edge->index() : GetStringId(edge->name()); |
2714 int buffer_pos = 0; | 2737 int buffer_pos = 0; |
(...skipping 16 matching lines...) Expand all Loading... |
2731 for (int i = 0; i < edges.length(); ++i) { | 2754 for (int i = 0; i < edges.length(); ++i) { |
2732 ASSERT(i == 0 || | 2755 ASSERT(i == 0 || |
2733 edges[i - 1]->from()->index() <= edges[i]->from()->index()); | 2756 edges[i - 1]->from()->index() <= edges[i]->from()->index()); |
2734 SerializeEdge(edges[i], i == 0); | 2757 SerializeEdge(edges[i], i == 0); |
2735 if (writer_->aborted()) return; | 2758 if (writer_->aborted()) return; |
2736 } | 2759 } |
2737 } | 2760 } |
2738 | 2761 |
2739 | 2762 |
2740 void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry) { | 2763 void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry) { |
2741 // The buffer needs space for 5 unsigned ints, 5 commas, \n and \0 | 2764 // The buffer needs space for 4 unsigned ints, 1 size_t, 5 commas, \n and \0 |
2742 static const int kBufferSize = | 2765 static const int kBufferSize = |
2743 5 * MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned // NOLINT | 2766 4 * MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned // NOLINT |
| 2767 + MaxDecimalDigitsIn<sizeof(size_t)>::kUnsigned // NOLINT |
2744 + 5 + 1 + 1; | 2768 + 5 + 1 + 1; |
2745 EmbeddedVector<char, kBufferSize> buffer; | 2769 EmbeddedVector<char, kBufferSize> buffer; |
2746 int buffer_pos = 0; | 2770 int buffer_pos = 0; |
2747 if (entry_index(entry) != 0) { | 2771 if (entry_index(entry) != 0) { |
2748 buffer[buffer_pos++] = ','; | 2772 buffer[buffer_pos++] = ','; |
2749 } | 2773 } |
2750 buffer_pos = utoa(entry->type(), buffer, buffer_pos); | 2774 buffer_pos = utoa(entry->type(), buffer, buffer_pos); |
2751 buffer[buffer_pos++] = ','; | 2775 buffer[buffer_pos++] = ','; |
2752 buffer_pos = utoa(GetStringId(entry->name()), buffer, buffer_pos); | 2776 buffer_pos = utoa(GetStringId(entry->name()), buffer, buffer_pos); |
2753 buffer[buffer_pos++] = ','; | 2777 buffer[buffer_pos++] = ','; |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3021 writer_->AddString("\"<dummy>\""); | 3045 writer_->AddString("\"<dummy>\""); |
3022 for (int i = 1; i < sorted_strings.length(); ++i) { | 3046 for (int i = 1; i < sorted_strings.length(); ++i) { |
3023 writer_->AddCharacter(','); | 3047 writer_->AddCharacter(','); |
3024 SerializeString(sorted_strings[i]); | 3048 SerializeString(sorted_strings[i]); |
3025 if (writer_->aborted()) return; | 3049 if (writer_->aborted()) return; |
3026 } | 3050 } |
3027 } | 3051 } |
3028 | 3052 |
3029 | 3053 |
3030 } } // namespace v8::internal | 3054 } } // namespace v8::internal |
OLD | NEW |