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

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

Issue 16693006: Initial implementation of on-stack replacement (OSR). (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Clean up for review. Created 7 years, 6 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 | Annotate | Revision Log
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/code_generator.h" 10 #include "vm/code_generator.h"
11 #include "vm/code_patcher.h" 11 #include "vm/code_patcher.h"
12 #include "vm/dart_entry.h" 12 #include "vm/dart_entry.h"
13 #include "vm/debugger.h" 13 #include "vm/debugger.h"
14 #include "vm/deopt_instructions.h" 14 #include "vm/deopt_instructions.h"
15 #include "vm/disassembler.h"
16 #include "vm/exceptions.h" 15 #include "vm/exceptions.h"
17 #include "vm/flags.h" 16 #include "vm/flags.h"
18 #include "vm/flow_graph.h" 17 #include "vm/flow_graph.h"
19 #include "vm/flow_graph_allocator.h" 18 #include "vm/flow_graph_allocator.h"
20 #include "vm/flow_graph_builder.h" 19 #include "vm/flow_graph_builder.h"
21 #include "vm/flow_graph_compiler.h" 20 #include "vm/flow_graph_compiler.h"
22 #include "vm/flow_graph_inliner.h" 21 #include "vm/flow_graph_inliner.h"
23 #include "vm/flow_graph_optimizer.h" 22 #include "vm/flow_graph_optimizer.h"
24 #include "vm/flow_graph_type_propagator.h" 23 #include "vm/flow_graph_type_propagator.h"
25 #include "vm/il_printer.h" 24 #include "vm/il_printer.h"
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 function.SwitchToUnoptimizedCode(); 233 function.SwitchToUnoptimizedCode();
235 if (FLAG_trace_compiler) { 234 if (FLAG_trace_compiler) {
236 OS::Print("--> restoring entry at %#"Px"\n", 235 OS::Print("--> restoring entry at %#"Px"\n",
237 Code::Handle(function.unoptimized_code()).EntryPoint()); 236 Code::Handle(function.unoptimized_code()).EntryPoint());
238 } 237 }
239 } 238 }
240 239
241 240
242 // Return false if bailed out. 241 // Return false if bailed out.
243 static bool CompileParsedFunctionHelper(ParsedFunction* parsed_function, 242 static bool CompileParsedFunctionHelper(ParsedFunction* parsed_function,
244 bool optimized) { 243 bool optimized,
244 intptr_t osr_id) {
245 const Function& function = parsed_function->function(); 245 const Function& function = parsed_function->function();
246 if (optimized && !function.is_optimizable()) { 246 if (optimized && !function.is_optimizable()) {
247 return false; 247 return false;
248 } 248 }
249 TimerScope timer(FLAG_compiler_stats, &CompilerStats::codegen_timer); 249 TimerScope timer(FLAG_compiler_stats, &CompilerStats::codegen_timer);
250 bool is_compiled = false; 250 bool is_compiled = false;
251 Isolate* isolate = Isolate::Current(); 251 Isolate* isolate = Isolate::Current();
252 HANDLESCOPE(isolate); 252 HANDLESCOPE(isolate);
253 const intptr_t prev_deopt_id = isolate->deopt_id(); 253 const intptr_t prev_deopt_id = isolate->deopt_id();
254 isolate->set_deopt_id(0); 254 isolate->set_deopt_id(0);
(...skipping 19 matching lines...) Expand all
274 FLAG_deoptimization_counter_threshold) { 274 FLAG_deoptimization_counter_threshold) {
275 const Code& unoptimized_code = 275 const Code& unoptimized_code =
276 Code::Handle(function.unoptimized_code()); 276 Code::Handle(function.unoptimized_code());
277 ic_data_array = unoptimized_code.ExtractTypeFeedbackArray(); 277 ic_data_array = unoptimized_code.ExtractTypeFeedbackArray();
278 } 278 }
279 } 279 }
280 280
281 // Build the flow graph. 281 // Build the flow graph.
282 FlowGraphBuilder builder(parsed_function, 282 FlowGraphBuilder builder(parsed_function,
283 ic_data_array, 283 ic_data_array,
284 NULL); // NULL = not inlining. 284 NULL, // NULL = not inlining.
285 osr_id);
285 flow_graph = builder.BuildGraph(); 286 flow_graph = builder.BuildGraph();
286 } 287 }
287 288
288 if (FLAG_print_flow_graph || 289 if (FLAG_print_flow_graph ||
289 (optimized && FLAG_print_flow_graph_optimized)) { 290 (optimized && FLAG_print_flow_graph_optimized)) {
290 FlowGraphPrinter::PrintGraph("Before Optimizations", flow_graph); 291 if (osr_id == Isolate::kNoDeoptId) {
292 FlowGraphPrinter::PrintGraph("Before Optimizations", flow_graph);
293 } else {
294 FlowGraphPrinter::PrintGraph("For OSR", flow_graph);
295 }
291 } 296 }
292 297
293 if (optimized) { 298 if (optimized) {
294 TimerScope timer(FLAG_compiler_stats, 299 TimerScope timer(FLAG_compiler_stats,
295 &CompilerStats::ssa_timer, 300 &CompilerStats::ssa_timer,
296 isolate); 301 isolate);
297 // Transform to SSA (virtual register 0 and no inlining arguments). 302 // Transform to SSA (virtual register 0 and no inlining arguments).
298 flow_graph->ComputeSSA(0, NULL); 303 flow_graph->ComputeSSA(0, NULL);
299 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 304 DEBUG_ASSERT(flow_graph->VerifyUseLists());
300 if (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized) { 305 if (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized) {
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
495 code.set_is_optimized(optimized); 500 code.set_is_optimized(optimized);
496 graph_compiler.FinalizePcDescriptors(code); 501 graph_compiler.FinalizePcDescriptors(code);
497 graph_compiler.FinalizeDeoptInfo(code); 502 graph_compiler.FinalizeDeoptInfo(code);
498 graph_compiler.FinalizeStackmaps(code); 503 graph_compiler.FinalizeStackmaps(code);
499 graph_compiler.FinalizeVarDescriptors(code); 504 graph_compiler.FinalizeVarDescriptors(code);
500 graph_compiler.FinalizeExceptionHandlers(code); 505 graph_compiler.FinalizeExceptionHandlers(code);
501 graph_compiler.FinalizeComments(code); 506 graph_compiler.FinalizeComments(code);
502 graph_compiler.FinalizeStaticCallTargetsTable(code); 507 graph_compiler.FinalizeStaticCallTargetsTable(code);
503 508
504 if (optimized) { 509 if (optimized) {
505 CodePatcher::PatchEntry(Code::Handle(function.CurrentCode())); 510 if (osr_id == Isolate::kNoDeoptId) {
511 CodePatcher::PatchEntry(Code::Handle(function.CurrentCode()));
512 if (FLAG_trace_compiler) {
513 OS::Print("--> patching entry %#"Px"\n",
514 Code::Handle(function.unoptimized_code()).EntryPoint());
515 }
516 }
506 function.SetCode(code); 517 function.SetCode(code);
507 if (FLAG_trace_compiler) {
508 OS::Print("--> patching entry %#"Px"\n",
509 Code::Handle(function.unoptimized_code()).EntryPoint());
510 }
511 518
512 // If not yet present, allocate deoptimization history array. 519 // If not yet present, allocate deoptimization history array.
513 function.EnsureDeoptHistory(); 520 function.EnsureDeoptHistory();
514 521
515 for (intptr_t i = 0; i < guarded_fields.length(); i++) { 522 for (intptr_t i = 0; i < guarded_fields.length(); i++) {
516 const Field& field = *guarded_fields[i]; 523 const Field& field = *guarded_fields[i];
517 field.RegisterDependentCode(code); 524 field.RegisterDependentCode(code);
518 } 525 }
519 } else { 526 } else {
520 function.set_unoptimized_code(code); 527 function.set_unoptimized_code(code);
(...skipping 20 matching lines...) Expand all
541 return is_compiled; 548 return is_compiled;
542 } 549 }
543 550
544 551
545 static void DisassembleCode(const Function& function, bool optimized) { 552 static void DisassembleCode(const Function& function, bool optimized) {
546 const char* function_fullname = function.ToFullyQualifiedCString(); 553 const char* function_fullname = function.ToFullyQualifiedCString();
547 OS::Print("Code for %sfunction '%s' {\n", 554 OS::Print("Code for %sfunction '%s' {\n",
548 optimized ? "optimized " : "", 555 optimized ? "optimized " : "",
549 function_fullname); 556 function_fullname);
550 const Code& code = Code::Handle(function.CurrentCode()); 557 const Code& code = Code::Handle(function.CurrentCode());
551 const Instructions& instructions = 558 code.Disassemble();
552 Instructions::Handle(code.instructions());
553 uword start = instructions.EntryPoint();
554 Disassembler::Disassemble(start,
555 start + instructions.size(),
556 code.comments());
557 OS::Print("}\n"); 559 OS::Print("}\n");
558 560
559 OS::Print("Pointer offsets for function: {\n"); 561 OS::Print("Pointer offsets for function: {\n");
560 // Pointer offsets are stored in descending order. 562 // Pointer offsets are stored in descending order.
561 for (intptr_t i = code.pointer_offsets_length() - 1; i >= 0; i--) { 563 for (intptr_t i = code.pointer_offsets_length() - 1; i >= 0; i--) {
562 const uword addr = code.GetPointerOffsetAt(i) + code.EntryPoint(); 564 const uword addr = code.GetPointerOffsetAt(i) + code.EntryPoint();
563 Object& obj = Object::Handle(); 565 Object& obj = Object::Handle();
564 obj = *reinterpret_cast<RawObject**>(addr); 566 obj = *reinterpret_cast<RawObject**>(addr);
565 OS::Print(" %d : %#"Px" '%s'\n", 567 OS::Print(" %d : %#"Px" '%s'\n",
566 code.GetPointerOffsetAt(i), addr, obj.ToCString()); 568 code.GetPointerOffsetAt(i), addr, obj.ToCString());
567 } 569 }
568 OS::Print("}\n"); 570 OS::Print("}\n");
569 571
570 OS::Print("PC Descriptors for function '%s' {\n", function_fullname); 572 OS::Print("PC Descriptors for function '%s' {\n", function_fullname);
571 PcDescriptors::PrintHeaderString(); 573 PcDescriptors::PrintHeaderString();
572 const PcDescriptors& descriptors = 574 const PcDescriptors& descriptors =
573 PcDescriptors::Handle(code.pc_descriptors()); 575 PcDescriptors::Handle(code.pc_descriptors());
574 OS::Print("%s}\n", descriptors.ToCString()); 576 OS::Print("%s}\n", descriptors.ToCString());
575 577
578 uword start = Instructions::Handle(code.instructions()).EntryPoint();
576 const Array& deopt_table = Array::Handle(code.deopt_info_array()); 579 const Array& deopt_table = Array::Handle(code.deopt_info_array());
577 intptr_t deopt_table_length = DeoptTable::GetLength(deopt_table); 580 intptr_t deopt_table_length = DeoptTable::GetLength(deopt_table);
578 if (deopt_table_length > 0) { 581 if (deopt_table_length > 0) {
579 OS::Print("DeoptInfo: {\n"); 582 OS::Print("DeoptInfo: {\n");
580 Smi& offset = Smi::Handle(); 583 Smi& offset = Smi::Handle();
581 DeoptInfo& info = DeoptInfo::Handle(); 584 DeoptInfo& info = DeoptInfo::Handle();
582 Smi& reason = Smi::Handle(); 585 Smi& reason = Smi::Handle();
583 for (intptr_t i = 0; i < deopt_table_length; ++i) { 586 for (intptr_t i = 0; i < deopt_table_length; ++i) {
584 DeoptTable::GetEntry(deopt_table, i, &offset, &info, &reason); 587 DeoptTable::GetEntry(deopt_table, i, &offset, &info, &reason);
585 OS::Print("%4"Pd": 0x%"Px" %s (%s)\n", 588 OS::Print("%4"Pd": 0x%"Px" %s (%s)\n",
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
665 start + offset.Value(), 668 start + offset.Value(),
666 function.ToFullyQualifiedCString(), 669 function.ToFullyQualifiedCString(),
667 code.raw()); 670 code.raw());
668 } 671 }
669 OS::Print("}\n"); 672 OS::Print("}\n");
670 } 673 }
671 } 674 }
672 675
673 676
674 static RawError* CompileFunctionHelper(const Function& function, 677 static RawError* CompileFunctionHelper(const Function& function,
675 bool optimized) { 678 bool optimized,
679 intptr_t osr_id) {
676 Isolate* isolate = Isolate::Current(); 680 Isolate* isolate = Isolate::Current();
677 StackZone zone(isolate); 681 StackZone zone(isolate);
678 LongJump* base = isolate->long_jump_base(); 682 LongJump* base = isolate->long_jump_base();
679 LongJump jump; 683 LongJump jump;
680 isolate->set_long_jump_base(&jump); 684 isolate->set_long_jump_base(&jump);
681 // Skips parsing if we need to only install unoptimized code. 685 // Skips parsing if we need to only install unoptimized code.
682 if (!optimized && !Code::Handle(function.unoptimized_code()).IsNull()) { 686 if (!optimized && !Code::Handle(function.unoptimized_code()).IsNull()) {
683 InstallUnoptimizedCode(function); 687 InstallUnoptimizedCode(function);
684 isolate->set_long_jump_base(base); 688 isolate->set_long_jump_base(base);
685 return Error::null(); 689 return Error::null();
686 } 690 }
687 if (setjmp(*jump.Set()) == 0) { 691 if (setjmp(*jump.Set()) == 0) {
688 TIMERSCOPE(time_compilation); 692 TIMERSCOPE(time_compilation);
689 Timer per_compile_timer(FLAG_trace_compiler, "Compilation time"); 693 Timer per_compile_timer(FLAG_trace_compiler, "Compilation time");
690 per_compile_timer.Start(); 694 per_compile_timer.Start();
691 ParsedFunction* parsed_function = new ParsedFunction( 695 ParsedFunction* parsed_function = new ParsedFunction(
692 Function::ZoneHandle(function.raw())); 696 Function::ZoneHandle(function.raw()));
693 if (FLAG_trace_compiler) { 697 if (FLAG_trace_compiler) {
694 OS::Print("Compiling %sfunction: '%s' @ token %"Pd", size %"Pd"\n", 698 OS::Print("Compiling %s%sfunction: '%s' @ token %"Pd", size %"Pd"\n",
699 (osr_id == Isolate::kNoDeoptId ? "" : "osr "),
695 (optimized ? "optimized " : ""), 700 (optimized ? "optimized " : ""),
696 function.ToFullyQualifiedCString(), 701 function.ToFullyQualifiedCString(),
697 function.token_pos(), 702 function.token_pos(),
698 (function.end_token_pos() - function.token_pos())); 703 (function.end_token_pos() - function.token_pos()));
699 } 704 }
700 { 705 {
701 HANDLESCOPE(isolate); 706 HANDLESCOPE(isolate);
702 Parser::ParseFunction(parsed_function); 707 Parser::ParseFunction(parsed_function);
703 parsed_function->AllocateVariables(); 708 parsed_function->AllocateVariables();
704 } 709 }
705 710
706 const bool success = 711 const bool success =
707 CompileParsedFunctionHelper(parsed_function, optimized); 712 CompileParsedFunctionHelper(parsed_function, optimized, osr_id);
708 if (optimized && !success) { 713 if (optimized && !success) {
709 // Optimizer bailed out. Disable optimizations and to never try again. 714 // Optimizer bailed out. Disable optimizations and to never try again.
710 if (FLAG_trace_compiler) { 715 if (FLAG_trace_compiler) {
711 OS::Print("--> disabling optimizations for '%s'\n", 716 OS::Print("--> disabling optimizations for '%s'\n",
712 function.ToFullyQualifiedCString()); 717 function.ToFullyQualifiedCString());
713 } else if (FLAG_trace_failed_optimization_attempts) { 718 } else if (FLAG_trace_failed_optimization_attempts) {
714 OS::Print("Cannot optimize: %s\n", function.ToFullyQualifiedCString()); 719 OS::Print("Cannot optimize: %s\n", function.ToFullyQualifiedCString());
715 } 720 }
716 function.set_is_optimizable(false); 721 function.set_is_optimizable(false);
717 isolate->set_long_jump_base(base); 722 isolate->set_long_jump_base(base);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
749 isolate->object_store()->clear_sticky_error(); 754 isolate->object_store()->clear_sticky_error();
750 isolate->set_long_jump_base(base); 755 isolate->set_long_jump_base(base);
751 return error.raw(); 756 return error.raw();
752 } 757 }
753 UNREACHABLE(); 758 UNREACHABLE();
754 return Error::null(); 759 return Error::null();
755 } 760 }
756 761
757 762
758 RawError* Compiler::CompileFunction(const Function& function) { 763 RawError* Compiler::CompileFunction(const Function& function) {
759 return CompileFunctionHelper(function, false); // Non-optimized. 764 return CompileFunctionHelper(function, false, Isolate::kNoDeoptId);
760 } 765 }
761 766
762 767
763 RawError* Compiler::CompileOptimizedFunction(const Function& function) { 768 RawError* Compiler::CompileOptimizedFunction(const Function& function,
764 return CompileFunctionHelper(function, true); // Optimized. 769 intptr_t osr_id) {
770 return CompileFunctionHelper(function, true, osr_id);
765 } 771 }
766 772
767 773
768 RawError* Compiler::CompileParsedFunction( 774 RawError* Compiler::CompileParsedFunction(
769 ParsedFunction* parsed_function) { 775 ParsedFunction* parsed_function) {
770 Isolate* isolate = Isolate::Current(); 776 Isolate* isolate = Isolate::Current();
771 LongJump* base = isolate->long_jump_base(); 777 LongJump* base = isolate->long_jump_base();
772 LongJump jump; 778 LongJump jump;
773 isolate->set_long_jump_base(&jump); 779 isolate->set_long_jump_base(&jump);
774 if (setjmp(*jump.Set()) == 0) { 780 if (setjmp(*jump.Set()) == 0) {
775 // Non-optimized code generator. 781 // Non-optimized code generator.
776 CompileParsedFunctionHelper(parsed_function, false); 782 CompileParsedFunctionHelper(parsed_function, false, Isolate::kNoDeoptId);
777 if (FLAG_disassemble) { 783 if (FLAG_disassemble) {
778 DisassembleCode(parsed_function->function(), false); 784 DisassembleCode(parsed_function->function(), false);
779 } 785 }
780 isolate->set_long_jump_base(base); 786 isolate->set_long_jump_base(base);
781 return Error::null(); 787 return Error::null();
782 } else { 788 } else {
783 Error& error = Error::Handle(); 789 Error& error = Error::Handle();
784 // We got an error during compilation. 790 // We got an error during compilation.
785 error = isolate->object_store()->sticky_error(); 791 error = isolate->object_store()->sticky_error();
786 isolate->object_store()->clear_sticky_error(); 792 isolate->object_store()->clear_sticky_error();
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
853 // would compile func automatically. We are checking fewer invariants 859 // would compile func automatically. We are checking fewer invariants
854 // here. 860 // here.
855 ParsedFunction* parsed_function = new ParsedFunction(func); 861 ParsedFunction* parsed_function = new ParsedFunction(func);
856 parsed_function->SetNodeSequence(fragment); 862 parsed_function->SetNodeSequence(fragment);
857 parsed_function->set_default_parameter_values(Array::ZoneHandle()); 863 parsed_function->set_default_parameter_values(Array::ZoneHandle());
858 parsed_function->EnsureExpressionTemp(); 864 parsed_function->EnsureExpressionTemp();
859 fragment->scope()->AddVariable(parsed_function->expression_temp_var()); 865 fragment->scope()->AddVariable(parsed_function->expression_temp_var());
860 parsed_function->AllocateVariables(); 866 parsed_function->AllocateVariables();
861 867
862 // Non-optimized code generator. 868 // Non-optimized code generator.
863 CompileParsedFunctionHelper(parsed_function, false); 869 CompileParsedFunctionHelper(parsed_function, false, Isolate::kNoDeoptId);
864 870
865 const Object& result = Object::Handle( 871 const Object& result = Object::Handle(
866 DartEntry::InvokeFunction(func, Object::empty_array())); 872 DartEntry::InvokeFunction(func, Object::empty_array()));
867 isolate->set_long_jump_base(base); 873 isolate->set_long_jump_base(base);
868 return result.raw(); 874 return result.raw();
869 } else { 875 } else {
870 const Object& result = 876 const Object& result =
871 Object::Handle(isolate->object_store()->sticky_error()); 877 Object::Handle(isolate->object_store()->sticky_error());
872 isolate->object_store()->clear_sticky_error(); 878 isolate->object_store()->clear_sticky_error();
873 isolate->set_long_jump_base(base); 879 isolate->set_long_jump_base(base);
874 return result.raw(); 880 return result.raw();
875 } 881 }
876 UNREACHABLE(); 882 UNREACHABLE();
877 return Object::null(); 883 return Object::null();
878 } 884 }
879 885
880 } // namespace dart 886 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698