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