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