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 <ctype.h> | 5 #include <ctype.h> |
6 | 6 |
7 #include "v8.h" | 7 #include "v8.h" |
8 | 8 |
9 #include "cctest.h" | 9 #include "cctest.h" |
| 10 #include "hashmap.h" |
10 #include "heap-profiler.h" | 11 #include "heap-profiler.h" |
11 #include "snapshot.h" | 12 #include "snapshot.h" |
12 #include "debug.h" | 13 #include "debug.h" |
13 #include "utils-inl.h" | 14 #include "utils-inl.h" |
14 #include "../include/v8-profiler.h" | 15 #include "../include/v8-profiler.h" |
15 | 16 |
16 namespace { | 17 namespace { |
17 | 18 |
18 class NamedEntriesDetector { | 19 class NamedEntriesDetector { |
19 public: | 20 public: |
20 NamedEntriesDetector() | 21 NamedEntriesDetector() |
21 : has_A2(false), has_B2(false), has_C2(false) { | 22 : has_A2(false), has_B2(false), has_C2(false) { |
22 } | 23 } |
23 | 24 |
24 void CheckEntry(i::HeapEntry* entry) { | 25 void CheckEntry(i::HeapEntry* entry) { |
25 if (strcmp(entry->name(), "A2") == 0) has_A2 = true; | 26 if (strcmp(entry->name(), "A2") == 0) has_A2 = true; |
26 if (strcmp(entry->name(), "B2") == 0) has_B2 = true; | 27 if (strcmp(entry->name(), "B2") == 0) has_B2 = true; |
27 if (strcmp(entry->name(), "C2") == 0) has_C2 = true; | 28 if (strcmp(entry->name(), "C2") == 0) has_C2 = true; |
28 } | 29 } |
29 | 30 |
| 31 static bool AddressesMatch(void* key1, void* key2) { |
| 32 return key1 == key2; |
| 33 } |
| 34 |
30 void CheckAllReachables(i::HeapEntry* root) { | 35 void CheckAllReachables(i::HeapEntry* root) { |
| 36 i::HashMap visited(AddressesMatch); |
31 i::List<i::HeapEntry*> list(10); | 37 i::List<i::HeapEntry*> list(10); |
32 list.Add(root); | 38 list.Add(root); |
33 root->paint(); | |
34 CheckEntry(root); | 39 CheckEntry(root); |
35 while (!list.is_empty()) { | 40 while (!list.is_empty()) { |
36 i::HeapEntry* entry = list.RemoveLast(); | 41 i::HeapEntry* entry = list.RemoveLast(); |
37 i::Vector<i::HeapGraphEdge*> children = entry->children(); | 42 i::Vector<i::HeapGraphEdge*> children = entry->children(); |
38 for (int i = 0; i < children.length(); ++i) { | 43 for (int i = 0; i < children.length(); ++i) { |
39 if (children[i]->type() == i::HeapGraphEdge::kShortcut) continue; | 44 if (children[i]->type() == i::HeapGraphEdge::kShortcut) continue; |
40 i::HeapEntry* child = children[i]->to(); | 45 i::HeapEntry* child = children[i]->to(); |
41 if (!child->painted()) { | 46 i::HashMap::Entry* entry = visited.Lookup( |
42 list.Add(child); | 47 reinterpret_cast<void*>(child), |
43 child->paint(); | 48 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(child)), |
44 CheckEntry(child); | 49 true); |
45 } | 50 if (entry->value) |
| 51 continue; |
| 52 entry->value = reinterpret_cast<void*>(1); |
| 53 list.Add(child); |
| 54 CheckEntry(child); |
46 } | 55 } |
47 } | 56 } |
48 } | 57 } |
49 | 58 |
50 bool has_A2; | 59 bool has_A2; |
51 bool has_B2; | 60 bool has_B2; |
52 bool has_C2; | 61 bool has_C2; |
53 }; | 62 }; |
54 | 63 |
55 } // namespace | 64 } // namespace |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
98 | 107 |
99 CompileRun( | 108 CompileRun( |
100 "function A2() {}\n" | 109 "function A2() {}\n" |
101 "function B2(x) { return function() { return typeof x; }; }\n" | 110 "function B2(x) { return function() { return typeof x; }; }\n" |
102 "function C2(x) { this.x1 = x; this.x2 = x; this[1] = x; }\n" | 111 "function C2(x) { this.x1 = x; this.x2 = x; this[1] = x; }\n" |
103 "var a2 = new A2();\n" | 112 "var a2 = new A2();\n" |
104 "var b2_1 = new B2(a2), b2_2 = new B2(a2);\n" | 113 "var b2_1 = new B2(a2), b2_2 = new B2(a2);\n" |
105 "var c2 = new C2(a2);"); | 114 "var c2 = new C2(a2);"); |
106 const v8::HeapSnapshot* snapshot_env2 = | 115 const v8::HeapSnapshot* snapshot_env2 = |
107 v8::HeapProfiler::TakeSnapshot(v8_str("env2")); | 116 v8::HeapProfiler::TakeSnapshot(v8_str("env2")); |
108 i::HeapSnapshot* i_snapshot_env2 = | |
109 const_cast<i::HeapSnapshot*>( | |
110 reinterpret_cast<const i::HeapSnapshot*>(snapshot_env2)); | |
111 const v8::HeapGraphNode* global_env2 = GetGlobalObject(snapshot_env2); | 117 const v8::HeapGraphNode* global_env2 = GetGlobalObject(snapshot_env2); |
112 | 118 |
113 // Verify, that JS global object of env2 has '..2' properties. | 119 // Verify, that JS global object of env2 has '..2' properties. |
114 const v8::HeapGraphNode* a2_node = | 120 const v8::HeapGraphNode* a2_node = |
115 GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "a2"); | 121 GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "a2"); |
116 CHECK_NE(NULL, a2_node); | 122 CHECK_NE(NULL, a2_node); |
117 CHECK_NE( | 123 CHECK_NE( |
118 NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "b2_1")); | 124 NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "b2_1")); |
119 CHECK_NE( | 125 CHECK_NE( |
120 NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "b2_2")); | 126 NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "b2_2")); |
121 CHECK_NE(NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "c2")); | 127 CHECK_NE(NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "c2")); |
122 | 128 |
123 // Paint all nodes reachable from global object. | |
124 NamedEntriesDetector det; | 129 NamedEntriesDetector det; |
125 i_snapshot_env2->ClearPaint(); | |
126 det.CheckAllReachables(const_cast<i::HeapEntry*>( | 130 det.CheckAllReachables(const_cast<i::HeapEntry*>( |
127 reinterpret_cast<const i::HeapEntry*>(global_env2))); | 131 reinterpret_cast<const i::HeapEntry*>(global_env2))); |
128 CHECK(det.has_A2); | 132 CHECK(det.has_A2); |
129 CHECK(det.has_B2); | 133 CHECK(det.has_B2); |
130 CHECK(det.has_C2); | 134 CHECK(det.has_C2); |
131 } | 135 } |
132 | 136 |
133 | 137 |
134 TEST(HeapSnapshotObjectSizes) { | 138 TEST(HeapSnapshotObjectSizes) { |
135 v8::HandleScope scope; | 139 v8::HandleScope scope; |
(...skipping 13 matching lines...) Expand all Loading... |
149 GetProperty(global, v8::HeapGraphEdge::kProperty, "x"); | 153 GetProperty(global, v8::HeapGraphEdge::kProperty, "x"); |
150 CHECK_NE(NULL, x); | 154 CHECK_NE(NULL, x); |
151 const v8::HeapGraphNode* x1 = | 155 const v8::HeapGraphNode* x1 = |
152 GetProperty(x, v8::HeapGraphEdge::kProperty, "a"); | 156 GetProperty(x, v8::HeapGraphEdge::kProperty, "a"); |
153 CHECK_NE(NULL, x1); | 157 CHECK_NE(NULL, x1); |
154 const v8::HeapGraphNode* x2 = | 158 const v8::HeapGraphNode* x2 = |
155 GetProperty(x, v8::HeapGraphEdge::kProperty, "b"); | 159 GetProperty(x, v8::HeapGraphEdge::kProperty, "b"); |
156 CHECK_NE(NULL, x2); | 160 CHECK_NE(NULL, x2); |
157 | 161 |
158 // Test sizes. | 162 // Test sizes. |
159 CHECK_EQ(x->GetSelfSize() * 3, x->GetRetainedSize()); | 163 CHECK_NE(0, x->GetSelfSize()); |
160 CHECK_EQ(x1->GetSelfSize(), x1->GetRetainedSize()); | 164 CHECK_NE(0, x1->GetSelfSize()); |
161 CHECK_EQ(x2->GetSelfSize(), x2->GetRetainedSize()); | 165 CHECK_NE(0, x2->GetSelfSize()); |
162 } | 166 } |
163 | 167 |
164 | 168 |
165 TEST(BoundFunctionInSnapshot) { | 169 TEST(BoundFunctionInSnapshot) { |
166 v8::HandleScope scope; | 170 v8::HandleScope scope; |
167 LocalContext env; | 171 LocalContext env; |
168 CompileRun( | 172 CompileRun( |
169 "function myFunction(a, b) { this.a = a; this.b = b; }\n" | 173 "function myFunction(a, b) { this.a = a; this.b = b; }\n" |
170 "function AAAAA() {}\n" | 174 "function AAAAA() {}\n" |
171 "boundFunction = myFunction.bind(new AAAAA(), 20, new Number(12)); \n"); | 175 "boundFunction = myFunction.bind(new AAAAA(), 20, new Number(12)); \n"); |
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
470 const v8::HeapSnapshot* snapshot = | 474 const v8::HeapSnapshot* snapshot = |
471 v8::HeapProfiler::TakeSnapshot(v8_str("s")); | 475 v8::HeapProfiler::TakeSnapshot(v8_str("s")); |
472 const v8::HeapGraphNode* root1 = snapshot->GetRoot(); | 476 const v8::HeapGraphNode* root1 = snapshot->GetRoot(); |
473 const_cast<i::HeapSnapshot*>(reinterpret_cast<const i::HeapSnapshot*>( | 477 const_cast<i::HeapSnapshot*>(reinterpret_cast<const i::HeapSnapshot*>( |
474 snapshot))->GetSortedEntriesList(); | 478 snapshot))->GetSortedEntriesList(); |
475 const v8::HeapGraphNode* root2 = snapshot->GetRoot(); | 479 const v8::HeapGraphNode* root2 = snapshot->GetRoot(); |
476 CHECK_EQ(root1, root2); | 480 CHECK_EQ(root1, root2); |
477 } | 481 } |
478 | 482 |
479 | 483 |
480 TEST(HeapEntryDominator) { | |
481 // The graph looks like this: | |
482 // | |
483 // -> node1 | |
484 // a |^ | |
485 // -> node5 ba | |
486 // a v| | |
487 // node6 -> node2 | |
488 // b a |^ | |
489 // -> node4 ba | |
490 // b v| | |
491 // -> node3 | |
492 // | |
493 // The dominator for all nodes is node6. | |
494 | |
495 v8::HandleScope scope; | |
496 LocalContext env; | |
497 | |
498 CompileRun( | |
499 "function X(a, b) { this.a = a; this.b = b; }\n" | |
500 "node6 = new X(new X(new X()), new X(new X(),new X()));\n" | |
501 "(function(){\n" | |
502 "node6.a.a.b = node6.b.a; // node1 -> node2\n" | |
503 "node6.b.a.a = node6.a.a; // node2 -> node1\n" | |
504 "node6.b.a.b = node6.b.b; // node2 -> node3\n" | |
505 "node6.b.b.a = node6.b.a; // node3 -> node2\n" | |
506 "})();"); | |
507 | |
508 const v8::HeapSnapshot* snapshot = | |
509 v8::HeapProfiler::TakeSnapshot(v8_str("dominators")); | |
510 | |
511 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); | |
512 CHECK_NE(NULL, global); | |
513 const v8::HeapGraphNode* node6 = | |
514 GetProperty(global, v8::HeapGraphEdge::kProperty, "node6"); | |
515 CHECK_NE(NULL, node6); | |
516 const v8::HeapGraphNode* node5 = | |
517 GetProperty(node6, v8::HeapGraphEdge::kProperty, "a"); | |
518 CHECK_NE(NULL, node5); | |
519 const v8::HeapGraphNode* node4 = | |
520 GetProperty(node6, v8::HeapGraphEdge::kProperty, "b"); | |
521 CHECK_NE(NULL, node4); | |
522 const v8::HeapGraphNode* node3 = | |
523 GetProperty(node4, v8::HeapGraphEdge::kProperty, "b"); | |
524 CHECK_NE(NULL, node3); | |
525 const v8::HeapGraphNode* node2 = | |
526 GetProperty(node4, v8::HeapGraphEdge::kProperty, "a"); | |
527 CHECK_NE(NULL, node2); | |
528 const v8::HeapGraphNode* node1 = | |
529 GetProperty(node5, v8::HeapGraphEdge::kProperty, "a"); | |
530 CHECK_NE(NULL, node1); | |
531 | |
532 CHECK_EQ(node6, node1->GetDominatorNode()); | |
533 CHECK_EQ(node6, node2->GetDominatorNode()); | |
534 CHECK_EQ(node6, node3->GetDominatorNode()); | |
535 CHECK_EQ(node6, node4->GetDominatorNode()); | |
536 CHECK_EQ(node6, node5->GetDominatorNode()); | |
537 } | |
538 | |
539 | |
540 namespace { | 484 namespace { |
541 | 485 |
542 class TestJSONStream : public v8::OutputStream { | 486 class TestJSONStream : public v8::OutputStream { |
543 public: | 487 public: |
544 TestJSONStream() : eos_signaled_(0), abort_countdown_(-1) {} | 488 TestJSONStream() : eos_signaled_(0), abort_countdown_(-1) {} |
545 explicit TestJSONStream(int abort_countdown) | 489 explicit TestJSONStream(int abort_countdown) |
546 : eos_signaled_(0), abort_countdown_(abort_countdown) {} | 490 : eos_signaled_(0), abort_countdown_(abort_countdown) {} |
547 virtual ~TestJSONStream() {} | 491 virtual ~TestJSONStream() {} |
548 virtual void EndOfStream() { ++eos_signaled_; } | 492 virtual void EndOfStream() { ++eos_signaled_; } |
549 virtual WriteResult WriteAsciiChunk(char* buffer, int chars_written) { | 493 virtual WriteResult WriteAsciiChunk(char* buffer, int chars_written) { |
(...skipping 1107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1657 const v8::HeapGraphNode* global_object = | 1601 const v8::HeapGraphNode* global_object = |
1658 GetProperty(global, v8::HeapGraphEdge::kProperty, "global_object"); | 1602 GetProperty(global, v8::HeapGraphEdge::kProperty, "global_object"); |
1659 CHECK_NE(NULL, global_object); | 1603 CHECK_NE(NULL, global_object); |
1660 const v8::HeapGraphNode* properties = | 1604 const v8::HeapGraphNode* properties = |
1661 GetProperty(global_object, v8::HeapGraphEdge::kInternal, "properties"); | 1605 GetProperty(global_object, v8::HeapGraphEdge::kInternal, "properties"); |
1662 CHECK_EQ(NULL, properties); | 1606 CHECK_EQ(NULL, properties); |
1663 const v8::HeapGraphNode* elements = | 1607 const v8::HeapGraphNode* elements = |
1664 GetProperty(global_object, v8::HeapGraphEdge::kInternal, "elements"); | 1608 GetProperty(global_object, v8::HeapGraphEdge::kInternal, "elements"); |
1665 CHECK_EQ(NULL, elements); | 1609 CHECK_EQ(NULL, elements); |
1666 } | 1610 } |
OLD | NEW |