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