| 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/api.h" | 8 #include "src/api.h" |
| 9 #include "src/base/platform/semaphore.h" | 9 #include "src/base/platform/semaphore.h" |
| 10 #include "src/compiler-dispatcher/compiler-dispatcher-job.h" | 10 #include "src/compiler-dispatcher/compiler-dispatcher-job.h" |
| (...skipping 825 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 836 ASSERT_TRUE(platform.IdleTaskPending()); | 836 ASSERT_TRUE(platform.IdleTaskPending()); |
| 837 platform.ClearIdleTask(); | 837 platform.ClearIdleTask(); |
| 838 ASSERT_TRUE(platform.BackgroundTasksPending()); | 838 ASSERT_TRUE(platform.BackgroundTasksPending()); |
| 839 platform.ClearBackgroundTasks(); | 839 platform.ClearBackgroundTasks(); |
| 840 } | 840 } |
| 841 | 841 |
| 842 TEST_F(CompilerDispatcherTest, EnqueueParsed) { | 842 TEST_F(CompilerDispatcherTest, EnqueueParsed) { |
| 843 MockPlatform platform; | 843 MockPlatform platform; |
| 844 CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); | 844 CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); |
| 845 | 845 |
| 846 const char script[] = | 846 const char source[] = |
| 847 "function g() { var y = 1; function f17(x) { return x * y }; return f17; " | 847 "function g() { var y = 1; function f17(x) { return x * y }; return f17; " |
| 848 "} g();"; | 848 "} g();"; |
| 849 Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), script)); | 849 Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), source)); |
| 850 Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); | 850 Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); |
| 851 Handle<Script> script(Script::cast(shared->script()), i_isolate()); |
| 851 | 852 |
| 852 ParseInfo parse_info(shared); | 853 ParseInfo parse_info(shared); |
| 853 ASSERT_TRUE(Compiler::ParseAndAnalyze(&parse_info)); | 854 ASSERT_TRUE(Compiler::ParseAndAnalyze(&parse_info)); |
| 854 std::shared_ptr<DeferredHandles> handles; | 855 std::shared_ptr<DeferredHandles> handles; |
| 855 | 856 |
| 856 ASSERT_FALSE(dispatcher.IsEnqueued(shared)); | 857 ASSERT_FALSE(dispatcher.IsEnqueued(shared)); |
| 857 ASSERT_TRUE(dispatcher.Enqueue(shared, parse_info.literal(), | 858 ASSERT_TRUE(dispatcher.Enqueue(script, shared, parse_info.literal(), |
| 858 parse_info.zone_shared(), handles, handles)); | 859 parse_info.zone_shared(), handles, handles)); |
| 859 ASSERT_TRUE(dispatcher.IsEnqueued(shared)); | 860 ASSERT_TRUE(dispatcher.IsEnqueued(shared)); |
| 860 | 861 |
| 861 ASSERT_TRUE(dispatcher.jobs_.begin()->second->status() == | 862 ASSERT_TRUE(dispatcher.jobs_.begin()->second->status() == |
| 862 CompileJobStatus::kAnalyzed); | 863 CompileJobStatus::kAnalyzed); |
| 863 | 864 |
| 864 ASSERT_TRUE(platform.IdleTaskPending()); | 865 ASSERT_TRUE(platform.IdleTaskPending()); |
| 865 platform.ClearIdleTask(); | 866 platform.ClearIdleTask(); |
| 866 ASSERT_FALSE(platform.BackgroundTasksPending()); | 867 ASSERT_FALSE(platform.BackgroundTasksPending()); |
| 867 } | 868 } |
| 868 | 869 |
| 869 TEST_F(CompilerDispatcherTest, EnqueueAndStepParsed) { | 870 TEST_F(CompilerDispatcherTest, EnqueueAndStepParsed) { |
| 870 MockPlatform platform; | 871 MockPlatform platform; |
| 871 CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); | 872 CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); |
| 872 | 873 |
| 873 const char script[] = | 874 const char source[] = |
| 874 "function g() { var y = 1; function f18(x) { return x * y }; return f18; " | 875 "function g() { var y = 1; function f18(x) { return x * y }; return f18; " |
| 875 "} g();"; | 876 "} g();"; |
| 876 Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), script)); | 877 Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), source)); |
| 877 Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); | 878 Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); |
| 879 Handle<Script> script(Script::cast(shared->script()), i_isolate()); |
| 878 | 880 |
| 879 ParseInfo parse_info(shared); | 881 ParseInfo parse_info(shared); |
| 880 ASSERT_TRUE(Compiler::ParseAndAnalyze(&parse_info)); | 882 ASSERT_TRUE(Compiler::ParseAndAnalyze(&parse_info)); |
| 881 std::shared_ptr<DeferredHandles> handles; | 883 std::shared_ptr<DeferredHandles> handles; |
| 882 | 884 |
| 883 ASSERT_FALSE(dispatcher.IsEnqueued(shared)); | 885 ASSERT_FALSE(dispatcher.IsEnqueued(shared)); |
| 884 ASSERT_TRUE(dispatcher.EnqueueAndStep(shared, parse_info.literal(), | 886 ASSERT_TRUE(dispatcher.EnqueueAndStep(script, shared, parse_info.literal(), |
| 885 parse_info.zone_shared(), handles, | 887 parse_info.zone_shared(), handles, |
| 886 handles)); | 888 handles)); |
| 887 ASSERT_TRUE(dispatcher.IsEnqueued(shared)); | 889 ASSERT_TRUE(dispatcher.IsEnqueued(shared)); |
| 888 | 890 |
| 889 ASSERT_TRUE(dispatcher.jobs_.begin()->second->status() == | 891 ASSERT_TRUE(dispatcher.jobs_.begin()->second->status() == |
| 890 CompileJobStatus::kReadyToCompile); | 892 CompileJobStatus::kReadyToCompile); |
| 891 | 893 |
| 892 ASSERT_TRUE(platform.IdleTaskPending()); | 894 ASSERT_TRUE(platform.IdleTaskPending()); |
| 893 ASSERT_TRUE(platform.BackgroundTasksPending()); | 895 ASSERT_TRUE(platform.BackgroundTasksPending()); |
| 894 platform.ClearIdleTask(); | 896 platform.ClearIdleTask(); |
| 895 platform.ClearBackgroundTasks(); | 897 platform.ClearBackgroundTasks(); |
| 896 } | 898 } |
| 897 | 899 |
| 898 TEST_F(CompilerDispatcherTest, FinishAllNow) { | |
| 899 MockPlatform platform; | |
| 900 CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); | |
| 901 | |
| 902 const char script1[] = | |
| 903 "function g() { var y = 1; function f19(x) { return x + y }; return f19; " | |
| 904 "} g();"; | |
| 905 Handle<JSFunction> f1 = Handle<JSFunction>::cast(RunJS(isolate(), script1)); | |
| 906 Handle<SharedFunctionInfo> shared1(f1->shared(), i_isolate()); | |
| 907 | |
| 908 const char script2[] = | |
| 909 "function g() { var y = 1; function f20(x) { return x * y }; return f20; " | |
| 910 "} g();"; | |
| 911 Handle<JSFunction> f2 = Handle<JSFunction>::cast(RunJS(isolate(), script2)); | |
| 912 Handle<SharedFunctionInfo> shared2(f2->shared(), i_isolate()); | |
| 913 | |
| 914 ASSERT_FALSE(shared1->is_compiled()); | |
| 915 ASSERT_FALSE(shared2->is_compiled()); | |
| 916 | |
| 917 // Enqueue shared1 as already parsed. | |
| 918 ParseInfo parse_info(shared1); | |
| 919 ASSERT_TRUE(Compiler::ParseAndAnalyze(&parse_info)); | |
| 920 std::shared_ptr<DeferredHandles> handles; | |
| 921 ASSERT_TRUE(dispatcher.Enqueue(shared1, parse_info.literal(), | |
| 922 parse_info.zone_shared(), handles, handles)); | |
| 923 | |
| 924 // Enqueue shared2 for parsing and compiling | |
| 925 ASSERT_TRUE(dispatcher.Enqueue(shared2)); | |
| 926 | |
| 927 ASSERT_TRUE(dispatcher.FinishAllNow()); | |
| 928 | |
| 929 // Finishing removes the SFI from the queue. | |
| 930 ASSERT_FALSE(dispatcher.IsEnqueued(shared1)); | |
| 931 ASSERT_FALSE(dispatcher.IsEnqueued(shared2)); | |
| 932 ASSERT_TRUE(shared1->is_compiled()); | |
| 933 ASSERT_TRUE(shared2->is_compiled()); | |
| 934 ASSERT_TRUE(platform.IdleTaskPending()); | |
| 935 platform.ClearIdleTask(); | |
| 936 } | |
| 937 | |
| 938 TEST_F(CompilerDispatcherTest, CompileParsedOutOfScope) { | 900 TEST_F(CompilerDispatcherTest, CompileParsedOutOfScope) { |
| 939 MockPlatform platform; | 901 MockPlatform platform; |
| 940 CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); | 902 CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size); |
| 941 | 903 |
| 942 const char script[] = | 904 const char source[] = |
| 943 "function g() { var y = 1; function f20(x) { return x + y }; return f20; " | 905 "function g() { var y = 1; function f20(x) { return x + y }; return f20; " |
| 944 "} g();"; | 906 "} g();"; |
| 945 Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), script)); | 907 Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), source)); |
| 946 Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); | 908 Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); |
| 909 Handle<Script> script(Script::cast(shared->script()), i_isolate()); |
| 947 | 910 |
| 948 { | 911 { |
| 949 HandleScope scope(i_isolate()); // Create handles scope for parsing. | 912 HandleScope scope(i_isolate()); // Create handles scope for parsing. |
| 950 | 913 |
| 951 ASSERT_FALSE(shared->is_compiled()); | 914 ASSERT_FALSE(shared->is_compiled()); |
| 952 ParseInfo parse_info(shared); | 915 ParseInfo parse_info(shared); |
| 953 | 916 |
| 954 ASSERT_TRUE(parsing::ParseAny(&parse_info)); | 917 ASSERT_TRUE(parsing::ParseAny(&parse_info)); |
| 955 DeferredHandleScope handles_scope(i_isolate()); | 918 DeferredHandleScope handles_scope(i_isolate()); |
| 956 { ASSERT_TRUE(Compiler::Analyze(&parse_info)); } | 919 { ASSERT_TRUE(Compiler::Analyze(&parse_info)); } |
| 957 std::shared_ptr<DeferredHandles> compilation_handles( | 920 std::shared_ptr<DeferredHandles> compilation_handles( |
| 958 handles_scope.Detach()); | 921 handles_scope.Detach()); |
| 959 | 922 |
| 960 ASSERT_FALSE(platform.IdleTaskPending()); | 923 ASSERT_FALSE(platform.IdleTaskPending()); |
| 961 ASSERT_TRUE(dispatcher.Enqueue( | 924 ASSERT_TRUE(dispatcher.Enqueue( |
| 962 shared, parse_info.literal(), parse_info.zone_shared(), | 925 script, shared, parse_info.literal(), parse_info.zone_shared(), |
| 963 parse_info.deferred_handles(), compilation_handles)); | 926 parse_info.deferred_handles(), compilation_handles)); |
| 964 ASSERT_TRUE(platform.IdleTaskPending()); | 927 ASSERT_TRUE(platform.IdleTaskPending()); |
| 965 } | 928 } |
| 966 // Exit the handles scope and destroy ParseInfo before running the idle task. | 929 // Exit the handles scope and destroy ParseInfo before running the idle task. |
| 967 | 930 |
| 968 // Since time doesn't progress on the MockPlatform, this is enough idle time | 931 // Since time doesn't progress on the MockPlatform, this is enough idle time |
| 969 // to finish compiling the function. | 932 // to finish compiling the function. |
| 970 platform.RunIdleTask(1000.0, 0.0); | 933 platform.RunIdleTask(1000.0, 0.0); |
| 971 | 934 |
| 972 ASSERT_FALSE(dispatcher.IsEnqueued(shared)); | 935 ASSERT_FALSE(dispatcher.IsEnqueued(shared)); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1026 { ASSERT_TRUE(Compiler::Analyze(&parse_info)); } | 989 { ASSERT_TRUE(Compiler::Analyze(&parse_info)); } |
| 1027 std::shared_ptr<DeferredHandles> compilation_handles( | 990 std::shared_ptr<DeferredHandles> compilation_handles( |
| 1028 handles_scope.Detach()); | 991 handles_scope.Detach()); |
| 1029 | 992 |
| 1030 shared = i_isolate()->factory()->NewSharedFunctionInfoForLiteral( | 993 shared = i_isolate()->factory()->NewSharedFunctionInfoForLiteral( |
| 1031 parse_info.literal(), script); | 994 parse_info.literal(), script); |
| 1032 parse_info.set_shared_info(shared); | 995 parse_info.set_shared_info(shared); |
| 1033 | 996 |
| 1034 ASSERT_FALSE(platform.IdleTaskPending()); | 997 ASSERT_FALSE(platform.IdleTaskPending()); |
| 1035 ASSERT_TRUE(dispatcher.Enqueue( | 998 ASSERT_TRUE(dispatcher.Enqueue( |
| 1036 shared, parse_info.literal(), parse_info.zone_shared(), | 999 script, shared, parse_info.literal(), parse_info.zone_shared(), |
| 1037 parse_info.deferred_handles(), compilation_handles)); | 1000 parse_info.deferred_handles(), compilation_handles)); |
| 1038 ASSERT_TRUE(platform.IdleTaskPending()); | 1001 ASSERT_TRUE(platform.IdleTaskPending()); |
| 1039 } | 1002 } |
| 1040 // Exit the context scope before running the idle task. | 1003 // Exit the context scope before running the idle task. |
| 1041 | 1004 |
| 1042 // Since time doesn't progress on the MockPlatform, this is enough idle time | 1005 // Since time doesn't progress on the MockPlatform, this is enough idle time |
| 1043 // to finish compiling the function. | 1006 // to finish compiling the function. |
| 1044 platform.RunIdleTask(1000.0, 0.0); | 1007 platform.RunIdleTask(1000.0, 0.0); |
| 1045 | 1008 |
| 1046 ASSERT_FALSE(dispatcher.IsEnqueued(shared)); | 1009 ASSERT_FALSE(dispatcher.IsEnqueued(shared)); |
| 1047 ASSERT_TRUE(shared->is_compiled()); | 1010 ASSERT_TRUE(shared->is_compiled()); |
| 1048 } | 1011 } |
| 1049 | 1012 |
| 1013 TEST_F(CompilerDispatcherTest, CompileLazyFinishesDispatcherJob) { |
| 1014 // Use the real dispatcher so that CompileLazy checks the same one for |
| 1015 // enqueued functions. |
| 1016 CompilerDispatcher* dispatcher = i_isolate()->compiler_dispatcher(); |
| 1017 |
| 1018 const char source[] = |
| 1019 "function g() { var y = 1; function f16(x) { return x * y }; return f16; " |
| 1020 "} g();"; |
| 1021 Handle<JSFunction> f = Handle<JSFunction>::cast(RunJS(isolate(), source)); |
| 1022 Handle<SharedFunctionInfo> shared(f->shared(), i_isolate()); |
| 1023 |
| 1024 ASSERT_FALSE(shared->is_compiled()); |
| 1025 ASSERT_FALSE(dispatcher->IsEnqueued(shared)); |
| 1026 ASSERT_TRUE(dispatcher->Enqueue(shared)); |
| 1027 ASSERT_TRUE(dispatcher->IsEnqueued(shared)); |
| 1028 |
| 1029 // Now force the function to run and ensure CompileLazy finished and dequeues |
| 1030 // it from the dispatcher. |
| 1031 RunJS(isolate(), "g()();"); |
| 1032 ASSERT_TRUE(shared->is_compiled()); |
| 1033 ASSERT_FALSE(dispatcher->IsEnqueued(shared)); |
| 1034 } |
| 1035 |
| 1036 TEST_F(CompilerDispatcherTest, CompileLazy2FinishesDispatcherJob) { |
| 1037 // Use the real dispatcher so that CompileLazy checks the same one for |
| 1038 // enqueued functions. |
| 1039 CompilerDispatcher* dispatcher = i_isolate()->compiler_dispatcher(); |
| 1040 |
| 1041 const char source2[] = "function lazy2() { return 42; }; lazy2;"; |
| 1042 Handle<JSFunction> lazy2 = |
| 1043 Handle<JSFunction>::cast(RunJS(isolate(), source2)); |
| 1044 Handle<SharedFunctionInfo> shared2(lazy2->shared(), i_isolate()); |
| 1045 ASSERT_FALSE(shared2->is_compiled()); |
| 1046 |
| 1047 const char source1[] = "function lazy1() { return lazy2(); }; lazy1;"; |
| 1048 Handle<JSFunction> lazy1 = |
| 1049 Handle<JSFunction>::cast(RunJS(isolate(), source1)); |
| 1050 Handle<SharedFunctionInfo> shared1(lazy1->shared(), i_isolate()); |
| 1051 ASSERT_FALSE(shared1->is_compiled()); |
| 1052 |
| 1053 ASSERT_TRUE(dispatcher->Enqueue(shared1)); |
| 1054 ASSERT_TRUE(dispatcher->Enqueue(shared2)); |
| 1055 |
| 1056 RunJS(isolate(), "lazy1();"); |
| 1057 ASSERT_TRUE(shared1->is_compiled()); |
| 1058 ASSERT_TRUE(shared2->is_compiled()); |
| 1059 ASSERT_FALSE(dispatcher->IsEnqueued(shared1)); |
| 1060 ASSERT_FALSE(dispatcher->IsEnqueued(shared2)); |
| 1061 } |
| 1062 |
| 1050 } // namespace internal | 1063 } // namespace internal |
| 1051 } // namespace v8 | 1064 } // namespace v8 |
| OLD | NEW |