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 |