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
213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CheckEntry(i::HeapEntry* entry) {
223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (strcmp(entry->name(), "A2") == 0) has_A2 = true;
233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (strcmp(entry->name(), "B2") == 0) has_B2 = true;
243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (strcmp(entry->name(), "C2") == 0) has_C2 = true;
25756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
26756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CheckAllReachables(i::HeapEntry* root) {
283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    i::List<i::HeapEntry*> list(10);
293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    list.Add(root);
303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    root->paint();
313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CheckEntry(root);
323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    while (!list.is_empty()) {
333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      i::HeapEntry* entry = list.RemoveLast();
343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      i::Vector<i::HeapGraphEdge> children = entry->children();
353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      for (int i = 0; i < children.length(); ++i) {
363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (children[i].type() == i::HeapGraphEdge::kShortcut) continue;
373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        i::HeapEntry* child = children[i].to();
383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (!child->painted()) {
393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          list.Add(child);
403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          child->paint();
413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          CheckEntry(child);
423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
459dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
479dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  bool has_A2;
489dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  bool has_B2;
499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  bool has_C2;
509dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen};
519dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
529dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}  // namespace
539dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
549dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
559dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenstatic const v8::HeapGraphNode* GetGlobalObject(
569dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    const v8::HeapSnapshot* snapshot) {
578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_EQ(2, snapshot->GetRoot()->GetChildrenCount());
588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  const v8::HeapGraphNode* global_obj =
598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      snapshot->GetRoot()->GetChild(0)->GetToNode();
603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_EQ(0, strncmp("Object", const_cast<i::HeapEntry*>(
613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      reinterpret_cast<const i::HeapEntry*>(global_obj))->name(), 6));
628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  return global_obj;
639dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
649dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
659dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
669dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenstatic const v8::HeapGraphNode* GetProperty(const v8::HeapGraphNode* node,
679dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                            v8::HeapGraphEdge::Type type,
689dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen                                            const char* name) {
699dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) {
709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    const v8::HeapGraphEdge* prop = node->GetChild(i);
719dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    v8::String::AsciiValue prop_name(prop->GetName());
729dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    if (prop->GetType() == type && strcmp(name, *prop_name) == 0)
739dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      return prop->GetToNode();
749dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
759dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  return NULL;
769dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
779dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
789dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
799dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsenstatic bool HasString(const v8::HeapGraphNode* node, const char* contents) {
809dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) {
819dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    const v8::HeapGraphEdge* prop = node->GetChild(i);
829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    const v8::HeapGraphNode* node = prop->GetToNode();
83756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (node->GetType() == v8::HeapGraphNode::kString) {
849dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      v8::String::AsciiValue node_name(node->GetName());
859dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      if (strcmp(contents, *node_name) == 0) return true;
869dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    }
879dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
889dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  return false;
899dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
909dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
919dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
929dcf7e2f83591d471e88bf7d230651900b8e424bKristian MonsenTEST(HeapSnapshot) {
939dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  v8::HandleScope scope;
943bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  LocalContext env2;
959dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
96f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CompileRun(
979dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      "function A2() {}\n"
989dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      "function B2(x) { return function() { return typeof x; }; }\n"
999dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      "function C2(x) { this.x1 = x; this.x2 = x; this[1] = x; }\n"
1009dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      "var a2 = new A2();\n"
1019dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      "var b2_1 = new B2(a2), b2_2 = new B2(a2);\n"
1029dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      "var c2 = new C2(a2);");
1039dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  const v8::HeapSnapshot* snapshot_env2 =
10469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("env2"));
105756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  i::HeapSnapshot* i_snapshot_env2 =
106756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      const_cast<i::HeapSnapshot*>(
107756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick          reinterpret_cast<const i::HeapSnapshot*>(snapshot_env2));
1089dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  const v8::HeapGraphNode* global_env2 = GetGlobalObject(snapshot_env2);
1099dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
11090bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  // Verify, that JS global object of env2 has '..2' properties.
1119dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  const v8::HeapGraphNode* a2_node =
1128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "a2");
1139dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  CHECK_NE(NULL, a2_node);
114756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_NE(
1158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "b2_1"));
116756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_NE(
1178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "b2_2"));
1188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_NE(NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "c2"));
1199dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
1203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Paint all nodes reachable from global object.
1219dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  NamedEntriesDetector det;
1223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  i_snapshot_env2->ClearPaint();
1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  det.CheckAllReachables(const_cast<i::HeapEntry*>(
1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      reinterpret_cast<const i::HeapEntry*>(global_env2)));
1259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  CHECK(det.has_A2);
1269dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  CHECK(det.has_B2);
1279dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  CHECK(det.has_C2);
1289dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
1299dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
1309dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
131756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain MerrickTEST(HeapSnapshotObjectSizes) {
132756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  v8::HandleScope scope;
133756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  LocalContext env;
134756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
135756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  //   -a-> X1 --a
136756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // x -b-> X2 <-|
137f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CompileRun(
138756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      "function X(a, b) { this.a = a; this.b = b; }\n"
139756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      "x = new X(new X(), new X());\n"
1408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "(function() { x.a.a = x.b; })();");
141756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const v8::HeapSnapshot* snapshot =
14269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("sizes"));
143756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
144756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const v8::HeapGraphNode* x =
1458a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      GetProperty(global, v8::HeapGraphEdge::kShortcut, "x");
146756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_NE(NULL, x);
147756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const v8::HeapGraphNode* x1 =
148756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      GetProperty(x, v8::HeapGraphEdge::kProperty, "a");
149756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_NE(NULL, x1);
150756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const v8::HeapGraphNode* x2 =
151756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      GetProperty(x, v8::HeapGraphEdge::kProperty, "b");
152756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_NE(NULL, x2);
1538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
1543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Test sizes.
1553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(x->GetSelfSize() * 3, x->GetRetainedSize());
1563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(x1->GetSelfSize(), x1->GetRetainedSize());
1573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(x2->GetSelfSize(), x2->GetRetainedSize());
1583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1613ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(BoundFunctionInSnapshot) {
1623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::HandleScope scope;
1633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
1643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun(
1653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "function myFunction(a, b) { this.a = a; this.b = b; }\n"
1663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "function AAAAA() {}\n"
1673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "boundFunction = myFunction.bind(new AAAAA(), 20, new Number(12)); \n");
1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapSnapshot* snapshot =
1693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("sizes"));
1703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
1713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* f =
1723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GetProperty(global, v8::HeapGraphEdge::kShortcut, "boundFunction");
1733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(f);
1743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(v8::String::New("native_bind"), f->GetName());
1753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* bindings =
1763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GetProperty(f, v8::HeapGraphEdge::kInternal, "bindings");
1773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_NE(NULL, bindings);
1783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(v8::HeapGraphNode::kArray, bindings->GetType());
1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(4, bindings->GetChildrenCount());
1803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* bound_this = GetProperty(
1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      f, v8::HeapGraphEdge::kShortcut, "bound_this");
1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(bound_this);
1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(v8::HeapGraphNode::kObject, bound_this->GetType());
1853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* bound_function = GetProperty(
1873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      f, v8::HeapGraphEdge::kShortcut, "bound_function");
1883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(bound_function);
1893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(v8::HeapGraphNode::kClosure, bound_function->GetType());
1903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* bound_argument = GetProperty(
1923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      f, v8::HeapGraphEdge::kShortcut, "bound_argument_1");
1933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(bound_argument);
1943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(v8::HeapGraphNode::kObject, bound_argument->GetType());
195756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
196756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
197756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
198756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain MerrickTEST(HeapSnapshotEntryChildren) {
199756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  v8::HandleScope scope;
200756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  LocalContext env;
201756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
202f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CompileRun(
203756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      "function A() { }\n"
204756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      "a = new A;");
205756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const v8::HeapSnapshot* snapshot =
20669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("children"));
207756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
208756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  for (int i = 0, count = global->GetChildrenCount(); i < count; ++i) {
209756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    const v8::HeapGraphEdge* prop = global->GetChild(i);
210756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    CHECK_EQ(global, prop->GetFromNode());
211756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
212756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  const v8::HeapGraphNode* a =
213756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      GetProperty(global, v8::HeapGraphEdge::kProperty, "a");
214756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_NE(NULL, a);
215756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  for (int i = 0, count = a->GetChildrenCount(); i < count; ++i) {
216756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    const v8::HeapGraphEdge* prop = a->GetChild(i);
217756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    CHECK_EQ(a, prop->GetFromNode());
218756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
219756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick}
220756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
221756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2229dcf7e2f83591d471e88bf7d230651900b8e424bKristian MonsenTEST(HeapSnapshotCodeObjects) {
2239dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  v8::HandleScope scope;
2243bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  LocalContext env;
2259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
226f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CompileRun(
2279dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      "function lazy(x) { return x - 1; }\n"
2289dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      "function compiled(x) { return x + 1; }\n"
229791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block      "var anonymous = (function() { return function() { return 0; } })();\n"
2309dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      "compiled(1)");
2319dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  const v8::HeapSnapshot* snapshot =
23269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("code"));
2339dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
2349dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
2359dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  const v8::HeapGraphNode* compiled =
2368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      GetProperty(global, v8::HeapGraphEdge::kShortcut, "compiled");
2379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  CHECK_NE(NULL, compiled);
238756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_EQ(v8::HeapGraphNode::kClosure, compiled->GetType());
2399dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  const v8::HeapGraphNode* lazy =
2408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      GetProperty(global, v8::HeapGraphEdge::kShortcut, "lazy");
2419dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  CHECK_NE(NULL, lazy);
242756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_EQ(v8::HeapGraphNode::kClosure, lazy->GetType());
243791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  const v8::HeapGraphNode* anonymous =
2448a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      GetProperty(global, v8::HeapGraphEdge::kShortcut, "anonymous");
245791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  CHECK_NE(NULL, anonymous);
246791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  CHECK_EQ(v8::HeapGraphNode::kClosure, anonymous->GetType());
247791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  v8::String::AsciiValue anonymous_name(anonymous->GetName());
248f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK_EQ("", *anonymous_name);
2499dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
2509dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Find references to code.
2519dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  const v8::HeapGraphNode* compiled_code =
2528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      GetProperty(compiled, v8::HeapGraphEdge::kInternal, "shared");
2539dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  CHECK_NE(NULL, compiled_code);
2549dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  const v8::HeapGraphNode* lazy_code =
2558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      GetProperty(lazy, v8::HeapGraphEdge::kInternal, "shared");
2569dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  CHECK_NE(NULL, lazy_code);
2579dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
2589dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  // Verify that non-compiled code doesn't contain references to "x"
2593bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // literal, while compiled code does. The scope info is stored in FixedArray
2603bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // objects attached to the SharedFunctionInfo.
2619dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  bool compiled_references_x = false, lazy_references_x = false;
2629dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  for (int i = 0, count = compiled_code->GetChildrenCount(); i < count; ++i) {
2639dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    const v8::HeapGraphEdge* prop = compiled_code->GetChild(i);
2649dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    const v8::HeapGraphNode* node = prop->GetToNode();
265756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (node->GetType() == v8::HeapGraphNode::kArray) {
2669dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      if (HasString(node, "x")) {
2679dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        compiled_references_x = true;
2689dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        break;
2699dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      }
2709dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    }
2719dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
2729dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  for (int i = 0, count = lazy_code->GetChildrenCount(); i < count; ++i) {
2739dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    const v8::HeapGraphEdge* prop = lazy_code->GetChild(i);
2749dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    const v8::HeapGraphNode* node = prop->GetToNode();
275756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    if (node->GetType() == v8::HeapGraphNode::kArray) {
2769dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      if (HasString(node, "x")) {
2779dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        lazy_references_x = true;
2789dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen        break;
2799dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen      }
2809dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen    }
2819dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  }
2829dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  CHECK(compiled_references_x);
2839dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen  CHECK(!lazy_references_x);
2849dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
2859dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
2863bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
287f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochTEST(HeapSnapshotHeapNumbers) {
288f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  v8::HandleScope scope;
289f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  LocalContext env;
290f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CompileRun(
291f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "a = 1;    // a is Smi\n"
292f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      "b = 2.5;  // b is HeapNumber");
293f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  const v8::HeapSnapshot* snapshot =
29469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("numbers"));
295f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
2968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_EQ(NULL, GetProperty(global, v8::HeapGraphEdge::kShortcut, "a"));
297f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  const v8::HeapGraphNode* b =
2988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      GetProperty(global, v8::HeapGraphEdge::kShortcut, "b");
299f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK_NE(NULL, b);
300f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK_EQ(v8::HeapGraphNode::kHeapNumber, b->GetType());
301f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch}
302f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
3033ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(HeapSnapshotSlicedString) {
3043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::HandleScope scope;
3053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
3063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun(
3073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "parent_string = \"123456789.123456789.123456789.123456789.123456789."
3083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "123456789.123456789.123456789.123456789.123456789."
3093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "123456789.123456789.123456789.123456789.123456789."
3103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "123456789.123456789.123456789.123456789.123456789.\";"
3113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "child_string = parent_string.slice(100);");
3123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapSnapshot* snapshot =
3133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("strings"));
3143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
3153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* parent_string =
3163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GetProperty(global, v8::HeapGraphEdge::kShortcut, "parent_string");
3173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_NE(NULL, parent_string);
3183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* child_string =
3193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GetProperty(global, v8::HeapGraphEdge::kShortcut, "child_string");
3203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_NE(NULL, child_string);
3213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* parent =
3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GetProperty(child_string, v8::HeapGraphEdge::kInternal, "parent");
3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(parent_string, parent);
3243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
325f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
326f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochTEST(HeapSnapshotInternalReferences) {
327f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  v8::HandleScope scope;
328f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  v8::Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
329f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  global_template->SetInternalFieldCount(2);
330f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  LocalContext env(NULL, global_template);
331f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  v8::Handle<v8::Object> global_proxy = env->Global();
332f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  v8::Handle<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>();
333f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK_EQ(2, global->InternalFieldCount());
334f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  v8::Local<v8::Object> obj = v8::Object::New();
335f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  global->SetInternalField(0, v8_num(17));
336f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  global->SetInternalField(1, obj);
337f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  const v8::HeapSnapshot* snapshot =
33869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("internals"));
339f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  const v8::HeapGraphNode* global_node = GetGlobalObject(snapshot);
340f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // The first reference will not present, because it's a Smi.
341f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK_EQ(NULL, GetProperty(global_node, v8::HeapGraphEdge::kInternal, "0"));
342f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  // The second reference is to an object.
343f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK_NE(NULL, GetProperty(global_node, v8::HeapGraphEdge::kInternal, "1"));
344f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch}
345f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
346f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
3473bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// Trying to introduce a check helper for uint64_t causes many
3483bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// overloading ambiguities, so it seems easier just to cast
3493bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// them to a signed type.
3503bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch#define CHECK_EQ_UINT64_T(a, b) \
3513bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CHECK_EQ(static_cast<int64_t>(a), static_cast<int64_t>(b))
352756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick#define CHECK_NE_UINT64_T(a, b) \
353756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK((a) != (b))  // NOLINT
3543bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(HeapEntryIdsAndArrayShift) {
3563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::HandleScope scope;
3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun(
3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "function AnObject() {\n"
3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "    this.first = 'first';\n"
3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "    this.second = 'second';\n"
3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "}\n"
3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "var a = new Array();\n"
3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "for (var i = 0; i < 10; ++i)\n"
3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "  a.push(new AnObject());\n");
3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapSnapshot* snapshot1 =
3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("s1"));
3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun(
3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "for (var i = 0; i < 1; ++i)\n"
3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "  a.shift();\n");
3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapSnapshot* snapshot2 =
3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("s2"));
3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* global1 = GetGlobalObject(snapshot1);
3803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* global2 = GetGlobalObject(snapshot2);
3813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_NE_UINT64_T(0, global1->GetId());
3823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ_UINT64_T(global1->GetId(), global2->GetId());
3833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* a1 =
3853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GetProperty(global1, v8::HeapGraphEdge::kProperty, "a");
3863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_NE(NULL, a1);
3873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* e1 =
3883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GetProperty(a1, v8::HeapGraphEdge::kHidden, "1");
3893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_NE(NULL, e1);
3903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* k1 =
3913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GetProperty(e1, v8::HeapGraphEdge::kInternal, "elements");
3923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_NE(NULL, k1);
3933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* a2 =
3943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GetProperty(global2, v8::HeapGraphEdge::kProperty, "a");
3953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_NE(NULL, a2);
3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* e2 =
3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GetProperty(a2, v8::HeapGraphEdge::kHidden, "1");
3983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_NE(NULL, e2);
3993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* k2 =
4003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GetProperty(e2, v8::HeapGraphEdge::kInternal, "elements");
4013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_NE(NULL, k2);
4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ_UINT64_T(a1->GetId(), a2->GetId());
4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ_UINT64_T(e1->GetId(), e2->GetId());
4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ_UINT64_T(k1->GetId(), k2->GetId());
4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4083bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben MurdochTEST(HeapEntryIdsAndGC) {
4093bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  v8::HandleScope scope;
4103bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  LocalContext env;
4113bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
412f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CompileRun(
4133bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      "function A() {}\n"
4143bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      "function B(x) { this.x = x; }\n"
4153bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      "var a = new A();\n"
4163bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      "var b = new B(a);");
4173bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  const v8::HeapSnapshot* snapshot1 =
41869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("s1"));
4193bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
4203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
4213bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
4223bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  const v8::HeapSnapshot* snapshot2 =
42369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("s2"));
4243bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
4253bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  const v8::HeapGraphNode* global1 = GetGlobalObject(snapshot1);
4263bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  const v8::HeapGraphNode* global2 = GetGlobalObject(snapshot2);
4273bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CHECK_NE_UINT64_T(0, global1->GetId());
4283bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CHECK_EQ_UINT64_T(global1->GetId(), global2->GetId());
4293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  const v8::HeapGraphNode* A1 =
430756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      GetProperty(global1, v8::HeapGraphEdge::kProperty, "A");
431756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_NE(NULL, A1);
4323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  const v8::HeapGraphNode* A2 =
433756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      GetProperty(global2, v8::HeapGraphEdge::kProperty, "A");
434756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_NE(NULL, A2);
4353bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CHECK_NE_UINT64_T(0, A1->GetId());
4363bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CHECK_EQ_UINT64_T(A1->GetId(), A2->GetId());
4373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  const v8::HeapGraphNode* B1 =
438756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      GetProperty(global1, v8::HeapGraphEdge::kProperty, "B");
439756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_NE(NULL, B1);
4403bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  const v8::HeapGraphNode* B2 =
441756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      GetProperty(global2, v8::HeapGraphEdge::kProperty, "B");
442756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_NE(NULL, B2);
4433bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CHECK_NE_UINT64_T(0, B1->GetId());
4443bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CHECK_EQ_UINT64_T(B1->GetId(), B2->GetId());
4453bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  const v8::HeapGraphNode* a1 =
446756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      GetProperty(global1, v8::HeapGraphEdge::kProperty, "a");
447756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_NE(NULL, a1);
4483bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  const v8::HeapGraphNode* a2 =
449756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      GetProperty(global2, v8::HeapGraphEdge::kProperty, "a");
450756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_NE(NULL, a2);
4513bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CHECK_NE_UINT64_T(0, a1->GetId());
4523bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CHECK_EQ_UINT64_T(a1->GetId(), a2->GetId());
4533bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  const v8::HeapGraphNode* b1 =
454756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      GetProperty(global1, v8::HeapGraphEdge::kProperty, "b");
455756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_NE(NULL, b1);
4563bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  const v8::HeapGraphNode* b2 =
457756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick      GetProperty(global2, v8::HeapGraphEdge::kProperty, "b");
458756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  CHECK_NE(NULL, b2);
4593bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CHECK_NE_UINT64_T(0, b1->GetId());
4603bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  CHECK_EQ_UINT64_T(b1->GetId(), b2->GetId());
4613bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
4623bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
4633bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
464f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochTEST(HeapSnapshotRootPreservedAfterSorting) {
465f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  v8::HandleScope scope;
466f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  LocalContext env;
467f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  const v8::HeapSnapshot* snapshot =
46869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("s"));
469f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  const v8::HeapGraphNode* root1 = snapshot->GetRoot();
470f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  const_cast<i::HeapSnapshot*>(reinterpret_cast<const i::HeapSnapshot*>(
471f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      snapshot))->GetSortedEntriesList();
472f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  const v8::HeapGraphNode* root2 = snapshot->GetRoot();
473f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CHECK_EQ(root1, root2);
474f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch}
475f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
476f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
4778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) WangTEST(HeapEntryDominator) {
4788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // The graph looks like this:
4798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //
4808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //                   -> node1
4818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //                  a    |^
4828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //          -> node5     ba
4838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //         a             v|
4848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //   node6           -> node2
4858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //         b        a    |^
4868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //          -> node4     ba
4878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //                  b    v|
4888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //                   -> node3
4898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  //
4908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // The dominator for all nodes is node6.
4918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
4928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  v8::HandleScope scope;
4938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  LocalContext env;
4948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
4958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CompileRun(
4968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "function X(a, b) { this.a = a; this.b = b; }\n"
4978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "node6 = new X(new X(new X()), new X(new X(),new X()));\n"
4988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "(function(){\n"
4998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "node6.a.a.b = node6.b.a;  // node1 -> node2\n"
5008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "node6.b.a.a = node6.a.a;  // node2 -> node1\n"
5018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "node6.b.a.b = node6.b.b;  // node2 -> node3\n"
5028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "node6.b.b.a = node6.b.a;  // node3 -> node2\n"
5038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "})();");
5048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
5058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  const v8::HeapSnapshot* snapshot =
50669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("dominators"));
5078a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
5088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
5098a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_NE(NULL, global);
5108a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  const v8::HeapGraphNode* node6 =
5118a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      GetProperty(global, v8::HeapGraphEdge::kShortcut, "node6");
5128a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_NE(NULL, node6);
5138a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  const v8::HeapGraphNode* node5 =
5148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      GetProperty(node6, v8::HeapGraphEdge::kProperty, "a");
5158a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_NE(NULL, node5);
5168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  const v8::HeapGraphNode* node4 =
5178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      GetProperty(node6, v8::HeapGraphEdge::kProperty, "b");
5188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_NE(NULL, node4);
5198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  const v8::HeapGraphNode* node3 =
5208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      GetProperty(node4, v8::HeapGraphEdge::kProperty, "b");
5218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_NE(NULL, node3);
5228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  const v8::HeapGraphNode* node2 =
5238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      GetProperty(node4, v8::HeapGraphEdge::kProperty, "a");
5248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_NE(NULL, node2);
5258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  const v8::HeapGraphNode* node1 =
5268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      GetProperty(node5, v8::HeapGraphEdge::kProperty, "a");
5278a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_NE(NULL, node1);
5288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
5298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_EQ(node6, node1->GetDominatorNode());
5308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_EQ(node6, node2->GetDominatorNode());
5318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_EQ(node6, node3->GetDominatorNode());
5328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_EQ(node6, node4->GetDominatorNode());
5338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  CHECK_EQ(node6, node5->GetDominatorNode());
5348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
5358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
5368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
5370d5e116f6aee03185f237311a943491bb079a768Kristian Monsennamespace {
5380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5390d5e116f6aee03185f237311a943491bb079a768Kristian Monsenclass TestJSONStream : public v8::OutputStream {
5400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen public:
5410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  TestJSONStream() : eos_signaled_(0), abort_countdown_(-1) {}
5420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  explicit TestJSONStream(int abort_countdown)
5430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      : eos_signaled_(0), abort_countdown_(abort_countdown) {}
5440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  virtual ~TestJSONStream() {}
5450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  virtual void EndOfStream() { ++eos_signaled_; }
5460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  virtual WriteResult WriteAsciiChunk(char* buffer, int chars_written) {
5470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (abort_countdown_ > 0) --abort_countdown_;
5480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (abort_countdown_ == 0) return kAbort;
5490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    CHECK_GT(chars_written, 0);
5500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    i::Vector<char> chunk = buffer_.AddBlock(chars_written, '\0');
5510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    memcpy(chunk.start(), buffer, chars_written);
5520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    return kContinue;
5530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
5540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  void WriteTo(i::Vector<char> dest) { buffer_.WriteTo(dest); }
5550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  int eos_signaled() { return eos_signaled_; }
5560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  int size() { return buffer_.size(); }
5570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen private:
5580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  i::Collector<char> buffer_;
5590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  int eos_signaled_;
5600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  int abort_countdown_;
5610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen};
5620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5630d5e116f6aee03185f237311a943491bb079a768Kristian Monsenclass AsciiResource: public v8::String::ExternalAsciiStringResource {
5640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen public:
5650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  explicit AsciiResource(i::Vector<char> string): data_(string.start()) {
5660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    length_ = string.length();
5670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
5680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  virtual const char* data() const { return data_; }
5690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  virtual size_t length() const { return length_; }
5700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen private:
5710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  const char* data_;
5720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  size_t length_;
5730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen};
5740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}  // namespace
5760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5770d5e116f6aee03185f237311a943491bb079a768Kristian MonsenTEST(HeapSnapshotJSONSerialization) {
5780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  v8::HandleScope scope;
5790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  LocalContext env;
5800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen#define STRING_LITERAL_FOR_TEST \
5820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  "\"String \\n\\r\\u0008\\u0081\\u0101\\u0801\\u8001\""
583f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  CompileRun(
5840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "function A(s) { this.s = s; }\n"
5850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "function B(x) { this.x = x; }\n"
5860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "var a = new A(" STRING_LITERAL_FOR_TEST ");\n"
5870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "var b = new B(a);");
5880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  const v8::HeapSnapshot* snapshot =
58969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("json"));
5900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  TestJSONStream stream;
5910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  snapshot->Serialize(&stream, v8::HeapSnapshot::kJSON);
5920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  CHECK_GT(stream.size(), 0);
5930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  CHECK_EQ(1, stream.eos_signaled());
5940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  i::ScopedVector<char> json(stream.size());
5950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  stream.WriteTo(json);
5960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Verify that snapshot string is valid JSON.
5980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  AsciiResource json_res(json);
5990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  v8::Local<v8::String> json_string = v8::String::NewExternal(&json_res);
60069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  env->Global()->Set(v8_str("json_snapshot"), json_string);
6010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  v8::Local<v8::Value> snapshot_parse_result = CompileRun(
6020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "var parsed = JSON.parse(json_snapshot); true;");
6030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  CHECK(!snapshot_parse_result.IsEmpty());
6040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Verify that snapshot object has required fields.
6060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  v8::Local<v8::Object> parsed_snapshot =
60769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      env->Global()->Get(v8_str("parsed"))->ToObject();
60869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(parsed_snapshot->Has(v8_str("snapshot")));
60969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(parsed_snapshot->Has(v8_str("nodes")));
61069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(parsed_snapshot->Has(v8_str("strings")));
6110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Get node and edge "member" offsets.
6130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  v8::Local<v8::Value> meta_analysis_result = CompileRun(
6148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "var parsed_meta = parsed.nodes[0];\n"
6150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "var children_count_offset ="
6160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "    parsed_meta.fields.indexOf('children_count');\n"
6170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "var children_offset ="
6180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "    parsed_meta.fields.indexOf('children');\n"
6190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "var children_meta ="
6200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "    parsed_meta.types[children_offset];\n"
6210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "var child_fields_count = children_meta.fields.length;\n"
6220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "var child_type_offset ="
6230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "    children_meta.fields.indexOf('type');\n"
6240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "var child_name_offset ="
6250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "    children_meta.fields.indexOf('name_or_index');\n"
6260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "var child_to_node_offset ="
6270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "    children_meta.fields.indexOf('to_node');\n"
6280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "var property_type ="
6298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "    children_meta.types[child_type_offset].indexOf('property');\n"
6308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "var shortcut_type ="
6318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "    children_meta.types[child_type_offset].indexOf('shortcut');");
6320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  CHECK(!meta_analysis_result.IsEmpty());
6330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // A helper function for processing encoded nodes.
6350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  CompileRun(
6368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "function GetChildPosByProperty(pos, prop_name, prop_type) {\n"
6370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "  var nodes = parsed.nodes;\n"
6380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "  var strings = parsed.strings;\n"
6390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "  for (var i = 0,\n"
6400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "      count = nodes[pos + children_count_offset] * child_fields_count;\n"
6410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "      i < count; i += child_fields_count) {\n"
6420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "    var child_pos = pos + children_offset + i;\n"
6438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "    if (nodes[child_pos + child_type_offset] === prop_type\n"
6440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "       && strings[nodes[child_pos + child_name_offset]] === prop_name)\n"
6450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "        return nodes[child_pos + child_to_node_offset];\n"
6460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "  }\n"
6470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "  return null;\n"
6480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "}\n");
6490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Get the string index using the path: <root> -> <global>.b.x.s
6500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  v8::Local<v8::Value> string_obj_pos_val = CompileRun(
6510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "GetChildPosByProperty(\n"
6520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "  GetChildPosByProperty(\n"
6530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      "    GetChildPosByProperty("
6548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "      parsed.nodes[1 + children_offset + child_to_node_offset],"
6558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "      \"b\",shortcut_type),\n"
6568a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "    \"x\", property_type),"
6578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      "  \"s\", property_type)");
6580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  CHECK(!string_obj_pos_val.IsEmpty());
6590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  int string_obj_pos =
6600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      static_cast<int>(string_obj_pos_val->ToNumber()->Value());
6610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  v8::Local<v8::Object> nodes_array =
66269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      parsed_snapshot->Get(v8_str("nodes"))->ToObject();
6630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  int string_index = static_cast<int>(
6640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      nodes_array->Get(string_obj_pos + 1)->ToNumber()->Value());
6650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  CHECK_GT(string_index, 0);
6660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  v8::Local<v8::Object> strings_array =
66769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      parsed_snapshot->Get(v8_str("strings"))->ToObject();
6680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  v8::Local<v8::String> string = strings_array->Get(string_index)->ToString();
6690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  v8::Local<v8::String> ref_string =
6700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      CompileRun(STRING_LITERAL_FOR_TEST)->ToString();
6710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen#undef STRING_LITERAL_FOR_TEST
6720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  CHECK_EQ(*v8::String::Utf8Value(ref_string),
6730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen           *v8::String::Utf8Value(string));
6740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
6750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6770d5e116f6aee03185f237311a943491bb079a768Kristian MonsenTEST(HeapSnapshotJSONSerializationAborting) {
6780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  v8::HandleScope scope;
6790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  LocalContext env;
6800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  const v8::HeapSnapshot* snapshot =
68169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("abort"));
6820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  TestJSONStream stream(5);
6830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  snapshot->Serialize(&stream, v8::HeapSnapshot::kJSON);
6840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  CHECK_GT(stream.size(), 0);
6850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  CHECK_EQ(0, stream.eos_signaled());
6860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
6870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
6893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void CheckChildrenIds(const v8::HeapSnapshot* snapshot,
6903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             const v8::HeapGraphNode* node,
6913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             int level, int max_level) {
6923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (level > max_level) return;
6933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(node, snapshot->GetNodeById(node->GetId()));
6943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) {
6953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    const v8::HeapGraphEdge* prop = node->GetChild(i);
6963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    const v8::HeapGraphNode* child =
6973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        snapshot->GetNodeById(prop->GetToNode()->GetId());
6983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK_EQ_UINT64_T(prop->GetToNode()->GetId(), child->GetId());
6993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK_EQ(prop->GetToNode(), child);
7003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CheckChildrenIds(snapshot, child, level + 1, max_level);
7013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
7023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
7033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochTEST(HeapSnapshotGetNodeById) {
706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  v8::HandleScope scope;
707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  LocalContext env;
708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const v8::HeapSnapshot* snapshot =
71069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("id"));
711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const v8::HeapGraphNode* root = snapshot->GetRoot();
7123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckChildrenIds(snapshot, root, 0, 3);
713b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Check a big id, which should not exist yet.
714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(NULL, snapshot->GetNodeById(0x1000000UL));
715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochnamespace {
719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass TestActivityControl : public v8::ActivityControl {
721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  explicit TestActivityControl(int abort_count)
723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      : done_(0), total_(0), abort_count_(abort_count) {}
724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ControlOption ReportProgressValue(int done, int total) {
725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    done_ = done;
726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    total_ = total;
727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return --abort_count_ != 0 ? kContinue : kAbort;
728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int done() { return done_; }
730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int total() { return total_; }
731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private:
733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int done_;
734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int total_;
735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int abort_count_;
736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
738b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochTEST(TakeHeapSnapshotAborting) {
740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  v8::HandleScope scope;
741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  LocalContext env;
742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const int snapshots_count = v8::HeapProfiler::GetSnapshotsCount();
7443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  TestActivityControl aborting_control(1);
745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const v8::HeapSnapshot* no_snapshot =
74669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("abort"),
747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                     v8::HeapSnapshot::kFull,
748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                     &aborting_control);
749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(NULL, no_snapshot);
750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(snapshots_count, v8::HeapProfiler::GetSnapshotsCount());
751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_GT(aborting_control.total(), aborting_control.done());
752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TestActivityControl control(-1);  // Don't abort.
754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const v8::HeapSnapshot* snapshot =
75569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("full"),
756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                     v8::HeapSnapshot::kFull,
757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                     &control);
758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_NE(NULL, snapshot);
759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(snapshots_count + 1, v8::HeapProfiler::GetSnapshotsCount());
760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_EQ(control.total(), control.done());
761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK_GT(control.total(), 0);
762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
76444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
76544f0eee88ff00398ff7f715fab053374d808c90dSteve Blocknamespace {
76644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
76744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass TestRetainedObjectInfo : public v8::RetainedObjectInfo {
76844f0eee88ff00398ff7f715fab053374d808c90dSteve Block public:
76944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  TestRetainedObjectInfo(int hash,
7703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         const char* group_label,
77144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                         const char* label,
77244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                         intptr_t element_count = -1,
77344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                         intptr_t size = -1)
77444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : disposed_(false),
77544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        hash_(hash),
7763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        group_label_(group_label),
77744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        label_(label),
77844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        element_count_(element_count),
77944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        size_(size) {
78044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    instances.Add(this);
78144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
78244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  virtual ~TestRetainedObjectInfo() {}
78344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  virtual void Dispose() {
78444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    CHECK(!disposed_);
78544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    disposed_ = true;
78644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
78744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  virtual bool IsEquivalent(RetainedObjectInfo* other) {
78844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return GetHash() == other->GetHash();
78944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
79044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  virtual intptr_t GetHash() { return hash_; }
7913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual const char* GetGroupLabel() { return group_label_; }
79244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  virtual const char* GetLabel() { return label_; }
79344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  virtual intptr_t GetElementCount() { return element_count_; }
79444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  virtual intptr_t GetSizeInBytes() { return size_; }
79544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bool disposed() { return disposed_; }
79644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
79744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static v8::RetainedObjectInfo* WrapperInfoCallback(
79844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      uint16_t class_id, v8::Handle<v8::Value> wrapper) {
79944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (class_id == 1) {
80044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (wrapper->IsString()) {
80144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        v8::String::AsciiValue ascii(wrapper);
80244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (strcmp(*ascii, "AAA") == 0)
8033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          return new TestRetainedObjectInfo(1, "aaa-group", "aaa", 100);
80444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        else if (strcmp(*ascii, "BBB") == 0)
8053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          return new TestRetainedObjectInfo(1, "aaa-group", "aaa", 100);
80644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
80744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    } else if (class_id == 2) {
80844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      if (wrapper->IsString()) {
80944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        v8::String::AsciiValue ascii(wrapper);
81044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (strcmp(*ascii, "CCC") == 0)
8113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          return new TestRetainedObjectInfo(2, "ccc-group", "ccc");
81244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
81344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
81444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    CHECK(false);
81544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return NULL;
81644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
81744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
81844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static i::List<TestRetainedObjectInfo*> instances;
81944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
82044f0eee88ff00398ff7f715fab053374d808c90dSteve Block private:
82144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bool disposed_;
82244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int category_;
82344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int hash_;
8243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const char* group_label_;
82544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const char* label_;
82644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  intptr_t element_count_;
82744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  intptr_t size_;
82844f0eee88ff00398ff7f715fab053374d808c90dSteve Block};
82944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
83044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
83144f0eee88ff00398ff7f715fab053374d808c90dSteve Blocki::List<TestRetainedObjectInfo*> TestRetainedObjectInfo::instances;
83244f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
83344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
83444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
83544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic const v8::HeapGraphNode* GetNode(const v8::HeapGraphNode* parent,
83644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                        v8::HeapGraphNode::Type type,
83744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                        const char* name) {
83844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (int i = 0, count = parent->GetChildrenCount(); i < count; ++i) {
83944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    const v8::HeapGraphNode* node = parent->GetChild(i)->GetToNode();
84044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (node->GetType() == type && strcmp(name,
84144f0eee88ff00398ff7f715fab053374d808c90dSteve Block               const_cast<i::HeapEntry*>(
84244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                   reinterpret_cast<const i::HeapEntry*>(node))->name()) == 0) {
84344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      return node;
84444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
84544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
84644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return NULL;
84744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
84844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
84944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
85044f0eee88ff00398ff7f715fab053374d808c90dSteve BlockTEST(HeapSnapshotRetainedObjectInfo) {
85144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::HandleScope scope;
85244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LocalContext env;
85344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
85444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::HeapProfiler::DefineWrapperClass(
85544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      1, TestRetainedObjectInfo::WrapperInfoCallback);
85644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::HeapProfiler::DefineWrapperClass(
85744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      2, TestRetainedObjectInfo::WrapperInfoCallback);
85844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::Persistent<v8::String> p_AAA =
85944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      v8::Persistent<v8::String>::New(v8_str("AAA"));
86044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  p_AAA.SetWrapperClassId(1);
86144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::Persistent<v8::String> p_BBB =
86244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      v8::Persistent<v8::String>::New(v8_str("BBB"));
86344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  p_BBB.SetWrapperClassId(1);
86444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::Persistent<v8::String> p_CCC =
86544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      v8::Persistent<v8::String>::New(v8_str("CCC"));
86644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  p_CCC.SetWrapperClassId(2);
86744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, TestRetainedObjectInfo::instances.length());
86844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const v8::HeapSnapshot* snapshot =
86969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("retained"));
87044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
87144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(3, TestRetainedObjectInfo::instances.length());
87244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (int i = 0; i < TestRetainedObjectInfo::instances.length(); ++i) {
87344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    CHECK(TestRetainedObjectInfo::instances[i]->disposed());
87444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    delete TestRetainedObjectInfo::instances[i];
87544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
87644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
8773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* native_group_aaa = GetNode(
8783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      snapshot->GetRoot(), v8::HeapGraphNode::kSynthetic, "aaa-group");
8793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_NE(NULL, native_group_aaa);
8803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(1, native_group_aaa->GetChildrenCount());
88144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const v8::HeapGraphNode* aaa = GetNode(
8823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      native_group_aaa, v8::HeapGraphNode::kNative, "aaa / 100 entries");
88344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_NE(NULL, aaa);
8843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(2, aaa->GetChildrenCount());
8853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* native_group_ccc = GetNode(
8873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      snapshot->GetRoot(), v8::HeapGraphNode::kSynthetic, "ccc-group");
88844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const v8::HeapGraphNode* ccc = GetNode(
8893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      native_group_ccc, v8::HeapGraphNode::kNative, "ccc");
89044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_NE(NULL, ccc);
89144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
89244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const v8::HeapGraphNode* n_AAA = GetNode(
89344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      aaa, v8::HeapGraphNode::kString, "AAA");
89444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_NE(NULL, n_AAA);
89544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const v8::HeapGraphNode* n_BBB = GetNode(
89644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      aaa, v8::HeapGraphNode::kString, "BBB");
89744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_NE(NULL, n_BBB);
89844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(1, ccc->GetChildrenCount());
89944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const v8::HeapGraphNode* n_CCC = GetNode(
90044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ccc, v8::HeapGraphNode::kString, "CCC");
90144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_NE(NULL, n_CCC);
90244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
9038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_EQ(aaa, GetProperty(n_AAA, v8::HeapGraphEdge::kInternal, "native"));
9048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_EQ(aaa, GetProperty(n_BBB, v8::HeapGraphEdge::kInternal, "native"));
9058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK_EQ(ccc, GetProperty(n_CCC, v8::HeapGraphEdge::kInternal, "native"));
90644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
90744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
90844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
9093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochclass GraphWithImplicitRefs {
9103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
9113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int kObjectsCount = 4;
9123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  explicit GraphWithImplicitRefs(LocalContext* env) {
9133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK_EQ(NULL, instance_);
9143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    instance_ = this;
9153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int i = 0; i < kObjectsCount; i++) {
9163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      objects_[i] = v8::Persistent<v8::Object>::New(v8::Object::New());
9173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
9183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    (*env)->Global()->Set(v8_str("root_object"), objects_[0]);
9193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
9203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ~GraphWithImplicitRefs() {
9213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    instance_ = NULL;
9223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
9233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void gcPrologue() {
9253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    instance_->AddImplicitReferences();
9263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
9273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private:
9293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void AddImplicitReferences() {
9303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // 0 -> 1
9313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    v8::V8::AddImplicitReferences(
9323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        v8::Persistent<v8::Object>::Cast(objects_[0]), &objects_[1], 1);
9333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Adding two more references(note length=2 in params): 1 -> 2, 1 -> 3
9343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    v8::V8::AddImplicitReferences(
9353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        v8::Persistent<v8::Object>::Cast(objects_[1]), &objects_[2], 2);
9363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
9373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Persistent<v8::Value> objects_[kObjectsCount];
9393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static GraphWithImplicitRefs* instance_;
9403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
9413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9423ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochGraphWithImplicitRefs* GraphWithImplicitRefs::instance_ = NULL;
9433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9453ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(HeapSnapshotImplicitReferences) {
9463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::HandleScope scope;
9473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
9483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  GraphWithImplicitRefs graph(&env);
9503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::V8::SetGlobalGCPrologueCallback(&GraphWithImplicitRefs::gcPrologue);
9513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapSnapshot* snapshot =
9533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("implicit_refs"));
9543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* global_object = GetGlobalObject(snapshot);
9563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Use kShortcut type to skip intermediate JSGlobalPropertyCell
9573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* obj0 = GetProperty(
9583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      global_object, v8::HeapGraphEdge::kShortcut, "root_object");
9593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(obj0);
9603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(v8::HeapGraphNode::kObject, obj0->GetType());
9613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* obj1 = GetProperty(
9623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      obj0, v8::HeapGraphEdge::kInternal, "native");
9633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(obj1);
9643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int implicit_targets_count = 0;
9653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0, count = obj1->GetChildrenCount(); i < count; ++i) {
9663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    const v8::HeapGraphEdge* prop = obj1->GetChild(i);
9673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    v8::String::AsciiValue prop_name(prop->GetName());
9683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (prop->GetType() == v8::HeapGraphEdge::kInternal &&
9693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        strcmp("native", *prop_name) == 0) {
9703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ++implicit_targets_count;
9713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
9723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
9733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(2, implicit_targets_count);
9743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::V8::SetGlobalGCPrologueCallback(NULL);
9753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
9763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
97844f0eee88ff00398ff7f715fab053374d808c90dSteve BlockTEST(DeleteAllHeapSnapshots) {
97944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::HandleScope scope;
98044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LocalContext env;
98144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
98244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount());
98344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::HeapProfiler::DeleteAllSnapshots();
98444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount());
98569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_NE(NULL, v8::HeapProfiler::TakeSnapshot(v8_str("1")));
98644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(1, v8::HeapProfiler::GetSnapshotsCount());
98744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::HeapProfiler::DeleteAllSnapshots();
98844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount());
98969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_NE(NULL, v8::HeapProfiler::TakeSnapshot(v8_str("1")));
99069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_NE(NULL, v8::HeapProfiler::TakeSnapshot(v8_str("2")));
99144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(2, v8::HeapProfiler::GetSnapshotsCount());
99244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::HeapProfiler::DeleteAllSnapshots();
99344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount());
99444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
99544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
99644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
99744f0eee88ff00398ff7f715fab053374d808c90dSteve BlockTEST(DeleteHeapSnapshot) {
99844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::HandleScope scope;
99944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  LocalContext env;
100044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
100144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount());
100244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const v8::HeapSnapshot* s1 =
100369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("1"));
100444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_NE(NULL, s1);
100544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(1, v8::HeapProfiler::GetSnapshotsCount());
100644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  unsigned uid1 = s1->GetUid();
100744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(s1, v8::HeapProfiler::FindSnapshot(uid1));
100844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const_cast<v8::HeapSnapshot*>(s1)->Delete();
100944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount());
101044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(NULL, v8::HeapProfiler::FindSnapshot(uid1));
101144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
101244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const v8::HeapSnapshot* s2 =
101369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("2"));
101444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_NE(NULL, s2);
101544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(1, v8::HeapProfiler::GetSnapshotsCount());
101644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  unsigned uid2 = s2->GetUid();
101744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid2));
101844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(s2, v8::HeapProfiler::FindSnapshot(uid2));
101944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const v8::HeapSnapshot* s3 =
102069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("3"));
102144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_NE(NULL, s3);
102244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(2, v8::HeapProfiler::GetSnapshotsCount());
102344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  unsigned uid3 = s3->GetUid();
102444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_NE(static_cast<int>(uid1), static_cast<int>(uid3));
102544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(s3, v8::HeapProfiler::FindSnapshot(uid3));
102644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const_cast<v8::HeapSnapshot*>(s2)->Delete();
102744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(1, v8::HeapProfiler::GetSnapshotsCount());
102844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(NULL, v8::HeapProfiler::FindSnapshot(uid2));
102944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(s3, v8::HeapProfiler::FindSnapshot(uid3));
103044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const_cast<v8::HeapSnapshot*>(s3)->Delete();
103144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount());
103244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CHECK_EQ(NULL, v8::HeapProfiler::FindSnapshot(uid3));
103344f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
103444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
10353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
10363fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochTEST(DocumentURL) {
10373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::HandleScope scope;
10383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  LocalContext env;
10393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
10403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CompileRun("document = { URL:\"abcdefgh\" };");
10413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
10423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const v8::HeapSnapshot* snapshot =
104369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("document"));
10443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
10453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_NE(NULL, global);
10463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_EQ("Object / abcdefgh",
10473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch           const_cast<i::HeapEntry*>(
10483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch               reinterpret_cast<const i::HeapEntry*>(global))->name());
10493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
10503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
10513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
10523fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochTEST(DocumentWithException) {
10533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::HandleScope scope;
10543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  LocalContext env;
10553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
10563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CompileRun(
10573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      "this.__defineGetter__(\"document\", function() { throw new Error(); })");
10583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const v8::HeapSnapshot* snapshot =
105969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("document"));
10603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
10613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_NE(NULL, global);
10623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_EQ("Object",
10633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch           const_cast<i::HeapEntry*>(
10643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch               reinterpret_cast<const i::HeapEntry*>(global))->name());
10653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
10663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
10673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
10683fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochTEST(DocumentURLWithException) {
10693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::HandleScope scope;
10703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  LocalContext env;
10713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
10723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CompileRun(
10733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      "function URLWithException() {}\n"
10743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      "URLWithException.prototype = { get URL() { throw new Error(); } };\n"
10753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      "document = { URL: new URLWithException() };");
10763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const v8::HeapSnapshot* snapshot =
107769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("document"));
10783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
10793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_NE(NULL, global);
10803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_EQ("Object",
10813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch           const_cast<i::HeapEntry*>(
10823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch               reinterpret_cast<const i::HeapEntry*>(global))->name());
10833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
10843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
10853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
10863ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(NoHandleLeaks) {
10873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::HandleScope scope;
10883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
10893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun("document = { URL:\"abcdefgh\" };");
10913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Handle<v8::String> name(v8_str("leakz"));
10933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int count_before = i::HandleScope::NumberOfHandles();
10943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::HeapProfiler::TakeSnapshot(name);
10953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int count_after = i::HandleScope::NumberOfHandles();
10963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(count_before, count_after);
10973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
10983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11003fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochTEST(NodesIteration) {
11013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  v8::HandleScope scope;
11023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  LocalContext env;
11033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const v8::HeapSnapshot* snapshot =
110469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("iteration"));
11053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
11063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_NE(NULL, global);
11073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Verify that we can find this object by iteration.
11083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const int nodes_count = snapshot->GetNodesCount();
11093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int count = 0;
11103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (int i = 0; i < nodes_count; ++i) {
11113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (snapshot->GetNode(i) == global)
11123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ++count;
11133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
11143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CHECK_EQ(1, count);
11153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
111669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
111769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
111869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen MurdochTEST(GetHeapValue) {
111969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  v8::HandleScope scope;
112069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  LocalContext env;
112169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
112269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CompileRun("a = { s_prop: \'value\', n_prop: 0.1 };");
112369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  const v8::HeapSnapshot* snapshot =
112469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("value"));
112569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
112669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(global->GetHeapValue()->IsObject());
112769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  v8::Local<v8::Object> js_global =
112869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      env->Global()->GetPrototype().As<v8::Object>();
112969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(js_global == global->GetHeapValue());
113069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  const v8::HeapGraphNode* obj = GetProperty(
113169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      global, v8::HeapGraphEdge::kShortcut, "a");
113269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(obj->GetHeapValue()->IsObject());
113369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  v8::Local<v8::Object> js_obj = js_global->Get(v8_str("a")).As<v8::Object>();
113469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(js_obj == obj->GetHeapValue());
113569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  const v8::HeapGraphNode* s_prop =
113669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      GetProperty(obj, v8::HeapGraphEdge::kProperty, "s_prop");
113769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  v8::Local<v8::String> js_s_prop =
113869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      js_obj->Get(v8_str("s_prop")).As<v8::String>();
113969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(js_s_prop == s_prop->GetHeapValue());
114069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  const v8::HeapGraphNode* n_prop =
114169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      GetProperty(obj, v8::HeapGraphEdge::kProperty, "n_prop");
114269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  v8::Local<v8::Number> js_n_prop =
114369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      js_obj->Get(v8_str("n_prop")).As<v8::Number>();
114469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(js_n_prop == n_prop->GetHeapValue());
114569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
114669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
114769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
114869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen MurdochTEST(GetHeapValueForDeletedObject) {
114969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  v8::HandleScope scope;
115069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  LocalContext env;
115169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
115269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // It is impossible to delete a global property, so we are about to delete a
115369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // property of the "a" object. Also, the "p" object can't be an empty one
115469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // because the empty object is static and isn't actually deleted.
115569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CompileRun("a = { p: { r: {} } };");
115669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  const v8::HeapSnapshot* snapshot =
115769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("snapshot"));
115869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
115969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  const v8::HeapGraphNode* obj = GetProperty(
116069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      global, v8::HeapGraphEdge::kShortcut, "a");
116169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  const v8::HeapGraphNode* prop = GetProperty(
116269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      obj, v8::HeapGraphEdge::kProperty, "p");
116369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  {
116469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    // Perform the check inside a nested local scope to avoid creating a
116569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    // reference to the object we are deleting.
116669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    v8::HandleScope scope;
116769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    CHECK(prop->GetHeapValue()->IsObject());
116869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
116969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CompileRun("delete a.p;");
117069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK(prop->GetHeapValue()->IsUndefined());
117169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
117269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
117369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
117469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochstatic int StringCmp(const char* ref, i::String* act) {
1175589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  i::SmartArrayPointer<char> s_act = act->ToCString();
117669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  int result = strcmp(ref, *s_act);
117769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  if (result != 0)
117869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    fprintf(stderr, "Expected: \"%s\", Actual: \"%s\"\n", ref, *s_act);
117969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  return result;
118069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
118169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
118269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
118369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen MurdochTEST(GetConstructorName) {
118469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  v8::HandleScope scope;
118569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  LocalContext env;
118669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
118769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CompileRun(
118869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "function Constructor1() {};\n"
118969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "var obj1 = new Constructor1();\n"
119069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "var Constructor2 = function() {};\n"
119169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "var obj2 = new Constructor2();\n"
119269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "var obj3 = {};\n"
119369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "obj3.constructor = function Constructor3() {};\n"
119469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "var obj4 = {};\n"
119569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "// Slow properties\n"
119669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "for (var i=0; i<2000; ++i) obj4[\"p\" + i] = i;\n"
119769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "obj4.constructor = function Constructor4() {};\n"
119869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "var obj5 = {};\n"
119969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "var obj6 = {};\n"
120069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "obj6.constructor = 6;");
120169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  v8::Local<v8::Object> js_global =
120269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      env->Global()->GetPrototype().As<v8::Object>();
120369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  v8::Local<v8::Object> obj1 = js_global->Get(v8_str("obj1")).As<v8::Object>();
120469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  i::Handle<i::JSObject> js_obj1 = v8::Utils::OpenHandle(*obj1);
120569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(0, StringCmp(
120669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "Constructor1", i::V8HeapExplorer::GetConstructorName(*js_obj1)));
120769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  v8::Local<v8::Object> obj2 = js_global->Get(v8_str("obj2")).As<v8::Object>();
120869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  i::Handle<i::JSObject> js_obj2 = v8::Utils::OpenHandle(*obj2);
120969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(0, StringCmp(
121069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "Constructor2", i::V8HeapExplorer::GetConstructorName(*js_obj2)));
121169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  v8::Local<v8::Object> obj3 = js_global->Get(v8_str("obj3")).As<v8::Object>();
121269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  i::Handle<i::JSObject> js_obj3 = v8::Utils::OpenHandle(*obj3);
121369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(0, StringCmp(
121469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "Constructor3", i::V8HeapExplorer::GetConstructorName(*js_obj3)));
121569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  v8::Local<v8::Object> obj4 = js_global->Get(v8_str("obj4")).As<v8::Object>();
121669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  i::Handle<i::JSObject> js_obj4 = v8::Utils::OpenHandle(*obj4);
121769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(0, StringCmp(
121869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "Constructor4", i::V8HeapExplorer::GetConstructorName(*js_obj4)));
121969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  v8::Local<v8::Object> obj5 = js_global->Get(v8_str("obj5")).As<v8::Object>();
122069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  i::Handle<i::JSObject> js_obj5 = v8::Utils::OpenHandle(*obj5);
122169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(0, StringCmp(
122269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "Object", i::V8HeapExplorer::GetConstructorName(*js_obj5)));
122369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  v8::Local<v8::Object> obj6 = js_global->Get(v8_str("obj6")).As<v8::Object>();
122469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  i::Handle<i::JSObject> js_obj6 = v8::Utils::OpenHandle(*obj6);
122569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  CHECK_EQ(0, StringCmp(
122669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      "Object", i::V8HeapExplorer::GetConstructorName(*js_obj6)));
122769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
12283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12303ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(FastCaseGetter) {
12313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::HandleScope scope;
12323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
12333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun("var obj1 = {};\n"
12353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "obj1.__defineGetter__('propWithGetter', function Y() {\n"
12363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "  return 42;\n"
12373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "});\n"
12383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "obj1.__defineSetter__('propWithSetter', function Z(value) {\n"
12393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "  return this.value_ = value;\n"
12403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             "});\n");
12413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapSnapshot* snapshot =
12423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("fastCaseGetter"));
12433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
12453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_NE(NULL, global);
12463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* obj1 =
12473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GetProperty(global, v8::HeapGraphEdge::kShortcut, "obj1");
12483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_NE(NULL, obj1);
12493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* getterFunction =
12503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GetProperty(obj1, v8::HeapGraphEdge::kProperty, "get-propWithGetter");
12513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_NE(NULL, getterFunction);
12523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* setterFunction =
12533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GetProperty(obj1, v8::HeapGraphEdge::kProperty, "set-propWithSetter");
12543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_NE(NULL, setterFunction);
12553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
12563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool HasWeakEdge(const v8::HeapGraphNode* node) {
12593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < node->GetChildrenCount(); ++i) {
12603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    const v8::HeapGraphEdge* handle_edge = node->GetChild(i);
12613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (handle_edge->GetType() == v8::HeapGraphEdge::kWeak) return true;
12623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
12633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return false;
12643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
12653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool HasWeakGlobalHandle() {
12683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapSnapshot* snapshot =
12693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("weaks"));
12703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* gc_roots = GetNode(
12713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      snapshot->GetRoot(), v8::HeapGraphNode::kObject, "(GC roots)");
12723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_NE(NULL, gc_roots);
12733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* global_handles = GetNode(
12743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      gc_roots, v8::HeapGraphNode::kObject, "(Global handles)");
12753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_NE(NULL, global_handles);
12763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return HasWeakEdge(global_handles);
12773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
12783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void PersistentHandleCallback(v8::Persistent<v8::Value> handle, void*) {
12813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  handle.Dispose();
12823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
12833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12853ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(WeakGlobalHandle) {
12863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::HandleScope scope;
12873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
12883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(!HasWeakGlobalHandle());
12903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Persistent<v8::Object> handle =
12923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      v8::Persistent<v8::Object>::New(v8::Object::New());
12933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  handle.MakeWeak(NULL, PersistentHandleCallback);
12943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(HasWeakGlobalHandle());
12963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
12973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12993ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(WeakGlobalContextRefs) {
13003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::HandleScope scope;
13013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
13023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapSnapshot* snapshot =
13043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("weaks"));
13053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* gc_roots = GetNode(
13063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      snapshot->GetRoot(), v8::HeapGraphNode::kObject, "(GC roots)");
13073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_NE(NULL, gc_roots);
13083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* global_handles = GetNode(
13093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      gc_roots, v8::HeapGraphNode::kObject, "(Global handles)");
13103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_NE(NULL, global_handles);
13113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* global_context = GetNode(
13123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      global_handles, v8::HeapGraphNode::kHidden, "system / GlobalContext");
13133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_NE(NULL, global_context);
13143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(HasWeakEdge(global_context));
13153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
13163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13183ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(SfiAndJsFunctionWeakRefs) {
13193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::HandleScope scope;
13203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
13213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CompileRun(
13233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      "fun = (function (x) { return function () { return x + 1; } })(1);");
13243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapSnapshot* snapshot =
13253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      v8::HeapProfiler::TakeSnapshot(v8_str("fun"));
13263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
13273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_NE(NULL, global);
13283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* fun =
13293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GetProperty(global, v8::HeapGraphEdge::kShortcut, "fun");
13303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(HasWeakEdge(fun));
13313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const v8::HeapGraphNode* shared =
13323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      GetProperty(fun, v8::HeapGraphEdge::kInternal, "shared");
13333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(HasWeakEdge(shared));
13343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
13353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13373ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochTEST(PersistentHandleCount) {
13383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::HandleScope scope;
13393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LocalContext env;
13403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // V8 also uses global handles internally, so we can't test for an absolute
13423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // number.
13433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int global_handle_count = v8::HeapProfiler::GetPersistentHandleCount();
13443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Create some persistent handles.
13463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Persistent<v8::String> p_AAA =
13473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      v8::Persistent<v8::String>::New(v8_str("AAA"));
13483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(global_handle_count + 1,
13493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           v8::HeapProfiler::GetPersistentHandleCount());
13503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Persistent<v8::String> p_BBB =
13513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      v8::Persistent<v8::String>::New(v8_str("BBB"));
13523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(global_handle_count + 2,
13533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           v8::HeapProfiler::GetPersistentHandleCount());
13543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  v8::Persistent<v8::String> p_CCC =
13553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      v8::Persistent<v8::String>::New(v8_str("CCC"));
13563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(global_handle_count + 3,
13573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           v8::HeapProfiler::GetPersistentHandleCount());
13583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Dipose the persistent handles in a different order.
13603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  p_AAA.Dispose();
13613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(global_handle_count + 2,
13623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           v8::HeapProfiler::GetPersistentHandleCount());
13633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  p_CCC.Dispose();
13643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(global_handle_count + 1,
13653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           v8::HeapProfiler::GetPersistentHandleCount());
13663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  p_BBB.Dispose();
13673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK_EQ(global_handle_count, v8::HeapProfiler::GetPersistentHandleCount());
13683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1369