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" |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 "var c2 = new C2(a2);"); | 102 "var c2 = new C2(a2);"); |
103 const v8::HeapSnapshot* snapshot_env2 = | 103 const v8::HeapSnapshot* snapshot_env2 = |
104 v8::HeapProfiler::TakeSnapshot(v8_str("env2")); | 104 v8::HeapProfiler::TakeSnapshot(v8_str("env2")); |
105 i::HeapSnapshot* i_snapshot_env2 = | 105 i::HeapSnapshot* i_snapshot_env2 = |
106 const_cast<i::HeapSnapshot*>( | 106 const_cast<i::HeapSnapshot*>( |
107 reinterpret_cast<const i::HeapSnapshot*>(snapshot_env2)); | 107 reinterpret_cast<const i::HeapSnapshot*>(snapshot_env2)); |
108 const v8::HeapGraphNode* global_env2 = GetGlobalObject(snapshot_env2); | 108 const v8::HeapGraphNode* global_env2 = GetGlobalObject(snapshot_env2); |
109 | 109 |
110 // Verify, that JS global object of env2 has '..2' properties. | 110 // Verify, that JS global object of env2 has '..2' properties. |
111 const v8::HeapGraphNode* a2_node = | 111 const v8::HeapGraphNode* a2_node = |
112 GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "a2"); | 112 GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "a2"); |
113 CHECK_NE(NULL, a2_node); | 113 CHECK_NE(NULL, a2_node); |
114 CHECK_NE( | 114 CHECK_NE( |
115 NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "b2_1")); | 115 NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "b2_1")); |
116 CHECK_NE( | 116 CHECK_NE( |
117 NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "b2_2")); | 117 NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "b2_2")); |
118 CHECK_NE(NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "c2")); | 118 CHECK_NE(NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "c2")); |
119 | 119 |
120 // Paint all nodes reachable from global object. | 120 // Paint all nodes reachable from global object. |
121 NamedEntriesDetector det; | 121 NamedEntriesDetector det; |
122 i_snapshot_env2->ClearPaint(); | 122 i_snapshot_env2->ClearPaint(); |
123 det.CheckAllReachables(const_cast<i::HeapEntry*>( | 123 det.CheckAllReachables(const_cast<i::HeapEntry*>( |
124 reinterpret_cast<const i::HeapEntry*>(global_env2))); | 124 reinterpret_cast<const i::HeapEntry*>(global_env2))); |
125 CHECK(det.has_A2); | 125 CHECK(det.has_A2); |
126 CHECK(det.has_B2); | 126 CHECK(det.has_B2); |
127 CHECK(det.has_C2); | 127 CHECK(det.has_C2); |
128 } | 128 } |
129 | 129 |
130 | 130 |
131 TEST(HeapSnapshotObjectSizes) { | 131 TEST(HeapSnapshotObjectSizes) { |
132 v8::HandleScope scope; | 132 v8::HandleScope scope; |
133 LocalContext env; | 133 LocalContext env; |
134 | 134 |
135 // -a-> X1 --a | 135 // -a-> X1 --a |
136 // x -b-> X2 <-| | 136 // x -b-> X2 <-| |
137 CompileRun( | 137 CompileRun( |
138 "function X(a, b) { this.a = a; this.b = b; }\n" | 138 "function X(a, b) { this.a = a; this.b = b; }\n" |
139 "x = new X(new X(), new X());\n" | 139 "x = new X(new X(), new X());\n" |
| 140 "dummy = new X();\n" |
140 "(function() { x.a.a = x.b; })();"); | 141 "(function() { x.a.a = x.b; })();"); |
141 const v8::HeapSnapshot* snapshot = | 142 const v8::HeapSnapshot* snapshot = |
142 v8::HeapProfiler::TakeSnapshot(v8_str("sizes")); | 143 v8::HeapProfiler::TakeSnapshot(v8_str("sizes")); |
143 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); | 144 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); |
144 const v8::HeapGraphNode* x = | 145 const v8::HeapGraphNode* x = |
145 GetProperty(global, v8::HeapGraphEdge::kShortcut, "x"); | 146 GetProperty(global, v8::HeapGraphEdge::kProperty, "x"); |
146 CHECK_NE(NULL, x); | 147 CHECK_NE(NULL, x); |
147 const v8::HeapGraphNode* x1 = | 148 const v8::HeapGraphNode* x1 = |
148 GetProperty(x, v8::HeapGraphEdge::kProperty, "a"); | 149 GetProperty(x, v8::HeapGraphEdge::kProperty, "a"); |
149 CHECK_NE(NULL, x1); | 150 CHECK_NE(NULL, x1); |
150 const v8::HeapGraphNode* x2 = | 151 const v8::HeapGraphNode* x2 = |
151 GetProperty(x, v8::HeapGraphEdge::kProperty, "b"); | 152 GetProperty(x, v8::HeapGraphEdge::kProperty, "b"); |
152 CHECK_NE(NULL, x2); | 153 CHECK_NE(NULL, x2); |
153 | 154 |
154 // Test sizes. | 155 // Test sizes. |
155 CHECK_EQ(x->GetSelfSize() * 3, x->GetRetainedSize()); | 156 CHECK_EQ(x->GetSelfSize() * 3, x->GetRetainedSize()); |
156 CHECK_EQ(x1->GetSelfSize(), x1->GetRetainedSize()); | 157 CHECK_EQ(x1->GetSelfSize(), x1->GetRetainedSize()); |
157 CHECK_EQ(x2->GetSelfSize(), x2->GetRetainedSize()); | 158 CHECK_EQ(x2->GetSelfSize(), x2->GetRetainedSize()); |
158 } | 159 } |
159 | 160 |
160 | 161 |
161 TEST(BoundFunctionInSnapshot) { | 162 TEST(BoundFunctionInSnapshot) { |
162 v8::HandleScope scope; | 163 v8::HandleScope scope; |
163 LocalContext env; | 164 LocalContext env; |
164 CompileRun( | 165 CompileRun( |
165 "function myFunction(a, b) { this.a = a; this.b = b; }\n" | 166 "function myFunction(a, b) { this.a = a; this.b = b; }\n" |
166 "function AAAAA() {}\n" | 167 "function AAAAA() {}\n" |
167 "boundFunction = myFunction.bind(new AAAAA(), 20, new Number(12)); \n"); | 168 "boundFunction = myFunction.bind(new AAAAA(), 20, new Number(12)); \n"); |
168 const v8::HeapSnapshot* snapshot = | 169 const v8::HeapSnapshot* snapshot = |
169 v8::HeapProfiler::TakeSnapshot(v8_str("sizes")); | 170 v8::HeapProfiler::TakeSnapshot(v8_str("sizes")); |
170 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); | 171 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); |
171 const v8::HeapGraphNode* f = | 172 const v8::HeapGraphNode* f = |
172 GetProperty(global, v8::HeapGraphEdge::kShortcut, "boundFunction"); | 173 GetProperty(global, v8::HeapGraphEdge::kProperty, "boundFunction"); |
173 CHECK(f); | 174 CHECK(f); |
174 CHECK_EQ(v8::String::New("native_bind"), f->GetName()); | 175 CHECK_EQ(v8::String::New("native_bind"), f->GetName()); |
175 const v8::HeapGraphNode* bindings = | 176 const v8::HeapGraphNode* bindings = |
176 GetProperty(f, v8::HeapGraphEdge::kInternal, "bindings"); | 177 GetProperty(f, v8::HeapGraphEdge::kInternal, "bindings"); |
177 CHECK_NE(NULL, bindings); | 178 CHECK_NE(NULL, bindings); |
178 CHECK_EQ(v8::HeapGraphNode::kArray, bindings->GetType()); | 179 CHECK_EQ(v8::HeapGraphNode::kArray, bindings->GetType()); |
179 CHECK_EQ(4, bindings->GetChildrenCount()); | 180 CHECK_EQ(4, bindings->GetChildrenCount()); |
180 | 181 |
181 const v8::HeapGraphNode* bound_this = GetProperty( | 182 const v8::HeapGraphNode* bound_this = GetProperty( |
182 f, v8::HeapGraphEdge::kShortcut, "bound_this"); | 183 f, v8::HeapGraphEdge::kShortcut, "bound_this"); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
226 CompileRun( | 227 CompileRun( |
227 "function lazy(x) { return x - 1; }\n" | 228 "function lazy(x) { return x - 1; }\n" |
228 "function compiled(x) { return x + 1; }\n" | 229 "function compiled(x) { return x + 1; }\n" |
229 "var anonymous = (function() { return function() { return 0; } })();\n" | 230 "var anonymous = (function() { return function() { return 0; } })();\n" |
230 "compiled(1)"); | 231 "compiled(1)"); |
231 const v8::HeapSnapshot* snapshot = | 232 const v8::HeapSnapshot* snapshot = |
232 v8::HeapProfiler::TakeSnapshot(v8_str("code")); | 233 v8::HeapProfiler::TakeSnapshot(v8_str("code")); |
233 | 234 |
234 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); | 235 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); |
235 const v8::HeapGraphNode* compiled = | 236 const v8::HeapGraphNode* compiled = |
236 GetProperty(global, v8::HeapGraphEdge::kShortcut, "compiled"); | 237 GetProperty(global, v8::HeapGraphEdge::kProperty, "compiled"); |
237 CHECK_NE(NULL, compiled); | 238 CHECK_NE(NULL, compiled); |
238 CHECK_EQ(v8::HeapGraphNode::kClosure, compiled->GetType()); | 239 CHECK_EQ(v8::HeapGraphNode::kClosure, compiled->GetType()); |
239 const v8::HeapGraphNode* lazy = | 240 const v8::HeapGraphNode* lazy = |
240 GetProperty(global, v8::HeapGraphEdge::kShortcut, "lazy"); | 241 GetProperty(global, v8::HeapGraphEdge::kProperty, "lazy"); |
241 CHECK_NE(NULL, lazy); | 242 CHECK_NE(NULL, lazy); |
242 CHECK_EQ(v8::HeapGraphNode::kClosure, lazy->GetType()); | 243 CHECK_EQ(v8::HeapGraphNode::kClosure, lazy->GetType()); |
243 const v8::HeapGraphNode* anonymous = | 244 const v8::HeapGraphNode* anonymous = |
244 GetProperty(global, v8::HeapGraphEdge::kShortcut, "anonymous"); | 245 GetProperty(global, v8::HeapGraphEdge::kProperty, "anonymous"); |
245 CHECK_NE(NULL, anonymous); | 246 CHECK_NE(NULL, anonymous); |
246 CHECK_EQ(v8::HeapGraphNode::kClosure, anonymous->GetType()); | 247 CHECK_EQ(v8::HeapGraphNode::kClosure, anonymous->GetType()); |
247 v8::String::AsciiValue anonymous_name(anonymous->GetName()); | 248 v8::String::AsciiValue anonymous_name(anonymous->GetName()); |
248 CHECK_EQ("", *anonymous_name); | 249 CHECK_EQ("", *anonymous_name); |
249 | 250 |
250 // Find references to code. | 251 // Find references to code. |
251 const v8::HeapGraphNode* compiled_code = | 252 const v8::HeapGraphNode* compiled_code = |
252 GetProperty(compiled, v8::HeapGraphEdge::kInternal, "shared"); | 253 GetProperty(compiled, v8::HeapGraphEdge::kInternal, "shared"); |
253 CHECK_NE(NULL, compiled_code); | 254 CHECK_NE(NULL, compiled_code); |
254 const v8::HeapGraphNode* lazy_code = | 255 const v8::HeapGraphNode* lazy_code = |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
286 | 287 |
287 TEST(HeapSnapshotHeapNumbers) { | 288 TEST(HeapSnapshotHeapNumbers) { |
288 v8::HandleScope scope; | 289 v8::HandleScope scope; |
289 LocalContext env; | 290 LocalContext env; |
290 CompileRun( | 291 CompileRun( |
291 "a = 1; // a is Smi\n" | 292 "a = 1; // a is Smi\n" |
292 "b = 2.5; // b is HeapNumber"); | 293 "b = 2.5; // b is HeapNumber"); |
293 const v8::HeapSnapshot* snapshot = | 294 const v8::HeapSnapshot* snapshot = |
294 v8::HeapProfiler::TakeSnapshot(v8_str("numbers")); | 295 v8::HeapProfiler::TakeSnapshot(v8_str("numbers")); |
295 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); | 296 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); |
296 CHECK_EQ(NULL, GetProperty(global, v8::HeapGraphEdge::kShortcut, "a")); | 297 CHECK_EQ(NULL, GetProperty(global, v8::HeapGraphEdge::kProperty, "a")); |
297 const v8::HeapGraphNode* b = | 298 const v8::HeapGraphNode* b = |
298 GetProperty(global, v8::HeapGraphEdge::kShortcut, "b"); | 299 GetProperty(global, v8::HeapGraphEdge::kProperty, "b"); |
299 CHECK_NE(NULL, b); | 300 CHECK_NE(NULL, b); |
300 CHECK_EQ(v8::HeapGraphNode::kHeapNumber, b->GetType()); | 301 CHECK_EQ(v8::HeapGraphNode::kHeapNumber, b->GetType()); |
301 } | 302 } |
302 | 303 |
303 TEST(HeapSnapshotSlicedString) { | 304 TEST(HeapSnapshotSlicedString) { |
304 v8::HandleScope scope; | 305 v8::HandleScope scope; |
305 LocalContext env; | 306 LocalContext env; |
306 CompileRun( | 307 CompileRun( |
307 "parent_string = \"123456789.123456789.123456789.123456789.123456789." | 308 "parent_string = \"123456789.123456789.123456789.123456789.123456789." |
308 "123456789.123456789.123456789.123456789.123456789." | 309 "123456789.123456789.123456789.123456789.123456789." |
309 "123456789.123456789.123456789.123456789.123456789." | 310 "123456789.123456789.123456789.123456789.123456789." |
310 "123456789.123456789.123456789.123456789.123456789.\";" | 311 "123456789.123456789.123456789.123456789.123456789.\";" |
311 "child_string = parent_string.slice(100);"); | 312 "child_string = parent_string.slice(100);"); |
312 const v8::HeapSnapshot* snapshot = | 313 const v8::HeapSnapshot* snapshot = |
313 v8::HeapProfiler::TakeSnapshot(v8_str("strings")); | 314 v8::HeapProfiler::TakeSnapshot(v8_str("strings")); |
314 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); | 315 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); |
315 const v8::HeapGraphNode* parent_string = | 316 const v8::HeapGraphNode* parent_string = |
316 GetProperty(global, v8::HeapGraphEdge::kShortcut, "parent_string"); | 317 GetProperty(global, v8::HeapGraphEdge::kProperty, "parent_string"); |
317 CHECK_NE(NULL, parent_string); | 318 CHECK_NE(NULL, parent_string); |
318 const v8::HeapGraphNode* child_string = | 319 const v8::HeapGraphNode* child_string = |
319 GetProperty(global, v8::HeapGraphEdge::kShortcut, "child_string"); | 320 GetProperty(global, v8::HeapGraphEdge::kProperty, "child_string"); |
320 CHECK_NE(NULL, child_string); | 321 CHECK_NE(NULL, child_string); |
321 const v8::HeapGraphNode* parent = | 322 const v8::HeapGraphNode* parent = |
322 GetProperty(child_string, v8::HeapGraphEdge::kInternal, "parent"); | 323 GetProperty(child_string, v8::HeapGraphEdge::kInternal, "parent"); |
323 CHECK_EQ(parent_string, parent); | 324 CHECK_EQ(parent_string, parent); |
324 } | 325 } |
325 | 326 |
326 TEST(HeapSnapshotInternalReferences) { | 327 TEST(HeapSnapshotInternalReferences) { |
327 v8::HandleScope scope; | 328 v8::HandleScope scope; |
328 v8::Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(); | 329 v8::Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(); |
329 global_template->SetInternalFieldCount(2); | 330 global_template->SetInternalFieldCount(2); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
377 v8::HeapProfiler::TakeSnapshot(v8_str("s2")); | 378 v8::HeapProfiler::TakeSnapshot(v8_str("s2")); |
378 | 379 |
379 const v8::HeapGraphNode* global1 = GetGlobalObject(snapshot1); | 380 const v8::HeapGraphNode* global1 = GetGlobalObject(snapshot1); |
380 const v8::HeapGraphNode* global2 = GetGlobalObject(snapshot2); | 381 const v8::HeapGraphNode* global2 = GetGlobalObject(snapshot2); |
381 CHECK_NE_SNAPSHOT_OBJECT_ID(0, global1->GetId()); | 382 CHECK_NE_SNAPSHOT_OBJECT_ID(0, global1->GetId()); |
382 CHECK_EQ_SNAPSHOT_OBJECT_ID(global1->GetId(), global2->GetId()); | 383 CHECK_EQ_SNAPSHOT_OBJECT_ID(global1->GetId(), global2->GetId()); |
383 | 384 |
384 const v8::HeapGraphNode* a1 = | 385 const v8::HeapGraphNode* a1 = |
385 GetProperty(global1, v8::HeapGraphEdge::kProperty, "a"); | 386 GetProperty(global1, v8::HeapGraphEdge::kProperty, "a"); |
386 CHECK_NE(NULL, a1); | 387 CHECK_NE(NULL, a1); |
387 const v8::HeapGraphNode* e1 = | |
388 GetProperty(a1, v8::HeapGraphEdge::kHidden, "1"); | |
389 CHECK_NE(NULL, e1); | |
390 const v8::HeapGraphNode* k1 = | 388 const v8::HeapGraphNode* k1 = |
391 GetProperty(e1, v8::HeapGraphEdge::kInternal, "elements"); | 389 GetProperty(a1, v8::HeapGraphEdge::kInternal, "elements"); |
392 CHECK_NE(NULL, k1); | 390 CHECK_NE(NULL, k1); |
393 const v8::HeapGraphNode* a2 = | 391 const v8::HeapGraphNode* a2 = |
394 GetProperty(global2, v8::HeapGraphEdge::kProperty, "a"); | 392 GetProperty(global2, v8::HeapGraphEdge::kProperty, "a"); |
395 CHECK_NE(NULL, a2); | 393 CHECK_NE(NULL, a2); |
396 const v8::HeapGraphNode* e2 = | |
397 GetProperty(a2, v8::HeapGraphEdge::kHidden, "1"); | |
398 CHECK_NE(NULL, e2); | |
399 const v8::HeapGraphNode* k2 = | 394 const v8::HeapGraphNode* k2 = |
400 GetProperty(e2, v8::HeapGraphEdge::kInternal, "elements"); | 395 GetProperty(a2, v8::HeapGraphEdge::kInternal, "elements"); |
401 CHECK_NE(NULL, k2); | 396 CHECK_NE(NULL, k2); |
402 | 397 |
403 CHECK_EQ_SNAPSHOT_OBJECT_ID(a1->GetId(), a2->GetId()); | 398 CHECK_EQ_SNAPSHOT_OBJECT_ID(a1->GetId(), a2->GetId()); |
404 CHECK_EQ_SNAPSHOT_OBJECT_ID(e1->GetId(), e2->GetId()); | |
405 CHECK_EQ_SNAPSHOT_OBJECT_ID(k1->GetId(), k2->GetId()); | 399 CHECK_EQ_SNAPSHOT_OBJECT_ID(k1->GetId(), k2->GetId()); |
406 } | 400 } |
407 | 401 |
408 TEST(HeapEntryIdsAndGC) { | 402 TEST(HeapEntryIdsAndGC) { |
409 v8::HandleScope scope; | 403 v8::HandleScope scope; |
410 LocalContext env; | 404 LocalContext env; |
411 | 405 |
412 CompileRun( | 406 CompileRun( |
413 "function A() {}\n" | 407 "function A() {}\n" |
414 "function B(x) { this.x = x; }\n" | 408 "function B(x) { this.x = x; }\n" |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
507 "node6.b.a.b = node6.b.b; // node2 -> node3\n" | 501 "node6.b.a.b = node6.b.b; // node2 -> node3\n" |
508 "node6.b.b.a = node6.b.a; // node3 -> node2\n" | 502 "node6.b.b.a = node6.b.a; // node3 -> node2\n" |
509 "})();"); | 503 "})();"); |
510 | 504 |
511 const v8::HeapSnapshot* snapshot = | 505 const v8::HeapSnapshot* snapshot = |
512 v8::HeapProfiler::TakeSnapshot(v8_str("dominators")); | 506 v8::HeapProfiler::TakeSnapshot(v8_str("dominators")); |
513 | 507 |
514 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); | 508 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); |
515 CHECK_NE(NULL, global); | 509 CHECK_NE(NULL, global); |
516 const v8::HeapGraphNode* node6 = | 510 const v8::HeapGraphNode* node6 = |
517 GetProperty(global, v8::HeapGraphEdge::kShortcut, "node6"); | 511 GetProperty(global, v8::HeapGraphEdge::kProperty, "node6"); |
518 CHECK_NE(NULL, node6); | 512 CHECK_NE(NULL, node6); |
519 const v8::HeapGraphNode* node5 = | 513 const v8::HeapGraphNode* node5 = |
520 GetProperty(node6, v8::HeapGraphEdge::kProperty, "a"); | 514 GetProperty(node6, v8::HeapGraphEdge::kProperty, "a"); |
521 CHECK_NE(NULL, node5); | 515 CHECK_NE(NULL, node5); |
522 const v8::HeapGraphNode* node4 = | 516 const v8::HeapGraphNode* node4 = |
523 GetProperty(node6, v8::HeapGraphEdge::kProperty, "b"); | 517 GetProperty(node6, v8::HeapGraphEdge::kProperty, "b"); |
524 CHECK_NE(NULL, node4); | 518 CHECK_NE(NULL, node4); |
525 const v8::HeapGraphNode* node3 = | 519 const v8::HeapGraphNode* node3 = |
526 GetProperty(node4, v8::HeapGraphEdge::kProperty, "b"); | 520 GetProperty(node4, v8::HeapGraphEdge::kProperty, "b"); |
527 CHECK_NE(NULL, node3); | 521 CHECK_NE(NULL, node3); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
611 env->Global()->Set(v8_str("json_snapshot"), json_string); | 605 env->Global()->Set(v8_str("json_snapshot"), json_string); |
612 v8::Local<v8::Value> snapshot_parse_result = CompileRun( | 606 v8::Local<v8::Value> snapshot_parse_result = CompileRun( |
613 "var parsed = JSON.parse(json_snapshot); true;"); | 607 "var parsed = JSON.parse(json_snapshot); true;"); |
614 CHECK(!snapshot_parse_result.IsEmpty()); | 608 CHECK(!snapshot_parse_result.IsEmpty()); |
615 | 609 |
616 // Verify that snapshot object has required fields. | 610 // Verify that snapshot object has required fields. |
617 v8::Local<v8::Object> parsed_snapshot = | 611 v8::Local<v8::Object> parsed_snapshot = |
618 env->Global()->Get(v8_str("parsed"))->ToObject(); | 612 env->Global()->Get(v8_str("parsed"))->ToObject(); |
619 CHECK(parsed_snapshot->Has(v8_str("snapshot"))); | 613 CHECK(parsed_snapshot->Has(v8_str("snapshot"))); |
620 CHECK(parsed_snapshot->Has(v8_str("nodes"))); | 614 CHECK(parsed_snapshot->Has(v8_str("nodes"))); |
| 615 CHECK(parsed_snapshot->Has(v8_str("edges"))); |
621 CHECK(parsed_snapshot->Has(v8_str("strings"))); | 616 CHECK(parsed_snapshot->Has(v8_str("strings"))); |
622 | 617 |
623 // Get node and edge "member" offsets. | 618 // Get node and edge "member" offsets. |
624 v8::Local<v8::Value> meta_analysis_result = CompileRun( | 619 v8::Local<v8::Value> meta_analysis_result = CompileRun( |
625 "var parsed_meta = parsed.nodes[0];\n" | 620 "var meta = parsed.snapshot.meta;\n" |
626 "var children_count_offset =" | 621 "var edges_index_offset = meta.node_fields.indexOf('edges_index');\n" |
627 " parsed_meta.fields.indexOf('children_count');\n" | 622 "var node_fields_count = meta.node_fields.length;\n" |
628 "var children_offset =" | 623 "var edge_fields_count = meta.edge_fields.length;\n" |
629 " parsed_meta.fields.indexOf('children');\n" | 624 "var edge_type_offset = meta.edge_fields.indexOf('type');\n" |
630 "var children_meta =" | 625 "var edge_name_offset = meta.edge_fields.indexOf('name_or_index');\n" |
631 " parsed_meta.types[children_offset];\n" | 626 "var edge_to_node_offset = meta.edge_fields.indexOf('to_node');\n" |
632 "var child_fields_count = children_meta.fields.length;\n" | |
633 "var child_type_offset =" | |
634 " children_meta.fields.indexOf('type');\n" | |
635 "var child_name_offset =" | |
636 " children_meta.fields.indexOf('name_or_index');\n" | |
637 "var child_to_node_offset =" | |
638 " children_meta.fields.indexOf('to_node');\n" | |
639 "var property_type =" | 627 "var property_type =" |
640 " children_meta.types[child_type_offset].indexOf('property');\n" | 628 " meta.edge_types[edge_type_offset].indexOf('property');\n" |
641 "var shortcut_type =" | 629 "var shortcut_type =" |
642 " children_meta.types[child_type_offset].indexOf('shortcut');"); | 630 " meta.edge_types[edge_type_offset].indexOf('shortcut');\n" |
| 631 "parsed.nodes.concat(0, 0, 0, 0, 0, 0, parsed.edges.length);"); |
643 CHECK(!meta_analysis_result.IsEmpty()); | 632 CHECK(!meta_analysis_result.IsEmpty()); |
644 | 633 |
645 // A helper function for processing encoded nodes. | 634 // A helper function for processing encoded nodes. |
646 CompileRun( | 635 CompileRun( |
647 "function GetChildPosByProperty(pos, prop_name, prop_type) {\n" | 636 "function GetChildPosByProperty(pos, prop_name, prop_type) {\n" |
648 " var nodes = parsed.nodes;\n" | 637 " var nodes = parsed.nodes;\n" |
| 638 " var edges = parsed.edges;\n" |
649 " var strings = parsed.strings;\n" | 639 " var strings = parsed.strings;\n" |
650 " for (var i = 0,\n" | 640 " for (var i = nodes[pos + edges_index_offset],\n" |
651 " count = nodes[pos + children_count_offset] * child_fields_count;\n" | 641 " count = nodes[pos + node_fields_count + edges_index_offset];\n" |
652 " i < count; i += child_fields_count) {\n" | 642 " i < count; i += edge_fields_count) {\n" |
653 " var child_pos = pos + children_offset + i;\n" | 643 " if (edges[i + edge_type_offset] === prop_type\n" |
654 " if (nodes[child_pos + child_type_offset] === prop_type\n" | 644 " && strings[edges[i + edge_name_offset]] === prop_name)\n" |
655 " && strings[nodes[child_pos + child_name_offset]] === prop_name)\n" | 645 " return edges[i + edge_to_node_offset];\n" |
656 " return nodes[child_pos + child_to_node_offset];\n" | |
657 " }\n" | 646 " }\n" |
658 " return null;\n" | 647 " return null;\n" |
659 "}\n"); | 648 "}\n"); |
660 // Get the string index using the path: <root> -> <global>.b.x.s | 649 // Get the string index using the path: <root> -> <global>.b.x.s |
661 v8::Local<v8::Value> string_obj_pos_val = CompileRun( | 650 v8::Local<v8::Value> string_obj_pos_val = CompileRun( |
662 "GetChildPosByProperty(\n" | 651 "GetChildPosByProperty(\n" |
663 " GetChildPosByProperty(\n" | 652 " GetChildPosByProperty(\n" |
664 " GetChildPosByProperty(" | 653 " GetChildPosByProperty(" |
665 " parsed.nodes[1 + children_offset + child_to_node_offset]," | 654 " parsed.edges[parsed.nodes[edges_index_offset]" |
666 " \"b\",shortcut_type),\n" | 655 " + edge_to_node_offset]," |
| 656 " \"b\", property_type),\n" |
667 " \"x\", property_type)," | 657 " \"x\", property_type)," |
668 " \"s\", property_type)"); | 658 " \"s\", property_type)"); |
669 CHECK(!string_obj_pos_val.IsEmpty()); | 659 CHECK(!string_obj_pos_val.IsEmpty()); |
670 int string_obj_pos = | 660 int string_obj_pos = |
671 static_cast<int>(string_obj_pos_val->ToNumber()->Value()); | 661 static_cast<int>(string_obj_pos_val->ToNumber()->Value()); |
672 v8::Local<v8::Object> nodes_array = | 662 v8::Local<v8::Object> nodes_array = |
673 parsed_snapshot->Get(v8_str("nodes"))->ToObject(); | 663 parsed_snapshot->Get(v8_str("nodes"))->ToObject(); |
674 int string_index = static_cast<int>( | 664 int string_index = static_cast<int>( |
675 nodes_array->Get(string_obj_pos + 1)->ToNumber()->Value()); | 665 nodes_array->Get(string_obj_pos + 1)->ToNumber()->Value()); |
676 CHECK_GT(string_index, 0); | 666 CHECK_GT(string_index, 0); |
(...skipping 20 matching lines...) Expand all Loading... |
697 } | 687 } |
698 | 688 |
699 namespace { | 689 namespace { |
700 | 690 |
701 class TestStatsStream : public v8::OutputStream { | 691 class TestStatsStream : public v8::OutputStream { |
702 public: | 692 public: |
703 TestStatsStream() | 693 TestStatsStream() |
704 : eos_signaled_(0), | 694 : eos_signaled_(0), |
705 numbers_written_(0), | 695 numbers_written_(0), |
706 entries_count_(0), | 696 entries_count_(0), |
| 697 entries_size_(0), |
707 intervals_count_(0), | 698 intervals_count_(0), |
708 first_interval_index_(-1) { } | 699 first_interval_index_(-1) { } |
709 TestStatsStream(const TestStatsStream& stream) | 700 TestStatsStream(const TestStatsStream& stream) |
710 : v8::OutputStream(stream), | 701 : v8::OutputStream(stream), |
711 eos_signaled_(stream.eos_signaled_), | 702 eos_signaled_(stream.eos_signaled_), |
712 numbers_written_(stream.numbers_written_), | 703 numbers_written_(stream.numbers_written_), |
713 entries_count_(stream.entries_count_), | 704 entries_count_(stream.entries_count_), |
| 705 entries_size_(stream.entries_size_), |
714 intervals_count_(stream.intervals_count_), | 706 intervals_count_(stream.intervals_count_), |
715 first_interval_index_(stream.first_interval_index_) { } | 707 first_interval_index_(stream.first_interval_index_) { } |
716 virtual ~TestStatsStream() {} | 708 virtual ~TestStatsStream() {} |
717 virtual void EndOfStream() { ++eos_signaled_; } | 709 virtual void EndOfStream() { ++eos_signaled_; } |
718 virtual WriteResult WriteAsciiChunk(char* buffer, int chars_written) { | 710 virtual WriteResult WriteAsciiChunk(char* buffer, int chars_written) { |
719 ASSERT(false); | 711 ASSERT(false); |
720 return kAbort; | 712 return kAbort; |
721 } | 713 } |
722 virtual WriteResult WriteUint32Chunk(uint32_t* buffer, int numbers_written) { | 714 virtual WriteResult WriteUint32Chunk(uint32_t* buffer, int numbers_written) { |
723 ++intervals_count_; | 715 ++intervals_count_; |
724 ASSERT(numbers_written); | 716 ASSERT(numbers_written); |
725 numbers_written_ += numbers_written; | 717 numbers_written_ += numbers_written; |
726 entries_count_ = 0; | 718 entries_count_ = 0; |
727 if (first_interval_index_ == -1 && numbers_written != 0) | 719 if (first_interval_index_ == -1 && numbers_written != 0) |
728 first_interval_index_ = buffer[0]; | 720 first_interval_index_ = buffer[0]; |
729 for (int i = 1; i < numbers_written; i += 2) | 721 for (int i = 0; i < numbers_written; i += 3) { |
730 entries_count_ += buffer[i]; | 722 entries_count_ += buffer[i+1]; |
| 723 entries_size_ += buffer[i+2]; |
| 724 } |
731 | 725 |
732 return kContinue; | 726 return kContinue; |
733 } | 727 } |
734 int eos_signaled() { return eos_signaled_; } | 728 int eos_signaled() { return eos_signaled_; } |
735 int numbers_written() { return numbers_written_; } | 729 int numbers_written() { return numbers_written_; } |
736 uint32_t entries_count() const { return entries_count_; } | 730 uint32_t entries_count() const { return entries_count_; } |
| 731 uint32_t entries_size() const { return entries_size_; } |
737 int intervals_count() const { return intervals_count_; } | 732 int intervals_count() const { return intervals_count_; } |
738 int first_interval_index() const { return first_interval_index_; } | 733 int first_interval_index() const { return first_interval_index_; } |
739 | 734 |
740 private: | 735 private: |
741 int eos_signaled_; | 736 int eos_signaled_; |
742 int numbers_written_; | 737 int numbers_written_; |
743 uint32_t entries_count_; | 738 uint32_t entries_count_; |
| 739 uint32_t entries_size_; |
744 int intervals_count_; | 740 int intervals_count_; |
745 int first_interval_index_; | 741 int first_interval_index_; |
746 }; | 742 }; |
747 | 743 |
748 } // namespace | 744 } // namespace |
749 | 745 |
750 static TestStatsStream GetHeapStatsUpdate() { | 746 static TestStatsStream GetHeapStatsUpdate() { |
751 TestStatsStream stream; | 747 TestStatsStream stream; |
752 v8::HeapProfiler::PushHeapObjectsStats(&stream); | 748 v8::HeapProfiler::PushHeapObjectsStats(&stream); |
753 CHECK_EQ(1, stream.eos_signaled()); | 749 CHECK_EQ(1, stream.eos_signaled()); |
754 return stream; | 750 return stream; |
755 } | 751 } |
756 | 752 |
757 | 753 |
758 TEST(HeapSnapshotObjectsStats) { | 754 TEST(HeapSnapshotObjectsStats) { |
759 v8::HandleScope scope; | 755 v8::HandleScope scope; |
760 LocalContext env; | 756 LocalContext env; |
761 | 757 |
762 v8::HeapProfiler::StartHeapObjectsTracking(); | 758 v8::HeapProfiler::StartHeapObjectsTracking(); |
763 // We have to call GC 5 times. In other case the garbage will be | 759 // We have to call GC 5 times. In other case the garbage will be |
764 // the reason of flakiness. | 760 // the reason of flakiness. |
765 for (int i = 0; i < 5; ++i) { | 761 for (int i = 0; i < 5; ++i) { |
766 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); | 762 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); |
767 } | 763 } |
768 | 764 |
769 { | 765 { |
770 // Single chunk of data expected in update. Initial data. | 766 // Single chunk of data expected in update. Initial data. |
771 TestStatsStream stats_update = GetHeapStatsUpdate(); | 767 TestStatsStream stats_update = GetHeapStatsUpdate(); |
772 CHECK_EQ(1, stats_update.intervals_count()); | 768 CHECK_EQ(1, stats_update.intervals_count()); |
773 CHECK_EQ(2, stats_update.numbers_written()); | 769 CHECK_EQ(3, stats_update.numbers_written()); |
| 770 CHECK_LT(0, stats_update.entries_size()); |
774 CHECK_EQ(0, stats_update.first_interval_index()); | 771 CHECK_EQ(0, stats_update.first_interval_index()); |
775 } | 772 } |
776 | 773 |
777 // No data expected in update because nothing has happened. | 774 // No data expected in update because nothing has happened. |
778 CHECK_EQ(0, GetHeapStatsUpdate().numbers_written()); | 775 CHECK_EQ(0, GetHeapStatsUpdate().numbers_written()); |
779 { | 776 { |
780 v8::HandleScope inner_scope_1; | 777 v8::HandleScope inner_scope_1; |
781 v8::Local<v8::String> string1 = v8_str("string1"); | 778 v8_str("string1"); |
782 { | 779 { |
783 // Single chunk of data with one new entry expected in update. | 780 // Single chunk of data with one new entry expected in update. |
784 TestStatsStream stats_update = GetHeapStatsUpdate(); | 781 TestStatsStream stats_update = GetHeapStatsUpdate(); |
785 CHECK_EQ(1, stats_update.intervals_count()); | 782 CHECK_EQ(1, stats_update.intervals_count()); |
786 CHECK_EQ(2, stats_update.numbers_written()); | 783 CHECK_EQ(3, stats_update.numbers_written()); |
| 784 CHECK_LT(0, stats_update.entries_size()); |
787 CHECK_EQ(1, stats_update.entries_count()); | 785 CHECK_EQ(1, stats_update.entries_count()); |
788 CHECK_EQ(2, stats_update.first_interval_index()); | 786 CHECK_EQ(2, stats_update.first_interval_index()); |
789 } | 787 } |
790 | 788 |
791 // No data expected in update because nothing happened. | 789 // No data expected in update because nothing happened. |
792 CHECK_EQ(0, GetHeapStatsUpdate().numbers_written()); | 790 CHECK_EQ(0, GetHeapStatsUpdate().numbers_written()); |
793 | 791 |
794 { | 792 { |
795 v8::HandleScope inner_scope_2; | 793 v8::HandleScope inner_scope_2; |
796 v8::Local<v8::String> string2 = v8_str("string2"); | 794 v8_str("string2"); |
797 | 795 |
| 796 uint32_t entries_size; |
798 { | 797 { |
799 v8::HandleScope inner_scope_3; | 798 v8::HandleScope inner_scope_3; |
800 v8::Handle<v8::String> string3 = v8::String::New("string3"); | 799 v8_str("string3"); |
801 v8::Handle<v8::String> string4 = v8::String::New("string4"); | 800 v8_str("string4"); |
802 | 801 |
803 { | 802 { |
804 // Single chunk of data with three new entries expected in update. | 803 // Single chunk of data with three new entries expected in update. |
805 TestStatsStream stats_update = GetHeapStatsUpdate(); | 804 TestStatsStream stats_update = GetHeapStatsUpdate(); |
806 CHECK_EQ(1, stats_update.intervals_count()); | 805 CHECK_EQ(1, stats_update.intervals_count()); |
807 CHECK_EQ(2, stats_update.numbers_written()); | 806 CHECK_EQ(3, stats_update.numbers_written()); |
| 807 CHECK_LT(0, entries_size = stats_update.entries_size()); |
808 CHECK_EQ(3, stats_update.entries_count()); | 808 CHECK_EQ(3, stats_update.entries_count()); |
809 CHECK_EQ(4, stats_update.first_interval_index()); | 809 CHECK_EQ(4, stats_update.first_interval_index()); |
810 } | 810 } |
811 } | 811 } |
812 | 812 |
813 { | 813 { |
814 // Single chunk of data with two left entries expected in update. | 814 // Single chunk of data with two left entries expected in update. |
815 TestStatsStream stats_update = GetHeapStatsUpdate(); | 815 TestStatsStream stats_update = GetHeapStatsUpdate(); |
816 CHECK_EQ(1, stats_update.intervals_count()); | 816 CHECK_EQ(1, stats_update.intervals_count()); |
817 CHECK_EQ(2, stats_update.numbers_written()); | 817 CHECK_EQ(3, stats_update.numbers_written()); |
| 818 CHECK_GT(entries_size, stats_update.entries_size()); |
818 CHECK_EQ(1, stats_update.entries_count()); | 819 CHECK_EQ(1, stats_update.entries_count()); |
819 // Two strings from forth interval were released. | 820 // Two strings from forth interval were released. |
820 CHECK_EQ(4, stats_update.first_interval_index()); | 821 CHECK_EQ(4, stats_update.first_interval_index()); |
821 } | 822 } |
822 } | 823 } |
823 | 824 |
824 { | 825 { |
825 // Single chunk of data with 0 left entries expected in update. | 826 // Single chunk of data with 0 left entries expected in update. |
826 TestStatsStream stats_update = GetHeapStatsUpdate(); | 827 TestStatsStream stats_update = GetHeapStatsUpdate(); |
827 CHECK_EQ(1, stats_update.intervals_count()); | 828 CHECK_EQ(1, stats_update.intervals_count()); |
828 CHECK_EQ(2, stats_update.numbers_written()); | 829 CHECK_EQ(3, stats_update.numbers_written()); |
| 830 CHECK_EQ(0, stats_update.entries_size()); |
829 CHECK_EQ(0, stats_update.entries_count()); | 831 CHECK_EQ(0, stats_update.entries_count()); |
830 // The last string from forth interval was released. | 832 // The last string from forth interval was released. |
831 CHECK_EQ(4, stats_update.first_interval_index()); | 833 CHECK_EQ(4, stats_update.first_interval_index()); |
832 } | 834 } |
833 } | 835 } |
834 { | 836 { |
835 // Single chunk of data with 0 left entries expected in update. | 837 // Single chunk of data with 0 left entries expected in update. |
836 TestStatsStream stats_update = GetHeapStatsUpdate(); | 838 TestStatsStream stats_update = GetHeapStatsUpdate(); |
837 CHECK_EQ(1, stats_update.intervals_count()); | 839 CHECK_EQ(1, stats_update.intervals_count()); |
838 CHECK_EQ(2, stats_update.numbers_written()); | 840 CHECK_EQ(3, stats_update.numbers_written()); |
| 841 CHECK_EQ(0, stats_update.entries_size()); |
839 CHECK_EQ(0, stats_update.entries_count()); | 842 CHECK_EQ(0, stats_update.entries_count()); |
840 // The only string from the second interval was released. | 843 // The only string from the second interval was released. |
841 CHECK_EQ(2, stats_update.first_interval_index()); | 844 CHECK_EQ(2, stats_update.first_interval_index()); |
842 } | 845 } |
843 | 846 |
| 847 v8::Local<v8::Array> array = v8::Array::New(); |
| 848 CHECK_EQ(0, array->Length()); |
| 849 // Force array's buffer allocation. |
| 850 array->Set(2, v8_num(7)); |
| 851 |
| 852 uint32_t entries_size; |
| 853 { |
| 854 // Single chunk of data with 2 entries expected in update. |
| 855 TestStatsStream stats_update = GetHeapStatsUpdate(); |
| 856 CHECK_EQ(1, stats_update.intervals_count()); |
| 857 CHECK_EQ(3, stats_update.numbers_written()); |
| 858 CHECK_LT(0, entries_size = stats_update.entries_size()); |
| 859 // They are the array and its buffer. |
| 860 CHECK_EQ(2, stats_update.entries_count()); |
| 861 CHECK_EQ(8, stats_update.first_interval_index()); |
| 862 } |
| 863 |
| 864 for (int i = 0; i < 100; ++i) |
| 865 array->Set(i, v8_num(i)); |
| 866 |
| 867 { |
| 868 // Single chunk of data with 1 entry expected in update. |
| 869 TestStatsStream stats_update = GetHeapStatsUpdate(); |
| 870 CHECK_EQ(1, stats_update.intervals_count()); |
| 871 // The first interval was changed because old buffer was collected. |
| 872 // The second interval was changed because new buffer was allocated. |
| 873 CHECK_EQ(6, stats_update.numbers_written()); |
| 874 CHECK_LT(entries_size, stats_update.entries_size()); |
| 875 CHECK_EQ(2, stats_update.entries_count()); |
| 876 CHECK_EQ(8, stats_update.first_interval_index()); |
| 877 } |
| 878 |
844 v8::HeapProfiler::StopHeapObjectsTracking(); | 879 v8::HeapProfiler::StopHeapObjectsTracking(); |
845 } | 880 } |
846 | 881 |
847 | 882 |
848 static void CheckChildrenIds(const v8::HeapSnapshot* snapshot, | 883 static void CheckChildrenIds(const v8::HeapSnapshot* snapshot, |
849 const v8::HeapGraphNode* node, | 884 const v8::HeapGraphNode* node, |
850 int level, int max_level) { | 885 int level, int max_level) { |
851 if (level > max_level) return; | 886 if (level > max_level) return; |
852 CHECK_EQ(node, snapshot->GetNodeById(node->GetId())); | 887 CHECK_EQ(node, snapshot->GetNodeById(node->GetId())); |
853 for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) { | 888 for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) { |
(...skipping 13 matching lines...) Expand all Loading... |
867 | 902 |
868 const v8::HeapSnapshot* snapshot = | 903 const v8::HeapSnapshot* snapshot = |
869 v8::HeapProfiler::TakeSnapshot(v8_str("id")); | 904 v8::HeapProfiler::TakeSnapshot(v8_str("id")); |
870 const v8::HeapGraphNode* root = snapshot->GetRoot(); | 905 const v8::HeapGraphNode* root = snapshot->GetRoot(); |
871 CheckChildrenIds(snapshot, root, 0, 3); | 906 CheckChildrenIds(snapshot, root, 0, 3); |
872 // Check a big id, which should not exist yet. | 907 // Check a big id, which should not exist yet. |
873 CHECK_EQ(NULL, snapshot->GetNodeById(0x1000000UL)); | 908 CHECK_EQ(NULL, snapshot->GetNodeById(0x1000000UL)); |
874 } | 909 } |
875 | 910 |
876 | 911 |
| 912 TEST(HeapSnapshotGetSnapshotObjectId) { |
| 913 v8::HandleScope scope; |
| 914 LocalContext env; |
| 915 CompileRun("globalObject = {};\n"); |
| 916 const v8::HeapSnapshot* snapshot = |
| 917 v8::HeapProfiler::TakeSnapshot(v8_str("get_snapshot_object_id")); |
| 918 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); |
| 919 const v8::HeapGraphNode* global_object = |
| 920 GetProperty(global, v8::HeapGraphEdge::kProperty, "globalObject"); |
| 921 CHECK(global_object); |
| 922 |
| 923 v8::Local<v8::Value> globalObjectHandle = |
| 924 env->Global()->Get(v8::String::New("globalObject")); |
| 925 CHECK(!globalObjectHandle.IsEmpty()); |
| 926 CHECK(globalObjectHandle->IsObject()); |
| 927 |
| 928 v8::SnapshotObjectId id = |
| 929 v8::HeapProfiler::GetSnapshotObjectId(globalObjectHandle); |
| 930 CHECK_NE(static_cast<int>(v8::HeapProfiler::kUnknownObjectId), |
| 931 id); |
| 932 CHECK_EQ(static_cast<int>(id), global_object->GetId()); |
| 933 } |
| 934 |
| 935 |
| 936 TEST(HeapSnapshotUnknownSnapshotObjectId) { |
| 937 v8::HandleScope scope; |
| 938 LocalContext env; |
| 939 CompileRun("globalObject = {};\n"); |
| 940 const v8::HeapSnapshot* snapshot = |
| 941 v8::HeapProfiler::TakeSnapshot(v8_str("unknown_object_id")); |
| 942 const v8::HeapGraphNode* node = |
| 943 snapshot->GetNodeById(v8::HeapProfiler::kUnknownObjectId); |
| 944 CHECK_EQ(NULL, node); |
| 945 } |
| 946 |
| 947 |
877 namespace { | 948 namespace { |
878 | 949 |
879 class TestActivityControl : public v8::ActivityControl { | 950 class TestActivityControl : public v8::ActivityControl { |
880 public: | 951 public: |
881 explicit TestActivityControl(int abort_count) | 952 explicit TestActivityControl(int abort_count) |
882 : done_(0), total_(0), abort_count_(abort_count) {} | 953 : done_(0), total_(0), abort_count_(abort_count) {} |
883 ControlOption ReportProgressValue(int done, int total) { | 954 ControlOption ReportProgressValue(int done, int total) { |
884 done_ = done; | 955 done_ = done; |
885 total_ = total; | 956 total_ = total; |
886 return --abort_count_ != 0 ? kContinue : kAbort; | 957 return --abort_count_ != 0 ? kContinue : kAbort; |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1105 v8::HandleScope scope; | 1176 v8::HandleScope scope; |
1106 LocalContext env; | 1177 LocalContext env; |
1107 | 1178 |
1108 GraphWithImplicitRefs graph(&env); | 1179 GraphWithImplicitRefs graph(&env); |
1109 v8::V8::SetGlobalGCPrologueCallback(&GraphWithImplicitRefs::gcPrologue); | 1180 v8::V8::SetGlobalGCPrologueCallback(&GraphWithImplicitRefs::gcPrologue); |
1110 | 1181 |
1111 const v8::HeapSnapshot* snapshot = | 1182 const v8::HeapSnapshot* snapshot = |
1112 v8::HeapProfiler::TakeSnapshot(v8_str("implicit_refs")); | 1183 v8::HeapProfiler::TakeSnapshot(v8_str("implicit_refs")); |
1113 | 1184 |
1114 const v8::HeapGraphNode* global_object = GetGlobalObject(snapshot); | 1185 const v8::HeapGraphNode* global_object = GetGlobalObject(snapshot); |
1115 // Use kShortcut type to skip intermediate JSGlobalPropertyCell | |
1116 const v8::HeapGraphNode* obj0 = GetProperty( | 1186 const v8::HeapGraphNode* obj0 = GetProperty( |
1117 global_object, v8::HeapGraphEdge::kShortcut, "root_object"); | 1187 global_object, v8::HeapGraphEdge::kProperty, "root_object"); |
1118 CHECK(obj0); | 1188 CHECK(obj0); |
1119 CHECK_EQ(v8::HeapGraphNode::kObject, obj0->GetType()); | 1189 CHECK_EQ(v8::HeapGraphNode::kObject, obj0->GetType()); |
1120 const v8::HeapGraphNode* obj1 = GetProperty( | 1190 const v8::HeapGraphNode* obj1 = GetProperty( |
1121 obj0, v8::HeapGraphEdge::kInternal, "native"); | 1191 obj0, v8::HeapGraphEdge::kInternal, "native"); |
1122 CHECK(obj1); | 1192 CHECK(obj1); |
1123 int implicit_targets_count = 0; | 1193 int implicit_targets_count = 0; |
1124 for (int i = 0, count = obj1->GetChildrenCount(); i < count; ++i) { | 1194 for (int i = 0, count = obj1->GetChildrenCount(); i < count; ++i) { |
1125 const v8::HeapGraphEdge* prop = obj1->GetChild(i); | 1195 const v8::HeapGraphEdge* prop = obj1->GetChild(i); |
1126 v8::String::AsciiValue prop_name(prop->GetName()); | 1196 v8::String::AsciiValue prop_name(prop->GetName()); |
1127 if (prop->GetType() == v8::HeapGraphEdge::kInternal && | 1197 if (prop->GetType() == v8::HeapGraphEdge::kInternal && |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1280 | 1350 |
1281 CompileRun("a = { s_prop: \'value\', n_prop: 0.1 };"); | 1351 CompileRun("a = { s_prop: \'value\', n_prop: 0.1 };"); |
1282 const v8::HeapSnapshot* snapshot = | 1352 const v8::HeapSnapshot* snapshot = |
1283 v8::HeapProfiler::TakeSnapshot(v8_str("value")); | 1353 v8::HeapProfiler::TakeSnapshot(v8_str("value")); |
1284 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); | 1354 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); |
1285 CHECK(global->GetHeapValue()->IsObject()); | 1355 CHECK(global->GetHeapValue()->IsObject()); |
1286 v8::Local<v8::Object> js_global = | 1356 v8::Local<v8::Object> js_global = |
1287 env->Global()->GetPrototype().As<v8::Object>(); | 1357 env->Global()->GetPrototype().As<v8::Object>(); |
1288 CHECK(js_global == global->GetHeapValue()); | 1358 CHECK(js_global == global->GetHeapValue()); |
1289 const v8::HeapGraphNode* obj = GetProperty( | 1359 const v8::HeapGraphNode* obj = GetProperty( |
1290 global, v8::HeapGraphEdge::kShortcut, "a"); | 1360 global, v8::HeapGraphEdge::kProperty, "a"); |
1291 CHECK(obj->GetHeapValue()->IsObject()); | 1361 CHECK(obj->GetHeapValue()->IsObject()); |
1292 v8::Local<v8::Object> js_obj = js_global->Get(v8_str("a")).As<v8::Object>(); | 1362 v8::Local<v8::Object> js_obj = js_global->Get(v8_str("a")).As<v8::Object>(); |
1293 CHECK(js_obj == obj->GetHeapValue()); | 1363 CHECK(js_obj == obj->GetHeapValue()); |
1294 const v8::HeapGraphNode* s_prop = | 1364 const v8::HeapGraphNode* s_prop = |
1295 GetProperty(obj, v8::HeapGraphEdge::kProperty, "s_prop"); | 1365 GetProperty(obj, v8::HeapGraphEdge::kProperty, "s_prop"); |
1296 v8::Local<v8::String> js_s_prop = | 1366 v8::Local<v8::String> js_s_prop = |
1297 js_obj->Get(v8_str("s_prop")).As<v8::String>(); | 1367 js_obj->Get(v8_str("s_prop")).As<v8::String>(); |
1298 CHECK(js_s_prop == s_prop->GetHeapValue()); | 1368 CHECK(js_s_prop == s_prop->GetHeapValue()); |
1299 const v8::HeapGraphNode* n_prop = | 1369 const v8::HeapGraphNode* n_prop = |
1300 GetProperty(obj, v8::HeapGraphEdge::kProperty, "n_prop"); | 1370 GetProperty(obj, v8::HeapGraphEdge::kProperty, "n_prop"); |
1301 v8::Local<v8::Number> js_n_prop = | 1371 v8::Local<v8::Number> js_n_prop = |
1302 js_obj->Get(v8_str("n_prop")).As<v8::Number>(); | 1372 js_obj->Get(v8_str("n_prop")).As<v8::Number>(); |
1303 CHECK(js_n_prop == n_prop->GetHeapValue()); | 1373 CHECK(js_n_prop == n_prop->GetHeapValue()); |
1304 } | 1374 } |
1305 | 1375 |
1306 | 1376 |
1307 TEST(GetHeapValueForDeletedObject) { | 1377 TEST(GetHeapValueForDeletedObject) { |
1308 v8::HandleScope scope; | 1378 v8::HandleScope scope; |
1309 LocalContext env; | 1379 LocalContext env; |
1310 | 1380 |
1311 // It is impossible to delete a global property, so we are about to delete a | 1381 // It is impossible to delete a global property, so we are about to delete a |
1312 // property of the "a" object. Also, the "p" object can't be an empty one | 1382 // property of the "a" object. Also, the "p" object can't be an empty one |
1313 // because the empty object is static and isn't actually deleted. | 1383 // because the empty object is static and isn't actually deleted. |
1314 CompileRun("a = { p: { r: {} } };"); | 1384 CompileRun("a = { p: { r: {} } };"); |
1315 const v8::HeapSnapshot* snapshot = | 1385 const v8::HeapSnapshot* snapshot = |
1316 v8::HeapProfiler::TakeSnapshot(v8_str("snapshot")); | 1386 v8::HeapProfiler::TakeSnapshot(v8_str("snapshot")); |
1317 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); | 1387 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); |
1318 const v8::HeapGraphNode* obj = GetProperty( | 1388 const v8::HeapGraphNode* obj = GetProperty( |
1319 global, v8::HeapGraphEdge::kShortcut, "a"); | 1389 global, v8::HeapGraphEdge::kProperty, "a"); |
1320 const v8::HeapGraphNode* prop = GetProperty( | 1390 const v8::HeapGraphNode* prop = GetProperty( |
1321 obj, v8::HeapGraphEdge::kProperty, "p"); | 1391 obj, v8::HeapGraphEdge::kProperty, "p"); |
1322 { | 1392 { |
1323 // Perform the check inside a nested local scope to avoid creating a | 1393 // Perform the check inside a nested local scope to avoid creating a |
1324 // reference to the object we are deleting. | 1394 // reference to the object we are deleting. |
1325 v8::HandleScope scope; | 1395 v8::HandleScope scope; |
1326 CHECK(prop->GetHeapValue()->IsObject()); | 1396 CHECK(prop->GetHeapValue()->IsObject()); |
1327 } | 1397 } |
1328 CompileRun("delete a.p;"); | 1398 CompileRun("delete a.p;"); |
1329 CHECK(prop->GetHeapValue()->IsUndefined()); | 1399 CHECK(prop->GetHeapValue()->IsUndefined()); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1396 "});\n" | 1466 "});\n" |
1397 "obj1.__defineSetter__('propWithSetter', function Z(value) {\n" | 1467 "obj1.__defineSetter__('propWithSetter', function Z(value) {\n" |
1398 " return this.value_ = value;\n" | 1468 " return this.value_ = value;\n" |
1399 "});\n"); | 1469 "});\n"); |
1400 const v8::HeapSnapshot* snapshot = | 1470 const v8::HeapSnapshot* snapshot = |
1401 v8::HeapProfiler::TakeSnapshot(v8_str("fastCaseGetter")); | 1471 v8::HeapProfiler::TakeSnapshot(v8_str("fastCaseGetter")); |
1402 | 1472 |
1403 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); | 1473 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); |
1404 CHECK_NE(NULL, global); | 1474 CHECK_NE(NULL, global); |
1405 const v8::HeapGraphNode* obj1 = | 1475 const v8::HeapGraphNode* obj1 = |
1406 GetProperty(global, v8::HeapGraphEdge::kShortcut, "obj1"); | 1476 GetProperty(global, v8::HeapGraphEdge::kProperty, "obj1"); |
1407 CHECK_NE(NULL, obj1); | 1477 CHECK_NE(NULL, obj1); |
1408 const v8::HeapGraphNode* getterFunction = | 1478 const v8::HeapGraphNode* getterFunction = |
1409 GetProperty(obj1, v8::HeapGraphEdge::kProperty, "get-propWithGetter"); | 1479 GetProperty(obj1, v8::HeapGraphEdge::kProperty, "get-propWithGetter"); |
1410 CHECK_NE(NULL, getterFunction); | 1480 CHECK_NE(NULL, getterFunction); |
1411 const v8::HeapGraphNode* setterFunction = | 1481 const v8::HeapGraphNode* setterFunction = |
1412 GetProperty(obj1, v8::HeapGraphEdge::kProperty, "set-propWithSetter"); | 1482 GetProperty(obj1, v8::HeapGraphEdge::kProperty, "set-propWithSetter"); |
1413 CHECK_NE(NULL, setterFunction); | 1483 CHECK_NE(NULL, setterFunction); |
1414 } | 1484 } |
1415 | 1485 |
1416 | 1486 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1478 v8::HandleScope scope; | 1548 v8::HandleScope scope; |
1479 LocalContext env; | 1549 LocalContext env; |
1480 | 1550 |
1481 CompileRun( | 1551 CompileRun( |
1482 "fun = (function (x) { return function () { return x + 1; } })(1);"); | 1552 "fun = (function (x) { return function () { return x + 1; } })(1);"); |
1483 const v8::HeapSnapshot* snapshot = | 1553 const v8::HeapSnapshot* snapshot = |
1484 v8::HeapProfiler::TakeSnapshot(v8_str("fun")); | 1554 v8::HeapProfiler::TakeSnapshot(v8_str("fun")); |
1485 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); | 1555 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); |
1486 CHECK_NE(NULL, global); | 1556 CHECK_NE(NULL, global); |
1487 const v8::HeapGraphNode* fun = | 1557 const v8::HeapGraphNode* fun = |
1488 GetProperty(global, v8::HeapGraphEdge::kShortcut, "fun"); | 1558 GetProperty(global, v8::HeapGraphEdge::kProperty, "fun"); |
1489 CHECK(HasWeakEdge(fun)); | 1559 CHECK(HasWeakEdge(fun)); |
1490 const v8::HeapGraphNode* shared = | 1560 const v8::HeapGraphNode* shared = |
1491 GetProperty(fun, v8::HeapGraphEdge::kInternal, "shared"); | 1561 GetProperty(fun, v8::HeapGraphEdge::kInternal, "shared"); |
1492 CHECK(HasWeakEdge(shared)); | 1562 CHECK(HasWeakEdge(shared)); |
1493 } | 1563 } |
1494 | 1564 |
1495 | 1565 |
1496 TEST(PersistentHandleCount) { | 1566 TEST(PersistentHandleCount) { |
1497 v8::HandleScope scope; | 1567 v8::HandleScope scope; |
1498 LocalContext env; | 1568 LocalContext env; |
(...skipping 19 matching lines...) Expand all Loading... |
1518 // Dipose the persistent handles in a different order. | 1588 // Dipose the persistent handles in a different order. |
1519 p_AAA.Dispose(); | 1589 p_AAA.Dispose(); |
1520 CHECK_EQ(global_handle_count + 2, | 1590 CHECK_EQ(global_handle_count + 2, |
1521 v8::HeapProfiler::GetPersistentHandleCount()); | 1591 v8::HeapProfiler::GetPersistentHandleCount()); |
1522 p_CCC.Dispose(); | 1592 p_CCC.Dispose(); |
1523 CHECK_EQ(global_handle_count + 1, | 1593 CHECK_EQ(global_handle_count + 1, |
1524 v8::HeapProfiler::GetPersistentHandleCount()); | 1594 v8::HeapProfiler::GetPersistentHandleCount()); |
1525 p_BBB.Dispose(); | 1595 p_BBB.Dispose(); |
1526 CHECK_EQ(global_handle_count, v8::HeapProfiler::GetPersistentHandleCount()); | 1596 CHECK_EQ(global_handle_count, v8::HeapProfiler::GetPersistentHandleCount()); |
1527 } | 1597 } |
OLD | NEW |