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

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: Address comments 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
« no previous file with comments | « runtime/vm/compiler.h ('k') | runtime/vm/compiler_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 337 matching lines...) Expand 10 before | Expand all | Expand 10 after
385 return Error::null(); 386 return Error::null();
386 } 387 }
387 388
388 389
389 // Return false if bailed out. 390 // Return false if bailed out.
390 // If optimized_result_code is not NULL then it is caller's responsibility 391 // If optimized_result_code is not NULL then it is caller's responsibility
391 // to install code. 392 // to install code.
392 static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline, 393 static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline,
393 ParsedFunction* parsed_function, 394 ParsedFunction* parsed_function,
394 bool optimized, 395 bool optimized,
395 intptr_t osr_id, 396 intptr_t osr_id) {
396 BackgroundCompilationResult* result) {
397 const Function& function = parsed_function->function(); 397 const Function& function = parsed_function->function();
398 if (optimized && !function.IsOptimizable()) { 398 if (optimized && !function.IsOptimizable()) {
399 return false; 399 return false;
400 } 400 }
401 bool is_compiled = false; 401 bool is_compiled = false;
402 Thread* const thread = Thread::Current(); 402 Thread* const thread = Thread::Current();
403 Zone* const zone = thread->zone(); 403 Zone* const zone = thread->zone();
404 Isolate* const isolate = thread->isolate(); 404 Isolate* const isolate = thread->isolate();
405 CSTAT_TIMER_SCOPE(thread, codegen_timer); 405 CSTAT_TIMER_SCOPE(thread, codegen_timer);
406 HANDLESCOPE(thread); 406 HANDLESCOPE(thread);
407 407
408 // Get current generation count so that we can check and ensure that the code
409 // was not invalidated while we were compiling in the background.
410 uint32_t cha_invalidation_gen_at_start = isolate->cha_invalidation_gen();
411 uint32_t field_invalidation_gen_at_start = isolate->field_invalidation_gen();
412 uint32_t prefix_invalidation_gen_at_start =
413 isolate->prefix_invalidation_gen();
414
408 // We may reattempt compilation if the function needs to be assembled using 415 // We may reattempt compilation if the function needs to be assembled using
409 // far branches on ARM and MIPS. In the else branch of the setjmp call, 416 // far branches on ARM and MIPS. In the else branch of the setjmp call,
410 // done is set to false, and use_far_branches is set to true if there is a 417 // done is set to false, and use_far_branches is set to true if there is a
411 // longjmp from the ARM or MIPS assemblers. In all other paths through this 418 // longjmp from the ARM or MIPS assemblers. In all other paths through this
412 // while loop, done is set to true. use_far_branches is always false on ia32 419 // while loop, done is set to true. use_far_branches is always false on ia32
413 // and x64. 420 // and x64.
414 bool done = false; 421 bool done = false;
415 // volatile because the variable may be clobbered by a longjmp. 422 // volatile because the variable may be clobbered by a longjmp.
416 volatile bool use_far_branches = false; 423 volatile bool use_far_branches = false;
417 volatile bool use_speculative_inlining = true; 424 volatile bool use_speculative_inlining = true;
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after
745 FlowGraphCompiler graph_compiler(&assembler, flow_graph, 752 FlowGraphCompiler graph_compiler(&assembler, flow_graph,
746 *parsed_function, optimized, 753 *parsed_function, optimized,
747 inline_id_to_function, 754 inline_id_to_function,
748 caller_inline_id); 755 caller_inline_id);
749 { 756 {
750 CSTAT_TIMER_SCOPE(thread, graphcompiler_timer); 757 CSTAT_TIMER_SCOPE(thread, graphcompiler_timer);
751 graph_compiler.CompileGraph(); 758 graph_compiler.CompileGraph();
752 pipeline->FinalizeCompilation(); 759 pipeline->FinalizeCompilation();
753 } 760 }
754 { 761 {
762 // This part of compilation must be at a safepoint.
763 if (!Thread::Current()->IsMutatorThread()) {
764 // Stop mutator thread before creating the instruction object and
765 // installing code.
766 // Mutator thread may not run code while we are creating the
767 // instruction object, since the creation of instruction object
768 // changes code page access permissions (makes them temporary not
769 // executable).
770 isolate->thread_registry()->SafepointThreads();
771 }
755 CSTAT_TIMER_SCOPE(thread, codefinalizer_timer); 772 CSTAT_TIMER_SCOPE(thread, codefinalizer_timer);
756 // CreateDeoptInfo uses the object pool and needs to be done before 773 // CreateDeoptInfo uses the object pool and needs to be done before
757 // FinalizeCode. 774 // FinalizeCode.
758 const Array& deopt_info_array = 775 const Array& deopt_info_array =
759 Array::Handle(zone, graph_compiler.CreateDeoptInfo(&assembler)); 776 Array::Handle(zone, graph_compiler.CreateDeoptInfo(&assembler));
760 INC_STAT(thread, total_code_size, 777 INC_STAT(thread, total_code_size,
761 deopt_info_array.Length() * sizeof(uword)); 778 deopt_info_array.Length() * sizeof(uword));
779 // Allocates instruction object. Since this occurs only at safepoint,
780 // there can be no concurrent access to the instruction page.
762 const Code& code = Code::Handle( 781 const Code& code = Code::Handle(
763 Code::FinalizeCode(function, &assembler, optimized)); 782 Code::FinalizeCode(function, &assembler, optimized));
764 code.set_is_optimized(optimized); 783 code.set_is_optimized(optimized);
765 code.set_owner(function); 784 code.set_owner(function);
766 785
767 const Array& intervals = graph_compiler.inlined_code_intervals(); 786 const Array& intervals = graph_compiler.inlined_code_intervals();
768 INC_STAT(thread, total_code_size, 787 INC_STAT(thread, total_code_size,
769 intervals.Length() * sizeof(uword)); 788 intervals.Length() * sizeof(uword));
770 code.SetInlinedIntervals(intervals); 789 code.SetInlinedIntervals(intervals);
771 790
(...skipping 11 matching lines...) Expand all
783 802
784 graph_compiler.FinalizePcDescriptors(code); 803 graph_compiler.FinalizePcDescriptors(code);
785 code.set_deopt_info_array(deopt_info_array); 804 code.set_deopt_info_array(deopt_info_array);
786 805
787 graph_compiler.FinalizeStackmaps(code); 806 graph_compiler.FinalizeStackmaps(code);
788 graph_compiler.FinalizeVarDescriptors(code); 807 graph_compiler.FinalizeVarDescriptors(code);
789 graph_compiler.FinalizeExceptionHandlers(code); 808 graph_compiler.FinalizeExceptionHandlers(code);
790 graph_compiler.FinalizeStaticCallTargetsTable(code); 809 graph_compiler.FinalizeStaticCallTargetsTable(code);
791 810
792 if (optimized) { 811 if (optimized) {
793 if (result != NULL) { 812 // Installs code while at safepoint.
794 // Background compilation, store compilation result in 'result'. 813 if (thread->IsMutatorThread()) {
795 ASSERT(!Thread::Current()->IsMutatorThread());
796 // Do not install code, but return it instead.
797 // Since code dependencies (CHA, fields) are defined eagerly,
798 // the code may be disabled before installing it.
799 code.set_owner(function);
800 result->set_result_code(code);
801 // Disable invalidation counters that are not relevant.
802 if (thread->cha()->leaf_classes().is_empty()) {
803 result->ClearCHAInvalidationGen();
804 }
805 if (flow_graph->guarded_fields()->is_empty()) {
806 result->ClearFieldInvalidationGen();
807 }
808 if (!parsed_function->HasDeferredPrefixes()) {
809 result->ClearPrefixInvalidationGen();
810 }
811 } else {
812 const bool is_osr = osr_id != Compiler::kNoOSRDeoptId; 814 const bool is_osr = osr_id != Compiler::kNoOSRDeoptId;
813 function.InstallOptimizedCode(code, is_osr); 815 function.InstallOptimizedCode(code, is_osr);
816 } else {
817 // Background compilation.
818 // Before installing code check generation counts if the code may
819 // have become invalid.
820 bool code_is_valid = true;
821 if (!thread->cha()->leaf_classes().is_empty()) {
822 if (cha_invalidation_gen_at_start !=
823 isolate->cha_invalidation_gen()) {
824 code_is_valid = false;
825 }
826 }
827 if (!flow_graph->guarded_fields()->is_empty()) {
828 if (field_invalidation_gen_at_start !=
829 isolate->field_invalidation_gen()) {
830 code_is_valid = false;
831 }
832 }
833 if (parsed_function->HasDeferredPrefixes()) {
834 if (prefix_invalidation_gen_at_start !=
835 isolate->prefix_invalidation_gen()) {
836 code_is_valid = false;
837 }
838 }
839 if (code_is_valid) {
840 const bool is_osr = osr_id != Compiler::kNoOSRDeoptId;
841 ASSERT(!is_osr); // OSR is compiled in background.
842 function.InstallOptimizedCode(code, is_osr);
843 }
844 if (function.usage_counter() < 0) {
845 // Reset to 0 so that it can be recompiled if needed.
846 function.set_usage_counter(0);
847 }
814 } 848 }
815 849
816 // Register code with the classes it depends on because of CHA and 850 // Register code with the classes it depends on because of CHA and
817 // fields it depends on because of store guards, unless we cannot 851 // fields it depends on because of store guards, unless we cannot
818 // deopt. 852 // deopt.
819 if (Compiler::allow_recompilation()) { 853 if (Compiler::allow_recompilation()) {
820 if (result != NULL) { 854 // Deoptimize field dependent code first, before registering
821 // Background compilation: delay registering code until we are 855 // this yet uninstalled code as dependent on a field.
822 // in the MutatorThread. 856 // TODO(srdjan): Debugging dart2js crashes;
823 result->SetLeafClasses(thread->cha()->leaf_classes()); 857 // FlowGraphOptimizer::VisitStoreInstanceField populates
824 result->SetGuardedFields(*flow_graph->guarded_fields()); 858 // deoptimize_dependent_code() list, currently disabled.
825 result->SetDeoptimizeDependentFields( 859 for (intptr_t i = 0;
826 flow_graph->deoptimize_dependent_code()); 860 i < flow_graph->deoptimize_dependent_code().length();
827 } else { 861 i++) {
828 // Deoptimize field dependent code first, before registering 862 const Field* field = flow_graph->deoptimize_dependent_code()[i];
829 // this yet uninstalled code as dependent on a field. 863 field->DeoptimizeDependentCode();
830 // TODO(srdjan): Debugging dart2js crashes; 864 }
831 // FlowGraphOptimizer::VisitStoreInstanceField populates 865 for (intptr_t i = 0;
832 // deoptimize_dependent_code() list, currently disabled. 866 i < thread->cha()->leaf_classes().length();
833 for (intptr_t i = 0; 867 ++i) {
834 i < flow_graph->deoptimize_dependent_code().length(); 868 thread->cha()->leaf_classes()[i]->RegisterCHACode(code);
835 i++) { 869 }
836 const Field* field = flow_graph->deoptimize_dependent_code()[i]; 870 for (intptr_t i = 0;
837 field->DeoptimizeDependentCode(); 871 i < flow_graph->guarded_fields()->length();
838 } 872 i++) {
839 for (intptr_t i = 0; 873 const Field* field = (*flow_graph->guarded_fields())[i];
840 i < thread->cha()->leaf_classes().length(); 874 field->RegisterDependentCode(code);
841 ++i) {
842 thread->cha()->leaf_classes()[i]->RegisterCHACode(code);
843 }
844 for (intptr_t i = 0;
845 i < flow_graph->guarded_fields()->length();
846 i++) {
847 const Field* field = (*flow_graph->guarded_fields())[i];
848 field->RegisterDependentCode(code);
849 }
850 } 875 }
851 } 876 }
852 } else { // not optimized. 877 } else { // not optimized.
853 if (!Compiler::always_optimize() && 878 if (!Compiler::always_optimize() &&
854 (function.ic_data_array() == Array::null())) { 879 (function.ic_data_array() == Array::null())) {
855 function.SaveICDataMap( 880 function.SaveICDataMap(
856 graph_compiler.deopt_id_to_ic_data(), 881 graph_compiler.deopt_id_to_ic_data(),
857 Array::Handle(zone, graph_compiler.edge_counters_array())); 882 Array::Handle(zone, graph_compiler.edge_counters_array()));
858 } 883 }
859 function.set_unoptimized_code(code); 884 function.set_unoptimized_code(code);
860 function.AttachCode(code); 885 function.AttachCode(code);
861 } 886 }
862 if (parsed_function->HasDeferredPrefixes()) { 887 if (parsed_function->HasDeferredPrefixes()) {
863 ASSERT(!FLAG_load_deferred_eagerly); 888 ASSERT(!FLAG_load_deferred_eagerly);
864 ZoneGrowableArray<const LibraryPrefix*>* prefixes = 889 ZoneGrowableArray<const LibraryPrefix*>* prefixes =
865 parsed_function->deferred_prefixes(); 890 parsed_function->deferred_prefixes();
866 for (intptr_t i = 0; i < prefixes->length(); i++) { 891 for (intptr_t i = 0; i < prefixes->length(); i++) {
867 (*prefixes)[i]->RegisterDependentCode(code); 892 (*prefixes)[i]->RegisterDependentCode(code);
868 } 893 }
869 } 894 }
895 if (!Thread::Current()->IsMutatorThread()) {
896 // Background compilation.
897 isolate->thread_registry()->ResumeAllThreads();
898 }
870 } 899 }
871 // Mark that this isolate now has compiled code. 900 // Mark that this isolate now has compiled code.
872 isolate->set_has_compiled_code(true); 901 isolate->set_has_compiled_code(true);
873 // Exit the loop and the function with the correct result value. 902 // Exit the loop and the function with the correct result value.
874 is_compiled = true; 903 is_compiled = true;
875 done = true; 904 done = true;
876 } else { 905 } else {
877 // We bailed out or we encountered an error. 906 // We bailed out or we encountered an error.
878 const Error& error = Error::Handle( 907 const Error& error = Error::Handle(
879 isolate->object_store()->sticky_error()); 908 isolate->object_store()->sticky_error());
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
1085 ASSERT(inlined_functions[inlined_functions.length() - 1]->raw() == 1114 ASSERT(inlined_functions[inlined_functions.length() - 1]->raw() ==
1086 function.raw()); 1115 function.raw());
1087 } 1116 }
1088 } 1117 }
1089 #endif 1118 #endif
1090 1119
1091 1120
1092 static RawError* CompileFunctionHelper(CompilationPipeline* pipeline, 1121 static RawError* CompileFunctionHelper(CompilationPipeline* pipeline,
1093 const Function& function, 1122 const Function& function,
1094 bool optimized, 1123 bool optimized,
1095 intptr_t osr_id, 1124 intptr_t osr_id) {
1096 BackgroundCompilationResult* result) {
1097 // Check that we optimize if 'Compiler::always_optimize()' is set to true, 1125 // Check that we optimize if 'Compiler::always_optimize()' is set to true,
1098 // except if the function is marked as not optimizable. 1126 // except if the function is marked as not optimizable.
1099 ASSERT(!function.IsOptimizable() || 1127 ASSERT(!function.IsOptimizable() ||
1100 !Compiler::always_optimize() || optimized); 1128 !Compiler::always_optimize() || optimized);
1101 ASSERT(Compiler::allow_recompilation() || !function.HasCode()); 1129 ASSERT(Compiler::allow_recompilation() || !function.HasCode());
1102 LongJumpScope jump; 1130 LongJumpScope jump;
1103 if (setjmp(*jump.Set()) == 0) { 1131 if (setjmp(*jump.Set()) == 0) {
1104 Thread* const thread = Thread::Current(); 1132 Thread* const thread = Thread::Current();
1105 Isolate* const isolate = thread->isolate(); 1133 Isolate* const isolate = thread->isolate();
1106 StackZone stack_zone(thread); 1134 StackZone stack_zone(thread);
(...skipping 21 matching lines...) Expand all
1128 pipeline->ParseFunction(parsed_function); 1156 pipeline->ParseFunction(parsed_function);
1129 const int64_t num_tokens_after = STAT_VALUE(thread, num_tokens_consumed); 1157 const int64_t num_tokens_after = STAT_VALUE(thread, num_tokens_consumed);
1130 INC_STAT(thread, 1158 INC_STAT(thread,
1131 num_func_tokens_compiled, 1159 num_func_tokens_compiled,
1132 num_tokens_after - num_tokens_before); 1160 num_tokens_after - num_tokens_before);
1133 } 1161 }
1134 1162
1135 const bool success = CompileParsedFunctionHelper(pipeline, 1163 const bool success = CompileParsedFunctionHelper(pipeline,
1136 parsed_function, 1164 parsed_function,
1137 optimized, 1165 optimized,
1138 osr_id, 1166 osr_id);
1139 result);
1140 if (!success) { 1167 if (!success) {
1141 if (optimized) { 1168 if (optimized) {
1142 ASSERT(!Compiler::always_optimize()); // Optimized is the only code. 1169 ASSERT(!Compiler::always_optimize()); // Optimized is the only code.
1143 // Optimizer bailed out. Disable optimizations and never try again. 1170 // Optimizer bailed out. Disable optimizations and never try again.
1144 if (FLAG_trace_compiler) { 1171 if (FLAG_trace_compiler) {
1145 THR_Print("--> disabling optimizations for '%s'\n", 1172 THR_Print("--> disabling optimizations for '%s'\n",
1146 function.ToFullyQualifiedCString()); 1173 function.ToFullyQualifiedCString());
1147 } else if (FLAG_trace_failed_optimization_attempts) { 1174 } else if (FLAG_trace_failed_optimization_attempts) {
1148 THR_Print("Cannot optimize: %s\n", 1175 THR_Print("Cannot optimize: %s\n",
1149 function.ToFullyQualifiedCString()); 1176 function.ToFullyQualifiedCString());
(...skipping 19 matching lines...) Expand all
1169 Code::Handle(function.CurrentCode()).Size(), 1196 Code::Handle(function.CurrentCode()).Size(),
1170 per_compile_timer.TotalElapsedTime()); 1197 per_compile_timer.TotalElapsedTime());
1171 } 1198 }
1172 1199
1173 isolate->debugger()->NotifyCompilation(function); 1200 isolate->debugger()->NotifyCompilation(function);
1174 1201
1175 if (FLAG_disassemble && FlowGraphPrinter::ShouldPrint(function)) { 1202 if (FLAG_disassemble && FlowGraphPrinter::ShouldPrint(function)) {
1176 DisassembleCode(function, optimized); 1203 DisassembleCode(function, optimized);
1177 } else if (FLAG_disassemble_optimized && 1204 } else if (FLAG_disassemble_optimized &&
1178 optimized && 1205 optimized &&
1179 FlowGraphPrinter::ShouldPrint(function) && 1206 FlowGraphPrinter::ShouldPrint(function)) {
1180 (result == NULL) /* no background compilation*/ ) {
1181 // With background compilation, print when installing the code.
1182 // TODO(fschneider): Print unoptimized code along with the optimized code. 1207 // TODO(fschneider): Print unoptimized code along with the optimized code.
1183 THR_Print("*** BEGIN CODE\n"); 1208 THR_Print("*** BEGIN CODE\n");
1184 DisassembleCode(function, true); 1209 DisassembleCode(function, true);
1185 THR_Print("*** END CODE\n"); 1210 THR_Print("*** END CODE\n");
1186 } 1211 }
1187 #if defined(DEBUG) 1212 #if defined(DEBUG)
1188 CheckInliningIntervals(function); 1213 CheckInliningIntervals(function);
1189 #endif 1214 #endif
1190 return Error::null(); 1215 return Error::null();
1191 } else { 1216 } else {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1223 1248
1224 CompilationPipeline* pipeline = 1249 CompilationPipeline* pipeline =
1225 CompilationPipeline::New(thread->zone(), function); 1250 CompilationPipeline::New(thread->zone(), function);
1226 1251
1227 const bool optimized = 1252 const bool optimized =
1228 Compiler::always_optimize() && function.IsOptimizable(); 1253 Compiler::always_optimize() && function.IsOptimizable();
1229 1254
1230 return CompileFunctionHelper(pipeline, 1255 return CompileFunctionHelper(pipeline,
1231 function, 1256 function,
1232 optimized, 1257 optimized,
1233 kNoOSRDeoptId, /* not OSR */ 1258 kNoOSRDeoptId);
1234 NULL /* no result code */);
1235 } 1259 }
1236 1260
1237 1261
1238 RawError* Compiler::EnsureUnoptimizedCode(Thread* thread, 1262 RawError* Compiler::EnsureUnoptimizedCode(Thread* thread,
1239 const Function& function) { 1263 const Function& function) {
1240 if (function.unoptimized_code() != Object::null()) { 1264 if (function.unoptimized_code() != Object::null()) {
1241 return Error::null(); 1265 return Error::null();
1242 } 1266 }
1243 Code& original_code = Code::ZoneHandle(thread->zone()); 1267 Code& original_code = Code::ZoneHandle(thread->zone());
1244 if (function.HasCode()) { 1268 if (function.HasCode()) {
1245 original_code = function.CurrentCode(); 1269 original_code = function.CurrentCode();
1246 } 1270 }
1247 CompilationPipeline* pipeline = 1271 CompilationPipeline* pipeline =
1248 CompilationPipeline::New(thread->zone(), function); 1272 CompilationPipeline::New(thread->zone(), function);
1249 const Error& error = Error::Handle( 1273 const Error& error = Error::Handle(
1250 CompileFunctionHelper(pipeline, 1274 CompileFunctionHelper(pipeline,
1251 function, 1275 function,
1252 false, /* not optimized */ 1276 false, /* not optimized */
1253 kNoOSRDeoptId, /* not OSR */ 1277 kNoOSRDeoptId));
1254 NULL /* no result code */));
1255 if (!error.IsNull()) { 1278 if (!error.IsNull()) {
1256 return error.raw(); 1279 return error.raw();
1257 } 1280 }
1258 // Since CompileFunctionHelper replaces the current code, re-attach the 1281 // Since CompileFunctionHelper replaces the current code, re-attach the
1259 // the original code if the function was already compiled. 1282 // the original code if the function was already compiled.
1260 if (!original_code.IsNull() && 1283 if (!original_code.IsNull() &&
1261 (original_code.raw() != function.CurrentCode())) { 1284 (original_code.raw() != function.CurrentCode())) {
1262 function.AttachCode(original_code); 1285 function.AttachCode(original_code);
1263 } 1286 }
1264 ASSERT(function.unoptimized_code() != Object::null()); 1287 ASSERT(function.unoptimized_code() != Object::null());
1265 if (FLAG_trace_compiler) { 1288 if (FLAG_trace_compiler) {
1266 THR_Print("Ensure unoptimized code for %s\n", function.ToCString()); 1289 THR_Print("Ensure unoptimized code for %s\n", function.ToCString());
1267 } 1290 }
1268 return Error::null(); 1291 return Error::null();
1269 } 1292 }
1270 1293
1271 1294
1272 RawError* Compiler::CompileOptimizedFunction(Thread* thread, 1295 RawError* Compiler::CompileOptimizedFunction(Thread* thread,
1273 const Function& function, 1296 const Function& function,
1274 intptr_t osr_id, 1297 intptr_t osr_id) {
1275 BackgroundCompilationResult* res) {
1276 VMTagScope tagScope(thread, VMTag::kCompileOptimizedTagId); 1298 VMTagScope tagScope(thread, VMTag::kCompileOptimizedTagId);
1277 TIMELINE_FUNCTION_COMPILATION_DURATION(thread, 1299 TIMELINE_FUNCTION_COMPILATION_DURATION(thread,
1278 "OptimizedFunction", function); 1300 "OptimizedFunction", function);
1279 1301
1280 // Optimization must happen in non-mutator/Dart thread if background 1302 // Optimization must happen in non-mutator/Dart thread if background
1281 // compilation is on. OSR compilation still occurs in the main thread. 1303 // compilation is on. OSR compilation still occurs in the main thread.
1282 ASSERT((osr_id != kNoOSRDeoptId) || !FLAG_background_compilation || 1304 ASSERT((osr_id != kNoOSRDeoptId) || !FLAG_background_compilation ||
1283 !thread->IsMutatorThread()); 1305 !thread->IsMutatorThread());
1284 CompilationPipeline* pipeline = 1306 CompilationPipeline* pipeline =
1285 CompilationPipeline::New(thread->zone(), function); 1307 CompilationPipeline::New(thread->zone(), function);
1286 return CompileFunctionHelper(pipeline, 1308 return CompileFunctionHelper(pipeline,
1287 function, 1309 function,
1288 true, /* optimized */ 1310 true, /* optimized */
1289 osr_id, 1311 osr_id);
1290 res);
1291 } 1312 }
1292 1313
1293 1314
1294 // This is only used from unit tests. 1315 // This is only used from unit tests.
1295 RawError* Compiler::CompileParsedFunction( 1316 RawError* Compiler::CompileParsedFunction(
1296 ParsedFunction* parsed_function) { 1317 ParsedFunction* parsed_function) {
1297 LongJumpScope jump; 1318 LongJumpScope jump;
1298 if (setjmp(*jump.Set()) == 0) { 1319 if (setjmp(*jump.Set()) == 0) {
1299 // Non-optimized code generator. 1320 // Non-optimized code generator.
1300 DartCompilationPipeline pipeline; 1321 DartCompilationPipeline pipeline;
1301 CompileParsedFunctionHelper(&pipeline, 1322 CompileParsedFunctionHelper(&pipeline,
1302 parsed_function, 1323 parsed_function,
1303 false, 1324 false,
1304 kNoOSRDeoptId, 1325 kNoOSRDeoptId);
1305 NULL /* no result code */);
1306 if (FLAG_disassemble) { 1326 if (FLAG_disassemble) {
1307 DisassembleCode(parsed_function->function(), false); 1327 DisassembleCode(parsed_function->function(), false);
1308 } 1328 }
1309 return Error::null(); 1329 return Error::null();
1310 } else { 1330 } else {
1311 Isolate* const isolate = Isolate::Current(); 1331 Isolate* const isolate = Isolate::Current();
1312 Error& error = Error::Handle(); 1332 Error& error = Error::Handle();
1313 // We got an error during compilation. 1333 // We got an error during compilation.
1314 error = isolate->object_store()->sticky_error(); 1334 error = isolate->object_store()->sticky_error();
1315 isolate->object_store()->clear_sticky_error(); 1335 isolate->object_store()->clear_sticky_error();
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
1401 StackZone zone(thread); 1421 StackZone zone(thread);
1402 1422
1403 ParsedFunction* parsed_function = Parser::ParseStaticFieldInitializer(field); 1423 ParsedFunction* parsed_function = Parser::ParseStaticFieldInitializer(field);
1404 1424
1405 parsed_function->AllocateVariables(); 1425 parsed_function->AllocateVariables();
1406 // Non-optimized code generator. 1426 // Non-optimized code generator.
1407 DartCompilationPipeline pipeline; 1427 DartCompilationPipeline pipeline;
1408 CompileParsedFunctionHelper(&pipeline, 1428 CompileParsedFunctionHelper(&pipeline,
1409 parsed_function, 1429 parsed_function,
1410 false, // optimized 1430 false, // optimized
1411 kNoOSRDeoptId, 1431 kNoOSRDeoptId);
1412 NULL /* no result code */);
1413 1432
1414 const Function& initializer = parsed_function->function(); 1433 const Function& initializer = parsed_function->function();
1415 field.SetPrecompiledInitializer(initializer); 1434 field.SetPrecompiledInitializer(initializer);
1416 } 1435 }
1417 1436
1418 1437
1419 RawObject* Compiler::EvaluateStaticInitializer(const Field& field) { 1438 RawObject* Compiler::EvaluateStaticInitializer(const Field& field) {
1420 ASSERT(field.is_static()); 1439 ASSERT(field.is_static());
1421 // The VM sets the field's value to transiton_sentinel prior to 1440 // The VM sets the field's value to transiton_sentinel prior to
1422 // evaluating the initializer value. 1441 // evaluating the initializer value.
(...skipping 10 matching lines...) Expand all
1433 StackZone zone(thread); 1452 StackZone zone(thread);
1434 ParsedFunction* parsed_function = 1453 ParsedFunction* parsed_function =
1435 Parser::ParseStaticFieldInitializer(field); 1454 Parser::ParseStaticFieldInitializer(field);
1436 1455
1437 parsed_function->AllocateVariables(); 1456 parsed_function->AllocateVariables();
1438 // Non-optimized code generator. 1457 // Non-optimized code generator.
1439 DartCompilationPipeline pipeline; 1458 DartCompilationPipeline pipeline;
1440 CompileParsedFunctionHelper(&pipeline, 1459 CompileParsedFunctionHelper(&pipeline,
1441 parsed_function, 1460 parsed_function,
1442 false, // optimized 1461 false, // optimized
1443 kNoOSRDeoptId, 1462 kNoOSRDeoptId);
1444 NULL /* no result code */);
1445 initializer = parsed_function->function().raw(); 1463 initializer = parsed_function->function().raw();
1446 Code::Handle(initializer.unoptimized_code()).set_var_descriptors( 1464 Code::Handle(initializer.unoptimized_code()).set_var_descriptors(
1447 Object::empty_var_descriptors()); 1465 Object::empty_var_descriptors());
1448 } else { 1466 } else {
1449 initializer ^= field.PrecompiledInitializer(); 1467 initializer ^= field.PrecompiledInitializer();
1450 } 1468 }
1451 // Invoke the function to evaluate the expression. 1469 // Invoke the function to evaluate the expression.
1452 return DartEntry::InvokeFunction(initializer, Object::empty_array()); 1470 return DartEntry::InvokeFunction(initializer, Object::empty_array());
1453 } else { 1471 } else {
1454 Thread* const thread = Thread::Current(); 1472 Thread* const thread = Thread::Current();
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1504 fragment->scope()->AddVariable(parsed_function->EnsureExpressionTemp()); 1522 fragment->scope()->AddVariable(parsed_function->EnsureExpressionTemp());
1505 fragment->scope()->AddVariable( 1523 fragment->scope()->AddVariable(
1506 parsed_function->current_context_var()); 1524 parsed_function->current_context_var());
1507 parsed_function->AllocateVariables(); 1525 parsed_function->AllocateVariables();
1508 1526
1509 // Non-optimized code generator. 1527 // Non-optimized code generator.
1510 DartCompilationPipeline pipeline; 1528 DartCompilationPipeline pipeline;
1511 CompileParsedFunctionHelper(&pipeline, 1529 CompileParsedFunctionHelper(&pipeline,
1512 parsed_function, 1530 parsed_function,
1513 false, 1531 false,
1514 kNoOSRDeoptId, 1532 kNoOSRDeoptId);
1515 NULL /* no result code */);
1516 Code::Handle(func.unoptimized_code()).set_var_descriptors( 1533 Code::Handle(func.unoptimized_code()).set_var_descriptors(
1517 Object::empty_var_descriptors()); 1534 Object::empty_var_descriptors());
1518 1535
1519 const Object& result = PassiveObject::Handle( 1536 const Object& result = PassiveObject::Handle(
1520 DartEntry::InvokeFunction(func, Object::empty_array())); 1537 DartEntry::InvokeFunction(func, Object::empty_array()));
1521 return result.raw(); 1538 return result.raw();
1522 } else { 1539 } else {
1523 Thread* const thread = Thread::Current(); 1540 Thread* const thread = Thread::Current();
1524 Isolate* const isolate = thread->isolate(); 1541 Isolate* const isolate = thread->isolate();
1525 const Object& result = 1542 const Object& result =
1526 PassiveObject::Handle(isolate->object_store()->sticky_error()); 1543 PassiveObject::Handle(isolate->object_store()->sticky_error());
1527 isolate->object_store()->clear_sticky_error(); 1544 isolate->object_store()->clear_sticky_error();
1528 return result.raw(); 1545 return result.raw();
1529 } 1546 }
1530 UNREACHABLE(); 1547 UNREACHABLE();
1531 return Object::null(); 1548 return Object::null();
1532 } 1549 }
1533 1550
1534 1551
1535 // C-heap allocated background compilation queue element. 1552 // C-heap allocated background compilation queue element.
1536 class QueueElement { 1553 class QueueElement {
1537 public: 1554 public:
1538 explicit QueueElement(const Function& function) 1555 explicit QueueElement(const Function& function)
1539 : next_(NULL), 1556 : next_(NULL),
1540 obj_(function.raw()), 1557 function_(function.raw()) {
1541 leaf_classes_(Array::null()),
1542 guarded_fields_(Array::null()),
1543 deoptimize_dependent_fields_(Array::null()),
1544 cha_invalidation_gen_(Isolate::kInvalidGen),
1545 field_invalidation_gen_(Isolate::kInvalidGen),
1546 prefix_invalidation_gen_(Isolate::kInvalidGen) {
1547 ASSERT(Thread::Current()->IsMutatorThread()); 1558 ASSERT(Thread::Current()->IsMutatorThread());
1548 } 1559 }
1549 1560
1550 ~QueueElement() { 1561 ~QueueElement() {
1551 ASSERT(Thread::Current()->IsMutatorThread()); 1562 function_ = Function::null();
1552 obj_ = Object::null();
1553 } 1563 }
1554 1564
1555 RawFunction* Function() const { return Function::RawCast(obj_); } 1565 RawFunction* Function() const { return function_; }
1556 RawCode* Code() const { return Code::RawCast(obj_); }
1557 1566
1558 RawArray* leaf_classes() const { return leaf_classes_; }
1559 RawArray* guarded_fields() const { return guarded_fields_; }
1560 RawArray* deoptimize_dependent_fields() const {
1561 return deoptimize_dependent_fields_;
1562 }
1563
1564 uint32_t cha_invalidation_gen() const { return cha_invalidation_gen_; }
1565 uint32_t field_invalidation_gen() const { return field_invalidation_gen_; }
1566 uint32_t prefix_invalidation_gen() const { return prefix_invalidation_gen_; }
1567 1567
1568 void set_next(QueueElement* elem) { next_ = elem; } 1568 void set_next(QueueElement* elem) { next_ = elem; }
1569 QueueElement* next() const { return next_; } 1569 QueueElement* next() const { return next_; }
1570 1570
1571 RawObject* obj() const { return obj_; } 1571 RawObject* function() const { return function_; }
1572 RawObject** obj_ptr() { return &obj_; } 1572 RawObject** function_ptr() {
1573 1573 return reinterpret_cast<RawObject**>(&function_);
1574 RawObject** leaf_classses_ptr() {
1575 return reinterpret_cast<RawObject**>(&leaf_classes_);
1576 }
1577
1578 RawObject** guarded_fields_ptr() {
1579 return reinterpret_cast<RawObject**>(&guarded_fields_);
1580 }
1581
1582 RawObject** deoptimize_dependent_fields_ptr() {
1583 return reinterpret_cast<RawObject**>(&deoptimize_dependent_fields_);
1584 }
1585
1586 void SetFromResult(const BackgroundCompilationResult& value) {
1587 ASSERT(!value.result_code().IsNull());
1588 obj_ = value.result_code().raw();
1589 leaf_classes_ = value.leaf_classes().raw();
1590 guarded_fields_ = value.guarded_fields().raw();
1591 deoptimize_dependent_fields_ = value.deoptimize_dependent_fields().raw();
1592 cha_invalidation_gen_ = value.cha_invalidation_gen();
1593 field_invalidation_gen_ = value.field_invalidation_gen();
1594 prefix_invalidation_gen_ = value.prefix_invalidation_gen();
1595 } 1574 }
1596 1575
1597 private: 1576 private:
1598 QueueElement* next_; 1577 QueueElement* next_;
1599 1578 RawFunction* function_;
1600 RawObject* obj_; // Code or Function.
1601 RawArray* leaf_classes_;
1602 RawArray* guarded_fields_;
1603 RawArray* deoptimize_dependent_fields_;
1604 uint32_t cha_invalidation_gen_;
1605 uint32_t field_invalidation_gen_;
1606 uint32_t prefix_invalidation_gen_;
1607 1579
1608 DISALLOW_COPY_AND_ASSIGN(QueueElement); 1580 DISALLOW_COPY_AND_ASSIGN(QueueElement);
1609 }; 1581 };
1610 1582
1611 1583
1612 // Allocated in C-heap. Handles both input and output of background compilation. 1584 // Allocated in C-heap. Handles both input and output of background compilation.
1613 // It implements a FIFO queue, using Peek, Add, Remove operations. 1585 // It implements a FIFO queue, using Peek, Add, Remove operations.
1614 class BackgroundCompilationQueue { 1586 class BackgroundCompilationQueue {
1615 public: 1587 public:
1616 BackgroundCompilationQueue() : first_(NULL), last_(NULL) {} 1588 BackgroundCompilationQueue() : first_(NULL), last_(NULL) {}
1617 ~BackgroundCompilationQueue() { 1589 ~BackgroundCompilationQueue() {
1618 while (!IsEmpty()) { 1590 while (!IsEmpty()) {
1619 QueueElement* e = Remove(); 1591 QueueElement* e = Remove();
1620 delete e; 1592 delete e;
1621 } 1593 }
1622 ASSERT((first_ == NULL) && (last_ == NULL)); 1594 ASSERT((first_ == NULL) && (last_ == NULL));
1623 } 1595 }
1624 1596
1625 void VisitObjectPointers(ObjectPointerVisitor* visitor) { 1597 void VisitObjectPointers(ObjectPointerVisitor* visitor) {
1626 ASSERT(visitor != NULL); 1598 ASSERT(visitor != NULL);
1627 QueueElement* p = first_; 1599 QueueElement* p = first_;
1628 while (p != NULL) { 1600 while (p != NULL) {
1629 visitor->VisitPointer(p->obj_ptr()); 1601 visitor->VisitPointer(p->function_ptr());
1630 visitor->VisitPointer(p->leaf_classses_ptr());
1631 visitor->VisitPointer(p->guarded_fields_ptr());
1632 visitor->VisitPointer(p->deoptimize_dependent_fields_ptr());
1633 p = p->next(); 1602 p = p->next();
1634 } 1603 }
1635 } 1604 }
1636 1605
1637 bool IsEmpty() const { return first_ == NULL; } 1606 bool IsEmpty() const { return first_ == NULL; }
1638 1607
1639 void Add(QueueElement* value) { 1608 void Add(QueueElement* value) {
1640 ASSERT(value != NULL); 1609 ASSERT(value != NULL);
1641 if (first_ == NULL) { 1610 if (first_ == NULL) {
1642 first_ = value; 1611 first_ = value;
(...skipping 23 matching lines...) Expand all
1666 first_ = first_->next(); 1635 first_ = first_->next();
1667 if (first_ == NULL) { 1636 if (first_ == NULL) {
1668 last_ = NULL; 1637 last_ = NULL;
1669 } 1638 }
1670 return result; 1639 return result;
1671 } 1640 }
1672 1641
1673 bool ContainsObj(const Object& obj) const { 1642 bool ContainsObj(const Object& obj) const {
1674 QueueElement* p = first_; 1643 QueueElement* p = first_;
1675 while (p != NULL) { 1644 while (p != NULL) {
1676 if (p->obj() == obj.raw()) { 1645 if (p->function() == obj.raw()) {
1677 return true; 1646 return true;
1678 } 1647 }
1679 p = p->next(); 1648 p = p->next();
1680 } 1649 }
1681 return false; 1650 return false;
1682 } 1651 }
1683 1652
1684 private: 1653 private:
1685 QueueElement* first_; 1654 QueueElement* first_;
1686 QueueElement* last_; 1655 QueueElement* last_;
1687 1656
1688 DISALLOW_COPY_AND_ASSIGN(BackgroundCompilationQueue); 1657 DISALLOW_COPY_AND_ASSIGN(BackgroundCompilationQueue);
1689 }; 1658 };
1690 1659
1691 1660
1692 BackgroundCompilationResult::BackgroundCompilationResult()
1693 : result_code_(Code::Handle()),
1694 leaf_classes_(Array::Handle()),
1695 guarded_fields_(Array::Handle()),
1696 deoptimize_dependent_fields_(Array::Handle()),
1697 cha_invalidation_gen_(Isolate::kInvalidGen),
1698 field_invalidation_gen_(Isolate::kInvalidGen),
1699 prefix_invalidation_gen_(Isolate::kInvalidGen) {
1700 }
1701
1702
1703 void BackgroundCompilationResult::Init() {
1704 Isolate* i = Isolate::Current();
1705 result_code_ = Code::null();
1706 leaf_classes_ = Array::null();
1707 guarded_fields_ = Array::null();
1708 deoptimize_dependent_fields_ = Array::null();
1709 cha_invalidation_gen_ = i->cha_invalidation_gen();
1710 field_invalidation_gen_ = i->field_invalidation_gen();
1711 prefix_invalidation_gen_ = i->prefix_invalidation_gen();
1712 }
1713
1714
1715 void BackgroundCompilationResult::SetFromQElement(QueueElement* value) {
1716 ASSERT(value != NULL);
1717 result_code_ = value->Code();
1718 leaf_classes_ = value->leaf_classes();
1719 guarded_fields_ = value->guarded_fields();
1720 deoptimize_dependent_fields_ = value->deoptimize_dependent_fields();
1721 cha_invalidation_gen_ = value->cha_invalidation_gen();
1722 field_invalidation_gen_ = value->field_invalidation_gen();
1723 prefix_invalidation_gen_ = value->prefix_invalidation_gen();
1724 }
1725
1726
1727 void BackgroundCompilationResult::SetLeafClasses(
1728 const GrowableArray<Class*>& leaf_classes) {
1729 const Array& a = Array::Handle(Array::New(leaf_classes.length(), Heap::kOld));
1730 for (intptr_t i = 0; i < leaf_classes.length(); i++) {
1731 a.SetAt(i, *leaf_classes[i]);
1732 }
1733 leaf_classes_ = a.raw();
1734 }
1735
1736
1737 void BackgroundCompilationResult::SetGuardedFields(
1738 const ZoneGrowableArray<const Field*>& guarded_fields) {
1739 const Array& a =
1740 Array::Handle(Array::New(guarded_fields.length(), Heap::kOld));
1741 for (intptr_t i = 0; i < guarded_fields.length(); i++) {
1742 a.SetAt(i, *guarded_fields[i]);
1743 }
1744 guarded_fields_ = a.raw();
1745 }
1746
1747
1748 void BackgroundCompilationResult::SetDeoptimizeDependentFields(
1749 const GrowableArray<const Field*>& fields) {
1750 const Array& a = Array::Handle(Array::New(fields.length(), Heap::kOld));
1751 for (intptr_t i = 0; i < fields.length(); i++) {
1752 a.SetAt(i, *fields[i]);
1753 }
1754 deoptimize_dependent_fields_ = a.raw();
1755 }
1756
1757
1758 bool BackgroundCompilationResult::IsValid() const {
1759 if (result_code().IsNull() || result_code().IsDisabled()) {
1760 return false;
1761 }
1762 Isolate* i = Isolate::Current();
1763 if ((cha_invalidation_gen_ != Isolate::kInvalidGen) &&
1764 (cha_invalidation_gen_ != i->cha_invalidation_gen())) {
1765 return false;
1766 }
1767 if ((field_invalidation_gen_ != Isolate::kInvalidGen) &&
1768 (field_invalidation_gen_ != i->field_invalidation_gen())) {
1769 return false;
1770 }
1771 if ((prefix_invalidation_gen_ != Isolate::kInvalidGen) &&
1772 (prefix_invalidation_gen_ != i->prefix_invalidation_gen())) {
1773 return false;
1774 }
1775 return true;
1776 }
1777
1778
1779 void BackgroundCompilationResult::PrintValidity() const {
1780 Object& o = Object::Handle(result_code().owner());
1781 THR_Print("BackgroundCompilationResult: %s\n",
1782 Function::Cast(o).ToQualifiedCString());
1783 if (result_code().IsNull()) {
1784 THR_Print(" result_code is NULL\n");
1785 return;
1786 }
1787 if (result_code().IsDisabled()) {
1788 THR_Print(" result_code is disabled\n");
1789 return;
1790 }
1791 Isolate* i = Isolate::Current();
1792 THR_Print(" cha_invalidation_gen: %u (current: %u)\n",
1793 cha_invalidation_gen_, i->cha_invalidation_gen());
1794 THR_Print(" field_invalidation_gen: %u (current: %u)\n",
1795 field_invalidation_gen_, i->field_invalidation_gen());
1796 THR_Print(" prefix_invalidation_gen: %u (current: %u)\n",
1797 prefix_invalidation_gen_, i->prefix_invalidation_gen());
1798 }
1799
1800
1801 BackgroundCompiler::BackgroundCompiler(Isolate* isolate) 1661 BackgroundCompiler::BackgroundCompiler(Isolate* isolate)
1802 : isolate_(isolate), running_(true), done_(new bool()), 1662 : isolate_(isolate), running_(true), done_(new bool()),
1803 queue_monitor_(new Monitor()), done_monitor_(new Monitor()), 1663 queue_monitor_(new Monitor()), done_monitor_(new Monitor()),
1804 function_queue_(new BackgroundCompilationQueue()), 1664 function_queue_(new BackgroundCompilationQueue()) {
1805 result_queue_(new BackgroundCompilationQueue()) {
1806 *done_ = false; 1665 *done_ = false;
1807 } 1666 }
1808 1667
1809 1668
1810 void BackgroundCompiler::Run() { 1669 void BackgroundCompiler::Run() {
1811 while (running_) { 1670 while (running_) {
1812 // Maybe something is already in the queue, check first before waiting 1671 // Maybe something is already in the queue, check first before waiting
1813 // to be notified. 1672 // to be notified.
1814 Thread::EnterIsolateAsHelper(isolate_); 1673 Thread::EnterIsolateAsHelper(isolate_);
1815 { 1674 {
1816 Thread* thread = Thread::Current(); 1675 Thread* thread = Thread::Current();
1817 StackZone stack_zone(thread); 1676 StackZone stack_zone(thread);
1818 Zone* zone = stack_zone.GetZone(); 1677 Zone* zone = stack_zone.GetZone();
1819 HANDLESCOPE(thread); 1678 HANDLESCOPE(thread);
1820 Function& function = Function::Handle(zone); 1679 Function& function = Function::Handle(zone);
1821 function = function_queue()->PeekFunction(); 1680 function = function_queue()->PeekFunction();
1822 BackgroundCompilationResult result;
1823 while (running_ && !function.IsNull()) { 1681 while (running_ && !function.IsNull()) {
1824 result.Init();
1825 const Error& error = Error::Handle(zone, 1682 const Error& error = Error::Handle(zone,
1826 Compiler::CompileOptimizedFunction(thread, 1683 Compiler::CompileOptimizedFunction(thread,
1827 function, 1684 function,
1828 Compiler::kNoOSRDeoptId, 1685 Compiler::kNoOSRDeoptId));
1829 &result));
1830 // TODO(srdjan): We do not expect errors while compiling optimized 1686 // TODO(srdjan): We do not expect errors while compiling optimized
1831 // code, any errors should have been caught when compiling 1687 // code, any errors should have been caught when compiling
1832 // unoptimized code. Any issues while optimizing are flagged by 1688 // unoptimized code. Any issues while optimizing are flagged by
1833 // making the result invalid. 1689 // making the result invalid.
1834 ASSERT(error.IsNull()); 1690 ASSERT(error.IsNull());
1835 AddResult(result); 1691 QueueElement* qelem = function_queue()->Remove();
1692 delete qelem;
1836 function = function_queue()->PeekFunction(); 1693 function = function_queue()->PeekFunction();
1837 } 1694 }
1838 } 1695 }
1839 Thread::ExitIsolateAsHelper(); 1696 Thread::ExitIsolateAsHelper();
1840 { 1697 {
1841 // Wait to be notified when the work queue is not empty. 1698 // Wait to be notified when the work queue is not empty.
1842 MonitorLocker ml(queue_monitor_); 1699 MonitorLocker ml(queue_monitor_);
1843 while (function_queue()->IsEmpty() && running_) { 1700 while (function_queue()->IsEmpty() && running_) {
1844 ml.Wait(); 1701 ml.Wait();
1845 } 1702 }
1846 } 1703 }
1847 } // while running 1704 } // while running
1848 1705
1849 { 1706 {
1850 // Notify that the thread is done. 1707 // Notify that the thread is done.
1851 MonitorLocker ml_done(done_monitor_); 1708 MonitorLocker ml_done(done_monitor_);
1852 *done_ = true; 1709 *done_ = true;
1853 ml_done.Notify(); 1710 ml_done.Notify();
1854 } 1711 }
1855 } 1712 }
1856 1713
1857 1714
1858 // Use to first queue element to form the result element.
1859 void BackgroundCompiler::AddResult(const BackgroundCompilationResult& result) {
1860 ASSERT(!Thread::Current()->IsMutatorThread());
1861 MonitorLocker ml(queue_monitor_);
1862 // Reuse the input QueueElement to return the result.
1863 QueueElement* qelem = function_queue()->Remove();
1864 // Always add result, even if it is invalid, since the queue element is
1865 // deleted in the mutator thread and potential field based deoptimizations
1866 // (carried in the result) still must be done.
1867 qelem->SetFromResult(result);
1868 result_queue()->Add(qelem);
1869 }
1870
1871
1872 void BackgroundCompiler::CompileOptimized(const Function& function) { 1715 void BackgroundCompiler::CompileOptimized(const Function& function) {
1873 ASSERT(Thread::Current()->IsMutatorThread()); 1716 ASSERT(Thread::Current()->IsMutatorThread());
1874 MonitorLocker ml(queue_monitor_); 1717 MonitorLocker ml(queue_monitor_);
1875 if (function_queue()->ContainsObj(function)) { 1718 if (function_queue()->ContainsObj(function)) {
1876 return; 1719 return;
1877 } 1720 }
1878 QueueElement* elem = new QueueElement(function); 1721 QueueElement* elem = new QueueElement(function);
1879 function_queue()->Add(elem); 1722 function_queue()->Add(elem);
1880 ml.Notify(); 1723 ml.Notify();
1881 } 1724 }
1882 1725
1883 1726
1884 void BackgroundCompiler::InstallGeneratedCode() {
1885 ASSERT(Thread::Current()->IsMutatorThread());
1886 MonitorLocker ml(queue_monitor_);
1887 Function& function = Function::Handle();
1888 while (result_queue()->Peek() != NULL) {
1889 BackgroundCompilationResult result;
1890 QueueElement* qelem = result_queue()->Remove();
1891 ASSERT(qelem != NULL);
1892 result.SetFromQElement(qelem);
1893 delete qelem;
1894
1895 const Code& code = result.result_code();
1896 function ^= code.owner();
1897 Field& field = Field::Handle();
1898 // Always execute necessary deoptimizations, even if the result is invalid.
1899 for (intptr_t i = 0; i < result.deoptimize_dependent_fields().Length();
1900 i++) {
1901 field ^= result.deoptimize_dependent_fields().At(i);
1902 field.DeoptimizeDependentCode();
1903 }
1904 if (result.IsValid()) {
1905 function.InstallOptimizedCode(result.result_code(), false /* not OSR */);
1906 if (FLAG_trace_compiler) {
1907 THR_Print("Installing optimized code for %s\n",
1908 function.ToQualifiedCString());
1909 }
1910 // Install leaf classes and fields dependencies.
1911 Class& cls = Class::Handle();
1912 for (intptr_t i = 0; i < result.leaf_classes().Length(); i++) {
1913 cls ^= result.leaf_classes().At(i);
1914 cls.RegisterCHACode(code);
1915 }
1916 for (intptr_t i = 0; i < result.guarded_fields().Length(); i++) {
1917 field ^= result.guarded_fields().At(i);
1918 field.RegisterDependentCode(code);
1919 }
1920 } else if (FLAG_trace_compiler) {
1921 THR_Print("Drop code generated in the background compiler:\n");
1922 result.PrintValidity();
1923 }
1924 if (function.usage_counter() < 0) {
1925 // Reset to 0 so that it can be recompiled if needed.
1926 function.set_usage_counter(0);
1927 }
1928 if (result.IsValid() &&
1929 FLAG_disassemble_optimized &&
1930 FlowGraphPrinter::ShouldPrint(function)) {
1931 THR_Print("*** BEGIN CODE\n");
1932 DisassembleCode(function, true);
1933 THR_Print("*** END CODE\n");
1934 }
1935 }
1936 }
1937
1938
1939 void BackgroundCompiler::VisitPointers(ObjectPointerVisitor* visitor) { 1727 void BackgroundCompiler::VisitPointers(ObjectPointerVisitor* visitor) {
1940 function_queue_->VisitObjectPointers(visitor); 1728 function_queue_->VisitObjectPointers(visitor);
1941 result_queue_->VisitObjectPointers(visitor);
1942 } 1729 }
1943 1730
1944 1731
1945 void BackgroundCompiler::Stop(BackgroundCompiler* task) { 1732 void BackgroundCompiler::Stop(BackgroundCompiler* task) {
1946 ASSERT(Isolate::Current()->background_compiler() == task); 1733 ASSERT(Isolate::Current()->background_compiler() == task);
1947 if (task == NULL) { 1734 if (task == NULL) {
1948 return; 1735 return;
1949 } 1736 }
1950 BackgroundCompilationQueue* function_queue = task->function_queue(); 1737 BackgroundCompilationQueue* function_queue = task->function_queue();
1951 BackgroundCompilationQueue* result_queue = task->result_queue();
1952 1738
1953 Monitor* queue_monitor = task->queue_monitor_; 1739 Monitor* queue_monitor = task->queue_monitor_;
1954 Monitor* done_monitor = task->done_monitor_; 1740 Monitor* done_monitor = task->done_monitor_;
1955 bool* task_done = task->done_; 1741 bool* task_done = task->done_;
1956 // Wake up compiler task and stop it. 1742 // Wake up compiler task and stop it.
1957 { 1743 {
1958 MonitorLocker ml(task->queue_monitor_); 1744 MonitorLocker ml(task->queue_monitor_);
1959 task->running_ = false; 1745 task->running_ = false;
1960 // 'task' will be deleted by thread pool. 1746 // 'task' will be deleted by thread pool.
1961 task = NULL; 1747 task = NULL;
1962 ml.Notify(); // Stop waiting for the queue. 1748 ml.Notify(); // Stop waiting for the queue.
1963 } 1749 }
1964 1750
1965 { 1751 {
1966 MonitorLocker ml_done(done_monitor); 1752 MonitorLocker ml_done(done_monitor);
1967 while (!(*task_done)) { 1753 while (!(*task_done)) {
1968 ml_done.Wait(); 1754 // In case that the compiler is waiting for safepoint.
1755 Isolate::Current()->thread_registry()->CheckSafepoint();
1756 ml_done.Wait(1);
1969 } 1757 }
1970 } 1758 }
1971 delete task_done; 1759 delete task_done;
1972 delete done_monitor; 1760 delete done_monitor;
1973 delete queue_monitor; 1761 delete queue_monitor;
1974 delete function_queue; 1762 delete function_queue;
1975 delete result_queue;
1976 Isolate::Current()->set_background_compiler(NULL); 1763 Isolate::Current()->set_background_compiler(NULL);
1977 } 1764 }
1978 1765
1979 1766
1980 void BackgroundCompiler::EnsureInit(Thread* thread) { 1767 void BackgroundCompiler::EnsureInit(Thread* thread) {
1981 ASSERT(thread->IsMutatorThread()); 1768 ASSERT(thread->IsMutatorThread());
1982 // Finalize NoSuchMethodError, _Mint; occasionally needed in optimized 1769 // Finalize NoSuchMethodError, _Mint; occasionally needed in optimized
1983 // compilation. 1770 // compilation.
1984 Class& cls = Class::Handle(thread->zone(), 1771 Class& cls = Class::Handle(thread->zone(),
1985 Library::LookupCoreClass(Symbols::NoSuchMethodError())); 1772 Library::LookupCoreClass(Symbols::NoSuchMethodError()));
(...skipping 13 matching lines...) Expand all
1999 isolate->set_background_compiler(task); 1786 isolate->set_background_compiler(task);
2000 start_task = true; 1787 start_task = true;
2001 } 1788 }
2002 } 1789 }
2003 if (start_task) { 1790 if (start_task) {
2004 Dart::thread_pool()->Run(isolate->background_compiler()); 1791 Dart::thread_pool()->Run(isolate->background_compiler());
2005 } 1792 }
2006 } 1793 }
2007 1794
2008 } // namespace dart 1795 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/compiler.h ('k') | runtime/vm/compiler_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698