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