Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler-dispatcher/compiler-dispatcher.h" | 5 #include "src/compiler-dispatcher/compiler-dispatcher.h" |
| 6 | 6 |
| 7 #include "include/v8-platform.h" | 7 #include "include/v8-platform.h" |
| 8 #include "src/base/platform/semaphore.h" | 8 #include "src/base/platform/semaphore.h" |
| 9 #include "src/compiler-dispatcher/compiler-dispatcher-job.h" | 9 #include "src/compiler-dispatcher/compiler-dispatcher-job.h" |
| 10 #include "src/compiler-dispatcher/compiler-dispatcher-tracer.h" | 10 #include "src/compiler-dispatcher/compiler-dispatcher-tracer.h" |
| (...skipping 791 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 802 ASSERT_TRUE(platform.IdleTaskPending()); | 802 ASSERT_TRUE(platform.IdleTaskPending()); |
| 803 platform.ClearIdleTask(); | 803 platform.ClearIdleTask(); |
| 804 ASSERT_TRUE(platform.BackgroundTasksPending()); | 804 ASSERT_TRUE(platform.BackgroundTasksPending()); |
| 805 platform.ClearBackgroundTasks(); | 805 platform.ClearBackgroundTasks(); |
| 806 } | 806 } |
| 807 | 807 |
| 808 TEST_F(CompilerDispatcherTest, EnqueueParsed) { | 808 TEST_F(CompilerDispatcherTest, EnqueueParsed) { |
| 809 MockPlatform platform; | 809 MockPlatform platform; |
| 810 CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); | 810 CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); |
| 811 | 811 |
| 812 const char script[] = | 812 const char source[] = |
| 813 "function g() { var y = 1; function f17(x) { return x * y }; return f17; " | 813 "function g() { var y = 1; function f17(x) { return x * y }; return f17; " |
| 814 "} g();"; | 814 "} g();"; |
| 815 Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), script)); | 815 Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), source)); |
| 816 Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); | 816 Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); |
| 817 Handle<Script> script(Script::cast(shared->script()), i_isolate()); | |
| 817 | 818 |
| 818 ParseInfo parse_info(shared); | 819 ParseInfo parse_info(shared); |
| 819 ASSERT_TRUE(Compiler::ParseAndAnalyze(&parse_info)); | 820 ASSERT_TRUE(Compiler::ParseAndAnalyze(&parse_info)); |
| 820 std::shared_ptr<DeferredHandles> handles; | 821 std::shared_ptr<DeferredHandles> handles; |
| 821 | 822 |
| 822 ASSERT_FALSE(dispatcher.IsEnqueued(shared)); | 823 ASSERT_FALSE(dispatcher.IsEnqueued(shared)); |
| 823 ASSERT_TRUE(dispatcher.Enqueue(shared, parse_info.literal(), | 824 ASSERT_TRUE(dispatcher.Enqueue(script, shared, parse_info.literal(), |
| 824 parse_info.zone_shared(), handles, handles)); | 825 parse_info.zone_shared(), handles, handles)); |
| 825 ASSERT_TRUE(dispatcher.IsEnqueued(shared)); | 826 ASSERT_TRUE(dispatcher.IsEnqueued(shared)); |
| 826 | 827 |
| 827 ASSERT_TRUE(dispatcher.jobs_.begin()->second->status() == | 828 ASSERT_TRUE(dispatcher.jobs_.begin()->second->status() == |
| 828 CompileJobStatus::kAnalyzed); | 829 CompileJobStatus::kAnalyzed); |
| 829 | 830 |
| 830 ASSERT_TRUE(platform.IdleTaskPending()); | 831 ASSERT_TRUE(platform.IdleTaskPending()); |
| 831 platform.ClearIdleTask(); | 832 platform.ClearIdleTask(); |
| 832 ASSERT_FALSE(platform.BackgroundTasksPending()); | 833 ASSERT_FALSE(platform.BackgroundTasksPending()); |
| 833 } | 834 } |
| 834 | 835 |
| 835 TEST_F(CompilerDispatcherTest, EnqueueAndStepParsed) { | 836 TEST_F(CompilerDispatcherTest, EnqueueAndStepParsed) { |
| 836 MockPlatform platform; | 837 MockPlatform platform; |
| 837 CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); | 838 CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); |
| 838 | 839 |
| 839 const char script[] = | 840 const char source[] = |
| 840 "function g() { var y = 1; function f18(x) { return x * y }; return f18; " | 841 "function g() { var y = 1; function f18(x) { return x * y }; return f18; " |
| 841 "} g();"; | 842 "} g();"; |
| 842 Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), script)); | 843 Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), source)); |
| 843 Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); | 844 Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); |
| 845 Handle<Script> script(Script::cast(shared->script()), i_isolate()); | |
| 844 | 846 |
| 845 ParseInfo parse_info(shared); | 847 ParseInfo parse_info(shared); |
| 846 ASSERT_TRUE(Compiler::ParseAndAnalyze(&parse_info)); | 848 ASSERT_TRUE(Compiler::ParseAndAnalyze(&parse_info)); |
| 847 std::shared_ptr<DeferredHandles> handles; | 849 std::shared_ptr<DeferredHandles> handles; |
| 848 | 850 |
| 849 ASSERT_FALSE(dispatcher.IsEnqueued(shared)); | 851 ASSERT_FALSE(dispatcher.IsEnqueued(shared)); |
| 850 ASSERT_TRUE(dispatcher.EnqueueAndStep(shared, parse_info.literal(), | 852 ASSERT_TRUE(dispatcher.EnqueueAndStep(script, shared, parse_info.literal(), |
| 851 parse_info.zone_shared(), handles, | 853 parse_info.zone_shared(), handles, |
| 852 handles)); | 854 handles)); |
| 853 ASSERT_TRUE(dispatcher.IsEnqueued(shared)); | 855 ASSERT_TRUE(dispatcher.IsEnqueued(shared)); |
| 854 | 856 |
| 855 ASSERT_TRUE(dispatcher.jobs_.begin()->second->status() == | 857 ASSERT_TRUE(dispatcher.jobs_.begin()->second->status() == |
| 856 CompileJobStatus::kReadyToCompile); | 858 CompileJobStatus::kReadyToCompile); |
| 857 | 859 |
| 858 ASSERT_TRUE(platform.IdleTaskPending()); | 860 ASSERT_TRUE(platform.IdleTaskPending()); |
| 859 ASSERT_TRUE(platform.BackgroundTasksPending()); | 861 ASSERT_TRUE(platform.BackgroundTasksPending()); |
| 860 platform.ClearIdleTask(); | 862 platform.ClearIdleTask(); |
| 861 platform.ClearBackgroundTasks(); | 863 platform.ClearBackgroundTasks(); |
| 862 } | 864 } |
| 863 | 865 |
| 864 TEST_F(CompilerDispatcherTest, FinishAllNow) { | |
| 865 MockPlatform platform; | |
| 866 CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); | |
| 867 | |
| 868 const char script1[] = | |
| 869 "function g() { var y = 1; function f19(x) { return x + y }; return f19; " | |
| 870 "} g();"; | |
| 871 Handle<JSFunction> f1 = Handle<JSFunction>::cast(RunJS(isolate(), script1)); | |
| 872 Handle<SharedFunctionInfo> shared1(f1->shared(), i_isolate()); | |
| 873 | |
| 874 const char script2[] = | |
| 875 "function g() { var y = 1; function f20(x) { return x * y }; return f20; " | |
| 876 "} g();"; | |
| 877 Handle<JSFunction> f2 = Handle<JSFunction>::cast(RunJS(isolate(), script2)); | |
| 878 Handle<SharedFunctionInfo> shared2(f2->shared(), i_isolate()); | |
| 879 | |
| 880 ASSERT_FALSE(shared1->is_compiled()); | |
| 881 ASSERT_FALSE(shared2->is_compiled()); | |
| 882 | |
| 883 // Enqueue shared1 as already parsed. | |
| 884 ParseInfo parse_info(shared1); | |
| 885 ASSERT_TRUE(Compiler::ParseAndAnalyze(&parse_info)); | |
| 886 std::shared_ptr<DeferredHandles> handles; | |
| 887 ASSERT_TRUE(dispatcher.Enqueue(shared1, parse_info.literal(), | |
| 888 parse_info.zone_shared(), handles, handles)); | |
| 889 | |
| 890 // Enqueue shared2 for parsing and compiling | |
| 891 ASSERT_TRUE(dispatcher.Enqueue(shared2)); | |
| 892 | |
| 893 ASSERT_TRUE(dispatcher.FinishAllNow()); | |
| 894 | |
| 895 // Finishing removes the SFI from the queue. | |
| 896 ASSERT_FALSE(dispatcher.IsEnqueued(shared1)); | |
| 897 ASSERT_FALSE(dispatcher.IsEnqueued(shared2)); | |
| 898 ASSERT_TRUE(shared1->is_compiled()); | |
| 899 ASSERT_TRUE(shared2->is_compiled()); | |
| 900 ASSERT_TRUE(platform.IdleTaskPending()); | |
| 901 platform.ClearIdleTask(); | |
| 902 } | |
| 903 | |
| 904 TEST_F(CompilerDispatcherTest, CompileParsedOutOfScope) { | 866 TEST_F(CompilerDispatcherTest, CompileParsedOutOfScope) { |
| 905 MockPlatform platform; | 867 MockPlatform platform; |
| 906 CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); | 868 CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); |
| 907 Local<v8::Context> context = v8::Context::New(isolate()); | 869 Local<v8::Context> context = v8::Context::New(isolate()); |
| 908 | 870 |
| 909 const char script[] = | 871 const char source[] = |
| 910 "function g() { var y = 1; function f20(x) { return x + y }; return f20; " | 872 "function g() { var y = 1; function f20(x) { return x + y }; return f20; " |
| 911 "} g();"; | 873 "} g();"; |
| 912 Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), script)); | 874 Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), source)); |
| 913 Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); | 875 Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); |
| 876 Handle<Script> script(Script::cast(shared->script()), i_isolate()); | |
| 914 | 877 |
| 915 { | 878 { |
| 916 HandleScope scope(i_isolate()); // Create handles scope for parsing. | 879 HandleScope scope(i_isolate()); // Create handles scope for parsing. |
| 917 | 880 |
| 918 ASSERT_FALSE(shared->is_compiled()); | 881 ASSERT_FALSE(shared->is_compiled()); |
| 919 ParseInfo parse_info(shared); | 882 ParseInfo parse_info(shared); |
| 920 | 883 |
| 921 ASSERT_TRUE(parsing::ParseAny(&parse_info)); | 884 ASSERT_TRUE(parsing::ParseAny(&parse_info)); |
| 922 DeferredHandleScope handles_scope(i_isolate()); | 885 DeferredHandleScope handles_scope(i_isolate()); |
| 923 { ASSERT_TRUE(Compiler::Analyze(&parse_info)); } | 886 { ASSERT_TRUE(Compiler::Analyze(&parse_info)); } |
| 924 std::shared_ptr<DeferredHandles> compilation_handles( | 887 std::shared_ptr<DeferredHandles> compilation_handles( |
| 925 handles_scope.Detach()); | 888 handles_scope.Detach()); |
| 926 | 889 |
| 927 ASSERT_FALSE(platform.IdleTaskPending()); | 890 ASSERT_FALSE(platform.IdleTaskPending()); |
| 928 ASSERT_TRUE(dispatcher.Enqueue( | 891 ASSERT_TRUE(dispatcher.Enqueue( |
| 929 shared, parse_info.literal(), parse_info.zone_shared(), | 892 script, shared, parse_info.literal(), parse_info.zone_shared(), |
| 930 parse_info.deferred_handles(), compilation_handles)); | 893 parse_info.deferred_handles(), compilation_handles)); |
| 931 ASSERT_TRUE(platform.IdleTaskPending()); | 894 ASSERT_TRUE(platform.IdleTaskPending()); |
| 932 } | 895 } |
| 933 // Exit the handles scope and destroy ParseInfo before running the idle task. | 896 // Exit the handles scope and destroy ParseInfo before running the idle task. |
| 934 | 897 |
| 935 // Since time doesn't progress on the MockPlatform, this is enough idle time | 898 // Since time doesn't progress on the MockPlatform, this is enough idle time |
| 936 // to finish compiling the function. | 899 // to finish compiling the function. |
| 937 platform.RunIdleTask(1000.0, 0.0); | 900 platform.RunIdleTask(1000.0, 0.0); |
| 938 | 901 |
| 939 ASSERT_FALSE(dispatcher.IsEnqueued(shared)); | 902 ASSERT_FALSE(dispatcher.IsEnqueued(shared)); |
| 940 ASSERT_TRUE(shared->is_compiled()); | 903 ASSERT_TRUE(shared->is_compiled()); |
| 941 } | 904 } |
| 942 | 905 |
| 906 TEST_F(CompilerDispatcherTest, CompileLazyFinishesDispatcherJob) { | |
| 907 // Use the real dispatcher so that CompileLazy checks the same one for | |
| 908 // enqueued functions. | |
| 909 CompilerDispatcher* dispatcher = i_isolate()->compiler_dispatcher(); | |
| 910 | |
| 911 const char source[] = | |
| 912 "function g() { var y = 1; function f16(x) { return x * y }; return f16; " | |
| 913 "} g();"; | |
| 914 Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), source)); | |
| 915 Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); | |
| 916 | |
| 917 ASSERT_FALSE(shared->is_compiled()); | |
| 918 ASSERT_FALSE(dispatcher->IsEnqueued(shared)); | |
| 919 ASSERT_TRUE(dispatcher->Enqueue(shared)); | |
| 920 ASSERT_TRUE(dispatcher->IsEnqueued(shared)); | |
| 921 | |
| 922 // Now force the function to run and ensure CompileLazy finished and dequeues | |
| 923 // it from the dispatcher. | |
| 924 RunJS(isolate(), "g()();"); | |
| 925 ASSERT_TRUE(shared->is_compiled()); | |
| 926 ASSERT_FALSE(dispatcher->IsEnqueued(shared)); | |
| 927 } | |
| 928 | |
| 929 TEST_F(CompilerDispatcherTest, CompileLazy2FinishesDispatcherJob) { | |
| 930 // Use the real dispatcher so that CompileLazy checks the same one for | |
| 931 // enqueued functions. | |
| 932 CompilerDispatcher* dispatcher = i_isolate()->compiler_dispatcher(); | |
| 933 | |
| 934 const char source2[] = | |
| 935 "var lazy2 = (function() {" | |
| 936 " var y = 42; " | |
|
rmcilroy
2017/02/10 11:21:16
Jochen, as discussed offline, I've had to add this
rmcilroy
2017/02/10 16:15:36
As discussed offline, changed the DCHECK to !share
| |
| 937 " return function lazy2() { return y; };" | |
| 938 "})();" | |
| 939 "lazy2;"; | |
| 940 Handle<JSFunction> lazy2 = | |
| 941 Handle<JSFunction>::cast(RunJS(isolate(), source2)); | |
| 942 Handle<SharedFunctionInfo> shared2(lazy2->shared(), i_isolate()); | |
| 943 ASSERT_FALSE(shared2->is_compiled()); | |
| 944 | |
| 945 const char source1[] = | |
| 946 "var lazy1 = (function() {" | |
| 947 " var y = 0; " | |
| 948 " return function lazy1() { return lazy2() - y; };" | |
| 949 "})();" | |
| 950 "lazy1;"; | |
| 951 Handle<JSFunction> lazy1 = | |
| 952 Handle<JSFunction>::cast(RunJS(isolate(), source1)); | |
| 953 Handle<SharedFunctionInfo> shared1(lazy1->shared(), i_isolate()); | |
| 954 ASSERT_FALSE(shared1->is_compiled()); | |
| 955 | |
| 956 ASSERT_TRUE(dispatcher->Enqueue(shared1)); | |
| 957 ASSERT_TRUE(dispatcher->Enqueue(shared2)); | |
| 958 | |
| 959 RunJS(isolate(), "lazy1();"); | |
| 960 ASSERT_TRUE(shared1->is_compiled()); | |
| 961 ASSERT_TRUE(shared2->is_compiled()); | |
| 962 ASSERT_FALSE(dispatcher->IsEnqueued(shared1)); | |
| 963 ASSERT_FALSE(dispatcher->IsEnqueued(shared2)); | |
| 964 } | |
| 965 | |
| 943 } // namespace internal | 966 } // namespace internal |
| 944 } // namespace v8 | 967 } // namespace v8 |
| OLD | NEW |