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

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

Issue 17233003: Reapply "Initial implementation of on-stack replacement (OSR)." (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: 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
« no previous file with comments | « runtime/vm/compiler.h ('k') | runtime/vm/flow_graph.h » ('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/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 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
501 code.set_is_optimized(optimized); 506 code.set_is_optimized(optimized);
502 graph_compiler.FinalizePcDescriptors(code); 507 graph_compiler.FinalizePcDescriptors(code);
503 graph_compiler.FinalizeDeoptInfo(code); 508 graph_compiler.FinalizeDeoptInfo(code);
504 graph_compiler.FinalizeStackmaps(code); 509 graph_compiler.FinalizeStackmaps(code);
505 graph_compiler.FinalizeVarDescriptors(code); 510 graph_compiler.FinalizeVarDescriptors(code);
506 graph_compiler.FinalizeExceptionHandlers(code); 511 graph_compiler.FinalizeExceptionHandlers(code);
507 graph_compiler.FinalizeComments(code); 512 graph_compiler.FinalizeComments(code);
508 graph_compiler.FinalizeStaticCallTargetsTable(code); 513 graph_compiler.FinalizeStaticCallTargetsTable(code);
509 514
510 if (optimized) { 515 if (optimized) {
511 CodePatcher::PatchEntry(Code::Handle(function.CurrentCode())); 516 if (osr_id == Isolate::kNoDeoptId) {
517 CodePatcher::PatchEntry(Code::Handle(function.CurrentCode()));
518 if (FLAG_trace_compiler) {
519 OS::Print("--> patching entry %#"Px"\n",
520 Code::Handle(function.unoptimized_code()).EntryPoint());
521 }
522 }
512 function.SetCode(code); 523 function.SetCode(code);
513 if (FLAG_trace_compiler) {
514 OS::Print("--> patching entry %#"Px"\n",
515 Code::Handle(function.unoptimized_code()).EntryPoint());
516 }
517 524
518 for (intptr_t i = 0; i < guarded_fields.length(); i++) { 525 for (intptr_t i = 0; i < guarded_fields.length(); i++) {
519 const Field& field = *guarded_fields[i]; 526 const Field& field = *guarded_fields[i];
520 field.RegisterDependentCode(code); 527 field.RegisterDependentCode(code);
521 } 528 }
522 } else { 529 } else {
523 function.set_unoptimized_code(code); 530 function.set_unoptimized_code(code);
524 function.SetCode(code); 531 function.SetCode(code);
525 ASSERT(CodePatcher::CodeIsPatchable(code)); 532 ASSERT(CodePatcher::CodeIsPatchable(code));
526 } 533 }
(...skipping 17 matching lines...) Expand all
544 return is_compiled; 551 return is_compiled;
545 } 552 }
546 553
547 554
548 static void DisassembleCode(const Function& function, bool optimized) { 555 static void DisassembleCode(const Function& function, bool optimized) {
549 const char* function_fullname = function.ToFullyQualifiedCString(); 556 const char* function_fullname = function.ToFullyQualifiedCString();
550 OS::Print("Code for %sfunction '%s' {\n", 557 OS::Print("Code for %sfunction '%s' {\n",
551 optimized ? "optimized " : "", 558 optimized ? "optimized " : "",
552 function_fullname); 559 function_fullname);
553 const Code& code = Code::Handle(function.CurrentCode()); 560 const Code& code = Code::Handle(function.CurrentCode());
554 const Instructions& instructions = 561 code.Disassemble();
555 Instructions::Handle(code.instructions());
556 uword start = instructions.EntryPoint();
557 Disassembler::Disassemble(start,
558 start + instructions.size(),
559 code.comments());
560 OS::Print("}\n"); 562 OS::Print("}\n");
561 563
562 OS::Print("Pointer offsets for function: {\n"); 564 OS::Print("Pointer offsets for function: {\n");
563 // Pointer offsets are stored in descending order. 565 // Pointer offsets are stored in descending order.
564 for (intptr_t i = code.pointer_offsets_length() - 1; i >= 0; i--) { 566 for (intptr_t i = code.pointer_offsets_length() - 1; i >= 0; i--) {
565 const uword addr = code.GetPointerOffsetAt(i) + code.EntryPoint(); 567 const uword addr = code.GetPointerOffsetAt(i) + code.EntryPoint();
566 Object& obj = Object::Handle(); 568 Object& obj = Object::Handle();
567 obj = *reinterpret_cast<RawObject**>(addr); 569 obj = *reinterpret_cast<RawObject**>(addr);
568 OS::Print(" %d : %#"Px" '%s'\n", 570 OS::Print(" %d : %#"Px" '%s'\n",
569 code.GetPointerOffsetAt(i), addr, obj.ToCString()); 571 code.GetPointerOffsetAt(i), addr, obj.ToCString());
570 } 572 }
571 OS::Print("}\n"); 573 OS::Print("}\n");
572 574
573 OS::Print("PC Descriptors for function '%s' {\n", function_fullname); 575 OS::Print("PC Descriptors for function '%s' {\n", function_fullname);
574 PcDescriptors::PrintHeaderString(); 576 PcDescriptors::PrintHeaderString();
575 const PcDescriptors& descriptors = 577 const PcDescriptors& descriptors =
576 PcDescriptors::Handle(code.pc_descriptors()); 578 PcDescriptors::Handle(code.pc_descriptors());
577 OS::Print("%s}\n", descriptors.ToCString()); 579 OS::Print("%s}\n", descriptors.ToCString());
578 580
581 uword start = Instructions::Handle(code.instructions()).EntryPoint();
579 const Array& deopt_table = Array::Handle(code.deopt_info_array()); 582 const Array& deopt_table = Array::Handle(code.deopt_info_array());
580 intptr_t deopt_table_length = DeoptTable::GetLength(deopt_table); 583 intptr_t deopt_table_length = DeoptTable::GetLength(deopt_table);
581 if (deopt_table_length > 0) { 584 if (deopt_table_length > 0) {
582 OS::Print("DeoptInfo: {\n"); 585 OS::Print("DeoptInfo: {\n");
583 Smi& offset = Smi::Handle(); 586 Smi& offset = Smi::Handle();
584 DeoptInfo& info = DeoptInfo::Handle(); 587 DeoptInfo& info = DeoptInfo::Handle();
585 Smi& reason = Smi::Handle(); 588 Smi& reason = Smi::Handle();
586 for (intptr_t i = 0; i < deopt_table_length; ++i) { 589 for (intptr_t i = 0; i < deopt_table_length; ++i) {
587 DeoptTable::GetEntry(deopt_table, i, &offset, &info, &reason); 590 DeoptTable::GetEntry(deopt_table, i, &offset, &info, &reason);
588 OS::Print("%4"Pd": 0x%"Px" %s (%s)\n", 591 OS::Print("%4"Pd": 0x%"Px" %s (%s)\n",
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
668 start + offset.Value(), 671 start + offset.Value(),
669 function.ToFullyQualifiedCString(), 672 function.ToFullyQualifiedCString(),
670 code.raw()); 673 code.raw());
671 } 674 }
672 OS::Print("}\n"); 675 OS::Print("}\n");
673 } 676 }
674 } 677 }
675 678
676 679
677 static RawError* CompileFunctionHelper(const Function& function, 680 static RawError* CompileFunctionHelper(const Function& function,
678 bool optimized) { 681 bool optimized,
682 intptr_t osr_id) {
679 Isolate* isolate = Isolate::Current(); 683 Isolate* isolate = Isolate::Current();
680 StackZone zone(isolate); 684 StackZone zone(isolate);
681 LongJump* base = isolate->long_jump_base(); 685 LongJump* base = isolate->long_jump_base();
682 LongJump jump; 686 LongJump jump;
683 isolate->set_long_jump_base(&jump); 687 isolate->set_long_jump_base(&jump);
684 // Skips parsing if we need to only install unoptimized code. 688 // Skips parsing if we need to only install unoptimized code.
685 if (!optimized && !Code::Handle(function.unoptimized_code()).IsNull()) { 689 if (!optimized && !Code::Handle(function.unoptimized_code()).IsNull()) {
686 InstallUnoptimizedCode(function); 690 InstallUnoptimizedCode(function);
687 isolate->set_long_jump_base(base); 691 isolate->set_long_jump_base(base);
688 return Error::null(); 692 return Error::null();
689 } 693 }
690 if (setjmp(*jump.Set()) == 0) { 694 if (setjmp(*jump.Set()) == 0) {
691 TIMERSCOPE(time_compilation); 695 TIMERSCOPE(time_compilation);
692 Timer per_compile_timer(FLAG_trace_compiler, "Compilation time"); 696 Timer per_compile_timer(FLAG_trace_compiler, "Compilation time");
693 per_compile_timer.Start(); 697 per_compile_timer.Start();
694 ParsedFunction* parsed_function = new ParsedFunction( 698 ParsedFunction* parsed_function = new ParsedFunction(
695 Function::ZoneHandle(function.raw())); 699 Function::ZoneHandle(function.raw()));
696 if (FLAG_trace_compiler) { 700 if (FLAG_trace_compiler) {
697 OS::Print("Compiling %sfunction: '%s' @ token %"Pd", size %"Pd"\n", 701 OS::Print("Compiling %s%sfunction: '%s' @ token %"Pd", size %"Pd"\n",
702 (osr_id == Isolate::kNoDeoptId ? "" : "osr "),
698 (optimized ? "optimized " : ""), 703 (optimized ? "optimized " : ""),
699 function.ToFullyQualifiedCString(), 704 function.ToFullyQualifiedCString(),
700 function.token_pos(), 705 function.token_pos(),
701 (function.end_token_pos() - function.token_pos())); 706 (function.end_token_pos() - function.token_pos()));
702 } 707 }
703 { 708 {
704 HANDLESCOPE(isolate); 709 HANDLESCOPE(isolate);
705 Parser::ParseFunction(parsed_function); 710 Parser::ParseFunction(parsed_function);
706 parsed_function->AllocateVariables(); 711 parsed_function->AllocateVariables();
707 } 712 }
708 713
709 const bool success = 714 const bool success =
710 CompileParsedFunctionHelper(parsed_function, optimized); 715 CompileParsedFunctionHelper(parsed_function, optimized, osr_id);
711 if (optimized && !success) { 716 if (optimized && !success) {
712 // Optimizer bailed out. Disable optimizations and to never try again. 717 // Optimizer bailed out. Disable optimizations and to never try again.
713 if (FLAG_trace_compiler) { 718 if (FLAG_trace_compiler) {
714 OS::Print("--> disabling optimizations for '%s'\n", 719 OS::Print("--> disabling optimizations for '%s'\n",
715 function.ToFullyQualifiedCString()); 720 function.ToFullyQualifiedCString());
716 } else if (FLAG_trace_failed_optimization_attempts) { 721 } else if (FLAG_trace_failed_optimization_attempts) {
717 OS::Print("Cannot optimize: %s\n", function.ToFullyQualifiedCString()); 722 OS::Print("Cannot optimize: %s\n", function.ToFullyQualifiedCString());
718 } 723 }
719 function.set_is_optimizable(false); 724 function.set_is_optimizable(false);
720 isolate->set_long_jump_base(base); 725 isolate->set_long_jump_base(base);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
752 isolate->object_store()->clear_sticky_error(); 757 isolate->object_store()->clear_sticky_error();
753 isolate->set_long_jump_base(base); 758 isolate->set_long_jump_base(base);
754 return error.raw(); 759 return error.raw();
755 } 760 }
756 UNREACHABLE(); 761 UNREACHABLE();
757 return Error::null(); 762 return Error::null();
758 } 763 }
759 764
760 765
761 RawError* Compiler::CompileFunction(const Function& function) { 766 RawError* Compiler::CompileFunction(const Function& function) {
762 return CompileFunctionHelper(function, false); // Non-optimized. 767 return CompileFunctionHelper(function, false, Isolate::kNoDeoptId);
763 } 768 }
764 769
765 770
766 RawError* Compiler::CompileOptimizedFunction(const Function& function) { 771 RawError* Compiler::CompileOptimizedFunction(const Function& function,
767 return CompileFunctionHelper(function, true); // Optimized. 772 intptr_t osr_id) {
773 return CompileFunctionHelper(function, true, osr_id);
768 } 774 }
769 775
770 776
771 RawError* Compiler::CompileParsedFunction( 777 RawError* Compiler::CompileParsedFunction(
772 ParsedFunction* parsed_function) { 778 ParsedFunction* parsed_function) {
773 Isolate* isolate = Isolate::Current(); 779 Isolate* isolate = Isolate::Current();
774 LongJump* base = isolate->long_jump_base(); 780 LongJump* base = isolate->long_jump_base();
775 LongJump jump; 781 LongJump jump;
776 isolate->set_long_jump_base(&jump); 782 isolate->set_long_jump_base(&jump);
777 if (setjmp(*jump.Set()) == 0) { 783 if (setjmp(*jump.Set()) == 0) {
778 // Non-optimized code generator. 784 // Non-optimized code generator.
779 CompileParsedFunctionHelper(parsed_function, false); 785 CompileParsedFunctionHelper(parsed_function, false, Isolate::kNoDeoptId);
780 if (FLAG_disassemble) { 786 if (FLAG_disassemble) {
781 DisassembleCode(parsed_function->function(), false); 787 DisassembleCode(parsed_function->function(), false);
782 } 788 }
783 isolate->set_long_jump_base(base); 789 isolate->set_long_jump_base(base);
784 return Error::null(); 790 return Error::null();
785 } else { 791 } else {
786 Error& error = Error::Handle(); 792 Error& error = Error::Handle();
787 // We got an error during compilation. 793 // We got an error during compilation.
788 error = isolate->object_store()->sticky_error(); 794 error = isolate->object_store()->sticky_error();
789 isolate->object_store()->clear_sticky_error(); 795 isolate->object_store()->clear_sticky_error();
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
856 // would compile func automatically. We are checking fewer invariants 862 // would compile func automatically. We are checking fewer invariants
857 // here. 863 // here.
858 ParsedFunction* parsed_function = new ParsedFunction(func); 864 ParsedFunction* parsed_function = new ParsedFunction(func);
859 parsed_function->SetNodeSequence(fragment); 865 parsed_function->SetNodeSequence(fragment);
860 parsed_function->set_default_parameter_values(Array::ZoneHandle()); 866 parsed_function->set_default_parameter_values(Array::ZoneHandle());
861 parsed_function->EnsureExpressionTemp(); 867 parsed_function->EnsureExpressionTemp();
862 fragment->scope()->AddVariable(parsed_function->expression_temp_var()); 868 fragment->scope()->AddVariable(parsed_function->expression_temp_var());
863 parsed_function->AllocateVariables(); 869 parsed_function->AllocateVariables();
864 870
865 // Non-optimized code generator. 871 // Non-optimized code generator.
866 CompileParsedFunctionHelper(parsed_function, false); 872 CompileParsedFunctionHelper(parsed_function, false, Isolate::kNoDeoptId);
867 873
868 const Object& result = Object::Handle( 874 const Object& result = Object::Handle(
869 DartEntry::InvokeFunction(func, Object::empty_array())); 875 DartEntry::InvokeFunction(func, Object::empty_array()));
870 isolate->set_long_jump_base(base); 876 isolate->set_long_jump_base(base);
871 return result.raw(); 877 return result.raw();
872 } else { 878 } else {
873 const Object& result = 879 const Object& result =
874 Object::Handle(isolate->object_store()->sticky_error()); 880 Object::Handle(isolate->object_store()->sticky_error());
875 isolate->object_store()->clear_sticky_error(); 881 isolate->object_store()->clear_sticky_error();
876 isolate->set_long_jump_base(base); 882 isolate->set_long_jump_base(base);
877 return result.raw(); 883 return result.raw();
878 } 884 }
879 UNREACHABLE(); 885 UNREACHABLE();
880 return Object::null(); 886 return Object::null();
881 } 887 }
882 888
883 } // namespace dart 889 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/compiler.h ('k') | runtime/vm/flow_graph.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698