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

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

Issue 2781483005: Improve internal compiler API so that OSR code is never installed on function. (Closed)
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/compiler.h" 5 #include "vm/compiler.h"
6 6
7 #include "vm/assembler.h" 7 #include "vm/assembler.h"
8 8
9 #include "vm/ast_printer.h" 9 #include "vm/ast_printer.h"
10 #include "vm/block_scheduler.h" 10 #include "vm/block_scheduler.h"
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
197 return new (zone) DartCompilationPipeline(); 197 return new (zone) DartCompilationPipeline();
198 } 198 }
199 } 199 }
200 200
201 201
202 // Compile a function. Should call only if the function has not been compiled. 202 // Compile a function. Should call only if the function has not been compiled.
203 // Arg0: function object. 203 // Arg0: function object.
204 DEFINE_RUNTIME_ENTRY(CompileFunction, 1) { 204 DEFINE_RUNTIME_ENTRY(CompileFunction, 1) {
205 const Function& function = Function::CheckedHandle(arguments.ArgAt(0)); 205 const Function& function = Function::CheckedHandle(arguments.ArgAt(0));
206 ASSERT(!function.HasCode()); 206 ASSERT(!function.HasCode());
207 const Error& error = 207 const Object& result =
208 Error::Handle(Compiler::CompileFunction(thread, function)); 208 Object::Handle(Compiler::CompileFunction(thread, function));
209 if (!error.IsNull()) { 209 if (result.IsError()) {
210 if (error.IsLanguageError()) { 210 if (result.IsLanguageError()) {
211 Exceptions::ThrowCompileTimeError(LanguageError::Cast(error)); 211 Exceptions::ThrowCompileTimeError(LanguageError::Cast(result));
212 UNREACHABLE(); 212 UNREACHABLE();
213 } 213 }
214 Exceptions::PropagateError(error); 214 Exceptions::PropagateError(Error::Cast(result));
215 } 215 }
216 } 216 }
217 217
218 218
219 bool Compiler::CanOptimizeFunction(Thread* thread, const Function& function) { 219 bool Compiler::CanOptimizeFunction(Thread* thread, const Function& function) {
220 if (FLAG_support_debugger) { 220 if (FLAG_support_debugger) {
221 Isolate* isolate = thread->isolate(); 221 Isolate* isolate = thread->isolate();
222 if (isolate->debugger()->IsStepping() || 222 if (isolate->debugger()->IsStepping() ||
223 isolate->debugger()->HasBreakpoint(function, thread->zone())) { 223 isolate->debugger()->HasBreakpoint(function, thread->zone())) {
224 // We cannot set breakpoints and single step in optimized code, 224 // We cannot set breakpoints and single step in optimized code,
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
489 CompileParsedFunctionHelper(ParsedFunction* parsed_function, 489 CompileParsedFunctionHelper(ParsedFunction* parsed_function,
490 bool optimized, 490 bool optimized,
491 intptr_t osr_id) 491 intptr_t osr_id)
492 : parsed_function_(parsed_function), 492 : parsed_function_(parsed_function),
493 optimized_(optimized), 493 optimized_(optimized),
494 osr_id_(osr_id), 494 osr_id_(osr_id),
495 thread_(Thread::Current()), 495 thread_(Thread::Current()),
496 loading_invalidation_gen_at_start_( 496 loading_invalidation_gen_at_start_(
497 isolate()->loading_invalidation_gen()) {} 497 isolate()->loading_invalidation_gen()) {}
498 498
499 bool Compile(CompilationPipeline* pipeline); 499 RawObject* Compile(CompilationPipeline* pipeline);
500 500
501 private: 501 private:
502 ParsedFunction* parsed_function() const { return parsed_function_; } 502 ParsedFunction* parsed_function() const { return parsed_function_; }
503 bool optimized() const { return optimized_; } 503 bool optimized() const { return optimized_; }
504 intptr_t osr_id() const { return osr_id_; } 504 intptr_t osr_id() const { return osr_id_; }
505 Thread* thread() const { return thread_; } 505 Thread* thread() const { return thread_; }
506 Isolate* isolate() const { return thread_->isolate(); } 506 Isolate* isolate() const { return thread_->isolate(); }
507 intptr_t loading_invalidation_gen_at_start() const { 507 intptr_t loading_invalidation_gen_at_start() const {
508 return loading_invalidation_gen_at_start_; 508 return loading_invalidation_gen_at_start_;
509 } 509 }
510 void FinalizeCompilation(Assembler* assembler, 510 RawObject* FinalizeCompilation(Assembler* assembler,
511 FlowGraphCompiler* graph_compiler, 511 FlowGraphCompiler* graph_compiler,
512 FlowGraph* flow_graph); 512 FlowGraph* flow_graph);
513 void CheckIfBackgroundCompilerIsBeingStopped(); 513 void CheckIfBackgroundCompilerIsBeingStopped();
514 514
515 ParsedFunction* parsed_function_; 515 ParsedFunction* parsed_function_;
516 const bool optimized_; 516 const bool optimized_;
517 const intptr_t osr_id_; 517 const intptr_t osr_id_;
518 Thread* const thread_; 518 Thread* const thread_;
519 const intptr_t loading_invalidation_gen_at_start_; 519 const intptr_t loading_invalidation_gen_at_start_;
520 520
521 DISALLOW_COPY_AND_ASSIGN(CompileParsedFunctionHelper); 521 DISALLOW_COPY_AND_ASSIGN(CompileParsedFunctionHelper);
522 }; 522 };
523 523
524 524
525 void CompileParsedFunctionHelper::FinalizeCompilation( 525 RawObject* CompileParsedFunctionHelper::FinalizeCompilation(
Vyacheslav Egorov (Google) 2017/03/30 09:58:52 It looks like this function always returns a Code
erikcorry 2017/03/30 12:26:33 Done.
526 Assembler* assembler, 526 Assembler* assembler,
527 FlowGraphCompiler* graph_compiler, 527 FlowGraphCompiler* graph_compiler,
528 FlowGraph* flow_graph) { 528 FlowGraph* flow_graph) {
529 ASSERT(!FLAG_precompiled_mode); 529 ASSERT(!FLAG_precompiled_mode);
530 const Function& function = parsed_function()->function(); 530 const Function& function = parsed_function()->function();
531 Zone* const zone = thread()->zone(); 531 Zone* const zone = thread()->zone();
532 532
533 CSTAT_TIMER_SCOPE(thread(), codefinalizer_timer); 533 CSTAT_TIMER_SCOPE(thread(), codefinalizer_timer);
534 // CreateDeoptInfo uses the object pool and needs to be done before 534 // CreateDeoptInfo uses the object pool and needs to be done before
535 // FinalizeCode. 535 // FinalizeCode.
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
580 graph_compiler->FinalizePcDescriptors(code); 580 graph_compiler->FinalizePcDescriptors(code);
581 code.set_deopt_info_array(deopt_info_array); 581 code.set_deopt_info_array(deopt_info_array);
582 582
583 graph_compiler->FinalizeStackMaps(code); 583 graph_compiler->FinalizeStackMaps(code);
584 graph_compiler->FinalizeVarDescriptors(code); 584 graph_compiler->FinalizeVarDescriptors(code);
585 graph_compiler->FinalizeExceptionHandlers(code); 585 graph_compiler->FinalizeExceptionHandlers(code);
586 graph_compiler->FinalizeCatchEntryStateMap(code); 586 graph_compiler->FinalizeCatchEntryStateMap(code);
587 graph_compiler->FinalizeStaticCallTargetsTable(code); 587 graph_compiler->FinalizeStaticCallTargetsTable(code);
588 graph_compiler->FinalizeCodeSourceMap(code); 588 graph_compiler->FinalizeCodeSourceMap(code);
589 589
590 bool code_was_compiled = false;
Vyacheslav Egorov (Google) 2017/03/30 09:58:52 Maybe you don't need this? How about just using
erikcorry 2017/03/30 12:26:33 Done.
591
590 if (optimized()) { 592 if (optimized()) {
591 bool code_was_installed = false;
592 // Installs code while at safepoint. 593 // Installs code while at safepoint.
593 if (thread()->IsMutatorThread()) { 594 if (thread()->IsMutatorThread()) {
594 const bool is_osr = osr_id() != Compiler::kNoOSRDeoptId; 595 const bool is_osr = osr_id() != Compiler::kNoOSRDeoptId;
595 function.InstallOptimizedCode(code, is_osr); 596 if (!is_osr) {
Vyacheslav Egorov (Google) 2017/03/30 09:58:52 InstallOptimizedCode() also does set the owner on
erikcorry 2017/03/30 12:26:34 That's done on line 545. I added an assert.
596 code_was_installed = true; 597 function.InstallOptimizedCode(code);
598 }
599 code_was_compiled = true;
597 } else { 600 } else {
598 // Background compilation. 601 // Background compilation.
599 // Before installing code check generation counts if the code may 602 // Before installing code check generation counts if the code may
600 // have become invalid. 603 // have become invalid.
601 const bool trace_compiler = 604 const bool trace_compiler =
602 FLAG_trace_compiler || FLAG_trace_optimizing_compiler; 605 FLAG_trace_compiler || FLAG_trace_optimizing_compiler;
603 bool code_is_valid = true; 606 bool code_is_valid = true;
604 if (!flow_graph->parsed_function().guarded_fields()->is_empty()) { 607 if (!flow_graph->parsed_function().guarded_fields()->is_empty()) {
605 const ZoneGrowableArray<const Field*>& guarded_fields = 608 const ZoneGrowableArray<const Field*>& guarded_fields =
606 *flow_graph->parsed_function().guarded_fields(); 609 *flow_graph->parsed_function().guarded_fields();
(...skipping 23 matching lines...) Expand all
630 code_is_valid = false; 633 code_is_valid = false;
631 if (trace_compiler) { 634 if (trace_compiler) {
632 THR_Print("--> FAIL: Class hierarchy has new subclasses."); 635 THR_Print("--> FAIL: Class hierarchy has new subclasses.");
633 } 636 }
634 } 637 }
635 638
636 // Setting breakpoints at runtime could make a function non-optimizable. 639 // Setting breakpoints at runtime could make a function non-optimizable.
637 if (code_is_valid && Compiler::CanOptimizeFunction(thread(), function)) { 640 if (code_is_valid && Compiler::CanOptimizeFunction(thread(), function)) {
638 const bool is_osr = osr_id() != Compiler::kNoOSRDeoptId; 641 const bool is_osr = osr_id() != Compiler::kNoOSRDeoptId;
639 ASSERT(!is_osr); // OSR is not compiled in background. 642 ASSERT(!is_osr); // OSR is not compiled in background.
640 function.InstallOptimizedCode(code, is_osr); 643 function.InstallOptimizedCode(code);
641 code_was_installed = true; 644 code_was_compiled = true;
642 } 645 }
Vyacheslav Egorov (Google) 2017/03/30 09:58:52 } else { code = Code::null(); } and use !code.I
erikcorry 2017/03/30 12:26:34 Done.
643 if (function.usage_counter() < 0) { 646 if (function.usage_counter() < 0) {
644 // Reset to 0 so that it can be recompiled if needed. 647 // Reset to 0 so that it can be recompiled if needed.
645 if (code_is_valid) { 648 if (code_is_valid) {
646 function.set_usage_counter(0); 649 function.set_usage_counter(0);
647 } else { 650 } else {
648 // Trigger another optimization pass soon. 651 // Trigger another optimization pass soon.
649 function.set_usage_counter(FLAG_optimization_counter_threshold - 100); 652 function.set_usage_counter(FLAG_optimization_counter_threshold - 100);
650 } 653 }
651 } 654 }
652 } 655 }
653 656
654 if (code_was_installed) { 657 if (code_was_compiled) {
655 // The generated code was compiled under certain assumptions about 658 // The generated code was compiled under certain assumptions about
656 // class hierarchy and field types. Register these dependencies 659 // class hierarchy and field types. Register these dependencies
657 // to ensure that the code will be deoptimized if they are violated. 660 // to ensure that the code will be deoptimized if they are violated.
658 thread()->cha()->RegisterDependencies(code); 661 thread()->cha()->RegisterDependencies(code);
659 662
660 const ZoneGrowableArray<const Field*>& guarded_fields = 663 const ZoneGrowableArray<const Field*>& guarded_fields =
661 *flow_graph->parsed_function().guarded_fields(); 664 *flow_graph->parsed_function().guarded_fields();
662 Field& field = Field::Handle(); 665 Field& field = Field::Handle();
663 for (intptr_t i = 0; i < guarded_fields.length(); i++) { 666 for (intptr_t i = 0; i < guarded_fields.length(); i++) {
664 field = guarded_fields[i]->Original(); 667 field = guarded_fields[i]->Original();
665 field.RegisterDependentCode(code); 668 field.RegisterDependentCode(code);
666 } 669 }
667 } 670 }
668 } else { // not optimized. 671 } else { // not optimized.
669 if (function.ic_data_array() == Array::null()) { 672 if (function.ic_data_array() == Array::null()) {
670 function.SaveICDataMap( 673 function.SaveICDataMap(
671 graph_compiler->deopt_id_to_ic_data(), 674 graph_compiler->deopt_id_to_ic_data(),
672 Array::Handle(zone, graph_compiler->edge_counters_array())); 675 Array::Handle(zone, graph_compiler->edge_counters_array()));
673 } 676 }
674 function.set_unoptimized_code(code); 677 function.set_unoptimized_code(code);
675 function.AttachCode(code); 678 function.AttachCode(code);
679 code_was_compiled = true;
676 } 680 }
677 if (parsed_function()->HasDeferredPrefixes()) { 681 if (parsed_function()->HasDeferredPrefixes()) {
678 ASSERT(!FLAG_load_deferred_eagerly); 682 ASSERT(!FLAG_load_deferred_eagerly);
679 ZoneGrowableArray<const LibraryPrefix*>* prefixes = 683 ZoneGrowableArray<const LibraryPrefix*>* prefixes =
680 parsed_function()->deferred_prefixes(); 684 parsed_function()->deferred_prefixes();
681 for (intptr_t i = 0; i < prefixes->length(); i++) { 685 for (intptr_t i = 0; i < prefixes->length(); i++) {
682 (*prefixes)[i]->RegisterDependentCode(code); 686 (*prefixes)[i]->RegisterDependentCode(code);
683 } 687 }
684 } 688 }
689 if (code_was_compiled) {
690 return code.raw();
691 }
692 return Object::null();
Vyacheslav Egorov (Google) 2017/03/30 09:58:52 here you then will be able to just return code.raw
erikcorry 2017/03/30 12:26:34 Done.
685 } 693 }
686 694
687 695
688 void CompileParsedFunctionHelper::CheckIfBackgroundCompilerIsBeingStopped() { 696 void CompileParsedFunctionHelper::CheckIfBackgroundCompilerIsBeingStopped() {
689 ASSERT(Compiler::IsBackgroundCompilation()); 697 ASSERT(Compiler::IsBackgroundCompilation());
690 if (!isolate()->background_compiler()->is_running()) { 698 if (!isolate()->background_compiler()->is_running()) {
691 // The background compiler is being stopped. 699 // The background compiler is being stopped.
692 Compiler::AbortBackgroundCompilation( 700 Compiler::AbortBackgroundCompilation(
693 Thread::kNoDeoptId, "Background compilation is being stopped"); 701 Thread::kNoDeoptId, "Background compilation is being stopped");
694 } 702 }
695 } 703 }
696 704
697 705
698 // Return false if bailed out. 706 // Return null if bailed out.
699 // If optimized_result_code is not NULL then it is caller's responsibility 707 // If optimized_result_code is not NULL then it is caller's responsibility
700 // to install code. 708 // to install code.
701 bool CompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) { 709 RawObject* CompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
Vyacheslav Egorov (Google) 2017/03/30 09:58:52 This returns Code or null. So maybe this should be
erikcorry 2017/03/30 12:26:33 Done.
702 ASSERT(!FLAG_precompiled_mode); 710 ASSERT(!FLAG_precompiled_mode);
703 const Function& function = parsed_function()->function(); 711 const Function& function = parsed_function()->function();
704 if (optimized() && !function.IsOptimizable()) { 712 if (optimized() && !function.IsOptimizable()) {
705 return false; 713 return Object::null();
706 } 714 }
707 bool is_compiled = false;
708 Zone* const zone = thread()->zone(); 715 Zone* const zone = thread()->zone();
709 NOT_IN_PRODUCT(TimelineStream* compiler_timeline = 716 NOT_IN_PRODUCT(TimelineStream* compiler_timeline =
710 Timeline::GetCompilerStream()); 717 Timeline::GetCompilerStream());
711 CSTAT_TIMER_SCOPE(thread(), codegen_timer); 718 CSTAT_TIMER_SCOPE(thread(), codegen_timer);
712 HANDLESCOPE(thread()); 719 HANDLESCOPE(thread());
713 720
714 // We may reattempt compilation if the function needs to be assembled using 721 // We may reattempt compilation if the function needs to be assembled using
715 // far branches on ARM and MIPS. In the else branch of the setjmp call, 722 // far branches on ARM and MIPS. In the else branch of the setjmp call,
716 // done is set to false, and use_far_branches is set to true if there is a 723 // done is set to false, and use_far_branches is set to true if there is a
717 // longjmp from the ARM or MIPS assemblers. In all other paths through this 724 // longjmp from the ARM or MIPS assemblers. In all other paths through this
718 // while loop, done is set to true. use_far_branches is always false on ia32 725 // while loop, done is set to true. use_far_branches is always false on ia32
719 // and x64. 726 // and x64.
720 volatile bool done = false; 727 volatile bool done = false;
721 // volatile because the variable may be clobbered by a longjmp. 728 // volatile because the variable may be clobbered by a longjmp.
722 volatile bool use_far_branches = false; 729 volatile bool use_far_branches = false;
723 const bool use_speculative_inlining = false; 730 const bool use_speculative_inlining = false;
724 731
732 Code& result = Code::ZoneHandle(zone);
Vyacheslav Egorov (Google) 2017/03/30 09:58:52 this variable needs to be volatile because of setj
erikcorry 2017/03/30 12:26:33 Yuck!
725 while (!done) { 733 while (!done) {
734 result = Code::null();
726 const intptr_t prev_deopt_id = thread()->deopt_id(); 735 const intptr_t prev_deopt_id = thread()->deopt_id();
727 thread()->set_deopt_id(0); 736 thread()->set_deopt_id(0);
728 LongJumpScope jump; 737 LongJumpScope jump;
729 const intptr_t val = setjmp(*jump.Set()); 738 const intptr_t val = setjmp(*jump.Set());
730 if (val == 0) { 739 if (val == 0) {
731 FlowGraph* flow_graph = NULL; 740 FlowGraph* flow_graph = NULL;
732 741
733 // Class hierarchy analysis is registered with the thread in the 742 // Class hierarchy analysis is registered with the thread in the
734 // constructor and unregisters itself upon destruction. 743 // constructor and unregisters itself upon destruction.
735 CHA cha(thread()); 744 CHA cha(thread());
(...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after
1128 CSTAT_TIMER_SCOPE(thread(), graphcompiler_timer); 1137 CSTAT_TIMER_SCOPE(thread(), graphcompiler_timer);
1129 NOT_IN_PRODUCT(TimelineDurationScope tds(thread(), compiler_timeline, 1138 NOT_IN_PRODUCT(TimelineDurationScope tds(thread(), compiler_timeline,
1130 "CompileGraph")); 1139 "CompileGraph"));
1131 graph_compiler.CompileGraph(); 1140 graph_compiler.CompileGraph();
1132 pipeline->FinalizeCompilation(flow_graph); 1141 pipeline->FinalizeCompilation(flow_graph);
1133 } 1142 }
1134 { 1143 {
1135 NOT_IN_PRODUCT(TimelineDurationScope tds(thread(), compiler_timeline, 1144 NOT_IN_PRODUCT(TimelineDurationScope tds(thread(), compiler_timeline,
1136 "FinalizeCompilation")); 1145 "FinalizeCompilation"));
1137 if (thread()->IsMutatorThread()) { 1146 if (thread()->IsMutatorThread()) {
1138 FinalizeCompilation(&assembler, &graph_compiler, flow_graph); 1147 result ^=
1148 FinalizeCompilation(&assembler, &graph_compiler, flow_graph);
Vyacheslav Egorov (Google) 2017/03/30 09:58:52 This can become result = FinalizeCompilation() if
erikcorry 2017/03/30 12:26:33 Done.
1139 } else { 1149 } else {
1140 // This part of compilation must be at a safepoint. 1150 // This part of compilation must be at a safepoint.
1141 // Stop mutator thread before creating the instruction object and 1151 // Stop mutator thread before creating the instruction object and
1142 // installing code. 1152 // installing code.
1143 // Mutator thread may not run code while we are creating the 1153 // Mutator thread may not run code while we are creating the
1144 // instruction object, since the creation of instruction object 1154 // instruction object, since the creation of instruction object
1145 // changes code page access permissions (makes them temporary not 1155 // changes code page access permissions (makes them temporary not
1146 // executable). 1156 // executable).
1147 { 1157 {
1148 CheckIfBackgroundCompilerIsBeingStopped(); 1158 CheckIfBackgroundCompilerIsBeingStopped();
1149 SafepointOperationScope safepoint_scope(thread()); 1159 SafepointOperationScope safepoint_scope(thread());
1150 // Do not Garbage collect during this stage and instead allow the 1160 // Do not Garbage collect during this stage and instead allow the
1151 // heap to grow. 1161 // heap to grow.
1152 NoHeapGrowthControlScope no_growth_control; 1162 NoHeapGrowthControlScope no_growth_control;
1153 CheckIfBackgroundCompilerIsBeingStopped(); 1163 CheckIfBackgroundCompilerIsBeingStopped();
1154 FinalizeCompilation(&assembler, &graph_compiler, flow_graph); 1164 result ^=
1165 FinalizeCompilation(&assembler, &graph_compiler, flow_graph);
1155 } 1166 }
1156 // TODO(srdjan): Enable this and remove the one from 1167 // TODO(srdjan): Enable this and remove the one from
1157 // 'BackgroundCompiler::CompileOptimized' once cause of time-outs 1168 // 'BackgroundCompiler::CompileOptimized' once cause of time-outs
1158 // is resolved. 1169 // is resolved.
1159 // if (isolate()->heap()->NeedsGarbageCollection()) { 1170 // if (isolate()->heap()->NeedsGarbageCollection()) {
1160 // isolate()->heap()->CollectAllGarbage(); 1171 // isolate()->heap()->CollectAllGarbage();
1161 // } 1172 // }
1162 } 1173 }
1163 } 1174 }
1164 // Exit the loop and the function with the correct result value. 1175 // Exit the loop and the function with the correct result value.
1165 is_compiled = true;
1166 done = true; 1176 done = true;
1167 } else { 1177 } else {
1168 // We bailed out or we encountered an error. 1178 // We bailed out or we encountered an error.
1169 const Error& error = Error::Handle(thread()->sticky_error()); 1179 const Error& error = Error::Handle(thread()->sticky_error());
1170 1180
1171 if (error.raw() == Object::branch_offset_error().raw()) { 1181 if (error.raw() == Object::branch_offset_error().raw()) {
1172 // Compilation failed due to an out of range branch offset in the 1182 // Compilation failed due to an out of range branch offset in the
1173 // assembler. We try again (done = false) with far branches enabled. 1183 // assembler. We try again (done = false) with far branches enabled.
1174 done = false; 1184 done = false;
1175 ASSERT(!use_far_branches); 1185 ASSERT(!use_far_branches);
1176 use_far_branches = true; 1186 use_far_branches = true;
1177 } else if (error.raw() == Object::speculative_inlining_error().raw()) { 1187 } else if (error.raw() == Object::speculative_inlining_error().raw()) {
1178 // Can only happen with precompilation. 1188 // Can only happen with precompilation.
1179 UNREACHABLE(); 1189 UNREACHABLE();
1180 } else { 1190 } else {
1181 // If the error isn't due to an out of range branch offset, we don't 1191 // If the error isn't due to an out of range branch offset, we don't
1182 // try again (done = true), and indicate that we did not finish 1192 // try again (done = true).
1183 // compiling (is_compiled = false).
1184 if (FLAG_trace_bailout) { 1193 if (FLAG_trace_bailout) {
1185 THR_Print("%s\n", error.ToErrorCString()); 1194 THR_Print("%s\n", error.ToErrorCString());
1186 } 1195 }
1187 done = true; 1196 done = true;
1188 } 1197 }
1189 1198
1190 // If is is not a background compilation, clear the error if it was not a 1199 // If is is not a background compilation, clear the error if it was not a
1191 // real error, but just a bailout. If we're it a background compilation 1200 // real error, but just a bailout. If we're it a background compilation
1192 // this will be dealt with in the caller. 1201 // this will be dealt with in the caller.
1193 if (!Compiler::IsBackgroundCompilation() && error.IsLanguageError() && 1202 if (!Compiler::IsBackgroundCompilation() && error.IsLanguageError() &&
1194 (LanguageError::Cast(error).kind() == Report::kBailout)) { 1203 (LanguageError::Cast(error).kind() == Report::kBailout)) {
1195 thread()->clear_sticky_error(); 1204 thread()->clear_sticky_error();
1196 } 1205 }
1197 is_compiled = false;
1198 } 1206 }
1199 // Reset global isolate state. 1207 // Reset global isolate state.
1200 thread()->set_deopt_id(prev_deopt_id); 1208 thread()->set_deopt_id(prev_deopt_id);
1201 } 1209 }
1202 return is_compiled; 1210 return result.raw();
1203 } 1211 }
1204 1212
1205 1213
1206 static RawError* CompileFunctionHelper(CompilationPipeline* pipeline, 1214 static RawObject* CompileFunctionHelper(CompilationPipeline* pipeline,
1207 const Function& function, 1215 const Function& function,
1208 bool optimized, 1216 bool optimized,
1209 intptr_t osr_id) { 1217 intptr_t osr_id) {
1210 ASSERT(!FLAG_precompiled_mode); 1218 ASSERT(!FLAG_precompiled_mode);
1211 ASSERT(!optimized || function.was_compiled()); 1219 ASSERT(!optimized || function.was_compiled());
1212 LongJumpScope jump; 1220 LongJumpScope jump;
1213 if (setjmp(*jump.Set()) == 0) { 1221 if (setjmp(*jump.Set()) == 0) {
1214 Thread* const thread = Thread::Current(); 1222 Thread* const thread = Thread::Current();
1215 Isolate* const isolate = thread->isolate(); 1223 Isolate* const isolate = thread->isolate();
1216 StackZone stack_zone(thread); 1224 StackZone stack_zone(thread);
1217 Zone* const zone = stack_zone.GetZone(); 1225 Zone* const zone = stack_zone.GetZone();
1218 const bool trace_compiler = 1226 const bool trace_compiler =
1219 FLAG_trace_compiler || (FLAG_trace_optimizing_compiler && optimized); 1227 FLAG_trace_compiler || (FLAG_trace_optimizing_compiler && optimized);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1255 (loading_invalidation_gen_at_start != 1263 (loading_invalidation_gen_at_start !=
1256 isolate->loading_invalidation_gen())) { 1264 isolate->loading_invalidation_gen())) {
1257 // Loading occured while parsing. We need to abort here because state 1265 // Loading occured while parsing. We need to abort here because state
1258 // changed while compiling. 1266 // changed while compiling.
1259 Compiler::AbortBackgroundCompilation( 1267 Compiler::AbortBackgroundCompilation(
1260 Thread::kNoDeoptId, 1268 Thread::kNoDeoptId,
1261 "Invalidated state during parsing because of script loading"); 1269 "Invalidated state during parsing because of script loading");
1262 } 1270 }
1263 } 1271 }
1264 1272
1265 const bool success = helper.Compile(pipeline); 1273 Object& result = Object::Handle(helper.Compile(pipeline));
Vyacheslav Egorov (Google) 2017/03/30 09:58:52 This probably needs to be Code because you expect
erikcorry 2017/03/30 12:26:33 Done.
1266 if (success) { 1274 if (!result.IsNull()) {
1267 if (!optimized) { 1275 if (!optimized) {
1268 function.set_was_compiled(true); 1276 function.set_was_compiled(true);
1269 } 1277 }
1270 } else { 1278 } else {
1271 if (optimized) { 1279 if (optimized) {
1272 if (Compiler::IsBackgroundCompilation()) { 1280 if (Compiler::IsBackgroundCompilation()) {
1273 // Try again later, background compilation may abort because of 1281 // Try again later, background compilation may abort because of
1274 // state change during compilation. 1282 // state change during compilation.
1275 if (FLAG_trace_compiler) { 1283 if (FLAG_trace_compiler) {
1276 THR_Print("Aborted background compilation: %s\n", 1284 THR_Print("Aborted background compilation: %s\n",
(...skipping 21 matching lines...) Expand all
1298 if (trace_compiler) { 1306 if (trace_compiler) {
1299 THR_Print("--> disabling optimizations for '%s'\n", 1307 THR_Print("--> disabling optimizations for '%s'\n",
1300 function.ToFullyQualifiedCString()); 1308 function.ToFullyQualifiedCString());
1301 } else if (FLAG_trace_failed_optimization_attempts) { 1309 } else if (FLAG_trace_failed_optimization_attempts) {
1302 THR_Print("Cannot optimize: %s\n", 1310 THR_Print("Cannot optimize: %s\n",
1303 function.ToFullyQualifiedCString()); 1311 function.ToFullyQualifiedCString());
1304 } 1312 }
1305 function.SetIsOptimizable(false); 1313 function.SetIsOptimizable(false);
1306 return Error::null(); 1314 return Error::null();
1307 } else { 1315 } else {
1316 ASSERT(!optimized);
Vyacheslav Egorov (Google) 2017/03/30 09:58:52 I don't get this code. We are inside if (optimiz
erikcorry 2017/03/30 12:26:33 No. I added the assert exactly to clarify which "
1308 // Encountered error. 1317 // Encountered error.
1309 Error& error = Error::Handle(); 1318 Error& error = Error::Handle();
1310 // We got an error during compilation. 1319 // We got an error during compilation.
1311 error = thread->sticky_error(); 1320 error = thread->sticky_error();
1312 thread->clear_sticky_error(); 1321 thread->clear_sticky_error();
1313 // The non-optimizing compiler can get an unhandled exception 1322 // The non-optimizing compiler can get an unhandled exception
1314 // due to OOM or Stack overflow errors, it should not however 1323 // due to OOM or Stack overflow errors, it should not however
1315 // bail out. 1324 // bail out.
1316 ASSERT(error.IsUnhandledException() || 1325 ASSERT(error.IsUnhandledException() ||
1317 (error.IsLanguageError() && 1326 (error.IsLanguageError() &&
1318 LanguageError::Cast(error).kind() != Report::kBailout)); 1327 LanguageError::Cast(error).kind() != Report::kBailout));
1319 return error.raw(); 1328 return error.raw();
1320 } 1329 }
1330 UNREACHABLE();
1321 } 1331 }
1322 1332
1323 per_compile_timer.Stop(); 1333 per_compile_timer.Stop();
1324 1334
1325 if (trace_compiler && success) { 1335 if (trace_compiler) {
1326 THR_Print("--> '%s' entry: %#" Px " size: %" Pd " time: %" Pd64 " us\n", 1336 THR_Print("--> '%s' entry: %#" Px " size: %" Pd " time: %" Pd64 " us\n",
1327 function.ToFullyQualifiedCString(), 1337 function.ToFullyQualifiedCString(),
1328 Code::Handle(function.CurrentCode()).PayloadStart(), 1338 Code::Handle(function.CurrentCode()).PayloadStart(),
1329 Code::Handle(function.CurrentCode()).Size(), 1339 Code::Handle(function.CurrentCode()).Size(),
1330 per_compile_timer.TotalElapsedTime()); 1340 per_compile_timer.TotalElapsedTime());
1331 } 1341 }
1332 1342
1333 if (FLAG_support_debugger) { 1343 if (FLAG_support_debugger) {
1334 isolate->debugger()->NotifyCompilation(function); 1344 isolate->debugger()->NotifyCompilation(function);
1335 } 1345 }
1336 1346
1337 if (FLAG_disassemble && FlowGraphPrinter::ShouldPrint(function)) { 1347 if (FLAG_disassemble && FlowGraphPrinter::ShouldPrint(function)) {
1338 Disassembler::DisassembleCode(function, optimized); 1348 Disassembler::DisassembleCode(function, optimized);
1339 } else if (FLAG_disassemble_optimized && optimized && 1349 } else if (FLAG_disassemble_optimized && optimized &&
1340 FlowGraphPrinter::ShouldPrint(function)) { 1350 FlowGraphPrinter::ShouldPrint(function)) {
1341 Disassembler::DisassembleCode(function, true); 1351 Disassembler::DisassembleCode(function, true);
1342 } 1352 }
1343 1353
1344 return Error::null(); 1354 return result.raw();
1345 } else { 1355 } else {
1346 Thread* const thread = Thread::Current(); 1356 Thread* const thread = Thread::Current();
1347 StackZone stack_zone(thread); 1357 StackZone stack_zone(thread);
1348 Error& error = Error::Handle(); 1358 Error& error = Error::Handle();
1349 // We got an error during compilation or it is a bailout from background 1359 // We got an error during compilation or it is a bailout from background
1350 // compilation (e.g., during parsing with EnsureIsFinalized). 1360 // compilation (e.g., during parsing with EnsureIsFinalized).
1351 error = thread->sticky_error(); 1361 error = thread->sticky_error();
1352 thread->clear_sticky_error(); 1362 thread->clear_sticky_error();
1353 if (error.raw() == Object::background_compilation_error().raw()) { 1363 if (error.raw() == Object::background_compilation_error().raw()) {
1354 // Exit compilation, retry it later. 1364 // Exit compilation, retry it later.
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
1417 // Unoptimized compilation or precompilation may encounter compile-time 1427 // Unoptimized compilation or precompilation may encounter compile-time
1418 // errors, but regular optimized compilation should not. 1428 // errors, but regular optimized compilation should not.
1419 ASSERT(!optimized); 1429 ASSERT(!optimized);
1420 return error.raw(); 1430 return error.raw();
1421 } 1431 }
1422 UNREACHABLE(); 1432 UNREACHABLE();
1423 return Error::null(); 1433 return Error::null();
1424 } 1434 }
1425 1435
1426 1436
1427 RawError* Compiler::CompileFunction(Thread* thread, const Function& function) { 1437 RawObject* Compiler::CompileFunction(Thread* thread, const Function& function) {
1428 #ifdef DART_PRECOMPILER 1438 #ifdef DART_PRECOMPILER
1429 if (FLAG_precompiled_mode) { 1439 if (FLAG_precompiled_mode) {
1430 return Precompiler::CompileFunction( 1440 return Precompiler::CompileFunction(
1431 /* precompiler = */ NULL, thread, thread->zone(), function); 1441 /* precompiler = */ NULL, thread, thread->zone(), function);
1432 } 1442 }
1433 #endif 1443 #endif
1434 1444
1435 Isolate* isolate = thread->isolate(); 1445 Isolate* isolate = thread->isolate();
1436 1446
1437 #if !defined(PRODUCT) 1447 #if !defined(PRODUCT)
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1480 const Function& function) { 1490 const Function& function) {
1481 if (function.unoptimized_code() != Object::null()) { 1491 if (function.unoptimized_code() != Object::null()) {
1482 return Error::null(); 1492 return Error::null();
1483 } 1493 }
1484 Code& original_code = Code::ZoneHandle(thread->zone()); 1494 Code& original_code = Code::ZoneHandle(thread->zone());
1485 if (function.HasCode()) { 1495 if (function.HasCode()) {
1486 original_code = function.CurrentCode(); 1496 original_code = function.CurrentCode();
1487 } 1497 }
1488 CompilationPipeline* pipeline = 1498 CompilationPipeline* pipeline =
1489 CompilationPipeline::New(thread->zone(), function); 1499 CompilationPipeline::New(thread->zone(), function);
1490 const Error& error = Error::Handle( 1500 const Object& result = Object::Handle(
1491 CompileFunctionHelper(pipeline, function, false, /* not optimized */ 1501 CompileFunctionHelper(pipeline, function, false, /* not optimized */
1492 kNoOSRDeoptId)); 1502 kNoOSRDeoptId));
1493 if (!error.IsNull()) { 1503 if (result.IsError()) {
1494 return error.raw(); 1504 return Error::Cast(result).raw();
1495 } 1505 }
1496 // Since CompileFunctionHelper replaces the current code, re-attach the 1506 // Since CompileFunctionHelper replaces the current code, re-attach the
1497 // the original code if the function was already compiled. 1507 // the original code if the function was already compiled.
1498 if (!original_code.IsNull() && 1508 if (!original_code.IsNull() && result.raw() == function.CurrentCode() &&
1499 (original_code.raw() != function.CurrentCode())) { 1509 !original_code.IsDisabled()) {
1500 function.AttachCode(original_code); 1510 function.AttachCode(original_code);
1501 } 1511 }
1502 ASSERT(function.unoptimized_code() != Object::null()); 1512 ASSERT(function.unoptimized_code() != Object::null());
1513 ASSERT(function.unoptimized_code() == result.raw());
1503 if (FLAG_trace_compiler) { 1514 if (FLAG_trace_compiler) {
1504 THR_Print("Ensure unoptimized code for %s\n", function.ToCString()); 1515 THR_Print("Ensure unoptimized code for %s\n", function.ToCString());
1505 } 1516 }
1506 return Error::null(); 1517 return Error::null();
1507 } 1518 }
1508 1519
1509 1520
1510 RawError* Compiler::CompileOptimizedFunction(Thread* thread, 1521 RawObject* Compiler::CompileOptimizedFunction(Thread* thread,
1511 const Function& function, 1522 const Function& function,
1512 intptr_t osr_id) { 1523 intptr_t osr_id) {
1513 #if !defined(PRODUCT) 1524 #if !defined(PRODUCT)
1514 VMTagScope tagScope(thread, VMTag::kCompileOptimizedTagId); 1525 VMTagScope tagScope(thread, VMTag::kCompileOptimizedTagId);
1515 const char* event_name; 1526 const char* event_name;
1516 if (osr_id != kNoOSRDeoptId) { 1527 if (osr_id != kNoOSRDeoptId) {
1517 event_name = "CompileFunctionOptimizedOSR"; 1528 event_name = "CompileFunctionOptimizedOSR";
1518 } else if (IsBackgroundCompilation()) { 1529 } else if (IsBackgroundCompilation()) {
1519 event_name = "CompileFunctionOptimizedBackground"; 1530 event_name = "CompileFunctionOptimizedBackground";
1520 } else { 1531 } else {
1521 event_name = "CompileFunctionOptimized"; 1532 event_name = "CompileFunctionOptimized";
1522 } 1533 }
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
1585 } else { 1596 } else {
1586 // Only possible with background compilation. 1597 // Only possible with background compilation.
1587 ASSERT(Compiler::IsBackgroundCompilation()); 1598 ASSERT(Compiler::IsBackgroundCompilation());
1588 } 1599 }
1589 } 1600 }
1590 1601
1591 1602
1592 RawError* Compiler::CompileAllFunctions(const Class& cls) { 1603 RawError* Compiler::CompileAllFunctions(const Class& cls) {
1593 Thread* thread = Thread::Current(); 1604 Thread* thread = Thread::Current();
1594 Zone* zone = thread->zone(); 1605 Zone* zone = thread->zone();
1595 Error& error = Error::Handle(zone); 1606 Object& result = Object::Handle(zone);
1596 Array& functions = Array::Handle(zone, cls.functions()); 1607 Array& functions = Array::Handle(zone, cls.functions());
1597 Function& func = Function::Handle(zone); 1608 Function& func = Function::Handle(zone);
1598 // Class dynamic lives in the vm isolate. Its array fields cannot be set to 1609 // Class dynamic lives in the vm isolate. Its array fields cannot be set to
1599 // an empty array. 1610 // an empty array.
1600 if (functions.IsNull()) { 1611 if (functions.IsNull()) {
1601 ASSERT(cls.IsDynamicClass()); 1612 ASSERT(cls.IsDynamicClass());
1602 return error.raw(); 1613 return Error::null();
1603 } 1614 }
1604 // Compile all the regular functions. 1615 // Compile all the regular functions.
1605 for (int i = 0; i < functions.Length(); i++) { 1616 for (int i = 0; i < functions.Length(); i++) {
1606 func ^= functions.At(i); 1617 func ^= functions.At(i);
1607 ASSERT(!func.IsNull()); 1618 ASSERT(!func.IsNull());
1608 if (!func.HasCode() && !func.is_abstract() && 1619 if (!func.HasCode() && !func.is_abstract() &&
1609 !func.IsRedirectingFactory()) { 1620 !func.IsRedirectingFactory()) {
1610 if ((cls.is_mixin_app_alias() || cls.IsMixinApplication()) && 1621 if ((cls.is_mixin_app_alias() || cls.IsMixinApplication()) &&
1611 func.HasOptionalParameters()) { 1622 func.HasOptionalParameters()) {
1612 // Skipping optional parameters in mixin application. 1623 // Skipping optional parameters in mixin application.
1613 continue; 1624 continue;
1614 } 1625 }
1615 error = CompileFunction(thread, func); 1626 result = CompileFunction(thread, func);
1616 if (!error.IsNull()) { 1627 if (result.IsError()) {
1617 return error.raw(); 1628 return Error::Cast(result).raw();
1618 } 1629 }
1630 ASSERT(!result.IsNull());
1619 func.ClearICDataArray(); 1631 func.ClearICDataArray();
1620 func.ClearCode(); 1632 func.ClearCode();
1621 } 1633 }
1622 } 1634 }
1623 return error.raw(); 1635 return Error::null();
1624 } 1636 }
1625 1637
1626 1638
1627 RawError* Compiler::ParseAllFunctions(const Class& cls) { 1639 RawError* Compiler::ParseAllFunctions(const Class& cls) {
1628 Thread* thread = Thread::Current(); 1640 Thread* thread = Thread::Current();
1629 Zone* zone = thread->zone(); 1641 Zone* zone = thread->zone();
1630 Error& error = Error::Handle(zone); 1642 Error& error = Error::Handle(zone);
1631 Array& functions = Array::Handle(zone, cls.functions()); 1643 Array& functions = Array::Handle(zone, cls.functions());
1632 Function& func = Function::Handle(zone); 1644 Function& func = Function::Handle(zone);
1633 // Class dynamic lives in the vm isolate. Its array fields cannot be set to 1645 // Class dynamic lives in the vm isolate. Its array fields cannot be set to
(...skipping 556 matching lines...) Expand 10 before | Expand all | Expand 10 after
2190 return Error::null(); 2202 return Error::null();
2191 } 2203 }
2192 2204
2193 2205
2194 RawError* Compiler::CompileClass(const Class& cls) { 2206 RawError* Compiler::CompileClass(const Class& cls) {
2195 UNREACHABLE(); 2207 UNREACHABLE();
2196 return Error::null(); 2208 return Error::null();
2197 } 2209 }
2198 2210
2199 2211
2200 RawError* Compiler::CompileFunction(Thread* thread, const Function& function) { 2212 RawObject* Compiler::CompileFunction(Thread* thread, const Function& function) {
2201 UNREACHABLE(); 2213 UNREACHABLE();
2202 return Error::null(); 2214 return Error::null();
2203 } 2215 }
2204 2216
2205 2217
2206 RawError* Compiler::ParseFunction(Thread* thread, const Function& function) { 2218 RawError* Compiler::ParseFunction(Thread* thread, const Function& function) {
2207 UNREACHABLE(); 2219 UNREACHABLE();
2208 return Error::null(); 2220 return Error::null();
2209 } 2221 }
2210 2222
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
2297 2309
2298 2310
2299 bool BackgroundCompiler::IsDisabled() { 2311 bool BackgroundCompiler::IsDisabled() {
2300 UNREACHABLE(); 2312 UNREACHABLE();
2301 return true; 2313 return true;
2302 } 2314 }
2303 2315
2304 #endif // DART_PRECOMPILED_RUNTIME 2316 #endif // DART_PRECOMPILED_RUNTIME
2305 2317
2306 } // namespace dart 2318 } // namespace dart
OLDNEW
« runtime/lib/mirrors.cc ('K') | « runtime/vm/compiler.h ('k') | runtime/vm/dart_entry.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698