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