| OLD | NEW |
| 1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
| 2 // | 2 // |
| 3 // Tests for heap profiler | 3 // Tests for heap profiler |
| 4 | 4 |
| 5 #ifdef ENABLE_LOGGING_AND_PROFILING | 5 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 6 | 6 |
| 7 #include "v8.h" | 7 #include "v8.h" |
| 8 #include "heap-profiler.h" | 8 #include "heap-profiler.h" |
| 9 #include "snapshot.h" | 9 #include "snapshot.h" |
| 10 #include "string-stream.h" | 10 #include "string-stream.h" |
| (...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 381 CHECK_EQ("(global property);2", printer.GetRetainers("B")); | 381 CHECK_EQ("(global property);2", printer.GetRetainers("B")); |
| 382 CHECK_EQ("(global property);1", printer.GetRetainers("C")); | 382 CHECK_EQ("(global property);1", printer.GetRetainers("C")); |
| 383 } | 383 } |
| 384 | 384 |
| 385 | 385 |
| 386 namespace { | 386 namespace { |
| 387 | 387 |
| 388 class NamedEntriesDetector { | 388 class NamedEntriesDetector { |
| 389 public: | 389 public: |
| 390 NamedEntriesDetector() | 390 NamedEntriesDetector() |
| 391 : has_A1(false), has_B1(false), has_C1(false), | 391 : has_A2(false), has_B2(false), has_C2(false) { |
| 392 has_A2(false), has_B2(false), has_C2(false) { | |
| 393 } | 392 } |
| 394 | 393 |
| 395 void Apply(i::HeapEntry** entry_ptr) { | 394 void Apply(i::HeapEntry** entry_ptr) { |
| 396 if (IsReachableNodeWithName(*entry_ptr, "A1")) has_A1 = true; | |
| 397 if (IsReachableNodeWithName(*entry_ptr, "B1")) has_B1 = true; | |
| 398 if (IsReachableNodeWithName(*entry_ptr, "C1")) has_C1 = true; | |
| 399 if (IsReachableNodeWithName(*entry_ptr, "A2")) has_A2 = true; | 395 if (IsReachableNodeWithName(*entry_ptr, "A2")) has_A2 = true; |
| 400 if (IsReachableNodeWithName(*entry_ptr, "B2")) has_B2 = true; | 396 if (IsReachableNodeWithName(*entry_ptr, "B2")) has_B2 = true; |
| 401 if (IsReachableNodeWithName(*entry_ptr, "C2")) has_C2 = true; | 397 if (IsReachableNodeWithName(*entry_ptr, "C2")) has_C2 = true; |
| 402 } | 398 } |
| 403 | 399 |
| 404 static bool IsReachableNodeWithName(i::HeapEntry* entry, const char* name) { | 400 static bool IsReachableNodeWithName(i::HeapEntry* entry, const char* name) { |
| 405 return strcmp(name, entry->name()) == 0 && entry->painted_reachable(); | 401 return strcmp(name, entry->name()) == 0 && entry->painted_reachable(); |
| 406 } | 402 } |
| 407 | 403 |
| 408 bool has_A1; | |
| 409 bool has_B1; | |
| 410 bool has_C1; | |
| 411 bool has_A2; | 404 bool has_A2; |
| 412 bool has_B2; | 405 bool has_B2; |
| 413 bool has_C2; | 406 bool has_C2; |
| 414 }; | 407 }; |
| 415 | 408 |
| 416 } // namespace | 409 } // namespace |
| 417 | 410 |
| 418 | 411 |
| 419 static const v8::HeapGraphNode* GetGlobalObject( | 412 static const v8::HeapGraphNode* GetGlobalObject( |
| 420 const v8::HeapSnapshot* snapshot) { | 413 const v8::HeapSnapshot* snapshot) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 457 v8::String::AsciiValue node_name(node->GetName()); | 450 v8::String::AsciiValue node_name(node->GetName()); |
| 458 if (strcmp(contents, *node_name) == 0) return true; | 451 if (strcmp(contents, *node_name) == 0) return true; |
| 459 } | 452 } |
| 460 } | 453 } |
| 461 return false; | 454 return false; |
| 462 } | 455 } |
| 463 | 456 |
| 464 | 457 |
| 465 TEST(HeapSnapshot) { | 458 TEST(HeapSnapshot) { |
| 466 v8::HandleScope scope; | 459 v8::HandleScope scope; |
| 467 v8::Handle<v8::String> token1 = v8::String::New("token1"); | |
| 468 LocalContext env1; | |
| 469 env1->SetSecurityToken(token1); | |
| 470 | |
| 471 CompileRun( | |
| 472 "function A1() {}\n" | |
| 473 "function B1(x) { this.x = x; }\n" | |
| 474 "function C1(x) { this.x1 = x; this.x2 = x; }\n" | |
| 475 "var a1 = new A1();\n" | |
| 476 "var b1_1 = new B1(a1), b1_2 = new B1(a1);\n" | |
| 477 "var c1 = new C1(a1);"); | |
| 478 | |
| 479 v8::Handle<v8::String> token2 = v8::String::New("token2"); | |
| 480 LocalContext env2; | 460 LocalContext env2; |
| 481 env2->SetSecurityToken(token2); | |
| 482 | 461 |
| 483 CompileRun( | 462 CompileRun( |
| 484 "function A2() {}\n" | 463 "function A2() {}\n" |
| 485 "function B2(x) { return function() { return typeof x; }; }\n" | 464 "function B2(x) { return function() { return typeof x; }; }\n" |
| 486 "function C2(x) { this.x1 = x; this.x2 = x; this[1] = x; }\n" | 465 "function C2(x) { this.x1 = x; this.x2 = x; this[1] = x; }\n" |
| 487 "var a2 = new A2();\n" | 466 "var a2 = new A2();\n" |
| 488 "var b2_1 = new B2(a2), b2_2 = new B2(a2);\n" | 467 "var b2_1 = new B2(a2), b2_2 = new B2(a2);\n" |
| 489 "var c2 = new C2(a2);"); | 468 "var c2 = new C2(a2);"); |
| 490 const v8::HeapSnapshot* snapshot_env2 = | 469 const v8::HeapSnapshot* snapshot_env2 = |
| 491 v8::HeapProfiler::TakeSnapshot(v8::String::New("env2")); | 470 v8::HeapProfiler::TakeSnapshot(v8::String::New("env2")); |
| 492 i::HeapSnapshot* i_snapshot_env2 = | 471 i::HeapSnapshot* i_snapshot_env2 = |
| 493 const_cast<i::HeapSnapshot*>( | 472 const_cast<i::HeapSnapshot*>( |
| 494 reinterpret_cast<const i::HeapSnapshot*>(snapshot_env2)); | 473 reinterpret_cast<const i::HeapSnapshot*>(snapshot_env2)); |
| 495 const v8::HeapGraphNode* global_env2 = GetGlobalObject(snapshot_env2); | 474 const v8::HeapGraphNode* global_env2 = GetGlobalObject(snapshot_env2); |
| 496 // Paint all nodes reachable from global object. | 475 // Paint all nodes reachable from global object. |
| 497 i_snapshot_env2->ClearPaint(); | 476 i_snapshot_env2->ClearPaint(); |
| 498 const_cast<i::HeapEntry*>( | 477 const_cast<i::HeapEntry*>( |
| 499 reinterpret_cast<const i::HeapEntry*>(global_env2))->PaintAllReachable(); | 478 reinterpret_cast<const i::HeapEntry*>(global_env2))->PaintAllReachable(); |
| 500 | 479 |
| 501 // Verify, that JS global object of env2 doesn't have '..1' | 480 // Verify, that JS global object of env2 has '..2' properties. |
| 502 // properties, but has '..2' properties. | |
| 503 CHECK_EQ(NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "a1")); | |
| 504 CHECK_EQ( | |
| 505 NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "b1_1")); | |
| 506 CHECK_EQ( | |
| 507 NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "b1_2")); | |
| 508 CHECK_EQ(NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "c1")); | |
| 509 const v8::HeapGraphNode* a2_node = | 481 const v8::HeapGraphNode* a2_node = |
| 510 GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "a2"); | 482 GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "a2"); |
| 511 CHECK_NE(NULL, a2_node); | 483 CHECK_NE(NULL, a2_node); |
| 512 CHECK_NE( | 484 CHECK_NE( |
| 513 NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "b2_1")); | 485 NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "b2_1")); |
| 514 CHECK_NE( | 486 CHECK_NE( |
| 515 NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "b2_2")); | 487 NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "b2_2")); |
| 516 CHECK_NE(NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "c2")); | 488 CHECK_NE(NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "c2")); |
| 517 | 489 |
| 518 // Verify that anything related to '[ABC]1' is not reachable. | 490 // Verify that anything related to '[ABC]1' is not reachable. |
| 519 NamedEntriesDetector det; | 491 NamedEntriesDetector det; |
| 520 i_snapshot_env2->IterateEntries(&det); | 492 i_snapshot_env2->IterateEntries(&det); |
| 521 CHECK(!det.has_A1); | |
| 522 CHECK(!det.has_B1); | |
| 523 CHECK(!det.has_C1); | |
| 524 CHECK(det.has_A2); | 493 CHECK(det.has_A2); |
| 525 CHECK(det.has_B2); | 494 CHECK(det.has_B2); |
| 526 CHECK(det.has_C2); | 495 CHECK(det.has_C2); |
| 527 | 496 |
| 528 // Verify 'a2' object retainers. They are: | 497 // Verify 'a2' object retainers. They are: |
| 529 // - (global object).a2 | 498 // - (global object).a2 |
| 530 // - c2.x1, c2.x2, c2[1] | 499 // - c2.x1, c2.x2, c2[1] |
| 531 // - b2_1 and b2_2 closures: via 'x' variable | 500 // - b2_1 and b2_2 closures: via 'x' variable |
| 532 CHECK_EQ(6, a2_node->GetRetainingPathsCount()); | 501 CHECK_EQ(6, a2_node->GetRetainingPathsCount()); |
| 533 bool has_global_obj_a2_ref = false; | 502 bool has_global_obj_a2_ref = false; |
| (...skipping 641 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1175 LocalContext env; | 1144 LocalContext env; |
| 1176 const v8::HeapSnapshot* snapshot = | 1145 const v8::HeapSnapshot* snapshot = |
| 1177 v8::HeapProfiler::TakeSnapshot(v8::String::New("abort")); | 1146 v8::HeapProfiler::TakeSnapshot(v8::String::New("abort")); |
| 1178 TestJSONStream stream(5); | 1147 TestJSONStream stream(5); |
| 1179 snapshot->Serialize(&stream, v8::HeapSnapshot::kJSON); | 1148 snapshot->Serialize(&stream, v8::HeapSnapshot::kJSON); |
| 1180 CHECK_GT(stream.size(), 0); | 1149 CHECK_GT(stream.size(), 0); |
| 1181 CHECK_EQ(0, stream.eos_signaled()); | 1150 CHECK_EQ(0, stream.eos_signaled()); |
| 1182 } | 1151 } |
| 1183 | 1152 |
| 1184 #endif // ENABLE_LOGGING_AND_PROFILING | 1153 #endif // ENABLE_LOGGING_AND_PROFILING |
| OLD | NEW |