OLD | NEW |
(Empty) | |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // |
| 3 // Tests of profiles generator and utilities. |
| 4 |
| 5 #include "v8.h" |
| 6 #include "profile-generator-inl.h" |
| 7 #include "cctest.h" |
| 8 |
| 9 namespace i = v8::internal; |
| 10 |
| 11 using i::CodeEntry; |
| 12 using i::CodeMap; |
| 13 using i::ProfileNode; |
| 14 using i::ProfileTree; |
| 15 using i::StaticNameCodeEntry; |
| 16 using i::Vector; |
| 17 |
| 18 |
| 19 TEST(ProfileNodeFindOrAddChild) { |
| 20 ProfileNode node(NULL); |
| 21 StaticNameCodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa"); |
| 22 ProfileNode* childNode1 = node.FindOrAddChild(&entry1); |
| 23 CHECK_NE(NULL, childNode1); |
| 24 CHECK_EQ(childNode1, node.FindOrAddChild(&entry1)); |
| 25 StaticNameCodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb"); |
| 26 ProfileNode* childNode2 = node.FindOrAddChild(&entry2); |
| 27 CHECK_NE(NULL, childNode2); |
| 28 CHECK_NE(childNode1, childNode2); |
| 29 CHECK_EQ(childNode1, node.FindOrAddChild(&entry1)); |
| 30 CHECK_EQ(childNode2, node.FindOrAddChild(&entry2)); |
| 31 StaticNameCodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc"); |
| 32 ProfileNode* childNode3 = node.FindOrAddChild(&entry3); |
| 33 CHECK_NE(NULL, childNode3); |
| 34 CHECK_NE(childNode1, childNode3); |
| 35 CHECK_NE(childNode2, childNode3); |
| 36 CHECK_EQ(childNode1, node.FindOrAddChild(&entry1)); |
| 37 CHECK_EQ(childNode2, node.FindOrAddChild(&entry2)); |
| 38 CHECK_EQ(childNode3, node.FindOrAddChild(&entry3)); |
| 39 } |
| 40 |
| 41 |
| 42 namespace { |
| 43 |
| 44 class ProfileTreeTestHelper { |
| 45 public: |
| 46 explicit ProfileTreeTestHelper(ProfileTree* tree) |
| 47 : tree_(tree) { } |
| 48 |
| 49 ProfileNode* Walk(CodeEntry* entry1, |
| 50 CodeEntry* entry2 = NULL, |
| 51 CodeEntry* entry3 = NULL) { |
| 52 ProfileNode* node = tree_->root(); |
| 53 node = node->FindChild(entry1); |
| 54 if (node == NULL) return NULL; |
| 55 if (entry2 != NULL) { |
| 56 node = node->FindChild(entry2); |
| 57 if (node == NULL) return NULL; |
| 58 } |
| 59 if (entry3 != NULL) { |
| 60 node = node->FindChild(entry3); |
| 61 } |
| 62 return node; |
| 63 } |
| 64 |
| 65 private: |
| 66 ProfileTree* tree_; |
| 67 }; |
| 68 |
| 69 } // namespace |
| 70 |
| 71 TEST(ProfileTreeAddPathFromStart) { |
| 72 StaticNameCodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa"); |
| 73 StaticNameCodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb"); |
| 74 StaticNameCodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc"); |
| 75 ProfileTree tree; |
| 76 ProfileTreeTestHelper helper(&tree); |
| 77 CHECK_EQ(NULL, helper.Walk(&entry1)); |
| 78 CHECK_EQ(NULL, helper.Walk(&entry2)); |
| 79 CHECK_EQ(NULL, helper.Walk(&entry3)); |
| 80 |
| 81 CodeEntry* path[] = {NULL, &entry1, NULL, &entry2, NULL, NULL, &entry3, NULL}; |
| 82 Vector<CodeEntry*> path_vec(path, sizeof(path) / sizeof(path[0])); |
| 83 tree.AddPathFromStart(path_vec); |
| 84 CHECK_EQ(NULL, helper.Walk(&entry2)); |
| 85 CHECK_EQ(NULL, helper.Walk(&entry3)); |
| 86 ProfileNode* node1 = helper.Walk(&entry1); |
| 87 CHECK_NE(NULL, node1); |
| 88 CHECK_EQ(0, node1->total_ticks()); |
| 89 CHECK_EQ(0, node1->self_ticks()); |
| 90 CHECK_EQ(NULL, helper.Walk(&entry1, &entry1)); |
| 91 CHECK_EQ(NULL, helper.Walk(&entry1, &entry3)); |
| 92 ProfileNode* node2 = helper.Walk(&entry1, &entry2); |
| 93 CHECK_NE(NULL, node2); |
| 94 CHECK_NE(node1, node2); |
| 95 CHECK_EQ(0, node2->total_ticks()); |
| 96 CHECK_EQ(0, node2->self_ticks()); |
| 97 CHECK_EQ(NULL, helper.Walk(&entry1, &entry2, &entry1)); |
| 98 CHECK_EQ(NULL, helper.Walk(&entry1, &entry2, &entry2)); |
| 99 ProfileNode* node3 = helper.Walk(&entry1, &entry2, &entry3); |
| 100 CHECK_NE(NULL, node3); |
| 101 CHECK_NE(node1, node3); |
| 102 CHECK_NE(node2, node3); |
| 103 CHECK_EQ(0, node3->total_ticks()); |
| 104 CHECK_EQ(1, node3->self_ticks()); |
| 105 |
| 106 tree.AddPathFromStart(path_vec); |
| 107 CHECK_EQ(node1, helper.Walk(&entry1)); |
| 108 CHECK_EQ(node2, helper.Walk(&entry1, &entry2)); |
| 109 CHECK_EQ(node3, helper.Walk(&entry1, &entry2, &entry3)); |
| 110 CHECK_EQ(0, node1->total_ticks()); |
| 111 CHECK_EQ(0, node1->self_ticks()); |
| 112 CHECK_EQ(0, node2->total_ticks()); |
| 113 CHECK_EQ(0, node2->self_ticks()); |
| 114 CHECK_EQ(0, node3->total_ticks()); |
| 115 CHECK_EQ(2, node3->self_ticks()); |
| 116 |
| 117 CodeEntry* path2[] = {&entry1, &entry2, &entry2}; |
| 118 Vector<CodeEntry*> path2_vec(path2, sizeof(path2) / sizeof(path2[0])); |
| 119 tree.AddPathFromStart(path2_vec); |
| 120 CHECK_EQ(NULL, helper.Walk(&entry2)); |
| 121 CHECK_EQ(NULL, helper.Walk(&entry3)); |
| 122 CHECK_EQ(node1, helper.Walk(&entry1)); |
| 123 CHECK_EQ(NULL, helper.Walk(&entry1, &entry1)); |
| 124 CHECK_EQ(NULL, helper.Walk(&entry1, &entry3)); |
| 125 CHECK_EQ(node2, helper.Walk(&entry1, &entry2)); |
| 126 CHECK_EQ(NULL, helper.Walk(&entry1, &entry2, &entry1)); |
| 127 CHECK_EQ(node3, helper.Walk(&entry1, &entry2, &entry3)); |
| 128 CHECK_EQ(0, node3->total_ticks()); |
| 129 CHECK_EQ(2, node3->self_ticks()); |
| 130 ProfileNode* node4 = helper.Walk(&entry1, &entry2, &entry2); |
| 131 CHECK_NE(NULL, node4); |
| 132 CHECK_NE(node3, node4); |
| 133 CHECK_EQ(0, node4->total_ticks()); |
| 134 CHECK_EQ(1, node4->self_ticks()); |
| 135 } |
| 136 |
| 137 |
| 138 TEST(ProfileTreeAddPathFromEnd) { |
| 139 StaticNameCodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa"); |
| 140 StaticNameCodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb"); |
| 141 StaticNameCodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc"); |
| 142 ProfileTree tree; |
| 143 ProfileTreeTestHelper helper(&tree); |
| 144 CHECK_EQ(NULL, helper.Walk(&entry1)); |
| 145 CHECK_EQ(NULL, helper.Walk(&entry2)); |
| 146 CHECK_EQ(NULL, helper.Walk(&entry3)); |
| 147 |
| 148 CodeEntry* path[] = {NULL, &entry3, NULL, &entry2, NULL, NULL, &entry1, NULL}; |
| 149 Vector<CodeEntry*> path_vec(path, sizeof(path) / sizeof(path[0])); |
| 150 tree.AddPathFromEnd(path_vec); |
| 151 CHECK_EQ(NULL, helper.Walk(&entry2)); |
| 152 CHECK_EQ(NULL, helper.Walk(&entry3)); |
| 153 ProfileNode* node1 = helper.Walk(&entry1); |
| 154 CHECK_NE(NULL, node1); |
| 155 CHECK_EQ(0, node1->total_ticks()); |
| 156 CHECK_EQ(0, node1->self_ticks()); |
| 157 CHECK_EQ(NULL, helper.Walk(&entry1, &entry1)); |
| 158 CHECK_EQ(NULL, helper.Walk(&entry1, &entry3)); |
| 159 ProfileNode* node2 = helper.Walk(&entry1, &entry2); |
| 160 CHECK_NE(NULL, node2); |
| 161 CHECK_NE(node1, node2); |
| 162 CHECK_EQ(0, node2->total_ticks()); |
| 163 CHECK_EQ(0, node2->self_ticks()); |
| 164 CHECK_EQ(NULL, helper.Walk(&entry1, &entry2, &entry1)); |
| 165 CHECK_EQ(NULL, helper.Walk(&entry1, &entry2, &entry2)); |
| 166 ProfileNode* node3 = helper.Walk(&entry1, &entry2, &entry3); |
| 167 CHECK_NE(NULL, node3); |
| 168 CHECK_NE(node1, node3); |
| 169 CHECK_NE(node2, node3); |
| 170 CHECK_EQ(0, node3->total_ticks()); |
| 171 CHECK_EQ(1, node3->self_ticks()); |
| 172 |
| 173 tree.AddPathFromEnd(path_vec); |
| 174 CHECK_EQ(node1, helper.Walk(&entry1)); |
| 175 CHECK_EQ(node2, helper.Walk(&entry1, &entry2)); |
| 176 CHECK_EQ(node3, helper.Walk(&entry1, &entry2, &entry3)); |
| 177 CHECK_EQ(0, node1->total_ticks()); |
| 178 CHECK_EQ(0, node1->self_ticks()); |
| 179 CHECK_EQ(0, node2->total_ticks()); |
| 180 CHECK_EQ(0, node2->self_ticks()); |
| 181 CHECK_EQ(0, node3->total_ticks()); |
| 182 CHECK_EQ(2, node3->self_ticks()); |
| 183 |
| 184 CodeEntry* path2[] = {&entry2, &entry2, &entry1}; |
| 185 Vector<CodeEntry*> path2_vec(path2, sizeof(path2) / sizeof(path2[0])); |
| 186 tree.AddPathFromEnd(path2_vec); |
| 187 CHECK_EQ(NULL, helper.Walk(&entry2)); |
| 188 CHECK_EQ(NULL, helper.Walk(&entry3)); |
| 189 CHECK_EQ(node1, helper.Walk(&entry1)); |
| 190 CHECK_EQ(NULL, helper.Walk(&entry1, &entry1)); |
| 191 CHECK_EQ(NULL, helper.Walk(&entry1, &entry3)); |
| 192 CHECK_EQ(node2, helper.Walk(&entry1, &entry2)); |
| 193 CHECK_EQ(NULL, helper.Walk(&entry1, &entry2, &entry1)); |
| 194 CHECK_EQ(node3, helper.Walk(&entry1, &entry2, &entry3)); |
| 195 CHECK_EQ(0, node3->total_ticks()); |
| 196 CHECK_EQ(2, node3->self_ticks()); |
| 197 ProfileNode* node4 = helper.Walk(&entry1, &entry2, &entry2); |
| 198 CHECK_NE(NULL, node4); |
| 199 CHECK_NE(node3, node4); |
| 200 CHECK_EQ(0, node4->total_ticks()); |
| 201 CHECK_EQ(1, node4->self_ticks()); |
| 202 } |
| 203 |
| 204 |
| 205 TEST(ProfileTreeCalculateTotalTicks) { |
| 206 ProfileTree empty_tree; |
| 207 CHECK_EQ(0, empty_tree.root()->total_ticks()); |
| 208 CHECK_EQ(0, empty_tree.root()->self_ticks()); |
| 209 empty_tree.CalculateTotalTicks(); |
| 210 CHECK_EQ(0, empty_tree.root()->total_ticks()); |
| 211 CHECK_EQ(0, empty_tree.root()->self_ticks()); |
| 212 empty_tree.root()->IncrementSelfTicks(); |
| 213 CHECK_EQ(0, empty_tree.root()->total_ticks()); |
| 214 CHECK_EQ(1, empty_tree.root()->self_ticks()); |
| 215 empty_tree.CalculateTotalTicks(); |
| 216 CHECK_EQ(1, empty_tree.root()->total_ticks()); |
| 217 CHECK_EQ(1, empty_tree.root()->self_ticks()); |
| 218 |
| 219 StaticNameCodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa"); |
| 220 StaticNameCodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb"); |
| 221 CodeEntry* e1_path[] = {&entry1}; |
| 222 Vector<CodeEntry*> e1_path_vec( |
| 223 e1_path, sizeof(e1_path) / sizeof(e1_path[0])); |
| 224 CodeEntry* e1_e2_path[] = {&entry1, &entry2}; |
| 225 Vector<CodeEntry*> e1_e2_path_vec( |
| 226 e1_e2_path, sizeof(e1_e2_path) / sizeof(e1_e2_path[0])); |
| 227 |
| 228 ProfileTree flat_tree; |
| 229 ProfileTreeTestHelper flat_helper(&flat_tree); |
| 230 flat_tree.AddPathFromStart(e1_path_vec); |
| 231 flat_tree.AddPathFromStart(e1_path_vec); |
| 232 flat_tree.AddPathFromStart(e1_e2_path_vec); |
| 233 flat_tree.AddPathFromStart(e1_e2_path_vec); |
| 234 flat_tree.AddPathFromStart(e1_e2_path_vec); |
| 235 // Results in {root,0,0} -> {entry1,0,2} -> {entry2,0,3} |
| 236 CHECK_EQ(0, flat_tree.root()->total_ticks()); |
| 237 CHECK_EQ(0, flat_tree.root()->self_ticks()); |
| 238 ProfileNode* node1 = flat_helper.Walk(&entry1); |
| 239 CHECK_NE(NULL, node1); |
| 240 CHECK_EQ(0, node1->total_ticks()); |
| 241 CHECK_EQ(2, node1->self_ticks()); |
| 242 ProfileNode* node2 = flat_helper.Walk(&entry1, &entry2); |
| 243 CHECK_NE(NULL, node2); |
| 244 CHECK_EQ(0, node2->total_ticks()); |
| 245 CHECK_EQ(3, node2->self_ticks()); |
| 246 flat_tree.CalculateTotalTicks(); |
| 247 // Must calculate {root,5,0} -> {entry1,5,2} -> {entry2,3,3} |
| 248 CHECK_EQ(5, flat_tree.root()->total_ticks()); |
| 249 CHECK_EQ(0, flat_tree.root()->self_ticks()); |
| 250 CHECK_EQ(5, node1->total_ticks()); |
| 251 CHECK_EQ(2, node1->self_ticks()); |
| 252 CHECK_EQ(3, node2->total_ticks()); |
| 253 CHECK_EQ(3, node2->self_ticks()); |
| 254 |
| 255 CodeEntry* e2_path[] = {&entry2}; |
| 256 Vector<CodeEntry*> e2_path_vec( |
| 257 e2_path, sizeof(e2_path) / sizeof(e2_path[0])); |
| 258 StaticNameCodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc"); |
| 259 CodeEntry* e3_path[] = {&entry3}; |
| 260 Vector<CodeEntry*> e3_path_vec( |
| 261 e3_path, sizeof(e3_path) / sizeof(e3_path[0])); |
| 262 |
| 263 ProfileTree wide_tree; |
| 264 ProfileTreeTestHelper wide_helper(&wide_tree); |
| 265 wide_tree.AddPathFromStart(e1_path_vec); |
| 266 wide_tree.AddPathFromStart(e1_path_vec); |
| 267 wide_tree.AddPathFromStart(e1_e2_path_vec); |
| 268 wide_tree.AddPathFromStart(e2_path_vec); |
| 269 wide_tree.AddPathFromStart(e2_path_vec); |
| 270 wide_tree.AddPathFromStart(e2_path_vec); |
| 271 wide_tree.AddPathFromStart(e3_path_vec); |
| 272 wide_tree.AddPathFromStart(e3_path_vec); |
| 273 wide_tree.AddPathFromStart(e3_path_vec); |
| 274 wide_tree.AddPathFromStart(e3_path_vec); |
| 275 // Results in -> {entry1,0,2} -> {entry2,0,1} |
| 276 // {root,0,0} -> {entry2,0,3} |
| 277 // -> {entry3,0,4} |
| 278 CHECK_EQ(0, wide_tree.root()->total_ticks()); |
| 279 CHECK_EQ(0, wide_tree.root()->self_ticks()); |
| 280 node1 = wide_helper.Walk(&entry1); |
| 281 CHECK_NE(NULL, node1); |
| 282 CHECK_EQ(0, node1->total_ticks()); |
| 283 CHECK_EQ(2, node1->self_ticks()); |
| 284 ProfileNode* node1_2 = wide_helper.Walk(&entry1, &entry2); |
| 285 CHECK_NE(NULL, node1_2); |
| 286 CHECK_EQ(0, node1_2->total_ticks()); |
| 287 CHECK_EQ(1, node1_2->self_ticks()); |
| 288 node2 = wide_helper.Walk(&entry2); |
| 289 CHECK_NE(NULL, node2); |
| 290 CHECK_EQ(0, node2->total_ticks()); |
| 291 CHECK_EQ(3, node2->self_ticks()); |
| 292 ProfileNode* node3 = wide_helper.Walk(&entry3); |
| 293 CHECK_NE(NULL, node3); |
| 294 CHECK_EQ(0, node3->total_ticks()); |
| 295 CHECK_EQ(4, node3->self_ticks()); |
| 296 wide_tree.CalculateTotalTicks(); |
| 297 // Calculates -> {entry1,3,2} -> {entry2,1,1} |
| 298 // {root,10,0} -> {entry2,3,3} |
| 299 // -> {entry3,4,4} |
| 300 CHECK_EQ(10, wide_tree.root()->total_ticks()); |
| 301 CHECK_EQ(0, wide_tree.root()->self_ticks()); |
| 302 CHECK_EQ(3, node1->total_ticks()); |
| 303 CHECK_EQ(2, node1->self_ticks()); |
| 304 CHECK_EQ(1, node1_2->total_ticks()); |
| 305 CHECK_EQ(1, node1_2->self_ticks()); |
| 306 CHECK_EQ(3, node2->total_ticks()); |
| 307 CHECK_EQ(3, node2->self_ticks()); |
| 308 CHECK_EQ(4, node3->total_ticks()); |
| 309 CHECK_EQ(4, node3->self_ticks()); |
| 310 } |
| 311 |
| 312 |
| 313 static inline i::Address ToAddress(int n) { |
| 314 return reinterpret_cast<i::Address>(n); |
| 315 } |
| 316 |
| 317 TEST(CodeMapAddCode) { |
| 318 CodeMap code_map; |
| 319 StaticNameCodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa"); |
| 320 StaticNameCodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb"); |
| 321 StaticNameCodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc"); |
| 322 StaticNameCodeEntry entry4(i::Logger::FUNCTION_TAG, "ddd"); |
| 323 code_map.AddCode(ToAddress(0x1500), &entry1, 0x200); |
| 324 code_map.AddCode(ToAddress(0x1700), &entry2, 0x100); |
| 325 code_map.AddCode(ToAddress(0x1900), &entry3, 0x50); |
| 326 code_map.AddCode(ToAddress(0x1950), &entry4, 0x10); |
| 327 CHECK_EQ(NULL, code_map.FindEntry(0)); |
| 328 CHECK_EQ(NULL, code_map.FindEntry(ToAddress(0x1500 - 1))); |
| 329 CHECK_EQ(&entry1, code_map.FindEntry(ToAddress(0x1500))); |
| 330 CHECK_EQ(&entry1, code_map.FindEntry(ToAddress(0x1500 + 0x100))); |
| 331 CHECK_EQ(&entry1, code_map.FindEntry(ToAddress(0x1500 + 0x200 - 1))); |
| 332 CHECK_EQ(&entry2, code_map.FindEntry(ToAddress(0x1700))); |
| 333 CHECK_EQ(&entry2, code_map.FindEntry(ToAddress(0x1700 + 0x50))); |
| 334 CHECK_EQ(&entry2, code_map.FindEntry(ToAddress(0x1700 + 0x100 - 1))); |
| 335 CHECK_EQ(NULL, code_map.FindEntry(ToAddress(0x1700 + 0x100))); |
| 336 CHECK_EQ(NULL, code_map.FindEntry(ToAddress(0x1900 - 1))); |
| 337 CHECK_EQ(&entry3, code_map.FindEntry(ToAddress(0x1900))); |
| 338 CHECK_EQ(&entry3, code_map.FindEntry(ToAddress(0x1900 + 0x28))); |
| 339 CHECK_EQ(&entry4, code_map.FindEntry(ToAddress(0x1950))); |
| 340 CHECK_EQ(&entry4, code_map.FindEntry(ToAddress(0x1950 + 0x7))); |
| 341 CHECK_EQ(&entry4, code_map.FindEntry(ToAddress(0x1950 + 0x10 - 1))); |
| 342 CHECK_EQ(NULL, code_map.FindEntry(ToAddress(0x1950 + 0x10))); |
| 343 CHECK_EQ(NULL, code_map.FindEntry(ToAddress(0xFFFFFFFF))); |
| 344 } |
| 345 |
| 346 |
| 347 TEST(CodeMapMoveAndDeleteCode) { |
| 348 CodeMap code_map; |
| 349 StaticNameCodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa"); |
| 350 StaticNameCodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb"); |
| 351 code_map.AddCode(ToAddress(0x1500), &entry1, 0x200); |
| 352 code_map.AddCode(ToAddress(0x1700), &entry2, 0x100); |
| 353 CHECK_EQ(&entry1, code_map.FindEntry(ToAddress(0x1500))); |
| 354 CHECK_EQ(&entry2, code_map.FindEntry(ToAddress(0x1700))); |
| 355 code_map.MoveCode(ToAddress(0x1500), ToAddress(0x1800)); |
| 356 CHECK_EQ(NULL, code_map.FindEntry(ToAddress(0x1500))); |
| 357 CHECK_EQ(&entry2, code_map.FindEntry(ToAddress(0x1700))); |
| 358 CHECK_EQ(&entry1, code_map.FindEntry(ToAddress(0x1800))); |
| 359 code_map.DeleteCode(ToAddress(0x1700)); |
| 360 CHECK_EQ(NULL, code_map.FindEntry(ToAddress(0x1700))); |
| 361 CHECK_EQ(&entry1, code_map.FindEntry(ToAddress(0x1800))); |
| 362 } |
OLD | NEW |