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

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: cosmetics 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
« no previous file with comments | « runtime/vm/compiler.h ('k') | runtime/vm/dart_entry.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 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 RawCode* 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 RawCode* 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 RawCode* CompileParsedFunctionHelper::FinalizeCompilation(
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.
536 const Array& deopt_info_array = 536 const Array& deopt_info_array =
537 Array::Handle(zone, graph_compiler->CreateDeoptInfo(assembler)); 537 Array::Handle(zone, graph_compiler->CreateDeoptInfo(assembler));
538 INC_STAT(thread(), total_code_size, 538 INC_STAT(thread(), total_code_size,
539 deopt_info_array.Length() * sizeof(uword)); 539 deopt_info_array.Length() * sizeof(uword));
540 // Allocates instruction object. Since this occurs only at safepoint, 540 // Allocates instruction object. Since this occurs only at safepoint,
541 // there can be no concurrent access to the instruction page. 541 // there can be no concurrent access to the instruction page.
542 const Code& code = 542 Code& code =
543 Code::Handle(Code::FinalizeCode(function, assembler, optimized())); 543 Code::Handle(Code::FinalizeCode(function, assembler, optimized()));
544 code.set_is_optimized(optimized()); 544 code.set_is_optimized(optimized());
545 code.set_owner(function); 545 code.set_owner(function);
546 #if !defined(PRODUCT) 546 #if !defined(PRODUCT)
547 if (FLAG_support_debugger) { 547 if (FLAG_support_debugger) {
548 ZoneGrowableArray<TokenPosition>* await_token_positions = 548 ZoneGrowableArray<TokenPosition>* await_token_positions =
549 flow_graph->await_token_positions(); 549 flow_graph->await_token_positions();
550 if (await_token_positions != NULL) { 550 if (await_token_positions != NULL) {
551 Smi& token_pos_value = Smi::Handle(zone); 551 Smi& token_pos_value = Smi::Handle(zone);
552 if (await_token_positions->length() > 0) { 552 if (await_token_positions->length() > 0) {
(...skipping 28 matching lines...) Expand all
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 if (optimized()) { 590 if (optimized()) {
591 bool code_was_installed = false;
592 // Installs code while at safepoint. 591 // Installs code while at safepoint.
593 if (thread()->IsMutatorThread()) { 592 if (thread()->IsMutatorThread()) {
594 const bool is_osr = osr_id() != Compiler::kNoOSRDeoptId; 593 const bool is_osr = osr_id() != Compiler::kNoOSRDeoptId;
595 function.InstallOptimizedCode(code, is_osr); 594 if (!is_osr) {
596 code_was_installed = true; 595 function.InstallOptimizedCode(code);
596 }
597 ASSERT(code.owner() == function.raw());
597 } else { 598 } else {
598 // Background compilation. 599 // Background compilation.
599 // Before installing code check generation counts if the code may 600 // Before installing code check generation counts if the code may
600 // have become invalid. 601 // have become invalid.
601 const bool trace_compiler = 602 const bool trace_compiler =
602 FLAG_trace_compiler || FLAG_trace_optimizing_compiler; 603 FLAG_trace_compiler || FLAG_trace_optimizing_compiler;
603 bool code_is_valid = true; 604 bool code_is_valid = true;
604 if (!flow_graph->parsed_function().guarded_fields()->is_empty()) { 605 if (!flow_graph->parsed_function().guarded_fields()->is_empty()) {
605 const ZoneGrowableArray<const Field*>& guarded_fields = 606 const ZoneGrowableArray<const Field*>& guarded_fields =
606 *flow_graph->parsed_function().guarded_fields(); 607 *flow_graph->parsed_function().guarded_fields();
(...skipping 23 matching lines...) Expand all
630 code_is_valid = false; 631 code_is_valid = false;
631 if (trace_compiler) { 632 if (trace_compiler) {
632 THR_Print("--> FAIL: Class hierarchy has new subclasses."); 633 THR_Print("--> FAIL: Class hierarchy has new subclasses.");
633 } 634 }
634 } 635 }
635 636
636 // Setting breakpoints at runtime could make a function non-optimizable. 637 // Setting breakpoints at runtime could make a function non-optimizable.
637 if (code_is_valid && Compiler::CanOptimizeFunction(thread(), function)) { 638 if (code_is_valid && Compiler::CanOptimizeFunction(thread(), function)) {
638 const bool is_osr = osr_id() != Compiler::kNoOSRDeoptId; 639 const bool is_osr = osr_id() != Compiler::kNoOSRDeoptId;
639 ASSERT(!is_osr); // OSR is not compiled in background. 640 ASSERT(!is_osr); // OSR is not compiled in background.
640 function.InstallOptimizedCode(code, is_osr); 641 function.InstallOptimizedCode(code);
641 code_was_installed = true; 642 } else {
643 code = Code::null();
642 } 644 }
643 if (function.usage_counter() < 0) { 645 if (function.usage_counter() < 0) {
644 // Reset to 0 so that it can be recompiled if needed. 646 // Reset to 0 so that it can be recompiled if needed.
645 if (code_is_valid) { 647 if (code_is_valid) {
646 function.set_usage_counter(0); 648 function.set_usage_counter(0);
647 } else { 649 } else {
648 // Trigger another optimization pass soon. 650 // Trigger another optimization pass soon.
649 function.set_usage_counter(FLAG_optimization_counter_threshold - 100); 651 function.set_usage_counter(FLAG_optimization_counter_threshold - 100);
650 } 652 }
651 } 653 }
652 } 654 }
653 655
654 if (code_was_installed) { 656 if (!code.IsNull()) {
655 // The generated code was compiled under certain assumptions about 657 // The generated code was compiled under certain assumptions about
656 // class hierarchy and field types. Register these dependencies 658 // class hierarchy and field types. Register these dependencies
657 // to ensure that the code will be deoptimized if they are violated. 659 // to ensure that the code will be deoptimized if they are violated.
658 thread()->cha()->RegisterDependencies(code); 660 thread()->cha()->RegisterDependencies(code);
659 661
660 const ZoneGrowableArray<const Field*>& guarded_fields = 662 const ZoneGrowableArray<const Field*>& guarded_fields =
661 *flow_graph->parsed_function().guarded_fields(); 663 *flow_graph->parsed_function().guarded_fields();
662 Field& field = Field::Handle(); 664 Field& field = Field::Handle();
663 for (intptr_t i = 0; i < guarded_fields.length(); i++) { 665 for (intptr_t i = 0; i < guarded_fields.length(); i++) {
664 field = guarded_fields[i]->Original(); 666 field = guarded_fields[i]->Original();
(...skipping 10 matching lines...) Expand all
675 function.AttachCode(code); 677 function.AttachCode(code);
676 } 678 }
677 if (parsed_function()->HasDeferredPrefixes()) { 679 if (parsed_function()->HasDeferredPrefixes()) {
678 ASSERT(!FLAG_load_deferred_eagerly); 680 ASSERT(!FLAG_load_deferred_eagerly);
679 ZoneGrowableArray<const LibraryPrefix*>* prefixes = 681 ZoneGrowableArray<const LibraryPrefix*>* prefixes =
680 parsed_function()->deferred_prefixes(); 682 parsed_function()->deferred_prefixes();
681 for (intptr_t i = 0; i < prefixes->length(); i++) { 683 for (intptr_t i = 0; i < prefixes->length(); i++) {
682 (*prefixes)[i]->RegisterDependentCode(code); 684 (*prefixes)[i]->RegisterDependentCode(code);
683 } 685 }
684 } 686 }
687 return code.raw();
685 } 688 }
686 689
687 690
688 void CompileParsedFunctionHelper::CheckIfBackgroundCompilerIsBeingStopped() { 691 void CompileParsedFunctionHelper::CheckIfBackgroundCompilerIsBeingStopped() {
689 ASSERT(Compiler::IsBackgroundCompilation()); 692 ASSERT(Compiler::IsBackgroundCompilation());
690 if (!isolate()->background_compiler()->is_running()) { 693 if (!isolate()->background_compiler()->is_running()) {
691 // The background compiler is being stopped. 694 // The background compiler is being stopped.
692 Compiler::AbortBackgroundCompilation( 695 Compiler::AbortBackgroundCompilation(
693 Thread::kNoDeoptId, "Background compilation is being stopped"); 696 Thread::kNoDeoptId, "Background compilation is being stopped");
694 } 697 }
695 } 698 }
696 699
697 700
698 // Return false if bailed out. 701 // Return null if bailed out.
699 // If optimized_result_code is not NULL then it is caller's responsibility 702 // If optimized_result_code is not NULL then it is caller's responsibility
700 // to install code. 703 // to install code.
701 bool CompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) { 704 RawCode* CompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
702 ASSERT(!FLAG_precompiled_mode); 705 ASSERT(!FLAG_precompiled_mode);
703 const Function& function = parsed_function()->function(); 706 const Function& function = parsed_function()->function();
704 if (optimized() && !function.IsOptimizable()) { 707 if (optimized() && !function.IsOptimizable()) {
705 return false; 708 return Code::null();
706 } 709 }
707 bool is_compiled = false;
708 Zone* const zone = thread()->zone(); 710 Zone* const zone = thread()->zone();
709 NOT_IN_PRODUCT(TimelineStream* compiler_timeline = 711 NOT_IN_PRODUCT(TimelineStream* compiler_timeline =
710 Timeline::GetCompilerStream()); 712 Timeline::GetCompilerStream());
711 CSTAT_TIMER_SCOPE(thread(), codegen_timer); 713 CSTAT_TIMER_SCOPE(thread(), codegen_timer);
712 HANDLESCOPE(thread()); 714 HANDLESCOPE(thread());
713 715
714 // We may reattempt compilation if the function needs to be assembled using 716 // 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, 717 // 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 718 // 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 719 // 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 720 // while loop, done is set to true. use_far_branches is always false on ia32
719 // and x64. 721 // and x64.
720 volatile bool done = false; 722 volatile bool done = false;
721 // volatile because the variable may be clobbered by a longjmp. 723 // volatile because the variable may be clobbered by a longjmp.
722 volatile bool use_far_branches = false; 724 volatile bool use_far_branches = false;
723 const bool use_speculative_inlining = false; 725 const bool use_speculative_inlining = false;
724 726
727 Code* volatile result = &Code::ZoneHandle(zone);
725 while (!done) { 728 while (!done) {
729 *result = Code::null();
726 const intptr_t prev_deopt_id = thread()->deopt_id(); 730 const intptr_t prev_deopt_id = thread()->deopt_id();
727 thread()->set_deopt_id(0); 731 thread()->set_deopt_id(0);
728 LongJumpScope jump; 732 LongJumpScope jump;
729 const intptr_t val = setjmp(*jump.Set()); 733 if (setjmp(*jump.Set()) == 0) {
730 if (val == 0) {
731 FlowGraph* flow_graph = NULL; 734 FlowGraph* flow_graph = NULL;
732 735
733 // Class hierarchy analysis is registered with the thread in the 736 // Class hierarchy analysis is registered with the thread in the
734 // constructor and unregisters itself upon destruction. 737 // constructor and unregisters itself upon destruction.
735 CHA cha(thread()); 738 CHA cha(thread());
736 739
737 // TimerScope needs an isolate to be properly terminated in case of a 740 // TimerScope needs an isolate to be properly terminated in case of a
738 // LongJump. 741 // LongJump.
739 { 742 {
740 CSTAT_TIMER_SCOPE(thread(), graphbuilder_timer); 743 CSTAT_TIMER_SCOPE(thread(), graphbuilder_timer);
(...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after
1128 CSTAT_TIMER_SCOPE(thread(), graphcompiler_timer); 1131 CSTAT_TIMER_SCOPE(thread(), graphcompiler_timer);
1129 NOT_IN_PRODUCT(TimelineDurationScope tds(thread(), compiler_timeline, 1132 NOT_IN_PRODUCT(TimelineDurationScope tds(thread(), compiler_timeline,
1130 "CompileGraph")); 1133 "CompileGraph"));
1131 graph_compiler.CompileGraph(); 1134 graph_compiler.CompileGraph();
1132 pipeline->FinalizeCompilation(flow_graph); 1135 pipeline->FinalizeCompilation(flow_graph);
1133 } 1136 }
1134 { 1137 {
1135 NOT_IN_PRODUCT(TimelineDurationScope tds(thread(), compiler_timeline, 1138 NOT_IN_PRODUCT(TimelineDurationScope tds(thread(), compiler_timeline,
1136 "FinalizeCompilation")); 1139 "FinalizeCompilation"));
1137 if (thread()->IsMutatorThread()) { 1140 if (thread()->IsMutatorThread()) {
1138 FinalizeCompilation(&assembler, &graph_compiler, flow_graph); 1141 *result =
1142 FinalizeCompilation(&assembler, &graph_compiler, flow_graph);
1139 } else { 1143 } else {
1140 // This part of compilation must be at a safepoint. 1144 // This part of compilation must be at a safepoint.
1141 // Stop mutator thread before creating the instruction object and 1145 // Stop mutator thread before creating the instruction object and
1142 // installing code. 1146 // installing code.
1143 // Mutator thread may not run code while we are creating the 1147 // Mutator thread may not run code while we are creating the
1144 // instruction object, since the creation of instruction object 1148 // instruction object, since the creation of instruction object
1145 // changes code page access permissions (makes them temporary not 1149 // changes code page access permissions (makes them temporary not
1146 // executable). 1150 // executable).
1147 { 1151 {
1148 CheckIfBackgroundCompilerIsBeingStopped(); 1152 CheckIfBackgroundCompilerIsBeingStopped();
1149 SafepointOperationScope safepoint_scope(thread()); 1153 SafepointOperationScope safepoint_scope(thread());
1150 // Do not Garbage collect during this stage and instead allow the 1154 // Do not Garbage collect during this stage and instead allow the
1151 // heap to grow. 1155 // heap to grow.
1152 NoHeapGrowthControlScope no_growth_control; 1156 NoHeapGrowthControlScope no_growth_control;
1153 CheckIfBackgroundCompilerIsBeingStopped(); 1157 CheckIfBackgroundCompilerIsBeingStopped();
1154 FinalizeCompilation(&assembler, &graph_compiler, flow_graph); 1158 *result =
1159 FinalizeCompilation(&assembler, &graph_compiler, flow_graph);
1155 } 1160 }
1156 // TODO(srdjan): Enable this and remove the one from 1161 // TODO(srdjan): Enable this and remove the one from
1157 // 'BackgroundCompiler::CompileOptimized' once cause of time-outs 1162 // 'BackgroundCompiler::CompileOptimized' once cause of time-outs
1158 // is resolved. 1163 // is resolved.
1159 // if (isolate()->heap()->NeedsGarbageCollection()) { 1164 // if (isolate()->heap()->NeedsGarbageCollection()) {
1160 // isolate()->heap()->CollectAllGarbage(); 1165 // isolate()->heap()->CollectAllGarbage();
1161 // } 1166 // }
1162 } 1167 }
1163 } 1168 }
1164 // Exit the loop and the function with the correct result value. 1169 // Exit the loop and the function with the correct result value.
1165 is_compiled = true;
1166 done = true; 1170 done = true;
1167 } else { 1171 } else {
1168 // We bailed out or we encountered an error. 1172 // We bailed out or we encountered an error.
1169 const Error& error = Error::Handle(thread()->sticky_error()); 1173 const Error& error = Error::Handle(thread()->sticky_error());
1170 1174
1171 if (error.raw() == Object::branch_offset_error().raw()) { 1175 if (error.raw() == Object::branch_offset_error().raw()) {
1172 // Compilation failed due to an out of range branch offset in the 1176 // Compilation failed due to an out of range branch offset in the
1173 // assembler. We try again (done = false) with far branches enabled. 1177 // assembler. We try again (done = false) with far branches enabled.
1174 done = false; 1178 done = false;
1175 ASSERT(!use_far_branches); 1179 ASSERT(!use_far_branches);
1176 use_far_branches = true; 1180 use_far_branches = true;
1177 } else if (error.raw() == Object::speculative_inlining_error().raw()) { 1181 } else if (error.raw() == Object::speculative_inlining_error().raw()) {
1178 // Can only happen with precompilation. 1182 // Can only happen with precompilation.
1179 UNREACHABLE(); 1183 UNREACHABLE();
1180 } else { 1184 } else {
1181 // If the error isn't due to an out of range branch offset, we don't 1185 // 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 1186 // try again (done = true).
1183 // compiling (is_compiled = false).
1184 if (FLAG_trace_bailout) { 1187 if (FLAG_trace_bailout) {
1185 THR_Print("%s\n", error.ToErrorCString()); 1188 THR_Print("%s\n", error.ToErrorCString());
1186 } 1189 }
1187 done = true; 1190 done = true;
1188 } 1191 }
1189 1192
1190 // If is is not a background compilation, clear the error if it was not a 1193 // 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 1194 // real error, but just a bailout. If we're it a background compilation
1192 // this will be dealt with in the caller. 1195 // this will be dealt with in the caller.
1193 if (!Compiler::IsBackgroundCompilation() && error.IsLanguageError() && 1196 if (!Compiler::IsBackgroundCompilation() && error.IsLanguageError() &&
1194 (LanguageError::Cast(error).kind() == Report::kBailout)) { 1197 (LanguageError::Cast(error).kind() == Report::kBailout)) {
1195 thread()->clear_sticky_error(); 1198 thread()->clear_sticky_error();
1196 } 1199 }
1197 is_compiled = false;
1198 } 1200 }
1199 // Reset global isolate state. 1201 // Reset global isolate state.
1200 thread()->set_deopt_id(prev_deopt_id); 1202 thread()->set_deopt_id(prev_deopt_id);
1201 } 1203 }
1202 return is_compiled; 1204 return result->raw();
1203 } 1205 }
1204 1206
1205 1207
1206 static RawError* CompileFunctionHelper(CompilationPipeline* pipeline, 1208 static RawObject* CompileFunctionHelper(CompilationPipeline* pipeline,
1207 const Function& function, 1209 const Function& function,
1208 bool optimized, 1210 bool optimized,
1209 intptr_t osr_id) { 1211 intptr_t osr_id) {
1210 ASSERT(!FLAG_precompiled_mode); 1212 ASSERT(!FLAG_precompiled_mode);
1211 ASSERT(!optimized || function.was_compiled()); 1213 ASSERT(!optimized || function.was_compiled());
1212 LongJumpScope jump; 1214 LongJumpScope jump;
1213 if (setjmp(*jump.Set()) == 0) { 1215 if (setjmp(*jump.Set()) == 0) {
1214 Thread* const thread = Thread::Current(); 1216 Thread* const thread = Thread::Current();
1215 Isolate* const isolate = thread->isolate(); 1217 Isolate* const isolate = thread->isolate();
1216 StackZone stack_zone(thread); 1218 StackZone stack_zone(thread);
1217 Zone* const zone = stack_zone.GetZone(); 1219 Zone* const zone = stack_zone.GetZone();
1218 const bool trace_compiler = 1220 const bool trace_compiler =
1219 FLAG_trace_compiler || (FLAG_trace_optimizing_compiler && optimized); 1221 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 != 1257 (loading_invalidation_gen_at_start !=
1256 isolate->loading_invalidation_gen())) { 1258 isolate->loading_invalidation_gen())) {
1257 // Loading occured while parsing. We need to abort here because state 1259 // Loading occured while parsing. We need to abort here because state
1258 // changed while compiling. 1260 // changed while compiling.
1259 Compiler::AbortBackgroundCompilation( 1261 Compiler::AbortBackgroundCompilation(
1260 Thread::kNoDeoptId, 1262 Thread::kNoDeoptId,
1261 "Invalidated state during parsing because of script loading"); 1263 "Invalidated state during parsing because of script loading");
1262 } 1264 }
1263 } 1265 }
1264 1266
1265 const bool success = helper.Compile(pipeline); 1267 const Code& result = Code::Handle(helper.Compile(pipeline));
1266 if (success) { 1268 if (!result.IsNull()) {
1267 if (!optimized) { 1269 if (!optimized) {
1268 function.set_was_compiled(true); 1270 function.set_was_compiled(true);
1269 } 1271 }
1270 } else { 1272 } else {
1271 if (optimized) { 1273 if (optimized) {
1272 if (Compiler::IsBackgroundCompilation()) { 1274 if (Compiler::IsBackgroundCompilation()) {
1273 // Try again later, background compilation may abort because of 1275 // Try again later, background compilation may abort because of
1274 // state change during compilation. 1276 // state change during compilation.
1275 if (FLAG_trace_compiler) { 1277 if (FLAG_trace_compiler) {
1276 THR_Print("Aborted background compilation: %s\n", 1278 THR_Print("Aborted background compilation: %s\n",
(...skipping 21 matching lines...) Expand all
1298 if (trace_compiler) { 1300 if (trace_compiler) {
1299 THR_Print("--> disabling optimizations for '%s'\n", 1301 THR_Print("--> disabling optimizations for '%s'\n",
1300 function.ToFullyQualifiedCString()); 1302 function.ToFullyQualifiedCString());
1301 } else if (FLAG_trace_failed_optimization_attempts) { 1303 } else if (FLAG_trace_failed_optimization_attempts) {
1302 THR_Print("Cannot optimize: %s\n", 1304 THR_Print("Cannot optimize: %s\n",
1303 function.ToFullyQualifiedCString()); 1305 function.ToFullyQualifiedCString());
1304 } 1306 }
1305 function.SetIsOptimizable(false); 1307 function.SetIsOptimizable(false);
1306 return Error::null(); 1308 return Error::null();
1307 } else { 1309 } else {
1310 ASSERT(!optimized);
1308 // Encountered error. 1311 // Encountered error.
1309 Error& error = Error::Handle(); 1312 Error& error = Error::Handle();
1310 // We got an error during compilation. 1313 // We got an error during compilation.
1311 error = thread->sticky_error(); 1314 error = thread->sticky_error();
1312 thread->clear_sticky_error(); 1315 thread->clear_sticky_error();
1313 // The non-optimizing compiler can get an unhandled exception 1316 // The non-optimizing compiler can get an unhandled exception
1314 // due to OOM or Stack overflow errors, it should not however 1317 // due to OOM or Stack overflow errors, it should not however
1315 // bail out. 1318 // bail out.
1316 ASSERT(error.IsUnhandledException() || 1319 ASSERT(error.IsUnhandledException() ||
1317 (error.IsLanguageError() && 1320 (error.IsLanguageError() &&
1318 LanguageError::Cast(error).kind() != Report::kBailout)); 1321 LanguageError::Cast(error).kind() != Report::kBailout));
1319 return error.raw(); 1322 return error.raw();
1320 } 1323 }
1324 UNREACHABLE();
1321 } 1325 }
1322 1326
1323 per_compile_timer.Stop(); 1327 per_compile_timer.Stop();
1324 1328
1325 if (trace_compiler && success) { 1329 if (trace_compiler) {
1326 THR_Print("--> '%s' entry: %#" Px " size: %" Pd " time: %" Pd64 " us\n", 1330 THR_Print("--> '%s' entry: %#" Px " size: %" Pd " time: %" Pd64 " us\n",
1327 function.ToFullyQualifiedCString(), 1331 function.ToFullyQualifiedCString(),
1328 Code::Handle(function.CurrentCode()).PayloadStart(), 1332 Code::Handle(function.CurrentCode()).PayloadStart(),
1329 Code::Handle(function.CurrentCode()).Size(), 1333 Code::Handle(function.CurrentCode()).Size(),
1330 per_compile_timer.TotalElapsedTime()); 1334 per_compile_timer.TotalElapsedTime());
1331 } 1335 }
1332 1336
1333 if (FLAG_support_debugger) { 1337 if (FLAG_support_debugger) {
1334 isolate->debugger()->NotifyCompilation(function); 1338 isolate->debugger()->NotifyCompilation(function);
1335 } 1339 }
1336 1340
1337 if (FLAG_disassemble && FlowGraphPrinter::ShouldPrint(function)) { 1341 if (FLAG_disassemble && FlowGraphPrinter::ShouldPrint(function)) {
1338 Disassembler::DisassembleCode(function, optimized); 1342 Disassembler::DisassembleCode(function, optimized);
1339 } else if (FLAG_disassemble_optimized && optimized && 1343 } else if (FLAG_disassemble_optimized && optimized &&
1340 FlowGraphPrinter::ShouldPrint(function)) { 1344 FlowGraphPrinter::ShouldPrint(function)) {
1341 Disassembler::DisassembleCode(function, true); 1345 Disassembler::DisassembleCode(function, true);
1342 } 1346 }
1343 1347
1344 return Error::null(); 1348 return result.raw();
1345 } else { 1349 } else {
1346 Thread* const thread = Thread::Current(); 1350 Thread* const thread = Thread::Current();
1347 StackZone stack_zone(thread); 1351 StackZone stack_zone(thread);
1348 Error& error = Error::Handle(); 1352 Error& error = Error::Handle();
1349 // We got an error during compilation or it is a bailout from background 1353 // We got an error during compilation or it is a bailout from background
1350 // compilation (e.g., during parsing with EnsureIsFinalized). 1354 // compilation (e.g., during parsing with EnsureIsFinalized).
1351 error = thread->sticky_error(); 1355 error = thread->sticky_error();
1352 thread->clear_sticky_error(); 1356 thread->clear_sticky_error();
1353 if (error.raw() == Object::background_compilation_error().raw()) { 1357 if (error.raw() == Object::background_compilation_error().raw()) {
1354 // Exit compilation, retry it later. 1358 // Exit compilation, retry it later.
1355 if (FLAG_trace_bailout) { 1359 if (FLAG_trace_bailout) {
1356 THR_Print("Aborted background compilation: %s\n", 1360 THR_Print("Aborted background compilation: %s\n",
1357 function.ToFullyQualifiedCString()); 1361 function.ToFullyQualifiedCString());
1358 } 1362 }
1359 return Error::null(); 1363 return Object::null();
1360 } 1364 }
1361 // Do not attempt to optimize functions that can cause errors. 1365 // Do not attempt to optimize functions that can cause errors.
1362 function.set_is_optimizable(false); 1366 function.set_is_optimizable(false);
1363 return error.raw(); 1367 return error.raw();
1364 } 1368 }
1365 UNREACHABLE(); 1369 UNREACHABLE();
1366 return Error::null(); 1370 return Object::null();
1367 } 1371 }
1368 1372
1369 1373
1370 static RawError* ParseFunctionHelper(CompilationPipeline* pipeline, 1374 static RawError* ParseFunctionHelper(CompilationPipeline* pipeline,
1371 const Function& function, 1375 const Function& function,
1372 bool optimized, 1376 bool optimized,
1373 intptr_t osr_id) { 1377 intptr_t osr_id) {
1374 ASSERT(!FLAG_precompiled_mode); 1378 ASSERT(!FLAG_precompiled_mode);
1375 ASSERT(!optimized || function.was_compiled()); 1379 ASSERT(!optimized || function.was_compiled());
1376 LongJumpScope jump; 1380 LongJumpScope jump;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1417 // Unoptimized compilation or precompilation may encounter compile-time 1421 // Unoptimized compilation or precompilation may encounter compile-time
1418 // errors, but regular optimized compilation should not. 1422 // errors, but regular optimized compilation should not.
1419 ASSERT(!optimized); 1423 ASSERT(!optimized);
1420 return error.raw(); 1424 return error.raw();
1421 } 1425 }
1422 UNREACHABLE(); 1426 UNREACHABLE();
1423 return Error::null(); 1427 return Error::null();
1424 } 1428 }
1425 1429
1426 1430
1427 RawError* Compiler::CompileFunction(Thread* thread, const Function& function) { 1431 RawObject* Compiler::CompileFunction(Thread* thread, const Function& function) {
1428 #ifdef DART_PRECOMPILER 1432 #ifdef DART_PRECOMPILER
1429 if (FLAG_precompiled_mode) { 1433 if (FLAG_precompiled_mode) {
1430 return Precompiler::CompileFunction( 1434 return Precompiler::CompileFunction(
1431 /* precompiler = */ NULL, thread, thread->zone(), function); 1435 /* precompiler = */ NULL, thread, thread->zone(), function);
1432 } 1436 }
1433 #endif 1437 #endif
1434 1438
1435 Isolate* isolate = thread->isolate(); 1439 Isolate* isolate = thread->isolate();
1436 1440
1437 #if !defined(PRODUCT) 1441 #if !defined(PRODUCT)
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1480 const Function& function) { 1484 const Function& function) {
1481 if (function.unoptimized_code() != Object::null()) { 1485 if (function.unoptimized_code() != Object::null()) {
1482 return Error::null(); 1486 return Error::null();
1483 } 1487 }
1484 Code& original_code = Code::ZoneHandle(thread->zone()); 1488 Code& original_code = Code::ZoneHandle(thread->zone());
1485 if (function.HasCode()) { 1489 if (function.HasCode()) {
1486 original_code = function.CurrentCode(); 1490 original_code = function.CurrentCode();
1487 } 1491 }
1488 CompilationPipeline* pipeline = 1492 CompilationPipeline* pipeline =
1489 CompilationPipeline::New(thread->zone(), function); 1493 CompilationPipeline::New(thread->zone(), function);
1490 const Error& error = Error::Handle( 1494 const Object& result = Object::Handle(
1491 CompileFunctionHelper(pipeline, function, false, /* not optimized */ 1495 CompileFunctionHelper(pipeline, function, false, /* not optimized */
1492 kNoOSRDeoptId)); 1496 kNoOSRDeoptId));
1493 if (!error.IsNull()) { 1497 if (result.IsError()) {
1494 return error.raw(); 1498 return Error::Cast(result).raw();
1495 } 1499 }
1496 // Since CompileFunctionHelper replaces the current code, re-attach the 1500 // Since CompileFunctionHelper replaces the current code, re-attach the
1497 // the original code if the function was already compiled. 1501 // the original code if the function was already compiled.
1498 if (!original_code.IsNull() && 1502 if (!original_code.IsNull() && result.raw() == function.CurrentCode() &&
1499 (original_code.raw() != function.CurrentCode())) { 1503 !original_code.IsDisabled()) {
1500 function.AttachCode(original_code); 1504 function.AttachCode(original_code);
1501 } 1505 }
1502 ASSERT(function.unoptimized_code() != Object::null()); 1506 ASSERT(function.unoptimized_code() != Object::null());
1507 ASSERT(function.unoptimized_code() == result.raw());
1503 if (FLAG_trace_compiler) { 1508 if (FLAG_trace_compiler) {
1504 THR_Print("Ensure unoptimized code for %s\n", function.ToCString()); 1509 THR_Print("Ensure unoptimized code for %s\n", function.ToCString());
1505 } 1510 }
1506 return Error::null(); 1511 return Error::null();
1507 } 1512 }
1508 1513
1509 1514
1510 RawError* Compiler::CompileOptimizedFunction(Thread* thread, 1515 RawObject* Compiler::CompileOptimizedFunction(Thread* thread,
1511 const Function& function, 1516 const Function& function,
1512 intptr_t osr_id) { 1517 intptr_t osr_id) {
1513 #if !defined(PRODUCT) 1518 #if !defined(PRODUCT)
1514 VMTagScope tagScope(thread, VMTag::kCompileOptimizedTagId); 1519 VMTagScope tagScope(thread, VMTag::kCompileOptimizedTagId);
1515 const char* event_name; 1520 const char* event_name;
1516 if (osr_id != kNoOSRDeoptId) { 1521 if (osr_id != kNoOSRDeoptId) {
1517 event_name = "CompileFunctionOptimizedOSR"; 1522 event_name = "CompileFunctionOptimizedOSR";
1518 } else if (IsBackgroundCompilation()) { 1523 } else if (IsBackgroundCompilation()) {
1519 event_name = "CompileFunctionOptimizedBackground"; 1524 event_name = "CompileFunctionOptimizedBackground";
1520 } else { 1525 } else {
1521 event_name = "CompileFunctionOptimized"; 1526 event_name = "CompileFunctionOptimized";
1522 } 1527 }
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
1585 } else { 1590 } else {
1586 // Only possible with background compilation. 1591 // Only possible with background compilation.
1587 ASSERT(Compiler::IsBackgroundCompilation()); 1592 ASSERT(Compiler::IsBackgroundCompilation());
1588 } 1593 }
1589 } 1594 }
1590 1595
1591 1596
1592 RawError* Compiler::CompileAllFunctions(const Class& cls) { 1597 RawError* Compiler::CompileAllFunctions(const Class& cls) {
1593 Thread* thread = Thread::Current(); 1598 Thread* thread = Thread::Current();
1594 Zone* zone = thread->zone(); 1599 Zone* zone = thread->zone();
1595 Error& error = Error::Handle(zone); 1600 Object& result = Object::Handle(zone);
1596 Array& functions = Array::Handle(zone, cls.functions()); 1601 Array& functions = Array::Handle(zone, cls.functions());
1597 Function& func = Function::Handle(zone); 1602 Function& func = Function::Handle(zone);
1598 // Class dynamic lives in the vm isolate. Its array fields cannot be set to 1603 // Class dynamic lives in the vm isolate. Its array fields cannot be set to
1599 // an empty array. 1604 // an empty array.
1600 if (functions.IsNull()) { 1605 if (functions.IsNull()) {
1601 ASSERT(cls.IsDynamicClass()); 1606 ASSERT(cls.IsDynamicClass());
1602 return error.raw(); 1607 return Error::null();
1603 } 1608 }
1604 // Compile all the regular functions. 1609 // Compile all the regular functions.
1605 for (int i = 0; i < functions.Length(); i++) { 1610 for (int i = 0; i < functions.Length(); i++) {
1606 func ^= functions.At(i); 1611 func ^= functions.At(i);
1607 ASSERT(!func.IsNull()); 1612 ASSERT(!func.IsNull());
1608 if (!func.HasCode() && !func.is_abstract() && 1613 if (!func.HasCode() && !func.is_abstract() &&
1609 !func.IsRedirectingFactory()) { 1614 !func.IsRedirectingFactory()) {
1610 if ((cls.is_mixin_app_alias() || cls.IsMixinApplication()) && 1615 if ((cls.is_mixin_app_alias() || cls.IsMixinApplication()) &&
1611 func.HasOptionalParameters()) { 1616 func.HasOptionalParameters()) {
1612 // Skipping optional parameters in mixin application. 1617 // Skipping optional parameters in mixin application.
1613 continue; 1618 continue;
1614 } 1619 }
1615 error = CompileFunction(thread, func); 1620 result = CompileFunction(thread, func);
1616 if (!error.IsNull()) { 1621 if (result.IsError()) {
1617 return error.raw(); 1622 return Error::Cast(result).raw();
1618 } 1623 }
1624 ASSERT(!result.IsNull());
1619 func.ClearICDataArray(); 1625 func.ClearICDataArray();
1620 func.ClearCode(); 1626 func.ClearCode();
1621 } 1627 }
1622 } 1628 }
1623 return error.raw(); 1629 return Error::null();
1624 } 1630 }
1625 1631
1626 1632
1627 RawError* Compiler::ParseAllFunctions(const Class& cls) { 1633 RawError* Compiler::ParseAllFunctions(const Class& cls) {
1628 Thread* thread = Thread::Current(); 1634 Thread* thread = Thread::Current();
1629 Zone* zone = thread->zone(); 1635 Zone* zone = thread->zone();
1630 Error& error = Error::Handle(zone); 1636 Error& error = Error::Handle(zone);
1631 Array& functions = Array::Handle(zone, cls.functions()); 1637 Array& functions = Array::Handle(zone, cls.functions());
1632 Function& func = Function::Handle(zone); 1638 Function& func = Function::Handle(zone);
1633 // Class dynamic lives in the vm isolate. Its array fields cannot be set to 1639 // 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(); 2196 return Error::null();
2191 } 2197 }
2192 2198
2193 2199
2194 RawError* Compiler::CompileClass(const Class& cls) { 2200 RawError* Compiler::CompileClass(const Class& cls) {
2195 UNREACHABLE(); 2201 UNREACHABLE();
2196 return Error::null(); 2202 return Error::null();
2197 } 2203 }
2198 2204
2199 2205
2200 RawError* Compiler::CompileFunction(Thread* thread, const Function& function) { 2206 RawObject* Compiler::CompileFunction(Thread* thread, const Function& function) {
2201 UNREACHABLE(); 2207 UNREACHABLE();
2202 return Error::null(); 2208 return Error::null();
2203 } 2209 }
2204 2210
2205 2211
2206 RawError* Compiler::ParseFunction(Thread* thread, const Function& function) { 2212 RawError* Compiler::ParseFunction(Thread* thread, const Function& function) {
2207 UNREACHABLE(); 2213 UNREACHABLE();
2208 return Error::null(); 2214 return Error::null();
2209 } 2215 }
2210 2216
2211 2217
2212 RawError* Compiler::EnsureUnoptimizedCode(Thread* thread, 2218 RawError* Compiler::EnsureUnoptimizedCode(Thread* thread,
2213 const Function& function) { 2219 const Function& function) {
2214 UNREACHABLE(); 2220 UNREACHABLE();
2215 return Error::null(); 2221 return Error::null();
2216 } 2222 }
2217 2223
2218 2224
2219 RawError* Compiler::CompileOptimizedFunction(Thread* thread, 2225 RawObject* Compiler::CompileOptimizedFunction(Thread* thread,
2220 const Function& function, 2226 const Function& function,
2221 intptr_t osr_id) { 2227 intptr_t osr_id) {
2222 UNREACHABLE(); 2228 UNREACHABLE();
2223 return Error::null(); 2229 return Error::null();
2224 } 2230 }
2225 2231
2226 2232
2227 RawError* Compiler::CompileParsedFunction(ParsedFunction* parsed_function) { 2233 RawError* Compiler::CompileParsedFunction(ParsedFunction* parsed_function) {
2228 UNREACHABLE(); 2234 UNREACHABLE();
2229 return Error::null(); 2235 return Error::null();
2230 } 2236 }
2231 2237
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
2297 2303
2298 2304
2299 bool BackgroundCompiler::IsDisabled() { 2305 bool BackgroundCompiler::IsDisabled() {
2300 UNREACHABLE(); 2306 UNREACHABLE();
2301 return true; 2307 return true;
2302 } 2308 }
2303 2309
2304 #endif // DART_PRECOMPILED_RUNTIME 2310 #endif // DART_PRECOMPILED_RUNTIME
2305 2311
2306 } // namespace dart 2312 } // namespace dart
OLDNEW
« no previous file with comments | « 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