| 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 16 matching lines...) Expand all Loading... |
| 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" | |
| 38 | 37 |
| 39 namespace v8 { | 38 namespace v8 { |
| 40 namespace internal { | 39 namespace internal { |
| 41 | 40 |
| 42 | 41 |
| 43 HeapGraphEdge::HeapGraphEdge(Type type, const char* name, int from, int to) | 42 HeapGraphEdge::HeapGraphEdge(Type type, const char* name, int from, int to) |
| 44 : type_(type), | 43 : type_(type), |
| 45 from_index_(from), | 44 from_index_(from), |
| 46 to_index_(to), | 45 to_index_(to), |
| 47 name_(name) { | 46 name_(name) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 66 to_entry_ = &snapshot->entries()[to_index_]; | 65 to_entry_ = &snapshot->entries()[to_index_]; |
| 67 } | 66 } |
| 68 | 67 |
| 69 | 68 |
| 70 const int HeapEntry::kNoEntry = -1; | 69 const int HeapEntry::kNoEntry = -1; |
| 71 | 70 |
| 72 HeapEntry::HeapEntry(HeapSnapshot* snapshot, | 71 HeapEntry::HeapEntry(HeapSnapshot* snapshot, |
| 73 Type type, | 72 Type type, |
| 74 const char* name, | 73 const char* name, |
| 75 SnapshotObjectId id, | 74 SnapshotObjectId id, |
| 76 size_t self_size) | 75 int self_size) |
| 77 : type_(type), | 76 : type_(type), |
| 78 children_count_(0), | 77 children_count_(0), |
| 79 children_index_(-1), | 78 children_index_(-1), |
| 80 self_size_(self_size), | 79 self_size_(self_size), |
| 81 id_(id), | 80 id_(id), |
| 82 snapshot_(snapshot), | 81 snapshot_(snapshot), |
| 83 name_(name) { } | 82 name_(name) { } |
| 84 | 83 |
| 85 | 84 |
| 86 void HeapEntry::SetNamedReference(HeapGraphEdge::Type type, | 85 void HeapEntry::SetNamedReference(HeapGraphEdge::Type type, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 97 HeapEntry* entry) { | 96 HeapEntry* entry) { |
| 98 HeapGraphEdge edge(type, index, this->index(), entry->index()); | 97 HeapGraphEdge edge(type, index, this->index(), entry->index()); |
| 99 snapshot_->edges().Add(edge); | 98 snapshot_->edges().Add(edge); |
| 100 ++children_count_; | 99 ++children_count_; |
| 101 } | 100 } |
| 102 | 101 |
| 103 | 102 |
| 104 void HeapEntry::Print( | 103 void HeapEntry::Print( |
| 105 const char* prefix, const char* edge_name, int max_depth, int indent) { | 104 const char* prefix, const char* edge_name, int max_depth, int indent) { |
| 106 STATIC_CHECK(sizeof(unsigned) == sizeof(id())); | 105 STATIC_CHECK(sizeof(unsigned) == sizeof(id())); |
| 107 OS::Print("%6" V8PRIuPTR " @%6u %*c %s%s: ", | 106 OS::Print("%6d @%6u %*c %s%s: ", |
| 108 self_size(), id(), indent, ' ', prefix, edge_name); | 107 self_size(), id(), indent, ' ', prefix, edge_name); |
| 109 if (type() != kString) { | 108 if (type() != kString) { |
| 110 OS::Print("%s %.40s\n", TypeAsString(), name_); | 109 OS::Print("%s %.40s\n", TypeAsString(), name_); |
| 111 } else { | 110 } else { |
| 112 OS::Print("\""); | 111 OS::Print("\""); |
| 113 const char* c = name_; | 112 const char* c = name_; |
| 114 while (*c && (c - name_) <= 40) { | 113 while (*c && (c - name_) <= 40) { |
| 115 if (*c != '\n') | 114 if (*c != '\n') |
| 116 OS::Print("%c", *c); | 115 OS::Print("%c", *c); |
| 117 else | 116 else |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 | 186 |
| 188 template <size_t ptr_size> struct SnapshotSizeConstants; | 187 template <size_t ptr_size> struct SnapshotSizeConstants; |
| 189 | 188 |
| 190 template <> struct SnapshotSizeConstants<4> { | 189 template <> struct SnapshotSizeConstants<4> { |
| 191 static const int kExpectedHeapGraphEdgeSize = 12; | 190 static const int kExpectedHeapGraphEdgeSize = 12; |
| 192 static const int kExpectedHeapEntrySize = 24; | 191 static const int kExpectedHeapEntrySize = 24; |
| 193 }; | 192 }; |
| 194 | 193 |
| 195 template <> struct SnapshotSizeConstants<8> { | 194 template <> struct SnapshotSizeConstants<8> { |
| 196 static const int kExpectedHeapGraphEdgeSize = 24; | 195 static const int kExpectedHeapGraphEdgeSize = 24; |
| 197 static const int kExpectedHeapEntrySize = 40; | 196 static const int kExpectedHeapEntrySize = 32; |
| 198 }; | 197 }; |
| 199 | 198 |
| 200 } // namespace | 199 } // namespace |
| 201 | 200 |
| 202 | 201 |
| 203 HeapSnapshot::HeapSnapshot(HeapProfiler* profiler, | 202 HeapSnapshot::HeapSnapshot(HeapProfiler* profiler, |
| 204 const char* title, | 203 const char* title, |
| 205 unsigned uid) | 204 unsigned uid) |
| 206 : profiler_(profiler), | 205 : profiler_(profiler), |
| 207 title_(title), | 206 title_(title), |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 270 HeapObjectsMap::GetNthGcSubrootId(tag), | 269 HeapObjectsMap::GetNthGcSubrootId(tag), |
| 271 0); | 270 0); |
| 272 gc_subroot_indexes_[tag] = entry->index(); | 271 gc_subroot_indexes_[tag] = entry->index(); |
| 273 return entry; | 272 return entry; |
| 274 } | 273 } |
| 275 | 274 |
| 276 | 275 |
| 277 HeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type, | 276 HeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type, |
| 278 const char* name, | 277 const char* name, |
| 279 SnapshotObjectId id, | 278 SnapshotObjectId id, |
| 280 size_t size) { | 279 int size) { |
| 281 HeapEntry entry(this, type, name, id, size); | 280 HeapEntry entry(this, type, name, id, size); |
| 282 entries_.Add(entry); | 281 entries_.Add(entry); |
| 283 return &entries_.last(); | 282 return &entries_.last(); |
| 284 } | 283 } |
| 285 | 284 |
| 286 | 285 |
| 287 void HeapSnapshot::FillChildren() { | 286 void HeapSnapshot::FillChildren() { |
| 288 ASSERT(children().is_empty()); | 287 ASSERT(children().is_empty()); |
| 289 children().Allocate(edges().length()); | 288 children().Allocate(edges().length()); |
| 290 int children_index = 0; | 289 int children_index = 0; |
| (...skipping 602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 893 } else if (object->IsHeapNumber()) { | 892 } else if (object->IsHeapNumber()) { |
| 894 return AddEntry(object, HeapEntry::kHeapNumber, "number"); | 893 return AddEntry(object, HeapEntry::kHeapNumber, "number"); |
| 895 } | 894 } |
| 896 return AddEntry(object, HeapEntry::kHidden, GetSystemEntryName(object)); | 895 return AddEntry(object, HeapEntry::kHidden, GetSystemEntryName(object)); |
| 897 } | 896 } |
| 898 | 897 |
| 899 | 898 |
| 900 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object, | 899 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object, |
| 901 HeapEntry::Type type, | 900 HeapEntry::Type type, |
| 902 const char* name) { | 901 const char* name) { |
| 903 return AddEntry(object->address(), type, name, object->Size()); | 902 int object_size = object->Size(); |
| 903 SnapshotObjectId object_id = |
| 904 heap_object_map_->FindOrAddEntry(object->address(), object_size); |
| 905 return snapshot_->AddEntry(type, name, object_id, object_size); |
| 904 } | 906 } |
| 905 | 907 |
| 906 | 908 |
| 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 | |
| 917 class GcSubrootsEnumerator : public ObjectVisitor { | 909 class GcSubrootsEnumerator : public ObjectVisitor { |
| 918 public: | 910 public: |
| 919 GcSubrootsEnumerator( | 911 GcSubrootsEnumerator( |
| 920 SnapshotFillerInterface* filler, V8HeapExplorer* explorer) | 912 SnapshotFillerInterface* filler, V8HeapExplorer* explorer) |
| 921 : filler_(filler), | 913 : filler_(filler), |
| 922 explorer_(explorer), | 914 explorer_(explorer), |
| 923 previous_object_count_(0), | 915 previous_object_count_(0), |
| 924 object_count_(0) { | 916 object_count_(0) { |
| 925 } | 917 } |
| 926 void VisitPointers(Object** start, Object** end) { | 918 void VisitPointers(Object** start, Object** end) { |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1030 }; | 1022 }; |
| 1031 | 1023 |
| 1032 | 1024 |
| 1033 void V8HeapExplorer::ExtractReferences(HeapObject* obj) { | 1025 void V8HeapExplorer::ExtractReferences(HeapObject* obj) { |
| 1034 HeapEntry* heap_entry = GetEntry(obj); | 1026 HeapEntry* heap_entry = GetEntry(obj); |
| 1035 if (heap_entry == NULL) return; // No interest in this object. | 1027 if (heap_entry == NULL) return; // No interest in this object. |
| 1036 int entry = heap_entry->index(); | 1028 int entry = heap_entry->index(); |
| 1037 | 1029 |
| 1038 if (obj->IsJSGlobalProxy()) { | 1030 if (obj->IsJSGlobalProxy()) { |
| 1039 ExtractJSGlobalProxyReferences(entry, JSGlobalProxy::cast(obj)); | 1031 ExtractJSGlobalProxyReferences(entry, JSGlobalProxy::cast(obj)); |
| 1040 } else if (obj->IsJSArrayBuffer()) { | |
| 1041 ExtractJSArrayBufferReferences(entry, JSArrayBuffer::cast(obj)); | |
| 1042 } else if (obj->IsJSObject()) { | 1032 } else if (obj->IsJSObject()) { |
| 1043 ExtractJSObjectReferences(entry, JSObject::cast(obj)); | 1033 ExtractJSObjectReferences(entry, JSObject::cast(obj)); |
| 1044 } else if (obj->IsString()) { | 1034 } else if (obj->IsString()) { |
| 1045 ExtractStringReferences(entry, String::cast(obj)); | 1035 ExtractStringReferences(entry, String::cast(obj)); |
| 1046 } else if (obj->IsContext()) { | 1036 } else if (obj->IsContext()) { |
| 1047 ExtractContextReferences(entry, Context::cast(obj)); | 1037 ExtractContextReferences(entry, Context::cast(obj)); |
| 1048 } else if (obj->IsMap()) { | 1038 } else if (obj->IsMap()) { |
| 1049 ExtractMapReferences(entry, Map::cast(obj)); | 1039 ExtractMapReferences(entry, Map::cast(obj)); |
| 1050 } else if (obj->IsSharedFunctionInfo()) { | 1040 } else if (obj->IsSharedFunctionInfo()) { |
| 1051 ExtractSharedFunctionInfoReferences(entry, SharedFunctionInfo::cast(obj)); | 1041 ExtractSharedFunctionInfoReferences(entry, SharedFunctionInfo::cast(obj)); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1150 "global_receiver", global_obj->global_receiver(), | 1140 "global_receiver", global_obj->global_receiver(), |
| 1151 GlobalObject::kGlobalReceiverOffset); | 1141 GlobalObject::kGlobalReceiverOffset); |
| 1152 STATIC_CHECK(GlobalObject::kHeaderSize - JSObject::kHeaderSize == | 1142 STATIC_CHECK(GlobalObject::kHeaderSize - JSObject::kHeaderSize == |
| 1153 4 * kPointerSize); | 1143 4 * kPointerSize); |
| 1154 } else if (obj->IsJSArrayBufferView()) { | 1144 } else if (obj->IsJSArrayBufferView()) { |
| 1155 JSArrayBufferView* view = JSArrayBufferView::cast(obj); | 1145 JSArrayBufferView* view = JSArrayBufferView::cast(obj); |
| 1156 SetInternalReference(view, entry, "buffer", view->buffer(), | 1146 SetInternalReference(view, entry, "buffer", view->buffer(), |
| 1157 JSArrayBufferView::kBufferOffset); | 1147 JSArrayBufferView::kBufferOffset); |
| 1158 SetWeakReference(view, entry, "weak_next", view->weak_next(), | 1148 SetWeakReference(view, entry, "weak_next", view->weak_next(), |
| 1159 JSArrayBufferView::kWeakNextOffset); | 1149 JSArrayBufferView::kWeakNextOffset); |
| 1150 } else if (obj->IsJSArrayBuffer()) { |
| 1151 JSArrayBuffer* buffer = JSArrayBuffer::cast(obj); |
| 1152 SetWeakReference(buffer, entry, "weak_next", buffer->weak_next(), |
| 1153 JSArrayBuffer::kWeakNextOffset); |
| 1154 SetWeakReference(buffer, entry, |
| 1155 "weak_first_view", buffer->weak_first_view(), |
| 1156 JSArrayBuffer::kWeakFirstViewOffset); |
| 1160 } | 1157 } |
| 1161 TagObject(js_obj->properties(), "(object properties)"); | 1158 TagObject(js_obj->properties(), "(object properties)"); |
| 1162 SetInternalReference(obj, entry, | 1159 SetInternalReference(obj, entry, |
| 1163 "properties", js_obj->properties(), | 1160 "properties", js_obj->properties(), |
| 1164 JSObject::kPropertiesOffset); | 1161 JSObject::kPropertiesOffset); |
| 1165 TagObject(js_obj->elements(), "(object elements)"); | 1162 TagObject(js_obj->elements(), "(object elements)"); |
| 1166 SetInternalReference(obj, entry, | 1163 SetInternalReference(obj, entry, |
| 1167 "elements", js_obj->elements(), | 1164 "elements", js_obj->elements(), |
| 1168 JSObject::kElementsOffset); | 1165 JSObject::kElementsOffset); |
| 1169 } | 1166 } |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1450 AllocationSite::kNestedSiteOffset); | 1447 AllocationSite::kNestedSiteOffset); |
| 1451 SetInternalReference(site, entry, "dependent_code", site->dependent_code(), | 1448 SetInternalReference(site, entry, "dependent_code", site->dependent_code(), |
| 1452 AllocationSite::kDependentCodeOffset); | 1449 AllocationSite::kDependentCodeOffset); |
| 1453 // Do not visit weak_next as it is not visited by the StaticVisitor, | 1450 // 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. | 1451 // and we're not very interested in weak_next field here. |
| 1455 STATIC_CHECK(AllocationSite::kWeakNextOffset >= | 1452 STATIC_CHECK(AllocationSite::kWeakNextOffset >= |
| 1456 AllocationSite::BodyDescriptor::kEndOffset); | 1453 AllocationSite::BodyDescriptor::kEndOffset); |
| 1457 } | 1454 } |
| 1458 | 1455 |
| 1459 | 1456 |
| 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 | |
| 1496 void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj, int entry) { | 1457 void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj, int entry) { |
| 1497 if (!js_obj->IsJSFunction()) return; | 1458 if (!js_obj->IsJSFunction()) return; |
| 1498 | 1459 |
| 1499 JSFunction* func = JSFunction::cast(js_obj); | 1460 JSFunction* func = JSFunction::cast(js_obj); |
| 1500 if (func->shared()->bound()) { | 1461 if (func->shared()->bound()) { |
| 1501 FixedArray* bindings = func->function_bindings(); | 1462 FixedArray* bindings = func->function_bindings(); |
| 1502 SetNativeBindReference(js_obj, entry, "bound_this", | 1463 SetNativeBindReference(js_obj, entry, "bound_this", |
| 1503 bindings->get(JSFunction::kBoundThisIndex)); | 1464 bindings->get(JSFunction::kBoundThisIndex)); |
| 1504 SetNativeBindReference(js_obj, entry, "bound_function", | 1465 SetNativeBindReference(js_obj, entry, "bound_function", |
| 1505 bindings->get(JSFunction::kBoundFunctionIndex)); | 1466 bindings->get(JSFunction::kBoundFunctionIndex)); |
| (...skipping 1189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2695 int HeapSnapshotJSONSerializer::GetStringId(const char* s) { | 2656 int HeapSnapshotJSONSerializer::GetStringId(const char* s) { |
| 2696 HashMap::Entry* cache_entry = strings_.Lookup( | 2657 HashMap::Entry* cache_entry = strings_.Lookup( |
| 2697 const_cast<char*>(s), StringHash(s), true); | 2658 const_cast<char*>(s), StringHash(s), true); |
| 2698 if (cache_entry->value == NULL) { | 2659 if (cache_entry->value == NULL) { |
| 2699 cache_entry->value = reinterpret_cast<void*>(next_string_id_++); | 2660 cache_entry->value = reinterpret_cast<void*>(next_string_id_++); |
| 2700 } | 2661 } |
| 2701 return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); | 2662 return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); |
| 2702 } | 2663 } |
| 2703 | 2664 |
| 2704 | 2665 |
| 2705 namespace { | 2666 static int utoa(unsigned value, const Vector<char>& buffer, int buffer_pos) { |
| 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 | |
| 2723 int number_of_digits = 0; | 2667 int number_of_digits = 0; |
| 2724 T t = value; | 2668 unsigned t = value; |
| 2725 do { | 2669 do { |
| 2726 ++number_of_digits; | 2670 ++number_of_digits; |
| 2727 } while (t /= 10); | 2671 } while (t /= 10); |
| 2728 | 2672 |
| 2729 buffer_pos += number_of_digits; | 2673 buffer_pos += number_of_digits; |
| 2730 int result = buffer_pos; | 2674 int result = buffer_pos; |
| 2731 do { | 2675 do { |
| 2732 int last_digit = static_cast<int>(value % 10); | 2676 int last_digit = value % 10; |
| 2733 buffer[--buffer_pos] = '0' + last_digit; | 2677 buffer[--buffer_pos] = '0' + last_digit; |
| 2734 value /= 10; | 2678 value /= 10; |
| 2735 } while (value); | 2679 } while (value); |
| 2736 return result; | 2680 return result; |
| 2737 } | 2681 } |
| 2738 | 2682 |
| 2739 | 2683 |
| 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 | |
| 2748 void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge, | 2684 void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge, |
| 2749 bool first_edge) { | 2685 bool first_edge) { |
| 2750 // The buffer needs space for 3 unsigned ints, 3 commas, \n and \0 | 2686 // The buffer needs space for 3 unsigned ints, 3 commas, \n and \0 |
| 2751 static const int kBufferSize = | 2687 static const int kBufferSize = |
| 2752 MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned * 3 + 3 + 2; // NOLINT | 2688 MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned * 3 + 3 + 2; // NOLINT |
| 2753 EmbeddedVector<char, kBufferSize> buffer; | 2689 EmbeddedVector<char, kBufferSize> buffer; |
| 2754 int edge_name_or_index = edge->type() == HeapGraphEdge::kElement | 2690 int edge_name_or_index = edge->type() == HeapGraphEdge::kElement |
| 2755 || edge->type() == HeapGraphEdge::kHidden | 2691 || edge->type() == HeapGraphEdge::kHidden |
| 2756 ? edge->index() : GetStringId(edge->name()); | 2692 ? edge->index() : GetStringId(edge->name()); |
| 2757 int buffer_pos = 0; | 2693 int buffer_pos = 0; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2774 for (int i = 0; i < edges.length(); ++i) { | 2710 for (int i = 0; i < edges.length(); ++i) { |
| 2775 ASSERT(i == 0 || | 2711 ASSERT(i == 0 || |
| 2776 edges[i - 1]->from()->index() <= edges[i]->from()->index()); | 2712 edges[i - 1]->from()->index() <= edges[i]->from()->index()); |
| 2777 SerializeEdge(edges[i], i == 0); | 2713 SerializeEdge(edges[i], i == 0); |
| 2778 if (writer_->aborted()) return; | 2714 if (writer_->aborted()) return; |
| 2779 } | 2715 } |
| 2780 } | 2716 } |
| 2781 | 2717 |
| 2782 | 2718 |
| 2783 void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry) { | 2719 void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry) { |
| 2784 // The buffer needs space for 4 unsigned ints, 1 size_t, 5 commas, \n and \0 | 2720 // The buffer needs space for 5 unsigned ints, 5 commas, \n and \0 |
| 2785 static const int kBufferSize = | 2721 static const int kBufferSize = |
| 2786 4 * MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned // NOLINT | 2722 5 * MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned // NOLINT |
| 2787 + MaxDecimalDigitsIn<sizeof(size_t)>::kUnsigned // NOLINT | |
| 2788 + 5 + 1 + 1; | 2723 + 5 + 1 + 1; |
| 2789 EmbeddedVector<char, kBufferSize> buffer; | 2724 EmbeddedVector<char, kBufferSize> buffer; |
| 2790 int buffer_pos = 0; | 2725 int buffer_pos = 0; |
| 2791 if (entry_index(entry) != 0) { | 2726 if (entry_index(entry) != 0) { |
| 2792 buffer[buffer_pos++] = ','; | 2727 buffer[buffer_pos++] = ','; |
| 2793 } | 2728 } |
| 2794 buffer_pos = utoa(entry->type(), buffer, buffer_pos); | 2729 buffer_pos = utoa(entry->type(), buffer, buffer_pos); |
| 2795 buffer[buffer_pos++] = ','; | 2730 buffer[buffer_pos++] = ','; |
| 2796 buffer_pos = utoa(GetStringId(entry->name()), buffer, buffer_pos); | 2731 buffer_pos = utoa(GetStringId(entry->name()), buffer, buffer_pos); |
| 2797 buffer[buffer_pos++] = ','; | 2732 buffer[buffer_pos++] = ','; |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3065 writer_->AddString("\"<dummy>\""); | 3000 writer_->AddString("\"<dummy>\""); |
| 3066 for (int i = 1; i < sorted_strings.length(); ++i) { | 3001 for (int i = 1; i < sorted_strings.length(); ++i) { |
| 3067 writer_->AddCharacter(','); | 3002 writer_->AddCharacter(','); |
| 3068 SerializeString(sorted_strings[i]); | 3003 SerializeString(sorted_strings[i]); |
| 3069 if (writer_->aborted()) return; | 3004 if (writer_->aborted()) return; |
| 3070 } | 3005 } |
| 3071 } | 3006 } |
| 3072 | 3007 |
| 3073 | 3008 |
| 3074 } } // namespace v8::internal | 3009 } } // namespace v8::internal |
| OLD | NEW |