OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 634 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
645 " var o = instance.foo;\n" | 645 " var o = instance.foo;\n" |
646 " instance.foo = o + 1;\n" | 646 " instance.foo = o + 1;\n" |
647 " }\n" | 647 " }\n" |
648 "}\n"; | 648 "}\n"; |
649 | 649 |
650 | 650 |
651 class FooAccessorsData { | 651 class FooAccessorsData { |
652 public: | 652 public: |
653 explicit FooAccessorsData(int min_duration_ms) | 653 explicit FooAccessorsData(int min_duration_ms) |
654 : min_duration_ms_(min_duration_ms), | 654 : min_duration_ms_(min_duration_ms), |
655 getter_duration_(0), | 655 is_warming_up_(false) {} |
656 setter_duration_(0), | |
657 getter_iterations_(0), | |
658 setter_iterations_(0) {} | |
659 | 656 |
660 static v8::Handle<v8::Value> Getter(v8::Local<v8::String> name, | 657 static v8::Handle<v8::Value> Getter(v8::Local<v8::String> name, |
661 const v8::AccessorInfo& info) { | 658 const v8::AccessorInfo& info) { |
662 FooAccessorsData* data = fromInfo(info); | 659 FooAccessorsData* data = fromInfo(info); |
663 data->getter_duration_ = data->Wait(&data->getter_iterations_); | 660 data->Wait(); |
664 return v8::Int32::New(2013); | 661 return v8::Int32::New(2013); |
665 } | 662 } |
666 | 663 |
667 static void Setter(v8::Local<v8::String> name, | 664 static void Setter(v8::Local<v8::String> name, |
668 v8::Local<v8::Value> value, | 665 v8::Local<v8::Value> value, |
669 const v8::AccessorInfo& info) { | 666 const v8::AccessorInfo& info) { |
670 FooAccessorsData* data = fromInfo(info); | 667 FooAccessorsData* data = fromInfo(info); |
671 data->setter_duration_ = data->Wait(&data->setter_iterations_); | 668 data->Wait(); |
672 } | 669 } |
673 | 670 |
674 void PrintAccessorTime() { | 671 void set_warming_up(bool value) { is_warming_up_ = value; } |
675 i::OS::Print("getter: %f ms (%d); setter: %f ms (%d)\n", getter_duration_, | |
676 getter_iterations_, setter_duration_, setter_iterations_); | |
677 } | |
678 | 672 |
679 private: | 673 private: |
680 double Wait(int* iterations) { | 674 void Wait() { |
| 675 if (is_warming_up_) return; |
681 double start = i::OS::TimeCurrentMillis(); | 676 double start = i::OS::TimeCurrentMillis(); |
682 double duration = 0; | 677 double duration = 0; |
683 while (duration < min_duration_ms_) { | 678 while (duration < min_duration_ms_) { |
684 i::OS::Sleep(1); | 679 i::OS::Sleep(1); |
685 duration = i::OS::TimeCurrentMillis() - start; | 680 duration = i::OS::TimeCurrentMillis() - start; |
686 ++*iterations; | |
687 } | 681 } |
688 return duration; | |
689 } | 682 } |
690 | 683 |
691 static FooAccessorsData* fromInfo(const v8::AccessorInfo& info) { | 684 static FooAccessorsData* fromInfo(const v8::AccessorInfo& info) { |
692 void* data = v8::External::Cast(*info.Data())->Value(); | 685 void* data = v8::External::Cast(*info.Data())->Value(); |
693 return reinterpret_cast<FooAccessorsData*>(data); | 686 return reinterpret_cast<FooAccessorsData*>(data); |
694 } | 687 } |
695 | 688 |
696 int min_duration_ms_; | 689 int min_duration_ms_; |
697 double getter_duration_; | 690 bool is_warming_up_; |
698 double setter_duration_; | |
699 int getter_iterations_; | |
700 int setter_iterations_; | |
701 }; | 691 }; |
702 | 692 |
703 | 693 |
704 // Test that native accessors are properly reported in the CPU profile. | 694 // Test that native accessors are properly reported in the CPU profile. |
705 // This test checks the case when the long-running accessors are called | 695 // This test checks the case when the long-running accessors are called |
706 // only once and the optimizer doesn't have chance to change the invocation | 696 // only once and the optimizer doesn't have chance to change the invocation |
707 // code. | 697 // code. |
708 TEST(NativeAccessorNameInProfile1) { | 698 TEST(NativeAccessorUninitializedIC) { |
709 LocalContext env; | 699 LocalContext env; |
710 v8::HandleScope scope(env->GetIsolate()); | 700 v8::HandleScope scope(env->GetIsolate()); |
711 | 701 |
712 | 702 |
713 v8::Local<v8::FunctionTemplate> func_template = v8::FunctionTemplate::New(); | 703 v8::Local<v8::FunctionTemplate> func_template = v8::FunctionTemplate::New(); |
714 v8::Local<v8::ObjectTemplate> instance_template = | 704 v8::Local<v8::ObjectTemplate> instance_template = |
715 func_template->InstanceTemplate(); | 705 func_template->InstanceTemplate(); |
716 | 706 |
717 FooAccessorsData accessors(100); | 707 FooAccessorsData accessors(100); |
718 v8::Local<v8::External> data = v8::External::New(&accessors); | 708 v8::Local<v8::External> data = v8::External::New(&accessors); |
(...skipping 14 matching lines...) Expand all Loading... |
733 cpu_profiler->StartCpuProfiling(profile_name); | 723 cpu_profiler->StartCpuProfiling(profile_name); |
734 int32_t repeat_count = 1; | 724 int32_t repeat_count = 1; |
735 v8::Handle<v8::Value> args[] = { v8::Integer::New(repeat_count) }; | 725 v8::Handle<v8::Value> args[] = { v8::Integer::New(repeat_count) }; |
736 function->Call(env->Global(), ARRAY_SIZE(args), args); | 726 function->Call(env->Global(), ARRAY_SIZE(args), args); |
737 const v8::CpuProfile* profile = cpu_profiler->StopCpuProfiling(profile_name); | 727 const v8::CpuProfile* profile = cpu_profiler->StopCpuProfiling(profile_name); |
738 | 728 |
739 CHECK_NE(NULL, profile); | 729 CHECK_NE(NULL, profile); |
740 // Dump collected profile to have a better diagnostic in case of failure. | 730 // Dump collected profile to have a better diagnostic in case of failure. |
741 reinterpret_cast<i::CpuProfile*>( | 731 reinterpret_cast<i::CpuProfile*>( |
742 const_cast<v8::CpuProfile*>(profile))->Print(); | 732 const_cast<v8::CpuProfile*>(profile))->Print(); |
743 accessors.PrintAccessorTime(); | |
744 | 733 |
745 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); | 734 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); |
746 const v8::CpuProfileNode* startNode = GetChild(root, "start"); | 735 const v8::CpuProfileNode* startNode = GetChild(root, "start"); |
747 GetChild(startNode, "get foo"); | 736 GetChild(startNode, "get foo"); |
748 GetChild(startNode, "set foo"); | 737 GetChild(startNode, "set foo"); |
749 | 738 |
750 cpu_profiler->DeleteAllCpuProfiles(); | 739 cpu_profiler->DeleteAllCpuProfiles(); |
751 } | 740 } |
752 | 741 |
753 | 742 |
754 // Test that native accessors are properly reported in the CPU profile. | 743 // Test that native accessors are properly reported in the CPU profile. |
755 // This test makes sure that the accessors are called enough times to become | 744 // This test makes sure that the accessors are called enough times to become |
756 // hot and to trigger optimizations. | 745 // hot and to trigger optimizations. |
757 TEST(NativeAccessorNameInProfile2) { | 746 TEST(NativeAccessorMonomorphicIC) { |
758 LocalContext env; | 747 LocalContext env; |
759 v8::HandleScope scope(env->GetIsolate()); | 748 v8::HandleScope scope(env->GetIsolate()); |
760 | 749 |
761 | 750 |
762 v8::Local<v8::FunctionTemplate> func_template = v8::FunctionTemplate::New(); | 751 v8::Local<v8::FunctionTemplate> func_template = v8::FunctionTemplate::New(); |
763 v8::Local<v8::ObjectTemplate> instance_template = | 752 v8::Local<v8::ObjectTemplate> instance_template = |
764 func_template->InstanceTemplate(); | 753 func_template->InstanceTemplate(); |
765 | 754 |
766 FooAccessorsData accessors(1); | 755 FooAccessorsData accessors(1); |
767 v8::Local<v8::External> data = v8::External::New(&accessors); | 756 v8::Local<v8::External> data = v8::External::New(&accessors); |
768 instance_template->SetAccessor( | 757 instance_template->SetAccessor( |
769 v8::String::New("foo"), &FooAccessorsData::Getter, | 758 v8::String::New("foo"), &FooAccessorsData::Getter, |
770 &FooAccessorsData::Setter, data); | 759 &FooAccessorsData::Setter, data); |
771 v8::Local<v8::Function> func = func_template->GetFunction(); | 760 v8::Local<v8::Function> func = func_template->GetFunction(); |
772 v8::Local<v8::Object> instance = func->NewInstance(); | 761 v8::Local<v8::Object> instance = func->NewInstance(); |
773 env->Global()->Set(v8::String::New("instance"), instance); | 762 env->Global()->Set(v8::String::New("instance"), instance); |
774 | 763 |
775 v8::Script::Compile(v8::String::New(native_accessor_test_source))->Run(); | 764 v8::Script::Compile(v8::String::New(native_accessor_test_source))->Run(); |
776 v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast( | 765 v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast( |
777 env->Global()->Get(v8::String::New("start"))); | 766 env->Global()->Get(v8::String::New("start"))); |
778 | 767 |
| 768 { |
| 769 // Make sure accessors ICs are in monomorphic state before starting |
| 770 // profiling. |
| 771 accessors.set_warming_up(true); |
| 772 int32_t warm_up_iterations = 3; |
| 773 v8::Handle<v8::Value> args[] = { v8::Integer::New(warm_up_iterations) }; |
| 774 function->Call(env->Global(), ARRAY_SIZE(args), args); |
| 775 accessors.set_warming_up(false); |
| 776 } |
| 777 |
779 v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler(); | 778 v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler(); |
780 v8::Local<v8::String> profile_name = v8::String::New("my_profile"); | 779 v8::Local<v8::String> profile_name = v8::String::New("my_profile"); |
781 | 780 |
782 cpu_profiler->StartCpuProfiling(profile_name); | 781 cpu_profiler->StartCpuProfiling(profile_name); |
783 int32_t repeat_count = 100; | 782 int32_t repeat_count = 100; |
784 v8::Handle<v8::Value> args[] = { v8::Integer::New(repeat_count) }; | 783 v8::Handle<v8::Value> args[] = { v8::Integer::New(repeat_count) }; |
785 function->Call(env->Global(), ARRAY_SIZE(args), args); | 784 function->Call(env->Global(), ARRAY_SIZE(args), args); |
786 const v8::CpuProfile* profile = cpu_profiler->StopCpuProfiling(profile_name); | 785 const v8::CpuProfile* profile = cpu_profiler->StopCpuProfiling(profile_name); |
787 | 786 |
788 CHECK_NE(NULL, profile); | 787 CHECK_NE(NULL, profile); |
789 // Dump collected profile to have a better diagnostic in case of failure. | 788 // Dump collected profile to have a better diagnostic in case of failure. |
790 reinterpret_cast<i::CpuProfile*>( | 789 reinterpret_cast<i::CpuProfile*>( |
791 const_cast<v8::CpuProfile*>(profile))->Print(); | 790 const_cast<v8::CpuProfile*>(profile))->Print(); |
792 | 791 |
793 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); | 792 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); |
794 const v8::CpuProfileNode* startNode = GetChild(root, "start"); | 793 const v8::CpuProfileNode* startNode = GetChild(root, "start"); |
795 // TODO(yurys): in LoadIC should be changed to report external callback | 794 // TODO(yurys): in LoadIC should be changed to report external callback |
796 // invocation. See r13768 where it was LoadCallbackProperty was removed. | 795 // invocation. See r13768 where it was LoadCallbackProperty was removed. |
797 // GetChild(startNode, "get foo"); | 796 // GetChild(startNode, "get foo"); |
798 GetChild(startNode, "set foo"); | 797 GetChild(startNode, "set foo"); |
799 | 798 |
800 cpu_profiler->DeleteAllCpuProfiles(); | 799 cpu_profiler->DeleteAllCpuProfiles(); |
801 } | 800 } |
OLD | NEW |