Line data Source code
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
3 : // found in the LICENSE file.
4 :
5 : #ifndef V8_PROFILER_HEAP_SNAPSHOT_GENERATOR_H_
6 : #define V8_PROFILER_HEAP_SNAPSHOT_GENERATOR_H_
7 :
8 : #include <deque>
9 : #include <unordered_map>
10 : #include <unordered_set>
11 : #include <vector>
12 :
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/heap-object.h"
19 : #include "src/objects/js-objects.h"
20 : #include "src/objects/literal-objects.h"
21 : #include "src/profiler/strings-storage.h"
22 : #include "src/string-hasher.h"
23 : #include "src/visitors.h"
24 :
25 : namespace v8 {
26 : namespace internal {
27 :
28 : class AllocationTracker;
29 : class AllocationTraceNode;
30 : class HeapEntry;
31 : class HeapIterator;
32 : class HeapProfiler;
33 : class HeapSnapshot;
34 : class HeapSnapshotGenerator;
35 : class JSArrayBuffer;
36 : class JSCollection;
37 : class JSGeneratorObject;
38 : class JSGlobalObject;
39 : class JSGlobalProxy;
40 : class JSPromise;
41 : class JSWeakCollection;
42 :
43 : struct SourceLocation {
44 : SourceLocation(int entry_index, int scriptId, int line, int col)
45 134703 : : entry_index(entry_index), scriptId(scriptId), line(line), col(col) {}
46 :
47 : const int entry_index;
48 : const int scriptId;
49 : const int line;
50 : const int col;
51 : };
52 :
53 : class HeapGraphEdge {
54 : public:
55 : enum Type {
56 : kContextVariable = v8::HeapGraphEdge::kContextVariable,
57 : kElement = v8::HeapGraphEdge::kElement,
58 : kProperty = v8::HeapGraphEdge::kProperty,
59 : kInternal = v8::HeapGraphEdge::kInternal,
60 : kHidden = v8::HeapGraphEdge::kHidden,
61 : kShortcut = v8::HeapGraphEdge::kShortcut,
62 : kWeak = v8::HeapGraphEdge::kWeak
63 : };
64 :
65 : HeapGraphEdge(Type type, const char* name, HeapEntry* from, HeapEntry* to);
66 : HeapGraphEdge(Type type, int index, HeapEntry* from, HeapEntry* to);
67 :
68 : Type type() const { return TypeField::decode(bit_field_); }
69 : int index() const {
70 : DCHECK(type() == kElement || type() == kHidden);
71 : return index_;
72 : }
73 : const char* name() const {
74 : DCHECK(type() == kContextVariable || type() == kProperty ||
75 : type() == kInternal || type() == kShortcut || type() == kWeak);
76 : return name_;
77 : }
78 : V8_INLINE HeapEntry* from() const;
79 : HeapEntry* to() const { return to_entry_; }
80 :
81 : V8_INLINE Isolate* isolate() const;
82 :
83 : private:
84 : V8_INLINE HeapSnapshot* snapshot() const;
85 21931082 : int from_index() const { return FromIndexField::decode(bit_field_); }
86 :
87 : class TypeField : public BitField<Type, 0, 3> {};
88 : class FromIndexField : public BitField<int, 3, 29> {};
89 : uint32_t bit_field_;
90 : HeapEntry* to_entry_;
91 : union {
92 : int index_;
93 : const char* name_;
94 : };
95 : };
96 :
97 :
98 : // HeapEntry instances represent an entity from the heap (or a special
99 : // virtual node, e.g. root).
100 : class HeapEntry {
101 : public:
102 : enum Type {
103 : kHidden = v8::HeapGraphNode::kHidden,
104 : kArray = v8::HeapGraphNode::kArray,
105 : kString = v8::HeapGraphNode::kString,
106 : kObject = v8::HeapGraphNode::kObject,
107 : kCode = v8::HeapGraphNode::kCode,
108 : kClosure = v8::HeapGraphNode::kClosure,
109 : kRegExp = v8::HeapGraphNode::kRegExp,
110 : kHeapNumber = v8::HeapGraphNode::kHeapNumber,
111 : kNative = v8::HeapGraphNode::kNative,
112 : kSynthetic = v8::HeapGraphNode::kSynthetic,
113 : kConsString = v8::HeapGraphNode::kConsString,
114 : kSlicedString = v8::HeapGraphNode::kSlicedString,
115 : kSymbol = v8::HeapGraphNode::kSymbol,
116 : kBigInt = v8::HeapGraphNode::kBigInt
117 : };
118 :
119 : HeapEntry(HeapSnapshot* snapshot, int index, Type type, const char* name,
120 : SnapshotObjectId id, size_t self_size, unsigned trace_node_id);
121 :
122 10965541 : HeapSnapshot* snapshot() { return snapshot_; }
123 209431 : Type type() const { return static_cast<Type>(type_); }
124 10 : void set_type(Type type) { type_ = type; }
125 : const char* name() const { return name_; }
126 617848 : void set_name(const char* name) { name_ = name; }
127 : SnapshotObjectId id() const { return id_; }
128 : size_t self_size() const { return self_size_; }
129 : unsigned trace_node_id() const { return trace_node_id_; }
130 12080558 : int index() const { return index_; }
131 : V8_INLINE int children_count() const;
132 : V8_INLINE int set_children_index(int index);
133 : V8_INLINE void add_child(HeapGraphEdge* edge);
134 : V8_INLINE HeapGraphEdge* child(int i);
135 : V8_INLINE Isolate* isolate() const;
136 :
137 : void SetIndexedReference(
138 : HeapGraphEdge::Type type, int index, HeapEntry* entry);
139 : void SetNamedReference(
140 : HeapGraphEdge::Type type, const char* name, HeapEntry* entry);
141 10090 : void SetIndexedAutoIndexReference(HeapGraphEdge::Type type,
142 : HeapEntry* child) {
143 10090 : SetIndexedReference(type, children_count_ + 1, child);
144 10090 : }
145 : void SetNamedAutoIndexReference(HeapGraphEdge::Type type,
146 : const char* description, HeapEntry* child,
147 : StringsStorage* strings);
148 :
149 : void Print(
150 : const char* prefix, const char* edge_name, int max_depth, int indent);
151 :
152 : private:
153 : V8_INLINE std::vector<HeapGraphEdge*>::iterator children_begin() const;
154 : V8_INLINE std::vector<HeapGraphEdge*>::iterator children_end() const;
155 : const char* TypeAsString();
156 :
157 : unsigned type_: 4;
158 : unsigned index_ : 28; // Supports up to ~250M objects.
159 : union {
160 : // The count is used during the snapshot build phase,
161 : // then it gets converted into the index by the |FillChildren| function.
162 : unsigned children_count_;
163 : unsigned children_end_index_;
164 : };
165 : size_t self_size_;
166 : HeapSnapshot* snapshot_;
167 : const char* name_;
168 : SnapshotObjectId id_;
169 : // id of allocation stack trace top node
170 : unsigned trace_node_id_;
171 : };
172 :
173 : // HeapSnapshot represents a single heap snapshot. It is stored in
174 : // HeapProfiler, which is also a factory for
175 : // HeapSnapshots. All HeapSnapshots share strings copied from JS heap
176 : // to be able to return them even if they were collected.
177 : // HeapSnapshotGenerator fills in a HeapSnapshot.
178 798 : class HeapSnapshot {
179 : public:
180 : explicit HeapSnapshot(HeapProfiler* profiler);
181 : void Delete();
182 :
183 6009015 : HeapProfiler* profiler() const { return profiler_; }
184 : HeapEntry* root() const { return root_entry_; }
185 : HeapEntry* gc_roots() const { return gc_roots_entry_; }
186 : HeapEntry* gc_subroot(Root root) const {
187 1447737 : return gc_subroot_entries_[static_cast<int>(root)];
188 : }
189 17743582 : std::deque<HeapEntry>& entries() { return entries_; }
190 : std::deque<HeapGraphEdge>& edges() { return edges_; }
191 18107438 : std::vector<HeapGraphEdge*>& children() { return children_; }
192 : const std::vector<SourceLocation>& locations() const { return locations_; }
193 : void RememberLastJSObjectId();
194 : SnapshotObjectId max_snapshot_js_object_id() const {
195 : return max_snapshot_js_object_id_;
196 : }
197 : bool is_complete() const { return !children_.empty(); }
198 :
199 : void AddLocation(HeapEntry* entry, int scriptId, int line, int col);
200 : HeapEntry* AddEntry(HeapEntry::Type type,
201 : const char* name,
202 : SnapshotObjectId id,
203 : size_t size,
204 : unsigned trace_node_id);
205 : void AddSyntheticRootEntries();
206 : HeapEntry* GetEntryById(SnapshotObjectId id);
207 : void FillChildren();
208 :
209 : void Print(int max_depth);
210 :
211 : private:
212 : void AddRootEntry();
213 : void AddGcRootsEntry();
214 : void AddGcSubrootEntry(Root root, SnapshotObjectId id);
215 :
216 : HeapProfiler* profiler_;
217 : HeapEntry* root_entry_ = nullptr;
218 : HeapEntry* gc_roots_entry_ = nullptr;
219 : HeapEntry* gc_subroot_entries_[static_cast<int>(Root::kNumberOfRoots)];
220 : // For |entries_| we rely on the deque property, that it never reallocates
221 : // backing storage, thus all entry pointers remain valid for the duration
222 : // of snapshotting.
223 : std::deque<HeapEntry> entries_;
224 : std::deque<HeapGraphEdge> edges_;
225 : std::vector<HeapGraphEdge*> children_;
226 : std::unordered_map<SnapshotObjectId, HeapEntry*> entries_by_id_cache_;
227 : std::vector<SourceLocation> locations_;
228 : SnapshotObjectId max_snapshot_js_object_id_ = -1;
229 :
230 : DISALLOW_COPY_AND_ASSIGN(HeapSnapshot);
231 : };
232 :
233 :
234 133413 : class HeapObjectsMap {
235 : public:
236 : struct TimeInterval {
237 : explicit TimeInterval(SnapshotObjectId id)
238 55 : : id(id), size(0), count(0), timestamp(base::TimeTicks::Now()) {}
239 0 : SnapshotObjectId last_assigned_id() const { return id - kObjectIdStep; }
240 : SnapshotObjectId id;
241 : uint32_t size;
242 : uint32_t count;
243 : base::TimeTicks timestamp;
244 : };
245 :
246 : explicit HeapObjectsMap(Heap* heap);
247 :
248 : Heap* heap() const { return heap_; }
249 :
250 : SnapshotObjectId FindEntry(Address addr);
251 : SnapshotObjectId FindOrAddEntry(Address addr,
252 : unsigned int size,
253 : bool accessed = true);
254 : bool MoveObject(Address from, Address to, int size);
255 : void UpdateObjectSize(Address addr, int size);
256 : SnapshotObjectId last_assigned_id() const {
257 449 : return next_id_ - kObjectIdStep;
258 : }
259 :
260 : void StopHeapObjectsTracking();
261 : SnapshotObjectId PushHeapObjectsStats(OutputStream* stream,
262 : int64_t* timestamp_us);
263 : const std::vector<TimeInterval>& samples() const { return time_intervals_; }
264 :
265 : SnapshotObjectId GenerateId(v8::RetainedObjectInfo* info);
266 :
267 : static const int kObjectIdStep = 2;
268 : static const SnapshotObjectId kInternalRootObjectId;
269 : static const SnapshotObjectId kGcRootsObjectId;
270 : static const SnapshotObjectId kGcRootsFirstSubrootId;
271 : static const SnapshotObjectId kFirstAvailableObjectId;
272 :
273 : void UpdateHeapObjectsMap();
274 : void RemoveDeadEntries();
275 :
276 : private:
277 : struct EntryInfo {
278 : EntryInfo(SnapshotObjectId id, Address addr, unsigned int size,
279 : bool accessed)
280 2963308 : : id(id), addr(addr), size(size), accessed(accessed) {}
281 : SnapshotObjectId id;
282 : Address addr;
283 : unsigned int size;
284 : bool accessed;
285 : };
286 :
287 : SnapshotObjectId next_id_;
288 : // TODO(jkummerow): Use a map that uses {Address} as the key type.
289 : base::HashMap entries_map_;
290 : std::vector<EntryInfo> entries_;
291 : std::vector<TimeInterval> time_intervals_;
292 : Heap* heap_;
293 :
294 : DISALLOW_COPY_AND_ASSIGN(HeapObjectsMap);
295 : };
296 :
297 : // A typedef for referencing anything that can be snapshotted living
298 : // in any kind of heap memory.
299 : typedef void* HeapThing;
300 :
301 : // An interface that creates HeapEntries by HeapThings.
302 1611 : class HeapEntriesAllocator {
303 : public:
304 1596 : virtual ~HeapEntriesAllocator() = default;
305 : virtual HeapEntry* AllocateEntry(HeapThing ptr) = 0;
306 : };
307 :
308 399 : class SnapshottingProgressReportingInterface {
309 : public:
310 399 : virtual ~SnapshottingProgressReportingInterface() = default;
311 : virtual void ProgressStep() = 0;
312 : virtual bool ProgressReport(bool force) = 0;
313 : };
314 :
315 : // An implementation of V8 heap graph extractor.
316 : class V8HeapExplorer : public HeapEntriesAllocator {
317 : public:
318 : V8HeapExplorer(HeapSnapshot* snapshot,
319 : SnapshottingProgressReportingInterface* progress,
320 : v8::HeapProfiler::ObjectNameResolver* resolver);
321 798 : ~V8HeapExplorer() override = default;
322 :
323 : HeapEntry* AllocateEntry(HeapThing ptr) override;
324 : int EstimateObjectsCount();
325 : bool IterateAndExtractReferences(HeapSnapshotGenerator* generator);
326 : void TagGlobalObjects();
327 : void TagBuiltinCodeObject(Code code, const char* name);
328 : HeapEntry* AddEntry(Address address,
329 : HeapEntry::Type type,
330 : const char* name,
331 : size_t size);
332 :
333 : static JSFunction GetConstructor(JSReceiver receiver);
334 : static String GetConstructorName(JSObject object);
335 :
336 : private:
337 : void MarkVisitedField(int offset);
338 :
339 : HeapEntry* AddEntry(HeapObject object);
340 : HeapEntry* AddEntry(HeapObject object, HeapEntry::Type type,
341 : const char* name);
342 :
343 : const char* GetSystemEntryName(HeapObject object);
344 :
345 : void ExtractLocation(HeapEntry* entry, HeapObject object);
346 : void ExtractLocationForJSFunction(HeapEntry* entry, JSFunction func);
347 : void ExtractReferences(HeapEntry* entry, HeapObject obj);
348 : void ExtractJSGlobalProxyReferences(HeapEntry* entry, JSGlobalProxy proxy);
349 : void ExtractJSObjectReferences(HeapEntry* entry, JSObject js_obj);
350 : void ExtractStringReferences(HeapEntry* entry, String obj);
351 : void ExtractSymbolReferences(HeapEntry* entry, Symbol symbol);
352 : void ExtractJSCollectionReferences(HeapEntry* entry, JSCollection collection);
353 : void ExtractJSWeakCollectionReferences(HeapEntry* entry,
354 : JSWeakCollection collection);
355 : void ExtractEphemeronHashTableReferences(HeapEntry* entry,
356 : EphemeronHashTable table);
357 : void ExtractContextReferences(HeapEntry* entry, Context context);
358 : void ExtractMapReferences(HeapEntry* entry, Map map);
359 : void ExtractSharedFunctionInfoReferences(HeapEntry* entry,
360 : SharedFunctionInfo shared);
361 : void ExtractScriptReferences(HeapEntry* entry, Script script);
362 : void ExtractAccessorInfoReferences(HeapEntry* entry,
363 : AccessorInfo accessor_info);
364 : void ExtractAccessorPairReferences(HeapEntry* entry, AccessorPair accessors);
365 : void ExtractCodeReferences(HeapEntry* entry, Code code);
366 : void ExtractCellReferences(HeapEntry* entry, Cell cell);
367 : void ExtractFeedbackCellReferences(HeapEntry* entry,
368 : FeedbackCell feedback_cell);
369 : void ExtractPropertyCellReferences(HeapEntry* entry, PropertyCell cell);
370 : void ExtractAllocationSiteReferences(HeapEntry* entry, AllocationSite site);
371 : void ExtractArrayBoilerplateDescriptionReferences(
372 : HeapEntry* entry, ArrayBoilerplateDescription value);
373 : void ExtractJSArrayBufferReferences(HeapEntry* entry, JSArrayBuffer buffer);
374 : void ExtractJSPromiseReferences(HeapEntry* entry, JSPromise promise);
375 : void ExtractJSGeneratorObjectReferences(HeapEntry* entry,
376 : JSGeneratorObject generator);
377 : void ExtractFixedArrayReferences(HeapEntry* entry, FixedArray array);
378 : void ExtractFeedbackVectorReferences(HeapEntry* entry,
379 : FeedbackVector feedback_vector);
380 : void ExtractDescriptorArrayReferences(HeapEntry* entry,
381 : DescriptorArray array);
382 : template <typename T>
383 : void ExtractWeakArrayReferences(int header_size, HeapEntry* entry, T array);
384 : void ExtractPropertyReferences(JSObject js_obj, HeapEntry* entry);
385 : void ExtractAccessorPairProperty(HeapEntry* entry, Name key,
386 : Object callback_obj, int field_offset = -1);
387 : void ExtractElementReferences(JSObject js_obj, HeapEntry* entry);
388 : void ExtractInternalReferences(JSObject js_obj, HeapEntry* entry);
389 :
390 : bool IsEssentialObject(Object object);
391 : bool IsEssentialHiddenReference(Object parent, int field_offset);
392 :
393 : void SetContextReference(HeapEntry* parent_entry, String reference_name,
394 : Object child, int field_offset);
395 : void SetNativeBindReference(HeapEntry* parent_entry,
396 : const char* reference_name, Object child);
397 : void SetElementReference(HeapEntry* parent_entry, int index, Object child);
398 : void SetInternalReference(HeapEntry* parent_entry, const char* reference_name,
399 : Object child, int field_offset = -1);
400 : void SetInternalReference(HeapEntry* parent_entry, int index, Object child,
401 : int field_offset = -1);
402 : void SetHiddenReference(HeapObject parent_obj, HeapEntry* parent_entry,
403 : int index, Object child, int field_offset);
404 : void SetWeakReference(HeapEntry* parent_entry, const char* reference_name,
405 : Object child_obj, int field_offset);
406 : void SetWeakReference(HeapEntry* parent_entry, int index, Object child_obj,
407 : int field_offset);
408 : void SetPropertyReference(HeapEntry* parent_entry, Name reference_name,
409 : Object child,
410 : const char* name_format_string = nullptr,
411 : int field_offset = -1);
412 : void SetDataOrAccessorPropertyReference(
413 : PropertyKind kind, HeapEntry* parent_entry, Name reference_name,
414 : Object child, const char* name_format_string = nullptr,
415 : int field_offset = -1);
416 :
417 : void SetUserGlobalReference(Object user_global);
418 : void SetRootGcRootsReference();
419 : void SetGcRootsReference(Root root);
420 : void SetGcSubrootReference(Root root, const char* description, bool is_weak,
421 : Object child);
422 : const char* GetStrongGcSubrootName(Object object);
423 : void TagObject(Object obj, const char* tag);
424 :
425 : HeapEntry* GetEntry(Object obj);
426 :
427 : Heap* heap_;
428 : HeapSnapshot* snapshot_;
429 : StringsStorage* names_;
430 : HeapObjectsMap* heap_object_map_;
431 : SnapshottingProgressReportingInterface* progress_;
432 : HeapSnapshotGenerator* generator_ = nullptr;
433 : std::unordered_map<JSGlobalObject, const char*, Object::Hasher> objects_tags_;
434 : std::unordered_map<Object, const char*, Object::Hasher>
435 : strong_gc_subroot_names_;
436 : std::unordered_set<JSGlobalObject, Object::Hasher> user_roots_;
437 : v8::HeapProfiler::ObjectNameResolver* global_object_name_resolver_;
438 :
439 : std::vector<bool> visited_fields_;
440 :
441 : friend class IndexedReferencesExtractor;
442 : friend class RootsReferencesExtractor;
443 :
444 : DISALLOW_COPY_AND_ASSIGN(V8HeapExplorer);
445 : };
446 :
447 :
448 : class NativeGroupRetainedObjectInfo;
449 :
450 :
451 : // An implementation of retained native objects extractor.
452 : class NativeObjectsExplorer {
453 : public:
454 : NativeObjectsExplorer(HeapSnapshot* snapshot,
455 : SnapshottingProgressReportingInterface* progress);
456 : virtual ~NativeObjectsExplorer();
457 : int EstimateObjectsCount();
458 : bool IterateAndExtractReferences(HeapSnapshotGenerator* generator);
459 :
460 : private:
461 : void FillRetainedObjects();
462 : void FillEdges();
463 : std::vector<HeapObject>* GetVectorMaybeDisposeInfo(
464 : v8::RetainedObjectInfo* info);
465 : void SetNativeRootReference(v8::RetainedObjectInfo* info);
466 : void SetRootNativeRootsReference();
467 : void SetWrapperNativeReferences(HeapObject wrapper,
468 : v8::RetainedObjectInfo* info);
469 : void VisitSubtreeWrapper(Handle<Object> p, uint16_t class_id);
470 :
471 : struct RetainedInfoHasher {
472 0 : std::size_t operator()(v8::RetainedObjectInfo* info) const {
473 0 : return ComputeUnseededHash(static_cast<uint32_t>(info->GetHash()));
474 : }
475 : };
476 : struct RetainedInfoEquals {
477 : bool operator()(v8::RetainedObjectInfo* info1,
478 : v8::RetainedObjectInfo* info2) const {
479 0 : return info1 == info2 || info1->IsEquivalent(info2);
480 : }
481 : };
482 :
483 : NativeGroupRetainedObjectInfo* FindOrAddGroupInfo(const char* label);
484 :
485 : HeapEntry* EntryForEmbedderGraphNode(EmbedderGraph::Node* node);
486 :
487 : Isolate* isolate_;
488 : HeapSnapshot* snapshot_;
489 : StringsStorage* names_;
490 : bool embedder_queried_;
491 : std::unordered_set<Object, Object::Hasher> in_groups_;
492 : std::unordered_map<v8::RetainedObjectInfo*, std::vector<HeapObject>*,
493 : RetainedInfoHasher, RetainedInfoEquals>
494 : objects_by_info_;
495 : std::unordered_map<const char*, NativeGroupRetainedObjectInfo*,
496 : SeededStringHasher, StringEquals>
497 : native_groups_;
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_;
501 : // Used during references extraction.
502 : HeapSnapshotGenerator* generator_ = nullptr;
503 : v8::HeapProfiler::RetainerEdges edges_;
504 :
505 : static HeapThing const kNativesRootObject;
506 :
507 : friend class GlobalHandlesExtractor;
508 :
509 : DISALLOW_COPY_AND_ASSIGN(NativeObjectsExplorer);
510 : };
511 :
512 1197 : class HeapSnapshotGenerator : public SnapshottingProgressReportingInterface {
513 : public:
514 : // The HeapEntriesMap instance is used to track a mapping between
515 : // real heap objects and their representations in heap snapshots.
516 : using HeapEntriesMap = std::unordered_map<HeapThing, HeapEntry*>;
517 :
518 : HeapSnapshotGenerator(HeapSnapshot* snapshot,
519 : v8::ActivityControl* control,
520 : v8::HeapProfiler::ObjectNameResolver* resolver,
521 : Heap* heap);
522 : bool GenerateSnapshot();
523 :
524 : HeapEntry* FindEntry(HeapThing ptr) {
525 : auto it = entries_map_.find(ptr);
526 22324209 : return it != entries_map_.end() ? it->second : nullptr;
527 : }
528 :
529 3080696 : HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
530 6161392 : return entries_map_.emplace(ptr, allocator->AllocateEntry(ptr))
531 6161392 : .first->second;
532 : }
533 :
534 22324134 : HeapEntry* FindOrAddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
535 : HeapEntry* entry = FindEntry(ptr);
536 22324134 : return entry != nullptr ? entry : AddEntry(ptr, allocator);
537 : }
538 :
539 : private:
540 : bool FillReferences();
541 : void ProgressStep() override;
542 : bool ProgressReport(bool force = false) override;
543 : void InitProgressCounter();
544 :
545 : HeapSnapshot* snapshot_;
546 : v8::ActivityControl* control_;
547 : V8HeapExplorer v8_heap_explorer_;
548 : NativeObjectsExplorer dom_explorer_;
549 : // Mapping from HeapThing pointers to HeapEntry indices.
550 : HeapEntriesMap entries_map_;
551 : // Used during snapshot generation.
552 : int progress_counter_;
553 : int progress_total_;
554 : Heap* heap_;
555 :
556 : DISALLOW_COPY_AND_ASSIGN(HeapSnapshotGenerator);
557 : };
558 :
559 : class OutputStreamWriter;
560 :
561 : class HeapSnapshotJSONSerializer {
562 : public:
563 : explicit HeapSnapshotJSONSerializer(HeapSnapshot* snapshot)
564 : : snapshot_(snapshot),
565 : strings_(StringsMatch),
566 : next_node_id_(1),
567 : next_string_id_(1),
568 70 : writer_(nullptr) {}
569 : void Serialize(v8::OutputStream* stream);
570 :
571 : private:
572 695801 : V8_INLINE static bool StringsMatch(void* key1, void* key2) {
573 : return strcmp(reinterpret_cast<char*>(key1),
574 695801 : reinterpret_cast<char*>(key2)) == 0;
575 : }
576 :
577 : V8_INLINE static uint32_t StringHash(const void* string);
578 :
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);
582 : void SerializeEdge(HeapGraphEdge* edge, bool first_edge);
583 : void SerializeEdges();
584 : void SerializeImpl();
585 : void SerializeNode(const HeapEntry* entry);
586 : void SerializeNodes();
587 : void SerializeSnapshot();
588 : void SerializeTraceTree();
589 : void SerializeTraceNode(AllocationTraceNode* node);
590 : void SerializeTraceNodeInfos();
591 : void SerializeSamples();
592 : void SerializeString(const unsigned char* s);
593 : void SerializeStrings();
594 : void SerializeLocation(const SourceLocation& location);
595 : void SerializeLocations();
596 :
597 : static const int kEdgeFieldsCount;
598 : static const int kNodeFieldsCount;
599 :
600 : HeapSnapshot* snapshot_;
601 : base::CustomMatcherHashMap strings_;
602 : int next_node_id_;
603 : int next_string_id_;
604 : OutputStreamWriter* writer_;
605 :
606 : friend class HeapSnapshotJSONSerializerEnumerator;
607 : friend class HeapSnapshotJSONSerializerIterator;
608 :
609 : DISALLOW_COPY_AND_ASSIGN(HeapSnapshotJSONSerializer);
610 : };
611 :
612 :
613 : } // namespace internal
614 : } // namespace v8
615 :
616 : #endif // V8_PROFILER_HEAP_SNAPSHOT_GENERATOR_H_
|