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 |