test-heap-profiler.cc revision 44f0eee88ff00398ff7f715fab053374d808c90d
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" 99dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen#include "snapshot.h" 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "string-stream.h" 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "cctest.h" 126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#include "zone-inl.h" 139dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen#include "../include/v8-profiler.h" 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace i = v8::internal; 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing i::ClustersCoarser; 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing i::JSObjectsCluster; 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing i::JSObjectsRetainerTree; 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing i::JSObjectsClusterTree; 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing i::RetainerHeapProfile; 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace { 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass ConstructorHeapProfileTestHelper : public i::ConstructorHeapProfile { 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ConstructorHeapProfileTestHelper() 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : i::ConstructorHeapProfile(), 2944f0eee88ff00398ff7f715fab053374d808c90dSteve Block f_name_(FACTORY->NewStringFromAscii(i::CStrVector("F"))), 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block f_count_(0) { 31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Call(const JSObjectsCluster& cluster, 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const i::NumberAndSizeInfo& number_and_size) { 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (f_name_->Equals(cluster.constructor())) { 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(f_count_, 0); 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block f_count_ = number_and_size.number(); 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_GT(f_count_, 0); 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int f_count() { return f_count_; } 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::Handle<i::String> f_name_; 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int f_count_; 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} // namespace 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ConstructorProfile) { 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::HandleScope scope; 543bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch LocalContext env; 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 56f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CompileRun( 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "function F() {} // A constructor\n" 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "var f1 = new F();\n" 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "var f2 = new F();\n"); 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ConstructorHeapProfileTestHelper cons_profile; 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::AssertNoAllocation no_alloc; 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::HeapIterator iterator; 64d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke for (i::HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cons_profile.CollectStats(obj); 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(0, cons_profile.f_count()); 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cons_profile.PrintStats(); 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(2, cons_profile.f_count()); 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic JSObjectsCluster AddHeapObjectToTree(JSObjectsRetainerTree* tree, 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::String* constructor, 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int instance, 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster* ref1 = NULL, 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster* ref2 = NULL, 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster* ref3 = NULL) { 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o(constructor, reinterpret_cast<i::Object*>(instance)); 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsClusterTree* o_tree = new JSObjectsClusterTree(); 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsClusterTree::Locator o_loc; 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (ref1 != NULL) o_tree->Insert(*ref1, &o_loc); 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (ref2 != NULL) o_tree->Insert(*ref2, &o_loc); 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (ref3 != NULL) o_tree->Insert(*ref3, &o_loc); 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsRetainerTree::Locator loc; 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tree->Insert(o, &loc); 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block loc.set_value(o_tree); 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return o; 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void AddSelfReferenceToTree(JSObjectsRetainerTree* tree, 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster* self_ref) { 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsRetainerTree::Locator loc; 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(tree->Find(*self_ref, &loc)); 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsClusterTree::Locator o_loc; 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_NE(NULL, loc.value()); 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block loc.value()->Insert(*self_ref, &o_loc); 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic inline void CheckEqualsHelper(const char* file, int line, 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* expected_source, 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const JSObjectsCluster& expected, 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* value_source, 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const JSObjectsCluster& value) { 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (JSObjectsCluster::Compare(expected, value) != 0) { 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::HeapStringAllocator allocator; 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::StringStream stream(&allocator); 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stream.Add("# Expected: "); 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block expected.DebugPrint(&stream); 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stream.Add("\n# Found: "); 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block value.DebugPrint(&stream); 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block V8_Fatal(file, line, "CHECK_EQ(%s, %s) failed\n%s", 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block expected_source, value_source, 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *stream.ToCString()); 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic inline void CheckNonEqualsHelper(const char* file, int line, 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* expected_source, 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const JSObjectsCluster& expected, 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* value_source, 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const JSObjectsCluster& value) { 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (JSObjectsCluster::Compare(expected, value) == 0) { 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::HeapStringAllocator allocator; 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::StringStream stream(&allocator); 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stream.Add("# !Expected: "); 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block expected.DebugPrint(&stream); 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stream.Add("\n# Found: "); 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block value.DebugPrint(&stream); 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block V8_Fatal(file, line, "CHECK_NE(%s, %s) failed\n%s", 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block expected_source, value_source, 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *stream.ToCString()); 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ClustersCoarserSimple) { 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::HandleScope scope; 1413bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch LocalContext env; 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::ZoneScope zn_scope(i::DELETE_ON_EXIT); 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsRetainerTree tree; 14644f0eee88ff00398ff7f715fab053374d808c90dSteve Block JSObjectsCluster function(HEAP->function_class_symbol()); 14744f0eee88ff00398ff7f715fab053374d808c90dSteve Block JSObjectsCluster a(*FACTORY->NewStringFromAscii(i::CStrVector("A"))); 14844f0eee88ff00398ff7f715fab053374d808c90dSteve Block JSObjectsCluster b(*FACTORY->NewStringFromAscii(i::CStrVector("B"))); 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // o1 <- Function 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o1 = 15244f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x100, &function); 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // o2 <- Function 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o2 = 15544f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x200, &function); 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // o3 <- A, B 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o3 = 15844f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x300, &a, &b); 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // o4 <- B, A 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o4 = 16144f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x400, &b, &a); 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // o5 <- A, B, Function 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o5 = 16444f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x500, 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &a, &b, &function); 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ClustersCoarser coarser; 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block coarser.Process(&tree); 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(coarser.GetCoarseEquivalent(o1), coarser.GetCoarseEquivalent(o2)); 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(coarser.GetCoarseEquivalent(o3), coarser.GetCoarseEquivalent(o4)); 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_NE(coarser.GetCoarseEquivalent(o1), coarser.GetCoarseEquivalent(o3)); 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(JSObjectsCluster(), coarser.GetCoarseEquivalent(o5)); 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ClustersCoarserMultipleConstructors) { 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::HandleScope scope; 1793bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch LocalContext env; 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::ZoneScope zn_scope(i::DELETE_ON_EXIT); 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsRetainerTree tree; 18444f0eee88ff00398ff7f715fab053374d808c90dSteve Block JSObjectsCluster function(HEAP->function_class_symbol()); 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // o1 <- Function 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o1 = 18844f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x100, &function); 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // a1 <- Function 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster a1 = 19144f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddHeapObjectToTree(&tree, HEAP->Array_symbol(), 0x1000, &function); 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // o2 <- Function 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o2 = 19444f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x200, &function); 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // a2 <- Function 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster a2 = 19744f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddHeapObjectToTree(&tree, HEAP->Array_symbol(), 0x2000, &function); 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ClustersCoarser coarser; 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block coarser.Process(&tree); 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(coarser.GetCoarseEquivalent(o1), coarser.GetCoarseEquivalent(o2)); 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(coarser.GetCoarseEquivalent(a1), coarser.GetCoarseEquivalent(a2)); 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ClustersCoarserPathsTraversal) { 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::HandleScope scope; 2093bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch LocalContext env; 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::ZoneScope zn_scope(i::DELETE_ON_EXIT); 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsRetainerTree tree; 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // On the following graph: 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // p 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // <- o21 <- o11 <- 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // q o 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // <- o22 <- o12 <- 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // we expect that coarser will deduce equivalences: p ~ q ~ r, 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // o21 ~ o22, and o11 ~ o12. 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o = 22744f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x100); 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o11 = 22944f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x110, &o); 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o12 = 23144f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x120, &o); 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o21 = 23344f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x210, &o11); 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o22 = 23544f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x220, &o12); 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster p = 23744f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x300, &o21); 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster q = 23944f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x310, &o21, &o22); 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster r = 24144f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x320, &o22); 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ClustersCoarser coarser; 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block coarser.Process(&tree); 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(JSObjectsCluster(), coarser.GetCoarseEquivalent(o)); 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_NE(JSObjectsCluster(), coarser.GetCoarseEquivalent(o11)); 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(coarser.GetCoarseEquivalent(o11), coarser.GetCoarseEquivalent(o12)); 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(coarser.GetCoarseEquivalent(o21), coarser.GetCoarseEquivalent(o22)); 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_NE(coarser.GetCoarseEquivalent(o11), coarser.GetCoarseEquivalent(o21)); 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_NE(JSObjectsCluster(), coarser.GetCoarseEquivalent(p)); 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(coarser.GetCoarseEquivalent(p), coarser.GetCoarseEquivalent(q)); 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(coarser.GetCoarseEquivalent(q), coarser.GetCoarseEquivalent(r)); 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_NE(coarser.GetCoarseEquivalent(o11), coarser.GetCoarseEquivalent(p)); 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_NE(coarser.GetCoarseEquivalent(o21), coarser.GetCoarseEquivalent(p)); 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ClustersCoarserSelf) { 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::HandleScope scope; 2613bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch LocalContext env; 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::ZoneScope zn_scope(i::DELETE_ON_EXIT); 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsRetainerTree tree; 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // On the following graph: 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // p (self-referencing) 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // <- o1 <- 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // q (self-referencing) o 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // <- o2 <- 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r (self-referencing) 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // we expect that coarser will deduce equivalences: p ~ q ~ r, o1 ~ o2; 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o = 27844f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x100); 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o1 = 28044f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x110, &o); 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o2 = 28244f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x120, &o); 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster p = 28444f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x300, &o1); 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddSelfReferenceToTree(&tree, &p); 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster q = 28744f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x310, &o1, &o2); 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddSelfReferenceToTree(&tree, &q); 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster r = 29044f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddHeapObjectToTree(&tree, HEAP->Object_symbol(), 0x320, &o2); 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddSelfReferenceToTree(&tree, &r); 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ClustersCoarser coarser; 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block coarser.Process(&tree); 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(JSObjectsCluster(), coarser.GetCoarseEquivalent(o)); 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_NE(JSObjectsCluster(), coarser.GetCoarseEquivalent(o1)); 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(coarser.GetCoarseEquivalent(o1), coarser.GetCoarseEquivalent(o2)); 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_NE(JSObjectsCluster(), coarser.GetCoarseEquivalent(p)); 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(coarser.GetCoarseEquivalent(p), coarser.GetCoarseEquivalent(q)); 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(coarser.GetCoarseEquivalent(q), coarser.GetCoarseEquivalent(r)); 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_NE(coarser.GetCoarseEquivalent(o1), coarser.GetCoarseEquivalent(p)); 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace { 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass RetainerProfilePrinter : public RetainerHeapProfile::Printer { 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RetainerProfilePrinter() : stream_(&allocator_), lines_(100) {} 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void PrintRetainers(const JSObjectsCluster& cluster, 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const i::StringStream& retainers) { 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cluster.Print(&stream_); 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stream_.Add("%s", *(retainers.ToCString())); 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stream_.Put('\0'); 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* GetRetainers(const char* constructor) { 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FillLines(); 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const size_t cons_len = strlen(constructor); 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < lines_.length(); ++i) { 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (strncmp(constructor, lines_[i], cons_len) == 0 && 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lines_[i][cons_len] == ',') { 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return lines_[i] + cons_len + 1; 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return NULL; 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void FillLines() { 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (lines_.length() > 0) return; 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stream_.Put('\0'); 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stream_str_ = stream_.ToCString(); 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* pos = *stream_str_; 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (pos != NULL && *pos != '\0') { 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lines_.Add(pos); 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pos = strchr(pos, '\0'); 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (pos != NULL) ++pos; 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::HeapStringAllocator allocator_; 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::StringStream stream_; 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::SmartPointer<const char> stream_str_; 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::List<const char*> lines_; 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} // namespace 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(RetainerProfile) { 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::HandleScope scope; 3553bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch LocalContext env; 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 357f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CompileRun( 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "function A() {}\n" 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "function B(x) { this.x = x; }\n" 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "function C(x) { this.x1 = x; this.x2 = x; }\n" 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "var a = new A();\n" 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "var b1 = new B(a), b2 = new B(a);\n" 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "var c = new C(a);"); 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RetainerHeapProfile ret_profile; 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::AssertNoAllocation no_alloc; 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::HeapIterator iterator; 368d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke for (i::HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ret_profile.CollectStats(obj); 370791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block ret_profile.CoarseAndAggregate(); 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RetainerProfilePrinter printer; 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ret_profile.DebugPrintStats(&printer); 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* retainers_of_a = printer.GetRetainers("A"); 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The order of retainers is unspecified, so we check string length, and 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // verify each retainer separately. 376d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block CHECK_EQ(i::StrLength("(global property);1,B;2,C;2"), 377d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block i::StrLength(retainers_of_a)); 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(strstr(retainers_of_a, "(global property);1") != NULL); 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(strstr(retainers_of_a, "B;2") != NULL); 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(strstr(retainers_of_a, "C;2") != NULL); 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ("(global property);2", printer.GetRetainers("B")); 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ("(global property);1", printer.GetRetainers("C")); 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3859dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 3869dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsennamespace { 3879dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 3889dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenclass NamedEntriesDetector { 3899dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen public: 3909dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen NamedEntriesDetector() 39190bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner : has_A2(false), has_B2(false), has_C2(false) { 3929dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 3939dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 394756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick void Apply(i::HeapEntry** entry_ptr) { 395756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (IsReachableNodeWithName(*entry_ptr, "A2")) has_A2 = true; 396756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (IsReachableNodeWithName(*entry_ptr, "B2")) has_B2 = true; 397756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (IsReachableNodeWithName(*entry_ptr, "C2")) has_C2 = true; 398756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 399756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 400756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick static bool IsReachableNodeWithName(i::HeapEntry* entry, const char* name) { 401756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick return strcmp(name, entry->name()) == 0 && entry->painted_reachable(); 4029dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 4039dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 4049dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen bool has_A2; 4059dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen bool has_B2; 4069dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen bool has_C2; 4079dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}; 4089dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 4099dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} // namespace 4109dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 4119dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 4129dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenstatic const v8::HeapGraphNode* GetGlobalObject( 4139dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapSnapshot* snapshot) { 4148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_EQ(2, snapshot->GetRoot()->GetChildrenCount()); 4158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const v8::HeapGraphNode* global_obj = 4168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang snapshot->GetRoot()->GetChild(0)->GetToNode(); 4178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_EQ("Object", const_cast<i::HeapEntry*>( 4188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang reinterpret_cast<const i::HeapEntry*>(global_obj))->name()); 4198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang return global_obj; 4209dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 4219dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 4229dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 4239dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenstatic const v8::HeapGraphNode* GetProperty(const v8::HeapGraphNode* node, 4249dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen v8::HeapGraphEdge::Type type, 4259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const char* name) { 4269dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) { 4279dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphEdge* prop = node->GetChild(i); 4289dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen v8::String::AsciiValue prop_name(prop->GetName()); 4299dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (prop->GetType() == type && strcmp(name, *prop_name) == 0) 4309dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen return prop->GetToNode(); 4319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 4329dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen return NULL; 4339dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 4349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 4359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 4369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenstatic bool HasString(const v8::HeapGraphNode* node, const char* contents) { 4379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) { 4389dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphEdge* prop = node->GetChild(i); 4399dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphNode* node = prop->GetToNode(); 440756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (node->GetType() == v8::HeapGraphNode::kString) { 4419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen v8::String::AsciiValue node_name(node->GetName()); 4429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (strcmp(contents, *node_name) == 0) return true; 4439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 4449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 4459dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen return false; 4469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 4479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 4489dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 4499dcf7e2f83591d471e88bf7d230651900b8e424bKristian MonsenTEST(HeapSnapshot) { 4509dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen v8::HandleScope scope; 4513bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch LocalContext env2; 4529dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 453f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CompileRun( 4549dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen "function A2() {}\n" 4559dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen "function B2(x) { return function() { return typeof x; }; }\n" 4569dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen "function C2(x) { this.x1 = x; this.x2 = x; this[1] = x; }\n" 4579dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen "var a2 = new A2();\n" 4589dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen "var b2_1 = new B2(a2), b2_2 = new B2(a2);\n" 4599dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen "var c2 = new C2(a2);"); 4609dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapSnapshot* snapshot_env2 = 4619dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen v8::HeapProfiler::TakeSnapshot(v8::String::New("env2")); 462756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick i::HeapSnapshot* i_snapshot_env2 = 463756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick const_cast<i::HeapSnapshot*>( 464756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick reinterpret_cast<const i::HeapSnapshot*>(snapshot_env2)); 4659dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphNode* global_env2 = GetGlobalObject(snapshot_env2); 466756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Paint all nodes reachable from global object. 467756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick i_snapshot_env2->ClearPaint(); 468756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick const_cast<i::HeapEntry*>( 469756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick reinterpret_cast<const i::HeapEntry*>(global_env2))->PaintAllReachable(); 4709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 47190bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner // Verify, that JS global object of env2 has '..2' properties. 4729dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphNode* a2_node = 4738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "a2"); 4749dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK_NE(NULL, a2_node); 475756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_NE( 4768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "b2_1")); 477756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_NE( 4788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "b2_2")); 4798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_NE(NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "c2")); 4809dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 4819dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen NamedEntriesDetector det; 4829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen i_snapshot_env2->IterateEntries(&det); 4839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK(det.has_A2); 4849dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK(det.has_B2); 4859dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK(det.has_C2); 4869dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 4879dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 4889dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 489756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain MerrickTEST(HeapSnapshotObjectSizes) { 490756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick v8::HandleScope scope; 491756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick LocalContext env; 492756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 493756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // -a-> X1 --a 494756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // x -b-> X2 <-| 495f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CompileRun( 496756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick "function X(a, b) { this.a = a; this.b = b; }\n" 497756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick "x = new X(new X(), new X());\n" 4988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang "(function() { x.a.a = x.b; })();"); 499756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick const v8::HeapSnapshot* snapshot = 500756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick v8::HeapProfiler::TakeSnapshot(v8::String::New("sizes")); 501756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick const v8::HeapGraphNode* global = GetGlobalObject(snapshot); 502756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick const v8::HeapGraphNode* x = 5038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang GetProperty(global, v8::HeapGraphEdge::kShortcut, "x"); 504756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_NE(NULL, x); 505756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick const v8::HeapGraphNode* x1 = 506756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick GetProperty(x, v8::HeapGraphEdge::kProperty, "a"); 507756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_NE(NULL, x1); 508756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick const v8::HeapGraphNode* x2 = 509756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick GetProperty(x, v8::HeapGraphEdge::kProperty, "b"); 510756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_NE(NULL, x2); 5118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 5128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Test approximate sizes. 5138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_EQ(x->GetSelfSize() * 3, x->GetRetainedSize(false)); 5148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_EQ(x1->GetSelfSize(), x1->GetRetainedSize(false)); 5158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_EQ(x2->GetSelfSize(), x2->GetRetainedSize(false)); 5168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Test exact sizes. 5178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_EQ(x->GetSelfSize() * 3, x->GetRetainedSize(true)); 5188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_EQ(x1->GetSelfSize(), x1->GetRetainedSize(true)); 5198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_EQ(x2->GetSelfSize(), x2->GetRetainedSize(true)); 520756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick} 521756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 522756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 523756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain MerrickTEST(HeapSnapshotEntryChildren) { 524756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick v8::HandleScope scope; 525756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick LocalContext env; 526756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 527f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CompileRun( 528756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick "function A() { }\n" 529756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick "a = new A;"); 530756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick const v8::HeapSnapshot* snapshot = 531756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick v8::HeapProfiler::TakeSnapshot(v8::String::New("children")); 532756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick const v8::HeapGraphNode* global = GetGlobalObject(snapshot); 533756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick for (int i = 0, count = global->GetChildrenCount(); i < count; ++i) { 534756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick const v8::HeapGraphEdge* prop = global->GetChild(i); 535756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_EQ(global, prop->GetFromNode()); 536756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 537756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick const v8::HeapGraphNode* a = 538756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick GetProperty(global, v8::HeapGraphEdge::kProperty, "a"); 539756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_NE(NULL, a); 540756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick for (int i = 0, count = a->GetChildrenCount(); i < count; ++i) { 541756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick const v8::HeapGraphEdge* prop = a->GetChild(i); 542756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_EQ(a, prop->GetFromNode()); 543756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 544756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick} 545756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 546756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 5479dcf7e2f83591d471e88bf7d230651900b8e424bKristian MonsenTEST(HeapSnapshotCodeObjects) { 5489dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen v8::HandleScope scope; 5493bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch LocalContext env; 5509dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 551f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CompileRun( 5529dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen "function lazy(x) { return x - 1; }\n" 5539dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen "function compiled(x) { return x + 1; }\n" 554791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block "var anonymous = (function() { return function() { return 0; } })();\n" 5559dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen "compiled(1)"); 5569dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapSnapshot* snapshot = 5579dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen v8::HeapProfiler::TakeSnapshot(v8::String::New("code")); 5589dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 5599dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphNode* global = GetGlobalObject(snapshot); 5609dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphNode* compiled = 5618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang GetProperty(global, v8::HeapGraphEdge::kShortcut, "compiled"); 5629dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK_NE(NULL, compiled); 563756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_EQ(v8::HeapGraphNode::kClosure, compiled->GetType()); 5649dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphNode* lazy = 5658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang GetProperty(global, v8::HeapGraphEdge::kShortcut, "lazy"); 5669dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK_NE(NULL, lazy); 567756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_EQ(v8::HeapGraphNode::kClosure, lazy->GetType()); 568791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block const v8::HeapGraphNode* anonymous = 5698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang GetProperty(global, v8::HeapGraphEdge::kShortcut, "anonymous"); 570791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_NE(NULL, anonymous); 571791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_EQ(v8::HeapGraphNode::kClosure, anonymous->GetType()); 572791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block v8::String::AsciiValue anonymous_name(anonymous->GetName()); 573f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CHECK_EQ("", *anonymous_name); 5749dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 5759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Find references to code. 5769dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphNode* compiled_code = 577756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick GetProperty(compiled, v8::HeapGraphEdge::kInternal, "code"); 5789dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK_NE(NULL, compiled_code); 5799dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphNode* lazy_code = 580756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick GetProperty(lazy, v8::HeapGraphEdge::kInternal, "code"); 5819dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK_NE(NULL, lazy_code); 5829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 5839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Verify that non-compiled code doesn't contain references to "x" 5843bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // literal, while compiled code does. The scope info is stored in FixedArray 5853bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // objects attached to the SharedFunctionInfo. 5869dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen bool compiled_references_x = false, lazy_references_x = false; 5879dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen for (int i = 0, count = compiled_code->GetChildrenCount(); i < count; ++i) { 5889dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphEdge* prop = compiled_code->GetChild(i); 5899dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphNode* node = prop->GetToNode(); 590756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (node->GetType() == v8::HeapGraphNode::kArray) { 5919dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (HasString(node, "x")) { 5929dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen compiled_references_x = true; 5939dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen break; 5949dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 5959dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 5969dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 5979dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen for (int i = 0, count = lazy_code->GetChildrenCount(); i < count; ++i) { 5989dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphEdge* prop = lazy_code->GetChild(i); 5999dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphNode* node = prop->GetToNode(); 600756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (node->GetType() == v8::HeapGraphNode::kArray) { 6019dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (HasString(node, "x")) { 6029dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen lazy_references_x = true; 6039dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen break; 6049dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 6059dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 6069dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 6079dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK(compiled_references_x); 6089dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK(!lazy_references_x); 6099dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 6109dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 6113bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 612f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochTEST(HeapSnapshotHeapNumbers) { 613f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch v8::HandleScope scope; 614f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch LocalContext env; 615f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CompileRun( 616f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch "a = 1; // a is Smi\n" 617f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch "b = 2.5; // b is HeapNumber"); 618f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch const v8::HeapSnapshot* snapshot = 619f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch v8::HeapProfiler::TakeSnapshot(v8::String::New("numbers")); 620f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch const v8::HeapGraphNode* global = GetGlobalObject(snapshot); 6218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_EQ(NULL, GetProperty(global, v8::HeapGraphEdge::kShortcut, "a")); 622f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch const v8::HeapGraphNode* b = 6238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang GetProperty(global, v8::HeapGraphEdge::kShortcut, "b"); 624f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CHECK_NE(NULL, b); 625f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CHECK_EQ(v8::HeapGraphNode::kHeapNumber, b->GetType()); 626f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch} 627f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 628f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 629f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochTEST(HeapSnapshotInternalReferences) { 630f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch v8::HandleScope scope; 631f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch v8::Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(); 632f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch global_template->SetInternalFieldCount(2); 633f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch LocalContext env(NULL, global_template); 634f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch v8::Handle<v8::Object> global_proxy = env->Global(); 635f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch v8::Handle<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>(); 636f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CHECK_EQ(2, global->InternalFieldCount()); 637f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch v8::Local<v8::Object> obj = v8::Object::New(); 638f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch global->SetInternalField(0, v8_num(17)); 639f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch global->SetInternalField(1, obj); 640f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch const v8::HeapSnapshot* snapshot = 641f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch v8::HeapProfiler::TakeSnapshot(v8::String::New("internals")); 642f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch const v8::HeapGraphNode* global_node = GetGlobalObject(snapshot); 643f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // The first reference will not present, because it's a Smi. 644f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CHECK_EQ(NULL, GetProperty(global_node, v8::HeapGraphEdge::kInternal, "0")); 645f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // The second reference is to an object. 646f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CHECK_NE(NULL, GetProperty(global_node, v8::HeapGraphEdge::kInternal, "1")); 647f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch} 648f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 649f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 6503bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// Trying to introduce a check helper for uint64_t causes many 6513bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// overloading ambiguities, so it seems easier just to cast 6523bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// them to a signed type. 6533bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch#define CHECK_EQ_UINT64_T(a, b) \ 6543bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CHECK_EQ(static_cast<int64_t>(a), static_cast<int64_t>(b)) 655756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick#define CHECK_NE_UINT64_T(a, b) \ 656756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK((a) != (b)) // NOLINT 6573bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 6583bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben MurdochTEST(HeapEntryIdsAndGC) { 6593bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch v8::HandleScope scope; 6603bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch LocalContext env; 6613bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 662f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CompileRun( 6633bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch "function A() {}\n" 6643bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch "function B(x) { this.x = x; }\n" 6653bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch "var a = new A();\n" 6663bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch "var b = new B(a);"); 6673bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const v8::HeapSnapshot* snapshot1 = 6683bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch v8::HeapProfiler::TakeSnapshot(v8::String::New("s1")); 6693bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 67044f0eee88ff00398ff7f715fab053374d808c90dSteve Block HEAP->CollectAllGarbage(true); // Enforce compaction. 6713bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 6723bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const v8::HeapSnapshot* snapshot2 = 6733bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch v8::HeapProfiler::TakeSnapshot(v8::String::New("s2")); 6743bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 6753bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const v8::HeapGraphNode* global1 = GetGlobalObject(snapshot1); 6763bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const v8::HeapGraphNode* global2 = GetGlobalObject(snapshot2); 6773bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CHECK_NE_UINT64_T(0, global1->GetId()); 6783bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CHECK_EQ_UINT64_T(global1->GetId(), global2->GetId()); 6793bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const v8::HeapGraphNode* A1 = 680756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick GetProperty(global1, v8::HeapGraphEdge::kProperty, "A"); 681756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_NE(NULL, A1); 6823bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const v8::HeapGraphNode* A2 = 683756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick GetProperty(global2, v8::HeapGraphEdge::kProperty, "A"); 684756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_NE(NULL, A2); 6853bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CHECK_NE_UINT64_T(0, A1->GetId()); 6863bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CHECK_EQ_UINT64_T(A1->GetId(), A2->GetId()); 6873bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const v8::HeapGraphNode* B1 = 688756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick GetProperty(global1, v8::HeapGraphEdge::kProperty, "B"); 689756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_NE(NULL, B1); 6903bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const v8::HeapGraphNode* B2 = 691756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick GetProperty(global2, v8::HeapGraphEdge::kProperty, "B"); 692756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_NE(NULL, B2); 6933bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CHECK_NE_UINT64_T(0, B1->GetId()); 6943bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CHECK_EQ_UINT64_T(B1->GetId(), B2->GetId()); 6953bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const v8::HeapGraphNode* a1 = 696756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick GetProperty(global1, v8::HeapGraphEdge::kProperty, "a"); 697756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_NE(NULL, a1); 6983bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const v8::HeapGraphNode* a2 = 699756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick GetProperty(global2, v8::HeapGraphEdge::kProperty, "a"); 700756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_NE(NULL, a2); 7013bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CHECK_NE_UINT64_T(0, a1->GetId()); 7023bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CHECK_EQ_UINT64_T(a1->GetId(), a2->GetId()); 7033bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const v8::HeapGraphNode* b1 = 704756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick GetProperty(global1, v8::HeapGraphEdge::kProperty, "b"); 705756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_NE(NULL, b1); 7063bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const v8::HeapGraphNode* b2 = 707756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick GetProperty(global2, v8::HeapGraphEdge::kProperty, "b"); 708756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_NE(NULL, b2); 7093bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CHECK_NE_UINT64_T(0, b1->GetId()); 7103bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CHECK_EQ_UINT64_T(b1->GetId(), b2->GetId()); 7113bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch} 7123bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 7133bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 714f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochTEST(HeapSnapshotRootPreservedAfterSorting) { 715f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch v8::HandleScope scope; 716f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch LocalContext env; 717f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch const v8::HeapSnapshot* snapshot = 718f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch v8::HeapProfiler::TakeSnapshot(v8::String::New("s")); 719f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch const v8::HeapGraphNode* root1 = snapshot->GetRoot(); 720f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch const_cast<i::HeapSnapshot*>(reinterpret_cast<const i::HeapSnapshot*>( 721f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch snapshot))->GetSortedEntriesList(); 722f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch const v8::HeapGraphNode* root2 = snapshot->GetRoot(); 723f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CHECK_EQ(root1, root2); 724f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch} 725f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 726f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 727791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockstatic const v8::HeapGraphNode* GetChild( 728791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block const v8::HeapGraphNode* node, 729791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block v8::HeapGraphNode::Type type, 730791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block const char* name, 731791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block const v8::HeapGraphNode* after = NULL) { 732791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block bool ignore_child = after == NULL ? false : true; 733791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) { 734791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block const v8::HeapGraphEdge* prop = node->GetChild(i); 735791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block const v8::HeapGraphNode* child = prop->GetToNode(); 736791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block v8::String::AsciiValue child_name(child->GetName()); 737791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block if (!ignore_child 738791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block && child->GetType() == type 739791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block && strcmp(name, *child_name) == 0) 740791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block return child; 741791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block if (after != NULL && child == after) ignore_child = false; 742791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block } 743791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block return NULL; 744791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block} 745791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block 746791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockstatic bool IsNodeRetainedAs(const v8::HeapGraphNode* node, 747791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block int element) { 748791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block for (int i = 0, count = node->GetRetainersCount(); i < count; ++i) { 749791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block const v8::HeapGraphEdge* prop = node->GetRetainer(i); 750791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block if (prop->GetType() == v8::HeapGraphEdge::kElement 751791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block && element == prop->GetName()->Int32Value()) 752791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block return true; 753791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block } 754791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block return false; 755791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block} 756791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block 757791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve BlockTEST(AggregatedHeapSnapshot) { 758791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block v8::HandleScope scope; 759791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block LocalContext env; 760791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block 761f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CompileRun( 762791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block "function A() {}\n" 763791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block "function B(x) { this.x = x; }\n" 764791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block "var a = new A();\n" 765791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block "var b = new B(a);"); 766791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block const v8::HeapSnapshot* snapshot = 767791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block v8::HeapProfiler::TakeSnapshot( 768791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block v8::String::New("agg"), v8::HeapSnapshot::kAggregated); 769791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block const v8::HeapGraphNode* strings = GetChild(snapshot->GetRoot(), 7708a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang v8::HeapGraphNode::kHidden, 771791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block "STRING_TYPE"); 772791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_NE(NULL, strings); 773791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_NE(0, strings->GetSelfSize()); 774791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_NE(0, strings->GetInstancesCount()); 775791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block const v8::HeapGraphNode* maps = GetChild(snapshot->GetRoot(), 7768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang v8::HeapGraphNode::kHidden, 777791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block "MAP_TYPE"); 778791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_NE(NULL, maps); 779791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_NE(0, maps->GetSelfSize()); 780791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_NE(0, maps->GetInstancesCount()); 781791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block 782791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block const v8::HeapGraphNode* a = GetChild(snapshot->GetRoot(), 783791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block v8::HeapGraphNode::kObject, 784791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block "A"); 785791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_NE(NULL, a); 786791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_NE(0, a->GetSelfSize()); 787791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_EQ(1, a->GetInstancesCount()); 788791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block 789791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block const v8::HeapGraphNode* b = GetChild(snapshot->GetRoot(), 790791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block v8::HeapGraphNode::kObject, 791791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block "B"); 792791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_NE(NULL, b); 793791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_NE(0, b->GetSelfSize()); 794791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_EQ(1, b->GetInstancesCount()); 795791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block 796791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block const v8::HeapGraphNode* glob_prop = GetChild(snapshot->GetRoot(), 797791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block v8::HeapGraphNode::kObject, 798791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block "(global property)", 799791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block b); 800791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_NE(NULL, glob_prop); 801791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_EQ(0, glob_prop->GetSelfSize()); 802791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_EQ(0, glob_prop->GetInstancesCount()); 803791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_NE(0, glob_prop->GetChildrenCount()); 804791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block 805791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block const v8::HeapGraphNode* a_from_glob_prop = GetChild( 806791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block glob_prop, 807791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block v8::HeapGraphNode::kObject, 808791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block "A"); 809791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_NE(NULL, a_from_glob_prop); 810791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_EQ(0, a_from_glob_prop->GetSelfSize()); 811791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_EQ(0, a_from_glob_prop->GetInstancesCount()); 812791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_EQ(0, a_from_glob_prop->GetChildrenCount()); // Retains nothing. 813791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK(IsNodeRetainedAs(a_from_glob_prop, 1)); // (global propery) has 1 ref. 814791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block 815791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block const v8::HeapGraphNode* b_with_children = GetChild( 816791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block snapshot->GetRoot(), 817791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block v8::HeapGraphNode::kObject, 818791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block "B", 819791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block b); 820791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_NE(NULL, b_with_children); 821791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_EQ(0, b_with_children->GetSelfSize()); 822791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_EQ(0, b_with_children->GetInstancesCount()); 823791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_NE(0, b_with_children->GetChildrenCount()); 824791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block 825791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block const v8::HeapGraphNode* a_from_b = GetChild( 826791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block b_with_children, 827791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block v8::HeapGraphNode::kObject, 828791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block "A"); 829791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_NE(NULL, a_from_b); 830791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_EQ(0, a_from_b->GetSelfSize()); 831791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_EQ(0, a_from_b->GetInstancesCount()); 832791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_EQ(0, a_from_b->GetChildrenCount()); // Retains nothing. 833791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK(IsNodeRetainedAs(a_from_b, 1)); // B has 1 ref to A. 834791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block} 835791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block 8368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 8378a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) WangTEST(HeapEntryDominator) { 8388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // The graph looks like this: 8398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // 8408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -> node1 8418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // a |^ 8428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -> node5 ba 8438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // a v| 8448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // node6 -> node2 8458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // b a |^ 8468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -> node4 ba 8478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // b v| 8488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -> node3 8498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // 8508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // The dominator for all nodes is node6. 8518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 8528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang v8::HandleScope scope; 8538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang LocalContext env; 8548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 8558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CompileRun( 8568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang "function X(a, b) { this.a = a; this.b = b; }\n" 8578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang "node6 = new X(new X(new X()), new X(new X(),new X()));\n" 8588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang "(function(){\n" 8598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang "node6.a.a.b = node6.b.a; // node1 -> node2\n" 8608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang "node6.b.a.a = node6.a.a; // node2 -> node1\n" 8618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang "node6.b.a.b = node6.b.b; // node2 -> node3\n" 8628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang "node6.b.b.a = node6.b.a; // node3 -> node2\n" 8638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang "})();"); 8648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 8658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const v8::HeapSnapshot* snapshot = 8668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang v8::HeapProfiler::TakeSnapshot(v8::String::New("dominators")); 8678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 8688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const v8::HeapGraphNode* global = GetGlobalObject(snapshot); 8698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_NE(NULL, global); 8708a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const v8::HeapGraphNode* node6 = 8718a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang GetProperty(global, v8::HeapGraphEdge::kShortcut, "node6"); 8728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_NE(NULL, node6); 8738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const v8::HeapGraphNode* node5 = 8748a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang GetProperty(node6, v8::HeapGraphEdge::kProperty, "a"); 8758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_NE(NULL, node5); 8768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const v8::HeapGraphNode* node4 = 8778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang GetProperty(node6, v8::HeapGraphEdge::kProperty, "b"); 8788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_NE(NULL, node4); 8798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const v8::HeapGraphNode* node3 = 8808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang GetProperty(node4, v8::HeapGraphEdge::kProperty, "b"); 8818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_NE(NULL, node3); 8828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const v8::HeapGraphNode* node2 = 8838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang GetProperty(node4, v8::HeapGraphEdge::kProperty, "a"); 8848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_NE(NULL, node2); 8858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const v8::HeapGraphNode* node1 = 8868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang GetProperty(node5, v8::HeapGraphEdge::kProperty, "a"); 8878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_NE(NULL, node1); 8888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 8898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_EQ(node6, node1->GetDominatorNode()); 8908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_EQ(node6, node2->GetDominatorNode()); 8918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_EQ(node6, node3->GetDominatorNode()); 8928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_EQ(node6, node4->GetDominatorNode()); 8938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_EQ(node6, node5->GetDominatorNode()); 8948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang} 8958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 8968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 8970d5e116f6aee03185f237311a943491bb079a768Kristian Monsennamespace { 8980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 8990d5e116f6aee03185f237311a943491bb079a768Kristian Monsenclass TestJSONStream : public v8::OutputStream { 9000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen public: 9010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen TestJSONStream() : eos_signaled_(0), abort_countdown_(-1) {} 9020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen explicit TestJSONStream(int abort_countdown) 9030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen : eos_signaled_(0), abort_countdown_(abort_countdown) {} 9040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen virtual ~TestJSONStream() {} 9050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen virtual void EndOfStream() { ++eos_signaled_; } 9060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen virtual WriteResult WriteAsciiChunk(char* buffer, int chars_written) { 9070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (abort_countdown_ > 0) --abort_countdown_; 9080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (abort_countdown_ == 0) return kAbort; 9090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CHECK_GT(chars_written, 0); 9100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen i::Vector<char> chunk = buffer_.AddBlock(chars_written, '\0'); 9110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen memcpy(chunk.start(), buffer, chars_written); 9120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen return kContinue; 9130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 9140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen void WriteTo(i::Vector<char> dest) { buffer_.WriteTo(dest); } 9150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int eos_signaled() { return eos_signaled_; } 9160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int size() { return buffer_.size(); } 9170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen private: 9180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen i::Collector<char> buffer_; 9190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int eos_signaled_; 9200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int abort_countdown_; 9210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}; 9220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 9230d5e116f6aee03185f237311a943491bb079a768Kristian Monsenclass AsciiResource: public v8::String::ExternalAsciiStringResource { 9240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen public: 9250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen explicit AsciiResource(i::Vector<char> string): data_(string.start()) { 9260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen length_ = string.length(); 9270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 9280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen virtual const char* data() const { return data_; } 9290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen virtual size_t length() const { return length_; } 9300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen private: 9310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen const char* data_; 9320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen size_t length_; 9330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}; 9340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 9350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} // namespace 9360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 9370d5e116f6aee03185f237311a943491bb079a768Kristian MonsenTEST(HeapSnapshotJSONSerialization) { 9380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen v8::HandleScope scope; 9390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen LocalContext env; 9400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 9410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen#define STRING_LITERAL_FOR_TEST \ 9420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "\"String \\n\\r\\u0008\\u0081\\u0101\\u0801\\u8001\"" 943f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CompileRun( 9440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "function A(s) { this.s = s; }\n" 9450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "function B(x) { this.x = x; }\n" 9460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "var a = new A(" STRING_LITERAL_FOR_TEST ");\n" 9470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "var b = new B(a);"); 9480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen const v8::HeapSnapshot* snapshot = 9490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen v8::HeapProfiler::TakeSnapshot(v8::String::New("json")); 9500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen TestJSONStream stream; 9510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen snapshot->Serialize(&stream, v8::HeapSnapshot::kJSON); 9520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CHECK_GT(stream.size(), 0); 9530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CHECK_EQ(1, stream.eos_signaled()); 9540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen i::ScopedVector<char> json(stream.size()); 9550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen stream.WriteTo(json); 9560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 9570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Verify that snapshot string is valid JSON. 9580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AsciiResource json_res(json); 9590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen v8::Local<v8::String> json_string = v8::String::NewExternal(&json_res); 9600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen env->Global()->Set(v8::String::New("json_snapshot"), json_string); 9610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen v8::Local<v8::Value> snapshot_parse_result = CompileRun( 9620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "var parsed = JSON.parse(json_snapshot); true;"); 9630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CHECK(!snapshot_parse_result.IsEmpty()); 9640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 9650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Verify that snapshot object has required fields. 9660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen v8::Local<v8::Object> parsed_snapshot = 9670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen env->Global()->Get(v8::String::New("parsed"))->ToObject(); 9680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CHECK(parsed_snapshot->Has(v8::String::New("snapshot"))); 9690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CHECK(parsed_snapshot->Has(v8::String::New("nodes"))); 9700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CHECK(parsed_snapshot->Has(v8::String::New("strings"))); 9710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 9720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Get node and edge "member" offsets. 9730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen v8::Local<v8::Value> meta_analysis_result = CompileRun( 9748a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang "var parsed_meta = parsed.nodes[0];\n" 9750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "var children_count_offset =" 9760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " parsed_meta.fields.indexOf('children_count');\n" 9770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "var children_offset =" 9780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " parsed_meta.fields.indexOf('children');\n" 9790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "var children_meta =" 9800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " parsed_meta.types[children_offset];\n" 9810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "var child_fields_count = children_meta.fields.length;\n" 9820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "var child_type_offset =" 9830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " children_meta.fields.indexOf('type');\n" 9840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "var child_name_offset =" 9850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " children_meta.fields.indexOf('name_or_index');\n" 9860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "var child_to_node_offset =" 9870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " children_meta.fields.indexOf('to_node');\n" 9880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "var property_type =" 9898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang " children_meta.types[child_type_offset].indexOf('property');\n" 9908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang "var shortcut_type =" 9918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang " children_meta.types[child_type_offset].indexOf('shortcut');"); 9920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CHECK(!meta_analysis_result.IsEmpty()); 9930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 9940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // A helper function for processing encoded nodes. 9950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CompileRun( 9968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang "function GetChildPosByProperty(pos, prop_name, prop_type) {\n" 9970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " var nodes = parsed.nodes;\n" 9980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " var strings = parsed.strings;\n" 9990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " for (var i = 0,\n" 10000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " count = nodes[pos + children_count_offset] * child_fields_count;\n" 10010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " i < count; i += child_fields_count) {\n" 10020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " var child_pos = pos + children_offset + i;\n" 10038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang " if (nodes[child_pos + child_type_offset] === prop_type\n" 10040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " && strings[nodes[child_pos + child_name_offset]] === prop_name)\n" 10050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " return nodes[child_pos + child_to_node_offset];\n" 10060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " }\n" 10070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " return null;\n" 10080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "}\n"); 10090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Get the string index using the path: <root> -> <global>.b.x.s 10100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen v8::Local<v8::Value> string_obj_pos_val = CompileRun( 10110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "GetChildPosByProperty(\n" 10120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " GetChildPosByProperty(\n" 10130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " GetChildPosByProperty(" 10148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang " parsed.nodes[1 + children_offset + child_to_node_offset]," 10158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang " \"b\",shortcut_type),\n" 10168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang " \"x\", property_type)," 10178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang " \"s\", property_type)"); 10180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CHECK(!string_obj_pos_val.IsEmpty()); 10190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int string_obj_pos = 10200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen static_cast<int>(string_obj_pos_val->ToNumber()->Value()); 10210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen v8::Local<v8::Object> nodes_array = 10220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen parsed_snapshot->Get(v8::String::New("nodes"))->ToObject(); 10230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int string_index = static_cast<int>( 10240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen nodes_array->Get(string_obj_pos + 1)->ToNumber()->Value()); 10250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CHECK_GT(string_index, 0); 10260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen v8::Local<v8::Object> strings_array = 10270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen parsed_snapshot->Get(v8::String::New("strings"))->ToObject(); 10280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen v8::Local<v8::String> string = strings_array->Get(string_index)->ToString(); 10290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen v8::Local<v8::String> ref_string = 10300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CompileRun(STRING_LITERAL_FOR_TEST)->ToString(); 10310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen#undef STRING_LITERAL_FOR_TEST 10320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CHECK_EQ(*v8::String::Utf8Value(ref_string), 10330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen *v8::String::Utf8Value(string)); 10340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 10350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 10360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 10370d5e116f6aee03185f237311a943491bb079a768Kristian MonsenTEST(HeapSnapshotJSONSerializationAborting) { 10380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen v8::HandleScope scope; 10390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen LocalContext env; 10400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen const v8::HeapSnapshot* snapshot = 10410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen v8::HeapProfiler::TakeSnapshot(v8::String::New("abort")); 10420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen TestJSONStream stream(5); 10430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen snapshot->Serialize(&stream, v8::HeapSnapshot::kJSON); 10440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CHECK_GT(stream.size(), 0); 10450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CHECK_EQ(0, stream.eos_signaled()); 10460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 10470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 10488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 10498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang// Must not crash in debug mode. 10508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) WangTEST(AggregatedHeapSnapshotJSONSerialization) { 10518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang v8::HandleScope scope; 10528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang LocalContext env; 10538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 10548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const v8::HeapSnapshot* snapshot = 10558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang v8::HeapProfiler::TakeSnapshot( 10568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang v8::String::New("agg"), v8::HeapSnapshot::kAggregated); 10578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang TestJSONStream stream; 10588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang snapshot->Serialize(&stream, v8::HeapSnapshot::kJSON); 10598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_GT(stream.size(), 0); 10608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_EQ(1, stream.eos_signaled()); 10618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang} 10628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 1063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochTEST(HeapSnapshotGetNodeById) { 1065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch v8::HandleScope scope; 1066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LocalContext env; 1067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const v8::HeapSnapshot* snapshot = 1069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch v8::HeapProfiler::TakeSnapshot(v8::String::New("id")); 1070b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const v8::HeapGraphNode* root = snapshot->GetRoot(); 1071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CHECK_EQ(root, snapshot->GetNodeById(root->GetId())); 1072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0, count = root->GetChildrenCount(); i < count; ++i) { 1073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const v8::HeapGraphEdge* prop = root->GetChild(i); 1074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CHECK_EQ( 1075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch prop->GetToNode(), snapshot->GetNodeById(prop->GetToNode()->GetId())); 1076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check a big id, which should not exist yet. 1078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CHECK_EQ(NULL, snapshot->GetNodeById(0x1000000UL)); 1079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochnamespace { 1083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass TestActivityControl : public v8::ActivityControl { 1085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public: 1086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch explicit TestActivityControl(int abort_count) 1087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : done_(0), total_(0), abort_count_(abort_count) {} 1088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ControlOption ReportProgressValue(int done, int total) { 1089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch done_ = done; 1090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch total_ = total; 1091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return --abort_count_ != 0 ? kContinue : kAbort; 1092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int done() { return done_; } 1094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int total() { return total_; } 1095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private: 1097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int done_; 1098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int total_; 1099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int abort_count_; 1100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}; 1101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochTEST(TakeHeapSnapshotAborting) { 1104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch v8::HandleScope scope; 1105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LocalContext env; 1106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const int snapshots_count = v8::HeapProfiler::GetSnapshotsCount(); 1108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TestActivityControl aborting_control(3); 1109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const v8::HeapSnapshot* no_snapshot = 1110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch v8::HeapProfiler::TakeSnapshot(v8::String::New("abort"), 1111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch v8::HeapSnapshot::kFull, 1112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch &aborting_control); 1113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CHECK_EQ(NULL, no_snapshot); 1114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CHECK_EQ(snapshots_count, v8::HeapProfiler::GetSnapshotsCount()); 1115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CHECK_GT(aborting_control.total(), aborting_control.done()); 1116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TestActivityControl control(-1); // Don't abort. 1118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const v8::HeapSnapshot* snapshot = 1119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch v8::HeapProfiler::TakeSnapshot(v8::String::New("full"), 1120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch v8::HeapSnapshot::kFull, 1121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch &control); 1122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CHECK_NE(NULL, snapshot); 1123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CHECK_EQ(snapshots_count + 1, v8::HeapProfiler::GetSnapshotsCount()); 1124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CHECK_EQ(control.total(), control.done()); 1125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CHECK_GT(control.total(), 0); 1126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 112844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 112944f0eee88ff00398ff7f715fab053374d808c90dSteve Blocknamespace { 113044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 113144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass TestRetainedObjectInfo : public v8::RetainedObjectInfo { 113244f0eee88ff00398ff7f715fab053374d808c90dSteve Block public: 113344f0eee88ff00398ff7f715fab053374d808c90dSteve Block TestRetainedObjectInfo(int hash, 113444f0eee88ff00398ff7f715fab053374d808c90dSteve Block const char* label, 113544f0eee88ff00398ff7f715fab053374d808c90dSteve Block intptr_t element_count = -1, 113644f0eee88ff00398ff7f715fab053374d808c90dSteve Block intptr_t size = -1) 113744f0eee88ff00398ff7f715fab053374d808c90dSteve Block : disposed_(false), 113844f0eee88ff00398ff7f715fab053374d808c90dSteve Block hash_(hash), 113944f0eee88ff00398ff7f715fab053374d808c90dSteve Block label_(label), 114044f0eee88ff00398ff7f715fab053374d808c90dSteve Block element_count_(element_count), 114144f0eee88ff00398ff7f715fab053374d808c90dSteve Block size_(size) { 114244f0eee88ff00398ff7f715fab053374d808c90dSteve Block instances.Add(this); 114344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 114444f0eee88ff00398ff7f715fab053374d808c90dSteve Block virtual ~TestRetainedObjectInfo() {} 114544f0eee88ff00398ff7f715fab053374d808c90dSteve Block virtual void Dispose() { 114644f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK(!disposed_); 114744f0eee88ff00398ff7f715fab053374d808c90dSteve Block disposed_ = true; 114844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 114944f0eee88ff00398ff7f715fab053374d808c90dSteve Block virtual bool IsEquivalent(RetainedObjectInfo* other) { 115044f0eee88ff00398ff7f715fab053374d808c90dSteve Block return GetHash() == other->GetHash(); 115144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 115244f0eee88ff00398ff7f715fab053374d808c90dSteve Block virtual intptr_t GetHash() { return hash_; } 115344f0eee88ff00398ff7f715fab053374d808c90dSteve Block virtual const char* GetLabel() { return label_; } 115444f0eee88ff00398ff7f715fab053374d808c90dSteve Block virtual intptr_t GetElementCount() { return element_count_; } 115544f0eee88ff00398ff7f715fab053374d808c90dSteve Block virtual intptr_t GetSizeInBytes() { return size_; } 115644f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool disposed() { return disposed_; } 115744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 115844f0eee88ff00398ff7f715fab053374d808c90dSteve Block static v8::RetainedObjectInfo* WrapperInfoCallback( 115944f0eee88ff00398ff7f715fab053374d808c90dSteve Block uint16_t class_id, v8::Handle<v8::Value> wrapper) { 116044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (class_id == 1) { 116144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (wrapper->IsString()) { 116244f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::String::AsciiValue ascii(wrapper); 116344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (strcmp(*ascii, "AAA") == 0) 116444f0eee88ff00398ff7f715fab053374d808c90dSteve Block return new TestRetainedObjectInfo(1, "aaa", 100); 116544f0eee88ff00398ff7f715fab053374d808c90dSteve Block else if (strcmp(*ascii, "BBB") == 0) 116644f0eee88ff00398ff7f715fab053374d808c90dSteve Block return new TestRetainedObjectInfo(1, "aaa", 100); 116744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 116844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (class_id == 2) { 116944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (wrapper->IsString()) { 117044f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::String::AsciiValue ascii(wrapper); 117144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (strcmp(*ascii, "CCC") == 0) 117244f0eee88ff00398ff7f715fab053374d808c90dSteve Block return new TestRetainedObjectInfo(2, "ccc"); 117344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 117444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 117544f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK(false); 117644f0eee88ff00398ff7f715fab053374d808c90dSteve Block return NULL; 117744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 117844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 117944f0eee88ff00398ff7f715fab053374d808c90dSteve Block static i::List<TestRetainedObjectInfo*> instances; 118044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 118144f0eee88ff00398ff7f715fab053374d808c90dSteve Block private: 118244f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool disposed_; 118344f0eee88ff00398ff7f715fab053374d808c90dSteve Block int category_; 118444f0eee88ff00398ff7f715fab053374d808c90dSteve Block int hash_; 118544f0eee88ff00398ff7f715fab053374d808c90dSteve Block const char* label_; 118644f0eee88ff00398ff7f715fab053374d808c90dSteve Block intptr_t element_count_; 118744f0eee88ff00398ff7f715fab053374d808c90dSteve Block intptr_t size_; 118844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}; 118944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 119044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 119144f0eee88ff00398ff7f715fab053374d808c90dSteve Blocki::List<TestRetainedObjectInfo*> TestRetainedObjectInfo::instances; 119244f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 119344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 119444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 119544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic const v8::HeapGraphNode* GetNode(const v8::HeapGraphNode* parent, 119644f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::HeapGraphNode::Type type, 119744f0eee88ff00398ff7f715fab053374d808c90dSteve Block const char* name) { 119844f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (int i = 0, count = parent->GetChildrenCount(); i < count; ++i) { 119944f0eee88ff00398ff7f715fab053374d808c90dSteve Block const v8::HeapGraphNode* node = parent->GetChild(i)->GetToNode(); 120044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (node->GetType() == type && strcmp(name, 120144f0eee88ff00398ff7f715fab053374d808c90dSteve Block const_cast<i::HeapEntry*>( 120244f0eee88ff00398ff7f715fab053374d808c90dSteve Block reinterpret_cast<const i::HeapEntry*>(node))->name()) == 0) { 120344f0eee88ff00398ff7f715fab053374d808c90dSteve Block return node; 120444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 120544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 120644f0eee88ff00398ff7f715fab053374d808c90dSteve Block return NULL; 120744f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 120844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 120944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 121044f0eee88ff00398ff7f715fab053374d808c90dSteve BlockTEST(HeapSnapshotRetainedObjectInfo) { 121144f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::HandleScope scope; 121244f0eee88ff00398ff7f715fab053374d808c90dSteve Block LocalContext env; 121344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 121444f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::HeapProfiler::DefineWrapperClass( 121544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1, TestRetainedObjectInfo::WrapperInfoCallback); 121644f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::HeapProfiler::DefineWrapperClass( 121744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 2, TestRetainedObjectInfo::WrapperInfoCallback); 121844f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::Persistent<v8::String> p_AAA = 121944f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::Persistent<v8::String>::New(v8_str("AAA")); 122044f0eee88ff00398ff7f715fab053374d808c90dSteve Block p_AAA.SetWrapperClassId(1); 122144f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::Persistent<v8::String> p_BBB = 122244f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::Persistent<v8::String>::New(v8_str("BBB")); 122344f0eee88ff00398ff7f715fab053374d808c90dSteve Block p_BBB.SetWrapperClassId(1); 122444f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::Persistent<v8::String> p_CCC = 122544f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::Persistent<v8::String>::New(v8_str("CCC")); 122644f0eee88ff00398ff7f715fab053374d808c90dSteve Block p_CCC.SetWrapperClassId(2); 122744f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_EQ(0, TestRetainedObjectInfo::instances.length()); 122844f0eee88ff00398ff7f715fab053374d808c90dSteve Block const v8::HeapSnapshot* snapshot = 122944f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::HeapProfiler::TakeSnapshot(v8::String::New("retained")); 123044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 123144f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_EQ(3, TestRetainedObjectInfo::instances.length()); 123244f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (int i = 0; i < TestRetainedObjectInfo::instances.length(); ++i) { 123344f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK(TestRetainedObjectInfo::instances[i]->disposed()); 123444f0eee88ff00398ff7f715fab053374d808c90dSteve Block delete TestRetainedObjectInfo::instances[i]; 123544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 123644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 123744f0eee88ff00398ff7f715fab053374d808c90dSteve Block const v8::HeapGraphNode* natives = GetNode( 123844f0eee88ff00398ff7f715fab053374d808c90dSteve Block snapshot->GetRoot(), v8::HeapGraphNode::kObject, "(Native objects)"); 123944f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_NE(NULL, natives); 124044f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_EQ(2, natives->GetChildrenCount()); 124144f0eee88ff00398ff7f715fab053374d808c90dSteve Block const v8::HeapGraphNode* aaa = GetNode( 124244f0eee88ff00398ff7f715fab053374d808c90dSteve Block natives, v8::HeapGraphNode::kNative, "aaa / 100 entries"); 124344f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_NE(NULL, aaa); 124444f0eee88ff00398ff7f715fab053374d808c90dSteve Block const v8::HeapGraphNode* ccc = GetNode( 124544f0eee88ff00398ff7f715fab053374d808c90dSteve Block natives, v8::HeapGraphNode::kNative, "ccc"); 124644f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_NE(NULL, ccc); 124744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 124844f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_EQ(2, aaa->GetChildrenCount()); 124944f0eee88ff00398ff7f715fab053374d808c90dSteve Block const v8::HeapGraphNode* n_AAA = GetNode( 125044f0eee88ff00398ff7f715fab053374d808c90dSteve Block aaa, v8::HeapGraphNode::kString, "AAA"); 125144f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_NE(NULL, n_AAA); 125244f0eee88ff00398ff7f715fab053374d808c90dSteve Block const v8::HeapGraphNode* n_BBB = GetNode( 125344f0eee88ff00398ff7f715fab053374d808c90dSteve Block aaa, v8::HeapGraphNode::kString, "BBB"); 125444f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_NE(NULL, n_BBB); 125544f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_EQ(1, ccc->GetChildrenCount()); 125644f0eee88ff00398ff7f715fab053374d808c90dSteve Block const v8::HeapGraphNode* n_CCC = GetNode( 125744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ccc, v8::HeapGraphNode::kString, "CCC"); 125844f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_NE(NULL, n_CCC); 125944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 126044f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_EQ(aaa, GetProperty(n_AAA, v8::HeapGraphEdge::kInternal, "Native")); 126144f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_EQ(aaa, GetProperty(n_BBB, v8::HeapGraphEdge::kInternal, "Native")); 126244f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_EQ(ccc, GetProperty(n_CCC, v8::HeapGraphEdge::kInternal, "Native")); 126344f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 126444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 126544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 126644f0eee88ff00398ff7f715fab053374d808c90dSteve BlockTEST(DeleteAllHeapSnapshots) { 126744f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::HandleScope scope; 126844f0eee88ff00398ff7f715fab053374d808c90dSteve Block LocalContext env; 126944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 127044f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount()); 127144f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::HeapProfiler::DeleteAllSnapshots(); 127244f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount()); 127344f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_NE(NULL, v8::HeapProfiler::TakeSnapshot(v8::String::New("1"))); 127444f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_EQ(1, v8::HeapProfiler::GetSnapshotsCount()); 127544f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::HeapProfiler::DeleteAllSnapshots(); 127644f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount()); 127744f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_NE(NULL, v8::HeapProfiler::TakeSnapshot(v8::String::New("1"))); 127844f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_NE(NULL, v8::HeapProfiler::TakeSnapshot(v8::String::New("2"))); 127944f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_EQ(2, v8::HeapProfiler::GetSnapshotsCount()); 128044f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::HeapProfiler::DeleteAllSnapshots(); 128144f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount()); 128244f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 128344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 128444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 128544f0eee88ff00398ff7f715fab053374d808c90dSteve BlockTEST(DeleteHeapSnapshot) { 128644f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::HandleScope scope; 128744f0eee88ff00398ff7f715fab053374d808c90dSteve Block LocalContext env; 128844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 128944f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount()); 129044f0eee88ff00398ff7f715fab053374d808c90dSteve Block const v8::HeapSnapshot* s1 = 129144f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::HeapProfiler::TakeSnapshot(v8::String::New("1")); 129244f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_NE(NULL, s1); 129344f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_EQ(1, v8::HeapProfiler::GetSnapshotsCount()); 129444f0eee88ff00398ff7f715fab053374d808c90dSteve Block unsigned uid1 = s1->GetUid(); 129544f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_EQ(s1, v8::HeapProfiler::FindSnapshot(uid1)); 129644f0eee88ff00398ff7f715fab053374d808c90dSteve Block const_cast<v8::HeapSnapshot*>(s1)->Delete(); 129744f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount()); 129844f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_EQ(NULL, v8::HeapProfiler::FindSnapshot(uid1)); 129944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 130044f0eee88ff00398ff7f715fab053374d808c90dSteve Block const v8::HeapSnapshot* s2 = 130144f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::HeapProfiler::TakeSnapshot(v8::String::New("2")); 130244f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_NE(NULL, s2); 130344f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_EQ(1, v8::HeapProfiler::GetSnapshotsCount()); 130444f0eee88ff00398ff7f715fab053374d808c90dSteve Block unsigned uid2 = s2->GetUid(); 130544f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid2)); 130644f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_EQ(s2, v8::HeapProfiler::FindSnapshot(uid2)); 130744f0eee88ff00398ff7f715fab053374d808c90dSteve Block const v8::HeapSnapshot* s3 = 130844f0eee88ff00398ff7f715fab053374d808c90dSteve Block v8::HeapProfiler::TakeSnapshot(v8::String::New("3")); 130944f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_NE(NULL, s3); 131044f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_EQ(2, v8::HeapProfiler::GetSnapshotsCount()); 131144f0eee88ff00398ff7f715fab053374d808c90dSteve Block unsigned uid3 = s3->GetUid(); 131244f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid3)); 131344f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_EQ(s3, v8::HeapProfiler::FindSnapshot(uid3)); 131444f0eee88ff00398ff7f715fab053374d808c90dSteve Block const_cast<v8::HeapSnapshot*>(s2)->Delete(); 131544f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_EQ(1, v8::HeapProfiler::GetSnapshotsCount()); 131644f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_EQ(NULL, v8::HeapProfiler::FindSnapshot(uid2)); 131744f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_EQ(s3, v8::HeapProfiler::FindSnapshot(uid3)); 131844f0eee88ff00398ff7f715fab053374d808c90dSteve Block const_cast<v8::HeapSnapshot*>(s3)->Delete(); 131944f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount()); 132044f0eee88ff00398ff7f715fab053374d808c90dSteve Block CHECK_EQ(NULL, v8::HeapProfiler::FindSnapshot(uid3)); 132144f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 132244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // ENABLE_LOGGING_AND_PROFILING 1324