| 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 |