5 #ifndef V8_PROFILER_HEAP_SNAPSHOT_GENERATOR_H_ 6 #define V8_PROFILER_HEAP_SNAPSHOT_GENERATOR_H_ 9 #include <unordered_map> 10 #include <unordered_set> 13 #include "include/v8-profiler.h" 14 #include "src/base/platform/time.h" 15 #include "src/objects.h" 16 #include "src/objects/fixed-array.h" 17 #include "src/objects/hash-table.h" 18 #include "src/objects/literal-objects.h" 19 #include "src/profiler/strings-storage.h" 20 #include "src/string-hasher.h" 21 #include "src/visitors.h" 26 class AllocationTracker;
27 class AllocationTraceNode;
32 class HeapSnapshotGenerator;
35 class JSGeneratorObject;
39 class JSWeakCollection;
43 : entry_index(entry_index), scriptId(scriptId), line(line), col(col) {}
45 const int entry_index;
54 kContextVariable = v8::HeapGraphEdge::kContextVariable,
55 kElement = v8::HeapGraphEdge::kElement,
56 kProperty = v8::HeapGraphEdge::kProperty,
57 kInternal = v8::HeapGraphEdge::kInternal,
58 kHidden = v8::HeapGraphEdge::kHidden,
59 kShortcut = v8::HeapGraphEdge::kShortcut,
60 kWeak = v8::HeapGraphEdge::kWeak
66 Type
type()
const {
return TypeField::decode(bit_field_); }
68 DCHECK(
type() == kElement ||
type() == kHidden);
71 const char* name()
const {
72 DCHECK(
type() == kContextVariable ||
type() == kProperty ||
73 type() == kInternal ||
type() == kShortcut ||
type() == kWeak);
77 HeapEntry* to()
const {
return to_entry_; }
79 V8_INLINE
Isolate* isolate()
const;
83 int from_index()
const {
return FromIndexField::decode(bit_field_); }
85 class TypeField :
public BitField<Type, 0, 3> {};
86 class FromIndexField :
public BitField<int, 3, 29> {};
101 kHidden = v8::HeapGraphNode::kHidden,
102 kArray = v8::HeapGraphNode::kArray,
103 kString = v8::HeapGraphNode::kString,
104 kObject = v8::HeapGraphNode::kObject,
105 kCode = v8::HeapGraphNode::kCode,
106 kClosure = v8::HeapGraphNode::kClosure,
107 kRegExp = v8::HeapGraphNode::kRegExp,
108 kHeapNumber = v8::HeapGraphNode::kHeapNumber,
109 kNative = v8::HeapGraphNode::kNative,
110 kSynthetic = v8::HeapGraphNode::kSynthetic,
111 kConsString = v8::HeapGraphNode::kConsString,
112 kSlicedString = v8::HeapGraphNode::kSlicedString,
113 kSymbol = v8::HeapGraphNode::kSymbol,
114 kBigInt = v8::HeapGraphNode::kBigInt
121 Type
type()
const {
return static_cast<Type
>(type_); }
122 void set_type(Type
type) { type_ =
type; }
123 const char* name()
const {
return name_; }
124 void set_name(
const char* name) { name_ = name; }
126 size_t self_size()
const {
return self_size_; }
127 unsigned trace_node_id()
const {
return trace_node_id_; }
128 int index()
const {
return index_; }
129 V8_INLINE
int children_count()
const;
130 V8_INLINE
int set_children_index(
int index);
133 V8_INLINE
Isolate* isolate()
const;
135 void SetIndexedReference(
137 void SetNamedReference(
138 HeapGraphEdge::Type
type,
const char* name,
HeapEntry* entry);
139 void SetIndexedAutoIndexReference(HeapGraphEdge::Type
type,
141 SetIndexedReference(
type, children_count_ + 1, child);
143 void SetNamedAutoIndexReference(HeapGraphEdge::Type
type,
144 const char* description,
HeapEntry* child,
148 const char* prefix,
const char* edge_name,
int max_depth,
int indent);
151 V8_INLINE std::vector<HeapGraphEdge*>::iterator children_begin()
const;
152 V8_INLINE std::vector<HeapGraphEdge*>::iterator children_end()
const;
153 const char* TypeAsString();
156 unsigned index_ : 28;
160 unsigned children_count_;
161 unsigned children_end_index_;
168 unsigned trace_node_id_;
182 HeapEntry* root()
const {
return root_entry_; }
183 HeapEntry* gc_roots()
const {
return gc_roots_entry_; }
185 return gc_subroot_entries_[
static_cast<int>(root)];
187 std::deque<HeapEntry>& entries() {
return entries_; }
188 std::deque<HeapGraphEdge>& edges() {
return edges_; }
189 std::vector<HeapGraphEdge*>& children() {
return children_; }
190 const std::vector<SourceLocation>& locations()
const {
return locations_; }
191 void RememberLastJSObjectId();
193 return max_snapshot_js_object_id_;
195 bool is_complete()
const {
return !children_.empty(); }
197 void AddLocation(
HeapEntry* entry,
int scriptId,
int line,
int col);
202 unsigned trace_node_id);
203 void AddSyntheticRootEntries();
207 void Print(
int max_depth);
211 void AddGcRootsEntry();
217 HeapEntry* gc_subroot_entries_[
static_cast<int>(Root::kNumberOfRoots)];
221 std::deque<HeapEntry> entries_;
222 std::deque<HeapGraphEdge> edges_;
223 std::vector<HeapGraphEdge*> children_;
224 std::unordered_map<SnapshotObjectId, HeapEntry*> entries_by_id_cache_;
225 std::vector<SourceLocation> locations_;
236 : id(
id), size(0), count(0), timestamp(base::TimeTicks::Now()) {}
246 Heap* heap()
const {
return heap_; }
248 SnapshotObjectId FindEntry(Address addr);
249 SnapshotObjectId FindOrAddEntry(Address addr,
251 bool accessed =
true);
252 bool MoveObject(Address from, Address to,
int size);
253 void UpdateObjectSize(Address addr,
int size);
254 SnapshotObjectId last_assigned_id()
const {
255 return next_id_ - kObjectIdStep;
258 void StopHeapObjectsTracking();
259 SnapshotObjectId PushHeapObjectsStats(
OutputStream* stream,
261 const std::vector<TimeInterval>& samples()
const {
return time_intervals_; }
265 static const int kObjectIdStep = 2;
266 static const SnapshotObjectId kInternalRootObjectId;
267 static const SnapshotObjectId kGcRootsObjectId;
268 static const SnapshotObjectId kGcRootsFirstSubrootId;
269 static const SnapshotObjectId kFirstAvailableObjectId;
271 void UpdateHeapObjectsMap();
272 void RemoveDeadEntries();
276 EntryInfo(SnapshotObjectId
id, Address addr,
unsigned int size,
278 : id(id), addr(addr), size(size), accessed(accessed) {}
285 SnapshotObjectId next_id_;
287 base::HashMap entries_map_;
288 std::vector<EntryInfo> entries_;
289 std::vector<TimeInterval> time_intervals_;
292 DISALLOW_COPY_AND_ASSIGN(HeapObjectsMap);
297 typedef void* HeapThing;
303 virtual HeapEntry* AllocateEntry(HeapThing ptr) = 0;
309 virtual void ProgressStep() = 0;
310 virtual bool ProgressReport(
bool force) = 0;
321 HeapEntry* AllocateEntry(HeapThing ptr)
override;
322 int EstimateObjectsCount();
324 void TagGlobalObjects();
325 void TagCodeObject(
Code code);
326 void TagBuiltinCodeObject(
Code code,
const char* name);
328 HeapEntry::Type
type,
336 void MarkVisitedField(
int offset);
340 HeapEntry::Type
type,
343 const char* GetSystemEntryName(
HeapObject*
object);
352 void ExtractJSCollectionReferences(
HeapEntry* entry,
354 void ExtractJSWeakCollectionReferences(
HeapEntry* entry,
356 void ExtractEphemeronHashTableReferences(
HeapEntry* entry,
360 void ExtractSharedFunctionInfoReferences(
HeapEntry* entry,
363 void ExtractAccessorInfoReferences(
HeapEntry* entry,
368 void ExtractFeedbackCellReferences(
HeapEntry* entry,
372 void ExtractArrayBoilerplateDescriptionReferences(
376 void ExtractJSGeneratorObjectReferences(
HeapEntry* entry,
379 void ExtractFeedbackVectorReferences(
HeapEntry* entry,
381 void ExtractDescriptorArrayReferences(
HeapEntry* entry,
383 template <
typename T>
384 void ExtractWeakArrayReferences(
int header_size,
HeapEntry* entry,
T* array);
387 Object* callback_obj,
int field_offset = -1);
391 bool IsEssentialObject(
Object*
object);
392 bool IsEssentialHiddenReference(
Object* parent,
int field_offset);
394 void SetContextReference(
HeapEntry* parent_entry,
String reference_name,
395 Object* child,
int field_offset);
396 void SetNativeBindReference(
HeapEntry* parent_entry,
397 const char* reference_name,
Object* child);
398 void SetElementReference(
HeapEntry* parent_entry,
int index,
Object* child);
399 void SetInternalReference(
HeapEntry* parent_entry,
const char* reference_name,
400 Object* child,
int field_offset = -1);
401 void SetInternalReference(
HeapEntry* parent_entry,
int index,
Object* child,
402 int field_offset = -1);
404 int index,
Object* child,
int field_offset);
405 void SetWeakReference(
HeapEntry* parent_entry,
const char* reference_name,
406 Object* child_obj,
int field_offset);
407 void SetWeakReference(
HeapEntry* parent_entry,
int index,
Object* child_obj,
409 void SetPropertyReference(
HeapEntry* parent_entry,
Name reference_name,
411 const char* name_format_string =
nullptr,
412 int field_offset = -1);
413 void SetDataOrAccessorPropertyReference(
414 PropertyKind kind,
HeapEntry* parent_entry,
Name reference_name,
415 Object* child,
const char* name_format_string =
nullptr,
416 int field_offset = -1);
418 void SetUserGlobalReference(
Object* user_global);
419 void SetRootGcRootsReference();
420 void SetGcRootsReference(Root root);
421 void SetGcSubrootReference(Root root,
const char* description,
bool is_weak,
423 const char* GetStrongGcSubrootName(
Object*
object);
424 void TagObject(
Object* obj,
const char* tag);
434 std::unordered_map<JSGlobalObject*, const char*> objects_tags_;
435 std::unordered_map<Object*, const char*> strong_gc_subroot_names_;
436 std::unordered_set<JSGlobalObject*> user_roots_;
439 std::vector<bool> visited_fields_;
457 int EstimateObjectsCount();
461 void FillRetainedObjects();
463 std::vector<HeapObject*>* GetVectorMaybeDisposeInfo(
466 void SetRootNativeRootsReference();
467 void SetWrapperNativeReferences(
HeapObject* wrapper,
469 void VisitSubtreeWrapper(
Object** p, uint16_t class_id);
471 struct RetainedInfoHasher {
473 return ComputeUnseededHash(static_cast<uint32_t>(info->
GetHash()));
476 struct RetainedInfoEquals {
490 bool embedder_queried_;
491 std::unordered_set<Object*> in_groups_;
492 std::unordered_map<v8::RetainedObjectInfo*, std::vector<HeapObject*>*,
493 RetainedInfoHasher, RetainedInfoEquals>
498 std::unique_ptr<HeapEntriesAllocator> synthetic_entries_allocator_;
499 std::unique_ptr<HeapEntriesAllocator> native_entries_allocator_;
500 std::unique_ptr<HeapEntriesAllocator> embedder_graph_entries_allocator_;
503 v8::HeapProfiler::RetainerEdges edges_;
505 static HeapThing
const kNativesRootObject;
516 using HeapEntriesMap = std::unordered_map<HeapThing, HeapEntry*>;
522 bool GenerateSnapshot();
525 auto it = entries_map_.find(ptr);
526 return it != entries_map_.end() ? it->second :
nullptr;
530 return entries_map_.emplace(ptr, allocator->AllocateEntry(ptr))
536 return entry !=
nullptr ? entry : AddEntry(ptr, allocator);
540 bool FillReferences();
541 void ProgressStep()
override;
542 bool ProgressReport(
bool force =
false)
override;
543 void InitProgressCounter();
550 HeapEntriesMap entries_map_;
552 int progress_counter_;
564 : snapshot_(snapshot),
565 strings_(StringsMatch),
572 V8_INLINE
static bool StringsMatch(
void* key1,
void* key2) {
573 return strcmp(reinterpret_cast<char*>(key1),
574 reinterpret_cast<char*>(key2)) == 0;
577 V8_INLINE
static uint32_t StringHash(
const void*
string);
579 int GetStringId(
const char* s);
580 V8_INLINE
int to_node_index(
const HeapEntry* e);
581 V8_INLINE
int to_node_index(
int entry_index);
583 void SerializeEdges();
584 void SerializeImpl();
585 void SerializeNode(
const HeapEntry* entry);
586 void SerializeNodes();
587 void SerializeSnapshot();
588 void SerializeTraceTree();
590 void SerializeTraceNodeInfos();
591 void SerializeSamples();
592 void SerializeString(
const unsigned char* s);
593 void SerializeStrings();
595 void SerializeLocations();
597 static const int kEdgeFieldsCount;
598 static const int kNodeFieldsCount;
601 base::CustomMatcherHashMap strings_;
606 friend class HeapSnapshotJSONSerializerEnumerator;
607 friend class HeapSnapshotJSONSerializerIterator;
616 #endif // V8_PROFILER_HEAP_SNAPSHOT_GENERATOR_H_
virtual bool IsEquivalent(RetainedObjectInfo *other)=0
virtual intptr_t GetHash()=0