test-heap-profiler.cc revision a7e24c173cf37484693b9abb38e494fa7bd7baeb
1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2009 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Tests for heap profiler 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_LOGGING_AND_PROFILING 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h" 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "heap-profiler.h" 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "string-stream.h" 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "cctest.h" 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace i = v8::internal; 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing i::ClustersCoarser; 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing i::JSObjectsCluster; 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing i::JSObjectsRetainerTree; 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing i::JSObjectsClusterTree; 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing i::RetainerHeapProfile; 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void CompileAndRunScript(const char *src) { 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Script::Compile(v8::String::New(src))->Run(); 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace { 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass ConstructorHeapProfileTestHelper : public i::ConstructorHeapProfile { 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ConstructorHeapProfileTestHelper() 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : i::ConstructorHeapProfile(), 31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block f_name_(i::Factory::NewStringFromAscii(i::CStrVector("F"))), 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block f_count_(0) { 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Call(const JSObjectsCluster& cluster, 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const i::NumberAndSizeInfo& number_and_size) { 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (f_name_->Equals(cluster.constructor())) { 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(f_count_, 0); 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block f_count_ = number_and_size.number(); 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_GT(f_count_, 0); 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int f_count() { return f_count_; } 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::Handle<i::String> f_name_; 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int f_count_; 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} // namespace 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ConstructorProfile) { 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::HandleScope scope; 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Handle<v8::Context> env = v8::Context::New(); 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block env->Enter(); 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CompileAndRunScript( 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "function F() {} // A constructor\n" 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "var f1 = new F();\n" 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "var f2 = new F();\n"); 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ConstructorHeapProfileTestHelper cons_profile; 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::AssertNoAllocation no_alloc; 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::HeapIterator iterator; 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (iterator.has_next()) { 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::HeapObject* obj = iterator.next(); 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cons_profile.CollectStats(obj); 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(0, cons_profile.f_count()); 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cons_profile.PrintStats(); 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(2, cons_profile.f_count()); 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic JSObjectsCluster AddHeapObjectToTree(JSObjectsRetainerTree* tree, 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::String* constructor, 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int instance, 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster* ref1 = NULL, 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster* ref2 = NULL, 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster* ref3 = NULL) { 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o(constructor, reinterpret_cast<i::Object*>(instance)); 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsClusterTree* o_tree = new JSObjectsClusterTree(); 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsClusterTree::Locator o_loc; 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (ref1 != NULL) o_tree->Insert(*ref1, &o_loc); 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (ref2 != NULL) o_tree->Insert(*ref2, &o_loc); 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (ref3 != NULL) o_tree->Insert(*ref3, &o_loc); 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsRetainerTree::Locator loc; 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tree->Insert(o, &loc); 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block loc.set_value(o_tree); 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return o; 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void AddSelfReferenceToTree(JSObjectsRetainerTree* tree, 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster* self_ref) { 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsRetainerTree::Locator loc; 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(tree->Find(*self_ref, &loc)); 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsClusterTree::Locator o_loc; 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_NE(NULL, loc.value()); 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block loc.value()->Insert(*self_ref, &o_loc); 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic inline void CheckEqualsHelper(const char* file, int line, 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* expected_source, 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const JSObjectsCluster& expected, 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* value_source, 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const JSObjectsCluster& value) { 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (JSObjectsCluster::Compare(expected, value) != 0) { 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::HeapStringAllocator allocator; 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::StringStream stream(&allocator); 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stream.Add("# Expected: "); 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block expected.DebugPrint(&stream); 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stream.Add("\n# Found: "); 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block value.DebugPrint(&stream); 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block V8_Fatal(file, line, "CHECK_EQ(%s, %s) failed\n%s", 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block expected_source, value_source, 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *stream.ToCString()); 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic inline void CheckNonEqualsHelper(const char* file, int line, 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* expected_source, 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const JSObjectsCluster& expected, 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* value_source, 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const JSObjectsCluster& value) { 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (JSObjectsCluster::Compare(expected, value) == 0) { 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::HeapStringAllocator allocator; 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::StringStream stream(&allocator); 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stream.Add("# !Expected: "); 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block expected.DebugPrint(&stream); 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stream.Add("\n# Found: "); 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block value.DebugPrint(&stream); 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block V8_Fatal(file, line, "CHECK_NE(%s, %s) failed\n%s", 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block expected_source, value_source, 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *stream.ToCString()); 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ClustersCoarserSimple) { 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::HandleScope scope; 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Handle<v8::Context> env = v8::Context::New(); 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block env->Enter(); 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::ZoneScope zn_scope(i::DELETE_ON_EXIT); 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsRetainerTree tree; 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster function(i::Heap::function_class_symbol()); 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster a(*i::Factory::NewStringFromAscii(i::CStrVector("A"))); 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster b(*i::Factory::NewStringFromAscii(i::CStrVector("B"))); 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // o1 <- Function 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o1 = 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x100, &function); 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // o2 <- Function 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o2 = 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x200, &function); 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // o3 <- A, B 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o3 = 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x300, &a, &b); 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // o4 <- B, A 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o4 = 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x400, &b, &a); 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // o5 <- A, B, Function 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o5 = 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x500, 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &a, &b, &function); 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ClustersCoarser coarser; 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block coarser.Process(&tree); 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(coarser.GetCoarseEquivalent(o1), coarser.GetCoarseEquivalent(o2)); 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(coarser.GetCoarseEquivalent(o3), coarser.GetCoarseEquivalent(o4)); 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_NE(coarser.GetCoarseEquivalent(o1), coarser.GetCoarseEquivalent(o3)); 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(JSObjectsCluster(), coarser.GetCoarseEquivalent(o5)); 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ClustersCoarserMultipleConstructors) { 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::HandleScope scope; 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Handle<v8::Context> env = v8::Context::New(); 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block env->Enter(); 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::ZoneScope zn_scope(i::DELETE_ON_EXIT); 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsRetainerTree tree; 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster function(i::Heap::function_class_symbol()); 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // o1 <- Function 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o1 = 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x100, &function); 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // a1 <- Function 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster a1 = 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Array_symbol(), 0x1000, &function); 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // o2 <- Function 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o2 = 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x200, &function); 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // a2 <- Function 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster a2 = 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Array_symbol(), 0x2000, &function); 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ClustersCoarser coarser; 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block coarser.Process(&tree); 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(coarser.GetCoarseEquivalent(o1), coarser.GetCoarseEquivalent(o2)); 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(coarser.GetCoarseEquivalent(a1), coarser.GetCoarseEquivalent(a2)); 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ClustersCoarserPathsTraversal) { 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::HandleScope scope; 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Handle<v8::Context> env = v8::Context::New(); 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block env->Enter(); 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::ZoneScope zn_scope(i::DELETE_ON_EXIT); 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsRetainerTree tree; 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // On the following graph: 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // p 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // <- o21 <- o11 <- 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // q o 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // <- o22 <- o12 <- 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // we expect that coarser will deduce equivalences: p ~ q ~ r, 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // o21 ~ o22, and o11 ~ o12. 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o = 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x100); 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o11 = 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x110, &o); 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o12 = 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x120, &o); 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o21 = 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x210, &o11); 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o22 = 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x220, &o12); 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster p = 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x300, &o21); 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster q = 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x310, &o21, &o22); 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster r = 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x320, &o22); 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ClustersCoarser coarser; 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block coarser.Process(&tree); 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(JSObjectsCluster(), coarser.GetCoarseEquivalent(o)); 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_NE(JSObjectsCluster(), coarser.GetCoarseEquivalent(o11)); 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(coarser.GetCoarseEquivalent(o11), coarser.GetCoarseEquivalent(o12)); 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(coarser.GetCoarseEquivalent(o21), coarser.GetCoarseEquivalent(o22)); 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_NE(coarser.GetCoarseEquivalent(o11), coarser.GetCoarseEquivalent(o21)); 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_NE(JSObjectsCluster(), coarser.GetCoarseEquivalent(p)); 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(coarser.GetCoarseEquivalent(p), coarser.GetCoarseEquivalent(q)); 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(coarser.GetCoarseEquivalent(q), coarser.GetCoarseEquivalent(r)); 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_NE(coarser.GetCoarseEquivalent(o11), coarser.GetCoarseEquivalent(p)); 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_NE(coarser.GetCoarseEquivalent(o21), coarser.GetCoarseEquivalent(p)); 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ClustersCoarserSelf) { 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::HandleScope scope; 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Handle<v8::Context> env = v8::Context::New(); 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block env->Enter(); 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::ZoneScope zn_scope(i::DELETE_ON_EXIT); 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsRetainerTree tree; 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // On the following graph: 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // p (self-referencing) 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // <- o1 <- 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // q (self-referencing) o 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // <- o2 <- 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r (self-referencing) 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // we expect that coarser will deduce equivalences: p ~ q ~ r, o1 ~ o2; 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o = 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x100); 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o1 = 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x110, &o); 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o2 = 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x120, &o); 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster p = 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x300, &o1); 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddSelfReferenceToTree(&tree, &p); 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster q = 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x310, &o1, &o2); 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddSelfReferenceToTree(&tree, &q); 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster r = 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x320, &o2); 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddSelfReferenceToTree(&tree, &r); 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ClustersCoarser coarser; 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block coarser.Process(&tree); 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(JSObjectsCluster(), coarser.GetCoarseEquivalent(o)); 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_NE(JSObjectsCluster(), coarser.GetCoarseEquivalent(o1)); 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(coarser.GetCoarseEquivalent(o1), coarser.GetCoarseEquivalent(o2)); 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_NE(JSObjectsCluster(), coarser.GetCoarseEquivalent(p)); 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(coarser.GetCoarseEquivalent(p), coarser.GetCoarseEquivalent(q)); 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(coarser.GetCoarseEquivalent(q), coarser.GetCoarseEquivalent(r)); 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_NE(coarser.GetCoarseEquivalent(o1), coarser.GetCoarseEquivalent(p)); 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace { 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass RetainerProfilePrinter : public RetainerHeapProfile::Printer { 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RetainerProfilePrinter() : stream_(&allocator_), lines_(100) {} 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void PrintRetainers(const JSObjectsCluster& cluster, 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const i::StringStream& retainers) { 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cluster.Print(&stream_); 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stream_.Add("%s", *(retainers.ToCString())); 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stream_.Put('\0'); 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* GetRetainers(const char* constructor) { 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FillLines(); 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const size_t cons_len = strlen(constructor); 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < lines_.length(); ++i) { 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (strncmp(constructor, lines_[i], cons_len) == 0 && 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lines_[i][cons_len] == ',') { 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return lines_[i] + cons_len + 1; 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return NULL; 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void FillLines() { 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (lines_.length() > 0) return; 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stream_.Put('\0'); 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stream_str_ = stream_.ToCString(); 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* pos = *stream_str_; 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (pos != NULL && *pos != '\0') { 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lines_.Add(pos); 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pos = strchr(pos, '\0'); 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (pos != NULL) ++pos; 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::HeapStringAllocator allocator_; 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::StringStream stream_; 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::SmartPointer<const char> stream_str_; 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::List<const char*> lines_; 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} // namespace 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(RetainerProfile) { 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::HandleScope scope; 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Handle<v8::Context> env = v8::Context::New(); 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block env->Enter(); 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CompileAndRunScript( 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "function A() {}\n" 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "function B(x) { this.x = x; }\n" 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "function C(x) { this.x1 = x; this.x2 = x; }\n" 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "var a = new A();\n" 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "var b1 = new B(a), b2 = new B(a);\n" 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "var c = new C(a);"); 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RetainerHeapProfile ret_profile; 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::AssertNoAllocation no_alloc; 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::HeapIterator iterator; 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (iterator.has_next()) { 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::HeapObject* obj = iterator.next(); 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ret_profile.CollectStats(obj); 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RetainerProfilePrinter printer; 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ret_profile.DebugPrintStats(&printer); 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* retainers_of_a = printer.GetRetainers("A"); 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The order of retainers is unspecified, so we check string length, and 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // verify each retainer separately. 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(static_cast<int>(strlen("(global property);1,B;2,C;2")), 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static_cast<int>(strlen(retainers_of_a))); 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(strstr(retainers_of_a, "(global property);1") != NULL); 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(strstr(retainers_of_a, "B;2") != NULL); 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(strstr(retainers_of_a, "C;2") != NULL); 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ("(global property);2", printer.GetRetainers("B")); 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ("(global property);1", printer.GetRetainers("C")); 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // ENABLE_LOGGING_AND_PROFILING 397