| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // | 2 // |
| 3 // Tests for heap profiler | 3 // Tests for heap profiler |
| 4 | 4 |
| 5 #include "v8.h" | 5 #include "v8.h" |
| 6 | 6 |
| 7 #include "cctest.h" | 7 #include "cctest.h" |
| 8 #include "heap-profiler.h" | 8 #include "heap-profiler.h" |
| 9 #include "snapshot.h" | 9 #include "snapshot.h" |
| 10 #include "utils-inl.h" | 10 #include "utils-inl.h" |
| 11 #include "../include/v8-profiler.h" | 11 #include "../include/v8-profiler.h" |
| 12 | 12 |
| 13 namespace { | 13 namespace { |
| 14 | 14 |
| 15 class NamedEntriesDetector { | 15 class NamedEntriesDetector { |
| 16 public: | 16 public: |
| 17 NamedEntriesDetector() | 17 NamedEntriesDetector() |
| 18 : has_A2(false), has_B2(false), has_C2(false) { | 18 : has_A2(false), has_B2(false), has_C2(false) { |
| 19 } | 19 } |
| 20 | 20 |
| 21 void Apply(i::HeapEntry** entry_ptr) { | 21 void CheckEntry(i::HeapEntry* entry) { |
| 22 if (IsReachableNodeWithName(*entry_ptr, "A2")) has_A2 = true; | 22 if (strcmp(entry->name(), "A2") == 0) has_A2 = true; |
| 23 if (IsReachableNodeWithName(*entry_ptr, "B2")) has_B2 = true; | 23 if (strcmp(entry->name(), "B2") == 0) has_B2 = true; |
| 24 if (IsReachableNodeWithName(*entry_ptr, "C2")) has_C2 = true; | 24 if (strcmp(entry->name(), "C2") == 0) has_C2 = true; |
| 25 } | 25 } |
| 26 | 26 |
| 27 static bool IsReachableNodeWithName(i::HeapEntry* entry, const char* name) { | 27 void CheckAllReachables(i::HeapEntry* root) { |
| 28 return strcmp(name, entry->name()) == 0 && entry->painted_reachable(); | 28 i::List<i::HeapEntry*> list(10); |
| 29 list.Add(root); |
| 30 root->paint(); |
| 31 CheckEntry(root); |
| 32 while (!list.is_empty()) { |
| 33 i::HeapEntry* entry = list.RemoveLast(); |
| 34 i::Vector<i::HeapGraphEdge> children = entry->children(); |
| 35 for (int i = 0; i < children.length(); ++i) { |
| 36 if (children[i].type() == i::HeapGraphEdge::kShortcut) continue; |
| 37 i::HeapEntry* child = children[i].to(); |
| 38 if (!child->painted()) { |
| 39 list.Add(child); |
| 40 child->paint(); |
| 41 CheckEntry(child); |
| 42 } |
| 43 } |
| 44 } |
| 29 } | 45 } |
| 30 | 46 |
| 31 bool has_A2; | 47 bool has_A2; |
| 32 bool has_B2; | 48 bool has_B2; |
| 33 bool has_C2; | 49 bool has_C2; |
| 34 }; | 50 }; |
| 35 | 51 |
| 36 } // namespace | 52 } // namespace |
| 37 | 53 |
| 38 | 54 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 "function C2(x) { this.x1 = x; this.x2 = x; this[1] = x; }\n" | 99 "function C2(x) { this.x1 = x; this.x2 = x; this[1] = x; }\n" |
| 84 "var a2 = new A2();\n" | 100 "var a2 = new A2();\n" |
| 85 "var b2_1 = new B2(a2), b2_2 = new B2(a2);\n" | 101 "var b2_1 = new B2(a2), b2_2 = new B2(a2);\n" |
| 86 "var c2 = new C2(a2);"); | 102 "var c2 = new C2(a2);"); |
| 87 const v8::HeapSnapshot* snapshot_env2 = | 103 const v8::HeapSnapshot* snapshot_env2 = |
| 88 v8::HeapProfiler::TakeSnapshot(v8_str("env2")); | 104 v8::HeapProfiler::TakeSnapshot(v8_str("env2")); |
| 89 i::HeapSnapshot* i_snapshot_env2 = | 105 i::HeapSnapshot* i_snapshot_env2 = |
| 90 const_cast<i::HeapSnapshot*>( | 106 const_cast<i::HeapSnapshot*>( |
| 91 reinterpret_cast<const i::HeapSnapshot*>(snapshot_env2)); | 107 reinterpret_cast<const i::HeapSnapshot*>(snapshot_env2)); |
| 92 const v8::HeapGraphNode* global_env2 = GetGlobalObject(snapshot_env2); | 108 const v8::HeapGraphNode* global_env2 = GetGlobalObject(snapshot_env2); |
| 93 // Paint all nodes reachable from global object. | |
| 94 i_snapshot_env2->ClearPaint(); | |
| 95 const_cast<i::HeapEntry*>( | |
| 96 reinterpret_cast<const i::HeapEntry*>(global_env2))->PaintAllReachable(); | |
| 97 | 109 |
| 98 // Verify, that JS global object of env2 has '..2' properties. | 110 // Verify, that JS global object of env2 has '..2' properties. |
| 99 const v8::HeapGraphNode* a2_node = | 111 const v8::HeapGraphNode* a2_node = |
| 100 GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "a2"); | 112 GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "a2"); |
| 101 CHECK_NE(NULL, a2_node); | 113 CHECK_NE(NULL, a2_node); |
| 102 CHECK_NE( | 114 CHECK_NE( |
| 103 NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "b2_1")); | 115 NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "b2_1")); |
| 104 CHECK_NE( | 116 CHECK_NE( |
| 105 NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "b2_2")); | 117 NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "b2_2")); |
| 106 CHECK_NE(NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "c2")); | 118 CHECK_NE(NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "c2")); |
| 107 | 119 |
| 120 // Paint all nodes reachable from global object. |
| 108 NamedEntriesDetector det; | 121 NamedEntriesDetector det; |
| 109 i_snapshot_env2->IterateEntries(&det); | 122 i_snapshot_env2->ClearPaint(); |
| 123 det.CheckAllReachables(const_cast<i::HeapEntry*>( |
| 124 reinterpret_cast<const i::HeapEntry*>(global_env2))); |
| 110 CHECK(det.has_A2); | 125 CHECK(det.has_A2); |
| 111 CHECK(det.has_B2); | 126 CHECK(det.has_B2); |
| 112 CHECK(det.has_C2); | 127 CHECK(det.has_C2); |
| 113 } | 128 } |
| 114 | 129 |
| 115 | 130 |
| 116 TEST(HeapSnapshotObjectSizes) { | 131 TEST(HeapSnapshotObjectSizes) { |
| 117 v8::HandleScope scope; | 132 v8::HandleScope scope; |
| 118 LocalContext env; | 133 LocalContext env; |
| 119 | 134 |
| 120 // -a-> X1 --a | 135 // -a-> X1 --a |
| 121 // x -b-> X2 <-| | 136 // x -b-> X2 <-| |
| 122 CompileRun( | 137 CompileRun( |
| 123 "function X(a, b) { this.a = a; this.b = b; }\n" | 138 "function X(a, b) { this.a = a; this.b = b; }\n" |
| 124 "x = new X(new X(), new X());\n" | 139 "x = new X(new X(), new X());\n" |
| 125 "(function() { x.a.a = x.b; })();"); | 140 "(function() { x.a.a = x.b; })();"); |
| 126 const v8::HeapSnapshot* snapshot = | 141 const v8::HeapSnapshot* snapshot = |
| 127 v8::HeapProfiler::TakeSnapshot(v8_str("sizes")); | 142 v8::HeapProfiler::TakeSnapshot(v8_str("sizes")); |
| 128 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); | 143 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); |
| 129 const v8::HeapGraphNode* x = | 144 const v8::HeapGraphNode* x = |
| 130 GetProperty(global, v8::HeapGraphEdge::kShortcut, "x"); | 145 GetProperty(global, v8::HeapGraphEdge::kShortcut, "x"); |
| 131 CHECK_NE(NULL, x); | 146 CHECK_NE(NULL, x); |
| 132 const v8::HeapGraphNode* x1 = | 147 const v8::HeapGraphNode* x1 = |
| 133 GetProperty(x, v8::HeapGraphEdge::kProperty, "a"); | 148 GetProperty(x, v8::HeapGraphEdge::kProperty, "a"); |
| 134 CHECK_NE(NULL, x1); | 149 CHECK_NE(NULL, x1); |
| 135 const v8::HeapGraphNode* x2 = | 150 const v8::HeapGraphNode* x2 = |
| 136 GetProperty(x, v8::HeapGraphEdge::kProperty, "b"); | 151 GetProperty(x, v8::HeapGraphEdge::kProperty, "b"); |
| 137 CHECK_NE(NULL, x2); | 152 CHECK_NE(NULL, x2); |
| 138 | 153 |
| 139 // Test approximate sizes. | 154 // Test sizes. |
| 140 CHECK_EQ(x->GetSelfSize() * 3, x->GetRetainedSize(false)); | 155 CHECK_EQ(x->GetSelfSize() * 3, x->GetRetainedSize()); |
| 141 CHECK_EQ(x1->GetSelfSize(), x1->GetRetainedSize(false)); | 156 CHECK_EQ(x1->GetSelfSize(), x1->GetRetainedSize()); |
| 142 CHECK_EQ(x2->GetSelfSize(), x2->GetRetainedSize(false)); | 157 CHECK_EQ(x2->GetSelfSize(), x2->GetRetainedSize()); |
| 143 // Test exact sizes. | |
| 144 CHECK_EQ(x->GetSelfSize() * 3, x->GetRetainedSize(true)); | |
| 145 CHECK_EQ(x1->GetSelfSize(), x1->GetRetainedSize(true)); | |
| 146 CHECK_EQ(x2->GetSelfSize(), x2->GetRetainedSize(true)); | |
| 147 } | 158 } |
| 148 | 159 |
| 149 | 160 |
| 150 TEST(BoundFunctionInSnapshot) { | 161 TEST(BoundFunctionInSnapshot) { |
| 151 v8::HandleScope scope; | 162 v8::HandleScope scope; |
| 152 LocalContext env; | 163 LocalContext env; |
| 153 CompileRun( | 164 CompileRun( |
| 154 "function myFunction(a, b) { this.a = a; this.b = b; }\n" | 165 "function myFunction(a, b) { this.a = a; this.b = b; }\n" |
| 155 "function AAAAA() {}\n" | 166 "function AAAAA() {}\n" |
| 156 "boundFunction = myFunction.bind(new AAAAA(), 20, new Number(12)); \n"); | 167 "boundFunction = myFunction.bind(new AAAAA(), 20, new Number(12)); \n"); |
| (...skipping 1104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1261 v8::HeapProfiler::TakeSnapshot(v8_str("fun")); | 1272 v8::HeapProfiler::TakeSnapshot(v8_str("fun")); |
| 1262 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); | 1273 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); |
| 1263 CHECK_NE(NULL, global); | 1274 CHECK_NE(NULL, global); |
| 1264 const v8::HeapGraphNode* fun = | 1275 const v8::HeapGraphNode* fun = |
| 1265 GetProperty(global, v8::HeapGraphEdge::kShortcut, "fun"); | 1276 GetProperty(global, v8::HeapGraphEdge::kShortcut, "fun"); |
| 1266 CHECK(HasWeakEdge(fun)); | 1277 CHECK(HasWeakEdge(fun)); |
| 1267 const v8::HeapGraphNode* shared = | 1278 const v8::HeapGraphNode* shared = |
| 1268 GetProperty(fun, v8::HeapGraphEdge::kInternal, "shared"); | 1279 GetProperty(fun, v8::HeapGraphEdge::kInternal, "shared"); |
| 1269 CHECK(HasWeakEdge(shared)); | 1280 CHECK(HasWeakEdge(shared)); |
| 1270 } | 1281 } |
| OLD | NEW |