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

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

Issue 1410363005: Make ICData changes thread safe (first compute array, then set it). Install code in the main thread… (Closed) Base URL: https://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 360 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 error = isolate->object_store()->sticky_error(); 371 error = isolate->object_store()->sticky_error();
372 isolate->object_store()->clear_sticky_error(); 372 isolate->object_store()->clear_sticky_error();
373 return error.raw(); 373 return error.raw();
374 } 374 }
375 UNREACHABLE(); 375 UNREACHABLE();
376 return Error::null(); 376 return Error::null();
377 } 377 }
378 378
379 379
380 // Return false if bailed out. 380 // Return false if bailed out.
381 // If optimized_result_code is not NULL then it is caller's responsibility
382 // to install code.
381 static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline, 383 static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline,
382 ParsedFunction* parsed_function, 384 ParsedFunction* parsed_function,
383 bool optimized, 385 bool optimized,
384 intptr_t osr_id) { 386 intptr_t osr_id,
387 Code* optimized_result_code) {
385 const Function& function = parsed_function->function(); 388 const Function& function = parsed_function->function();
386 if (optimized && !function.IsOptimizable()) { 389 if (optimized && !function.IsOptimizable()) {
387 return false; 390 return false;
388 } 391 }
389 bool is_compiled = false; 392 bool is_compiled = false;
390 Thread* const thread = Thread::Current(); 393 Thread* const thread = Thread::Current();
391 Zone* const zone = thread->zone(); 394 Zone* const zone = thread->zone();
392 Isolate* const isolate = thread->isolate(); 395 Isolate* const isolate = thread->isolate();
393 CSTAT_TIMER_SCOPE(thread, codegen_timer); 396 CSTAT_TIMER_SCOPE(thread, codegen_timer);
394 HANDLESCOPE(thread); 397 HANDLESCOPE(thread);
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
440 *ic_data_array, 443 *ic_data_array,
441 osr_id); 444 osr_id);
442 } 445 }
443 446
444 const bool print_flow_graph = 447 const bool print_flow_graph =
445 (FLAG_print_flow_graph || 448 (FLAG_print_flow_graph ||
446 (optimized && FLAG_print_flow_graph_optimized)) && 449 (optimized && FLAG_print_flow_graph_optimized)) &&
447 FlowGraphPrinter::ShouldPrint(function); 450 FlowGraphPrinter::ShouldPrint(function);
448 451
449 if (print_flow_graph) { 452 if (print_flow_graph) {
450 if (osr_id == Thread::kNoDeoptId) { 453 if (osr_id == Compiler::kNoOSRDeoptId) {
451 FlowGraphPrinter::PrintGraph("Before Optimizations", flow_graph); 454 FlowGraphPrinter::PrintGraph("Before Optimizations", flow_graph);
452 } else { 455 } else {
453 FlowGraphPrinter::PrintGraph("For OSR", flow_graph); 456 FlowGraphPrinter::PrintGraph("For OSR", flow_graph);
454 } 457 }
455 } 458 }
456 459
457 BlockScheduler block_scheduler(flow_graph); 460 BlockScheduler block_scheduler(flow_graph);
458 const bool reorder_blocks = 461 const bool reorder_blocks =
459 FlowGraph::ShouldReorderBlocks(function, optimized); 462 FlowGraph::ShouldReorderBlocks(function, optimized);
460 if (reorder_blocks) { 463 if (reorder_blocks) {
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after
723 CSTAT_TIMER_SCOPE(thread, codefinalizer_timer); 726 CSTAT_TIMER_SCOPE(thread, codefinalizer_timer);
724 // CreateDeoptInfo uses the object pool and needs to be done before 727 // CreateDeoptInfo uses the object pool and needs to be done before
725 // FinalizeCode. 728 // FinalizeCode.
726 const Array& deopt_info_array = 729 const Array& deopt_info_array =
727 Array::Handle(zone, graph_compiler.CreateDeoptInfo(&assembler)); 730 Array::Handle(zone, graph_compiler.CreateDeoptInfo(&assembler));
728 INC_STAT(thread, total_code_size, 731 INC_STAT(thread, total_code_size,
729 deopt_info_array.Length() * sizeof(uword)); 732 deopt_info_array.Length() * sizeof(uword));
730 const Code& code = Code::Handle( 733 const Code& code = Code::Handle(
731 Code::FinalizeCode(function, &assembler, optimized)); 734 Code::FinalizeCode(function, &assembler, optimized));
732 code.set_is_optimized(optimized); 735 code.set_is_optimized(optimized);
736 code.set_owner(function);
733 737
734 const Array& intervals = graph_compiler.inlined_code_intervals(); 738 const Array& intervals = graph_compiler.inlined_code_intervals();
735 INC_STAT(thread, total_code_size, 739 INC_STAT(thread, total_code_size,
736 intervals.Length() * sizeof(uword)); 740 intervals.Length() * sizeof(uword));
737 code.SetInlinedIntervals(intervals); 741 code.SetInlinedIntervals(intervals);
738 742
739 const Array& inlined_id_array = 743 const Array& inlined_id_array =
740 Array::Handle(zone, graph_compiler.InliningIdToFunction()); 744 Array::Handle(zone, graph_compiler.InliningIdToFunction());
741 INC_STAT(thread, total_code_size, 745 INC_STAT(thread, total_code_size,
742 inlined_id_array.Length() * sizeof(uword)); 746 inlined_id_array.Length() * sizeof(uword));
743 code.SetInlinedIdToFunction(inlined_id_array); 747 code.SetInlinedIdToFunction(inlined_id_array);
744 748
745 const Array& caller_inlining_id_map_array = 749 const Array& caller_inlining_id_map_array =
746 Array::Handle(zone, graph_compiler.CallerInliningIdMap()); 750 Array::Handle(zone, graph_compiler.CallerInliningIdMap());
747 INC_STAT(thread, total_code_size, 751 INC_STAT(thread, total_code_size,
748 caller_inlining_id_map_array.Length() * sizeof(uword)); 752 caller_inlining_id_map_array.Length() * sizeof(uword));
749 code.SetInlinedCallerIdMap(caller_inlining_id_map_array); 753 code.SetInlinedCallerIdMap(caller_inlining_id_map_array);
750 754
751 graph_compiler.FinalizePcDescriptors(code); 755 graph_compiler.FinalizePcDescriptors(code);
752 code.set_deopt_info_array(deopt_info_array); 756 code.set_deopt_info_array(deopt_info_array);
753 757
754 graph_compiler.FinalizeStackmaps(code); 758 graph_compiler.FinalizeStackmaps(code);
755 graph_compiler.FinalizeVarDescriptors(code); 759 graph_compiler.FinalizeVarDescriptors(code);
756 graph_compiler.FinalizeExceptionHandlers(code); 760 graph_compiler.FinalizeExceptionHandlers(code);
757 graph_compiler.FinalizeStaticCallTargetsTable(code); 761 graph_compiler.FinalizeStaticCallTargetsTable(code);
758 762
759 if (optimized) { 763 if (optimized) {
760 // We may not have previous code if 'always_optimize' is set. 764 if (optimized_result_code != NULL) {
761 if ((osr_id == Thread::kNoDeoptId) && function.HasCode()) { 765 // Do not install code, but return it instead.
762 Code::Handle(function.CurrentCode()).DisableDartCode(); 766 // Since code dependencies (CHA, fields) are defined eagerly,
767 // the code may be disabled before installing it.
768 code.set_owner(function);
769 *optimized_result_code = code.raw();
770 } else {
771 const bool is_osr = osr_id != Compiler::kNoOSRDeoptId;
772 function.InstallOptimizedCode(code, is_osr);
763 } 773 }
764 function.AttachCode(code);
765 774
775 // TODO(srdjan): In background compilation, verify that CHA has not
776 // been invalidated in the meantime.
766 // Register code with the classes it depends on because of CHA. 777 // Register code with the classes it depends on because of CHA.
767 for (intptr_t i = 0; 778 for (intptr_t i = 0;
768 i < thread->cha()->leaf_classes().length(); 779 i < thread->cha()->leaf_classes().length();
769 ++i) { 780 ++i) {
770 thread->cha()->leaf_classes()[i]->RegisterCHACode(code); 781 thread->cha()->leaf_classes()[i]->RegisterCHACode(code);
771 } 782 }
772 783
773 for (intptr_t i = 0; 784 for (intptr_t i = 0;
774 i < flow_graph->guarded_fields()->length(); 785 i < flow_graph->guarded_fields()->length();
775 i++) { 786 i++) {
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
993 ASSERT(inlined_functions[inlined_functions.length() - 1]->raw() == 1004 ASSERT(inlined_functions[inlined_functions.length() - 1]->raw() ==
994 function.raw()); 1005 function.raw());
995 } 1006 }
996 } 1007 }
997 #endif 1008 #endif
998 1009
999 1010
1000 static RawError* CompileFunctionHelper(CompilationPipeline* pipeline, 1011 static RawError* CompileFunctionHelper(CompilationPipeline* pipeline,
1001 const Function& function, 1012 const Function& function,
1002 bool optimized, 1013 bool optimized,
1003 intptr_t osr_id) { 1014 intptr_t osr_id,
1015 Code* result_code) {
1004 // Check that we optimize if 'Compiler::always_optimize()' is set to true, 1016 // Check that we optimize if 'Compiler::always_optimize()' is set to true,
1005 // except if the function is marked as not optimizable. 1017 // except if the function is marked as not optimizable.
1006 ASSERT(!function.IsOptimizable() || 1018 ASSERT(!function.IsOptimizable() ||
1007 !Compiler::always_optimize() || optimized); 1019 !Compiler::always_optimize() || optimized);
1008 ASSERT(Compiler::allow_recompilation() || !function.HasCode()); 1020 ASSERT(Compiler::allow_recompilation() || !function.HasCode());
1009 LongJumpScope jump; 1021 LongJumpScope jump;
1010 if (setjmp(*jump.Set()) == 0) { 1022 if (setjmp(*jump.Set()) == 0) {
1011 Thread* const thread = Thread::Current(); 1023 Thread* const thread = Thread::Current();
1012 Isolate* const isolate = thread->isolate(); 1024 Isolate* const isolate = thread->isolate();
1013 StackZone stack_zone(thread); 1025 StackZone stack_zone(thread);
1014 Zone* const zone = stack_zone.GetZone(); 1026 Zone* const zone = stack_zone.GetZone();
1015 Timer per_compile_timer(FLAG_trace_compiler, "Compilation time"); 1027 Timer per_compile_timer(FLAG_trace_compiler, "Compilation time");
1016 per_compile_timer.Start(); 1028 per_compile_timer.Start();
1017 1029
1018 ParsedFunction* parsed_function = new(zone) ParsedFunction( 1030 ParsedFunction* parsed_function = new(zone) ParsedFunction(
1019 thread, Function::ZoneHandle(zone, function.raw())); 1031 thread, Function::ZoneHandle(zone, function.raw()));
1020 if (FLAG_trace_compiler) { 1032 if (FLAG_trace_compiler) {
1021 THR_Print("Compiling %s%sfunction: '%s' @ token %" Pd ", size %" Pd "\n", 1033 THR_Print("Compiling %s%sfunction: '%s' @ token %" Pd ", size %" Pd "\n",
1022 (osr_id == Thread::kNoDeoptId ? "" : "osr "), 1034 (osr_id == Compiler::kNoOSRDeoptId ? "" : "osr "),
1023 (optimized ? "optimized " : ""), 1035 (optimized ? "optimized " : ""),
1024 function.ToFullyQualifiedCString(), 1036 function.ToFullyQualifiedCString(),
1025 function.token_pos(), 1037 function.token_pos(),
1026 (function.end_token_pos() - function.token_pos())); 1038 (function.end_token_pos() - function.token_pos()));
1027 } 1039 }
1028 INC_STAT(thread, num_functions_compiled, 1); 1040 INC_STAT(thread, num_functions_compiled, 1);
1029 if (optimized) { 1041 if (optimized) {
1030 INC_STAT(thread, num_functions_optimized, 1); 1042 INC_STAT(thread, num_functions_optimized, 1);
1031 } 1043 }
1032 { 1044 {
1033 HANDLESCOPE(thread); 1045 HANDLESCOPE(thread);
1034 const int64_t num_tokens_before = STAT_VALUE(thread, num_tokens_consumed); 1046 const int64_t num_tokens_before = STAT_VALUE(thread, num_tokens_consumed);
1035 pipeline->ParseFunction(parsed_function); 1047 pipeline->ParseFunction(parsed_function);
1036 const int64_t num_tokens_after = STAT_VALUE(thread, num_tokens_consumed); 1048 const int64_t num_tokens_after = STAT_VALUE(thread, num_tokens_consumed);
1037 INC_STAT(thread, 1049 INC_STAT(thread,
1038 num_func_tokens_compiled, 1050 num_func_tokens_compiled,
1039 num_tokens_after - num_tokens_before); 1051 num_tokens_after - num_tokens_before);
1040 } 1052 }
1041 1053
1042 const bool success = CompileParsedFunctionHelper(pipeline, 1054 const bool success = CompileParsedFunctionHelper(pipeline,
1043 parsed_function, 1055 parsed_function,
1044 optimized, 1056 optimized,
1045 osr_id); 1057 osr_id,
1058 result_code);
1046 if (!success) { 1059 if (!success) {
1047 if (optimized) { 1060 if (optimized) {
1048 ASSERT(!Compiler::always_optimize()); // Optimized is the only code. 1061 ASSERT(!Compiler::always_optimize()); // Optimized is the only code.
1049 // Optimizer bailed out. Disable optimizations and never try again. 1062 // Optimizer bailed out. Disable optimizations and never try again.
1050 if (FLAG_trace_compiler) { 1063 if (FLAG_trace_compiler) {
1051 THR_Print("--> disabling optimizations for '%s'\n", 1064 THR_Print("--> disabling optimizations for '%s'\n",
1052 function.ToFullyQualifiedCString()); 1065 function.ToFullyQualifiedCString());
1053 } else if (FLAG_trace_failed_optimization_attempts) { 1066 } else if (FLAG_trace_failed_optimization_attempts) {
1054 THR_Print("Cannot optimize: %s\n", 1067 THR_Print("Cannot optimize: %s\n",
1055 function.ToFullyQualifiedCString()); 1068 function.ToFullyQualifiedCString());
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1113 function.token_pos(), 1126 function.token_pos(),
1114 Function::KindToCString(function.kind())); 1127 Function::KindToCString(function.kind()));
1115 } 1128 }
1116 1129
1117 CompilationPipeline* pipeline = 1130 CompilationPipeline* pipeline =
1118 CompilationPipeline::New(thread->zone(), function); 1131 CompilationPipeline::New(thread->zone(), function);
1119 1132
1120 const bool optimized = 1133 const bool optimized =
1121 Compiler::always_optimize() && function.IsOptimizable(); 1134 Compiler::always_optimize() && function.IsOptimizable();
1122 1135
1123 return CompileFunctionHelper(pipeline, function, optimized, 1136 return CompileFunctionHelper(pipeline,
1124 Thread::kNoDeoptId); 1137 function,
1138 optimized,
1139 kNoOSRDeoptId, /* not OSR */
1140 NULL /* no result code */);
1125 } 1141 }
1126 1142
1127 1143
1128 RawError* Compiler::EnsureUnoptimizedCode(Thread* thread, 1144 RawError* Compiler::EnsureUnoptimizedCode(Thread* thread,
1129 const Function& function) { 1145 const Function& function) {
1130 if (function.unoptimized_code() != Object::null()) { 1146 if (function.unoptimized_code() != Object::null()) {
1131 return Error::null(); 1147 return Error::null();
1132 } 1148 }
1133 Code& original_code = Code::ZoneHandle(thread->zone()); 1149 Code& original_code = Code::ZoneHandle(thread->zone());
1134 if (function.HasCode()) { 1150 if (function.HasCode()) {
1135 original_code = function.CurrentCode(); 1151 original_code = function.CurrentCode();
1136 } 1152 }
1137 CompilationPipeline* pipeline = 1153 CompilationPipeline* pipeline =
1138 CompilationPipeline::New(thread->zone(), function); 1154 CompilationPipeline::New(thread->zone(), function);
1139 const Error& error = Error::Handle( 1155 const Error& error = Error::Handle(
1140 CompileFunctionHelper(pipeline, function, false, Thread::kNoDeoptId)); 1156 CompileFunctionHelper(pipeline,
1157 function,
1158 false, /* not optimized */
1159 kNoOSRDeoptId, /* not OSR */
1160 NULL /* no result code */));
1141 if (!error.IsNull()) { 1161 if (!error.IsNull()) {
1142 return error.raw(); 1162 return error.raw();
1143 } 1163 }
1144 // Since CompileFunctionHelper replaces the current code, re-attach the 1164 // Since CompileFunctionHelper replaces the current code, re-attach the
1145 // the original code if the function was already compiled. 1165 // the original code if the function was already compiled.
1146 if (!original_code.IsNull() && 1166 if (!original_code.IsNull() &&
1147 (original_code.raw() != function.CurrentCode())) { 1167 (original_code.raw() != function.CurrentCode())) {
1148 function.AttachCode(original_code); 1168 function.AttachCode(original_code);
1149 } 1169 }
1150 ASSERT(function.unoptimized_code() != Object::null()); 1170 ASSERT(function.unoptimized_code() != Object::null());
1151 if (FLAG_trace_compiler) { 1171 if (FLAG_trace_compiler) {
1152 THR_Print("Ensure unoptimized code for %s\n", function.ToCString()); 1172 THR_Print("Ensure unoptimized code for %s\n", function.ToCString());
1153 } 1173 }
1154 return Error::null(); 1174 return Error::null();
1155 } 1175 }
1156 1176
1157 1177
1158 RawError* Compiler::CompileOptimizedFunction(Thread* thread, 1178 RawError* Compiler::CompileOptimizedFunction(Thread* thread,
1159 const Function& function, 1179 const Function& function,
1160 intptr_t osr_id) { 1180 intptr_t osr_id,
1181 Code* result_code) {
1161 VMTagScope tagScope(thread, VMTag::kCompileOptimizedTagId); 1182 VMTagScope tagScope(thread, VMTag::kCompileOptimizedTagId);
1162 TIMELINE_FUNCTION_COMPILATION_DURATION(thread, 1183 TIMELINE_FUNCTION_COMPILATION_DURATION(thread,
1163 "OptimizedFunction", function); 1184 "OptimizedFunction", function);
1164 1185
1165 // Optimization must happen in non-mutator/Dart thread if background 1186 // Optimization must happen in non-mutator/Dart thread if background
1166 // compilation is on. OSR compilation still occurs in the main thread. 1187 // compilation is on. OSR compilation still occurs in the main thread.
1167 ASSERT((osr_id != Thread::kNoDeoptId) || !FLAG_background_compilation || 1188 ASSERT((osr_id != kNoOSRDeoptId) || !FLAG_background_compilation ||
1168 !thread->IsMutatorThread()); 1189 !thread->IsMutatorThread());
1169 CompilationPipeline* pipeline = 1190 CompilationPipeline* pipeline =
1170 CompilationPipeline::New(thread->zone(), function); 1191 CompilationPipeline::New(thread->zone(), function);
1171 return CompileFunctionHelper(pipeline, function, true, osr_id); 1192 return CompileFunctionHelper(pipeline,
1193 function,
1194 true, /* optimized */
1195 osr_id,
1196 result_code);
1172 } 1197 }
1173 1198
1174 1199
1175 // This is only used from unit tests. 1200 // This is only used from unit tests.
1176 RawError* Compiler::CompileParsedFunction( 1201 RawError* Compiler::CompileParsedFunction(
1177 ParsedFunction* parsed_function) { 1202 ParsedFunction* parsed_function) {
1178 LongJumpScope jump; 1203 LongJumpScope jump;
1179 if (setjmp(*jump.Set()) == 0) { 1204 if (setjmp(*jump.Set()) == 0) {
1180 // Non-optimized code generator. 1205 // Non-optimized code generator.
1181 DartCompilationPipeline pipeline; 1206 DartCompilationPipeline pipeline;
1182 CompileParsedFunctionHelper(&pipeline, 1207 CompileParsedFunctionHelper(&pipeline,
1183 parsed_function, 1208 parsed_function,
1184 false, 1209 false,
1185 Thread::kNoDeoptId); 1210 kNoOSRDeoptId,
1211 NULL /* no result code */);
1186 if (FLAG_disassemble) { 1212 if (FLAG_disassemble) {
1187 DisassembleCode(parsed_function->function(), false); 1213 DisassembleCode(parsed_function->function(), false);
1188 } 1214 }
1189 return Error::null(); 1215 return Error::null();
1190 } else { 1216 } else {
1191 Isolate* const isolate = Isolate::Current(); 1217 Isolate* const isolate = Isolate::Current();
1192 Error& error = Error::Handle(); 1218 Error& error = Error::Handle();
1193 // We got an error during compilation. 1219 // We got an error during compilation.
1194 error = isolate->object_store()->sticky_error(); 1220 error = isolate->object_store()->sticky_error();
1195 isolate->object_store()->clear_sticky_error(); 1221 isolate->object_store()->clear_sticky_error();
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
1281 StackZone zone(thread); 1307 StackZone zone(thread);
1282 1308
1283 ParsedFunction* parsed_function = Parser::ParseStaticFieldInitializer(field); 1309 ParsedFunction* parsed_function = Parser::ParseStaticFieldInitializer(field);
1284 1310
1285 parsed_function->AllocateVariables(); 1311 parsed_function->AllocateVariables();
1286 // Non-optimized code generator. 1312 // Non-optimized code generator.
1287 DartCompilationPipeline pipeline; 1313 DartCompilationPipeline pipeline;
1288 CompileParsedFunctionHelper(&pipeline, 1314 CompileParsedFunctionHelper(&pipeline,
1289 parsed_function, 1315 parsed_function,
1290 false, // optimized 1316 false, // optimized
1291 Thread::kNoDeoptId); 1317 kNoOSRDeoptId,
1318 NULL /* no result code */);
1292 1319
1293 const Function& initializer = parsed_function->function(); 1320 const Function& initializer = parsed_function->function();
1294 field.SetPrecompiledInitializer(initializer); 1321 field.SetPrecompiledInitializer(initializer);
1295 } 1322 }
1296 1323
1297 1324
1298 RawObject* Compiler::EvaluateStaticInitializer(const Field& field) { 1325 RawObject* Compiler::EvaluateStaticInitializer(const Field& field) {
1299 ASSERT(field.is_static()); 1326 ASSERT(field.is_static());
1300 // The VM sets the field's value to transiton_sentinel prior to 1327 // The VM sets the field's value to transiton_sentinel prior to
1301 // evaluating the initializer value. 1328 // evaluating the initializer value.
(...skipping 10 matching lines...) Expand all
1312 StackZone zone(thread); 1339 StackZone zone(thread);
1313 ParsedFunction* parsed_function = 1340 ParsedFunction* parsed_function =
1314 Parser::ParseStaticFieldInitializer(field); 1341 Parser::ParseStaticFieldInitializer(field);
1315 1342
1316 parsed_function->AllocateVariables(); 1343 parsed_function->AllocateVariables();
1317 // Non-optimized code generator. 1344 // Non-optimized code generator.
1318 DartCompilationPipeline pipeline; 1345 DartCompilationPipeline pipeline;
1319 CompileParsedFunctionHelper(&pipeline, 1346 CompileParsedFunctionHelper(&pipeline,
1320 parsed_function, 1347 parsed_function,
1321 false, // optimized 1348 false, // optimized
1322 Thread::kNoDeoptId); 1349 kNoOSRDeoptId,
1350 NULL /* no result code */);
1323 initializer = parsed_function->function().raw(); 1351 initializer = parsed_function->function().raw();
1324 Code::Handle(initializer.unoptimized_code()).set_var_descriptors( 1352 Code::Handle(initializer.unoptimized_code()).set_var_descriptors(
1325 Object::empty_var_descriptors()); 1353 Object::empty_var_descriptors());
1326 } else { 1354 } else {
1327 initializer ^= field.PrecompiledInitializer(); 1355 initializer ^= field.PrecompiledInitializer();
1328 } 1356 }
1329 // Invoke the function to evaluate the expression. 1357 // Invoke the function to evaluate the expression.
1330 return DartEntry::InvokeFunction(initializer, Object::empty_array()); 1358 return DartEntry::InvokeFunction(initializer, Object::empty_array());
1331 } else { 1359 } else {
1332 Thread* const thread = Thread::Current(); 1360 Thread* const thread = Thread::Current();
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1382 fragment->scope()->AddVariable(parsed_function->EnsureExpressionTemp()); 1410 fragment->scope()->AddVariable(parsed_function->EnsureExpressionTemp());
1383 fragment->scope()->AddVariable( 1411 fragment->scope()->AddVariable(
1384 parsed_function->current_context_var()); 1412 parsed_function->current_context_var());
1385 parsed_function->AllocateVariables(); 1413 parsed_function->AllocateVariables();
1386 1414
1387 // Non-optimized code generator. 1415 // Non-optimized code generator.
1388 DartCompilationPipeline pipeline; 1416 DartCompilationPipeline pipeline;
1389 CompileParsedFunctionHelper(&pipeline, 1417 CompileParsedFunctionHelper(&pipeline,
1390 parsed_function, 1418 parsed_function,
1391 false, 1419 false,
1392 Thread::kNoDeoptId); 1420 kNoOSRDeoptId,
1421 NULL /* no result code */);
1393 Code::Handle(func.unoptimized_code()).set_var_descriptors( 1422 Code::Handle(func.unoptimized_code()).set_var_descriptors(
1394 Object::empty_var_descriptors()); 1423 Object::empty_var_descriptors());
1395 1424
1396 const Object& result = PassiveObject::Handle( 1425 const Object& result = PassiveObject::Handle(
1397 DartEntry::InvokeFunction(func, Object::empty_array())); 1426 DartEntry::InvokeFunction(func, Object::empty_array()));
1398 return result.raw(); 1427 return result.raw();
1399 } else { 1428 } else {
1400 Thread* const thread = Thread::Current(); 1429 Thread* const thread = Thread::Current();
1401 Isolate* const isolate = thread->isolate(); 1430 Isolate* const isolate = thread->isolate();
1402 const Object& result = 1431 const Object& result =
1403 PassiveObject::Handle(isolate->object_store()->sticky_error()); 1432 PassiveObject::Handle(isolate->object_store()->sticky_error());
1404 isolate->object_store()->clear_sticky_error(); 1433 isolate->object_store()->clear_sticky_error();
1405 return result.raw(); 1434 return result.raw();
1406 } 1435 }
1407 UNREACHABLE(); 1436 UNREACHABLE();
1408 return Object::null(); 1437 return Object::null();
1409 } 1438 }
1410 1439
1411 1440
1412 // A simple work queue containing functions to be optimized. Use 1441 // A simple work queue containing functions to be optimized or code generated.
1413 // PushFront and PopBack to add and read from queue. 1442 // Use PushFrontFunction and PopBackFunction to add and remove from the function
1443 // queue and PushBackCode and PopBackCode to add and remove from the code queue.
1414 // TODO(srdjan): Write a more efficient implementation. 1444 // TODO(srdjan): Write a more efficient implementation.
1415 class CompilationWorkQueue : public ValueObject { 1445 class CompilationWorkQueue : public ValueObject {
1416 public: 1446 public:
1417 explicit CompilationWorkQueue(Isolate* isolate) : 1447 explicit CompilationWorkQueue(GrowableObjectArray* data) : data_(data) {}
1418 data_(GrowableObjectArray::Handle()) {
1419 data_ = isolate->background_compilation_queue();
1420 }
1421 1448
1422 intptr_t IsEmpty() const { return data_.Length() == 0; } 1449 intptr_t IsEmpty() const { return data_->Length() == 0; }
1423 intptr_t Length() const { return data_.Length(); } 1450 intptr_t Length() const { return data_->Length(); }
1424 1451
1452 void PushFrontFunction(const Function& function) { PushFront(function); }
1453 RawFunction* PopBackFunction() { return Function::RawCast(PopBack()); }
1454 RawFunction* LastFunction() { return Function::RawCast(Last()); }
1455
1456 void PushBackCode(const Code& code) { PushBack(code); }
1457 RawCode* PopBackCode() { return Code::RawCast(PopBack()); }
1458 RawCode* LastCode() { return Code::RawCast(Last()); }
1459
1460 private:
1425 // Adds to the queue only if 'function' is not already in there. 1461 // Adds to the queue only if 'function' is not already in there.
1426 void PushFront(const Function& function) { 1462 void PushFront(const Object& value) {
1427 for (intptr_t i = 0; i < data_.Length(); i++) { 1463 for (intptr_t i = 0; i < data_->Length(); i++) {
1428 if (data_.At(i) == function.raw()) { 1464 if (data_->At(i) == value.raw()) {
1429 return; 1465 return;
1430 } 1466 }
1431 } 1467 }
1432 // Insert new element in front. 1468 // Insert new element in front.
1433 Object& f = Object::Handle(); 1469 Object& f = Object::Handle();
1434 data_.Add(f); 1470 data_->Add(f);
1435 for (intptr_t i = data_.Length() - 1; i > 0; i--) { 1471 for (intptr_t i = data_->Length() - 1; i > 0; i--) {
1436 f = data_.At(i - 1); 1472 f = data_->At(i - 1);
1437 data_.SetAt(i, f); 1473 data_->SetAt(i, f);
1438 } 1474 }
1439 data_.SetAt(0, function); 1475 data_->SetAt(0, value);
1440 } 1476 }
1441 1477
1442 RawFunction* PopBack() { 1478
1479 void PushBack(const Object& value) {
1480 data_->Add(value, Heap::kOld);
1481 }
1482
1483
1484 RawObject* PopBack() {
1443 ASSERT(!IsEmpty()); 1485 ASSERT(!IsEmpty());
1444 Object& result = Object::Handle(); 1486 Object& result = Object::Handle();
1445 result = data_.At(data_.Length() - 1); 1487 result = data_->At(data_->Length() - 1);
1446 data_.SetLength(data_.Length() - 1); 1488 data_->SetLength(data_->Length() - 1);
1447 return Function::Cast(result).raw(); 1489 return result.raw();
1448 } 1490 }
1449 1491
1450 RawFunction* Last() { 1492 RawObject* Last() {
1451 ASSERT(!IsEmpty()); 1493 ASSERT(!IsEmpty());
1452 return Function::RawCast(data_.At(data_.Length() - 1)); 1494 return data_->At(data_->Length() - 1);
1453 } 1495 }
1454 1496
1455 private: 1497 GrowableObjectArray* data_;
1456 GrowableObjectArray& data_;
1457 1498
1458 DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationWorkQueue); 1499 DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationWorkQueue);
1459 }; 1500 };
1460 1501
1461 1502
1462 BackgroundCompiler::BackgroundCompiler(Isolate* isolate) 1503 BackgroundCompiler::BackgroundCompiler(Isolate* isolate)
1463 : isolate_(isolate), running_(true), done_(new bool()), 1504 : isolate_(isolate), running_(true), done_(new bool()),
1464 queue_monitor_(new Monitor()), done_monitor_(new Monitor()), 1505 queue_monitor_(new Monitor()), done_monitor_(new Monitor()),
1465 queue_length_(0) { 1506 function_queue_length_(0) {
1466 *done_ = false; 1507 *done_ = false;
1467 } 1508 }
1468 1509
1469 1510
1470 void BackgroundCompiler::Run() { 1511 void BackgroundCompiler::Run() {
1471 while (running_) { 1512 while (running_) {
1472 // Maybe something is already in the queue, check first before waiting 1513 // Maybe something is already in the queue, check first before waiting
1473 // to be notified. 1514 // to be notified.
1474 Thread::EnterIsolateAsHelper(isolate_); 1515 Thread::EnterIsolateAsHelper(isolate_);
1475 { 1516 {
1476 Thread* thread = Thread::Current(); 1517 Thread* thread = Thread::Current();
1477 StackZone stack_zone(thread); 1518 StackZone stack_zone(thread);
1478 HANDLESCOPE(thread); 1519 HANDLESCOPE(thread);
1479 Zone* zone = stack_zone.GetZone(); 1520 Zone* zone = stack_zone.GetZone();
1480 Function& function = Function::Handle(zone); 1521 Function& function = Function::Handle(zone);
1481 Function& temp_function = Function::Handle(zone); 1522 Function& temp_function = Function::Handle(zone);
1482 function = LastOrNull(); 1523 Code& code = Code::Handle(zone);
1483 while (!function.IsNull() && running_) { 1524 function = LastFunctionOrNull();
1525 // Finish all compilation before exiting (even if running_ is changed to
1526 // false).
1527 while (!function.IsNull()) {
1484 const Error& error = Error::Handle(zone, 1528 const Error& error = Error::Handle(zone,
1485 Compiler::CompileOptimizedFunction(thread, function)); 1529 Compiler::CompileOptimizedFunction(thread,
1530 function,
1531 Compiler::kNoOSRDeoptId,
1532 &code));
1486 // TODO(srdjan): We do not expect errors while compiling optimized 1533 // TODO(srdjan): We do not expect errors while compiling optimized
1487 // code, any errors should have been caught when compiling 1534 // code, any errors should have been caught when compiling
1488 // unoptimized code. 1535 // unoptimized code.
1489 // If it still happens mark function as not optimizable. 1536 // If it still happens mark function as not optimizable.
1490 ASSERT(error.IsNull()); 1537 ASSERT(error.IsNull());
1491 temp_function = RemoveOrNull(); 1538 temp_function = RemoveFunctionOrNull();
1492 ASSERT(temp_function.raw() == function.raw()); 1539 ASSERT(temp_function.raw() == function.raw());
1493 // Reset to 0 so that it can be recompiled if needed. 1540 // Reset to 0 so that it can be recompiled if needed.
1494 function.set_usage_counter(0); 1541 function.set_usage_counter(0);
1495 function = LastOrNull(); 1542 function = LastFunctionOrNull();
1543 AddCode(code);
1496 } 1544 }
1497 } 1545 }
1498 Thread::ExitIsolateAsHelper(); 1546 Thread::ExitIsolateAsHelper();
1499 { 1547 {
1500 // Wait to be notified when the work queue is not empty. 1548 // Wait to be notified when the work queue is not empty.
1501 MonitorLocker ml(queue_monitor_); 1549 MonitorLocker ml(queue_monitor_);
1502 while ((queue_length() == 0) && running_) { 1550 while ((function_queue_length() == 0) && running_) {
1503 ml.Wait(); 1551 ml.Wait();
1504 } 1552 }
1505 } 1553 }
1506 } 1554 }
1507 { 1555 {
1508 // Notify that the thread is done. 1556 // Notify that the thread is done.
1509 MonitorLocker ml_done(done_monitor_); 1557 MonitorLocker ml_done(done_monitor_);
1510 *done_ = true; 1558 *done_ = true;
1511 ml_done.Notify(); 1559 ml_done.Notify();
1512 } 1560 }
1513 } 1561 }
1514 1562
1515 1563
1516 void BackgroundCompiler::CompileOptimized(const Function& function) { 1564 void BackgroundCompiler::CompileOptimized(const Function& function) {
1517 Add(function); 1565 AddFunction(function);
1518 } 1566 }
1519 1567
1520 1568
1521 void BackgroundCompiler::Add(const Function& f) { 1569 void BackgroundCompiler::InstallGeneratedCode() {
1522 MonitorLocker ml(queue_monitor_); 1570 MonitorLocker ml(queue_monitor_);
1523 CompilationWorkQueue queue(isolate_); 1571 CompilationWorkQueue queue(CodesQueue());
1524 queue.PushFront(f); 1572 Code& code = Code::Handle();
1525 set_queue_length(queue.Length()); 1573 Object& owner = Object::Handle();
1574 for (intptr_t i = 0; i < queue.Length(); i++) {
1575 code = queue.PopBackCode();
1576 if (code.IsDisabled()) continue;
1577 owner = code.owner();
1578 ASSERT(owner.IsFunction());
1579 Function::Cast(owner).InstallOptimizedCode(code, false /* not OSR */);
1580 }
1581 }
1582
1583
1584 GrowableObjectArray* BackgroundCompiler::FunctionsQueue() const {
1585 return
1586 &GrowableObjectArray::ZoneHandle(isolate_->compilation_function_queue());
1587 }
1588
1589
1590 GrowableObjectArray* BackgroundCompiler::CodesQueue() const {
1591 // Use code queue
1592 return &GrowableObjectArray::ZoneHandle(isolate_->compilation_code_queue());
1593 }
1594
1595
1596 void BackgroundCompiler::AddFunction(const Function& f) {
1597 MonitorLocker ml(queue_monitor_);
1598 CompilationWorkQueue queue(FunctionsQueue());
1599 queue.PushFrontFunction(f);
1600 set_function_queue_length(queue.Length());
1601 // Notify waiting background compiler task.
1526 ml.Notify(); 1602 ml.Notify();
1527 } 1603 }
1528 1604
1529 1605
1530 RawFunction* BackgroundCompiler::RemoveOrNull() { 1606 RawFunction* BackgroundCompiler::RemoveFunctionOrNull() {
1531 MonitorLocker ml(queue_monitor_); 1607 MonitorLocker ml(queue_monitor_);
1532 CompilationWorkQueue queue(isolate_); 1608 CompilationWorkQueue queue(FunctionsQueue());
1533 if (queue.IsEmpty()) return Function::null(); 1609 if (queue.IsEmpty()) return Function::null();
1534 set_queue_length(queue.Length() - 1); 1610 set_function_queue_length(queue.Length() - 1);
1535 return queue.PopBack(); 1611 return queue.PopBackFunction();
1536 } 1612 }
1537 1613
1538 1614
1539 RawFunction* BackgroundCompiler::LastOrNull() const { 1615 RawFunction* BackgroundCompiler::LastFunctionOrNull() const {
1540 MonitorLocker ml(queue_monitor_); 1616 MonitorLocker ml(queue_monitor_);
1541 CompilationWorkQueue queue(isolate_); 1617 CompilationWorkQueue queue(FunctionsQueue());
1542 return queue.IsEmpty() ? Function::null() : queue.Last(); 1618 return queue.IsEmpty() ? Function::null() : queue.LastFunction();
1619 }
1620
1621
1622 void BackgroundCompiler::AddCode(const Code& c) {
1623 MonitorLocker ml(queue_monitor_);
1624 CompilationWorkQueue queue(CodesQueue());
1625 queue.PushBackCode(c);
1543 } 1626 }
1544 1627
1545 1628
1546 void BackgroundCompiler::Stop(BackgroundCompiler* task) { 1629 void BackgroundCompiler::Stop(BackgroundCompiler* task) {
1630 ASSERT(Isolate::Current()->background_compiler() == task);
1547 if (task == NULL) { 1631 if (task == NULL) {
1548 return; 1632 return;
1549 } 1633 }
1550 Monitor* monitor = task->queue_monitor_; 1634 Monitor* monitor = task->queue_monitor_;
1551 Monitor* done_monitor = task->done_monitor_; 1635 Monitor* done_monitor = task->done_monitor_;
1552 bool* task_done = task->done_; 1636 bool* task_done = task->done_;
1553 // Wake up compiler task and stop it. 1637 // Wake up compiler task and stop it.
1554 { 1638 {
1555 MonitorLocker ml(task->queue_monitor_); 1639 MonitorLocker ml(task->queue_monitor_);
1556 task->running_ = false; 1640 task->running_ = false;
1557 // 'task' will be deleted by thread pool. 1641 // 'task' will be deleted by thread pool.
1558 task = NULL; 1642 task = NULL;
1559 ml.Notify(); // Stop waiting for the queue. 1643 ml.Notify(); // Stop waiting for the queue.
1560 } 1644 }
1561 1645
1562 { 1646 {
1563 MonitorLocker ml_done(done_monitor); 1647 MonitorLocker ml_done(done_monitor);
1564 while (!(*task_done)) { 1648 while (!(*task_done)) {
1565 ml_done.Wait(); 1649 ml_done.Wait();
1566 } 1650 }
1567 } 1651 }
1568 delete task_done; 1652 delete task_done;
1569 delete done_monitor; 1653 delete done_monitor;
1570 delete monitor; 1654 delete monitor;
1655 Isolate::Current()->set_background_compiler(NULL);
1571 } 1656 }
1572 1657
1573 1658
1574 void BackgroundCompiler::EnsureInit(Thread* thread) { 1659 void BackgroundCompiler::EnsureInit(Thread* thread) {
1575 bool start_task = false; 1660 bool start_task = false;
1576 Isolate* isolate = thread->isolate(); 1661 Isolate* isolate = thread->isolate();
1577 { 1662 {
1578 MutexLocker ml(isolate->mutex()); 1663 MutexLocker ml(isolate->mutex());
1579 if (isolate->background_compiler() == NULL) { 1664 if (isolate->background_compiler() == NULL) {
1580 BackgroundCompiler* task = new BackgroundCompiler(isolate); 1665 BackgroundCompiler* task = new BackgroundCompiler(isolate);
1581 isolate->set_background_compiler(task); 1666 isolate->set_background_compiler(task);
1582 isolate->set_background_compilation_queue(GrowableObjectArray::Handle( 1667 isolate->set_compilation_function_queue(GrowableObjectArray::Handle(
1668 thread->zone(), GrowableObjectArray::New()));
1669 isolate->set_compilation_code_queue(GrowableObjectArray::Handle(
1583 thread->zone(), GrowableObjectArray::New())); 1670 thread->zone(), GrowableObjectArray::New()));
1584 start_task = true; 1671 start_task = true;
1585 } 1672 }
1586 } 1673 }
1587 if (start_task) { 1674 if (start_task) {
1588 Dart::thread_pool()->Run(isolate->background_compiler()); 1675 Dart::thread_pool()->Run(isolate->background_compiler());
1589 } 1676 }
1590 } 1677 }
1591 1678
1592 } // namespace dart 1679 } // 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