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 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 | 185 |
186 | 186 |
187 RawError* Compiler::Compile(const Library& library, const Script& script) { | 187 RawError* Compiler::Compile(const Library& library, const Script& script) { |
188 LongJumpScope jump; | 188 LongJumpScope jump; |
189 if (setjmp(*jump.Set()) == 0) { | 189 if (setjmp(*jump.Set()) == 0) { |
190 Thread* const thread = Thread::Current(); | 190 Thread* const thread = Thread::Current(); |
191 StackZone zone(thread); | 191 StackZone zone(thread); |
192 if (FLAG_trace_compiler) { | 192 if (FLAG_trace_compiler) { |
193 const String& script_url = String::Handle(script.url()); | 193 const String& script_url = String::Handle(script.url()); |
194 // TODO(iposva): Extract script kind. | 194 // TODO(iposva): Extract script kind. |
195 ISL_Print("Compiling %s '%s'\n", "", script_url.ToCString()); | 195 THR_Print("Compiling %s '%s'\n", "", script_url.ToCString()); |
196 } | 196 } |
197 const String& library_key = String::Handle(library.private_key()); | 197 const String& library_key = String::Handle(library.private_key()); |
198 script.Tokenize(library_key); | 198 script.Tokenize(library_key); |
199 Parser::ParseCompilationUnit(library, script); | 199 Parser::ParseCompilationUnit(library, script); |
200 return Error::null(); | 200 return Error::null(); |
201 } else { | 201 } else { |
202 Thread* const thread = Thread::Current(); | 202 Thread* const thread = Thread::Current(); |
203 Isolate* const isolate = thread->isolate(); | 203 Isolate* const isolate = thread->isolate(); |
204 StackZone zone(thread); | 204 StackZone zone(thread); |
205 Error& error = Error::Handle(); | 205 Error& error = Error::Handle(); |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
297 // also allows us to reset the marked_for_parsing state in case we see an | 297 // also allows us to reset the marked_for_parsing state in case we see an |
298 // error. | 298 // error. |
299 VMTagScope tagScope(thread, VMTag::kCompileClassTagId); | 299 VMTagScope tagScope(thread, VMTag::kCompileClassTagId); |
300 GrowableHandlePtrArray<const Class> parse_list(thread->zone(), 4); | 300 GrowableHandlePtrArray<const Class> parse_list(thread->zone(), 4); |
301 GrowableHandlePtrArray<const Class> patch_list(thread->zone(), 4); | 301 GrowableHandlePtrArray<const Class> patch_list(thread->zone(), 4); |
302 | 302 |
303 // Parse the class and all the interfaces it implements and super classes. | 303 // Parse the class and all the interfaces it implements and super classes. |
304 LongJumpScope jump; | 304 LongJumpScope jump; |
305 if (setjmp(*jump.Set()) == 0) { | 305 if (setjmp(*jump.Set()) == 0) { |
306 if (FLAG_trace_compiler) { | 306 if (FLAG_trace_compiler) { |
307 ISL_Print("Compiling Class %s '%s'\n", "", cls.ToCString()); | 307 THR_Print("Compiling Class %s '%s'\n", "", cls.ToCString()); |
308 } | 308 } |
309 | 309 |
310 // Add the primary class which needs to be parsed to the parse list. | 310 // Add the primary class which needs to be parsed to the parse list. |
311 // Mark the class as parsed so that we don't recursively add the same | 311 // Mark the class as parsed so that we don't recursively add the same |
312 // class back into the list. | 312 // class back into the list. |
313 parse_list.Add(cls); | 313 parse_list.Add(cls); |
314 cls.set_is_marked_for_parsing(); | 314 cls.set_is_marked_for_parsing(); |
315 | 315 |
316 // Add all super classes, interface classes and patch class if one | 316 // Add all super classes, interface classes and patch class if one |
317 // exists to the corresponding lists. | 317 // exists to the corresponding lists. |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
420 new(zone) ZoneGrowableArray<const ICData*>(); | 420 new(zone) ZoneGrowableArray<const ICData*>(); |
421 if (optimized) { | 421 if (optimized) { |
422 // Extract type feedback before the graph is built, as the graph | 422 // Extract type feedback before the graph is built, as the graph |
423 // builder uses it to attach it to nodes. | 423 // builder uses it to attach it to nodes. |
424 ASSERT(function.deoptimization_counter() < | 424 ASSERT(function.deoptimization_counter() < |
425 FLAG_deoptimization_counter_threshold); | 425 FLAG_deoptimization_counter_threshold); |
426 function.RestoreICDataMap(ic_data_array); | 426 function.RestoreICDataMap(ic_data_array); |
427 if (FLAG_print_ic_data_map) { | 427 if (FLAG_print_ic_data_map) { |
428 for (intptr_t i = 0; i < ic_data_array->length(); i++) { | 428 for (intptr_t i = 0; i < ic_data_array->length(); i++) { |
429 if ((*ic_data_array)[i] != NULL) { | 429 if ((*ic_data_array)[i] != NULL) { |
430 ISL_Print("%" Pd " ", i); | 430 THR_Print("%" Pd " ", i); |
431 FlowGraphPrinter::PrintICData(*(*ic_data_array)[i]); | 431 FlowGraphPrinter::PrintICData(*(*ic_data_array)[i]); |
432 } | 432 } |
433 } | 433 } |
434 } | 434 } |
435 } | 435 } |
436 | 436 |
437 flow_graph = pipeline->BuildFlowGraph(zone, | 437 flow_graph = pipeline->BuildFlowGraph(zone, |
438 parsed_function, | 438 parsed_function, |
439 *ic_data_array, | 439 *ic_data_array, |
440 osr_id); | 440 osr_id); |
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
754 graph_compiler.FinalizeVarDescriptors(code); | 754 graph_compiler.FinalizeVarDescriptors(code); |
755 graph_compiler.FinalizeExceptionHandlers(code); | 755 graph_compiler.FinalizeExceptionHandlers(code); |
756 graph_compiler.FinalizeStaticCallTargetsTable(code); | 756 graph_compiler.FinalizeStaticCallTargetsTable(code); |
757 | 757 |
758 if (optimized) { | 758 if (optimized) { |
759 // We may not have previous code if 'always_optimize' is set. | 759 // We may not have previous code if 'always_optimize' is set. |
760 if ((osr_id == Isolate::kNoDeoptId) && function.HasCode()) { | 760 if ((osr_id == Isolate::kNoDeoptId) && function.HasCode()) { |
761 CodePatcher::PatchEntry(Code::Handle(function.CurrentCode())); | 761 CodePatcher::PatchEntry(Code::Handle(function.CurrentCode())); |
762 if (FLAG_trace_compiler || FLAG_trace_patching) { | 762 if (FLAG_trace_compiler || FLAG_trace_patching) { |
763 if (FLAG_trace_compiler) { | 763 if (FLAG_trace_compiler) { |
764 ISL_Print(" "); | 764 THR_Print(" "); |
765 } | 765 } |
766 ISL_Print("Patch unoptimized '%s' entry point %#" Px "\n", | 766 THR_Print("Patch unoptimized '%s' entry point %#" Px "\n", |
767 function.ToFullyQualifiedCString(), | 767 function.ToFullyQualifiedCString(), |
768 Code::Handle(function.unoptimized_code()).EntryPoint()); | 768 Code::Handle(function.unoptimized_code()).EntryPoint()); |
769 } | 769 } |
770 } | 770 } |
771 function.AttachCode(code); | 771 function.AttachCode(code); |
772 | 772 |
773 // Register code with the classes it depends on because of CHA. | 773 // Register code with the classes it depends on because of CHA. |
774 for (intptr_t i = 0; | 774 for (intptr_t i = 0; |
775 i < thread->cha()->leaf_classes().length(); | 775 i < thread->cha()->leaf_classes().length(); |
776 ++i) { | 776 ++i) { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
815 // Compilation failed due to an out of range branch offset in the | 815 // Compilation failed due to an out of range branch offset in the |
816 // assembler. We try again (done = false) with far branches enabled. | 816 // assembler. We try again (done = false) with far branches enabled. |
817 done = false; | 817 done = false; |
818 ASSERT(!use_far_branches); | 818 ASSERT(!use_far_branches); |
819 use_far_branches = true; | 819 use_far_branches = true; |
820 } else { | 820 } else { |
821 // If the error isn't due to an out of range branch offset, we don't | 821 // If the error isn't due to an out of range branch offset, we don't |
822 // try again (done = true), and indicate that we did not finish | 822 // try again (done = true), and indicate that we did not finish |
823 // compiling (is_compiled = false). | 823 // compiling (is_compiled = false). |
824 if (FLAG_trace_bailout) { | 824 if (FLAG_trace_bailout) { |
825 ISL_Print("%s\n", error.ToErrorCString()); | 825 THR_Print("%s\n", error.ToErrorCString()); |
826 } | 826 } |
827 done = true; | 827 done = true; |
828 ASSERT(optimized); | 828 ASSERT(optimized); |
829 } | 829 } |
830 | 830 |
831 // Clear the error if it was not a real error, but just a bailout. | 831 // Clear the error if it was not a real error, but just a bailout. |
832 if (error.IsLanguageError() && | 832 if (error.IsLanguageError() && |
833 (LanguageError::Cast(error).kind() == Report::kBailout)) { | 833 (LanguageError::Cast(error).kind() == Report::kBailout)) { |
834 isolate->object_store()->clear_sticky_error(); | 834 isolate->object_store()->clear_sticky_error(); |
835 } | 835 } |
836 is_compiled = false; | 836 is_compiled = false; |
837 } | 837 } |
838 // Reset global isolate state. | 838 // Reset global isolate state. |
839 isolate->set_deopt_id(prev_deopt_id); | 839 isolate->set_deopt_id(prev_deopt_id); |
840 } | 840 } |
841 return is_compiled; | 841 return is_compiled; |
842 } | 842 } |
843 | 843 |
844 | 844 |
845 static void DisassembleCode(const Function& function, bool optimized) { | 845 static void DisassembleCode(const Function& function, bool optimized) { |
846 const char* function_fullname = function.ToFullyQualifiedCString(); | 846 const char* function_fullname = function.ToFullyQualifiedCString(); |
847 ISL_Print("Code for %sfunction '%s' {\n", | 847 THR_Print("Code for %sfunction '%s' {\n", |
848 optimized ? "optimized " : "", | 848 optimized ? "optimized " : "", |
849 function_fullname); | 849 function_fullname); |
850 const Code& code = Code::Handle(function.CurrentCode()); | 850 const Code& code = Code::Handle(function.CurrentCode()); |
851 code.Disassemble(); | 851 code.Disassemble(); |
852 ISL_Print("}\n"); | 852 THR_Print("}\n"); |
853 | 853 |
854 ISL_Print("Pointer offsets for function: {\n"); | 854 THR_Print("Pointer offsets for function: {\n"); |
855 // Pointer offsets are stored in descending order. | 855 // Pointer offsets are stored in descending order. |
856 Object& obj = Object::Handle(); | 856 Object& obj = Object::Handle(); |
857 for (intptr_t i = code.pointer_offsets_length() - 1; i >= 0; i--) { | 857 for (intptr_t i = code.pointer_offsets_length() - 1; i >= 0; i--) { |
858 const uword addr = code.GetPointerOffsetAt(i) + code.EntryPoint(); | 858 const uword addr = code.GetPointerOffsetAt(i) + code.EntryPoint(); |
859 obj = *reinterpret_cast<RawObject**>(addr); | 859 obj = *reinterpret_cast<RawObject**>(addr); |
860 ISL_Print(" %d : %#" Px " '%s'\n", | 860 THR_Print(" %d : %#" Px " '%s'\n", |
861 code.GetPointerOffsetAt(i), addr, obj.ToCString()); | 861 code.GetPointerOffsetAt(i), addr, obj.ToCString()); |
862 } | 862 } |
863 ISL_Print("}\n"); | 863 THR_Print("}\n"); |
864 | 864 |
865 ISL_Print("PC Descriptors for function '%s' {\n", function_fullname); | 865 THR_Print("PC Descriptors for function '%s' {\n", function_fullname); |
866 PcDescriptors::PrintHeaderString(); | 866 PcDescriptors::PrintHeaderString(); |
867 const PcDescriptors& descriptors = | 867 const PcDescriptors& descriptors = |
868 PcDescriptors::Handle(code.pc_descriptors()); | 868 PcDescriptors::Handle(code.pc_descriptors()); |
869 ISL_Print("%s}\n", descriptors.ToCString()); | 869 THR_Print("%s}\n", descriptors.ToCString()); |
870 | 870 |
871 uword start = Instructions::Handle(code.instructions()).EntryPoint(); | 871 uword start = Instructions::Handle(code.instructions()).EntryPoint(); |
872 const Array& deopt_table = Array::Handle(code.deopt_info_array()); | 872 const Array& deopt_table = Array::Handle(code.deopt_info_array()); |
873 intptr_t deopt_table_length = DeoptTable::GetLength(deopt_table); | 873 intptr_t deopt_table_length = DeoptTable::GetLength(deopt_table); |
874 if (deopt_table_length > 0) { | 874 if (deopt_table_length > 0) { |
875 ISL_Print("DeoptInfo: {\n"); | 875 THR_Print("DeoptInfo: {\n"); |
876 Smi& offset = Smi::Handle(); | 876 Smi& offset = Smi::Handle(); |
877 TypedData& info = TypedData::Handle(); | 877 TypedData& info = TypedData::Handle(); |
878 Smi& reason_and_flags = Smi::Handle(); | 878 Smi& reason_and_flags = Smi::Handle(); |
879 for (intptr_t i = 0; i < deopt_table_length; ++i) { | 879 for (intptr_t i = 0; i < deopt_table_length; ++i) { |
880 DeoptTable::GetEntry(deopt_table, i, &offset, &info, &reason_and_flags); | 880 DeoptTable::GetEntry(deopt_table, i, &offset, &info, &reason_and_flags); |
881 const intptr_t reason = | 881 const intptr_t reason = |
882 DeoptTable::ReasonField::decode(reason_and_flags.Value()); | 882 DeoptTable::ReasonField::decode(reason_and_flags.Value()); |
883 ASSERT((0 <= reason) && (reason < ICData::kDeoptNumReasons)); | 883 ASSERT((0 <= reason) && (reason < ICData::kDeoptNumReasons)); |
884 ISL_Print("%4" Pd ": 0x%" Px " %s (%s)\n", | 884 THR_Print("%4" Pd ": 0x%" Px " %s (%s)\n", |
885 i, | 885 i, |
886 start + offset.Value(), | 886 start + offset.Value(), |
887 DeoptInfo::ToCString(deopt_table, info), | 887 DeoptInfo::ToCString(deopt_table, info), |
888 DeoptReasonToCString( | 888 DeoptReasonToCString( |
889 static_cast<ICData::DeoptReasonId>(reason))); | 889 static_cast<ICData::DeoptReasonId>(reason))); |
890 } | 890 } |
891 ISL_Print("}\n"); | 891 THR_Print("}\n"); |
892 } | 892 } |
893 | 893 |
894 const ObjectPool& object_pool = ObjectPool::Handle(code.GetObjectPool()); | 894 const ObjectPool& object_pool = ObjectPool::Handle(code.GetObjectPool()); |
895 object_pool.DebugPrint(); | 895 object_pool.DebugPrint(); |
896 | 896 |
897 ISL_Print("Stackmaps for function '%s' {\n", function_fullname); | 897 THR_Print("Stackmaps for function '%s' {\n", function_fullname); |
898 if (code.stackmaps() != Array::null()) { | 898 if (code.stackmaps() != Array::null()) { |
899 const Array& stackmap_table = Array::Handle(code.stackmaps()); | 899 const Array& stackmap_table = Array::Handle(code.stackmaps()); |
900 Stackmap& map = Stackmap::Handle(); | 900 Stackmap& map = Stackmap::Handle(); |
901 for (intptr_t i = 0; i < stackmap_table.Length(); ++i) { | 901 for (intptr_t i = 0; i < stackmap_table.Length(); ++i) { |
902 map ^= stackmap_table.At(i); | 902 map ^= stackmap_table.At(i); |
903 ISL_Print("%s\n", map.ToCString()); | 903 THR_Print("%s\n", map.ToCString()); |
904 } | 904 } |
905 } | 905 } |
906 ISL_Print("}\n"); | 906 THR_Print("}\n"); |
907 | 907 |
908 ISL_Print("Variable Descriptors for function '%s' {\n", | 908 THR_Print("Variable Descriptors for function '%s' {\n", |
909 function_fullname); | 909 function_fullname); |
910 const LocalVarDescriptors& var_descriptors = | 910 const LocalVarDescriptors& var_descriptors = |
911 LocalVarDescriptors::Handle(code.GetLocalVarDescriptors()); | 911 LocalVarDescriptors::Handle(code.GetLocalVarDescriptors()); |
912 intptr_t var_desc_length = | 912 intptr_t var_desc_length = |
913 var_descriptors.IsNull() ? 0 : var_descriptors.Length(); | 913 var_descriptors.IsNull() ? 0 : var_descriptors.Length(); |
914 String& var_name = String::Handle(); | 914 String& var_name = String::Handle(); |
915 for (intptr_t i = 0; i < var_desc_length; i++) { | 915 for (intptr_t i = 0; i < var_desc_length; i++) { |
916 var_name = var_descriptors.GetName(i); | 916 var_name = var_descriptors.GetName(i); |
917 RawLocalVarDescriptors::VarInfo var_info; | 917 RawLocalVarDescriptors::VarInfo var_info; |
918 var_descriptors.GetInfo(i, &var_info); | 918 var_descriptors.GetInfo(i, &var_info); |
919 const int8_t kind = var_info.kind(); | 919 const int8_t kind = var_info.kind(); |
920 if (kind == RawLocalVarDescriptors::kSavedCurrentContext) { | 920 if (kind == RawLocalVarDescriptors::kSavedCurrentContext) { |
921 ISL_Print(" saved current CTX reg offset %d\n", var_info.index()); | 921 THR_Print(" saved current CTX reg offset %d\n", var_info.index()); |
922 } else { | 922 } else { |
923 if (kind == RawLocalVarDescriptors::kContextLevel) { | 923 if (kind == RawLocalVarDescriptors::kContextLevel) { |
924 ISL_Print(" context level %d scope %d", var_info.index(), | 924 THR_Print(" context level %d scope %d", var_info.index(), |
925 var_info.scope_id); | 925 var_info.scope_id); |
926 } else if (kind == RawLocalVarDescriptors::kStackVar) { | 926 } else if (kind == RawLocalVarDescriptors::kStackVar) { |
927 ISL_Print(" stack var '%s' offset %d", | 927 THR_Print(" stack var '%s' offset %d", |
928 var_name.ToCString(), var_info.index()); | 928 var_name.ToCString(), var_info.index()); |
929 } else if (kind == RawLocalVarDescriptors::kContextVar) { | 929 } else if (kind == RawLocalVarDescriptors::kContextVar) { |
930 ISL_Print(" context var '%s' level %d offset %d", | 930 THR_Print(" context var '%s' level %d offset %d", |
931 var_name.ToCString(), var_info.scope_id, var_info.index()); | 931 var_name.ToCString(), var_info.scope_id, var_info.index()); |
932 } else { | 932 } else { |
933 ASSERT(kind == RawLocalVarDescriptors::kAsyncOperation); | 933 ASSERT(kind == RawLocalVarDescriptors::kAsyncOperation); |
934 ISL_Print(" async operation '%s' level %d offset %d", | 934 THR_Print(" async operation '%s' level %d offset %d", |
935 var_name.ToCString(), var_info.scope_id, var_info.index()); | 935 var_name.ToCString(), var_info.scope_id, var_info.index()); |
936 } | 936 } |
937 ISL_Print(" (valid %d-%d)\n", var_info.begin_pos, var_info.end_pos); | 937 THR_Print(" (valid %d-%d)\n", var_info.begin_pos, var_info.end_pos); |
938 } | 938 } |
939 } | 939 } |
940 ISL_Print("}\n"); | 940 THR_Print("}\n"); |
941 | 941 |
942 ISL_Print("Exception Handlers for function '%s' {\n", function_fullname); | 942 THR_Print("Exception Handlers for function '%s' {\n", function_fullname); |
943 const ExceptionHandlers& handlers = | 943 const ExceptionHandlers& handlers = |
944 ExceptionHandlers::Handle(code.exception_handlers()); | 944 ExceptionHandlers::Handle(code.exception_handlers()); |
945 ISL_Print("%s}\n", handlers.ToCString()); | 945 THR_Print("%s}\n", handlers.ToCString()); |
946 | 946 |
947 { | 947 { |
948 ISL_Print("Static call target functions {\n"); | 948 THR_Print("Static call target functions {\n"); |
949 const Array& table = Array::Handle(code.static_calls_target_table()); | 949 const Array& table = Array::Handle(code.static_calls_target_table()); |
950 Smi& offset = Smi::Handle(); | 950 Smi& offset = Smi::Handle(); |
951 Function& function = Function::Handle(); | 951 Function& function = Function::Handle(); |
952 Code& code = Code::Handle(); | 952 Code& code = Code::Handle(); |
953 for (intptr_t i = 0; i < table.Length(); | 953 for (intptr_t i = 0; i < table.Length(); |
954 i += Code::kSCallTableEntryLength) { | 954 i += Code::kSCallTableEntryLength) { |
955 offset ^= table.At(i + Code::kSCallTableOffsetEntry); | 955 offset ^= table.At(i + Code::kSCallTableOffsetEntry); |
956 function ^= table.At(i + Code::kSCallTableFunctionEntry); | 956 function ^= table.At(i + Code::kSCallTableFunctionEntry); |
957 code ^= table.At(i + Code::kSCallTableCodeEntry); | 957 code ^= table.At(i + Code::kSCallTableCodeEntry); |
958 if (function.IsNull()) { | 958 if (function.IsNull()) { |
959 Class& cls = Class::Handle(); | 959 Class& cls = Class::Handle(); |
960 cls ^= code.owner(); | 960 cls ^= code.owner(); |
961 if (cls.IsNull()) { | 961 if (cls.IsNull()) { |
962 const String& code_name = String::Handle(code.Name()); | 962 const String& code_name = String::Handle(code.Name()); |
963 ISL_Print(" 0x%" Px ": %s, %p\n", | 963 THR_Print(" 0x%" Px ": %s, %p\n", |
964 start + offset.Value(), | 964 start + offset.Value(), |
965 code_name.ToCString(), | 965 code_name.ToCString(), |
966 code.raw()); | 966 code.raw()); |
967 } else { | 967 } else { |
968 ISL_Print(" 0x%" Px ": allocation stub for %s, %p\n", | 968 THR_Print(" 0x%" Px ": allocation stub for %s, %p\n", |
969 start + offset.Value(), | 969 start + offset.Value(), |
970 cls.ToCString(), | 970 cls.ToCString(), |
971 code.raw()); | 971 code.raw()); |
972 } | 972 } |
973 } else { | 973 } else { |
974 ISL_Print(" 0x%" Px ": %s, %p\n", | 974 THR_Print(" 0x%" Px ": %s, %p\n", |
975 start + offset.Value(), | 975 start + offset.Value(), |
976 function.ToFullyQualifiedCString(), | 976 function.ToFullyQualifiedCString(), |
977 code.raw()); | 977 code.raw()); |
978 } | 978 } |
979 } | 979 } |
980 ISL_Print("}\n"); | 980 THR_Print("}\n"); |
981 } | 981 } |
982 if (optimized && FLAG_trace_inlining_intervals) { | 982 if (optimized && FLAG_trace_inlining_intervals) { |
983 code.DumpInlinedIntervals(); | 983 code.DumpInlinedIntervals(); |
984 } | 984 } |
985 } | 985 } |
986 | 986 |
987 | 987 |
988 #if defined(DEBUG) | 988 #if defined(DEBUG) |
989 // Verifies that the inliner is always in the list of inlined functions. | 989 // Verifies that the inliner is always in the list of inlined functions. |
990 // If this fails run with --trace-inlining-intervals to get more information. | 990 // If this fails run with --trace-inlining-intervals to get more information. |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1032 zone, Compiler::EnsureUnoptimizedCode(Thread::Current(), function)); | 1032 zone, Compiler::EnsureUnoptimizedCode(Thread::Current(), function)); |
1033 if (!error.IsNull()) { | 1033 if (!error.IsNull()) { |
1034 return error.raw(); | 1034 return error.raw(); |
1035 } | 1035 } |
1036 } | 1036 } |
1037 } | 1037 } |
1038 | 1038 |
1039 ParsedFunction* parsed_function = new(zone) ParsedFunction( | 1039 ParsedFunction* parsed_function = new(zone) ParsedFunction( |
1040 thread, Function::ZoneHandle(zone, function.raw())); | 1040 thread, Function::ZoneHandle(zone, function.raw())); |
1041 if (FLAG_trace_compiler) { | 1041 if (FLAG_trace_compiler) { |
1042 ISL_Print("Compiling %s%sfunction: '%s' @ token %" Pd ", size %" Pd "\n", | 1042 THR_Print("Compiling %s%sfunction: '%s' @ token %" Pd ", size %" Pd "\n", |
1043 (osr_id == Isolate::kNoDeoptId ? "" : "osr "), | 1043 (osr_id == Isolate::kNoDeoptId ? "" : "osr "), |
1044 (optimized ? "optimized " : ""), | 1044 (optimized ? "optimized " : ""), |
1045 function.ToFullyQualifiedCString(), | 1045 function.ToFullyQualifiedCString(), |
1046 function.token_pos(), | 1046 function.token_pos(), |
1047 (function.end_token_pos() - function.token_pos())); | 1047 (function.end_token_pos() - function.token_pos())); |
1048 } | 1048 } |
1049 INC_STAT(thread, num_functions_compiled, 1); | 1049 INC_STAT(thread, num_functions_compiled, 1); |
1050 if (optimized) { | 1050 if (optimized) { |
1051 INC_STAT(thread, num_functions_optimized, 1); | 1051 INC_STAT(thread, num_functions_optimized, 1); |
1052 } | 1052 } |
1053 { | 1053 { |
1054 HANDLESCOPE(thread); | 1054 HANDLESCOPE(thread); |
1055 const int64_t num_tokens_before = STAT_VALUE(thread, num_tokens_consumed); | 1055 const int64_t num_tokens_before = STAT_VALUE(thread, num_tokens_consumed); |
1056 pipeline->ParseFunction(parsed_function); | 1056 pipeline->ParseFunction(parsed_function); |
1057 const int64_t num_tokens_after = STAT_VALUE(thread, num_tokens_consumed); | 1057 const int64_t num_tokens_after = STAT_VALUE(thread, num_tokens_consumed); |
1058 INC_STAT(thread, | 1058 INC_STAT(thread, |
1059 num_func_tokens_compiled, | 1059 num_func_tokens_compiled, |
1060 num_tokens_after - num_tokens_before); | 1060 num_tokens_after - num_tokens_before); |
1061 } | 1061 } |
1062 | 1062 |
1063 const bool success = CompileParsedFunctionHelper(pipeline, | 1063 const bool success = CompileParsedFunctionHelper(pipeline, |
1064 parsed_function, | 1064 parsed_function, |
1065 optimized, | 1065 optimized, |
1066 osr_id); | 1066 osr_id); |
1067 if (!success) { | 1067 if (!success) { |
1068 if (optimized) { | 1068 if (optimized) { |
1069 ASSERT(!Compiler::always_optimize()); // Optimized is the only code. | 1069 ASSERT(!Compiler::always_optimize()); // Optimized is the only code. |
1070 // Optimizer bailed out. Disable optimizations and never try again. | 1070 // Optimizer bailed out. Disable optimizations and never try again. |
1071 if (FLAG_trace_compiler) { | 1071 if (FLAG_trace_compiler) { |
1072 ISL_Print("--> disabling optimizations for '%s'\n", | 1072 THR_Print("--> disabling optimizations for '%s'\n", |
1073 function.ToFullyQualifiedCString()); | 1073 function.ToFullyQualifiedCString()); |
1074 } else if (FLAG_trace_failed_optimization_attempts) { | 1074 } else if (FLAG_trace_failed_optimization_attempts) { |
1075 ISL_Print("Cannot optimize: %s\n", | 1075 THR_Print("Cannot optimize: %s\n", |
1076 function.ToFullyQualifiedCString()); | 1076 function.ToFullyQualifiedCString()); |
1077 } | 1077 } |
1078 function.SetIsOptimizable(false); | 1078 function.SetIsOptimizable(false); |
1079 return Error::null(); | 1079 return Error::null(); |
1080 } | 1080 } |
1081 UNREACHABLE(); | 1081 UNREACHABLE(); |
1082 } | 1082 } |
1083 | 1083 |
1084 per_compile_timer.Stop(); | 1084 per_compile_timer.Stop(); |
1085 | 1085 |
1086 if (FLAG_trace_compiler) { | 1086 if (FLAG_trace_compiler) { |
1087 ISL_Print("--> '%s' entry: %#" Px " size: %" Pd " time: %" Pd64 " us\n", | 1087 THR_Print("--> '%s' entry: %#" Px " size: %" Pd " time: %" Pd64 " us\n", |
1088 function.ToFullyQualifiedCString(), | 1088 function.ToFullyQualifiedCString(), |
1089 Code::Handle(function.CurrentCode()).EntryPoint(), | 1089 Code::Handle(function.CurrentCode()).EntryPoint(), |
1090 Code::Handle(function.CurrentCode()).Size(), | 1090 Code::Handle(function.CurrentCode()).Size(), |
1091 per_compile_timer.TotalElapsedTime()); | 1091 per_compile_timer.TotalElapsedTime()); |
1092 } | 1092 } |
1093 | 1093 |
1094 isolate->debugger()->NotifyCompilation(function); | 1094 isolate->debugger()->NotifyCompilation(function); |
1095 | 1095 |
1096 if (FLAG_disassemble && FlowGraphPrinter::ShouldPrint(function)) { | 1096 if (FLAG_disassemble && FlowGraphPrinter::ShouldPrint(function)) { |
1097 DisassembleCode(function, optimized); | 1097 DisassembleCode(function, optimized); |
1098 } else if (FLAG_disassemble_optimized && | 1098 } else if (FLAG_disassemble_optimized && |
1099 optimized && | 1099 optimized && |
1100 FlowGraphPrinter::ShouldPrint(function)) { | 1100 FlowGraphPrinter::ShouldPrint(function)) { |
1101 // TODO(fschneider): Print unoptimized code along with the optimized code. | 1101 // TODO(fschneider): Print unoptimized code along with the optimized code. |
1102 ISL_Print("*** BEGIN CODE\n"); | 1102 THR_Print("*** BEGIN CODE\n"); |
1103 DisassembleCode(function, true); | 1103 DisassembleCode(function, true); |
1104 ISL_Print("*** END CODE\n"); | 1104 THR_Print("*** END CODE\n"); |
1105 } | 1105 } |
1106 #if defined(DEBUG) | 1106 #if defined(DEBUG) |
1107 CheckInliningIntervals(function); | 1107 CheckInliningIntervals(function); |
1108 #endif | 1108 #endif |
1109 return Error::null(); | 1109 return Error::null(); |
1110 } else { | 1110 } else { |
1111 Thread* const thread = Thread::Current(); | 1111 Thread* const thread = Thread::Current(); |
1112 Isolate* const isolate = thread->isolate(); | 1112 Isolate* const isolate = thread->isolate(); |
1113 StackZone stack_zone(thread); | 1113 StackZone stack_zone(thread); |
1114 Error& error = Error::Handle(); | 1114 Error& error = Error::Handle(); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1163 return error.raw(); | 1163 return error.raw(); |
1164 } | 1164 } |
1165 // Since CompileFunctionHelper replaces the current code, re-attach the | 1165 // Since CompileFunctionHelper replaces the current code, re-attach the |
1166 // the original code if the function was already compiled. | 1166 // the original code if the function was already compiled. |
1167 if (!original_code.IsNull() && | 1167 if (!original_code.IsNull() && |
1168 (original_code.raw() != function.CurrentCode())) { | 1168 (original_code.raw() != function.CurrentCode())) { |
1169 function.AttachCode(original_code); | 1169 function.AttachCode(original_code); |
1170 } | 1170 } |
1171 ASSERT(function.unoptimized_code() != Object::null()); | 1171 ASSERT(function.unoptimized_code() != Object::null()); |
1172 if (FLAG_trace_compiler) { | 1172 if (FLAG_trace_compiler) { |
1173 ISL_Print("Ensure unoptimized code for %s\n", function.ToCString()); | 1173 THR_Print("Ensure unoptimized code for %s\n", function.ToCString()); |
1174 } | 1174 } |
1175 return Error::null(); | 1175 return Error::null(); |
1176 } | 1176 } |
1177 | 1177 |
1178 | 1178 |
1179 RawError* Compiler::CompileOptimizedFunction(Thread* thread, | 1179 RawError* Compiler::CompileOptimizedFunction(Thread* thread, |
1180 const Function& function, | 1180 const Function& function, |
1181 intptr_t osr_id) { | 1181 intptr_t osr_id) { |
1182 VMTagScope tagScope(thread, VMTag::kCompileOptimizedTagId); | 1182 VMTagScope tagScope(thread, VMTag::kCompileOptimizedTagId); |
1183 TIMELINE_FUNCTION_COMPILATION_DURATION(thread, | 1183 TIMELINE_FUNCTION_COMPILATION_DURATION(thread, |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1357 return Object::null(); | 1357 return Object::null(); |
1358 } | 1358 } |
1359 | 1359 |
1360 | 1360 |
1361 | 1361 |
1362 RawObject* Compiler::ExecuteOnce(SequenceNode* fragment) { | 1362 RawObject* Compiler::ExecuteOnce(SequenceNode* fragment) { |
1363 LongJumpScope jump; | 1363 LongJumpScope jump; |
1364 if (setjmp(*jump.Set()) == 0) { | 1364 if (setjmp(*jump.Set()) == 0) { |
1365 Thread* const thread = Thread::Current(); | 1365 Thread* const thread = Thread::Current(); |
1366 if (FLAG_trace_compiler) { | 1366 if (FLAG_trace_compiler) { |
1367 ISL_Print("compiling expression: "); | 1367 THR_Print("compiling expression: "); |
1368 AstPrinter::PrintNode(fragment); | 1368 AstPrinter::PrintNode(fragment); |
1369 } | 1369 } |
1370 | 1370 |
1371 // Create a dummy function object for the code generator. | 1371 // Create a dummy function object for the code generator. |
1372 // The function needs to be associated with a named Class: the interface | 1372 // The function needs to be associated with a named Class: the interface |
1373 // Function fits the bill. | 1373 // Function fits the bill. |
1374 const char* kEvalConst = "eval_const"; | 1374 const char* kEvalConst = "eval_const"; |
1375 const Function& func = Function::ZoneHandle(Function::New( | 1375 const Function& func = Function::ZoneHandle(Function::New( |
1376 String::Handle(Symbols::New(kEvalConst)), | 1376 String::Handle(Symbols::New(kEvalConst)), |
1377 RawFunction::kRegularFunction, | 1377 RawFunction::kRegularFunction, |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1416 const Object& result = | 1416 const Object& result = |
1417 PassiveObject::Handle(isolate->object_store()->sticky_error()); | 1417 PassiveObject::Handle(isolate->object_store()->sticky_error()); |
1418 isolate->object_store()->clear_sticky_error(); | 1418 isolate->object_store()->clear_sticky_error(); |
1419 return result.raw(); | 1419 return result.raw(); |
1420 } | 1420 } |
1421 UNREACHABLE(); | 1421 UNREACHABLE(); |
1422 return Object::null(); | 1422 return Object::null(); |
1423 } | 1423 } |
1424 | 1424 |
1425 } // namespace dart | 1425 } // namespace dart |
OLD | NEW |