Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(212)

Side by Side Diff: runtime/vm/compiler.cc

Issue 1454553004: Create code and instruction object, and install them in the background compilation thread while br… (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: c Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 17 matching lines...) Expand all
28 #include "vm/longjump.h" 28 #include "vm/longjump.h"
29 #include "vm/object.h" 29 #include "vm/object.h"
30 #include "vm/object_store.h" 30 #include "vm/object_store.h"
31 #include "vm/os.h" 31 #include "vm/os.h"
32 #include "vm/parser.h" 32 #include "vm/parser.h"
33 #include "vm/regexp_parser.h" 33 #include "vm/regexp_parser.h"
34 #include "vm/regexp_assembler.h" 34 #include "vm/regexp_assembler.h"
35 #include "vm/scanner.h" 35 #include "vm/scanner.h"
36 #include "vm/symbols.h" 36 #include "vm/symbols.h"
37 #include "vm/tags.h" 37 #include "vm/tags.h"
38 #include "vm/thread_registry.h"
38 #include "vm/timer.h" 39 #include "vm/timer.h"
39 40
40 namespace dart { 41 namespace dart {
41 42
42 DEFINE_FLAG(bool, allocation_sinking, true, 43 DEFINE_FLAG(bool, allocation_sinking, true,
43 "Attempt to sink temporary allocations to side exits"); 44 "Attempt to sink temporary allocations to side exits");
44 DEFINE_FLAG(bool, common_subexpression_elimination, true, 45 DEFINE_FLAG(bool, common_subexpression_elimination, true,
45 "Do common subexpression elimination."); 46 "Do common subexpression elimination.");
46 DEFINE_FLAG(bool, constant_propagation, true, 47 DEFINE_FLAG(bool, constant_propagation, true,
47 "Do conditional constant propagation/unreachable code elimination."); 48 "Do conditional constant propagation/unreachable code elimination.");
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after
383 return Error::null(); 384 return Error::null();
384 } 385 }
385 386
386 387
387 // Return false if bailed out. 388 // Return false if bailed out.
388 // If optimized_result_code is not NULL then it is caller's responsibility 389 // If optimized_result_code is not NULL then it is caller's responsibility
389 // to install code. 390 // to install code.
390 static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline, 391 static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline,
391 ParsedFunction* parsed_function, 392 ParsedFunction* parsed_function,
392 bool optimized, 393 bool optimized,
393 intptr_t osr_id, 394 intptr_t osr_id) {
394 BackgroundCompilationResult* result) {
395 const Function& function = parsed_function->function(); 395 const Function& function = parsed_function->function();
396 if (optimized && !function.IsOptimizable()) { 396 if (optimized && !function.IsOptimizable()) {
397 return false; 397 return false;
398 } 398 }
399 bool is_compiled = false; 399 bool is_compiled = false;
400 Thread* const thread = Thread::Current(); 400 Thread* const thread = Thread::Current();
401 Zone* const zone = thread->zone(); 401 Zone* const zone = thread->zone();
402 Isolate* const isolate = thread->isolate(); 402 Isolate* const isolate = thread->isolate();
403 CSTAT_TIMER_SCOPE(thread, codegen_timer); 403 CSTAT_TIMER_SCOPE(thread, codegen_timer);
404 HANDLESCOPE(thread); 404 HANDLESCOPE(thread);
405 405
406 // Get current generetion count to check in background compilation
407 // if the code may got invalidated while compiling.
siva 2015/11/18 17:46:27 The comment does not read well, maybe Get current
srdjan 2015/11/18 19:04:53 Done.
408 uint32_t cha_invalidation_gen_at_start = isolate->cha_invalidation_gen();
409 uint32_t field_invalidation_gen_at_start = isolate->field_invalidation_gen();
410 uint32_t prefix_invalidation_gen_at_start =
411 isolate->prefix_invalidation_gen();
412
406 // We may reattempt compilation if the function needs to be assembled using 413 // We may reattempt compilation if the function needs to be assembled using
407 // far branches on ARM and MIPS. In the else branch of the setjmp call, 414 // far branches on ARM and MIPS. In the else branch of the setjmp call,
408 // done is set to false, and use_far_branches is set to true if there is a 415 // done is set to false, and use_far_branches is set to true if there is a
409 // longjmp from the ARM or MIPS assemblers. In all other paths through this 416 // longjmp from the ARM or MIPS assemblers. In all other paths through this
410 // while loop, done is set to true. use_far_branches is always false on ia32 417 // while loop, done is set to true. use_far_branches is always false on ia32
411 // and x64. 418 // and x64.
412 bool done = false; 419 bool done = false;
413 // volatile because the variable may be clobbered by a longjmp. 420 // volatile because the variable may be clobbered by a longjmp.
414 volatile bool use_far_branches = false; 421 volatile bool use_far_branches = false;
415 while (!done) { 422 while (!done) {
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after
731 FlowGraphCompiler graph_compiler(&assembler, flow_graph, 738 FlowGraphCompiler graph_compiler(&assembler, flow_graph,
732 *parsed_function, optimized, 739 *parsed_function, optimized,
733 inline_id_to_function, 740 inline_id_to_function,
734 caller_inline_id); 741 caller_inline_id);
735 { 742 {
736 CSTAT_TIMER_SCOPE(thread, graphcompiler_timer); 743 CSTAT_TIMER_SCOPE(thread, graphcompiler_timer);
737 graph_compiler.CompileGraph(); 744 graph_compiler.CompileGraph();
738 pipeline->FinalizeCompilation(); 745 pipeline->FinalizeCompilation();
739 } 746 }
740 { 747 {
748 // This part of compilation must be at a safepoint.
749 if (!Thread::Current()->IsMutatorThread()) {
750 // Stop mutator thread while in background compilation.
siva 2015/11/18 17:46:27 Stop mutator thread before creating the instructio
srdjan 2015/11/18 19:04:53 Stop mutator thread before creating the instructio
751 // Mutator thread may not run code while we are creating the
752 // instruction object, since the creation of instruction object
753 // changes code page access permissions (makes them temporary not
754 // executable).
755 isolate->thread_registry()->SafepointThreads();
756 }
741 CSTAT_TIMER_SCOPE(thread, codefinalizer_timer); 757 CSTAT_TIMER_SCOPE(thread, codefinalizer_timer);
742 // CreateDeoptInfo uses the object pool and needs to be done before 758 // CreateDeoptInfo uses the object pool and needs to be done before
743 // FinalizeCode. 759 // FinalizeCode.
744 const Array& deopt_info_array = 760 const Array& deopt_info_array =
745 Array::Handle(zone, graph_compiler.CreateDeoptInfo(&assembler)); 761 Array::Handle(zone, graph_compiler.CreateDeoptInfo(&assembler));
746 INC_STAT(thread, total_code_size, 762 INC_STAT(thread, total_code_size,
747 deopt_info_array.Length() * sizeof(uword)); 763 deopt_info_array.Length() * sizeof(uword));
748 const Code& code = Code::Handle( 764 const Code& code = Code::Handle(
749 Code::FinalizeCode(function, &assembler, optimized)); 765 Code::FinalizeCode(function, &assembler, optimized));
750 code.set_is_optimized(optimized); 766 code.set_is_optimized(optimized);
(...skipping 18 matching lines...) Expand all
769 785
770 graph_compiler.FinalizePcDescriptors(code); 786 graph_compiler.FinalizePcDescriptors(code);
771 code.set_deopt_info_array(deopt_info_array); 787 code.set_deopt_info_array(deopt_info_array);
772 788
773 graph_compiler.FinalizeStackmaps(code); 789 graph_compiler.FinalizeStackmaps(code);
774 graph_compiler.FinalizeVarDescriptors(code); 790 graph_compiler.FinalizeVarDescriptors(code);
775 graph_compiler.FinalizeExceptionHandlers(code); 791 graph_compiler.FinalizeExceptionHandlers(code);
776 graph_compiler.FinalizeStaticCallTargetsTable(code); 792 graph_compiler.FinalizeStaticCallTargetsTable(code);
777 793
778 if (optimized) { 794 if (optimized) {
779 if (result != NULL) { 795 if (thread->IsMutatorThread()) {
780 // Background compilation, store compilation result in 'result'.
781 ASSERT(!Thread::Current()->IsMutatorThread());
782 // Do not install code, but return it instead.
783 // Since code dependencies (CHA, fields) are defined eagerly,
784 // the code may be disabled before installing it.
785 code.set_owner(function);
786 result->set_result_code(code);
787 // Disable invalidation counters that are not relevant.
788 if (thread->cha()->leaf_classes().is_empty()) {
789 result->ClearCHAInvalidationGen();
790 }
791 if (flow_graph->guarded_fields()->is_empty()) {
792 result->ClearFieldInvalidationGen();
793 }
794 if (!parsed_function->HasDeferredPrefixes()) {
795 result->ClearPrefixInvalidationGen();
796 }
797 } else {
798 const bool is_osr = osr_id != Compiler::kNoOSRDeoptId; 796 const bool is_osr = osr_id != Compiler::kNoOSRDeoptId;
799 function.InstallOptimizedCode(code, is_osr); 797 function.InstallOptimizedCode(code, is_osr);
siva 2015/11/18 17:46:27 Maybe add a comment here that there won't be concu
srdjan 2015/11/18 19:04:53 Adding that comment above at FinalizeCode:
798 } else {
799 // Background compilation
siva 2015/11/18 17:46:27 Background compilation.
srdjan 2015/11/18 19:04:53 Done and added: // Before installing c
800 bool code_is_valid = true;
801 if (!thread->cha()->leaf_classes().is_empty()) {
802 if (cha_invalidation_gen_at_start !=
803 isolate->cha_invalidation_gen()) {
804 code_is_valid = false;
805 }
806 }
807 if (!flow_graph->guarded_fields()->is_empty()) {
808 if (field_invalidation_gen_at_start !=
809 isolate->field_invalidation_gen()) {
810 code_is_valid = false;
811 }
812 }
813 if (parsed_function->HasDeferredPrefixes()) {
814 if (prefix_invalidation_gen_at_start !=
815 isolate->prefix_invalidation_gen()) {
816 code_is_valid = false;
817 }
818 }
819 if (code_is_valid) {
820 const bool is_osr = osr_id != Compiler::kNoOSRDeoptId;
821 ASSERT(!is_osr); // OSR is compiled in background.
822 function.InstallOptimizedCode(code, is_osr);
823 }
824 if (function.usage_counter() < 0) {
825 // Reset to 0 so that it can be recompiled if needed.
826 function.set_usage_counter(0);
827 }
800 } 828 }
801 829
802 // Register code with the classes it depends on because of CHA and 830 // Register code with the classes it depends on because of CHA and
803 // fields it depends on because of store guards, unless we cannot 831 // fields it depends on because of store guards, unless we cannot
804 // deopt. 832 // deopt.
805 if (Compiler::allow_recompilation()) { 833 if (Compiler::allow_recompilation()) {
806 if (result != NULL) { 834 // Deoptimize field dependent code first, before registering
807 // Background compilation: delay registering code until we are 835 // this yet uninstalled code as dependent on a field.
808 // in the MutatorThread. 836 // TODO(srdjan): Debugging dart2js crashes;
809 result->SetLeafClasses(thread->cha()->leaf_classes()); 837 // FlowGraphOptimizer::VisitStoreInstanceField populates
810 result->SetGuardedFields(*flow_graph->guarded_fields()); 838 // deoptimize_dependent_code() list, currently disabled.
811 result->SetDeoptimizeDependentFields( 839 for (intptr_t i = 0;
812 flow_graph->deoptimize_dependent_code()); 840 i < flow_graph->deoptimize_dependent_code().length();
813 } else { 841 i++) {
814 // Deoptimize field dependent code first, before registering 842 const Field* field = flow_graph->deoptimize_dependent_code()[i];
815 // this yet uninstalled code as dependent on a field. 843 field->DeoptimizeDependentCode();
816 // TODO(srdjan): Debugging dart2js crashes; 844 }
817 // FlowGraphOptimizer::VisitStoreInstanceField populates 845 for (intptr_t i = 0;
818 // deoptimize_dependent_code() list, currently disabled. 846 i < thread->cha()->leaf_classes().length();
819 for (intptr_t i = 0; 847 ++i) {
820 i < flow_graph->deoptimize_dependent_code().length(); 848 thread->cha()->leaf_classes()[i]->RegisterCHACode(code);
821 i++) { 849 }
822 const Field* field = flow_graph->deoptimize_dependent_code()[i]; 850 for (intptr_t i = 0;
823 field->DeoptimizeDependentCode(); 851 i < flow_graph->guarded_fields()->length();
824 } 852 i++) {
825 for (intptr_t i = 0; 853 const Field* field = (*flow_graph->guarded_fields())[i];
826 i < thread->cha()->leaf_classes().length(); 854 field->RegisterDependentCode(code);
827 ++i) {
828 thread->cha()->leaf_classes()[i]->RegisterCHACode(code);
829 }
830 for (intptr_t i = 0;
831 i < flow_graph->guarded_fields()->length();
832 i++) {
833 const Field* field = (*flow_graph->guarded_fields())[i];
834 field->RegisterDependentCode(code);
835 }
836 } 855 }
837 } 856 }
838 } else { // not optimized. 857 } else { // not optimized.
839 if (!Compiler::always_optimize() && 858 if (!Compiler::always_optimize() &&
840 (function.ic_data_array() == Array::null())) { 859 (function.ic_data_array() == Array::null())) {
841 function.SaveICDataMap( 860 function.SaveICDataMap(
842 graph_compiler.deopt_id_to_ic_data(), 861 graph_compiler.deopt_id_to_ic_data(),
843 Array::Handle(zone, graph_compiler.edge_counters_array())); 862 Array::Handle(zone, graph_compiler.edge_counters_array()));
844 } 863 }
845 function.set_unoptimized_code(code); 864 function.set_unoptimized_code(code);
846 function.AttachCode(code); 865 function.AttachCode(code);
847 } 866 }
848 if (parsed_function->HasDeferredPrefixes()) { 867 if (parsed_function->HasDeferredPrefixes()) {
849 ASSERT(!FLAG_load_deferred_eagerly); 868 ASSERT(!FLAG_load_deferred_eagerly);
850 ZoneGrowableArray<const LibraryPrefix*>* prefixes = 869 ZoneGrowableArray<const LibraryPrefix*>* prefixes =
851 parsed_function->deferred_prefixes(); 870 parsed_function->deferred_prefixes();
852 for (intptr_t i = 0; i < prefixes->length(); i++) { 871 for (intptr_t i = 0; i < prefixes->length(); i++) {
853 (*prefixes)[i]->RegisterDependentCode(code); 872 (*prefixes)[i]->RegisterDependentCode(code);
854 } 873 }
855 } 874 }
875 if (!Thread::Current()->IsMutatorThread()) {
876 // Background compilation.
877 isolate->thread_registry()->ResumeAllThreads();
878 }
856 } 879 }
857 // Mark that this isolate now has compiled code. 880 // Mark that this isolate now has compiled code.
858 isolate->set_has_compiled_code(true); 881 isolate->set_has_compiled_code(true);
859 // Exit the loop and the function with the correct result value. 882 // Exit the loop and the function with the correct result value.
860 is_compiled = true; 883 is_compiled = true;
861 done = true; 884 done = true;
862 } else { 885 } else {
863 // We bailed out or we encountered an error. 886 // We bailed out or we encountered an error.
864 const Error& error = Error::Handle( 887 const Error& error = Error::Handle(
865 isolate->object_store()->sticky_error()); 888 isolate->object_store()->sticky_error());
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
1051 ASSERT(inlined_functions[inlined_functions.length() - 1]->raw() == 1074 ASSERT(inlined_functions[inlined_functions.length() - 1]->raw() ==
1052 function.raw()); 1075 function.raw());
1053 } 1076 }
1054 } 1077 }
1055 #endif 1078 #endif
1056 1079
1057 1080
1058 static RawError* CompileFunctionHelper(CompilationPipeline* pipeline, 1081 static RawError* CompileFunctionHelper(CompilationPipeline* pipeline,
1059 const Function& function, 1082 const Function& function,
1060 bool optimized, 1083 bool optimized,
1061 intptr_t osr_id, 1084 intptr_t osr_id) {
1062 BackgroundCompilationResult* result) {
1063 // Check that we optimize if 'Compiler::always_optimize()' is set to true, 1085 // Check that we optimize if 'Compiler::always_optimize()' is set to true,
1064 // except if the function is marked as not optimizable. 1086 // except if the function is marked as not optimizable.
1065 ASSERT(!function.IsOptimizable() || 1087 ASSERT(!function.IsOptimizable() ||
1066 !Compiler::always_optimize() || optimized); 1088 !Compiler::always_optimize() || optimized);
1067 ASSERT(Compiler::allow_recompilation() || !function.HasCode()); 1089 ASSERT(Compiler::allow_recompilation() || !function.HasCode());
1068 LongJumpScope jump; 1090 LongJumpScope jump;
1069 if (setjmp(*jump.Set()) == 0) { 1091 if (setjmp(*jump.Set()) == 0) {
1070 Thread* const thread = Thread::Current(); 1092 Thread* const thread = Thread::Current();
1071 Isolate* const isolate = thread->isolate(); 1093 Isolate* const isolate = thread->isolate();
1072 StackZone stack_zone(thread); 1094 StackZone stack_zone(thread);
(...skipping 21 matching lines...) Expand all
1094 pipeline->ParseFunction(parsed_function); 1116 pipeline->ParseFunction(parsed_function);
1095 const int64_t num_tokens_after = STAT_VALUE(thread, num_tokens_consumed); 1117 const int64_t num_tokens_after = STAT_VALUE(thread, num_tokens_consumed);
1096 INC_STAT(thread, 1118 INC_STAT(thread,
1097 num_func_tokens_compiled, 1119 num_func_tokens_compiled,
1098 num_tokens_after - num_tokens_before); 1120 num_tokens_after - num_tokens_before);
1099 } 1121 }
1100 1122
1101 const bool success = CompileParsedFunctionHelper(pipeline, 1123 const bool success = CompileParsedFunctionHelper(pipeline,
1102 parsed_function, 1124 parsed_function,
1103 optimized, 1125 optimized,
1104 osr_id, 1126 osr_id);
1105 result);
1106 if (!success) { 1127 if (!success) {
1107 if (optimized) { 1128 if (optimized) {
1108 ASSERT(!Compiler::always_optimize()); // Optimized is the only code. 1129 ASSERT(!Compiler::always_optimize()); // Optimized is the only code.
1109 // Optimizer bailed out. Disable optimizations and never try again. 1130 // Optimizer bailed out. Disable optimizations and never try again.
1110 if (FLAG_trace_compiler) { 1131 if (FLAG_trace_compiler) {
1111 THR_Print("--> disabling optimizations for '%s'\n", 1132 THR_Print("--> disabling optimizations for '%s'\n",
1112 function.ToFullyQualifiedCString()); 1133 function.ToFullyQualifiedCString());
1113 } else if (FLAG_trace_failed_optimization_attempts) { 1134 } else if (FLAG_trace_failed_optimization_attempts) {
1114 THR_Print("Cannot optimize: %s\n", 1135 THR_Print("Cannot optimize: %s\n",
1115 function.ToFullyQualifiedCString()); 1136 function.ToFullyQualifiedCString());
(...skipping 19 matching lines...) Expand all
1135 Code::Handle(function.CurrentCode()).Size(), 1156 Code::Handle(function.CurrentCode()).Size(),
1136 per_compile_timer.TotalElapsedTime()); 1157 per_compile_timer.TotalElapsedTime());
1137 } 1158 }
1138 1159
1139 isolate->debugger()->NotifyCompilation(function); 1160 isolate->debugger()->NotifyCompilation(function);
1140 1161
1141 if (FLAG_disassemble && FlowGraphPrinter::ShouldPrint(function)) { 1162 if (FLAG_disassemble && FlowGraphPrinter::ShouldPrint(function)) {
1142 DisassembleCode(function, optimized); 1163 DisassembleCode(function, optimized);
1143 } else if (FLAG_disassemble_optimized && 1164 } else if (FLAG_disassemble_optimized &&
1144 optimized && 1165 optimized &&
1145 FlowGraphPrinter::ShouldPrint(function) && 1166 FlowGraphPrinter::ShouldPrint(function)) {
1146 (result == NULL) /* no background compilation*/ ) {
1147 // With background compilation, print when installing the code.
1148 // TODO(fschneider): Print unoptimized code along with the optimized code. 1167 // TODO(fschneider): Print unoptimized code along with the optimized code.
1149 THR_Print("*** BEGIN CODE\n"); 1168 THR_Print("*** BEGIN CODE\n");
1150 DisassembleCode(function, true); 1169 DisassembleCode(function, true);
1151 THR_Print("*** END CODE\n"); 1170 THR_Print("*** END CODE\n");
1152 } 1171 }
1153 #if defined(DEBUG) 1172 #if defined(DEBUG)
1154 CheckInliningIntervals(function); 1173 CheckInliningIntervals(function);
1155 #endif 1174 #endif
1156 return Error::null(); 1175 return Error::null();
1157 } else { 1176 } else {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1189 1208
1190 CompilationPipeline* pipeline = 1209 CompilationPipeline* pipeline =
1191 CompilationPipeline::New(thread->zone(), function); 1210 CompilationPipeline::New(thread->zone(), function);
1192 1211
1193 const bool optimized = 1212 const bool optimized =
1194 Compiler::always_optimize() && function.IsOptimizable(); 1213 Compiler::always_optimize() && function.IsOptimizable();
1195 1214
1196 return CompileFunctionHelper(pipeline, 1215 return CompileFunctionHelper(pipeline,
1197 function, 1216 function,
1198 optimized, 1217 optimized,
1199 kNoOSRDeoptId, /* not OSR */ 1218 kNoOSRDeoptId);
1200 NULL /* no result code */);
1201 } 1219 }
1202 1220
1203 1221
1204 RawError* Compiler::EnsureUnoptimizedCode(Thread* thread, 1222 RawError* Compiler::EnsureUnoptimizedCode(Thread* thread,
1205 const Function& function) { 1223 const Function& function) {
1206 if (function.unoptimized_code() != Object::null()) { 1224 if (function.unoptimized_code() != Object::null()) {
1207 return Error::null(); 1225 return Error::null();
1208 } 1226 }
1209 Code& original_code = Code::ZoneHandle(thread->zone()); 1227 Code& original_code = Code::ZoneHandle(thread->zone());
1210 if (function.HasCode()) { 1228 if (function.HasCode()) {
1211 original_code = function.CurrentCode(); 1229 original_code = function.CurrentCode();
1212 } 1230 }
1213 CompilationPipeline* pipeline = 1231 CompilationPipeline* pipeline =
1214 CompilationPipeline::New(thread->zone(), function); 1232 CompilationPipeline::New(thread->zone(), function);
1215 const Error& error = Error::Handle( 1233 const Error& error = Error::Handle(
1216 CompileFunctionHelper(pipeline, 1234 CompileFunctionHelper(pipeline,
1217 function, 1235 function,
1218 false, /* not optimized */ 1236 false, /* not optimized */
1219 kNoOSRDeoptId, /* not OSR */ 1237 kNoOSRDeoptId));
1220 NULL /* no result code */));
1221 if (!error.IsNull()) { 1238 if (!error.IsNull()) {
1222 return error.raw(); 1239 return error.raw();
1223 } 1240 }
1224 // Since CompileFunctionHelper replaces the current code, re-attach the 1241 // Since CompileFunctionHelper replaces the current code, re-attach the
1225 // the original code if the function was already compiled. 1242 // the original code if the function was already compiled.
1226 if (!original_code.IsNull() && 1243 if (!original_code.IsNull() &&
1227 (original_code.raw() != function.CurrentCode())) { 1244 (original_code.raw() != function.CurrentCode())) {
1228 function.AttachCode(original_code); 1245 function.AttachCode(original_code);
1229 } 1246 }
1230 ASSERT(function.unoptimized_code() != Object::null()); 1247 ASSERT(function.unoptimized_code() != Object::null());
1231 if (FLAG_trace_compiler) { 1248 if (FLAG_trace_compiler) {
1232 THR_Print("Ensure unoptimized code for %s\n", function.ToCString()); 1249 THR_Print("Ensure unoptimized code for %s\n", function.ToCString());
1233 } 1250 }
1234 return Error::null(); 1251 return Error::null();
1235 } 1252 }
1236 1253
1237 1254
1238 RawError* Compiler::CompileOptimizedFunction(Thread* thread, 1255 RawError* Compiler::CompileOptimizedFunction(Thread* thread,
1239 const Function& function, 1256 const Function& function,
1240 intptr_t osr_id, 1257 intptr_t osr_id) {
1241 BackgroundCompilationResult* res) {
1242 VMTagScope tagScope(thread, VMTag::kCompileOptimizedTagId); 1258 VMTagScope tagScope(thread, VMTag::kCompileOptimizedTagId);
1243 TIMELINE_FUNCTION_COMPILATION_DURATION(thread, 1259 TIMELINE_FUNCTION_COMPILATION_DURATION(thread,
1244 "OptimizedFunction", function); 1260 "OptimizedFunction", function);
1245 1261
1246 // Optimization must happen in non-mutator/Dart thread if background 1262 // Optimization must happen in non-mutator/Dart thread if background
1247 // compilation is on. OSR compilation still occurs in the main thread. 1263 // compilation is on. OSR compilation still occurs in the main thread.
1248 ASSERT((osr_id != kNoOSRDeoptId) || !FLAG_background_compilation || 1264 ASSERT((osr_id != kNoOSRDeoptId) || !FLAG_background_compilation ||
1249 !thread->IsMutatorThread()); 1265 !thread->IsMutatorThread());
1250 CompilationPipeline* pipeline = 1266 CompilationPipeline* pipeline =
1251 CompilationPipeline::New(thread->zone(), function); 1267 CompilationPipeline::New(thread->zone(), function);
1252 return CompileFunctionHelper(pipeline, 1268 return CompileFunctionHelper(pipeline,
1253 function, 1269 function,
1254 true, /* optimized */ 1270 true, /* optimized */
1255 osr_id, 1271 osr_id);
1256 res);
1257 } 1272 }
1258 1273
1259 1274
1260 // This is only used from unit tests. 1275 // This is only used from unit tests.
1261 RawError* Compiler::CompileParsedFunction( 1276 RawError* Compiler::CompileParsedFunction(
1262 ParsedFunction* parsed_function) { 1277 ParsedFunction* parsed_function) {
1263 LongJumpScope jump; 1278 LongJumpScope jump;
1264 if (setjmp(*jump.Set()) == 0) { 1279 if (setjmp(*jump.Set()) == 0) {
1265 // Non-optimized code generator. 1280 // Non-optimized code generator.
1266 DartCompilationPipeline pipeline; 1281 DartCompilationPipeline pipeline;
1267 CompileParsedFunctionHelper(&pipeline, 1282 CompileParsedFunctionHelper(&pipeline,
1268 parsed_function, 1283 parsed_function,
1269 false, 1284 false,
1270 kNoOSRDeoptId, 1285 kNoOSRDeoptId);
1271 NULL /* no result code */);
1272 if (FLAG_disassemble) { 1286 if (FLAG_disassemble) {
1273 DisassembleCode(parsed_function->function(), false); 1287 DisassembleCode(parsed_function->function(), false);
1274 } 1288 }
1275 return Error::null(); 1289 return Error::null();
1276 } else { 1290 } else {
1277 Isolate* const isolate = Isolate::Current(); 1291 Isolate* const isolate = Isolate::Current();
1278 Error& error = Error::Handle(); 1292 Error& error = Error::Handle();
1279 // We got an error during compilation. 1293 // We got an error during compilation.
1280 error = isolate->object_store()->sticky_error(); 1294 error = isolate->object_store()->sticky_error();
1281 isolate->object_store()->clear_sticky_error(); 1295 isolate->object_store()->clear_sticky_error();
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
1367 StackZone zone(thread); 1381 StackZone zone(thread);
1368 1382
1369 ParsedFunction* parsed_function = Parser::ParseStaticFieldInitializer(field); 1383 ParsedFunction* parsed_function = Parser::ParseStaticFieldInitializer(field);
1370 1384
1371 parsed_function->AllocateVariables(); 1385 parsed_function->AllocateVariables();
1372 // Non-optimized code generator. 1386 // Non-optimized code generator.
1373 DartCompilationPipeline pipeline; 1387 DartCompilationPipeline pipeline;
1374 CompileParsedFunctionHelper(&pipeline, 1388 CompileParsedFunctionHelper(&pipeline,
1375 parsed_function, 1389 parsed_function,
1376 false, // optimized 1390 false, // optimized
1377 kNoOSRDeoptId, 1391 kNoOSRDeoptId);
1378 NULL /* no result code */);
1379 1392
1380 const Function& initializer = parsed_function->function(); 1393 const Function& initializer = parsed_function->function();
1381 field.SetPrecompiledInitializer(initializer); 1394 field.SetPrecompiledInitializer(initializer);
1382 } 1395 }
1383 1396
1384 1397
1385 RawObject* Compiler::EvaluateStaticInitializer(const Field& field) { 1398 RawObject* Compiler::EvaluateStaticInitializer(const Field& field) {
1386 ASSERT(field.is_static()); 1399 ASSERT(field.is_static());
1387 // The VM sets the field's value to transiton_sentinel prior to 1400 // The VM sets the field's value to transiton_sentinel prior to
1388 // evaluating the initializer value. 1401 // evaluating the initializer value.
(...skipping 10 matching lines...) Expand all
1399 StackZone zone(thread); 1412 StackZone zone(thread);
1400 ParsedFunction* parsed_function = 1413 ParsedFunction* parsed_function =
1401 Parser::ParseStaticFieldInitializer(field); 1414 Parser::ParseStaticFieldInitializer(field);
1402 1415
1403 parsed_function->AllocateVariables(); 1416 parsed_function->AllocateVariables();
1404 // Non-optimized code generator. 1417 // Non-optimized code generator.
1405 DartCompilationPipeline pipeline; 1418 DartCompilationPipeline pipeline;
1406 CompileParsedFunctionHelper(&pipeline, 1419 CompileParsedFunctionHelper(&pipeline,
1407 parsed_function, 1420 parsed_function,
1408 false, // optimized 1421 false, // optimized
1409 kNoOSRDeoptId, 1422 kNoOSRDeoptId);
1410 NULL /* no result code */);
1411 initializer = parsed_function->function().raw(); 1423 initializer = parsed_function->function().raw();
1412 Code::Handle(initializer.unoptimized_code()).set_var_descriptors( 1424 Code::Handle(initializer.unoptimized_code()).set_var_descriptors(
1413 Object::empty_var_descriptors()); 1425 Object::empty_var_descriptors());
1414 } else { 1426 } else {
1415 initializer ^= field.PrecompiledInitializer(); 1427 initializer ^= field.PrecompiledInitializer();
1416 } 1428 }
1417 // Invoke the function to evaluate the expression. 1429 // Invoke the function to evaluate the expression.
1418 return DartEntry::InvokeFunction(initializer, Object::empty_array()); 1430 return DartEntry::InvokeFunction(initializer, Object::empty_array());
1419 } else { 1431 } else {
1420 Thread* const thread = Thread::Current(); 1432 Thread* const thread = Thread::Current();
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1470 fragment->scope()->AddVariable(parsed_function->EnsureExpressionTemp()); 1482 fragment->scope()->AddVariable(parsed_function->EnsureExpressionTemp());
1471 fragment->scope()->AddVariable( 1483 fragment->scope()->AddVariable(
1472 parsed_function->current_context_var()); 1484 parsed_function->current_context_var());
1473 parsed_function->AllocateVariables(); 1485 parsed_function->AllocateVariables();
1474 1486
1475 // Non-optimized code generator. 1487 // Non-optimized code generator.
1476 DartCompilationPipeline pipeline; 1488 DartCompilationPipeline pipeline;
1477 CompileParsedFunctionHelper(&pipeline, 1489 CompileParsedFunctionHelper(&pipeline,
1478 parsed_function, 1490 parsed_function,
1479 false, 1491 false,
1480 kNoOSRDeoptId, 1492 kNoOSRDeoptId);
1481 NULL /* no result code */);
1482 Code::Handle(func.unoptimized_code()).set_var_descriptors( 1493 Code::Handle(func.unoptimized_code()).set_var_descriptors(
1483 Object::empty_var_descriptors()); 1494 Object::empty_var_descriptors());
1484 1495
1485 const Object& result = PassiveObject::Handle( 1496 const Object& result = PassiveObject::Handle(
1486 DartEntry::InvokeFunction(func, Object::empty_array())); 1497 DartEntry::InvokeFunction(func, Object::empty_array()));
1487 return result.raw(); 1498 return result.raw();
1488 } else { 1499 } else {
1489 Thread* const thread = Thread::Current(); 1500 Thread* const thread = Thread::Current();
1490 Isolate* const isolate = thread->isolate(); 1501 Isolate* const isolate = thread->isolate();
1491 const Object& result = 1502 const Object& result =
1492 PassiveObject::Handle(isolate->object_store()->sticky_error()); 1503 PassiveObject::Handle(isolate->object_store()->sticky_error());
1493 isolate->object_store()->clear_sticky_error(); 1504 isolate->object_store()->clear_sticky_error();
1494 return result.raw(); 1505 return result.raw();
1495 } 1506 }
1496 UNREACHABLE(); 1507 UNREACHABLE();
1497 return Object::null(); 1508 return Object::null();
1498 } 1509 }
1499 1510
1500 1511
1501 // C-heap allocated background compilation queue element. 1512 // C-heap allocated background compilation queue element.
1502 class QueueElement { 1513 class QueueElement {
1503 public: 1514 public:
1504 explicit QueueElement(const Function& function) 1515 explicit QueueElement(const Function& function)
1505 : next_(NULL), 1516 : next_(NULL),
1506 obj_(function.raw()), 1517 function_(function.raw()) {
1507 leaf_classes_(Array::null()),
1508 guarded_fields_(Array::null()),
1509 deoptimize_dependent_fields_(Array::null()),
1510 cha_invalidation_gen_(Isolate::kInvalidGen),
1511 field_invalidation_gen_(Isolate::kInvalidGen),
1512 prefix_invalidation_gen_(Isolate::kInvalidGen) {
1513 ASSERT(Thread::Current()->IsMutatorThread()); 1518 ASSERT(Thread::Current()->IsMutatorThread());
1514 } 1519 }
1515 1520
1516 ~QueueElement() { 1521 ~QueueElement() {
1517 ASSERT(Thread::Current()->IsMutatorThread()); 1522 function_ = Function::null();
1518 obj_ = Object::null();
1519 } 1523 }
1520 1524
1521 RawFunction* Function() const { return Function::RawCast(obj_); } 1525 RawFunction* Function() const { return function_; }
1522 RawCode* Code() const { return Code::RawCast(obj_); }
1523 1526
1524 RawArray* leaf_classes() const { return leaf_classes_; }
1525 RawArray* guarded_fields() const { return guarded_fields_; }
1526 RawArray* deoptimize_dependent_fields() const {
1527 return deoptimize_dependent_fields_;
1528 }
1529
1530 uint32_t cha_invalidation_gen() const { return cha_invalidation_gen_; }
1531 uint32_t field_invalidation_gen() const { return field_invalidation_gen_; }
1532 uint32_t prefix_invalidation_gen() const { return prefix_invalidation_gen_; }
1533 1527
1534 void set_next(QueueElement* elem) { next_ = elem; } 1528 void set_next(QueueElement* elem) { next_ = elem; }
1535 QueueElement* next() const { return next_; } 1529 QueueElement* next() const { return next_; }
1536 1530
1537 RawObject* obj() const { return obj_; } 1531 RawObject* function() const { return function_; }
1538 RawObject** obj_ptr() { return &obj_; } 1532 RawObject** function_ptr() {
1539 1533 return reinterpret_cast<RawObject**>(&function_);
1540 RawObject** leaf_classses_ptr() {
1541 return reinterpret_cast<RawObject**>(&leaf_classes_);
1542 }
1543
1544 RawObject** guarded_fields_ptr() {
1545 return reinterpret_cast<RawObject**>(&guarded_fields_);
1546 }
1547
1548 RawObject** deoptimize_dependent_fields_ptr() {
1549 return reinterpret_cast<RawObject**>(&deoptimize_dependent_fields_);
1550 }
1551
1552 void SetFromResult(const BackgroundCompilationResult& value) {
1553 ASSERT(!value.result_code().IsNull());
1554 obj_ = value.result_code().raw();
1555 leaf_classes_ = value.leaf_classes().raw();
1556 guarded_fields_ = value.guarded_fields().raw();
1557 deoptimize_dependent_fields_ = value.deoptimize_dependent_fields().raw();
1558 cha_invalidation_gen_ = value.cha_invalidation_gen();
1559 field_invalidation_gen_ = value.field_invalidation_gen();
1560 prefix_invalidation_gen_ = value.prefix_invalidation_gen();
1561 } 1534 }
1562 1535
1563 private: 1536 private:
1564 QueueElement* next_; 1537 QueueElement* next_;
1565 1538 RawFunction* function_;
1566 RawObject* obj_; // Code or Function.
1567 RawArray* leaf_classes_;
1568 RawArray* guarded_fields_;
1569 RawArray* deoptimize_dependent_fields_;
1570 uint32_t cha_invalidation_gen_;
1571 uint32_t field_invalidation_gen_;
1572 uint32_t prefix_invalidation_gen_;
1573 1539
1574 DISALLOW_COPY_AND_ASSIGN(QueueElement); 1540 DISALLOW_COPY_AND_ASSIGN(QueueElement);
1575 }; 1541 };
1576 1542
1577 1543
1578 // Allocated in C-heap. Handles both input and output of background compilation. 1544 // Allocated in C-heap. Handles both input and output of background compilation.
1579 // It implements a FIFO queue, using Peek, Add, Remove operations. 1545 // It implements a FIFO queue, using Peek, Add, Remove operations.
1580 class BackgroundCompilationQueue { 1546 class BackgroundCompilationQueue {
1581 public: 1547 public:
1582 BackgroundCompilationQueue() : first_(NULL), last_(NULL) {} 1548 BackgroundCompilationQueue() : first_(NULL), last_(NULL) {}
1583 ~BackgroundCompilationQueue() { 1549 ~BackgroundCompilationQueue() {
1584 while (!IsEmpty()) { 1550 while (!IsEmpty()) {
1585 QueueElement* e = Remove(); 1551 QueueElement* e = Remove();
1586 delete e; 1552 delete e;
1587 } 1553 }
1588 ASSERT((first_ == NULL) && (last_ == NULL)); 1554 ASSERT((first_ == NULL) && (last_ == NULL));
1589 } 1555 }
1590 1556
1591 void VisitObjectPointers(ObjectPointerVisitor* visitor) { 1557 void VisitObjectPointers(ObjectPointerVisitor* visitor) {
1592 ASSERT(visitor != NULL); 1558 ASSERT(visitor != NULL);
1593 QueueElement* p = first_; 1559 QueueElement* p = first_;
1594 while (p != NULL) { 1560 while (p != NULL) {
1595 visitor->VisitPointer(p->obj_ptr()); 1561 visitor->VisitPointer(p->function_ptr());
1596 visitor->VisitPointer(p->leaf_classses_ptr());
1597 visitor->VisitPointer(p->guarded_fields_ptr());
1598 visitor->VisitPointer(p->deoptimize_dependent_fields_ptr());
1599 p = p->next(); 1562 p = p->next();
1600 } 1563 }
1601 } 1564 }
1602 1565
1603 bool IsEmpty() const { return first_ == NULL; } 1566 bool IsEmpty() const { return first_ == NULL; }
1604 1567
1605 void Add(QueueElement* value) { 1568 void Add(QueueElement* value) {
1606 ASSERT(value != NULL); 1569 ASSERT(value != NULL);
1607 if (first_ == NULL) { 1570 if (first_ == NULL) {
1608 first_ = value; 1571 first_ = value;
(...skipping 23 matching lines...) Expand all
1632 first_ = first_->next(); 1595 first_ = first_->next();
1633 if (first_ == NULL) { 1596 if (first_ == NULL) {
1634 last_ = NULL; 1597 last_ = NULL;
1635 } 1598 }
1636 return result; 1599 return result;
1637 } 1600 }
1638 1601
1639 bool ContainsObj(const Object& obj) const { 1602 bool ContainsObj(const Object& obj) const {
1640 QueueElement* p = first_; 1603 QueueElement* p = first_;
1641 while (p != NULL) { 1604 while (p != NULL) {
1642 if (p->obj() == obj.raw()) { 1605 if (p->function() == obj.raw()) {
1643 return true; 1606 return true;
1644 } 1607 }
1645 p = p->next(); 1608 p = p->next();
1646 } 1609 }
1647 return false; 1610 return false;
1648 } 1611 }
1649 1612
1650 private: 1613 private:
1651 QueueElement* first_; 1614 QueueElement* first_;
1652 QueueElement* last_; 1615 QueueElement* last_;
1653 1616
1654 DISALLOW_COPY_AND_ASSIGN(BackgroundCompilationQueue); 1617 DISALLOW_COPY_AND_ASSIGN(BackgroundCompilationQueue);
1655 }; 1618 };
1656 1619
1657 1620
1658 BackgroundCompilationResult::BackgroundCompilationResult()
1659 : result_code_(Code::Handle()),
1660 leaf_classes_(Array::Handle()),
1661 guarded_fields_(Array::Handle()),
1662 deoptimize_dependent_fields_(Array::Handle()),
1663 cha_invalidation_gen_(Isolate::kInvalidGen),
1664 field_invalidation_gen_(Isolate::kInvalidGen),
1665 prefix_invalidation_gen_(Isolate::kInvalidGen) {
1666 }
1667
1668
1669 void BackgroundCompilationResult::Init() {
1670 Isolate* i = Isolate::Current();
1671 result_code_ = Code::null();
1672 leaf_classes_ = Array::null();
1673 guarded_fields_ = Array::null();
1674 deoptimize_dependent_fields_ = Array::null();
1675 cha_invalidation_gen_ = i->cha_invalidation_gen();
1676 field_invalidation_gen_ = i->field_invalidation_gen();
1677 prefix_invalidation_gen_ = i->prefix_invalidation_gen();
1678 }
1679
1680
1681 void BackgroundCompilationResult::SetFromQElement(QueueElement* value) {
1682 ASSERT(value != NULL);
1683 result_code_ = value->Code();
1684 leaf_classes_ = value->leaf_classes();
1685 guarded_fields_ = value->guarded_fields();
1686 deoptimize_dependent_fields_ = value->deoptimize_dependent_fields();
1687 cha_invalidation_gen_ = value->cha_invalidation_gen();
1688 field_invalidation_gen_ = value->field_invalidation_gen();
1689 prefix_invalidation_gen_ = value->prefix_invalidation_gen();
1690 }
1691
1692
1693 void BackgroundCompilationResult::SetLeafClasses(
1694 const GrowableArray<Class*>& leaf_classes) {
1695 const Array& a = Array::Handle(Array::New(leaf_classes.length(), Heap::kOld));
1696 for (intptr_t i = 0; i < leaf_classes.length(); i++) {
1697 a.SetAt(i, *leaf_classes[i]);
1698 }
1699 leaf_classes_ = a.raw();
1700 }
1701
1702
1703 void BackgroundCompilationResult::SetGuardedFields(
1704 const ZoneGrowableArray<const Field*>& guarded_fields) {
1705 const Array& a =
1706 Array::Handle(Array::New(guarded_fields.length(), Heap::kOld));
1707 for (intptr_t i = 0; i < guarded_fields.length(); i++) {
1708 a.SetAt(i, *guarded_fields[i]);
1709 }
1710 guarded_fields_ = a.raw();
1711 }
1712
1713
1714 void BackgroundCompilationResult::SetDeoptimizeDependentFields(
1715 const GrowableArray<const Field*>& fields) {
1716 const Array& a = Array::Handle(Array::New(fields.length(), Heap::kOld));
1717 for (intptr_t i = 0; i < fields.length(); i++) {
1718 a.SetAt(i, *fields[i]);
1719 }
1720 deoptimize_dependent_fields_ = a.raw();
1721 }
1722
1723
1724 bool BackgroundCompilationResult::IsValid() const {
1725 if (result_code().IsNull() || result_code().IsDisabled()) {
1726 return false;
1727 }
1728 Isolate* i = Isolate::Current();
1729 if ((cha_invalidation_gen_ != Isolate::kInvalidGen) &&
1730 (cha_invalidation_gen_ != i->cha_invalidation_gen())) {
1731 return false;
1732 }
1733 if ((field_invalidation_gen_ != Isolate::kInvalidGen) &&
1734 (field_invalidation_gen_ != i->field_invalidation_gen())) {
1735 return false;
1736 }
1737 if ((prefix_invalidation_gen_ != Isolate::kInvalidGen) &&
1738 (prefix_invalidation_gen_ != i->prefix_invalidation_gen())) {
1739 return false;
1740 }
1741 return true;
1742 }
1743
1744
1745 void BackgroundCompilationResult::PrintValidity() const {
1746 Object& o = Object::Handle(result_code().owner());
1747 THR_Print("BackgroundCompilationResult: %s\n",
1748 Function::Cast(o).ToQualifiedCString());
1749 if (result_code().IsNull()) {
1750 THR_Print(" result_code is NULL\n");
1751 return;
1752 }
1753 if (result_code().IsDisabled()) {
1754 THR_Print(" result_code is disabled\n");
1755 return;
1756 }
1757 Isolate* i = Isolate::Current();
1758 THR_Print(" cha_invalidation_gen: %u (current: %u)\n",
1759 cha_invalidation_gen_, i->cha_invalidation_gen());
1760 THR_Print(" field_invalidation_gen: %u (current: %u)\n",
1761 field_invalidation_gen_, i->field_invalidation_gen());
1762 THR_Print(" prefix_invalidation_gen: %u (current: %u)\n",
1763 prefix_invalidation_gen_, i->prefix_invalidation_gen());
1764 }
1765
1766
1767 BackgroundCompiler::BackgroundCompiler(Isolate* isolate) 1621 BackgroundCompiler::BackgroundCompiler(Isolate* isolate)
1768 : isolate_(isolate), running_(true), done_(new bool()), 1622 : isolate_(isolate), running_(true), done_(new bool()),
1769 queue_monitor_(new Monitor()), done_monitor_(new Monitor()), 1623 queue_monitor_(new Monitor()), done_monitor_(new Monitor()),
1770 function_queue_(new BackgroundCompilationQueue()), 1624 function_queue_(new BackgroundCompilationQueue()) {
1771 result_queue_(new BackgroundCompilationQueue()) {
1772 *done_ = false; 1625 *done_ = false;
1773 } 1626 }
1774 1627
1775 1628
1776 void BackgroundCompiler::Run() { 1629 void BackgroundCompiler::Run() {
1777 while (running_) { 1630 while (running_) {
1778 // Maybe something is already in the queue, check first before waiting 1631 // Maybe something is already in the queue, check first before waiting
1779 // to be notified. 1632 // to be notified.
1780 Thread::EnterIsolateAsHelper(isolate_); 1633 Thread::EnterIsolateAsHelper(isolate_);
1781 { 1634 {
1782 Thread* thread = Thread::Current(); 1635 Thread* thread = Thread::Current();
1783 StackZone stack_zone(thread); 1636 StackZone stack_zone(thread);
1784 Zone* zone = stack_zone.GetZone(); 1637 Zone* zone = stack_zone.GetZone();
1785 HANDLESCOPE(thread); 1638 HANDLESCOPE(thread);
1786 Function& function = Function::Handle(zone); 1639 Function& function = Function::Handle(zone);
1787 function = function_queue()->PeekFunction(); 1640 function = function_queue()->PeekFunction();
1788 BackgroundCompilationResult result;
1789 while (running_ && !function.IsNull()) { 1641 while (running_ && !function.IsNull()) {
1790 result.Init();
1791 const Error& error = Error::Handle(zone, 1642 const Error& error = Error::Handle(zone,
1792 Compiler::CompileOptimizedFunction(thread, 1643 Compiler::CompileOptimizedFunction(thread,
1793 function, 1644 function,
1794 Compiler::kNoOSRDeoptId, 1645 Compiler::kNoOSRDeoptId));
1795 &result));
1796 // TODO(srdjan): We do not expect errors while compiling optimized 1646 // TODO(srdjan): We do not expect errors while compiling optimized
1797 // code, any errors should have been caught when compiling 1647 // code, any errors should have been caught when compiling
1798 // unoptimized code. Any issues while optimizing are flagged by 1648 // unoptimized code. Any issues while optimizing are flagged by
1799 // making the result invalid. 1649 // making the result invalid.
1800 ASSERT(error.IsNull()); 1650 ASSERT(error.IsNull());
1801 AddResult(result); 1651 QueueElement* qelem = function_queue()->Remove();
1652 delete qelem;
1802 function = function_queue()->PeekFunction(); 1653 function = function_queue()->PeekFunction();
1803 } 1654 }
1804 } 1655 }
1805 Thread::ExitIsolateAsHelper(); 1656 Thread::ExitIsolateAsHelper();
1806 { 1657 {
1807 // Wait to be notified when the work queue is not empty. 1658 // Wait to be notified when the work queue is not empty.
1808 MonitorLocker ml(queue_monitor_); 1659 MonitorLocker ml(queue_monitor_);
1809 while (function_queue()->IsEmpty() && running_) { 1660 while (function_queue()->IsEmpty() && running_) {
1810 ml.Wait(); 1661 ml.Wait();
1811 } 1662 }
1812 } 1663 }
1813 } // while running 1664 } // while running
1814 1665
1815 { 1666 {
1816 // Notify that the thread is done. 1667 // Notify that the thread is done.
1817 MonitorLocker ml_done(done_monitor_); 1668 MonitorLocker ml_done(done_monitor_);
1818 *done_ = true; 1669 *done_ = true;
1819 ml_done.Notify(); 1670 ml_done.Notify();
1820 } 1671 }
1821 } 1672 }
1822 1673
1823 1674
1824 // Use to first queue element to form the result element.
1825 void BackgroundCompiler::AddResult(const BackgroundCompilationResult& result) {
1826 ASSERT(!Thread::Current()->IsMutatorThread());
1827 MonitorLocker ml(queue_monitor_);
1828 // Reuse the input QueueElement to return the result.
1829 QueueElement* qelem = function_queue()->Remove();
1830 // Always add result, even if it is invalid, since the queue element is
1831 // deleted in the mutator thread and potential field based deoptimizations
1832 // (carried in the result) still must be done.
1833 qelem->SetFromResult(result);
1834 result_queue()->Add(qelem);
1835 }
1836
1837
1838 void BackgroundCompiler::CompileOptimized(const Function& function) { 1675 void BackgroundCompiler::CompileOptimized(const Function& function) {
1839 ASSERT(Thread::Current()->IsMutatorThread()); 1676 ASSERT(Thread::Current()->IsMutatorThread());
1840 MonitorLocker ml(queue_monitor_); 1677 MonitorLocker ml(queue_monitor_);
1841 if (function_queue()->ContainsObj(function)) { 1678 if (function_queue()->ContainsObj(function)) {
1842 return; 1679 return;
1843 } 1680 }
1844 QueueElement* elem = new QueueElement(function); 1681 QueueElement* elem = new QueueElement(function);
1845 function_queue()->Add(elem); 1682 function_queue()->Add(elem);
1846 ml.Notify(); 1683 ml.Notify();
1847 } 1684 }
1848 1685
1849 1686
1850 void BackgroundCompiler::InstallGeneratedCode() {
1851 ASSERT(Thread::Current()->IsMutatorThread());
1852 MonitorLocker ml(queue_monitor_);
1853 Function& function = Function::Handle();
1854 while (result_queue()->Peek() != NULL) {
1855 BackgroundCompilationResult result;
1856 QueueElement* qelem = result_queue()->Remove();
1857 ASSERT(qelem != NULL);
1858 result.SetFromQElement(qelem);
1859 delete qelem;
1860
1861 const Code& code = result.result_code();
1862 function ^= code.owner();
1863 Field& field = Field::Handle();
1864 // Always execute necessary deoptimizations, even if the result is invalid.
1865 for (intptr_t i = 0; i < result.deoptimize_dependent_fields().Length();
1866 i++) {
1867 field ^= result.deoptimize_dependent_fields().At(i);
1868 field.DeoptimizeDependentCode();
1869 }
1870 if (result.IsValid()) {
1871 function.InstallOptimizedCode(result.result_code(), false /* not OSR */);
1872 if (FLAG_trace_compiler) {
1873 THR_Print("Installing optimized code for %s\n",
1874 function.ToQualifiedCString());
1875 }
1876 // Install leaf classes and fields dependencies.
1877 Class& cls = Class::Handle();
1878 for (intptr_t i = 0; i < result.leaf_classes().Length(); i++) {
1879 cls ^= result.leaf_classes().At(i);
1880 cls.RegisterCHACode(code);
1881 }
1882 for (intptr_t i = 0; i < result.guarded_fields().Length(); i++) {
1883 field ^= result.guarded_fields().At(i);
1884 field.RegisterDependentCode(code);
1885 }
1886 } else if (FLAG_trace_compiler) {
1887 THR_Print("Drop code generated in the background compiler:\n");
1888 result.PrintValidity();
1889 }
1890 if (function.usage_counter() < 0) {
1891 // Reset to 0 so that it can be recompiled if needed.
1892 function.set_usage_counter(0);
1893 }
1894 if (result.IsValid() &&
1895 FLAG_disassemble_optimized &&
1896 FlowGraphPrinter::ShouldPrint(function)) {
1897 THR_Print("*** BEGIN CODE\n");
1898 DisassembleCode(function, true);
1899 THR_Print("*** END CODE\n");
1900 }
1901 }
1902 }
1903
1904
1905 void BackgroundCompiler::VisitPointers(ObjectPointerVisitor* visitor) { 1687 void BackgroundCompiler::VisitPointers(ObjectPointerVisitor* visitor) {
1906 function_queue_->VisitObjectPointers(visitor); 1688 function_queue_->VisitObjectPointers(visitor);
1907 result_queue_->VisitObjectPointers(visitor);
1908 } 1689 }
1909 1690
1910 1691
1911 void BackgroundCompiler::Stop(BackgroundCompiler* task) { 1692 void BackgroundCompiler::Stop(BackgroundCompiler* task) {
1912 ASSERT(Isolate::Current()->background_compiler() == task); 1693 ASSERT(Isolate::Current()->background_compiler() == task);
1913 if (task == NULL) { 1694 if (task == NULL) {
1914 return; 1695 return;
1915 } 1696 }
1916 BackgroundCompilationQueue* function_queue = task->function_queue(); 1697 BackgroundCompilationQueue* function_queue = task->function_queue();
1917 BackgroundCompilationQueue* result_queue = task->result_queue();
1918 1698
1919 Monitor* queue_monitor = task->queue_monitor_; 1699 Monitor* queue_monitor = task->queue_monitor_;
1920 Monitor* done_monitor = task->done_monitor_; 1700 Monitor* done_monitor = task->done_monitor_;
1921 bool* task_done = task->done_; 1701 bool* task_done = task->done_;
1922 // Wake up compiler task and stop it. 1702 // Wake up compiler task and stop it.
1923 { 1703 {
1924 MonitorLocker ml(task->queue_monitor_); 1704 MonitorLocker ml(task->queue_monitor_);
1925 task->running_ = false; 1705 task->running_ = false;
1926 // 'task' will be deleted by thread pool. 1706 // 'task' will be deleted by thread pool.
1927 task = NULL; 1707 task = NULL;
1928 ml.Notify(); // Stop waiting for the queue. 1708 ml.Notify(); // Stop waiting for the queue.
1929 } 1709 }
1930 1710
1931 { 1711 {
1932 MonitorLocker ml_done(done_monitor); 1712 MonitorLocker ml_done(done_monitor);
1933 while (!(*task_done)) { 1713 while (!(*task_done)) {
1934 ml_done.Wait(); 1714 // In case that the compiler is waiting for safepoint.
1715 Isolate::Current()->thread_registry()->CheckSafepoint();
1716 ml_done.Wait(1);
1935 } 1717 }
1936 } 1718 }
1937 delete task_done; 1719 delete task_done;
1938 delete done_monitor; 1720 delete done_monitor;
1939 delete queue_monitor; 1721 delete queue_monitor;
1940 delete function_queue; 1722 delete function_queue;
1941 delete result_queue;
1942 Isolate::Current()->set_background_compiler(NULL); 1723 Isolate::Current()->set_background_compiler(NULL);
1943 } 1724 }
1944 1725
1945 1726
1946 void BackgroundCompiler::EnsureInit(Thread* thread) { 1727 void BackgroundCompiler::EnsureInit(Thread* thread) {
1947 ASSERT(thread->IsMutatorThread()); 1728 ASSERT(thread->IsMutatorThread());
1948 // Finalize NoSuchMethodError, _Mint; occasionally needed in optimized 1729 // Finalize NoSuchMethodError, _Mint; occasionally needed in optimized
1949 // compilation. 1730 // compilation.
1950 Class& cls = Class::Handle(thread->zone(), 1731 Class& cls = Class::Handle(thread->zone(),
1951 Library::LookupCoreClass(Symbols::NoSuchMethodError())); 1732 Library::LookupCoreClass(Symbols::NoSuchMethodError()));
(...skipping 13 matching lines...) Expand all
1965 isolate->set_background_compiler(task); 1746 isolate->set_background_compiler(task);
1966 start_task = true; 1747 start_task = true;
1967 } 1748 }
1968 } 1749 }
1969 if (start_task) { 1750 if (start_task) {
1970 Dart::thread_pool()->Run(isolate->background_compiler()); 1751 Dart::thread_pool()->Run(isolate->background_compiler());
1971 } 1752 }
1972 } 1753 }
1973 1754
1974 } // namespace dart 1755 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/compiler.h ('k') | runtime/vm/compiler_test.cc » ('j') | runtime/vm/object.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698