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