Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(328)

Side by Side Diff: test/cctest/test-heap-profiler.cc

Issue 5274002: Version 2.5.8... (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « test/cctest/test-debug.cc ('k') | test/cctest/test-parsing.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 393 matching lines...) Expand 10 before | Expand all | Expand 10 after
404 bool has_A2; 404 bool has_A2;
405 bool has_B2; 405 bool has_B2;
406 bool has_C2; 406 bool has_C2;
407 }; 407 };
408 408
409 } // namespace 409 } // namespace
410 410
411 411
412 static const v8::HeapGraphNode* GetGlobalObject( 412 static const v8::HeapGraphNode* GetGlobalObject(
413 const v8::HeapSnapshot* snapshot) { 413 const v8::HeapSnapshot* snapshot) {
414 CHECK_EQ(1, snapshot->GetRoot()->GetChildrenCount()); 414 CHECK_EQ(2, snapshot->GetRoot()->GetChildrenCount());
415 return snapshot->GetRoot()->GetChild(0)->GetToNode(); 415 const v8::HeapGraphNode* global_obj =
416 snapshot->GetRoot()->GetChild(0)->GetToNode();
417 CHECK_EQ("Object", const_cast<i::HeapEntry*>(
418 reinterpret_cast<const i::HeapEntry*>(global_obj))->name());
419 return global_obj;
416 } 420 }
417 421
418 422
419 static const v8::HeapGraphNode* GetProperty(const v8::HeapGraphNode* node, 423 static const v8::HeapGraphNode* GetProperty(const v8::HeapGraphNode* node,
420 v8::HeapGraphEdge::Type type, 424 v8::HeapGraphEdge::Type type,
421 const char* name) { 425 const char* name) {
422 for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) { 426 for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) {
423 const v8::HeapGraphEdge* prop = node->GetChild(i); 427 const v8::HeapGraphEdge* prop = node->GetChild(i);
424 v8::String::AsciiValue prop_name(prop->GetName()); 428 v8::String::AsciiValue prop_name(prop->GetName());
425 if (prop->GetType() == type && strcmp(name, *prop_name) == 0) 429 if (prop->GetType() == type && strcmp(name, *prop_name) == 0)
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 const_cast<i::HeapSnapshot*>( 476 const_cast<i::HeapSnapshot*>(
473 reinterpret_cast<const i::HeapSnapshot*>(snapshot_env2)); 477 reinterpret_cast<const i::HeapSnapshot*>(snapshot_env2));
474 const v8::HeapGraphNode* global_env2 = GetGlobalObject(snapshot_env2); 478 const v8::HeapGraphNode* global_env2 = GetGlobalObject(snapshot_env2);
475 // Paint all nodes reachable from global object. 479 // Paint all nodes reachable from global object.
476 i_snapshot_env2->ClearPaint(); 480 i_snapshot_env2->ClearPaint();
477 const_cast<i::HeapEntry*>( 481 const_cast<i::HeapEntry*>(
478 reinterpret_cast<const i::HeapEntry*>(global_env2))->PaintAllReachable(); 482 reinterpret_cast<const i::HeapEntry*>(global_env2))->PaintAllReachable();
479 483
480 // Verify, that JS global object of env2 has '..2' properties. 484 // Verify, that JS global object of env2 has '..2' properties.
481 const v8::HeapGraphNode* a2_node = 485 const v8::HeapGraphNode* a2_node =
482 GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "a2"); 486 GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "a2");
483 CHECK_NE(NULL, a2_node); 487 CHECK_NE(NULL, a2_node);
484 CHECK_NE( 488 CHECK_NE(
485 NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "b2_1")); 489 NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "b2_1"));
486 CHECK_NE( 490 CHECK_NE(
487 NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "b2_2")); 491 NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "b2_2"));
488 CHECK_NE(NULL, GetProperty(global_env2, v8::HeapGraphEdge::kProperty, "c2")); 492 CHECK_NE(NULL, GetProperty(global_env2, v8::HeapGraphEdge::kShortcut, "c2"));
489 493
490 // Verify that anything related to '[ABC]1' is not reachable.
491 NamedEntriesDetector det; 494 NamedEntriesDetector det;
492 i_snapshot_env2->IterateEntries(&det); 495 i_snapshot_env2->IterateEntries(&det);
493 CHECK(det.has_A2); 496 CHECK(det.has_A2);
494 CHECK(det.has_B2); 497 CHECK(det.has_B2);
495 CHECK(det.has_C2); 498 CHECK(det.has_C2);
496 499
500 /*
501 // Currently disabled. Too many retaining paths emerge, need to
502 // reduce the amount.
503
497 // Verify 'a2' object retainers. They are: 504 // Verify 'a2' object retainers. They are:
498 // - (global object).a2 505 // - (global object).a2
499 // - c2.x1, c2.x2, c2[1] 506 // - c2.x1, c2.x2, c2[1]
500 // - b2_1 and b2_2 closures: via 'x' variable 507 // - b2_1 and b2_2 closures: via 'x' variable
501 CHECK_EQ(6, a2_node->GetRetainingPathsCount()); 508 CHECK_EQ(6, a2_node->GetRetainingPathsCount());
502 bool has_global_obj_a2_ref = false; 509 bool has_global_obj_a2_ref = false;
503 bool has_c2_x1_ref = false, has_c2_x2_ref = false, has_c2_1_ref = false; 510 bool has_c2_x1_ref = false, has_c2_x2_ref = false, has_c2_1_ref = false;
504 bool has_b2_1_x_ref = false, has_b2_2_x_ref = false; 511 bool has_b2_1_x_ref = false, has_b2_2_x_ref = false;
505 for (int i = 0; i < a2_node->GetRetainingPathsCount(); ++i) { 512 for (int i = 0; i < a2_node->GetRetainingPathsCount(); ++i) {
506 const v8::HeapGraphPath* path = a2_node->GetRetainingPath(i); 513 const v8::HeapGraphPath* path = a2_node->GetRetainingPath(i);
(...skipping 24 matching lines...) Expand all
531 if (strcmp("x", *last_edge_name) == 0 538 if (strcmp("x", *last_edge_name) == 0
532 && last_edge->GetType() == v8::HeapGraphEdge::kContextVariable 539 && last_edge->GetType() == v8::HeapGraphEdge::kContextVariable
533 && strcmp("b2_2", *prev_edge_name) == 0) has_b2_2_x_ref = true; 540 && strcmp("b2_2", *prev_edge_name) == 0) has_b2_2_x_ref = true;
534 } 541 }
535 CHECK(has_global_obj_a2_ref); 542 CHECK(has_global_obj_a2_ref);
536 CHECK(has_c2_x1_ref); 543 CHECK(has_c2_x1_ref);
537 CHECK(has_c2_x2_ref); 544 CHECK(has_c2_x2_ref);
538 CHECK(has_c2_1_ref); 545 CHECK(has_c2_1_ref);
539 CHECK(has_b2_1_x_ref); 546 CHECK(has_b2_1_x_ref);
540 CHECK(has_b2_2_x_ref); 547 CHECK(has_b2_2_x_ref);
548 */
541 } 549 }
542 550
543 551
544 TEST(HeapSnapshotObjectSizes) { 552 TEST(HeapSnapshotObjectSizes) {
545 v8::HandleScope scope; 553 v8::HandleScope scope;
546 LocalContext env; 554 LocalContext env;
547 555
548 // -a-> X1 --a 556 // -a-> X1 --a
549 // x -b-> X2 <-| 557 // x -b-> X2 <-|
550 CompileRun( 558 CompileRun(
551 "function X(a, b) { this.a = a; this.b = b; }\n" 559 "function X(a, b) { this.a = a; this.b = b; }\n"
552 "x = new X(new X(), new X());\n" 560 "x = new X(new X(), new X());\n"
553 "x.a.a = x.b;"); 561 "(function() { x.a.a = x.b; })();");
554 const v8::HeapSnapshot* snapshot = 562 const v8::HeapSnapshot* snapshot =
555 v8::HeapProfiler::TakeSnapshot(v8::String::New("sizes")); 563 v8::HeapProfiler::TakeSnapshot(v8::String::New("sizes"));
556 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); 564 const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
557 const v8::HeapGraphNode* x = 565 const v8::HeapGraphNode* x =
558 GetProperty(global, v8::HeapGraphEdge::kProperty, "x"); 566 GetProperty(global, v8::HeapGraphEdge::kShortcut, "x");
559 CHECK_NE(NULL, x); 567 CHECK_NE(NULL, x);
560 const v8::HeapGraphNode* x_prototype =
561 GetProperty(x, v8::HeapGraphEdge::kProperty, "__proto__");
562 CHECK_NE(NULL, x_prototype);
563 const v8::HeapGraphNode* x1 = 568 const v8::HeapGraphNode* x1 =
564 GetProperty(x, v8::HeapGraphEdge::kProperty, "a"); 569 GetProperty(x, v8::HeapGraphEdge::kProperty, "a");
565 CHECK_NE(NULL, x1); 570 CHECK_NE(NULL, x1);
566 const v8::HeapGraphNode* x2 = 571 const v8::HeapGraphNode* x2 =
567 GetProperty(x, v8::HeapGraphEdge::kProperty, "b"); 572 GetProperty(x, v8::HeapGraphEdge::kProperty, "b");
568 CHECK_NE(NULL, x2); 573 CHECK_NE(NULL, x2);
569 CHECK_EQ( 574
570 x->GetSelfSize() * 3, 575 // Test approximate sizes.
571 x->GetReachableSize() - x_prototype->GetReachableSize()); 576 CHECK_EQ(x->GetSelfSize() * 3, x->GetRetainedSize(false));
572 CHECK_EQ( 577 CHECK_EQ(x1->GetSelfSize(), x1->GetRetainedSize(false));
573 x->GetSelfSize() * 3, x->GetRetainedSize()); 578 CHECK_EQ(x2->GetSelfSize(), x2->GetRetainedSize(false));
574 CHECK_EQ( 579 // Test exact sizes.
575 x1->GetSelfSize() * 2, 580 CHECK_EQ(x->GetSelfSize() * 3, x->GetRetainedSize(true));
576 x1->GetReachableSize() - x_prototype->GetReachableSize()); 581 CHECK_EQ(x1->GetSelfSize(), x1->GetRetainedSize(true));
577 CHECK_EQ( 582 CHECK_EQ(x2->GetSelfSize(), x2->GetRetainedSize(true));
578 x1->GetSelfSize(), x1->GetRetainedSize());
579 CHECK_EQ(
580 x2->GetSelfSize(),
581 x2->GetReachableSize() - x_prototype->GetReachableSize());
582 CHECK_EQ(
583 x2->GetSelfSize(), x2->GetRetainedSize());
584 } 583 }
585 584
586 585
587 TEST(HeapSnapshotEntryChildren) { 586 TEST(HeapSnapshotEntryChildren) {
588 v8::HandleScope scope; 587 v8::HandleScope scope;
589 LocalContext env; 588 LocalContext env;
590 589
591 CompileRun( 590 CompileRun(
592 "function A() { }\n" 591 "function A() { }\n"
593 "a = new A;"); 592 "a = new A;");
(...skipping 21 matching lines...) Expand all
615 CompileRun( 614 CompileRun(
616 "function lazy(x) { return x - 1; }\n" 615 "function lazy(x) { return x - 1; }\n"
617 "function compiled(x) { return x + 1; }\n" 616 "function compiled(x) { return x + 1; }\n"
618 "var anonymous = (function() { return function() { return 0; } })();\n" 617 "var anonymous = (function() { return function() { return 0; } })();\n"
619 "compiled(1)"); 618 "compiled(1)");
620 const v8::HeapSnapshot* snapshot = 619 const v8::HeapSnapshot* snapshot =
621 v8::HeapProfiler::TakeSnapshot(v8::String::New("code")); 620 v8::HeapProfiler::TakeSnapshot(v8::String::New("code"));
622 621
623 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); 622 const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
624 const v8::HeapGraphNode* compiled = 623 const v8::HeapGraphNode* compiled =
625 GetProperty(global, v8::HeapGraphEdge::kProperty, "compiled"); 624 GetProperty(global, v8::HeapGraphEdge::kShortcut, "compiled");
626 CHECK_NE(NULL, compiled); 625 CHECK_NE(NULL, compiled);
627 CHECK_EQ(v8::HeapGraphNode::kClosure, compiled->GetType()); 626 CHECK_EQ(v8::HeapGraphNode::kClosure, compiled->GetType());
628 const v8::HeapGraphNode* lazy = 627 const v8::HeapGraphNode* lazy =
629 GetProperty(global, v8::HeapGraphEdge::kProperty, "lazy"); 628 GetProperty(global, v8::HeapGraphEdge::kShortcut, "lazy");
630 CHECK_NE(NULL, lazy); 629 CHECK_NE(NULL, lazy);
631 CHECK_EQ(v8::HeapGraphNode::kClosure, lazy->GetType()); 630 CHECK_EQ(v8::HeapGraphNode::kClosure, lazy->GetType());
632 const v8::HeapGraphNode* anonymous = 631 const v8::HeapGraphNode* anonymous =
633 GetProperty(global, v8::HeapGraphEdge::kProperty, "anonymous"); 632 GetProperty(global, v8::HeapGraphEdge::kShortcut, "anonymous");
634 CHECK_NE(NULL, anonymous); 633 CHECK_NE(NULL, anonymous);
635 CHECK_EQ(v8::HeapGraphNode::kClosure, anonymous->GetType()); 634 CHECK_EQ(v8::HeapGraphNode::kClosure, anonymous->GetType());
636 v8::String::AsciiValue anonymous_name(anonymous->GetName()); 635 v8::String::AsciiValue anonymous_name(anonymous->GetName());
637 CHECK_EQ("", *anonymous_name); 636 CHECK_EQ("", *anonymous_name);
638 637
639 // Find references to code. 638 // Find references to code.
640 const v8::HeapGraphNode* compiled_code = 639 const v8::HeapGraphNode* compiled_code =
641 GetProperty(compiled, v8::HeapGraphEdge::kInternal, "code"); 640 GetProperty(compiled, v8::HeapGraphEdge::kInternal, "code");
642 CHECK_NE(NULL, compiled_code); 641 CHECK_NE(NULL, compiled_code);
643 const v8::HeapGraphNode* lazy_code = 642 const v8::HeapGraphNode* lazy_code =
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
675 674
676 TEST(HeapSnapshotHeapNumbers) { 675 TEST(HeapSnapshotHeapNumbers) {
677 v8::HandleScope scope; 676 v8::HandleScope scope;
678 LocalContext env; 677 LocalContext env;
679 CompileRun( 678 CompileRun(
680 "a = 1; // a is Smi\n" 679 "a = 1; // a is Smi\n"
681 "b = 2.5; // b is HeapNumber"); 680 "b = 2.5; // b is HeapNumber");
682 const v8::HeapSnapshot* snapshot = 681 const v8::HeapSnapshot* snapshot =
683 v8::HeapProfiler::TakeSnapshot(v8::String::New("numbers")); 682 v8::HeapProfiler::TakeSnapshot(v8::String::New("numbers"));
684 const v8::HeapGraphNode* global = GetGlobalObject(snapshot); 683 const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
685 CHECK_EQ(NULL, GetProperty(global, v8::HeapGraphEdge::kProperty, "a")); 684 CHECK_EQ(NULL, GetProperty(global, v8::HeapGraphEdge::kShortcut, "a"));
686 const v8::HeapGraphNode* b = 685 const v8::HeapGraphNode* b =
687 GetProperty(global, v8::HeapGraphEdge::kProperty, "b"); 686 GetProperty(global, v8::HeapGraphEdge::kShortcut, "b");
688 CHECK_NE(NULL, b); 687 CHECK_NE(NULL, b);
689 CHECK_EQ(v8::HeapGraphNode::kHeapNumber, b->GetType()); 688 CHECK_EQ(v8::HeapGraphNode::kHeapNumber, b->GetType());
690 } 689 }
691 690
692 691
693 TEST(HeapSnapshotInternalReferences) { 692 TEST(HeapSnapshotInternalReferences) {
694 v8::HandleScope scope; 693 v8::HandleScope scope;
695 v8::Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(); 694 v8::Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
696 global_template->SetInternalFieldCount(2); 695 global_template->SetInternalFieldCount(2);
697 LocalContext env(NULL, global_template); 696 LocalContext env(NULL, global_template);
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
801 // Verify additions: ensure that addition of A and B was detected. 800 // Verify additions: ensure that addition of A and B was detected.
802 const v8::HeapGraphNode* additions_root = diff->GetAdditionsRoot(); 801 const v8::HeapGraphNode* additions_root = diff->GetAdditionsRoot();
803 bool found_A = false, found_B = false; 802 bool found_A = false, found_B = false;
804 uint64_t s1_A_id = 0; 803 uint64_t s1_A_id = 0;
805 for (int i = 0, count = additions_root->GetChildrenCount(); i < count; ++i) { 804 for (int i = 0, count = additions_root->GetChildrenCount(); i < count; ++i) {
806 const v8::HeapGraphEdge* prop = additions_root->GetChild(i); 805 const v8::HeapGraphEdge* prop = additions_root->GetChild(i);
807 const v8::HeapGraphNode* node = prop->GetToNode(); 806 const v8::HeapGraphNode* node = prop->GetToNode();
808 if (node->GetType() == v8::HeapGraphNode::kObject) { 807 if (node->GetType() == v8::HeapGraphNode::kObject) {
809 v8::String::AsciiValue node_name(node->GetName()); 808 v8::String::AsciiValue node_name(node->GetName());
810 if (strcmp(*node_name, "A2") == 0) { 809 if (strcmp(*node_name, "A2") == 0) {
811 CHECK(IsNodeRetainedAs(node, v8::HeapGraphEdge::kProperty, "a")); 810 CHECK(IsNodeRetainedAs(node, v8::HeapGraphEdge::kShortcut, "a"));
812 CHECK(!found_A); 811 CHECK(!found_A);
813 found_A = true; 812 found_A = true;
814 s1_A_id = node->GetId(); 813 s1_A_id = node->GetId();
815 } else if (strcmp(*node_name, "B") == 0) { 814 } else if (strcmp(*node_name, "B") == 0) {
816 CHECK(IsNodeRetainedAs(node, v8::HeapGraphEdge::kProperty, "b2")); 815 CHECK(IsNodeRetainedAs(node, v8::HeapGraphEdge::kShortcut, "b2"));
817 CHECK(!found_B); 816 CHECK(!found_B);
818 found_B = true; 817 found_B = true;
819 } 818 }
820 } 819 }
821 } 820 }
822 CHECK(found_A); 821 CHECK(found_A);
823 CHECK(found_B); 822 CHECK(found_B);
824 823
825 // Verify deletions: ensure that deletion of A was detected. 824 // Verify deletions: ensure that deletion of A was detected.
826 const v8::HeapGraphNode* deletions_root = diff->GetDeletionsRoot(); 825 const v8::HeapGraphNode* deletions_root = diff->GetDeletionsRoot();
827 bool found_A_del = false; 826 bool found_A_del = false;
828 uint64_t s2_A_id = 0; 827 uint64_t s2_A_id = 0;
829 for (int i = 0, count = deletions_root->GetChildrenCount(); i < count; ++i) { 828 for (int i = 0, count = deletions_root->GetChildrenCount(); i < count; ++i) {
830 const v8::HeapGraphEdge* prop = deletions_root->GetChild(i); 829 const v8::HeapGraphEdge* prop = deletions_root->GetChild(i);
831 const v8::HeapGraphNode* node = prop->GetToNode(); 830 const v8::HeapGraphNode* node = prop->GetToNode();
832 if (node->GetType() == v8::HeapGraphNode::kObject) { 831 if (node->GetType() == v8::HeapGraphNode::kObject) {
833 v8::String::AsciiValue node_name(node->GetName()); 832 v8::String::AsciiValue node_name(node->GetName());
834 if (strcmp(*node_name, "A") == 0) { 833 if (strcmp(*node_name, "A") == 0) {
835 CHECK(IsNodeRetainedAs(node, v8::HeapGraphEdge::kProperty, "a")); 834 CHECK(IsNodeRetainedAs(node, v8::HeapGraphEdge::kShortcut, "a"));
836 CHECK(!found_A_del); 835 CHECK(!found_A_del);
837 found_A_del = true; 836 found_A_del = true;
838 s2_A_id = node->GetId(); 837 s2_A_id = node->GetId();
839 } 838 }
840 } 839 }
841 } 840 }
842 CHECK(found_A_del); 841 CHECK(found_A_del);
843 CHECK_NE_UINT64_T(0, s1_A_id); 842 CHECK_NE_UINT64_T(0, s1_A_id);
844 CHECK(s1_A_id != s2_A_id); 843 CHECK(s1_A_id != s2_A_id);
845 } 844 }
846 845
847 846
848 TEST(HeapSnapshotRootPreservedAfterSorting) { 847 TEST(HeapSnapshotRootPreservedAfterSorting) {
849 v8::HandleScope scope; 848 v8::HandleScope scope;
850 LocalContext env; 849 LocalContext env;
851 const v8::HeapSnapshot* snapshot = 850 const v8::HeapSnapshot* snapshot =
852 v8::HeapProfiler::TakeSnapshot(v8::String::New("s")); 851 v8::HeapProfiler::TakeSnapshot(v8::String::New("s"));
853 const v8::HeapGraphNode* root1 = snapshot->GetRoot(); 852 const v8::HeapGraphNode* root1 = snapshot->GetRoot();
854 const_cast<i::HeapSnapshot*>(reinterpret_cast<const i::HeapSnapshot*>( 853 const_cast<i::HeapSnapshot*>(reinterpret_cast<const i::HeapSnapshot*>(
855 snapshot))->GetSortedEntriesList(); 854 snapshot))->GetSortedEntriesList();
856 const v8::HeapGraphNode* root2 = snapshot->GetRoot(); 855 const v8::HeapGraphNode* root2 = snapshot->GetRoot();
857 CHECK_EQ(root1, root2); 856 CHECK_EQ(root1, root2);
858 } 857 }
859 858
860 859
861 namespace v8 {
862 namespace internal {
863
864 class HeapSnapshotTester {
865 public:
866 static int CalculateNetworkSize(JSObject* obj) {
867 return HeapSnapshot::CalculateNetworkSize(obj);
868 }
869 };
870
871 } } // namespace v8::internal
872
873 // http://code.google.com/p/v8/issues/detail?id=822
874 // Trying to call CalculateNetworkSize on an object with elements set
875 // to non-FixedArray may cause an assertion error in debug builds.
876 TEST(Issue822) {
877 v8::HandleScope scope;
878 LocalContext context;
879 const int kElementCount = 260;
880 uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
881 i::Handle<i::PixelArray> pixels = i::Factory::NewPixelArray(kElementCount,
882 pixel_data);
883 v8::Handle<v8::Object> obj = v8::Object::New();
884 // Set the elements to be the pixels.
885 obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
886 i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
887 // This call must not cause an assertion error in debug builds.
888 i::HeapSnapshotTester::CalculateNetworkSize(*jsobj);
889 }
890
891
892 static const v8::HeapGraphNode* GetChild( 860 static const v8::HeapGraphNode* GetChild(
893 const v8::HeapGraphNode* node, 861 const v8::HeapGraphNode* node,
894 v8::HeapGraphNode::Type type, 862 v8::HeapGraphNode::Type type,
895 const char* name, 863 const char* name,
896 const v8::HeapGraphNode* after = NULL) { 864 const v8::HeapGraphNode* after = NULL) {
897 bool ignore_child = after == NULL ? false : true; 865 bool ignore_child = after == NULL ? false : true;
898 for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) { 866 for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) {
899 const v8::HeapGraphEdge* prop = node->GetChild(i); 867 const v8::HeapGraphEdge* prop = node->GetChild(i);
900 const v8::HeapGraphNode* child = prop->GetToNode(); 868 const v8::HeapGraphNode* child = prop->GetToNode();
901 v8::String::AsciiValue child_name(child->GetName()); 869 v8::String::AsciiValue child_name(child->GetName());
(...skipping 23 matching lines...) Expand all
925 893
926 CompileRun( 894 CompileRun(
927 "function A() {}\n" 895 "function A() {}\n"
928 "function B(x) { this.x = x; }\n" 896 "function B(x) { this.x = x; }\n"
929 "var a = new A();\n" 897 "var a = new A();\n"
930 "var b = new B(a);"); 898 "var b = new B(a);");
931 const v8::HeapSnapshot* snapshot = 899 const v8::HeapSnapshot* snapshot =
932 v8::HeapProfiler::TakeSnapshot( 900 v8::HeapProfiler::TakeSnapshot(
933 v8::String::New("agg"), v8::HeapSnapshot::kAggregated); 901 v8::String::New("agg"), v8::HeapSnapshot::kAggregated);
934 const v8::HeapGraphNode* strings = GetChild(snapshot->GetRoot(), 902 const v8::HeapGraphNode* strings = GetChild(snapshot->GetRoot(),
935 v8::HeapGraphNode::kInternal, 903 v8::HeapGraphNode::kHidden,
936 "STRING_TYPE"); 904 "STRING_TYPE");
937 CHECK_NE(NULL, strings); 905 CHECK_NE(NULL, strings);
938 CHECK_NE(0, strings->GetSelfSize()); 906 CHECK_NE(0, strings->GetSelfSize());
939 CHECK_NE(0, strings->GetInstancesCount()); 907 CHECK_NE(0, strings->GetInstancesCount());
940 const v8::HeapGraphNode* maps = GetChild(snapshot->GetRoot(), 908 const v8::HeapGraphNode* maps = GetChild(snapshot->GetRoot(),
941 v8::HeapGraphNode::kInternal, 909 v8::HeapGraphNode::kHidden,
942 "MAP_TYPE"); 910 "MAP_TYPE");
943 CHECK_NE(NULL, maps); 911 CHECK_NE(NULL, maps);
944 CHECK_NE(0, maps->GetSelfSize()); 912 CHECK_NE(0, maps->GetSelfSize());
945 CHECK_NE(0, maps->GetInstancesCount()); 913 CHECK_NE(0, maps->GetInstancesCount());
946 914
947 const v8::HeapGraphNode* a = GetChild(snapshot->GetRoot(), 915 const v8::HeapGraphNode* a = GetChild(snapshot->GetRoot(),
948 v8::HeapGraphNode::kObject, 916 v8::HeapGraphNode::kObject,
949 "A"); 917 "A");
950 CHECK_NE(NULL, a); 918 CHECK_NE(NULL, a);
951 CHECK_NE(0, a->GetSelfSize()); 919 CHECK_NE(0, a->GetSelfSize());
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
991 b_with_children, 959 b_with_children,
992 v8::HeapGraphNode::kObject, 960 v8::HeapGraphNode::kObject,
993 "A"); 961 "A");
994 CHECK_NE(NULL, a_from_b); 962 CHECK_NE(NULL, a_from_b);
995 CHECK_EQ(0, a_from_b->GetSelfSize()); 963 CHECK_EQ(0, a_from_b->GetSelfSize());
996 CHECK_EQ(0, a_from_b->GetInstancesCount()); 964 CHECK_EQ(0, a_from_b->GetInstancesCount());
997 CHECK_EQ(0, a_from_b->GetChildrenCount()); // Retains nothing. 965 CHECK_EQ(0, a_from_b->GetChildrenCount()); // Retains nothing.
998 CHECK(IsNodeRetainedAs(a_from_b, 1)); // B has 1 ref to A. 966 CHECK(IsNodeRetainedAs(a_from_b, 1)); // B has 1 ref to A.
999 } 967 }
1000 968
969
970 TEST(HeapEntryDominator) {
971 // The graph looks like this:
972 //
973 // -> node1
974 // a |^
975 // -> node5 ba
976 // a v|
977 // node6 -> node2
978 // b a |^
979 // -> node4 ba
980 // b v|
981 // -> node3
982 //
983 // The dominator for all nodes is node6.
984
985 v8::HandleScope scope;
986 LocalContext env;
987
988 CompileRun(
989 "function X(a, b) { this.a = a; this.b = b; }\n"
990 "node6 = new X(new X(new X()), new X(new X(),new X()));\n"
991 "(function(){\n"
992 "node6.a.a.b = node6.b.a; // node1 -> node2\n"
993 "node6.b.a.a = node6.a.a; // node2 -> node1\n"
994 "node6.b.a.b = node6.b.b; // node2 -> node3\n"
995 "node6.b.b.a = node6.b.a; // node3 -> node2\n"
996 "})();");
997
998 const v8::HeapSnapshot* snapshot =
999 v8::HeapProfiler::TakeSnapshot(v8::String::New("dominators"));
1000
1001 const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
1002 CHECK_NE(NULL, global);
1003 const v8::HeapGraphNode* node6 =
1004 GetProperty(global, v8::HeapGraphEdge::kShortcut, "node6");
1005 CHECK_NE(NULL, node6);
1006 const v8::HeapGraphNode* node5 =
1007 GetProperty(node6, v8::HeapGraphEdge::kProperty, "a");
1008 CHECK_NE(NULL, node5);
1009 const v8::HeapGraphNode* node4 =
1010 GetProperty(node6, v8::HeapGraphEdge::kProperty, "b");
1011 CHECK_NE(NULL, node4);
1012 const v8::HeapGraphNode* node3 =
1013 GetProperty(node4, v8::HeapGraphEdge::kProperty, "b");
1014 CHECK_NE(NULL, node3);
1015 const v8::HeapGraphNode* node2 =
1016 GetProperty(node4, v8::HeapGraphEdge::kProperty, "a");
1017 CHECK_NE(NULL, node2);
1018 const v8::HeapGraphNode* node1 =
1019 GetProperty(node5, v8::HeapGraphEdge::kProperty, "a");
1020 CHECK_NE(NULL, node1);
1021
1022 CHECK_EQ(node6, node1->GetDominatorNode());
1023 CHECK_EQ(node6, node2->GetDominatorNode());
1024 CHECK_EQ(node6, node3->GetDominatorNode());
1025 CHECK_EQ(node6, node4->GetDominatorNode());
1026 CHECK_EQ(node6, node5->GetDominatorNode());
1027 }
1028
1029
1001 namespace { 1030 namespace {
1002 1031
1003 class TestJSONStream : public v8::OutputStream { 1032 class TestJSONStream : public v8::OutputStream {
1004 public: 1033 public:
1005 TestJSONStream() : eos_signaled_(0), abort_countdown_(-1) {} 1034 TestJSONStream() : eos_signaled_(0), abort_countdown_(-1) {}
1006 explicit TestJSONStream(int abort_countdown) 1035 explicit TestJSONStream(int abort_countdown)
1007 : eos_signaled_(0), abort_countdown_(abort_countdown) {} 1036 : eos_signaled_(0), abort_countdown_(abort_countdown) {}
1008 virtual ~TestJSONStream() {} 1037 virtual ~TestJSONStream() {}
1009 virtual void EndOfStream() { ++eos_signaled_; } 1038 virtual void EndOfStream() { ++eos_signaled_; }
1010 virtual WriteResult WriteAsciiChunk(char* buffer, int chars_written) { 1039 virtual WriteResult WriteAsciiChunk(char* buffer, int chars_written) {
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1066 "var parsed = JSON.parse(json_snapshot); true;"); 1095 "var parsed = JSON.parse(json_snapshot); true;");
1067 CHECK(!snapshot_parse_result.IsEmpty()); 1096 CHECK(!snapshot_parse_result.IsEmpty());
1068 1097
1069 // Verify that snapshot object has required fields. 1098 // Verify that snapshot object has required fields.
1070 v8::Local<v8::Object> parsed_snapshot = 1099 v8::Local<v8::Object> parsed_snapshot =
1071 env->Global()->Get(v8::String::New("parsed"))->ToObject(); 1100 env->Global()->Get(v8::String::New("parsed"))->ToObject();
1072 CHECK(parsed_snapshot->Has(v8::String::New("snapshot"))); 1101 CHECK(parsed_snapshot->Has(v8::String::New("snapshot")));
1073 CHECK(parsed_snapshot->Has(v8::String::New("nodes"))); 1102 CHECK(parsed_snapshot->Has(v8::String::New("nodes")));
1074 CHECK(parsed_snapshot->Has(v8::String::New("strings"))); 1103 CHECK(parsed_snapshot->Has(v8::String::New("strings")));
1075 1104
1076 // Verify that nodes meta-info is valid JSON.
1077 v8::Local<v8::Value> nodes_meta_parse_result = CompileRun(
1078 "var parsed_meta = JSON.parse(parsed.nodes[0]); true;");
1079 CHECK(!nodes_meta_parse_result.IsEmpty());
1080
1081 // Get node and edge "member" offsets. 1105 // Get node and edge "member" offsets.
1082 v8::Local<v8::Value> meta_analysis_result = CompileRun( 1106 v8::Local<v8::Value> meta_analysis_result = CompileRun(
1107 "var parsed_meta = parsed.nodes[0];\n"
1083 "var children_count_offset =" 1108 "var children_count_offset ="
1084 " parsed_meta.fields.indexOf('children_count');\n" 1109 " parsed_meta.fields.indexOf('children_count');\n"
1085 "var children_offset =" 1110 "var children_offset ="
1086 " parsed_meta.fields.indexOf('children');\n" 1111 " parsed_meta.fields.indexOf('children');\n"
1087 "var children_meta =" 1112 "var children_meta ="
1088 " parsed_meta.types[children_offset];\n" 1113 " parsed_meta.types[children_offset];\n"
1089 "var child_fields_count = children_meta.fields.length;\n" 1114 "var child_fields_count = children_meta.fields.length;\n"
1090 "var child_type_offset =" 1115 "var child_type_offset ="
1091 " children_meta.fields.indexOf('type');\n" 1116 " children_meta.fields.indexOf('type');\n"
1092 "var child_name_offset =" 1117 "var child_name_offset ="
1093 " children_meta.fields.indexOf('name_or_index');\n" 1118 " children_meta.fields.indexOf('name_or_index');\n"
1094 "var child_to_node_offset =" 1119 "var child_to_node_offset ="
1095 " children_meta.fields.indexOf('to_node');\n" 1120 " children_meta.fields.indexOf('to_node');\n"
1096 "var property_type =" 1121 "var property_type ="
1097 " children_meta.types[child_type_offset].indexOf('property');"); 1122 " children_meta.types[child_type_offset].indexOf('property');\n"
1123 "var shortcut_type ="
1124 " children_meta.types[child_type_offset].indexOf('shortcut');");
1098 CHECK(!meta_analysis_result.IsEmpty()); 1125 CHECK(!meta_analysis_result.IsEmpty());
1099 1126
1100 // A helper function for processing encoded nodes. 1127 // A helper function for processing encoded nodes.
1101 CompileRun( 1128 CompileRun(
1102 "function GetChildPosByProperty(pos, prop_name) {\n" 1129 "function GetChildPosByProperty(pos, prop_name, prop_type) {\n"
1103 " var nodes = parsed.nodes;\n" 1130 " var nodes = parsed.nodes;\n"
1104 " var strings = parsed.strings;\n" 1131 " var strings = parsed.strings;\n"
1105 " for (var i = 0,\n" 1132 " for (var i = 0,\n"
1106 " count = nodes[pos + children_count_offset] * child_fields_count;\n" 1133 " count = nodes[pos + children_count_offset] * child_fields_count;\n"
1107 " i < count; i += child_fields_count) {\n" 1134 " i < count; i += child_fields_count) {\n"
1108 " var child_pos = pos + children_offset + i;\n" 1135 " var child_pos = pos + children_offset + i;\n"
1109 " if (nodes[child_pos + child_type_offset] === property_type\n" 1136 " if (nodes[child_pos + child_type_offset] === prop_type\n"
1110 " && strings[nodes[child_pos + child_name_offset]] === prop_name)\n" 1137 " && strings[nodes[child_pos + child_name_offset]] === prop_name)\n"
1111 " return nodes[child_pos + child_to_node_offset];\n" 1138 " return nodes[child_pos + child_to_node_offset];\n"
1112 " }\n" 1139 " }\n"
1113 " return null;\n" 1140 " return null;\n"
1114 "}\n"); 1141 "}\n");
1115 // Get the string index using the path: <root> -> <global>.b.x.s 1142 // Get the string index using the path: <root> -> <global>.b.x.s
1116 v8::Local<v8::Value> string_obj_pos_val = CompileRun( 1143 v8::Local<v8::Value> string_obj_pos_val = CompileRun(
1117 "GetChildPosByProperty(\n" 1144 "GetChildPosByProperty(\n"
1118 " GetChildPosByProperty(\n" 1145 " GetChildPosByProperty(\n"
1119 " GetChildPosByProperty(" 1146 " GetChildPosByProperty("
1120 " parsed.nodes[1 + children_offset + child_to_node_offset],\"b\"),\n" 1147 " parsed.nodes[1 + children_offset + child_to_node_offset],"
1121 " \"x\")," 1148 " \"b\",shortcut_type),\n"
1122 " \"s\")"); 1149 " \"x\", property_type),"
1150 " \"s\", property_type)");
1123 CHECK(!string_obj_pos_val.IsEmpty()); 1151 CHECK(!string_obj_pos_val.IsEmpty());
1124 int string_obj_pos = 1152 int string_obj_pos =
1125 static_cast<int>(string_obj_pos_val->ToNumber()->Value()); 1153 static_cast<int>(string_obj_pos_val->ToNumber()->Value());
1126 v8::Local<v8::Object> nodes_array = 1154 v8::Local<v8::Object> nodes_array =
1127 parsed_snapshot->Get(v8::String::New("nodes"))->ToObject(); 1155 parsed_snapshot->Get(v8::String::New("nodes"))->ToObject();
1128 int string_index = static_cast<int>( 1156 int string_index = static_cast<int>(
1129 nodes_array->Get(string_obj_pos + 1)->ToNumber()->Value()); 1157 nodes_array->Get(string_obj_pos + 1)->ToNumber()->Value());
1130 CHECK_GT(string_index, 0); 1158 CHECK_GT(string_index, 0);
1131 v8::Local<v8::Object> strings_array = 1159 v8::Local<v8::Object> strings_array =
1132 parsed_snapshot->Get(v8::String::New("strings"))->ToObject(); 1160 parsed_snapshot->Get(v8::String::New("strings"))->ToObject();
(...skipping 11 matching lines...) Expand all
1144 LocalContext env; 1172 LocalContext env;
1145 const v8::HeapSnapshot* snapshot = 1173 const v8::HeapSnapshot* snapshot =
1146 v8::HeapProfiler::TakeSnapshot(v8::String::New("abort")); 1174 v8::HeapProfiler::TakeSnapshot(v8::String::New("abort"));
1147 TestJSONStream stream(5); 1175 TestJSONStream stream(5);
1148 snapshot->Serialize(&stream, v8::HeapSnapshot::kJSON); 1176 snapshot->Serialize(&stream, v8::HeapSnapshot::kJSON);
1149 CHECK_GT(stream.size(), 0); 1177 CHECK_GT(stream.size(), 0);
1150 CHECK_EQ(0, stream.eos_signaled()); 1178 CHECK_EQ(0, stream.eos_signaled());
1151 } 1179 }
1152 1180
1153 #endif // ENABLE_LOGGING_AND_PROFILING 1181 #endif // ENABLE_LOGGING_AND_PROFILING
OLDNEW
« no previous file with comments | « test/cctest/test-debug.cc ('k') | test/cctest/test-parsing.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698