test-heap-profiler.cc revision 8a31eba00023874d4a1dcdc5f411cc4336776874
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(), 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block f_name_(i::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; 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster function(i::Heap::function_class_symbol()); 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster a(*i::Factory::NewStringFromAscii(i::CStrVector("A"))); 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster b(*i::Factory::NewStringFromAscii(i::CStrVector("B"))); 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // o1 <- Function 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o1 = 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x100, &function); 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // o2 <- Function 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o2 = 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x200, &function); 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // o3 <- A, B 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o3 = 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x300, &a, &b); 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // o4 <- B, A 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o4 = 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x400, &b, &a); 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // o5 <- A, B, Function 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o5 = 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::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; 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster function(i::Heap::function_class_symbol()); 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // o1 <- Function 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o1 = 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x100, &function); 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // a1 <- Function 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster a1 = 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Array_symbol(), 0x1000, &function); 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // o2 <- Function 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o2 = 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x200, &function); 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // a2 <- Function 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster a2 = 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::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 = 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x100); 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o11 = 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x110, &o); 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o12 = 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x120, &o); 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o21 = 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x210, &o11); 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o22 = 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x220, &o12); 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster p = 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x300, &o21); 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster q = 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x310, &o21, &o22); 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster r = 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::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 = 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x100); 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o1 = 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x110, &o); 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o2 = 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x120, &o); 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster p = 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x300, &o1); 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddSelfReferenceToTree(&tree, &p); 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster q = 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x310, &o1, &o2); 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddSelfReferenceToTree(&tree, &q); 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster r = 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::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 4363bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochstatic bool IsNodeRetainedAs(const v8::HeapGraphNode* node, 4373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch v8::HeapGraphEdge::Type type, 4383bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const char* name) { 4393bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch for (int i = 0, count = node->GetRetainersCount(); i < count; ++i) { 4403bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const v8::HeapGraphEdge* prop = node->GetRetainer(i); 4413bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch v8::String::AsciiValue prop_name(prop->GetName()); 4423bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch if (prop->GetType() == type && strcmp(name, *prop_name) == 0) 4433bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch return true; 4443bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } 4453bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch return false; 4463bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch} 4473bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 4483bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 4499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenstatic bool HasString(const v8::HeapGraphNode* node, const char* contents) { 4509dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) { 4519dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphEdge* prop = node->GetChild(i); 4529dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphNode* node = prop->GetToNode(); 453756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (node->GetType() == v8::HeapGraphNode::kString) { 4549dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen v8::String::AsciiValue node_name(node->GetName()); 4559dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (strcmp(contents, *node_name) == 0) return true; 4569dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 4579dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 4589dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen return false; 4599dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 4609dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 4619dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 4629dcf7e2f83591d471e88bf7d230651900b8e424bKristian MonsenTEST(HeapSnapshot) { 4639dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen v8::HandleScope scope; 4643bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch LocalContext env2; 4659dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 466f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CompileRun( 4679dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen "function A2() {}\n" 4689dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen "function B2(x) { return function() { return typeof x; }; }\n" 4699dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen "function C2(x) { this.x1 = x; this.x2 = x; this[1] = x; }\n" 4709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen "var a2 = new A2();\n" 4719dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen "var b2_1 = new B2(a2), b2_2 = new B2(a2);\n" 4729dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen "var c2 = new C2(a2);"); 4739dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapSnapshot* snapshot_env2 = 4749dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen v8::HeapProfiler::TakeSnapshot(v8::String::New("env2")); 475756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick i::HeapSnapshot* i_snapshot_env2 = 476756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick const_cast<i::HeapSnapshot*>( 477756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick reinterpret_cast<const i::HeapSnapshot*>(snapshot_env2)); 4789dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphNode* global_env2 = GetGlobalObject(snapshot_env2); 479756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Paint all nodes reachable from global object. 480756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick i_snapshot_env2->ClearPaint(); 481756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick const_cast<i::HeapEntry*>( 482756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick reinterpret_cast<const i::HeapEntry*>(global_env2))->PaintAllReachable(); 4839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 48490bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner // Verify, that JS global object of env2 has '..2' properties. 4859dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphNode* a2_node = 4868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "a2"); 4879dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK_NE(NULL, a2_node); 488756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_NE( 4898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "b2_1")); 490756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_NE( 4918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "b2_2")); 4928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_NE(NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "c2")); 4939dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 4949dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen NamedEntriesDetector det; 4959dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen i_snapshot_env2->IterateEntries(&det); 4969dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK(det.has_A2); 4979dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK(det.has_B2); 4989dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK(det.has_C2); 4999dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 5008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang /* 5018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Currently disabled. Too many retaining paths emerge, need to 5028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // reduce the amount. 5038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 5049dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Verify 'a2' object retainers. They are: 5059dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // - (global object).a2 5069dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // - c2.x1, c2.x2, c2[1] 5079dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // - b2_1 and b2_2 closures: via 'x' variable 5089dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK_EQ(6, a2_node->GetRetainingPathsCount()); 5099dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen bool has_global_obj_a2_ref = false; 5109dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen bool has_c2_x1_ref = false, has_c2_x2_ref = false, has_c2_1_ref = false; 5119dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen bool has_b2_1_x_ref = false, has_b2_2_x_ref = false; 5129dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen for (int i = 0; i < a2_node->GetRetainingPathsCount(); ++i) { 5139dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphPath* path = a2_node->GetRetainingPath(i); 5149dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const int edges_count = path->GetEdgesCount(); 5159dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK_GT(edges_count, 0); 5169dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphEdge* last_edge = path->GetEdge(edges_count - 1); 5179dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen v8::String::AsciiValue last_edge_name(last_edge->GetName()); 5189dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (strcmp("a2", *last_edge_name) == 0 519756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick && last_edge->GetType() == v8::HeapGraphEdge::kProperty) { 5209dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen has_global_obj_a2_ref = true; 5219dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen continue; 5229dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 5239dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK_GT(edges_count, 1); 5249dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphEdge* prev_edge = path->GetEdge(edges_count - 2); 5259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen v8::String::AsciiValue prev_edge_name(prev_edge->GetName()); 5269dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (strcmp("x1", *last_edge_name) == 0 527756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick && last_edge->GetType() == v8::HeapGraphEdge::kProperty 5289dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen && strcmp("c2", *prev_edge_name) == 0) has_c2_x1_ref = true; 5299dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (strcmp("x2", *last_edge_name) == 0 530756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick && last_edge->GetType() == v8::HeapGraphEdge::kProperty 5319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen && strcmp("c2", *prev_edge_name) == 0) has_c2_x2_ref = true; 5329dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (strcmp("1", *last_edge_name) == 0 533756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick && last_edge->GetType() == v8::HeapGraphEdge::kElement 5349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen && strcmp("c2", *prev_edge_name) == 0) has_c2_1_ref = true; 5359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (strcmp("x", *last_edge_name) == 0 536756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick && last_edge->GetType() == v8::HeapGraphEdge::kContextVariable 5379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen && strcmp("b2_1", *prev_edge_name) == 0) has_b2_1_x_ref = true; 5389dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (strcmp("x", *last_edge_name) == 0 539756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick && last_edge->GetType() == v8::HeapGraphEdge::kContextVariable 5409dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen && strcmp("b2_2", *prev_edge_name) == 0) has_b2_2_x_ref = true; 5419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 5429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK(has_global_obj_a2_ref); 5439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK(has_c2_x1_ref); 5449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK(has_c2_x2_ref); 5459dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK(has_c2_1_ref); 5469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK(has_b2_1_x_ref); 5479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK(has_b2_2_x_ref); 5488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang */ 5499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 5509dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 5519dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 552756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain MerrickTEST(HeapSnapshotObjectSizes) { 553756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick v8::HandleScope scope; 554756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick LocalContext env; 555756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 556756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // -a-> X1 --a 557756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // x -b-> X2 <-| 558f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CompileRun( 559756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick "function X(a, b) { this.a = a; this.b = b; }\n" 560756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick "x = new X(new X(), new X());\n" 5618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang "(function() { x.a.a = x.b; })();"); 562756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick const v8::HeapSnapshot* snapshot = 563756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick v8::HeapProfiler::TakeSnapshot(v8::String::New("sizes")); 564756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick const v8::HeapGraphNode* global = GetGlobalObject(snapshot); 565756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick const v8::HeapGraphNode* x = 5668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang GetProperty(global, v8::HeapGraphEdge::kShortcut, "x"); 567756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_NE(NULL, x); 568756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick const v8::HeapGraphNode* x1 = 569756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick GetProperty(x, v8::HeapGraphEdge::kProperty, "a"); 570756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_NE(NULL, x1); 571756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick const v8::HeapGraphNode* x2 = 572756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick GetProperty(x, v8::HeapGraphEdge::kProperty, "b"); 573756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_NE(NULL, x2); 5748a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 5758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Test approximate sizes. 5768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_EQ(x->GetSelfSize() * 3, x->GetRetainedSize(false)); 5778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_EQ(x1->GetSelfSize(), x1->GetRetainedSize(false)); 5788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_EQ(x2->GetSelfSize(), x2->GetRetainedSize(false)); 5798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Test exact sizes. 5808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_EQ(x->GetSelfSize() * 3, x->GetRetainedSize(true)); 5818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_EQ(x1->GetSelfSize(), x1->GetRetainedSize(true)); 5828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_EQ(x2->GetSelfSize(), x2->GetRetainedSize(true)); 583756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick} 584756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 585756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 586756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain MerrickTEST(HeapSnapshotEntryChildren) { 587756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick v8::HandleScope scope; 588756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick LocalContext env; 589756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 590f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CompileRun( 591756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick "function A() { }\n" 592756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick "a = new A;"); 593756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick const v8::HeapSnapshot* snapshot = 594756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick v8::HeapProfiler::TakeSnapshot(v8::String::New("children")); 595756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick const v8::HeapGraphNode* global = GetGlobalObject(snapshot); 596756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick for (int i = 0, count = global->GetChildrenCount(); i < count; ++i) { 597756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick const v8::HeapGraphEdge* prop = global->GetChild(i); 598756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_EQ(global, prop->GetFromNode()); 599756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 600756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick const v8::HeapGraphNode* a = 601756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick GetProperty(global, v8::HeapGraphEdge::kProperty, "a"); 602756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_NE(NULL, a); 603756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick for (int i = 0, count = a->GetChildrenCount(); i < count; ++i) { 604756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick const v8::HeapGraphEdge* prop = a->GetChild(i); 605756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_EQ(a, prop->GetFromNode()); 606756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 607756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick} 608756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 609756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 6109dcf7e2f83591d471e88bf7d230651900b8e424bKristian MonsenTEST(HeapSnapshotCodeObjects) { 6119dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen v8::HandleScope scope; 6123bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch LocalContext env; 6139dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 614f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CompileRun( 6159dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen "function lazy(x) { return x - 1; }\n" 6169dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen "function compiled(x) { return x + 1; }\n" 617791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block "var anonymous = (function() { return function() { return 0; } })();\n" 6189dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen "compiled(1)"); 6199dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapSnapshot* snapshot = 6209dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen v8::HeapProfiler::TakeSnapshot(v8::String::New("code")); 6219dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 6229dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphNode* global = GetGlobalObject(snapshot); 6239dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphNode* compiled = 6248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang GetProperty(global, v8::HeapGraphEdge::kShortcut, "compiled"); 6259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK_NE(NULL, compiled); 626756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_EQ(v8::HeapGraphNode::kClosure, compiled->GetType()); 6279dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphNode* lazy = 6288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang GetProperty(global, v8::HeapGraphEdge::kShortcut, "lazy"); 6299dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK_NE(NULL, lazy); 630756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_EQ(v8::HeapGraphNode::kClosure, lazy->GetType()); 631791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block const v8::HeapGraphNode* anonymous = 6328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang GetProperty(global, v8::HeapGraphEdge::kShortcut, "anonymous"); 633791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_NE(NULL, anonymous); 634791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_EQ(v8::HeapGraphNode::kClosure, anonymous->GetType()); 635791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block v8::String::AsciiValue anonymous_name(anonymous->GetName()); 636f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CHECK_EQ("", *anonymous_name); 6379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 6389dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Find references to code. 6399dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphNode* compiled_code = 640756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick GetProperty(compiled, v8::HeapGraphEdge::kInternal, "code"); 6419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK_NE(NULL, compiled_code); 6429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphNode* lazy_code = 643756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick GetProperty(lazy, v8::HeapGraphEdge::kInternal, "code"); 6449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK_NE(NULL, lazy_code); 6459dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 6469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Verify that non-compiled code doesn't contain references to "x" 6473bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // literal, while compiled code does. The scope info is stored in FixedArray 6483bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // objects attached to the SharedFunctionInfo. 6499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen bool compiled_references_x = false, lazy_references_x = false; 6509dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen for (int i = 0, count = compiled_code->GetChildrenCount(); i < count; ++i) { 6519dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphEdge* prop = compiled_code->GetChild(i); 6529dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphNode* node = prop->GetToNode(); 653756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (node->GetType() == v8::HeapGraphNode::kArray) { 6549dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (HasString(node, "x")) { 6559dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen compiled_references_x = true; 6569dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen break; 6579dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 6589dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 6599dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 6609dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen for (int i = 0, count = lazy_code->GetChildrenCount(); i < count; ++i) { 6619dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphEdge* prop = lazy_code->GetChild(i); 6629dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphNode* node = prop->GetToNode(); 663756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (node->GetType() == v8::HeapGraphNode::kArray) { 6649dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (HasString(node, "x")) { 6659dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen lazy_references_x = true; 6669dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen break; 6679dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 6689dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 6699dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 6709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK(compiled_references_x); 6719dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK(!lazy_references_x); 6729dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 6739dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 6743bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 675f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochTEST(HeapSnapshotHeapNumbers) { 676f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch v8::HandleScope scope; 677f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch LocalContext env; 678f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CompileRun( 679f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch "a = 1; // a is Smi\n" 680f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch "b = 2.5; // b is HeapNumber"); 681f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch const v8::HeapSnapshot* snapshot = 682f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch v8::HeapProfiler::TakeSnapshot(v8::String::New("numbers")); 683f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch const v8::HeapGraphNode* global = GetGlobalObject(snapshot); 6848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_EQ(NULL, GetProperty(global, v8::HeapGraphEdge::kShortcut, "a")); 685f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch const v8::HeapGraphNode* b = 6868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang GetProperty(global, v8::HeapGraphEdge::kShortcut, "b"); 687f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CHECK_NE(NULL, b); 688f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CHECK_EQ(v8::HeapGraphNode::kHeapNumber, b->GetType()); 689f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch} 690f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 691f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 692f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochTEST(HeapSnapshotInternalReferences) { 693f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch v8::HandleScope scope; 694f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch v8::Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(); 695f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch global_template->SetInternalFieldCount(2); 696f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch LocalContext env(NULL, global_template); 697f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch v8::Handle<v8::Object> global_proxy = env->Global(); 698f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch v8::Handle<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>(); 699f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CHECK_EQ(2, global->InternalFieldCount()); 700f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch v8::Local<v8::Object> obj = v8::Object::New(); 701f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch global->SetInternalField(0, v8_num(17)); 702f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch global->SetInternalField(1, obj); 703f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch const v8::HeapSnapshot* snapshot = 704f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch v8::HeapProfiler::TakeSnapshot(v8::String::New("internals")); 705f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch const v8::HeapGraphNode* global_node = GetGlobalObject(snapshot); 706f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // The first reference will not present, because it's a Smi. 707f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CHECK_EQ(NULL, GetProperty(global_node, v8::HeapGraphEdge::kInternal, "0")); 708f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // The second reference is to an object. 709f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CHECK_NE(NULL, GetProperty(global_node, v8::HeapGraphEdge::kInternal, "1")); 710f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch} 711f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 712f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 7133bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// Trying to introduce a check helper for uint64_t causes many 7143bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// overloading ambiguities, so it seems easier just to cast 7153bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// them to a signed type. 7163bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch#define CHECK_EQ_UINT64_T(a, b) \ 7173bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CHECK_EQ(static_cast<int64_t>(a), static_cast<int64_t>(b)) 718756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick#define CHECK_NE_UINT64_T(a, b) \ 719756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK((a) != (b)) // NOLINT 7203bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 7213bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben MurdochTEST(HeapEntryIdsAndGC) { 7223bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch v8::HandleScope scope; 7233bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch LocalContext env; 7243bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 725f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CompileRun( 7263bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch "function A() {}\n" 7273bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch "function B(x) { this.x = x; }\n" 7283bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch "var a = new A();\n" 7293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch "var b = new B(a);"); 7303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const v8::HeapSnapshot* snapshot1 = 7313bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch v8::HeapProfiler::TakeSnapshot(v8::String::New("s1")); 7323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 7333bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch i::Heap::CollectAllGarbage(true); // Enforce compaction. 7343bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 7353bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const v8::HeapSnapshot* snapshot2 = 7363bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch v8::HeapProfiler::TakeSnapshot(v8::String::New("s2")); 7373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 7383bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const v8::HeapGraphNode* global1 = GetGlobalObject(snapshot1); 7393bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const v8::HeapGraphNode* global2 = GetGlobalObject(snapshot2); 7403bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CHECK_NE_UINT64_T(0, global1->GetId()); 7413bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CHECK_EQ_UINT64_T(global1->GetId(), global2->GetId()); 7423bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const v8::HeapGraphNode* A1 = 743756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick GetProperty(global1, v8::HeapGraphEdge::kProperty, "A"); 744756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_NE(NULL, A1); 7453bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const v8::HeapGraphNode* A2 = 746756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick GetProperty(global2, v8::HeapGraphEdge::kProperty, "A"); 747756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_NE(NULL, A2); 7483bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CHECK_NE_UINT64_T(0, A1->GetId()); 7493bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CHECK_EQ_UINT64_T(A1->GetId(), A2->GetId()); 7503bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const v8::HeapGraphNode* B1 = 751756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick GetProperty(global1, v8::HeapGraphEdge::kProperty, "B"); 752756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_NE(NULL, B1); 7533bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const v8::HeapGraphNode* B2 = 754756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick GetProperty(global2, v8::HeapGraphEdge::kProperty, "B"); 755756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_NE(NULL, B2); 7563bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CHECK_NE_UINT64_T(0, B1->GetId()); 7573bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CHECK_EQ_UINT64_T(B1->GetId(), B2->GetId()); 7583bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const v8::HeapGraphNode* a1 = 759756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick GetProperty(global1, v8::HeapGraphEdge::kProperty, "a"); 760756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_NE(NULL, a1); 7613bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const v8::HeapGraphNode* a2 = 762756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick GetProperty(global2, v8::HeapGraphEdge::kProperty, "a"); 763756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_NE(NULL, a2); 7643bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CHECK_NE_UINT64_T(0, a1->GetId()); 7653bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CHECK_EQ_UINT64_T(a1->GetId(), a2->GetId()); 7663bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const v8::HeapGraphNode* b1 = 767756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick GetProperty(global1, v8::HeapGraphEdge::kProperty, "b"); 768756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_NE(NULL, b1); 7693bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const v8::HeapGraphNode* b2 = 770756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick GetProperty(global2, v8::HeapGraphEdge::kProperty, "b"); 771756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick CHECK_NE(NULL, b2); 7723bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CHECK_NE_UINT64_T(0, b1->GetId()); 7733bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CHECK_EQ_UINT64_T(b1->GetId(), b2->GetId()); 7743bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch} 7753bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 7763bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 7773bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben MurdochTEST(HeapSnapshotsDiff) { 7783bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch v8::HandleScope scope; 7793bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch LocalContext env; 7803bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 781f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CompileRun( 7823bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch "function A() {}\n" 7833bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch "function B(x) { this.x = x; }\n" 784f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch "function A2(a) { for (var i = 0; i < a; ++i) this[i] = i; }\n" 7853bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch "var a = new A();\n" 7863bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch "var b = new B(a);"); 7873bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const v8::HeapSnapshot* snapshot1 = 7883bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch v8::HeapProfiler::TakeSnapshot(v8::String::New("s1")); 7893bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 790f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CompileRun( 7913bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch "delete a;\n" 7923bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch "b.x = null;\n" 793f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch "var a = new A2(20);\n" 7943bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch "var b2 = new B(a);"); 7953bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const v8::HeapSnapshot* snapshot2 = 7963bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch v8::HeapProfiler::TakeSnapshot(v8::String::New("s2")); 7973bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 7983bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const v8::HeapSnapshotsDiff* diff = snapshot1->CompareWith(snapshot2); 7993bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 8003bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Verify additions: ensure that addition of A and B was detected. 8013bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const v8::HeapGraphNode* additions_root = diff->GetAdditionsRoot(); 8023bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch bool found_A = false, found_B = false; 8033bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch uint64_t s1_A_id = 0; 8043bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch for (int i = 0, count = additions_root->GetChildrenCount(); i < count; ++i) { 8053bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const v8::HeapGraphEdge* prop = additions_root->GetChild(i); 8063bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const v8::HeapGraphNode* node = prop->GetToNode(); 807756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (node->GetType() == v8::HeapGraphNode::kObject) { 8083bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch v8::String::AsciiValue node_name(node->GetName()); 809f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if (strcmp(*node_name, "A2") == 0) { 8108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK(IsNodeRetainedAs(node, v8::HeapGraphEdge::kShortcut, "a")); 8113bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CHECK(!found_A); 8123bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch found_A = true; 8133bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch s1_A_id = node->GetId(); 8143bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } else if (strcmp(*node_name, "B") == 0) { 8158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK(IsNodeRetainedAs(node, v8::HeapGraphEdge::kShortcut, "b2")); 8163bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CHECK(!found_B); 8173bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch found_B = true; 8183bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } 8193bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } 8203bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } 8213bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CHECK(found_A); 8223bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CHECK(found_B); 8233bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 8243bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Verify deletions: ensure that deletion of A was detected. 8253bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const v8::HeapGraphNode* deletions_root = diff->GetDeletionsRoot(); 8263bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch bool found_A_del = false; 8273bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch uint64_t s2_A_id = 0; 8283bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch for (int i = 0, count = deletions_root->GetChildrenCount(); i < count; ++i) { 8293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const v8::HeapGraphEdge* prop = deletions_root->GetChild(i); 8303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const v8::HeapGraphNode* node = prop->GetToNode(); 831756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (node->GetType() == v8::HeapGraphNode::kObject) { 8323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch v8::String::AsciiValue node_name(node->GetName()); 8333bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch if (strcmp(*node_name, "A") == 0) { 8348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK(IsNodeRetainedAs(node, v8::HeapGraphEdge::kShortcut, "a")); 8353bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CHECK(!found_A_del); 8363bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch found_A_del = true; 8373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch s2_A_id = node->GetId(); 8383bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } 8393bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } 8403bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch } 8413bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CHECK(found_A_del); 8423bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CHECK_NE_UINT64_T(0, s1_A_id); 8433bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch CHECK(s1_A_id != s2_A_id); 8443bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch} 8453bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 846756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 847f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochTEST(HeapSnapshotRootPreservedAfterSorting) { 848f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch v8::HandleScope scope; 849f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch LocalContext env; 850f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch const v8::HeapSnapshot* snapshot = 851f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch v8::HeapProfiler::TakeSnapshot(v8::String::New("s")); 852f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch const v8::HeapGraphNode* root1 = snapshot->GetRoot(); 853f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch const_cast<i::HeapSnapshot*>(reinterpret_cast<const i::HeapSnapshot*>( 854f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch snapshot))->GetSortedEntriesList(); 855f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch const v8::HeapGraphNode* root2 = snapshot->GetRoot(); 856f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CHECK_EQ(root1, root2); 857f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch} 858f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 859f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 860791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockstatic const v8::HeapGraphNode* GetChild( 861791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block const v8::HeapGraphNode* node, 862791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block v8::HeapGraphNode::Type type, 863791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block const char* name, 864791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block const v8::HeapGraphNode* after = NULL) { 865791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block bool ignore_child = after == NULL ? false : true; 866791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) { 867791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block const v8::HeapGraphEdge* prop = node->GetChild(i); 868791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block const v8::HeapGraphNode* child = prop->GetToNode(); 869791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block v8::String::AsciiValue child_name(child->GetName()); 870791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block if (!ignore_child 871791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block && child->GetType() == type 872791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block && strcmp(name, *child_name) == 0) 873791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block return child; 874791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block if (after != NULL && child == after) ignore_child = false; 875791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block } 876791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block return NULL; 877791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block} 878791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block 879791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Blockstatic bool IsNodeRetainedAs(const v8::HeapGraphNode* node, 880791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block int element) { 881791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block for (int i = 0, count = node->GetRetainersCount(); i < count; ++i) { 882791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block const v8::HeapGraphEdge* prop = node->GetRetainer(i); 883791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block if (prop->GetType() == v8::HeapGraphEdge::kElement 884791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block && element == prop->GetName()->Int32Value()) 885791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block return true; 886791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block } 887791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block return false; 888791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block} 889791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block 890791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve BlockTEST(AggregatedHeapSnapshot) { 891791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block v8::HandleScope scope; 892791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block LocalContext env; 893791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block 894f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CompileRun( 895791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block "function A() {}\n" 896791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block "function B(x) { this.x = x; }\n" 897791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block "var a = new A();\n" 898791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block "var b = new B(a);"); 899791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block const v8::HeapSnapshot* snapshot = 900791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block v8::HeapProfiler::TakeSnapshot( 901791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block v8::String::New("agg"), v8::HeapSnapshot::kAggregated); 902791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block const v8::HeapGraphNode* strings = GetChild(snapshot->GetRoot(), 9038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang v8::HeapGraphNode::kHidden, 904791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block "STRING_TYPE"); 905791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_NE(NULL, strings); 906791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_NE(0, strings->GetSelfSize()); 907791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_NE(0, strings->GetInstancesCount()); 908791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block const v8::HeapGraphNode* maps = GetChild(snapshot->GetRoot(), 9098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang v8::HeapGraphNode::kHidden, 910791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block "MAP_TYPE"); 911791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_NE(NULL, maps); 912791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_NE(0, maps->GetSelfSize()); 913791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_NE(0, maps->GetInstancesCount()); 914791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block 915791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block const v8::HeapGraphNode* a = GetChild(snapshot->GetRoot(), 916791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block v8::HeapGraphNode::kObject, 917791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block "A"); 918791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_NE(NULL, a); 919791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_NE(0, a->GetSelfSize()); 920791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_EQ(1, a->GetInstancesCount()); 921791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block 922791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block const v8::HeapGraphNode* b = GetChild(snapshot->GetRoot(), 923791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block v8::HeapGraphNode::kObject, 924791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block "B"); 925791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_NE(NULL, b); 926791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_NE(0, b->GetSelfSize()); 927791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_EQ(1, b->GetInstancesCount()); 928791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block 929791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block const v8::HeapGraphNode* glob_prop = GetChild(snapshot->GetRoot(), 930791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block v8::HeapGraphNode::kObject, 931791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block "(global property)", 932791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block b); 933791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_NE(NULL, glob_prop); 934791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_EQ(0, glob_prop->GetSelfSize()); 935791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_EQ(0, glob_prop->GetInstancesCount()); 936791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_NE(0, glob_prop->GetChildrenCount()); 937791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block 938791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block const v8::HeapGraphNode* a_from_glob_prop = GetChild( 939791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block glob_prop, 940791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block v8::HeapGraphNode::kObject, 941791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block "A"); 942791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_NE(NULL, a_from_glob_prop); 943791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_EQ(0, a_from_glob_prop->GetSelfSize()); 944791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_EQ(0, a_from_glob_prop->GetInstancesCount()); 945791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_EQ(0, a_from_glob_prop->GetChildrenCount()); // Retains nothing. 946791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK(IsNodeRetainedAs(a_from_glob_prop, 1)); // (global propery) has 1 ref. 947791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block 948791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block const v8::HeapGraphNode* b_with_children = GetChild( 949791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block snapshot->GetRoot(), 950791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block v8::HeapGraphNode::kObject, 951791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block "B", 952791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block b); 953791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_NE(NULL, b_with_children); 954791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_EQ(0, b_with_children->GetSelfSize()); 955791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_EQ(0, b_with_children->GetInstancesCount()); 956791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_NE(0, b_with_children->GetChildrenCount()); 957791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block 958791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block const v8::HeapGraphNode* a_from_b = GetChild( 959791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block b_with_children, 960791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block v8::HeapGraphNode::kObject, 961791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block "A"); 962791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_NE(NULL, a_from_b); 963791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_EQ(0, a_from_b->GetSelfSize()); 964791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_EQ(0, a_from_b->GetInstancesCount()); 965791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK_EQ(0, a_from_b->GetChildrenCount()); // Retains nothing. 966791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block CHECK(IsNodeRetainedAs(a_from_b, 1)); // B has 1 ref to A. 967791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block} 968791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block 9698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 9708a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) WangTEST(HeapEntryDominator) { 9718a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // The graph looks like this: 9728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // 9738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -> node1 9748a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // a |^ 9758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -> node5 ba 9768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // a v| 9778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // node6 -> node2 9788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // b a |^ 9798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -> node4 ba 9808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // b v| 9818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -> node3 9828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // 9838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // The dominator for all nodes is node6. 9848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 9858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang v8::HandleScope scope; 9868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang LocalContext env; 9878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 9888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CompileRun( 9898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang "function X(a, b) { this.a = a; this.b = b; }\n" 9908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang "node6 = new X(new X(new X()), new X(new X(),new X()));\n" 9918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang "(function(){\n" 9928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang "node6.a.a.b = node6.b.a; // node1 -> node2\n" 9938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang "node6.b.a.a = node6.a.a; // node2 -> node1\n" 9948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang "node6.b.a.b = node6.b.b; // node2 -> node3\n" 9958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang "node6.b.b.a = node6.b.a; // node3 -> node2\n" 9968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang "})();"); 9978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 9988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const v8::HeapSnapshot* snapshot = 9998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang v8::HeapProfiler::TakeSnapshot(v8::String::New("dominators")); 10008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 10018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const v8::HeapGraphNode* global = GetGlobalObject(snapshot); 10028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_NE(NULL, global); 10038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const v8::HeapGraphNode* node6 = 10048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang GetProperty(global, v8::HeapGraphEdge::kShortcut, "node6"); 10058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_NE(NULL, node6); 10068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const v8::HeapGraphNode* node5 = 10078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang GetProperty(node6, v8::HeapGraphEdge::kProperty, "a"); 10088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_NE(NULL, node5); 10098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const v8::HeapGraphNode* node4 = 10108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang GetProperty(node6, v8::HeapGraphEdge::kProperty, "b"); 10118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_NE(NULL, node4); 10128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const v8::HeapGraphNode* node3 = 10138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang GetProperty(node4, v8::HeapGraphEdge::kProperty, "b"); 10148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_NE(NULL, node3); 10158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const v8::HeapGraphNode* node2 = 10168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang GetProperty(node4, v8::HeapGraphEdge::kProperty, "a"); 10178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_NE(NULL, node2); 10188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const v8::HeapGraphNode* node1 = 10198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang GetProperty(node5, v8::HeapGraphEdge::kProperty, "a"); 10208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_NE(NULL, node1); 10218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 10228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_EQ(node6, node1->GetDominatorNode()); 10238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_EQ(node6, node2->GetDominatorNode()); 10248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_EQ(node6, node3->GetDominatorNode()); 10258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_EQ(node6, node4->GetDominatorNode()); 10268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_EQ(node6, node5->GetDominatorNode()); 10278a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang} 10288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 10298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 10300d5e116f6aee03185f237311a943491bb079a768Kristian Monsennamespace { 10310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 10320d5e116f6aee03185f237311a943491bb079a768Kristian Monsenclass TestJSONStream : public v8::OutputStream { 10330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen public: 10340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen TestJSONStream() : eos_signaled_(0), abort_countdown_(-1) {} 10350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen explicit TestJSONStream(int abort_countdown) 10360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen : eos_signaled_(0), abort_countdown_(abort_countdown) {} 10370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen virtual ~TestJSONStream() {} 10380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen virtual void EndOfStream() { ++eos_signaled_; } 10390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen virtual WriteResult WriteAsciiChunk(char* buffer, int chars_written) { 10400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (abort_countdown_ > 0) --abort_countdown_; 10410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (abort_countdown_ == 0) return kAbort; 10420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CHECK_GT(chars_written, 0); 10430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen i::Vector<char> chunk = buffer_.AddBlock(chars_written, '\0'); 10440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen memcpy(chunk.start(), buffer, chars_written); 10450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen return kContinue; 10460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 10470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen void WriteTo(i::Vector<char> dest) { buffer_.WriteTo(dest); } 10480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int eos_signaled() { return eos_signaled_; } 10490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int size() { return buffer_.size(); } 10500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen private: 10510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen i::Collector<char> buffer_; 10520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int eos_signaled_; 10530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int abort_countdown_; 10540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}; 10550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 10560d5e116f6aee03185f237311a943491bb079a768Kristian Monsenclass AsciiResource: public v8::String::ExternalAsciiStringResource { 10570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen public: 10580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen explicit AsciiResource(i::Vector<char> string): data_(string.start()) { 10590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen length_ = string.length(); 10600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 10610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen virtual const char* data() const { return data_; } 10620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen virtual size_t length() const { return length_; } 10630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen private: 10640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen const char* data_; 10650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen size_t length_; 10660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}; 10670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 10680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} // namespace 10690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 10700d5e116f6aee03185f237311a943491bb079a768Kristian MonsenTEST(HeapSnapshotJSONSerialization) { 10710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen v8::HandleScope scope; 10720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen LocalContext env; 10730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 10740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen#define STRING_LITERAL_FOR_TEST \ 10750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "\"String \\n\\r\\u0008\\u0081\\u0101\\u0801\\u8001\"" 1076f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CompileRun( 10770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "function A(s) { this.s = s; }\n" 10780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "function B(x) { this.x = x; }\n" 10790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "var a = new A(" STRING_LITERAL_FOR_TEST ");\n" 10800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "var b = new B(a);"); 10810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen const v8::HeapSnapshot* snapshot = 10820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen v8::HeapProfiler::TakeSnapshot(v8::String::New("json")); 10830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen TestJSONStream stream; 10840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen snapshot->Serialize(&stream, v8::HeapSnapshot::kJSON); 10850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CHECK_GT(stream.size(), 0); 10860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CHECK_EQ(1, stream.eos_signaled()); 10870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen i::ScopedVector<char> json(stream.size()); 10880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen stream.WriteTo(json); 10890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 10900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Verify that snapshot string is valid JSON. 10910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AsciiResource json_res(json); 10920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen v8::Local<v8::String> json_string = v8::String::NewExternal(&json_res); 10930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen env->Global()->Set(v8::String::New("json_snapshot"), json_string); 10940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen v8::Local<v8::Value> snapshot_parse_result = CompileRun( 10950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "var parsed = JSON.parse(json_snapshot); true;"); 10960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CHECK(!snapshot_parse_result.IsEmpty()); 10970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 10980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Verify that snapshot object has required fields. 10990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen v8::Local<v8::Object> parsed_snapshot = 11000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen env->Global()->Get(v8::String::New("parsed"))->ToObject(); 11010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CHECK(parsed_snapshot->Has(v8::String::New("snapshot"))); 11020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CHECK(parsed_snapshot->Has(v8::String::New("nodes"))); 11030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CHECK(parsed_snapshot->Has(v8::String::New("strings"))); 11040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 11050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Get node and edge "member" offsets. 11060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen v8::Local<v8::Value> meta_analysis_result = CompileRun( 11078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang "var parsed_meta = parsed.nodes[0];\n" 11080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "var children_count_offset =" 11090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " parsed_meta.fields.indexOf('children_count');\n" 11100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "var children_offset =" 11110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " parsed_meta.fields.indexOf('children');\n" 11120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "var children_meta =" 11130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " parsed_meta.types[children_offset];\n" 11140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "var child_fields_count = children_meta.fields.length;\n" 11150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "var child_type_offset =" 11160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " children_meta.fields.indexOf('type');\n" 11170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "var child_name_offset =" 11180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " children_meta.fields.indexOf('name_or_index');\n" 11190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "var child_to_node_offset =" 11200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " children_meta.fields.indexOf('to_node');\n" 11210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "var property_type =" 11228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang " children_meta.types[child_type_offset].indexOf('property');\n" 11238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang "var shortcut_type =" 11248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang " children_meta.types[child_type_offset].indexOf('shortcut');"); 11250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CHECK(!meta_analysis_result.IsEmpty()); 11260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 11270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // A helper function for processing encoded nodes. 11280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CompileRun( 11298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang "function GetChildPosByProperty(pos, prop_name, prop_type) {\n" 11300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " var nodes = parsed.nodes;\n" 11310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " var strings = parsed.strings;\n" 11320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " for (var i = 0,\n" 11330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " count = nodes[pos + children_count_offset] * child_fields_count;\n" 11340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " i < count; i += child_fields_count) {\n" 11350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " var child_pos = pos + children_offset + i;\n" 11368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang " if (nodes[child_pos + child_type_offset] === prop_type\n" 11370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " && strings[nodes[child_pos + child_name_offset]] === prop_name)\n" 11380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " return nodes[child_pos + child_to_node_offset];\n" 11390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " }\n" 11400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " return null;\n" 11410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "}\n"); 11420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Get the string index using the path: <root> -> <global>.b.x.s 11430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen v8::Local<v8::Value> string_obj_pos_val = CompileRun( 11440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen "GetChildPosByProperty(\n" 11450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " GetChildPosByProperty(\n" 11460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen " GetChildPosByProperty(" 11478a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang " parsed.nodes[1 + children_offset + child_to_node_offset]," 11488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang " \"b\",shortcut_type),\n" 11498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang " \"x\", property_type)," 11508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang " \"s\", property_type)"); 11510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CHECK(!string_obj_pos_val.IsEmpty()); 11520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int string_obj_pos = 11530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen static_cast<int>(string_obj_pos_val->ToNumber()->Value()); 11540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen v8::Local<v8::Object> nodes_array = 11550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen parsed_snapshot->Get(v8::String::New("nodes"))->ToObject(); 11560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int string_index = static_cast<int>( 11570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen nodes_array->Get(string_obj_pos + 1)->ToNumber()->Value()); 11580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CHECK_GT(string_index, 0); 11590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen v8::Local<v8::Object> strings_array = 11600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen parsed_snapshot->Get(v8::String::New("strings"))->ToObject(); 11610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen v8::Local<v8::String> string = strings_array->Get(string_index)->ToString(); 11620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen v8::Local<v8::String> ref_string = 11630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CompileRun(STRING_LITERAL_FOR_TEST)->ToString(); 11640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen#undef STRING_LITERAL_FOR_TEST 11650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CHECK_EQ(*v8::String::Utf8Value(ref_string), 11660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen *v8::String::Utf8Value(string)); 11670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 11680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 11690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 11700d5e116f6aee03185f237311a943491bb079a768Kristian MonsenTEST(HeapSnapshotJSONSerializationAborting) { 11710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen v8::HandleScope scope; 11720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen LocalContext env; 11730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen const v8::HeapSnapshot* snapshot = 11740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen v8::HeapProfiler::TakeSnapshot(v8::String::New("abort")); 11750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen TestJSONStream stream(5); 11760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen snapshot->Serialize(&stream, v8::HeapSnapshot::kJSON); 11770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CHECK_GT(stream.size(), 0); 11780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CHECK_EQ(0, stream.eos_signaled()); 11790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 11800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 11818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 11828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang// Must not crash in debug mode. 11838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) WangTEST(AggregatedHeapSnapshotJSONSerialization) { 11848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang v8::HandleScope scope; 11858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang LocalContext env; 11868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 11878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const v8::HeapSnapshot* snapshot = 11888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang v8::HeapProfiler::TakeSnapshot( 11898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang v8::String::New("agg"), v8::HeapSnapshot::kAggregated); 11908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang TestJSONStream stream; 11918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang snapshot->Serialize(&stream, v8::HeapSnapshot::kJSON); 11928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_GT(stream.size(), 0); 11938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang CHECK_EQ(1, stream.eos_signaled()); 11948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang} 11958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // ENABLE_LOGGING_AND_PROFILING 1197