OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/compiler.h" | 5 #include "vm/compiler.h" |
6 | 6 |
7 #include "vm/assembler.h" | 7 #include "vm/assembler.h" |
8 | 8 |
9 #include "vm/ast_printer.h" | 9 #include "vm/ast_printer.h" |
10 #include "vm/block_scheduler.h" | 10 #include "vm/block_scheduler.h" |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 | 60 |
61 DECLARE_FLAG(bool, trace_failed_optimization_attempts); | 61 DECLARE_FLAG(bool, trace_failed_optimization_attempts); |
62 DECLARE_FLAG(bool, warn_on_javascript_compatibility); | 62 DECLARE_FLAG(bool, warn_on_javascript_compatibility); |
63 DECLARE_FLAG(bool, warning_as_error); | 63 DECLARE_FLAG(bool, warning_as_error); |
64 | 64 |
65 // Compile a function. Should call only if the function has not been compiled. | 65 // Compile a function. Should call only if the function has not been compiled. |
66 // Arg0: function object. | 66 // Arg0: function object. |
67 DEFINE_RUNTIME_ENTRY(CompileFunction, 1) { | 67 DEFINE_RUNTIME_ENTRY(CompileFunction, 1) { |
68 const Function& function = Function::CheckedHandle(arguments.ArgAt(0)); | 68 const Function& function = Function::CheckedHandle(arguments.ArgAt(0)); |
69 ASSERT(!function.HasCode()); | 69 ASSERT(!function.HasCode()); |
70 const Error& error = Error::Handle(Compiler::CompileFunction(function)); | 70 const Error& error = Error::Handle(Compiler::CompileFunction(isolate, |
| 71 function)); |
71 if (!error.IsNull()) { | 72 if (!error.IsNull()) { |
72 Exceptions::PropagateError(error); | 73 Exceptions::PropagateError(error); |
73 } | 74 } |
74 } | 75 } |
75 | 76 |
76 | 77 |
77 RawError* Compiler::Compile(const Library& library, const Script& script) { | 78 RawError* Compiler::Compile(const Library& library, const Script& script) { |
78 Isolate* isolate = Isolate::Current(); | 79 Isolate* isolate = Isolate::Current(); |
79 StackZone zone(isolate); | 80 StackZone zone(isolate); |
80 LongJumpScope jump; | 81 LongJumpScope jump; |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
152 } | 153 } |
153 // If the class is already marked for parsing return immediately. | 154 // If the class is already marked for parsing return immediately. |
154 if (cls.is_marked_for_parsing()) { | 155 if (cls.is_marked_for_parsing()) { |
155 return Error::null(); | 156 return Error::null(); |
156 } | 157 } |
157 | 158 |
158 Isolate* isolate = Isolate::Current(); | 159 Isolate* isolate = Isolate::Current(); |
159 // We remember all the classes that are being compiled in these lists. This | 160 // We remember all the classes that are being compiled in these lists. This |
160 // also allows us to reset the marked_for_parsing state in case we see an | 161 // also allows us to reset the marked_for_parsing state in case we see an |
161 // error. | 162 // error. |
162 Class& parse_class = Class::Handle(); | 163 VMTagScope tagScope(isolate, VMTag::kCompileTopLevelTagId); |
| 164 Class& parse_class = Class::Handle(isolate); |
163 const GrowableObjectArray& parse_list = | 165 const GrowableObjectArray& parse_list = |
164 GrowableObjectArray::Handle(GrowableObjectArray::New(4)); | 166 GrowableObjectArray::Handle(isolate, GrowableObjectArray::New(4)); |
165 const GrowableObjectArray& patch_list = | 167 const GrowableObjectArray& patch_list = |
166 GrowableObjectArray::Handle(GrowableObjectArray::New(4)); | 168 GrowableObjectArray::Handle(isolate, GrowableObjectArray::New(4)); |
167 | 169 |
168 // Parse the class and all the interfaces it implements and super classes. | 170 // Parse the class and all the interfaces it implements and super classes. |
169 StackZone zone(isolate); | 171 StackZone zone(isolate); |
170 LongJumpScope jump; | 172 LongJumpScope jump; |
171 if (setjmp(*jump.Set()) == 0) { | 173 if (setjmp(*jump.Set()) == 0) { |
172 if (FLAG_trace_compiler) { | 174 if (FLAG_trace_compiler) { |
173 OS::Print("Compiling Class %s '%s'\n", "", cls.ToCString()); | 175 OS::Print("Compiling Class %s '%s'\n", "", cls.ToCString()); |
174 } | 176 } |
175 | 177 |
176 // Add the primary class which needs to be parsed to the parse list. | 178 // Add the primary class which needs to be parsed to the parse list. |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
221 parse_class.reset_is_marked_for_parsing(); | 223 parse_class.reset_is_marked_for_parsing(); |
222 } | 224 } |
223 } | 225 } |
224 for (intptr_t i = 0; i < patch_list.Length(); i++) { | 226 for (intptr_t i = 0; i < patch_list.Length(); i++) { |
225 parse_class ^= patch_list.At(i); | 227 parse_class ^= patch_list.At(i); |
226 if (parse_class.is_marked_for_parsing()) { | 228 if (parse_class.is_marked_for_parsing()) { |
227 parse_class.reset_is_marked_for_parsing(); | 229 parse_class.reset_is_marked_for_parsing(); |
228 } | 230 } |
229 } | 231 } |
230 | 232 |
231 Error& error = Error::Handle(); | 233 Error& error = Error::Handle(isolate); |
232 error = isolate->object_store()->sticky_error(); | 234 error = isolate->object_store()->sticky_error(); |
233 isolate->object_store()->clear_sticky_error(); | 235 isolate->object_store()->clear_sticky_error(); |
234 return error.raw(); | 236 return error.raw(); |
235 } | 237 } |
236 UNREACHABLE(); | 238 UNREACHABLE(); |
237 return Error::null(); | 239 return Error::null(); |
238 } | 240 } |
239 | 241 |
240 | 242 |
241 static void InstallUnoptimizedCode(const Function& function) { | 243 static void InstallUnoptimizedCode(const Function& function) { |
(...skipping 15 matching lines...) Expand all Loading... |
257 static bool CompileParsedFunctionHelper(ParsedFunction* parsed_function, | 259 static bool CompileParsedFunctionHelper(ParsedFunction* parsed_function, |
258 bool optimized, | 260 bool optimized, |
259 intptr_t osr_id) { | 261 intptr_t osr_id) { |
260 const Function& function = parsed_function->function(); | 262 const Function& function = parsed_function->function(); |
261 if (optimized && !function.IsOptimizable()) { | 263 if (optimized && !function.IsOptimizable()) { |
262 return false; | 264 return false; |
263 } | 265 } |
264 TimerScope timer(FLAG_compiler_stats, &CompilerStats::codegen_timer); | 266 TimerScope timer(FLAG_compiler_stats, &CompilerStats::codegen_timer); |
265 bool is_compiled = false; | 267 bool is_compiled = false; |
266 Isolate* isolate = Isolate::Current(); | 268 Isolate* isolate = Isolate::Current(); |
267 VMTagScope tagScope(isolate, VMTag::kCompileTagId); | |
268 HANDLESCOPE(isolate); | 269 HANDLESCOPE(isolate); |
269 isolate->set_cha_used(false); | 270 isolate->set_cha_used(false); |
270 | 271 |
271 // We may reattempt compilation if the function needs to be assembled using | 272 // We may reattempt compilation if the function needs to be assembled using |
272 // far branches on ARM and MIPS. In the else branch of the setjmp call, | 273 // far branches on ARM and MIPS. In the else branch of the setjmp call, |
273 // done is set to false, and use_far_branches is set to true if there is a | 274 // done is set to false, and use_far_branches is set to true if there is a |
274 // longjmp from the ARM or MIPS assemblers. In all other paths through this | 275 // longjmp from the ARM or MIPS assemblers. In all other paths through this |
275 // while loop, done is set to true. use_far_branches is always false on ia32 | 276 // while loop, done is set to true. use_far_branches is always false on ia32 |
276 // and x64. | 277 // and x64. |
277 bool done = false; | 278 bool done = false; |
(...skipping 572 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
850 // We got an error during compilation. | 851 // We got an error during compilation. |
851 error = isolate->object_store()->sticky_error(); | 852 error = isolate->object_store()->sticky_error(); |
852 isolate->object_store()->clear_sticky_error(); | 853 isolate->object_store()->clear_sticky_error(); |
853 return error.raw(); | 854 return error.raw(); |
854 } | 855 } |
855 UNREACHABLE(); | 856 UNREACHABLE(); |
856 return Error::null(); | 857 return Error::null(); |
857 } | 858 } |
858 | 859 |
859 | 860 |
860 RawError* Compiler::CompileFunction(const Function& function) { | 861 RawError* Compiler::CompileFunction(Isolate* isolate, |
| 862 const Function& function) { |
| 863 VMTagScope tagScope(isolate, VMTag::kCompileUnoptimizedTagId); |
861 return CompileFunctionHelper(function, false, Isolate::kNoDeoptId); | 864 return CompileFunctionHelper(function, false, Isolate::kNoDeoptId); |
862 } | 865 } |
863 | 866 |
864 | 867 |
865 RawError* Compiler::CompileOptimizedFunction(const Function& function, | 868 RawError* Compiler::CompileOptimizedFunction(Isolate* isolate, |
| 869 const Function& function, |
866 intptr_t osr_id) { | 870 intptr_t osr_id) { |
| 871 VMTagScope tagScope(isolate, VMTag::kCompileOptimizedTagId); |
867 return CompileFunctionHelper(function, true, osr_id); | 872 return CompileFunctionHelper(function, true, osr_id); |
868 } | 873 } |
869 | 874 |
870 | 875 |
| 876 // This is only used from unit tests. |
871 RawError* Compiler::CompileParsedFunction( | 877 RawError* Compiler::CompileParsedFunction( |
872 ParsedFunction* parsed_function) { | 878 ParsedFunction* parsed_function) { |
873 Isolate* isolate = Isolate::Current(); | 879 Isolate* isolate = Isolate::Current(); |
874 LongJumpScope jump; | 880 LongJumpScope jump; |
875 if (setjmp(*jump.Set()) == 0) { | 881 if (setjmp(*jump.Set()) == 0) { |
876 // Non-optimized code generator. | 882 // Non-optimized code generator. |
877 CompileParsedFunctionHelper(parsed_function, false, Isolate::kNoDeoptId); | 883 CompileParsedFunctionHelper(parsed_function, false, Isolate::kNoDeoptId); |
878 if (FLAG_disassemble) { | 884 if (FLAG_disassemble) { |
879 DisassembleCode(parsed_function->function(), false); | 885 DisassembleCode(parsed_function->function(), false); |
880 } | 886 } |
881 return Error::null(); | 887 return Error::null(); |
882 } else { | 888 } else { |
883 Error& error = Error::Handle(); | 889 Error& error = Error::Handle(); |
884 // We got an error during compilation. | 890 // We got an error during compilation. |
885 error = isolate->object_store()->sticky_error(); | 891 error = isolate->object_store()->sticky_error(); |
886 isolate->object_store()->clear_sticky_error(); | 892 isolate->object_store()->clear_sticky_error(); |
887 return error.raw(); | 893 return error.raw(); |
888 } | 894 } |
889 UNREACHABLE(); | 895 UNREACHABLE(); |
890 return Error::null(); | 896 return Error::null(); |
891 } | 897 } |
892 | 898 |
893 | 899 |
894 RawError* Compiler::CompileAllFunctions(const Class& cls) { | 900 RawError* Compiler::CompileAllFunctions(const Class& cls) { |
895 Error& error = Error::Handle(); | 901 Isolate* isolate = Isolate::Current(); |
896 Array& functions = Array::Handle(cls.functions()); | 902 Error& error = Error::Handle(isolate); |
897 Function& func = Function::Handle(); | 903 Array& functions = Array::Handle(isolate, cls.functions()); |
| 904 Function& func = Function::Handle(isolate); |
898 // Class dynamic lives in the vm isolate. Its array fields cannot be set to | 905 // Class dynamic lives in the vm isolate. Its array fields cannot be set to |
899 // an empty array. | 906 // an empty array. |
900 if (functions.IsNull()) { | 907 if (functions.IsNull()) { |
901 ASSERT(cls.IsDynamicClass()); | 908 ASSERT(cls.IsDynamicClass()); |
902 return error.raw(); | 909 return error.raw(); |
903 } | 910 } |
904 // Compile all the regular functions. | 911 // Compile all the regular functions. |
905 for (int i = 0; i < functions.Length(); i++) { | 912 for (int i = 0; i < functions.Length(); i++) { |
906 func ^= functions.At(i); | 913 func ^= functions.At(i); |
907 ASSERT(!func.IsNull()); | 914 ASSERT(!func.IsNull()); |
908 if (!func.HasCode() && | 915 if (!func.HasCode() && |
909 !func.is_abstract() && | 916 !func.is_abstract() && |
910 !func.IsRedirectingFactory()) { | 917 !func.IsRedirectingFactory()) { |
911 error = CompileFunction(func); | 918 error = CompileFunction(isolate, func); |
912 if (!error.IsNull()) { | 919 if (!error.IsNull()) { |
913 return error.raw(); | 920 return error.raw(); |
914 } | 921 } |
915 func.ClearCode(); | 922 func.ClearCode(); |
916 } | 923 } |
917 } | 924 } |
918 // Inner functions get added to the closures array. As part of compilation | 925 // Inner functions get added to the closures array. As part of compilation |
919 // more closures can be added to the end of the array. Compile all the | 926 // more closures can be added to the end of the array. Compile all the |
920 // closures until we have reached the end of the "worklist". | 927 // closures until we have reached the end of the "worklist". |
921 GrowableObjectArray& closures = | 928 GrowableObjectArray& closures = |
922 GrowableObjectArray::Handle(cls.closures()); | 929 GrowableObjectArray::Handle(isolate, cls.closures()); |
923 if (!closures.IsNull()) { | 930 if (!closures.IsNull()) { |
924 for (int i = 0; i < closures.Length(); i++) { | 931 for (int i = 0; i < closures.Length(); i++) { |
925 func ^= closures.At(i); | 932 func ^= closures.At(i); |
926 if (!func.HasCode()) { | 933 if (!func.HasCode()) { |
927 error = CompileFunction(func); | 934 error = CompileFunction(isolate, func); |
928 if (!error.IsNull()) { | 935 if (!error.IsNull()) { |
929 return error.raw(); | 936 return error.raw(); |
930 } | 937 } |
931 func.ClearCode(); | 938 func.ClearCode(); |
932 } | 939 } |
933 } | 940 } |
934 } | 941 } |
935 return error.raw(); | 942 return error.raw(); |
936 } | 943 } |
937 | 944 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
986 const Object& result = | 993 const Object& result = |
987 Object::Handle(isolate->object_store()->sticky_error()); | 994 Object::Handle(isolate->object_store()->sticky_error()); |
988 isolate->object_store()->clear_sticky_error(); | 995 isolate->object_store()->clear_sticky_error(); |
989 return result.raw(); | 996 return result.raw(); |
990 } | 997 } |
991 UNREACHABLE(); | 998 UNREACHABLE(); |
992 return Object::null(); | 999 return Object::null(); |
993 } | 1000 } |
994 | 1001 |
995 } // namespace dart | 1002 } // namespace dart |
OLD | NEW |