Chromium Code Reviews| 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 { | |
| 14 | |
| 15 class NamedEntriesDetector { | |
| 16 public: | |
| 17 NamedEntriesDetector() | |
| 18 : has_A2(false), has_B2(false), has_C2(false) { | |
| 19 } | |
| 20 | |
| 21 void Apply(i::HeapEntry** entry_ptr) { | |
| 22 if (IsReachableNodeWithName(*entry_ptr, "A2")) has_A2 = true; | |
| 23 if (IsReachableNodeWithName(*entry_ptr, "B2")) has_B2 = true; | |
| 24 if (IsReachableNodeWithName(*entry_ptr, "C2")) has_C2 = true; | |
| 25 } | |
| 26 | |
| 27 static bool IsReachableNodeWithName(i::HeapEntry* entry, const char* name) { | |
| 28 return strcmp(name, entry->name()) == 0 && entry->painted_reachable(); | |
| 29 } | |
| 30 | |
| 31 bool has_A2; | |
| 32 bool has_B2; | |
| 33 bool has_C2; | |
| 34 }; | |
| 35 | |
| 36 } // namespace | |
| 37 | |
| 38 | 13 |
| 39 static const v8::HeapGraphNode* GetGlobalObject( | 14 static const v8::HeapGraphNode* GetGlobalObject( |
| 40 const v8::HeapSnapshot* snapshot) { | 15 const v8::HeapSnapshot* snapshot) { |
| 41 CHECK_EQ(2, snapshot->GetRoot()->GetChildrenCount()); | 16 CHECK_EQ(2, snapshot->GetRoot()->GetChildrenCount()); |
| 42 const v8::HeapGraphNode* global_obj = | 17 const v8::HeapGraphNode* global_obj = |
| 43 snapshot->GetRoot()->GetChild(0)->GetToNode(); | 18 snapshot->GetRoot()->GetChild(0)->GetToNode(); |
| 44 CHECK_EQ(0, strncmp("Object", const_cast<i::HeapEntry*>( | 19 CHECK_EQ(0, strncmp("Object", const_cast<i::HeapEntry*>( |
| 45 reinterpret_cast<const i::HeapEntry*>(global_obj))->name(), 6)); | 20 reinterpret_cast<const i::HeapEntry*>(global_obj))->name(), 6)); |
| 46 return global_obj; | 21 return global_obj; |
| 47 } | 22 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 79 | 54 |
| 80 CompileRun( | 55 CompileRun( |
| 81 "function A2() {}\n" | 56 "function A2() {}\n" |
| 82 "function B2(x) { return function() { return typeof x; }; }\n" | 57 "function B2(x) { return function() { return typeof x; }; }\n" |
| 83 "function C2(x) { this.x1 = x; this.x2 = x; this[1] = x; }\n" | 58 "function C2(x) { this.x1 = x; this.x2 = x; this[1] = x; }\n" |
| 84 "var a2 = new A2();\n" | 59 "var a2 = new A2();\n" |
| 85 "var b2_1 = new B2(a2), b2_2 = new B2(a2);\n" | 60 "var b2_1 = new B2(a2), b2_2 = new B2(a2);\n" |
| 86 "var c2 = new C2(a2);"); | 61 "var c2 = new C2(a2);"); |
| 87 const v8::HeapSnapshot* snapshot_env2 = | 62 const v8::HeapSnapshot* snapshot_env2 = |
| 88 v8::HeapProfiler::TakeSnapshot(v8_str("env2")); | 63 v8::HeapProfiler::TakeSnapshot(v8_str("env2")); |
| 89 i::HeapSnapshot* i_snapshot_env2 = | |
| 90 const_cast<i::HeapSnapshot*>( | |
| 91 reinterpret_cast<const i::HeapSnapshot*>(snapshot_env2)); | |
| 92 const v8::HeapGraphNode* global_env2 = GetGlobalObject(snapshot_env2); | 64 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 | 65 |
| 98 // Verify, that JS global object of env2 has '..2' properties. | 66 // Verify, that JS global object of env2 has '..2' properties. |
| 99 const v8::HeapGraphNode* a2_node = | 67 const v8::HeapGraphNode* a2_node = |
| 100 GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "a2"); | 68 GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "a2"); |
| 101 CHECK_NE(NULL, a2_node); | 69 CHECK_NE(NULL, a2_node); |
| 102 CHECK_NE( | 70 CHECK_NE( |
| 103 NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "b2_1")); | 71 NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "b2_1")); |
| 104 CHECK_NE( | 72 CHECK_NE( |
| 105 NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "b2_2")); | 73 NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "b2_2")); |
| 106 CHECK_NE(NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "c2")); | 74 CHECK_NE(NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "c2")); |
| 107 | |
| 108 NamedEntriesDetector det; | |
| 109 i_snapshot_env2->IterateEntries(&det); | |
| 110 CHECK(det.has_A2); | |
|
mnaganov (inactive)
2012/02/24 23:19:50
I'm against removing this code. It checks that A2,
alexeif
2012/02/27 11:57:25
Done.
| |
| 111 CHECK(det.has_B2); | |
| 112 CHECK(det.has_C2); | |
| 113 } | 75 } |
| 114 | 76 |
| 115 | 77 |
| 116 TEST(HeapSnapshotObjectSizes) { | 78 TEST(HeapSnapshotObjectSizes) { |
| 117 v8::HandleScope scope; | 79 v8::HandleScope scope; |
| 118 LocalContext env; | 80 LocalContext env; |
| 119 | 81 |
| 120 // -a-> X1 --a | 82 // -a-> X1 --a |
| 121 // x -b-> X2 <-| | 83 // x -b-> X2 <-| |
| 122 CompileRun( | 84 CompileRun( |
| 123 "function X(a, b) { this.a = a; this.b = b; }\n" | 85 "function X(a, b) { this.a = a; this.b = b; }\n" |
| 124 "x = new X(new X(), new X());\n" | 86 "x = new X(new X(), new X());\n" |
| 125 "(function() { x.a.a = x.b; })();"); | 87 "(function() { x.a.a = x.b; })();"); |
| 126 const v8::HeapSnapshot* snapshot = | 88 const v8::HeapSnapshot* snapshot = |
| 127 v8::HeapProfiler::TakeSnapshot(v8_str("sizes")); | 89 v8::HeapProfiler::TakeSnapshot(v8_str("sizes")); |
| 128 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); | 90 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); |
| 129 const v8::HeapGraphNode* x = | 91 const v8::HeapGraphNode* x = |
| 130 GetProperty(global, v8::HeapGraphEdge::kShortcut, "x"); | 92 GetProperty(global, v8::HeapGraphEdge::kShortcut, "x"); |
| 131 CHECK_NE(NULL, x); | 93 CHECK_NE(NULL, x); |
| 132 const v8::HeapGraphNode* x1 = | 94 const v8::HeapGraphNode* x1 = |
| 133 GetProperty(x, v8::HeapGraphEdge::kProperty, "a"); | 95 GetProperty(x, v8::HeapGraphEdge::kProperty, "a"); |
| 134 CHECK_NE(NULL, x1); | 96 CHECK_NE(NULL, x1); |
| 135 const v8::HeapGraphNode* x2 = | 97 const v8::HeapGraphNode* x2 = |
| 136 GetProperty(x, v8::HeapGraphEdge::kProperty, "b"); | 98 GetProperty(x, v8::HeapGraphEdge::kProperty, "b"); |
| 137 CHECK_NE(NULL, x2); | 99 CHECK_NE(NULL, x2); |
| 138 | 100 |
| 139 // Test approximate sizes. | 101 // Test sizes. |
| 140 CHECK_EQ(x->GetSelfSize() * 3, x->GetRetainedSize(false)); | 102 CHECK_EQ(x->GetSelfSize() * 3, x->GetRetainedSize()); |
| 141 CHECK_EQ(x1->GetSelfSize(), x1->GetRetainedSize(false)); | 103 CHECK_EQ(x1->GetSelfSize(), x1->GetRetainedSize()); |
| 142 CHECK_EQ(x2->GetSelfSize(), x2->GetRetainedSize(false)); | 104 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 } | 105 } |
| 148 | 106 |
| 149 | 107 |
| 150 TEST(BoundFunctionInSnapshot) { | 108 TEST(BoundFunctionInSnapshot) { |
| 151 v8::HandleScope scope; | 109 v8::HandleScope scope; |
| 152 LocalContext env; | 110 LocalContext env; |
| 153 CompileRun( | 111 CompileRun( |
| 154 "function myFunction(a, b) { this.a = a; this.b = b; }\n" | 112 "function myFunction(a, b) { this.a = a; this.b = b; }\n" |
| 155 "function AAAAA() {}\n" | 113 "function AAAAA() {}\n" |
| 156 "boundFunction = myFunction.bind(new AAAAA(), 20, new Number(12)); \n"); | 114 "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")); | 1219 v8::HeapProfiler::TakeSnapshot(v8_str("fun")); |
| 1262 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); | 1220 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); |
| 1263 CHECK_NE(NULL, global); | 1221 CHECK_NE(NULL, global); |
| 1264 const v8::HeapGraphNode* fun = | 1222 const v8::HeapGraphNode* fun = |
| 1265 GetProperty(global, v8::HeapGraphEdge::kShortcut, "fun"); | 1223 GetProperty(global, v8::HeapGraphEdge::kShortcut, "fun"); |
| 1266 CHECK(HasWeakEdge(fun)); | 1224 CHECK(HasWeakEdge(fun)); |
| 1267 const v8::HeapGraphNode* shared = | 1225 const v8::HeapGraphNode* shared = |
| 1268 GetProperty(fun, v8::HeapGraphEdge::kInternal, "shared"); | 1226 GetProperty(fun, v8::HeapGraphEdge::kInternal, "shared"); |
| 1269 CHECK(HasWeakEdge(shared)); | 1227 CHECK(HasWeakEdge(shared)); |
| 1270 } | 1228 } |
| OLD | NEW |