test-heap-profiler.cc revision 69a99ed0b2b2ef69d393c371b03db3a98aaf880e
1257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Tests for heap profiler
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h"
6257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
7257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#include "cctest.h"
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "heap-profiler.h"
99dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen#include "snapshot.h"
10257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#include "utils-inl.h"
119dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen#include "../include/v8-profiler.h"
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
139dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsennamespace {
149dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
159dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenclass NamedEntriesDetector {
169dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen public:
179dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  NamedEntriesDetector()
1890bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner      : has_A2(false), has_B2(false), has_C2(false) {
199dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
209dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
21756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  void Apply(i::HeapEntry** entry_ptr) {
22756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (IsReachableNodeWithName(*entry_ptr, "A2")) has_A2 = true;
23756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (IsReachableNodeWithName(*entry_ptr, "B2")) has_B2 = true;
24756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (IsReachableNodeWithName(*entry_ptr, "C2")) has_C2 = true;
25756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
26756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
27756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  static bool IsReachableNodeWithName(i::HeapEntry* entry, const char* name) {
28756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    return strcmp(name, entry->name()) == 0 && entry->painted_reachable();
299dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
309dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  bool has_A2;
329dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  bool has_B2;
339dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  bool has_C2;
349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen};
359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}  // namespace
379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
389dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
399dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenstatic const v8::HeapGraphNode* GetGlobalObject(
409dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    const v8::HeapSnapshot* snapshot) {
418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_EQ(2, snapshot->GetRoot()->GetChildrenCount());
428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  const v8::HeapGraphNode* global_obj =
438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      snapshot->GetRoot()->GetChild(0)->GetToNode();
443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_EQ(0, strncmp("Object", const_cast<i::HeapEntry*>(
453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      reinterpret_cast<const i::HeapEntry*>(global_obj))->name(), 6));
468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  return global_obj;
479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
489dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
509dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenstatic const v8::HeapGraphNode* GetProperty(const v8::HeapGraphNode* node,
519dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                            v8::HeapGraphEdge::Type type,
529dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                            const char* name) {
539dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) {
549dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    const v8::HeapGraphEdge* prop = node->GetChild(i);
559dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    v8::String::AsciiValue prop_name(prop->GetName());
569dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    if (prop->GetType() == type && strcmp(name, *prop_name) == 0)
579dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      return prop->GetToNode();
589dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
599dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  return NULL;
609dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
619dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
629dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
639dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenstatic bool HasString(const v8::HeapGraphNode* node, const char* contents) {
649dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) {
659dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    const v8::HeapGraphEdge* prop = node->GetChild(i);
669dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    const v8::HeapGraphNode* node = prop->GetToNode();
67756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (node->GetType() == v8::HeapGraphNode::kString) {
689dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      v8::String::AsciiValue node_name(node->GetName());
699dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      if (strcmp(contents, *node_name) == 0) return true;
709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    }
719dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
729dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  return false;
739dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
749dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
769dcf7e2f83591d471e88bf7d230651900b8e424bKristian MonsenTEST(HeapSnapshot) {
779dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  v8::HandleScope scope;
783bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  LocalContext env2;
799dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
80f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CompileRun(
819dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      "function A2() {}\n"
829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      "function B2(x) { return function() { return typeof x; }; }\n"
839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      "function C2(x) { this.x1 = x; this.x2 = x; this[1] = x; }\n"
849dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      "var a2 = new A2();\n"
859dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      "var b2_1 = new B2(a2), b2_2 = new B2(a2);\n"
869dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      "var c2 = new C2(a2);");
879dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  const v8::HeapSnapshot* snapshot_env2 =
8869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("env2"));
89756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  i::HeapSnapshot* i_snapshot_env2 =
90756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      const_cast<i::HeapSnapshot*>(
91756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick          reinterpret_cast<const i::HeapSnapshot*>(snapshot_env2));
929dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  const v8::HeapGraphNode* global_env2 = GetGlobalObject(snapshot_env2);
93756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Paint all nodes reachable from global object.
94756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  i_snapshot_env2->ClearPaint();
95756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const_cast<i::HeapEntry*>(
96756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      reinterpret_cast<const i::HeapEntry*>(global_env2))->PaintAllReachable();
979dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
9890bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  // Verify, that JS global object of env2 has '..2' properties.
999dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  const v8::HeapGraphNode* a2_node =
1008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "a2");
1019dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  CHECK_NE(NULL, a2_node);
102756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_NE(
1038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "b2_1"));
104756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_NE(
1058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "b2_2"));
1068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_NE(NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "c2"));
1079dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
1089dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  NamedEntriesDetector det;
1099dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  i_snapshot_env2->IterateEntries(&det);
1109dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  CHECK(det.has_A2);
1119dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  CHECK(det.has_B2);
1129dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  CHECK(det.has_C2);
1139dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
1149dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
1159dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
116756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain MerrickTEST(HeapSnapshotObjectSizes) {
117756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  v8::HandleScope scope;
118756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  LocalContext env;
119756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
120756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  //   -a-> X1 --a
121756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // x -b-> X2 <-|
122f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CompileRun(
123756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      "function X(a, b) { this.a = a; this.b = b; }\n"
124756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      "x = new X(new X(), new X());\n"
1258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "(function() { x.a.a = x.b; })();");
126756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const v8::HeapSnapshot* snapshot =
12769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("sizes"));
128756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
129756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const v8::HeapGraphNode* x =
1308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      GetProperty(global, v8::HeapGraphEdge::kShortcut, "x");
131756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_NE(NULL, x);
132756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const v8::HeapGraphNode* x1 =
133756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      GetProperty(x, v8::HeapGraphEdge::kProperty, "a");
134756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_NE(NULL, x1);
135756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const v8::HeapGraphNode* x2 =
136756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      GetProperty(x, v8::HeapGraphEdge::kProperty, "b");
137756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_NE(NULL, x2);
1388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Test approximate sizes.
1408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_EQ(x->GetSelfSize() * 3, x->GetRetainedSize(false));
1418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_EQ(x1->GetSelfSize(), x1->GetRetainedSize(false));
1428a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_EQ(x2->GetSelfSize(), x2->GetRetainedSize(false));
1438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Test exact sizes.
1448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_EQ(x->GetSelfSize() * 3, x->GetRetainedSize(true));
1458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_EQ(x1->GetSelfSize(), x1->GetRetainedSize(true));
1468a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_EQ(x2->GetSelfSize(), x2->GetRetainedSize(true));
147756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
148756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
149756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
150756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain MerrickTEST(HeapSnapshotEntryChildren) {
151756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  v8::HandleScope scope;
152756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  LocalContext env;
153756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
154f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CompileRun(
155756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      "function A() { }\n"
156756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      "a = new A;");
157756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const v8::HeapSnapshot* snapshot =
15869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("children"));
159756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
160756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  for (int i = 0, count = global->GetChildrenCount(); i < count; ++i) {
161756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    const v8::HeapGraphEdge* prop = global->GetChild(i);
162756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    CHECK_EQ(global, prop->GetFromNode());
163756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
164756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const v8::HeapGraphNode* a =
165756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      GetProperty(global, v8::HeapGraphEdge::kProperty, "a");
166756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_NE(NULL, a);
167756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  for (int i = 0, count = a->GetChildrenCount(); i < count; ++i) {
168756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    const v8::HeapGraphEdge* prop = a->GetChild(i);
169756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    CHECK_EQ(a, prop->GetFromNode());
170756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
171756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
172756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
173756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
1749dcf7e2f83591d471e88bf7d230651900b8e424bKristian MonsenTEST(HeapSnapshotCodeObjects) {
1759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  v8::HandleScope scope;
1763bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  LocalContext env;
1779dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
178f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CompileRun(
1799dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      "function lazy(x) { return x - 1; }\n"
1809dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      "function compiled(x) { return x + 1; }\n"
181791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      "var anonymous = (function() { return function() { return 0; } })();\n"
1829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      "compiled(1)");
1839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  const v8::HeapSnapshot* snapshot =
18469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("code"));
1859dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
1869dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
1879dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  const v8::HeapGraphNode* compiled =
1888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      GetProperty(global, v8::HeapGraphEdge::kShortcut, "compiled");
1899dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  CHECK_NE(NULL, compiled);
190756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_EQ(v8::HeapGraphNode::kClosure, compiled->GetType());
1919dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  const v8::HeapGraphNode* lazy =
1928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      GetProperty(global, v8::HeapGraphEdge::kShortcut, "lazy");
1939dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  CHECK_NE(NULL, lazy);
194756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_EQ(v8::HeapGraphNode::kClosure, lazy->GetType());
195791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  const v8::HeapGraphNode* anonymous =
1968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      GetProperty(global, v8::HeapGraphEdge::kShortcut, "anonymous");
197791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  CHECK_NE(NULL, anonymous);
198791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  CHECK_EQ(v8::HeapGraphNode::kClosure, anonymous->GetType());
199791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  v8::String::AsciiValue anonymous_name(anonymous->GetName());
200f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK_EQ("", *anonymous_name);
2019dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
2029dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Find references to code.
2039dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  const v8::HeapGraphNode* compiled_code =
2048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      GetProperty(compiled, v8::HeapGraphEdge::kInternal, "shared");
2059dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  CHECK_NE(NULL, compiled_code);
2069dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  const v8::HeapGraphNode* lazy_code =
2078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      GetProperty(lazy, v8::HeapGraphEdge::kInternal, "shared");
2089dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  CHECK_NE(NULL, lazy_code);
2099dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
2109dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Verify that non-compiled code doesn't contain references to "x"
2113bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // literal, while compiled code does. The scope info is stored in FixedArray
2123bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // objects attached to the SharedFunctionInfo.
2139dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  bool compiled_references_x = false, lazy_references_x = false;
2149dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  for (int i = 0, count = compiled_code->GetChildrenCount(); i < count; ++i) {
2159dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    const v8::HeapGraphEdge* prop = compiled_code->GetChild(i);
2169dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    const v8::HeapGraphNode* node = prop->GetToNode();
217756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (node->GetType() == v8::HeapGraphNode::kArray) {
2189dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      if (HasString(node, "x")) {
2199dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        compiled_references_x = true;
2209dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        break;
2219dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      }
2229dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    }
2239dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
2249dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  for (int i = 0, count = lazy_code->GetChildrenCount(); i < count; ++i) {
2259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    const v8::HeapGraphEdge* prop = lazy_code->GetChild(i);
2269dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    const v8::HeapGraphNode* node = prop->GetToNode();
227756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (node->GetType() == v8::HeapGraphNode::kArray) {
2289dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      if (HasString(node, "x")) {
2299dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        lazy_references_x = true;
2309dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        break;
2319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      }
2329dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    }
2339dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
2349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  CHECK(compiled_references_x);
2359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  CHECK(!lazy_references_x);
2369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
2379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
2383bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
239f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochTEST(HeapSnapshotHeapNumbers) {
240f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  v8::HandleScope scope;
241f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  LocalContext env;
242f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CompileRun(
243f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "a = 1;    // a is Smi\n"
244f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "b = 2.5;  // b is HeapNumber");
245f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  const v8::HeapSnapshot* snapshot =
24669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("numbers"));
247f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
2488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_EQ(NULL, GetProperty(global, v8::HeapGraphEdge::kShortcut, "a"));
249f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  const v8::HeapGraphNode* b =
2508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      GetProperty(global, v8::HeapGraphEdge::kShortcut, "b");
251f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK_NE(NULL, b);
252f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK_EQ(v8::HeapGraphNode::kHeapNumber, b->GetType());
253f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch}
254f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
255f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
256f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochTEST(HeapSnapshotInternalReferences) {
257f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  v8::HandleScope scope;
258f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  v8::Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
259f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  global_template->SetInternalFieldCount(2);
260f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  LocalContext env(NULL, global_template);
261f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  v8::Handle<v8::Object> global_proxy = env->Global();
262f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  v8::Handle<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>();
263f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK_EQ(2, global->InternalFieldCount());
264f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  v8::Local<v8::Object> obj = v8::Object::New();
265f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  global->SetInternalField(0, v8_num(17));
266f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  global->SetInternalField(1, obj);
267f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  const v8::HeapSnapshot* snapshot =
26869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("internals"));
269f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  const v8::HeapGraphNode* global_node = GetGlobalObject(snapshot);
270f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // The first reference will not present, because it's a Smi.
271f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK_EQ(NULL, GetProperty(global_node, v8::HeapGraphEdge::kInternal, "0"));
272f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // The second reference is to an object.
273f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK_NE(NULL, GetProperty(global_node, v8::HeapGraphEdge::kInternal, "1"));
274f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch}
275f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
276f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
2773bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// Trying to introduce a check helper for uint64_t causes many
2783bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// overloading ambiguities, so it seems easier just to cast
2793bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// them to a signed type.
2803bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch#define CHECK_EQ_UINT64_T(a, b) \
2813bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CHECK_EQ(static_cast<int64_t>(a), static_cast<int64_t>(b))
282756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick#define CHECK_NE_UINT64_T(a, b) \
283756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK((a) != (b))  // NOLINT
2843bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
2853bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben MurdochTEST(HeapEntryIdsAndGC) {
2863bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  v8::HandleScope scope;
2873bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  LocalContext env;
2883bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
289f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CompileRun(
2903bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      "function A() {}\n"
2913bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      "function B(x) { this.x = x; }\n"
2923bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      "var a = new A();\n"
2933bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      "var b = new B(a);");
2943bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  const v8::HeapSnapshot* snapshot1 =
29569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("s1"));
2963bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
29744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HEAP->CollectAllGarbage(true);  // Enforce compaction.
2983bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
2993bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  const v8::HeapSnapshot* snapshot2 =
30069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("s2"));
3013bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
3023bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  const v8::HeapGraphNode* global1 = GetGlobalObject(snapshot1);
3033bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  const v8::HeapGraphNode* global2 = GetGlobalObject(snapshot2);
3043bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CHECK_NE_UINT64_T(0, global1->GetId());
3053bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CHECK_EQ_UINT64_T(global1->GetId(), global2->GetId());
3063bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  const v8::HeapGraphNode* A1 =
307756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      GetProperty(global1, v8::HeapGraphEdge::kProperty, "A");
308756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_NE(NULL, A1);
3093bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  const v8::HeapGraphNode* A2 =
310756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      GetProperty(global2, v8::HeapGraphEdge::kProperty, "A");
311756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_NE(NULL, A2);
3123bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CHECK_NE_UINT64_T(0, A1->GetId());
3133bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CHECK_EQ_UINT64_T(A1->GetId(), A2->GetId());
3143bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  const v8::HeapGraphNode* B1 =
315756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      GetProperty(global1, v8::HeapGraphEdge::kProperty, "B");
316756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_NE(NULL, B1);
3173bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  const v8::HeapGraphNode* B2 =
318756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      GetProperty(global2, v8::HeapGraphEdge::kProperty, "B");
319756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_NE(NULL, B2);
3203bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CHECK_NE_UINT64_T(0, B1->GetId());
3213bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CHECK_EQ_UINT64_T(B1->GetId(), B2->GetId());
3223bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  const v8::HeapGraphNode* a1 =
323756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      GetProperty(global1, v8::HeapGraphEdge::kProperty, "a");
324756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_NE(NULL, a1);
3253bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  const v8::HeapGraphNode* a2 =
326756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      GetProperty(global2, v8::HeapGraphEdge::kProperty, "a");
327756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_NE(NULL, a2);
3283bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CHECK_NE_UINT64_T(0, a1->GetId());
3293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CHECK_EQ_UINT64_T(a1->GetId(), a2->GetId());
3303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  const v8::HeapGraphNode* b1 =
331756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      GetProperty(global1, v8::HeapGraphEdge::kProperty, "b");
332756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_NE(NULL, b1);
3333bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  const v8::HeapGraphNode* b2 =
334756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      GetProperty(global2, v8::HeapGraphEdge::kProperty, "b");
335756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_NE(NULL, b2);
3363bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CHECK_NE_UINT64_T(0, b1->GetId());
3373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CHECK_EQ_UINT64_T(b1->GetId(), b2->GetId());
3383bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
3393bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
3403bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
341f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochTEST(HeapSnapshotRootPreservedAfterSorting) {
342f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  v8::HandleScope scope;
343f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  LocalContext env;
344f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  const v8::HeapSnapshot* snapshot =
34569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("s"));
346f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  const v8::HeapGraphNode* root1 = snapshot->GetRoot();
347f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  const_cast<i::HeapSnapshot*>(reinterpret_cast<const i::HeapSnapshot*>(
348f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      snapshot))->GetSortedEntriesList();
349f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  const v8::HeapGraphNode* root2 = snapshot->GetRoot();
350f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK_EQ(root1, root2);
351f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch}
352f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
353f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
3548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) WangTEST(HeapEntryDominator) {
3558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // The graph looks like this:
3568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //
3578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //                   -> node1
3588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //                  a    |^
3598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //          -> node5     ba
3608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //         a             v|
3618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //   node6           -> node2
3628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //         b        a    |^
3638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //          -> node4     ba
3648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //                  b    v|
3658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //                   -> node3
3668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //
3678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // The dominator for all nodes is node6.
3688a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
3698a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  v8::HandleScope scope;
3708a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LocalContext env;
3718a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
3728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CompileRun(
3738a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "function X(a, b) { this.a = a; this.b = b; }\n"
3748a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "node6 = new X(new X(new X()), new X(new X(),new X()));\n"
3758a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "(function(){\n"
3768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "node6.a.a.b = node6.b.a;  // node1 -> node2\n"
3778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "node6.b.a.a = node6.a.a;  // node2 -> node1\n"
3788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "node6.b.a.b = node6.b.b;  // node2 -> node3\n"
3798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "node6.b.b.a = node6.b.a;  // node3 -> node2\n"
3808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "})();");
3818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
3828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  const v8::HeapSnapshot* snapshot =
38369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("dominators"));
3848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
3858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
3868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_NE(NULL, global);
3878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  const v8::HeapGraphNode* node6 =
3888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      GetProperty(global, v8::HeapGraphEdge::kShortcut, "node6");
3898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_NE(NULL, node6);
3908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  const v8::HeapGraphNode* node5 =
3918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      GetProperty(node6, v8::HeapGraphEdge::kProperty, "a");
3928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_NE(NULL, node5);
3938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  const v8::HeapGraphNode* node4 =
3948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      GetProperty(node6, v8::HeapGraphEdge::kProperty, "b");
3958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_NE(NULL, node4);
3968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  const v8::HeapGraphNode* node3 =
3978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      GetProperty(node4, v8::HeapGraphEdge::kProperty, "b");
3988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_NE(NULL, node3);
3998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  const v8::HeapGraphNode* node2 =
4008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      GetProperty(node4, v8::HeapGraphEdge::kProperty, "a");
4018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_NE(NULL, node2);
4028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  const v8::HeapGraphNode* node1 =
4038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      GetProperty(node5, v8::HeapGraphEdge::kProperty, "a");
4048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_NE(NULL, node1);
4058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
4068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_EQ(node6, node1->GetDominatorNode());
4078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_EQ(node6, node2->GetDominatorNode());
4088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_EQ(node6, node3->GetDominatorNode());
4098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_EQ(node6, node4->GetDominatorNode());
4108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_EQ(node6, node5->GetDominatorNode());
4118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
4128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
4138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
4140d5e116f6aee03185f237311a943491bb079a768Kristian Monsennamespace {
4150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4160d5e116f6aee03185f237311a943491bb079a768Kristian Monsenclass TestJSONStream : public v8::OutputStream {
4170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen public:
4180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  TestJSONStream() : eos_signaled_(0), abort_countdown_(-1) {}
4190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  explicit TestJSONStream(int abort_countdown)
4200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      : eos_signaled_(0), abort_countdown_(abort_countdown) {}
4210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  virtual ~TestJSONStream() {}
4220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  virtual void EndOfStream() { ++eos_signaled_; }
4230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  virtual WriteResult WriteAsciiChunk(char* buffer, int chars_written) {
4240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (abort_countdown_ > 0) --abort_countdown_;
4250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (abort_countdown_ == 0) return kAbort;
4260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    CHECK_GT(chars_written, 0);
4270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    i::Vector<char> chunk = buffer_.AddBlock(chars_written, '\0');
4280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    memcpy(chunk.start(), buffer, chars_written);
4290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    return kContinue;
4300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
4310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  void WriteTo(i::Vector<char> dest) { buffer_.WriteTo(dest); }
4320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  int eos_signaled() { return eos_signaled_; }
4330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  int size() { return buffer_.size(); }
4340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen private:
4350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  i::Collector<char> buffer_;
4360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  int eos_signaled_;
4370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  int abort_countdown_;
4380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen};
4390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4400d5e116f6aee03185f237311a943491bb079a768Kristian Monsenclass AsciiResource: public v8::String::ExternalAsciiStringResource {
4410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen public:
4420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  explicit AsciiResource(i::Vector<char> string): data_(string.start()) {
4430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    length_ = string.length();
4440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
4450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  virtual const char* data() const { return data_; }
4460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  virtual size_t length() const { return length_; }
4470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen private:
4480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  const char* data_;
4490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  size_t length_;
4500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen};
4510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}  // namespace
4530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4540d5e116f6aee03185f237311a943491bb079a768Kristian MonsenTEST(HeapSnapshotJSONSerialization) {
4550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  v8::HandleScope scope;
4560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  LocalContext env;
4570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen#define STRING_LITERAL_FOR_TEST \
4590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  "\"String \\n\\r\\u0008\\u0081\\u0101\\u0801\\u8001\""
460f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CompileRun(
4610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "function A(s) { this.s = s; }\n"
4620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "function B(x) { this.x = x; }\n"
4630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "var a = new A(" STRING_LITERAL_FOR_TEST ");\n"
4640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "var b = new B(a);");
4650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  const v8::HeapSnapshot* snapshot =
46669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("json"));
4670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  TestJSONStream stream;
4680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  snapshot->Serialize(&stream, v8::HeapSnapshot::kJSON);
4690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  CHECK_GT(stream.size(), 0);
4700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  CHECK_EQ(1, stream.eos_signaled());
4710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  i::ScopedVector<char> json(stream.size());
4720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  stream.WriteTo(json);
4730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Verify that snapshot string is valid JSON.
4750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  AsciiResource json_res(json);
4760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  v8::Local<v8::String> json_string = v8::String::NewExternal(&json_res);
47769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  env->Global()->Set(v8_str("json_snapshot"), json_string);
4780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  v8::Local<v8::Value> snapshot_parse_result = CompileRun(
4790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "var parsed = JSON.parse(json_snapshot); true;");
4800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  CHECK(!snapshot_parse_result.IsEmpty());
4810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Verify that snapshot object has required fields.
4830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  v8::Local<v8::Object> parsed_snapshot =
48469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      env->Global()->Get(v8_str("parsed"))->ToObject();
48569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(parsed_snapshot->Has(v8_str("snapshot")));
48669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(parsed_snapshot->Has(v8_str("nodes")));
48769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(parsed_snapshot->Has(v8_str("strings")));
4880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Get node and edge "member" offsets.
4900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  v8::Local<v8::Value> meta_analysis_result = CompileRun(
4918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "var parsed_meta = parsed.nodes[0];\n"
4920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "var children_count_offset ="
4930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "    parsed_meta.fields.indexOf('children_count');\n"
4940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "var children_offset ="
4950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "    parsed_meta.fields.indexOf('children');\n"
4960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "var children_meta ="
4970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "    parsed_meta.types[children_offset];\n"
4980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "var child_fields_count = children_meta.fields.length;\n"
4990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "var child_type_offset ="
5000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "    children_meta.fields.indexOf('type');\n"
5010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "var child_name_offset ="
5020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "    children_meta.fields.indexOf('name_or_index');\n"
5030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "var child_to_node_offset ="
5040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "    children_meta.fields.indexOf('to_node');\n"
5050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "var property_type ="
5068a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "    children_meta.types[child_type_offset].indexOf('property');\n"
5078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "var shortcut_type ="
5088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "    children_meta.types[child_type_offset].indexOf('shortcut');");
5090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  CHECK(!meta_analysis_result.IsEmpty());
5100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // A helper function for processing encoded nodes.
5120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  CompileRun(
5138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "function GetChildPosByProperty(pos, prop_name, prop_type) {\n"
5140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "  var nodes = parsed.nodes;\n"
5150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "  var strings = parsed.strings;\n"
5160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "  for (var i = 0,\n"
5170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "      count = nodes[pos + children_count_offset] * child_fields_count;\n"
5180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "      i < count; i += child_fields_count) {\n"
5190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "    var child_pos = pos + children_offset + i;\n"
5208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "    if (nodes[child_pos + child_type_offset] === prop_type\n"
5210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "       && strings[nodes[child_pos + child_name_offset]] === prop_name)\n"
5220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "        return nodes[child_pos + child_to_node_offset];\n"
5230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "  }\n"
5240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "  return null;\n"
5250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "}\n");
5260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Get the string index using the path: <root> -> <global>.b.x.s
5270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  v8::Local<v8::Value> string_obj_pos_val = CompileRun(
5280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "GetChildPosByProperty(\n"
5290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "  GetChildPosByProperty(\n"
5300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "    GetChildPosByProperty("
5318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "      parsed.nodes[1 + children_offset + child_to_node_offset],"
5328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "      \"b\",shortcut_type),\n"
5338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "    \"x\", property_type),"
5348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "  \"s\", property_type)");
5350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  CHECK(!string_obj_pos_val.IsEmpty());
5360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  int string_obj_pos =
5370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      static_cast<int>(string_obj_pos_val->ToNumber()->Value());
5380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  v8::Local<v8::Object> nodes_array =
53969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      parsed_snapshot->Get(v8_str("nodes"))->ToObject();
5400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  int string_index = static_cast<int>(
5410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      nodes_array->Get(string_obj_pos + 1)->ToNumber()->Value());
5420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  CHECK_GT(string_index, 0);
5430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  v8::Local<v8::Object> strings_array =
54469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      parsed_snapshot->Get(v8_str("strings"))->ToObject();
5450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  v8::Local<v8::String> string = strings_array->Get(string_index)->ToString();
5460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  v8::Local<v8::String> ref_string =
5470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      CompileRun(STRING_LITERAL_FOR_TEST)->ToString();
5480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen#undef STRING_LITERAL_FOR_TEST
5490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  CHECK_EQ(*v8::String::Utf8Value(ref_string),
5500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen           *v8::String::Utf8Value(string));
5510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5540d5e116f6aee03185f237311a943491bb079a768Kristian MonsenTEST(HeapSnapshotJSONSerializationAborting) {
5550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  v8::HandleScope scope;
5560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  LocalContext env;
5570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  const v8::HeapSnapshot* snapshot =
55869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("abort"));
5590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  TestJSONStream stream(5);
5600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  snapshot->Serialize(&stream, v8::HeapSnapshot::kJSON);
5610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  CHECK_GT(stream.size(), 0);
5620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  CHECK_EQ(0, stream.eos_signaled());
5630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochTEST(HeapSnapshotGetNodeById) {
567b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  v8::HandleScope scope;
568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  LocalContext env;
569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const v8::HeapSnapshot* snapshot =
57169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("id"));
572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const v8::HeapGraphNode* root = snapshot->GetRoot();
573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(root, snapshot->GetNodeById(root->GetId()));
574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0, count = root->GetChildrenCount(); i < count; ++i) {
575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    const v8::HeapGraphEdge* prop = root->GetChild(i);
576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CHECK_EQ(
577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        prop->GetToNode(), snapshot->GetNodeById(prop->GetToNode()->GetId()));
578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Check a big id, which should not exist yet.
580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(NULL, snapshot->GetNodeById(0x1000000UL));
581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochnamespace {
585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass TestActivityControl : public v8::ActivityControl {
587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  explicit TestActivityControl(int abort_count)
589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      : done_(0), total_(0), abort_count_(abort_count) {}
590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ControlOption ReportProgressValue(int done, int total) {
591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    done_ = done;
592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    total_ = total;
593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return --abort_count_ != 0 ? kContinue : kAbort;
594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int done() { return done_; }
596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int total() { return total_; }
597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int done_;
600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int total_;
601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int abort_count_;
602b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochTEST(TakeHeapSnapshotAborting) {
606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  v8::HandleScope scope;
607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  LocalContext env;
608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const int snapshots_count = v8::HeapProfiler::GetSnapshotsCount();
610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TestActivityControl aborting_control(3);
611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const v8::HeapSnapshot* no_snapshot =
61269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("abort"),
613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                     v8::HeapSnapshot::kFull,
614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                     &aborting_control);
615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(NULL, no_snapshot);
616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(snapshots_count, v8::HeapProfiler::GetSnapshotsCount());
617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_GT(aborting_control.total(), aborting_control.done());
618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TestActivityControl control(-1);  // Don't abort.
620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const v8::HeapSnapshot* snapshot =
62169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("full"),
622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                     v8::HeapSnapshot::kFull,
623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                     &control);
624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_NE(NULL, snapshot);
625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(snapshots_count + 1, v8::HeapProfiler::GetSnapshotsCount());
626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(control.total(), control.done());
627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_GT(control.total(), 0);
628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
629b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
63044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
63144f0eee88ff00398ff7f715fab053374d808c90dSteve Blocknamespace {
63244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
63344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass TestRetainedObjectInfo : public v8::RetainedObjectInfo {
63444f0eee88ff00398ff7f715fab053374d808c90dSteve Block public:
63544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  TestRetainedObjectInfo(int hash,
63644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                         const char* label,
63744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                         intptr_t element_count = -1,
63844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                         intptr_t size = -1)
63944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : disposed_(false),
64044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        hash_(hash),
64144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        label_(label),
64244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        element_count_(element_count),
64344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        size_(size) {
64444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    instances.Add(this);
64544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
64644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  virtual ~TestRetainedObjectInfo() {}
64744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  virtual void Dispose() {
64844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    CHECK(!disposed_);
64944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    disposed_ = true;
65044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
65144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  virtual bool IsEquivalent(RetainedObjectInfo* other) {
65244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return GetHash() == other->GetHash();
65344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
65444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  virtual intptr_t GetHash() { return hash_; }
65544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  virtual const char* GetLabel() { return label_; }
65644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  virtual intptr_t GetElementCount() { return element_count_; }
65744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  virtual intptr_t GetSizeInBytes() { return size_; }
65844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bool disposed() { return disposed_; }
65944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
66044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static v8::RetainedObjectInfo* WrapperInfoCallback(
66144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      uint16_t class_id, v8::Handle<v8::Value> wrapper) {
66244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (class_id == 1) {
66344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (wrapper->IsString()) {
66444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        v8::String::AsciiValue ascii(wrapper);
66544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (strcmp(*ascii, "AAA") == 0)
66644f0eee88ff00398ff7f715fab053374d808c90dSteve Block          return new TestRetainedObjectInfo(1, "aaa", 100);
66744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        else if (strcmp(*ascii, "BBB") == 0)
66844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          return new TestRetainedObjectInfo(1, "aaa", 100);
66944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
67044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    } else if (class_id == 2) {
67144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (wrapper->IsString()) {
67244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        v8::String::AsciiValue ascii(wrapper);
67344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (strcmp(*ascii, "CCC") == 0)
67444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          return new TestRetainedObjectInfo(2, "ccc");
67544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
67644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
67744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    CHECK(false);
67844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return NULL;
67944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
68044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
68144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static i::List<TestRetainedObjectInfo*> instances;
68244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
68344f0eee88ff00398ff7f715fab053374d808c90dSteve Block private:
68444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bool disposed_;
68544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int category_;
68644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int hash_;
68744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const char* label_;
68844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  intptr_t element_count_;
68944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  intptr_t size_;
69044f0eee88ff00398ff7f715fab053374d808c90dSteve Block};
69144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
69244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
69344f0eee88ff00398ff7f715fab053374d808c90dSteve Blocki::List<TestRetainedObjectInfo*> TestRetainedObjectInfo::instances;
69444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
69544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
69644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
69744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic const v8::HeapGraphNode* GetNode(const v8::HeapGraphNode* parent,
69844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                        v8::HeapGraphNode::Type type,
69944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                        const char* name) {
70044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (int i = 0, count = parent->GetChildrenCount(); i < count; ++i) {
70144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    const v8::HeapGraphNode* node = parent->GetChild(i)->GetToNode();
70244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (node->GetType() == type && strcmp(name,
70344f0eee88ff00398ff7f715fab053374d808c90dSteve Block               const_cast<i::HeapEntry*>(
70444f0eee88ff00398ff7f715fab053374d808c90dSteve Block                   reinterpret_cast<const i::HeapEntry*>(node))->name()) == 0) {
70544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      return node;
70644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
70744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
70844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return NULL;
70944f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
71044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
71144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
71244f0eee88ff00398ff7f715fab053374d808c90dSteve BlockTEST(HeapSnapshotRetainedObjectInfo) {
71344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::HandleScope scope;
71444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LocalContext env;
71544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
71644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::HeapProfiler::DefineWrapperClass(
71744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      1, TestRetainedObjectInfo::WrapperInfoCallback);
71844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::HeapProfiler::DefineWrapperClass(
71944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      2, TestRetainedObjectInfo::WrapperInfoCallback);
72044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::Persistent<v8::String> p_AAA =
72144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      v8::Persistent<v8::String>::New(v8_str("AAA"));
72244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  p_AAA.SetWrapperClassId(1);
72344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::Persistent<v8::String> p_BBB =
72444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      v8::Persistent<v8::String>::New(v8_str("BBB"));
72544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  p_BBB.SetWrapperClassId(1);
72644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::Persistent<v8::String> p_CCC =
72744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      v8::Persistent<v8::String>::New(v8_str("CCC"));
72844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  p_CCC.SetWrapperClassId(2);
72944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, TestRetainedObjectInfo::instances.length());
73044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const v8::HeapSnapshot* snapshot =
73169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("retained"));
73244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
73344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(3, TestRetainedObjectInfo::instances.length());
73444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (int i = 0; i < TestRetainedObjectInfo::instances.length(); ++i) {
73544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    CHECK(TestRetainedObjectInfo::instances[i]->disposed());
73644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    delete TestRetainedObjectInfo::instances[i];
73744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
73844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
73944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const v8::HeapGraphNode* natives = GetNode(
74044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      snapshot->GetRoot(), v8::HeapGraphNode::kObject, "(Native objects)");
74144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_NE(NULL, natives);
74244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(2, natives->GetChildrenCount());
74344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const v8::HeapGraphNode* aaa = GetNode(
74444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      natives, v8::HeapGraphNode::kNative, "aaa / 100 entries");
74544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_NE(NULL, aaa);
74644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const v8::HeapGraphNode* ccc = GetNode(
74744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      natives, v8::HeapGraphNode::kNative, "ccc");
74844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_NE(NULL, ccc);
74944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
75044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(2, aaa->GetChildrenCount());
75144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const v8::HeapGraphNode* n_AAA = GetNode(
75244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      aaa, v8::HeapGraphNode::kString, "AAA");
75344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_NE(NULL, n_AAA);
75444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const v8::HeapGraphNode* n_BBB = GetNode(
75544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      aaa, v8::HeapGraphNode::kString, "BBB");
75644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_NE(NULL, n_BBB);
75744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(1, ccc->GetChildrenCount());
75844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const v8::HeapGraphNode* n_CCC = GetNode(
75944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ccc, v8::HeapGraphNode::kString, "CCC");
76044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_NE(NULL, n_CCC);
76144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
7628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_EQ(aaa, GetProperty(n_AAA, v8::HeapGraphEdge::kInternal, "native"));
7638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_EQ(aaa, GetProperty(n_BBB, v8::HeapGraphEdge::kInternal, "native"));
7648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_EQ(ccc, GetProperty(n_CCC, v8::HeapGraphEdge::kInternal, "native"));
76544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
76644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
76744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
76844f0eee88ff00398ff7f715fab053374d808c90dSteve BlockTEST(DeleteAllHeapSnapshots) {
76944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::HandleScope scope;
77044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LocalContext env;
77144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
77244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount());
77344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::HeapProfiler::DeleteAllSnapshots();
77444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount());
77569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_NE(NULL, v8::HeapProfiler::TakeSnapshot(v8_str("1")));
77644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(1, v8::HeapProfiler::GetSnapshotsCount());
77744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::HeapProfiler::DeleteAllSnapshots();
77844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount());
77969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_NE(NULL, v8::HeapProfiler::TakeSnapshot(v8_str("1")));
78069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_NE(NULL, v8::HeapProfiler::TakeSnapshot(v8_str("2")));
78144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(2, v8::HeapProfiler::GetSnapshotsCount());
78244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::HeapProfiler::DeleteAllSnapshots();
78344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount());
78444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
78544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
78644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
78744f0eee88ff00398ff7f715fab053374d808c90dSteve BlockTEST(DeleteHeapSnapshot) {
78844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::HandleScope scope;
78944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LocalContext env;
79044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
79144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount());
79244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const v8::HeapSnapshot* s1 =
79369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("1"));
79444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_NE(NULL, s1);
79544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(1, v8::HeapProfiler::GetSnapshotsCount());
79644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  unsigned uid1 = s1->GetUid();
79744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(s1, v8::HeapProfiler::FindSnapshot(uid1));
79844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const_cast<v8::HeapSnapshot*>(s1)->Delete();
79944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount());
80044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(NULL, v8::HeapProfiler::FindSnapshot(uid1));
80144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
80244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const v8::HeapSnapshot* s2 =
80369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("2"));
80444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_NE(NULL, s2);
80544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(1, v8::HeapProfiler::GetSnapshotsCount());
80644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  unsigned uid2 = s2->GetUid();
80744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid2));
80844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(s2, v8::HeapProfiler::FindSnapshot(uid2));
80944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const v8::HeapSnapshot* s3 =
81069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("3"));
81144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_NE(NULL, s3);
81244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(2, v8::HeapProfiler::GetSnapshotsCount());
81344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  unsigned uid3 = s3->GetUid();
81444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid3));
81544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(s3, v8::HeapProfiler::FindSnapshot(uid3));
81644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const_cast<v8::HeapSnapshot*>(s2)->Delete();
81744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(1, v8::HeapProfiler::GetSnapshotsCount());
81844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(NULL, v8::HeapProfiler::FindSnapshot(uid2));
81944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(s3, v8::HeapProfiler::FindSnapshot(uid3));
82044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const_cast<v8::HeapSnapshot*>(s3)->Delete();
82144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount());
82244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(NULL, v8::HeapProfiler::FindSnapshot(uid3));
82344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
82444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
8253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
8263fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochTEST(DocumentURL) {
8273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::HandleScope scope;
8283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  LocalContext env;
8293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
8303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CompileRun("document = { URL:\"abcdefgh\" };");
8313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
8323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const v8::HeapSnapshot* snapshot =
83369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("document"));
8343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
8353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_NE(NULL, global);
8363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_EQ("Object / abcdefgh",
8373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch           const_cast<i::HeapEntry*>(
8383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch               reinterpret_cast<const i::HeapEntry*>(global))->name());
8393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
8403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
8413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
8423fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochTEST(DocumentWithException) {
8433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::HandleScope scope;
8443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  LocalContext env;
8453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
8463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CompileRun(
8473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      "this.__defineGetter__(\"document\", function() { throw new Error(); })");
8483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const v8::HeapSnapshot* snapshot =
84969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("document"));
8503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
8513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_NE(NULL, global);
8523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_EQ("Object",
8533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch           const_cast<i::HeapEntry*>(
8543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch               reinterpret_cast<const i::HeapEntry*>(global))->name());
8553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
8563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
8573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
8583fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochTEST(DocumentURLWithException) {
8593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::HandleScope scope;
8603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  LocalContext env;
8613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
8623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CompileRun(
8633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      "function URLWithException() {}\n"
8643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      "URLWithException.prototype = { get URL() { throw new Error(); } };\n"
8653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      "document = { URL: new URLWithException() };");
8663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const v8::HeapSnapshot* snapshot =
86769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("document"));
8683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
8693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_NE(NULL, global);
8703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_EQ("Object",
8713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch           const_cast<i::HeapEntry*>(
8723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch               reinterpret_cast<const i::HeapEntry*>(global))->name());
8733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
8743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
8753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
8763fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochTEST(NodesIteration) {
8773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::HandleScope scope;
8783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  LocalContext env;
8793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const v8::HeapSnapshot* snapshot =
88069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("iteration"));
8813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
8823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_NE(NULL, global);
8833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Verify that we can find this object by iteration.
8843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const int nodes_count = snapshot->GetNodesCount();
8853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int count = 0;
8863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (int i = 0; i < nodes_count; ++i) {
8873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (snapshot->GetNode(i) == global)
8883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ++count;
8893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
8903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_EQ(1, count);
8913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
89269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
89369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
89469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen MurdochTEST(GetHeapValue) {
89569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  v8::HandleScope scope;
89669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  LocalContext env;
89769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
89869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CompileRun("a = { s_prop: \'value\', n_prop: 0.1 };");
89969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  const v8::HeapSnapshot* snapshot =
90069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("value"));
90169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
90269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(global->GetHeapValue()->IsObject());
90369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  v8::Local<v8::Object> js_global =
90469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      env->Global()->GetPrototype().As<v8::Object>();
90569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(js_global == global->GetHeapValue());
90669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  const v8::HeapGraphNode* obj = GetProperty(
90769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      global, v8::HeapGraphEdge::kShortcut, "a");
90869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(obj->GetHeapValue()->IsObject());
90969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  v8::Local<v8::Object> js_obj = js_global->Get(v8_str("a")).As<v8::Object>();
91069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(js_obj == obj->GetHeapValue());
91169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  const v8::HeapGraphNode* s_prop =
91269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      GetProperty(obj, v8::HeapGraphEdge::kProperty, "s_prop");
91369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  v8::Local<v8::String> js_s_prop =
91469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      js_obj->Get(v8_str("s_prop")).As<v8::String>();
91569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(js_s_prop == s_prop->GetHeapValue());
91669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  const v8::HeapGraphNode* n_prop =
91769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      GetProperty(obj, v8::HeapGraphEdge::kProperty, "n_prop");
91869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  v8::Local<v8::Number> js_n_prop =
91969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      js_obj->Get(v8_str("n_prop")).As<v8::Number>();
92069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(js_n_prop == n_prop->GetHeapValue());
92169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
92269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
92369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
92469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen MurdochTEST(GetHeapValueForDeletedObject) {
92569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  v8::HandleScope scope;
92669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  LocalContext env;
92769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
92869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // It is impossible to delete a global property, so we are about to delete a
92969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // property of the "a" object. Also, the "p" object can't be an empty one
93069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // because the empty object is static and isn't actually deleted.
93169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CompileRun("a = { p: { r: {} } };");
93269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  const v8::HeapSnapshot* snapshot =
93369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("snapshot"));
93469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
93569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  const v8::HeapGraphNode* obj = GetProperty(
93669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      global, v8::HeapGraphEdge::kShortcut, "a");
93769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  const v8::HeapGraphNode* prop = GetProperty(
93869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      obj, v8::HeapGraphEdge::kProperty, "p");
93969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  {
94069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    // Perform the check inside a nested local scope to avoid creating a
94169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    // reference to the object we are deleting.
94269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    v8::HandleScope scope;
94369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    CHECK(prop->GetHeapValue()->IsObject());
94469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
94569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CompileRun("delete a.p;");
94669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(prop->GetHeapValue()->IsUndefined());
94769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
94869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
94969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
95069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic int StringCmp(const char* ref, i::String* act) {
95169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  i::SmartPointer<char> s_act = act->ToCString();
95269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  int result = strcmp(ref, *s_act);
95369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  if (result != 0)
95469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    fprintf(stderr, "Expected: \"%s\", Actual: \"%s\"\n", ref, *s_act);
95569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  return result;
95669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
95769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
95869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
95969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen MurdochTEST(GetConstructorName) {
96069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  v8::HandleScope scope;
96169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  LocalContext env;
96269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
96369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CompileRun(
96469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "function Constructor1() {};\n"
96569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "var obj1 = new Constructor1();\n"
96669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "var Constructor2 = function() {};\n"
96769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "var obj2 = new Constructor2();\n"
96869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "var obj3 = {};\n"
96969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "obj3.constructor = function Constructor3() {};\n"
97069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "var obj4 = {};\n"
97169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "// Slow properties\n"
97269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "for (var i=0; i<2000; ++i) obj4[\"p\" + i] = i;\n"
97369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "obj4.constructor = function Constructor4() {};\n"
97469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "var obj5 = {};\n"
97569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "var obj6 = {};\n"
97669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "obj6.constructor = 6;");
97769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  v8::Local<v8::Object> js_global =
97869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      env->Global()->GetPrototype().As<v8::Object>();
97969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  v8::Local<v8::Object> obj1 = js_global->Get(v8_str("obj1")).As<v8::Object>();
98069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  i::Handle<i::JSObject> js_obj1 = v8::Utils::OpenHandle(*obj1);
98169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(0, StringCmp(
98269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "Constructor1", i::V8HeapExplorer::GetConstructorName(*js_obj1)));
98369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  v8::Local<v8::Object> obj2 = js_global->Get(v8_str("obj2")).As<v8::Object>();
98469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  i::Handle<i::JSObject> js_obj2 = v8::Utils::OpenHandle(*obj2);
98569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(0, StringCmp(
98669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "Constructor2", i::V8HeapExplorer::GetConstructorName(*js_obj2)));
98769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  v8::Local<v8::Object> obj3 = js_global->Get(v8_str("obj3")).As<v8::Object>();
98869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  i::Handle<i::JSObject> js_obj3 = v8::Utils::OpenHandle(*obj3);
98969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(0, StringCmp(
99069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "Constructor3", i::V8HeapExplorer::GetConstructorName(*js_obj3)));
99169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  v8::Local<v8::Object> obj4 = js_global->Get(v8_str("obj4")).As<v8::Object>();
99269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  i::Handle<i::JSObject> js_obj4 = v8::Utils::OpenHandle(*obj4);
99369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(0, StringCmp(
99469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "Constructor4", i::V8HeapExplorer::GetConstructorName(*js_obj4)));
99569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  v8::Local<v8::Object> obj5 = js_global->Get(v8_str("obj5")).As<v8::Object>();
99669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  i::Handle<i::JSObject> js_obj5 = v8::Utils::OpenHandle(*obj5);
99769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(0, StringCmp(
99869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "Object", i::V8HeapExplorer::GetConstructorName(*js_obj5)));
99969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  v8::Local<v8::Object> obj6 = js_global->Get(v8_str("obj6")).As<v8::Object>();
100069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  i::Handle<i::JSObject> js_obj6 = v8::Utils::OpenHandle(*obj6);
100169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(0, StringCmp(
100269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "Object", i::V8HeapExplorer::GetConstructorName(*js_obj6)));
100369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
1004