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 |