1b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Copyright 2009-2010 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h"
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "heap-profiler.h"
313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "frames-inl.h"
323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#include "global-handles.h"
339dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen#include "profile-generator.h"
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "string-stream.h"
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_LOGGING_AND_PROFILING
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace {
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Clusterizer is a set of helper functions for converting
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// object references into clusters.
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Clusterizer : public AllStatic {
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static JSObjectsCluster Clusterize(HeapObject* obj) {
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return Clusterize(obj, true);
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void InsertIntoTree(JSObjectsClusterTree* tree,
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                             HeapObject* obj, bool fine_grain);
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void InsertReferenceIntoTree(JSObjectsClusterTree* tree,
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      const JSObjectsCluster& cluster) {
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    InsertIntoTree(tree, cluster, 0);
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static JSObjectsCluster Clusterize(HeapObject* obj, bool fine_grain);
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static int CalculateNetworkSize(JSObject* obj);
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static int GetObjectSize(HeapObject* obj) {
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return obj->IsJSObject() ?
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        CalculateNetworkSize(JSObject::cast(obj)) : obj->Size();
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void InsertIntoTree(JSObjectsClusterTree* tree,
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                             const JSObjectsCluster& cluster, int size);
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockJSObjectsCluster Clusterizer::Clusterize(HeapObject* obj, bool fine_grain) {
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (obj->IsJSObject()) {
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    JSObject* js_obj = JSObject::cast(obj);
728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    String* constructor = GetConstructorNameForHeapProfile(
738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        JSObject::cast(js_obj));
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Differentiate Object and Array instances.
7544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (fine_grain && (constructor == HEAP->Object_symbol() ||
7644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                       constructor == HEAP->Array_symbol())) {
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return JSObjectsCluster(constructor, obj);
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return JSObjectsCluster(constructor);
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (obj->IsString()) {
8244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return JSObjectsCluster(HEAP->String_symbol());
83d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (obj->IsJSGlobalPropertyCell()) {
84d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    return JSObjectsCluster(JSObjectsCluster::GLOBAL_PROPERTY);
85d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (obj->IsCode() || obj->IsSharedFunctionInfo() || obj->IsScript()) {
86d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    return JSObjectsCluster(JSObjectsCluster::CODE);
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return JSObjectsCluster();
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Clusterizer::InsertIntoTree(JSObjectsClusterTree* tree,
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 HeapObject* obj, bool fine_grain) {
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  JSObjectsCluster cluster = Clusterize(obj, fine_grain);
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (cluster.is_null()) return;
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  InsertIntoTree(tree, cluster, GetObjectSize(obj));
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Clusterizer::InsertIntoTree(JSObjectsClusterTree* tree,
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 const JSObjectsCluster& cluster, int size) {
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  JSObjectsClusterTree::Locator loc;
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  tree->Insert(cluster, &loc);
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  NumberAndSizeInfo number_and_size = loc.value();
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  number_and_size.increment_number(1);
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  number_and_size.increment_bytes(size);
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  loc.set_value(number_and_size);
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Clusterizer::CalculateNetworkSize(JSObject* obj) {
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int size = obj->Size();
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If 'properties' and 'elements' are non-empty (thus, non-shared),
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // take their size into account.
11544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (obj->properties() != HEAP->empty_fixed_array()) {
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    size += obj->properties()->Size();
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
11844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (obj->elements() != HEAP->empty_fixed_array()) {
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    size += obj->elements()->Size();
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
121d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // For functions, also account non-empty context and literals sizes.
122d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (obj->IsJSFunction()) {
123d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    JSFunction* f = JSFunction::cast(obj);
124d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (f->unchecked_context()->IsContext()) {
125d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      size += f->context()->Size();
126d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
127d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (f->literals()->length() != 0) {
128d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      size += f->literals()->Size();
129d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    }
130d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  }
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return size;
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A helper class for recording back references.
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass ReferencesExtractor : public ObjectVisitor {
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ReferencesExtractor(const JSObjectsCluster& cluster,
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      RetainerHeapProfile* profile)
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      : cluster_(cluster),
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        profile_(profile),
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        inside_array_(false) {
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void VisitPointer(Object** o) {
146d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if ((*o)->IsFixedArray() && !inside_array_) {
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // Traverse one level deep for data members that are fixed arrays.
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // This covers the case of 'elements' and 'properties' of JSObject,
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // and function contexts.
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      inside_array_ = true;
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      FixedArray::cast(*o)->Iterate(this);
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      inside_array_ = false;
153d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    } else if ((*o)->IsHeapObject()) {
154d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      profile_->StoreReference(cluster_, HeapObject::cast(*o));
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void VisitPointers(Object** start, Object** end) {
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (Object** p = start; p < end; p++) VisitPointer(p);
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const JSObjectsCluster& cluster_;
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RetainerHeapProfile* profile_;
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool inside_array_;
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A printer interface implementation for the Retainers profile.
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass RetainersPrinter : public RetainerHeapProfile::Printer {
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void PrintRetainers(const JSObjectsCluster& cluster,
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      const StringStream& retainers) {
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    HeapStringAllocator allocator;
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    StringStream stream(&allocator);
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    cluster.Print(&stream);
17744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    LOG(ISOLATE,
17844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        HeapSampleJSRetainersEvent(
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        *(stream.ToCString()), *(retainers.ToCString())));
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Visitor for printing a cluster tree.
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass ClusterTreePrinter BASE_EMBEDDED {
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit ClusterTreePrinter(StringStream* stream) : stream_(stream) {}
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Call(const JSObjectsCluster& cluster,
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            const NumberAndSizeInfo& number_and_size) {
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Print(stream_, cluster, number_and_size);
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void Print(StringStream* stream,
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    const JSObjectsCluster& cluster,
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    const NumberAndSizeInfo& number_and_size);
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StringStream* stream_;
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ClusterTreePrinter::Print(StringStream* stream,
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               const JSObjectsCluster& cluster,
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               const NumberAndSizeInfo& number_and_size) {
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  stream->Put(',');
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cluster.Print(stream);
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  stream->Add(";%d", number_and_size.number());
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Visitor for printing a retainer tree.
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass SimpleRetainerTreePrinter BASE_EMBEDDED {
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit SimpleRetainerTreePrinter(RetainerHeapProfile::Printer* printer)
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      : printer_(printer) {}
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Call(const JSObjectsCluster& cluster, JSObjectsClusterTree* tree);
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RetainerHeapProfile::Printer* printer_;
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid SimpleRetainerTreePrinter::Call(const JSObjectsCluster& cluster,
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     JSObjectsClusterTree* tree) {
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  HeapStringAllocator allocator;
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StringStream stream(&allocator);
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ClusterTreePrinter retainers_printer(&stream);
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  tree->ForEach(&retainers_printer);
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  printer_->PrintRetainers(cluster, stream);
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Visitor for aggregating references count of equivalent clusters.
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass RetainersAggregator BASE_EMBEDDED {
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RetainersAggregator(ClustersCoarser* coarser, JSObjectsClusterTree* dest_tree)
236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      : coarser_(coarser), dest_tree_(dest_tree) {}
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Call(const JSObjectsCluster& cluster,
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            const NumberAndSizeInfo& number_and_size);
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ClustersCoarser* coarser_;
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  JSObjectsClusterTree* dest_tree_;
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RetainersAggregator::Call(const JSObjectsCluster& cluster,
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               const NumberAndSizeInfo& number_and_size) {
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  JSObjectsCluster eq = coarser_->GetCoarseEquivalent(cluster);
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (eq.is_null()) eq = cluster;
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  JSObjectsClusterTree::Locator loc;
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  dest_tree_->Insert(eq, &loc);
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  NumberAndSizeInfo aggregated_number = loc.value();
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  aggregated_number.increment_number(number_and_size.number());
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  loc.set_value(aggregated_number);
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Visitor for printing retainers tree. Aggregates equivalent retainer clusters.
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass AggregatingRetainerTreePrinter BASE_EMBEDDED {
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AggregatingRetainerTreePrinter(ClustersCoarser* coarser,
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 RetainerHeapProfile::Printer* printer)
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      : coarser_(coarser), printer_(printer) {}
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Call(const JSObjectsCluster& cluster, JSObjectsClusterTree* tree);
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ClustersCoarser* coarser_;
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RetainerHeapProfile::Printer* printer_;
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid AggregatingRetainerTreePrinter::Call(const JSObjectsCluster& cluster,
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                          JSObjectsClusterTree* tree) {
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!coarser_->GetCoarseEquivalent(cluster).is_null()) return;
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  JSObjectsClusterTree dest_tree_;
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RetainersAggregator retainers_aggregator(coarser_, &dest_tree_);
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  tree->ForEach(&retainers_aggregator);
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  HeapStringAllocator allocator;
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StringStream stream(&allocator);
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ClusterTreePrinter retainers_printer(&stream);
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  dest_tree_.ForEach(&retainers_printer);
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  printer_->PrintRetainers(cluster, stream);
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
285791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block}  // namespace
286791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A helper class for building a retainers tree, that aggregates
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// all equivalent clusters.
290791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockclass RetainerTreeAggregator {
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit RetainerTreeAggregator(ClustersCoarser* coarser)
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      : coarser_(coarser) {}
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Process(JSObjectsRetainerTree* input_tree) {
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    input_tree->ForEach(this);
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Call(const JSObjectsCluster& cluster, JSObjectsClusterTree* tree);
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  JSObjectsRetainerTree& output_tree() { return output_tree_; }
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ClustersCoarser* coarser_;
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  JSObjectsRetainerTree output_tree_;
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RetainerTreeAggregator::Call(const JSObjectsCluster& cluster,
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  JSObjectsClusterTree* tree) {
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  JSObjectsCluster eq = coarser_->GetCoarseEquivalent(cluster);
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (eq.is_null()) return;
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  JSObjectsRetainerTree::Locator loc;
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (output_tree_.Insert(eq, &loc)) {
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    loc.set_value(new JSObjectsClusterTree());
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RetainersAggregator retainers_aggregator(coarser_, loc.value());
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  tree->ForEach(&retainers_aggregator);
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3199dcf7e2f83591d471e88bf7d230651900b8e424bKristian MonsenHeapProfiler::HeapProfiler()
3209dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    : snapshots_(new HeapSnapshotsCollection()),
3219dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      next_snapshot_uid_(1) {
3229dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
3239dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
3249dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
3259dcf7e2f83591d471e88bf7d230651900b8e424bKristian MonsenHeapProfiler::~HeapProfiler() {
3269dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  delete snapshots_;
3279dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
3289dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
32944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
33044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid HeapProfiler::ResetSnapshots() {
33144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  delete snapshots_;
33244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  snapshots_ = new HeapSnapshotsCollection();
33344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
33444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
33544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
3369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen#endif  // ENABLE_LOGGING_AND_PROFILING
3379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
3389dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid HeapProfiler::Setup() {
3399dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen#ifdef ENABLE_LOGGING_AND_PROFILING
34044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate = Isolate::Current();
34144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (isolate->heap_profiler() == NULL) {
34244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    isolate->set_heap_profiler(new HeapProfiler());
3439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
3449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen#endif
3459dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
3469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
3479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
3489dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenvoid HeapProfiler::TearDown() {
3499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen#ifdef ENABLE_LOGGING_AND_PROFILING
35044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate = Isolate::Current();
35144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  delete isolate->heap_profiler();
35244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate->set_heap_profiler(NULL);
3539dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen#endif
3549dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
3559dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
3569dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
3579dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen#ifdef ENABLE_LOGGING_AND_PROFILING
3589dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHeapSnapshot* HeapProfiler::TakeSnapshot(const char* name,
360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                         int type,
361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                         v8::ActivityControl* control) {
36244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(Isolate::Current()->heap_profiler() != NULL);
36344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return Isolate::Current()->heap_profiler()->TakeSnapshotImpl(name,
36444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                               type,
36544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                               control);
3669dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
3679dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
3689dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHeapSnapshot* HeapProfiler::TakeSnapshot(String* name,
370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                         int type,
371b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                         v8::ActivityControl* control) {
37244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(Isolate::Current()->heap_profiler() != NULL);
37344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return Isolate::Current()->heap_profiler()->TakeSnapshotImpl(name,
37444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                               type,
37544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                                               control);
37644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
37744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
37844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
37944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid HeapProfiler::DefineWrapperClass(
38044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    uint16_t class_id, v8::HeapProfiler::WrapperInfoCallback callback) {
38144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(class_id != v8::HeapProfiler::kPersistentHandleNoClassId);
38244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (wrapper_callbacks_.length() <= class_id) {
38344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    wrapper_callbacks_.AddBlock(
38444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        NULL, class_id - wrapper_callbacks_.length() + 1);
38544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
38644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  wrapper_callbacks_[class_id] = callback;
38744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
38844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
38944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
39044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockv8::RetainedObjectInfo* HeapProfiler::ExecuteWrapperClassCallback(
39144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    uint16_t class_id, Object** wrapper) {
39244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (wrapper_callbacks_.length() <= class_id) return NULL;
39344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return wrapper_callbacks_[class_id](
39444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      class_id, Utils::ToLocal(Handle<Object>(wrapper)));
3959dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
3969dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
3979dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHeapSnapshot* HeapProfiler::TakeSnapshotImpl(const char* name,
399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                             int type,
400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                             v8::ActivityControl* control) {
401791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  HeapSnapshot::Type s_type = static_cast<HeapSnapshot::Type>(type);
402791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  HeapSnapshot* result =
403791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      snapshots_->NewSnapshot(s_type, name, next_snapshot_uid_++);
404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool generation_completed = true;
405791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  switch (s_type) {
406791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    case HeapSnapshot::kFull: {
40744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      HEAP->CollectAllGarbage(true);
408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      HeapSnapshotGenerator generator(result, control);
409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      generation_completed = generator.GenerateSnapshot();
410791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      break;
411791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    }
412791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    case HeapSnapshot::kAggregated: {
41344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      HEAP->CollectAllGarbage(true);
414791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      AggregatedHeapSnapshot agg_snapshot;
415791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      AggregatedHeapSnapshotGenerator generator(&agg_snapshot);
416791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      generator.GenerateSnapshot();
417791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      generator.FillHeapSnapshot(result);
418791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      break;
419791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    }
420791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    default:
421791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      UNREACHABLE();
422791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  }
423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!generation_completed) {
424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    delete result;
425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    result = NULL;
426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  snapshots_->SnapshotGenerationFinished(result);
4289dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  return result;
4299dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
4309dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
4319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHeapSnapshot* HeapProfiler::TakeSnapshotImpl(String* name,
433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                             int type,
434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                             v8::ActivityControl* control) {
43544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return TakeSnapshotImpl(snapshots_->names()->GetName(name), type, control);
4369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
4379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
4389dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
4399dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenint HeapProfiler::GetSnapshotsCount() {
44044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HeapProfiler* profiler = Isolate::Current()->heap_profiler();
44144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(profiler != NULL);
44244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return profiler->snapshots_->snapshots()->length();
4439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
4449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
4459dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
4469dcf7e2f83591d471e88bf7d230651900b8e424bKristian MonsenHeapSnapshot* HeapProfiler::GetSnapshot(int index) {
44744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HeapProfiler* profiler = Isolate::Current()->heap_profiler();
44844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(profiler != NULL);
44944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return profiler->snapshots_->snapshots()->at(index);
4509dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
4519dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
4529dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
4539dcf7e2f83591d471e88bf7d230651900b8e424bKristian MonsenHeapSnapshot* HeapProfiler::FindSnapshot(unsigned uid) {
45444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HeapProfiler* profiler = Isolate::Current()->heap_profiler();
45544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(profiler != NULL);
45644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return profiler->snapshots_->GetSnapshot(uid);
45744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
45844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
45944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
46044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid HeapProfiler::DeleteAllSnapshots() {
46144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HeapProfiler* profiler = Isolate::Current()->heap_profiler();
46244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(profiler != NULL);
46344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  profiler->ResetSnapshots();
4649dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
4659dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
4669dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
4673bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochvoid HeapProfiler::ObjectMoveEvent(Address from, Address to) {
46844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  snapshots_->ObjectMoveEvent(from, to);
4693bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
4703bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
4713bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst JSObjectsClusterTreeConfig::Key JSObjectsClusterTreeConfig::kNoKey;
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst JSObjectsClusterTreeConfig::Value JSObjectsClusterTreeConfig::kNoValue;
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockConstructorHeapProfile::ConstructorHeapProfile()
477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    : zscope_(DELETE_ON_EXIT) {
478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ConstructorHeapProfile::Call(const JSObjectsCluster& cluster,
482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  const NumberAndSizeInfo& number_and_size) {
483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  HeapStringAllocator allocator;
484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StringStream stream(&allocator);
485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cluster.Print(&stream);
48644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LOG(ISOLATE,
48744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      HeapSampleJSConstructorEvent(*(stream.ToCString()),
488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   number_and_size.number(),
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   number_and_size.bytes()));
490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ConstructorHeapProfile::CollectStats(HeapObject* obj) {
494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Clusterizer::InsertIntoTree(&js_objects_info_tree_, obj, false);
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ConstructorHeapProfile::PrintStats() {
499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  js_objects_info_tree_.ForEach(this);
500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockstatic const char* GetConstructorName(const char* name) {
5043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  return name[0] != '\0' ? name : "(anonymous)";
5053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
5063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
5073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
508791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockconst char* JSObjectsCluster::GetSpecialCaseName() const {
509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (constructor_ == FromSpecialCase(ROOTS)) {
510791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    return "(roots)";
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (constructor_ == FromSpecialCase(GLOBAL_PROPERTY)) {
512791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    return "(global property)";
513d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  } else if (constructor_ == FromSpecialCase(CODE)) {
514791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    return "(code)";
515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (constructor_ == FromSpecialCase(SELF)) {
516791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    return "(self)";
517791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  }
518791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  return NULL;
519791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block}
520791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
521791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
522791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockvoid JSObjectsCluster::Print(StringStream* accumulator) const {
523791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  ASSERT(!is_null());
524791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  const char* special_case_name = GetSpecialCaseName();
525791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  if (special_case_name != NULL) {
526791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    accumulator->Add(special_case_name);
527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SmartPointer<char> s_name(
529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        constructor_->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL));
5303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    accumulator->Add("%s", GetConstructorName(*s_name));
531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (instance_ != NULL) {
532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      accumulator->Add(":%p", static_cast<void*>(instance_));
533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid JSObjectsCluster::DebugPrint(StringStream* accumulator) const {
539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!is_null()) {
540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Print(accumulator);
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    accumulator->Add("(null cluster)");
543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockinline ClustersCoarser::ClusterBackRefs::ClusterBackRefs(
548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const JSObjectsCluster& cluster_)
549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    : cluster(cluster_), refs(kInitialBackrefsListCapacity) {
550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockinline ClustersCoarser::ClusterBackRefs::ClusterBackRefs(
554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const ClustersCoarser::ClusterBackRefs& src)
555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    : cluster(src.cluster), refs(src.refs.capacity()) {
556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  refs.AddAll(src.refs);
557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockinline ClustersCoarser::ClusterBackRefs&
561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ClustersCoarser::ClusterBackRefs::operator=(
562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const ClustersCoarser::ClusterBackRefs& src) {
563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (this == &src) return *this;
564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cluster = src.cluster;
565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  refs.Clear();
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  refs.AddAll(src.refs);
567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return *this;
568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockinline int ClustersCoarser::ClusterBackRefs::Compare(
572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const ClustersCoarser::ClusterBackRefs& a,
573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const ClustersCoarser::ClusterBackRefs& b) {
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int cmp = JSObjectsCluster::CompareConstructors(a.cluster, b.cluster);
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (cmp != 0) return cmp;
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (a.refs.length() < b.refs.length()) return -1;
577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (a.refs.length() > b.refs.length()) return 1;
578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < a.refs.length(); ++i) {
579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int cmp = JSObjectsCluster::Compare(a.refs[i], b.refs[i]);
580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (cmp != 0) return cmp;
581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return 0;
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockClustersCoarser::ClustersCoarser()
587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    : zscope_(DELETE_ON_EXIT),
588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      sim_list_(ClustersCoarser::kInitialSimilarityListCapacity),
589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      current_pair_(NULL),
590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      current_set_(NULL),
591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      self_(NULL) {
592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ClustersCoarser::Call(const JSObjectsCluster& cluster,
596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                           JSObjectsClusterTree* tree) {
597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!cluster.can_be_coarsed()) return;
598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ClusterBackRefs pair(cluster);
599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(current_pair_ == NULL);
600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  current_pair_ = &pair;
601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  current_set_ = new JSObjectsRetainerTree();
602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  self_ = &cluster;
603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  tree->ForEach(this);
604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  sim_list_.Add(pair);
605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  current_pair_ = NULL;
606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  current_set_ = NULL;
607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  self_ = NULL;
608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ClustersCoarser::Call(const JSObjectsCluster& cluster,
612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                           const NumberAndSizeInfo& number_and_size) {
613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(current_pair_ != NULL);
614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(current_set_ != NULL);
615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(self_ != NULL);
616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  JSObjectsRetainerTree::Locator loc;
617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (JSObjectsCluster::Compare(*self_, cluster) == 0) {
618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    current_pair_->refs.Add(JSObjectsCluster(JSObjectsCluster::SELF));
619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  JSObjectsCluster eq = GetCoarseEquivalent(cluster);
622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!eq.is_null()) {
623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (current_set_->Find(eq, &loc)) return;
624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    current_pair_->refs.Add(eq);
625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    current_set_->Insert(eq, &loc);
626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    current_pair_->refs.Add(cluster);
628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ClustersCoarser::Process(JSObjectsRetainerTree* tree) {
633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int last_eq_clusters = -1;
634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < kMaxPassesCount; ++i) {
635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    sim_list_.Clear();
636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const int curr_eq_clusters = DoProcess(tree);
637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // If no new cluster equivalents discovered, abort processing.
638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (last_eq_clusters == curr_eq_clusters) break;
639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    last_eq_clusters = curr_eq_clusters;
640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint ClustersCoarser::DoProcess(JSObjectsRetainerTree* tree) {
645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  tree->ForEach(this);
646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  sim_list_.Iterate(ClusterBackRefs::SortRefsIterator);
647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  sim_list_.Sort(ClusterBackRefsCmp);
648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return FillEqualityTree();
649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockJSObjectsCluster ClustersCoarser::GetCoarseEquivalent(
653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const JSObjectsCluster& cluster) {
654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!cluster.can_be_coarsed()) return JSObjectsCluster();
655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  EqualityTree::Locator loc;
656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return eq_tree_.Find(cluster, &loc) ? loc.value() : JSObjectsCluster();
657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool ClustersCoarser::HasAnEquivalent(const JSObjectsCluster& cluster) {
661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return true for coarsible clusters that have a non-identical equivalent.
662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!cluster.can_be_coarsed()) return false;
663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  JSObjectsCluster eq = GetCoarseEquivalent(cluster);
664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return !eq.is_null() && JSObjectsCluster::Compare(cluster, eq) != 0;
665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint ClustersCoarser::FillEqualityTree() {
669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int eq_clusters_count = 0;
670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int eq_to = 0;
671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool first_added = false;
672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 1; i < sim_list_.length(); ++i) {
673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (ClusterBackRefs::Compare(sim_list_[i], sim_list_[eq_to]) == 0) {
674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      EqualityTree::Locator loc;
675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (!first_added) {
676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Add self-equivalence, if we have more than one item in this
677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // equivalence class.
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        eq_tree_.Insert(sim_list_[eq_to].cluster, &loc);
679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        loc.set_value(sim_list_[eq_to].cluster);
680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        first_added = true;
681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      eq_tree_.Insert(sim_list_[i].cluster, &loc);
683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      loc.set_value(sim_list_[eq_to].cluster);
684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ++eq_clusters_count;
685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      eq_to = i;
687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      first_added = false;
688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return eq_clusters_count;
691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst JSObjectsCluster ClustersCoarser::ClusterEqualityConfig::kNoKey;
695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst JSObjectsCluster ClustersCoarser::ClusterEqualityConfig::kNoValue;
696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst JSObjectsRetainerTreeConfig::Key JSObjectsRetainerTreeConfig::kNoKey;
697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst JSObjectsRetainerTreeConfig::Value JSObjectsRetainerTreeConfig::kNoValue =
698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    NULL;
699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRetainerHeapProfile::RetainerHeapProfile()
702791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    : zscope_(DELETE_ON_EXIT),
703791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      aggregator_(NULL) {
704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  JSObjectsCluster roots(JSObjectsCluster::ROOTS);
705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ReferencesExtractor extractor(roots, this);
70644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEAP->IterateRoots(&extractor, VISIT_ONLY_STRONG);
707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
710791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve BlockRetainerHeapProfile::~RetainerHeapProfile() {
711791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  delete aggregator_;
712791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block}
713791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
714791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RetainerHeapProfile::StoreReference(const JSObjectsCluster& cluster,
716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                         HeapObject* ref) {
717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  JSObjectsCluster ref_cluster = Clusterizer::Clusterize(ref);
718d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (ref_cluster.is_null()) return;
719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  JSObjectsRetainerTree::Locator ref_loc;
720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (retainers_tree_.Insert(ref_cluster, &ref_loc)) {
721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ref_loc.set_value(new JSObjectsClusterTree());
722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  JSObjectsClusterTree* referenced_by = ref_loc.value();
724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Clusterizer::InsertReferenceIntoTree(referenced_by, cluster);
725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RetainerHeapProfile::CollectStats(HeapObject* obj) {
729d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  const JSObjectsCluster cluster = Clusterizer::Clusterize(obj);
730d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  if (cluster.is_null()) return;
731d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  ReferencesExtractor extractor(cluster, this);
732d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  obj->Iterate(&extractor);
733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
736791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockvoid RetainerHeapProfile::CoarseAndAggregate() {
737791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  coarser_.Process(&retainers_tree_);
738791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  ASSERT(aggregator_ == NULL);
739791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  aggregator_ = new RetainerTreeAggregator(&coarser_);
740791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  aggregator_->Process(&retainers_tree_);
741791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block}
742791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
743791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RetainerHeapProfile::DebugPrintStats(
745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RetainerHeapProfile::Printer* printer) {
746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Print clusters that have no equivalents, aggregating their retainers.
747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AggregatingRetainerTreePrinter agg_printer(&coarser_, printer);
748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  retainers_tree_.ForEach(&agg_printer);
749791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  // Print clusters that have equivalents.
750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SimpleRetainerTreePrinter s_printer(printer);
751791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  aggregator_->output_tree().ForEach(&s_printer);
752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RetainerHeapProfile::PrintStats() {
756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RetainersPrinter printer;
757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DebugPrintStats(&printer);
758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// HeapProfiler class implementation.
763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
7643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockstatic void StackWeakReferenceCallback(Persistent<Value> object,
7653ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                       void* trace) {
7663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  DeleteArray(static_cast<Address*>(trace));
7673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  object.Dispose();
7683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
7693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
7713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockstatic void PrintProducerStackTrace(Object* obj, void* trace) {
7723ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (!obj->IsJSObject()) return;
7738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  String* constructor = GetConstructorNameForHeapProfile(JSObject::cast(obj));
7743ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SmartPointer<char> s_name(
7753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      constructor->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL));
77644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LOG(ISOLATE,
77744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      HeapSampleJSProducerEvent(GetConstructorName(*s_name),
7783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                                reinterpret_cast<Address*>(trace)));
779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid HeapProfiler::WriteSample() {
78344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate = Isolate::Current();
78444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LOG(isolate, HeapSampleBeginEvent("Heap", "allocated"));
78544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LOG(isolate,
78644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      HeapSampleStats(
78744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          "Heap", "allocated", HEAP->CommittedMemory(), HEAP->SizeOfObjects()));
788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
789791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  AggregatedHeapSnapshot snapshot;
790791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  AggregatedHeapSnapshotGenerator generator(&snapshot);
791791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  generator.GenerateSnapshot();
792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
793791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  HistogramInfo* info = snapshot.info();
794791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  for (int i = FIRST_NONSTRING_TYPE;
795791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block       i <= AggregatedHeapSnapshotGenerator::kAllStringsType;
796791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block       ++i) {
797791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    if (info[i].bytes() > 0) {
79844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      LOG(isolate,
79944f0eee88ff00398ff7f715fab053374d808c90dSteve Block          HeapSampleItemEvent(info[i].name(), info[i].number(),
800791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                              info[i].bytes()));
801791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    }
802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
804791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  snapshot.js_cons_profile()->PrintStats();
805791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  snapshot.js_retainer_profile()->PrintStats();
806791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
80744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate->global_handles()->IterateWeakRoots(PrintProducerStackTrace,
80844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                              StackWeakReferenceCallback);
809791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
81044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LOG(isolate, HeapSampleEndEvent("Heap", "allocated"));
811791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block}
812791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
813791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
814791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve BlockAggregatedHeapSnapshot::AggregatedHeapSnapshot()
815791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    : info_(NewArray<HistogramInfo>(
816791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block        AggregatedHeapSnapshotGenerator::kAllStringsType + 1)) {
817791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block#define DEF_TYPE_NAME(name) info_[name].set_name(#name);
818791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  INSTANCE_TYPE_LIST(DEF_TYPE_NAME);
819791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block#undef DEF_TYPE_NAME
820791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  info_[AggregatedHeapSnapshotGenerator::kAllStringsType].set_name(
821791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      "STRING_TYPE");
822791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block}
823791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
824791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
825791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve BlockAggregatedHeapSnapshot::~AggregatedHeapSnapshot() {
826791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  DeleteArray(info_);
827791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block}
828791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
829791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
830791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve BlockAggregatedHeapSnapshotGenerator::AggregatedHeapSnapshotGenerator(
831791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    AggregatedHeapSnapshot* agg_snapshot)
832791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    : agg_snapshot_(agg_snapshot) {
833791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block}
834791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
835791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
836791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockvoid AggregatedHeapSnapshotGenerator::CalculateStringsStats() {
837791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  HistogramInfo* info = agg_snapshot_->info();
838791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  HistogramInfo& strings = info[kAllStringsType];
839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Lump all the string types together.
840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define INCREMENT_SIZE(type, size, name, camel_name)   \
841791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  strings.increment_number(info[type].number());       \
842791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  strings.increment_bytes(info[type].bytes());
843791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  STRING_TYPE_LIST(INCREMENT_SIZE);
844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef INCREMENT_SIZE
845791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block}
846791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
847791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
848791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockvoid AggregatedHeapSnapshotGenerator::CollectStats(HeapObject* obj) {
849791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  InstanceType type = obj->map()->instance_type();
850791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  ASSERT(0 <= type && type <= LAST_TYPE);
8518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  agg_snapshot_->info()[type].increment_number(1);
8528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  agg_snapshot_->info()[type].increment_bytes(obj->Size());
853791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block}
854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
855791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
856791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockvoid AggregatedHeapSnapshotGenerator::GenerateSnapshot() {
8571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  HeapIterator iterator(HeapIterator::kFilterUnreachable);
858791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
859791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    CollectStats(obj);
860791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    agg_snapshot_->js_cons_profile()->CollectStats(obj);
861791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    agg_snapshot_->js_retainer_profile()->CollectStats(obj);
862791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  }
863791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  CalculateStringsStats();
864791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  agg_snapshot_->js_retainer_profile()->CoarseAndAggregate();
865791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block}
866791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
867791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
868791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockclass CountingConstructorHeapProfileIterator {
869791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block public:
870791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  CountingConstructorHeapProfileIterator()
871791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      : entities_count_(0), children_count_(0) {
872791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  }
873791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
874791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  void Call(const JSObjectsCluster& cluster,
875791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block            const NumberAndSizeInfo& number_and_size) {
876791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    ++entities_count_;
877791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    children_count_ += number_and_size.number();
878791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  }
879791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
880791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  int entities_count() { return entities_count_; }
881791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  int children_count() { return children_count_; }
882791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
883791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block private:
884791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  int entities_count_;
885791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  int children_count_;
886791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block};
887791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
888791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
889791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockstatic HeapEntry* AddEntryFromAggregatedSnapshot(HeapSnapshot* snapshot,
890791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                                                 int* root_child_index,
891791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                                                 HeapEntry::Type type,
892791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                                                 const char* name,
893791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                                                 int count,
894791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                                                 int size,
895791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                                                 int children_count,
896791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                                                 int retainers_count) {
897791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  HeapEntry* entry = snapshot->AddEntry(
898791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      type, name, count, size, children_count, retainers_count);
899791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  ASSERT(entry != NULL);
900791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  snapshot->root()->SetUnidirElementReference(*root_child_index,
901791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                                              *root_child_index + 1,
902791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                                              entry);
903791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  *root_child_index = *root_child_index + 1;
904791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  return entry;
905791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block}
906791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
907791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
908791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockclass AllocatingConstructorHeapProfileIterator {
909791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block public:
910791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  AllocatingConstructorHeapProfileIterator(HeapSnapshot* snapshot,
911791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                                  int* root_child_index)
912791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      : snapshot_(snapshot),
913791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block        root_child_index_(root_child_index) {
914791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  }
915791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
916791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  void Call(const JSObjectsCluster& cluster,
917791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block            const NumberAndSizeInfo& number_and_size) {
918791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    const char* name = cluster.GetSpecialCaseName();
919791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    if (name == NULL) {
92044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      name = snapshot_->collection()->names()->GetFunctionName(
92144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          cluster.constructor());
922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
923791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    AddEntryFromAggregatedSnapshot(snapshot_,
924791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                                   root_child_index_,
925791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                                   HeapEntry::kObject,
926791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                                   name,
927791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                                   number_and_size.number(),
928791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                                   number_and_size.bytes(),
929791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                                   0,
930791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                                   0);
931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
933791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block private:
934791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  HeapSnapshot* snapshot_;
935791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  int* root_child_index_;
936791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block};
937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
939791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockstatic HeapObject* ClusterAsHeapObject(const JSObjectsCluster& cluster) {
940791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  return cluster.can_be_coarsed() ?
941791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      reinterpret_cast<HeapObject*>(cluster.instance()) : cluster.constructor();
942791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block}
943791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
944791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
945791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockstatic JSObjectsCluster HeapObjectAsCluster(HeapObject* object) {
946791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  if (object->IsString()) {
947791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    return JSObjectsCluster(String::cast(object));
948791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  } else {
949791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    JSObject* js_obj = JSObject::cast(object);
9508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    String* constructor = GetConstructorNameForHeapProfile(
9518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        JSObject::cast(js_obj));
952791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    return JSObjectsCluster(constructor, object);
953791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  }
954791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block}
955791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
956791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
957791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockclass CountingRetainersIterator {
958791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block public:
959791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  CountingRetainersIterator(const JSObjectsCluster& child_cluster,
960e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                            HeapEntriesAllocator* allocator,
961791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                            HeapEntriesMap* map)
962e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      : child_(ClusterAsHeapObject(child_cluster)),
963e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        allocator_(allocator),
964e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        map_(map) {
965791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    if (map_->Map(child_) == NULL)
966e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      map_->Pair(child_, allocator_, HeapEntriesMap::kHeapEntryPlaceholder);
967791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  }
968791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
969791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  void Call(const JSObjectsCluster& cluster,
970791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block            const NumberAndSizeInfo& number_and_size) {
971791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    if (map_->Map(ClusterAsHeapObject(cluster)) == NULL)
972791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      map_->Pair(ClusterAsHeapObject(cluster),
973e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                 allocator_,
974791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                 HeapEntriesMap::kHeapEntryPlaceholder);
975791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    map_->CountReference(ClusterAsHeapObject(cluster), child_);
976791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  }
977791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
978791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block private:
979791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  HeapObject* child_;
980e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HeapEntriesAllocator* allocator_;
981791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  HeapEntriesMap* map_;
982791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block};
983791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
984791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
985791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockclass AllocatingRetainersIterator {
986791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block public:
987791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  AllocatingRetainersIterator(const JSObjectsCluster& child_cluster,
988e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                              HeapEntriesAllocator*,
989791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                              HeapEntriesMap* map)
990791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      : child_(ClusterAsHeapObject(child_cluster)), map_(map) {
991791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    child_entry_ = map_->Map(child_);
992791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    ASSERT(child_entry_ != NULL);
993791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  }
994791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
995791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  void Call(const JSObjectsCluster& cluster,
996791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block            const NumberAndSizeInfo& number_and_size) {
997791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    int child_index, retainer_index;
9988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    map_->CountReference(ClusterAsHeapObject(cluster),
9998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                         child_,
10008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                         &child_index,
10018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                         &retainer_index);
10028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    map_->Map(ClusterAsHeapObject(cluster))->SetIndexedReference(
10038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        HeapGraphEdge::kElement,
10048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        child_index,
10058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        number_and_size.number(),
10068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        child_entry_,
10078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        retainer_index);
1008791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  }
1009791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
1010791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block private:
1011791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  HeapObject* child_;
1012791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  HeapEntriesMap* map_;
1013791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  HeapEntry* child_entry_;
1014791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block};
1015791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
1016791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
1017791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blocktemplate<class RetainersIterator>
1018791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockclass AggregatingRetainerTreeIterator {
1019791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block public:
1020791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  explicit AggregatingRetainerTreeIterator(ClustersCoarser* coarser,
1021e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                           HeapEntriesAllocator* allocator,
1022791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                                           HeapEntriesMap* map)
1023e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      : coarser_(coarser), allocator_(allocator), map_(map) {
1024791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  }
1025791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
1026791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  void Call(const JSObjectsCluster& cluster, JSObjectsClusterTree* tree) {
1027791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    if (coarser_ != NULL &&
1028791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block        !coarser_->GetCoarseEquivalent(cluster).is_null()) return;
1029791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    JSObjectsClusterTree* tree_to_iterate = tree;
1030791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    ZoneScope zs(DELETE_ON_EXIT);
1031791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    JSObjectsClusterTree dest_tree_;
1032791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    if (coarser_ != NULL) {
1033791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      RetainersAggregator retainers_aggregator(coarser_, &dest_tree_);
1034791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      tree->ForEach(&retainers_aggregator);
1035791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      tree_to_iterate = &dest_tree_;
1036791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    }
1037e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    RetainersIterator iterator(cluster, allocator_, map_);
1038791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    tree_to_iterate->ForEach(&iterator);
1039791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  }
1040791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
1041791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block private:
1042791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  ClustersCoarser* coarser_;
1043e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HeapEntriesAllocator* allocator_;
1044791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  HeapEntriesMap* map_;
1045791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block};
1046791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
1047791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
1048e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochclass AggregatedRetainerTreeAllocator : public HeapEntriesAllocator {
1049791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block public:
1050791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  AggregatedRetainerTreeAllocator(HeapSnapshot* snapshot,
1051791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                                  int* root_child_index)
1052791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      : snapshot_(snapshot), root_child_index_(root_child_index) {
1053791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  }
1054e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ~AggregatedRetainerTreeAllocator() { }
1055791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
1056e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  HeapEntry* AllocateEntry(
1057e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      HeapThing ptr, int children_count, int retainers_count) {
1058e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HeapObject* obj = reinterpret_cast<HeapObject*>(ptr);
1059791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    JSObjectsCluster cluster = HeapObjectAsCluster(obj);
1060791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    const char* name = cluster.GetSpecialCaseName();
1061791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    if (name == NULL) {
106244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      name = snapshot_->collection()->names()->GetFunctionName(
106344f0eee88ff00398ff7f715fab053374d808c90dSteve Block          cluster.constructor());
1064791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    }
1065791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    return AddEntryFromAggregatedSnapshot(
1066791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block        snapshot_, root_child_index_, HeapEntry::kObject, name,
1067791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block        0, 0, children_count, retainers_count);
1068791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  }
1069791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
1070791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block private:
1071791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  HeapSnapshot* snapshot_;
1072791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  int* root_child_index_;
1073791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block};
1074791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
1075791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
1076791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blocktemplate<class Iterator>
1077791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockvoid AggregatedHeapSnapshotGenerator::IterateRetainers(
1078e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    HeapEntriesAllocator* allocator, HeapEntriesMap* entries_map) {
1079791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  RetainerHeapProfile* p = agg_snapshot_->js_retainer_profile();
1080791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  AggregatingRetainerTreeIterator<Iterator> agg_ret_iter_1(
1081e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      p->coarser(), allocator, entries_map);
1082791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  p->retainers_tree()->ForEach(&agg_ret_iter_1);
1083e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  AggregatingRetainerTreeIterator<Iterator> agg_ret_iter_2(
1084e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      NULL, allocator, entries_map);
1085791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  p->aggregator()->output_tree().ForEach(&agg_ret_iter_2);
1086791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block}
1087791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
1088791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
1089791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockvoid AggregatedHeapSnapshotGenerator::FillHeapSnapshot(HeapSnapshot* snapshot) {
1090791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  // Count the number of entities.
1091791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  int histogram_entities_count = 0;
1092791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  int histogram_children_count = 0;
1093791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  int histogram_retainers_count = 0;
1094791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  for (int i = FIRST_NONSTRING_TYPE; i <= kAllStringsType; ++i) {
1095791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    if (agg_snapshot_->info()[i].bytes() > 0) {
1096791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      ++histogram_entities_count;
1097791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    }
1098791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  }
1099791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  CountingConstructorHeapProfileIterator counting_cons_iter;
1100791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  agg_snapshot_->js_cons_profile()->ForEach(&counting_cons_iter);
1101791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  histogram_entities_count += counting_cons_iter.entities_count();
1102791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  HeapEntriesMap entries_map;
1103e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int root_child_index = 0;
1104e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  AggregatedRetainerTreeAllocator allocator(snapshot, &root_child_index);
1105e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  IterateRetainers<CountingRetainersIterator>(&allocator, &entries_map);
1106791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  histogram_entities_count += entries_map.entries_count();
1107791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  histogram_children_count += entries_map.total_children_count();
1108791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  histogram_retainers_count += entries_map.total_retainers_count();
1109791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
1110791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  // Root entry references all other entries.
1111791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  histogram_children_count += histogram_entities_count;
1112791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  int root_children_count = histogram_entities_count;
1113791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  ++histogram_entities_count;
1114791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
1115791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  // Allocate and fill entries in the snapshot, allocate references.
1116791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  snapshot->AllocateEntries(histogram_entities_count,
1117791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                            histogram_children_count,
1118791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                            histogram_retainers_count);
1119e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  snapshot->AddRootEntry(root_children_count);
1120791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  for (int i = FIRST_NONSTRING_TYPE; i <= kAllStringsType; ++i) {
1121791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    if (agg_snapshot_->info()[i].bytes() > 0) {
1122791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      AddEntryFromAggregatedSnapshot(snapshot,
1123791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                                     &root_child_index,
11248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                     HeapEntry::kHidden,
1125791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                                     agg_snapshot_->info()[i].name(),
1126791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                                     agg_snapshot_->info()[i].number(),
1127791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                                     agg_snapshot_->info()[i].bytes(),
1128791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                                     0,
1129791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block                                     0);
1130791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block    }
1131791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  }
1132791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  AllocatingConstructorHeapProfileIterator alloc_cons_iter(
1133791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      snapshot, &root_child_index);
1134791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  agg_snapshot_->js_cons_profile()->ForEach(&alloc_cons_iter);
1135e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  entries_map.AllocateEntries();
1136791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
1137791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  // Fill up references.
1138e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  IterateRetainers<AllocatingRetainersIterator>(&allocator, &entries_map);
11398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
11408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  snapshot->SetDominatorsToSelf();
1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockvoid ProducerHeapProfile::Setup() {
11453ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  can_log_ = true;
11463ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
11473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1148e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkevoid ProducerHeapProfile::DoRecordJSObjectAllocation(Object* obj) {
1149e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT(FLAG_log_producers);
1150e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  if (!can_log_) return;
11513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int framesCount = 0;
11523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  for (JavaScriptFrameIterator it; !it.done(); it.Advance()) {
11533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    ++framesCount;
11543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
11553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  if (framesCount == 0) return;
11563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  ++framesCount;  // Reserve place for the terminator item.
11573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  Vector<Address> stack(NewArray<Address>(framesCount), framesCount);
11583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  int i = 0;
11593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  for (JavaScriptFrameIterator it; !it.done(); it.Advance()) {
11603ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    stack[i++] = it.frame()->pc();
11613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
11623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  stack[i] = NULL;
116344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<Object> handle = isolate_->global_handles()->Create(obj);
116444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate_->global_handles()->MakeWeak(handle.location(),
116544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       static_cast<void*>(stack.start()),
116644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       StackWeakReferenceCallback);
11673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
11683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
11693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // ENABLE_LOGGING_AND_PROFILING
1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
1174