test-heap-profiler.cc revision 9dcf7e2f83591d471e88bf7d230651900b8e424b
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 Blockstatic void CompileAndRunScript(const char *src) { 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Script::Compile(v8::String::New(src))->Run(); 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace { 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass ConstructorHeapProfileTestHelper : public i::ConstructorHeapProfile { 31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ConstructorHeapProfileTestHelper() 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : i::ConstructorHeapProfile(), 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block f_name_(i::Factory::NewStringFromAscii(i::CStrVector("F"))), 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block f_count_(0) { 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Call(const JSObjectsCluster& cluster, 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const i::NumberAndSizeInfo& number_and_size) { 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (f_name_->Equals(cluster.constructor())) { 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(f_count_, 0); 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block f_count_ = number_and_size.number(); 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_GT(f_count_, 0); 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int f_count() { return f_count_; } 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::Handle<i::String> f_name_; 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int f_count_; 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} // namespace 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ConstructorProfile) { 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::HandleScope scope; 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Handle<v8::Context> env = v8::Context::New(); 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block env->Enter(); 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CompileAndRunScript( 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "function F() {} // A constructor\n" 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "var f1 = new F();\n" 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "var f2 = new F();\n"); 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ConstructorHeapProfileTestHelper cons_profile; 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::AssertNoAllocation no_alloc; 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::HeapIterator iterator; 70d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke for (i::HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cons_profile.CollectStats(obj); 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(0, cons_profile.f_count()); 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cons_profile.PrintStats(); 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(2, cons_profile.f_count()); 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic JSObjectsCluster AddHeapObjectToTree(JSObjectsRetainerTree* tree, 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::String* constructor, 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int instance, 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster* ref1 = NULL, 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster* ref2 = NULL, 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster* ref3 = NULL) { 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o(constructor, reinterpret_cast<i::Object*>(instance)); 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsClusterTree* o_tree = new JSObjectsClusterTree(); 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsClusterTree::Locator o_loc; 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (ref1 != NULL) o_tree->Insert(*ref1, &o_loc); 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (ref2 != NULL) o_tree->Insert(*ref2, &o_loc); 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (ref3 != NULL) o_tree->Insert(*ref3, &o_loc); 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsRetainerTree::Locator loc; 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tree->Insert(o, &loc); 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block loc.set_value(o_tree); 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return o; 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void AddSelfReferenceToTree(JSObjectsRetainerTree* tree, 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster* self_ref) { 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsRetainerTree::Locator loc; 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(tree->Find(*self_ref, &loc)); 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsClusterTree::Locator o_loc; 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_NE(NULL, loc.value()); 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block loc.value()->Insert(*self_ref, &o_loc); 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic inline void CheckEqualsHelper(const char* file, int line, 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* expected_source, 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const JSObjectsCluster& expected, 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* value_source, 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const JSObjectsCluster& value) { 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (JSObjectsCluster::Compare(expected, value) != 0) { 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::HeapStringAllocator allocator; 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::StringStream stream(&allocator); 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stream.Add("# Expected: "); 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block expected.DebugPrint(&stream); 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stream.Add("\n# Found: "); 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block value.DebugPrint(&stream); 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block V8_Fatal(file, line, "CHECK_EQ(%s, %s) failed\n%s", 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block expected_source, value_source, 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *stream.ToCString()); 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic inline void CheckNonEqualsHelper(const char* file, int line, 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* expected_source, 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const JSObjectsCluster& expected, 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* value_source, 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const JSObjectsCluster& value) { 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (JSObjectsCluster::Compare(expected, value) == 0) { 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::HeapStringAllocator allocator; 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::StringStream stream(&allocator); 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stream.Add("# !Expected: "); 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block expected.DebugPrint(&stream); 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stream.Add("\n# Found: "); 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block value.DebugPrint(&stream); 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block V8_Fatal(file, line, "CHECK_NE(%s, %s) failed\n%s", 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block expected_source, value_source, 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *stream.ToCString()); 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ClustersCoarserSimple) { 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::HandleScope scope; 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Handle<v8::Context> env = v8::Context::New(); 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block env->Enter(); 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::ZoneScope zn_scope(i::DELETE_ON_EXIT); 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsRetainerTree tree; 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster function(i::Heap::function_class_symbol()); 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster a(*i::Factory::NewStringFromAscii(i::CStrVector("A"))); 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster b(*i::Factory::NewStringFromAscii(i::CStrVector("B"))); 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // o1 <- Function 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o1 = 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x100, &function); 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // o2 <- Function 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o2 = 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x200, &function); 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // o3 <- A, B 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o3 = 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x300, &a, &b); 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // o4 <- B, A 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o4 = 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x400, &b, &a); 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // o5 <- A, B, Function 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o5 = 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x500, 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &a, &b, &function); 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ClustersCoarser coarser; 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block coarser.Process(&tree); 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(coarser.GetCoarseEquivalent(o1), coarser.GetCoarseEquivalent(o2)); 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(coarser.GetCoarseEquivalent(o3), coarser.GetCoarseEquivalent(o4)); 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_NE(coarser.GetCoarseEquivalent(o1), coarser.GetCoarseEquivalent(o3)); 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(JSObjectsCluster(), coarser.GetCoarseEquivalent(o5)); 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ClustersCoarserMultipleConstructors) { 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::HandleScope scope; 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Handle<v8::Context> env = v8::Context::New(); 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block env->Enter(); 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::ZoneScope zn_scope(i::DELETE_ON_EXIT); 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsRetainerTree tree; 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster function(i::Heap::function_class_symbol()); 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // o1 <- Function 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o1 = 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x100, &function); 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // a1 <- Function 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster a1 = 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Array_symbol(), 0x1000, &function); 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // o2 <- Function 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o2 = 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x200, &function); 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // a2 <- Function 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster a2 = 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Array_symbol(), 0x2000, &function); 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ClustersCoarser coarser; 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block coarser.Process(&tree); 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(coarser.GetCoarseEquivalent(o1), coarser.GetCoarseEquivalent(o2)); 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(coarser.GetCoarseEquivalent(a1), coarser.GetCoarseEquivalent(a2)); 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ClustersCoarserPathsTraversal) { 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::HandleScope scope; 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Handle<v8::Context> env = v8::Context::New(); 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block env->Enter(); 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::ZoneScope zn_scope(i::DELETE_ON_EXIT); 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsRetainerTree tree; 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // On the following graph: 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // p 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // <- o21 <- o11 <- 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // q o 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // <- o22 <- o12 <- 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // we expect that coarser will deduce equivalences: p ~ q ~ r, 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // o21 ~ o22, and o11 ~ o12. 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o = 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x100); 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o11 = 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x110, &o); 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o12 = 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x120, &o); 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o21 = 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x210, &o11); 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o22 = 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x220, &o12); 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster p = 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x300, &o21); 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster q = 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x310, &o21, &o22); 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster r = 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x320, &o22); 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ClustersCoarser coarser; 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block coarser.Process(&tree); 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(JSObjectsCluster(), coarser.GetCoarseEquivalent(o)); 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_NE(JSObjectsCluster(), coarser.GetCoarseEquivalent(o11)); 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(coarser.GetCoarseEquivalent(o11), coarser.GetCoarseEquivalent(o12)); 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(coarser.GetCoarseEquivalent(o21), coarser.GetCoarseEquivalent(o22)); 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_NE(coarser.GetCoarseEquivalent(o11), coarser.GetCoarseEquivalent(o21)); 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_NE(JSObjectsCluster(), coarser.GetCoarseEquivalent(p)); 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(coarser.GetCoarseEquivalent(p), coarser.GetCoarseEquivalent(q)); 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(coarser.GetCoarseEquivalent(q), coarser.GetCoarseEquivalent(r)); 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_NE(coarser.GetCoarseEquivalent(o11), coarser.GetCoarseEquivalent(p)); 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_NE(coarser.GetCoarseEquivalent(o21), coarser.GetCoarseEquivalent(p)); 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ClustersCoarserSelf) { 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::HandleScope scope; 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Handle<v8::Context> env = v8::Context::New(); 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block env->Enter(); 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::ZoneScope zn_scope(i::DELETE_ON_EXIT); 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsRetainerTree tree; 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // On the following graph: 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // p (self-referencing) 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // <- o1 <- 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // q (self-referencing) o 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // <- o2 <- 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r (self-referencing) 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // we expect that coarser will deduce equivalences: p ~ q ~ r, o1 ~ o2; 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o = 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x100); 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o1 = 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x110, &o); 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster o2 = 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x120, &o); 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster p = 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x300, &o1); 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddSelfReferenceToTree(&tree, &p); 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster q = 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x310, &o1, &o2); 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddSelfReferenceToTree(&tree, &q); 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSObjectsCluster r = 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddHeapObjectToTree(&tree, i::Heap::Object_symbol(), 0x320, &o2); 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block AddSelfReferenceToTree(&tree, &r); 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ClustersCoarser coarser; 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block coarser.Process(&tree); 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(JSObjectsCluster(), coarser.GetCoarseEquivalent(o)); 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_NE(JSObjectsCluster(), coarser.GetCoarseEquivalent(o1)); 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(coarser.GetCoarseEquivalent(o1), coarser.GetCoarseEquivalent(o2)); 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_NE(JSObjectsCluster(), coarser.GetCoarseEquivalent(p)); 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(coarser.GetCoarseEquivalent(p), coarser.GetCoarseEquivalent(q)); 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ(coarser.GetCoarseEquivalent(q), coarser.GetCoarseEquivalent(r)); 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_NE(coarser.GetCoarseEquivalent(o1), coarser.GetCoarseEquivalent(p)); 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace { 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass RetainerProfilePrinter : public RetainerHeapProfile::Printer { 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RetainerProfilePrinter() : stream_(&allocator_), lines_(100) {} 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void PrintRetainers(const JSObjectsCluster& cluster, 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const i::StringStream& retainers) { 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cluster.Print(&stream_); 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stream_.Add("%s", *(retainers.ToCString())); 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stream_.Put('\0'); 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* GetRetainers(const char* constructor) { 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FillLines(); 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const size_t cons_len = strlen(constructor); 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < lines_.length(); ++i) { 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (strncmp(constructor, lines_[i], cons_len) == 0 && 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lines_[i][cons_len] == ',') { 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return lines_[i] + cons_len + 1; 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return NULL; 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void FillLines() { 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (lines_.length() > 0) return; 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stream_.Put('\0'); 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stream_str_ = stream_.ToCString(); 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* pos = *stream_str_; 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (pos != NULL && *pos != '\0') { 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lines_.Add(pos); 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pos = strchr(pos, '\0'); 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (pos != NULL) ++pos; 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::HeapStringAllocator allocator_; 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::StringStream stream_; 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::SmartPointer<const char> stream_str_; 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::List<const char*> lines_; 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} // namespace 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(RetainerProfile) { 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::HandleScope scope; 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v8::Handle<v8::Context> env = v8::Context::New(); 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block env->Enter(); 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CompileAndRunScript( 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "function A() {}\n" 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "function B(x) { this.x = x; }\n" 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "function C(x) { this.x1 = x; this.x2 = x; }\n" 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "var a = new A();\n" 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "var b1 = new B(a), b2 = new B(a);\n" 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "var c = new C(a);"); 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RetainerHeapProfile ret_profile; 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::AssertNoAllocation no_alloc; 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i::HeapIterator iterator; 379d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke for (i::HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ret_profile.CollectStats(obj); 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RetainerProfilePrinter printer; 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ret_profile.DebugPrintStats(&printer); 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* retainers_of_a = printer.GetRetainers("A"); 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The order of retainers is unspecified, so we check string length, and 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // verify each retainer separately. 386d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block CHECK_EQ(i::StrLength("(global property);1,B;2,C;2"), 387d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block i::StrLength(retainers_of_a)); 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(strstr(retainers_of_a, "(global property);1") != NULL); 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(strstr(retainers_of_a, "B;2") != NULL); 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(strstr(retainers_of_a, "C;2") != NULL); 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ("(global property);2", printer.GetRetainers("B")); 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK_EQ("(global property);1", printer.GetRetainers("C")); 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3959dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 3969dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsennamespace { 3979dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 3989dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenclass NamedEntriesDetector { 3999dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen public: 4009dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen NamedEntriesDetector() 4019dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen : has_A1(false), has_B1(false), has_C1(false), 4029dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen has_A2(false), has_B2(false), has_C2(false) { 4039dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 4049dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 4059dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen void Apply(i::HeapEntry* entry) { 4069dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const char* node_name = entry->name(); 4079dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (strcmp("A1", node_name) == 0 4089dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen && entry->GetRetainingPaths()->length() > 0) has_A1 = true; 4099dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (strcmp("B1", node_name) == 0 4109dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen && entry->GetRetainingPaths()->length() > 0) has_B1 = true; 4119dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (strcmp("C1", node_name) == 0 4129dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen && entry->GetRetainingPaths()->length() > 0) has_C1 = true; 4139dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (strcmp("A2", node_name) == 0 4149dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen && entry->GetRetainingPaths()->length() > 0) has_A2 = true; 4159dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (strcmp("B2", node_name) == 0 4169dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen && entry->GetRetainingPaths()->length() > 0) has_B2 = true; 4179dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (strcmp("C2", node_name) == 0 4189dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen && entry->GetRetainingPaths()->length() > 0) has_C2 = true; 4199dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 4209dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 4219dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen bool has_A1; 4229dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen bool has_B1; 4239dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen bool has_C1; 4249dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen bool has_A2; 4259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen bool has_B2; 4269dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen bool has_C2; 4279dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}; 4289dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 4299dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} // namespace 4309dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 4319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 4329dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenstatic const v8::HeapGraphNode* GetGlobalObject( 4339dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapSnapshot* snapshot) { 4349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK_EQ(1, snapshot->GetHead()->GetChildrenCount()); 4359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen return snapshot->GetHead()->GetChild(0)->GetToNode(); 4369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 4379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 4389dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 4399dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenstatic const v8::HeapGraphNode* GetProperty(const v8::HeapGraphNode* node, 4409dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen v8::HeapGraphEdge::Type type, 4419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const char* name) { 4429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) { 4439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphEdge* prop = node->GetChild(i); 4449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen v8::String::AsciiValue prop_name(prop->GetName()); 4459dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (prop->GetType() == type && strcmp(name, *prop_name) == 0) 4469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen return prop->GetToNode(); 4479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 4489dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen return NULL; 4499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 4509dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 4519dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 4529dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenstatic bool HasString(const v8::HeapGraphNode* node, const char* contents) { 4539dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) { 4549dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphEdge* prop = node->GetChild(i); 4559dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphNode* node = prop->GetToNode(); 4569dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (node->GetType() == v8::HeapGraphNode::STRING) { 4579dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen v8::String::AsciiValue node_name(node->GetName()); 4589dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (strcmp(contents, *node_name) == 0) return true; 4599dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 4609dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 4619dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen return false; 4629dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 4639dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 4649dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 4659dcf7e2f83591d471e88bf7d230651900b8e424bKristian MonsenTEST(HeapSnapshot) { 4669dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen v8::HandleScope scope; 4679dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 4689dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen v8::Handle<v8::String> token1 = v8::String::New("token1"); 4699dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen v8::Handle<v8::Context> env1 = v8::Context::New(); 4709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen env1->SetSecurityToken(token1); 4719dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen env1->Enter(); 4729dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 4739dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CompileAndRunScript( 4749dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen "function A1() {}\n" 4759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen "function B1(x) { this.x = x; }\n" 4769dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen "function C1(x) { this.x1 = x; this.x2 = x; }\n" 4779dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen "var a1 = new A1();\n" 4789dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen "var b1_1 = new B1(a1), b1_2 = new B1(a1);\n" 4799dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen "var c1 = new C1(a1);"); 4809dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 4819dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen v8::Handle<v8::String> token2 = v8::String::New("token2"); 4829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen v8::Handle<v8::Context> env2 = v8::Context::New(); 4839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen env2->SetSecurityToken(token2); 4849dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen env2->Enter(); 4859dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 4869dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CompileAndRunScript( 4879dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen "function A2() {}\n" 4889dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen "function B2(x) { return function() { return typeof x; }; }\n" 4899dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen "function C2(x) { this.x1 = x; this.x2 = x; this[1] = x; }\n" 4909dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen "var a2 = new A2();\n" 4919dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen "var b2_1 = new B2(a2), b2_2 = new B2(a2);\n" 4929dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen "var c2 = new C2(a2);"); 4939dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapSnapshot* snapshot_env2 = 4949dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen v8::HeapProfiler::TakeSnapshot(v8::String::New("env2")); 4959dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphNode* global_env2 = GetGlobalObject(snapshot_env2); 4969dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 4979dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Verify, that JS global object of env2 doesn't have '..1' 4989dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // properties, but has '..2' properties. 4999dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK_EQ(NULL, GetProperty(global_env2, v8::HeapGraphEdge::PROPERTY, "a1")); 5009dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK_EQ(NULL, GetProperty(global_env2, v8::HeapGraphEdge::PROPERTY, "b1_1")); 5019dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK_EQ(NULL, GetProperty(global_env2, v8::HeapGraphEdge::PROPERTY, "b1_2")); 5029dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK_EQ(NULL, GetProperty(global_env2, v8::HeapGraphEdge::PROPERTY, "c1")); 5039dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphNode* a2_node = 5049dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GetProperty(global_env2, v8::HeapGraphEdge::PROPERTY, "a2"); 5059dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK_NE(NULL, a2_node); 5069dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK_NE(NULL, GetProperty(global_env2, v8::HeapGraphEdge::PROPERTY, "b2_1")); 5079dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK_NE(NULL, GetProperty(global_env2, v8::HeapGraphEdge::PROPERTY, "b2_2")); 5089dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK_NE(NULL, GetProperty(global_env2, v8::HeapGraphEdge::PROPERTY, "c2")); 5099dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 5109dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Verify that anything related to '[ABC]1' is not reachable. 5119dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen NamedEntriesDetector det; 5129dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen i::HeapSnapshot* i_snapshot_env2 = 5139dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const_cast<i::HeapSnapshot*>( 5149dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen reinterpret_cast<const i::HeapSnapshot*>(snapshot_env2)); 5159dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen i_snapshot_env2->IterateEntries(&det); 5169dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK(!det.has_A1); 5179dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK(!det.has_B1); 5189dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK(!det.has_C1); 5199dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK(det.has_A2); 5209dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK(det.has_B2); 5219dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK(det.has_C2); 5229dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 5239dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Verify 'a2' object retainers. They are: 5249dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // - (global object).a2 5259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // - c2.x1, c2.x2, c2[1] 5269dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // - b2_1 and b2_2 closures: via 'x' variable 5279dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK_EQ(6, a2_node->GetRetainingPathsCount()); 5289dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen bool has_global_obj_a2_ref = false; 5299dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen bool has_c2_x1_ref = false, has_c2_x2_ref = false, has_c2_1_ref = false; 5309dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen bool has_b2_1_x_ref = false, has_b2_2_x_ref = false; 5319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen for (int i = 0; i < a2_node->GetRetainingPathsCount(); ++i) { 5329dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphPath* path = a2_node->GetRetainingPath(i); 5339dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const int edges_count = path->GetEdgesCount(); 5349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK_GT(edges_count, 0); 5359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphEdge* last_edge = path->GetEdge(edges_count - 1); 5369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen v8::String::AsciiValue last_edge_name(last_edge->GetName()); 5379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (strcmp("a2", *last_edge_name) == 0 5389dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen && last_edge->GetType() == v8::HeapGraphEdge::PROPERTY) { 5399dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen has_global_obj_a2_ref = true; 5409dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen continue; 5419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 5429dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK_GT(edges_count, 1); 5439dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphEdge* prev_edge = path->GetEdge(edges_count - 2); 5449dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen v8::String::AsciiValue prev_edge_name(prev_edge->GetName()); 5459dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (strcmp("x1", *last_edge_name) == 0 5469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen && last_edge->GetType() == v8::HeapGraphEdge::PROPERTY 5479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen && strcmp("c2", *prev_edge_name) == 0) has_c2_x1_ref = true; 5489dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (strcmp("x2", *last_edge_name) == 0 5499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen && last_edge->GetType() == v8::HeapGraphEdge::PROPERTY 5509dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen && strcmp("c2", *prev_edge_name) == 0) has_c2_x2_ref = true; 5519dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (strcmp("1", *last_edge_name) == 0 5529dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen && last_edge->GetType() == v8::HeapGraphEdge::ELEMENT 5539dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen && strcmp("c2", *prev_edge_name) == 0) has_c2_1_ref = true; 5549dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (strcmp("x", *last_edge_name) == 0 5559dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen && last_edge->GetType() == v8::HeapGraphEdge::CONTEXT_VARIABLE 5569dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen && strcmp("b2_1", *prev_edge_name) == 0) has_b2_1_x_ref = true; 5579dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (strcmp("x", *last_edge_name) == 0 5589dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen && last_edge->GetType() == v8::HeapGraphEdge::CONTEXT_VARIABLE 5599dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen && strcmp("b2_2", *prev_edge_name) == 0) has_b2_2_x_ref = true; 5609dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 5619dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK(has_global_obj_a2_ref); 5629dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK(has_c2_x1_ref); 5639dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK(has_c2_x2_ref); 5649dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK(has_c2_1_ref); 5659dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK(has_b2_1_x_ref); 5669dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK(has_b2_2_x_ref); 5679dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 5689dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 5699dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 5709dcf7e2f83591d471e88bf7d230651900b8e424bKristian MonsenTEST(HeapSnapshotCodeObjects) { 5719dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen v8::HandleScope scope; 5729dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen v8::Handle<v8::Context> env = v8::Context::New(); 5739dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen env->Enter(); 5749dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 5759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CompileAndRunScript( 5769dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen "function lazy(x) { return x - 1; }\n" 5779dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen "function compiled(x) { return x + 1; }\n" 5789dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen "compiled(1)"); 5799dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapSnapshot* snapshot = 5809dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen v8::HeapProfiler::TakeSnapshot(v8::String::New("code")); 5819dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 5829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphNode* global = GetGlobalObject(snapshot); 5839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphNode* compiled = 5849dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GetProperty(global, v8::HeapGraphEdge::PROPERTY, "compiled"); 5859dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK_NE(NULL, compiled); 5869dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK_EQ(v8::HeapGraphNode::CLOSURE, compiled->GetType()); 5879dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphNode* lazy = 5889dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GetProperty(global, v8::HeapGraphEdge::PROPERTY, "lazy"); 5899dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK_NE(NULL, lazy); 5909dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK_EQ(v8::HeapGraphNode::CLOSURE, lazy->GetType()); 5919dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 5929dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Find references to code. 5939dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphNode* compiled_code = 5949dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GetProperty(compiled, v8::HeapGraphEdge::INTERNAL, "code"); 5959dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK_NE(NULL, compiled_code); 5969dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphNode* lazy_code = 5979dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen GetProperty(lazy, v8::HeapGraphEdge::INTERNAL, "code"); 5989dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK_NE(NULL, lazy_code); 5999dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 6009dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // Verify that non-compiled code doesn't contain references to "x" 6019dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen // literal, while compiled code does. 6029dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen bool compiled_references_x = false, lazy_references_x = false; 6039dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen for (int i = 0, count = compiled_code->GetChildrenCount(); i < count; ++i) { 6049dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphEdge* prop = compiled_code->GetChild(i); 6059dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphNode* node = prop->GetToNode(); 6069dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (node->GetType() == v8::HeapGraphNode::CODE) { 6079dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (HasString(node, "x")) { 6089dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen compiled_references_x = true; 6099dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen break; 6109dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 6119dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 6129dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 6139dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen for (int i = 0, count = lazy_code->GetChildrenCount(); i < count; ++i) { 6149dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphEdge* prop = lazy_code->GetChild(i); 6159dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen const v8::HeapGraphNode* node = prop->GetToNode(); 6169dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (node->GetType() == v8::HeapGraphNode::CODE) { 6179dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen if (HasString(node, "x")) { 6189dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen lazy_references_x = true; 6199dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen break; 6209dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 6219dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 6229dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen } 6239dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK(compiled_references_x); 6249dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen CHECK(!lazy_references_x); 6259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 6269dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // ENABLE_LOGGING_AND_PROFILING 628