OLD | NEW |
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" |
11 #include "vm/branch_optimizer.h" | 11 #include "vm/branch_optimizer.h" |
12 #include "vm/cha.h" | 12 #include "vm/cha.h" |
13 #include "vm/code_generator.h" | 13 #include "vm/code_generator.h" |
14 #include "vm/code_patcher.h" | 14 #include "vm/code_patcher.h" |
15 #include "vm/constant_propagator.h" | 15 #include "vm/constant_propagator.h" |
16 #include "vm/dart_entry.h" | 16 #include "vm/dart_entry.h" |
17 #include "vm/debugger.h" | 17 #include "vm/debugger.h" |
18 #include "vm/deopt_instructions.h" | 18 #include "vm/deopt_instructions.h" |
| 19 #include "vm/disassembler.h" |
19 #include "vm/exceptions.h" | 20 #include "vm/exceptions.h" |
20 #include "vm/flags.h" | 21 #include "vm/flags.h" |
21 #include "vm/flow_graph.h" | 22 #include "vm/flow_graph.h" |
22 #include "vm/flow_graph_allocator.h" | 23 #include "vm/flow_graph_allocator.h" |
23 #include "vm/flow_graph_builder.h" | 24 #include "vm/flow_graph_builder.h" |
24 #include "vm/flow_graph_compiler.h" | 25 #include "vm/flow_graph_compiler.h" |
25 #include "vm/flow_graph_inliner.h" | 26 #include "vm/flow_graph_inliner.h" |
26 #include "vm/flow_graph_optimizer.h" | 27 #include "vm/flow_graph_optimizer.h" |
27 #include "vm/flow_graph_type_propagator.h" | 28 #include "vm/flow_graph_type_propagator.h" |
28 #include "vm/il_printer.h" | 29 #include "vm/il_printer.h" |
29 #include "vm/longjump.h" | 30 #include "vm/longjump.h" |
30 #include "vm/object.h" | 31 #include "vm/object.h" |
31 #include "vm/object_store.h" | 32 #include "vm/object_store.h" |
32 #include "vm/os.h" | 33 #include "vm/os.h" |
33 #include "vm/parser.h" | 34 #include "vm/parser.h" |
| 35 #include "vm/precompiler.h" |
34 #include "vm/redundancy_elimination.h" | 36 #include "vm/redundancy_elimination.h" |
35 #include "vm/regexp_parser.h" | 37 #include "vm/regexp_parser.h" |
36 #include "vm/regexp_assembler.h" | 38 #include "vm/regexp_assembler.h" |
37 #include "vm/scanner.h" | |
38 #include "vm/symbols.h" | 39 #include "vm/symbols.h" |
39 #include "vm/tags.h" | 40 #include "vm/tags.h" |
40 #include "vm/thread_registry.h" | 41 #include "vm/thread_registry.h" |
41 #include "vm/timer.h" | 42 #include "vm/timer.h" |
42 | 43 |
43 namespace dart { | 44 namespace dart { |
44 | 45 |
45 DEFINE_FLAG(bool, allocation_sinking, true, | 46 DEFINE_FLAG(bool, allocation_sinking, true, |
46 "Attempt to sink temporary allocations to side exits"); | 47 "Attempt to sink temporary allocations to side exits"); |
47 DEFINE_FLAG(bool, common_subexpression_elimination, true, | 48 DEFINE_FLAG(bool, common_subexpression_elimination, true, |
(...skipping 11 matching lines...) Expand all Loading... |
59 "Print the deopt-id to ICData map in optimizing compiler."); | 60 "Print the deopt-id to ICData map in optimizing compiler."); |
60 DEFINE_FLAG(bool, range_analysis, true, "Enable range analysis"); | 61 DEFINE_FLAG(bool, range_analysis, true, "Enable range analysis"); |
61 DEFINE_FLAG(bool, reorder_basic_blocks, true, "Enable basic-block reordering."); | 62 DEFINE_FLAG(bool, reorder_basic_blocks, true, "Enable basic-block reordering."); |
62 DEFINE_FLAG(bool, trace_compiler, false, "Trace compiler operations."); | 63 DEFINE_FLAG(bool, trace_compiler, false, "Trace compiler operations."); |
63 DEFINE_FLAG(bool, trace_optimizing_compiler, false, | 64 DEFINE_FLAG(bool, trace_optimizing_compiler, false, |
64 "Trace only optimizing compiler operations."); | 65 "Trace only optimizing compiler operations."); |
65 DEFINE_FLAG(bool, trace_bailout, false, "Print bailout from ssa compiler."); | 66 DEFINE_FLAG(bool, trace_bailout, false, "Print bailout from ssa compiler."); |
66 DEFINE_FLAG(bool, use_inlining, true, "Enable call-site inlining"); | 67 DEFINE_FLAG(bool, use_inlining, true, "Enable call-site inlining"); |
67 DEFINE_FLAG(bool, verify_compiler, false, | 68 DEFINE_FLAG(bool, verify_compiler, false, |
68 "Enable compiler verification assertions"); | 69 "Enable compiler verification assertions"); |
69 DEFINE_FLAG(int, max_speculative_inlining_attempts, 1, | |
70 "Max number of attempts with speculative inlining (precompilation only)"); | |
71 | 70 |
72 DECLARE_FLAG(bool, background_compilation); | 71 DECLARE_FLAG(bool, background_compilation); |
73 DECLARE_FLAG(bool, huge_method_cutoff_in_code_size); | 72 DECLARE_FLAG(bool, huge_method_cutoff_in_code_size); |
74 DECLARE_FLAG(bool, load_deferred_eagerly); | 73 DECLARE_FLAG(bool, load_deferred_eagerly); |
75 DECLARE_FLAG(bool, trace_failed_optimization_attempts); | 74 DECLARE_FLAG(bool, trace_failed_optimization_attempts); |
76 DECLARE_FLAG(bool, trace_inlining_intervals); | |
77 DECLARE_FLAG(bool, trace_irregexp); | 75 DECLARE_FLAG(bool, trace_irregexp); |
78 DECLARE_FLAG(bool, precompilation); | 76 DECLARE_FLAG(bool, precompilation); |
79 | 77 |
80 | 78 |
81 #ifndef DART_PRECOMPILED_RUNTIME | 79 #ifndef DART_PRECOMPILED_RUNTIME |
82 | 80 |
83 // TODO(zerny): Factor out unoptimizing/optimizing pipelines and remove | 81 void DartCompilationPipeline::ParseFunction(ParsedFunction* parsed_function) { |
84 // separate helpers functions & `optimizing` args. | 82 Parser::ParseFunction(parsed_function); |
85 class CompilationPipeline : public ZoneAllocated { | 83 parsed_function->AllocateVariables(); |
86 public: | 84 } |
87 static CompilationPipeline* New(Zone* zone, const Function& function); | |
88 | |
89 virtual void ParseFunction(ParsedFunction* parsed_function) = 0; | |
90 virtual FlowGraph* BuildFlowGraph( | |
91 Zone* zone, | |
92 ParsedFunction* parsed_function, | |
93 const ZoneGrowableArray<const ICData*>& ic_data_array, | |
94 intptr_t osr_id) = 0; | |
95 virtual void FinalizeCompilation() = 0; | |
96 virtual ~CompilationPipeline() { } | |
97 }; | |
98 | 85 |
99 | 86 |
100 class DartCompilationPipeline : public CompilationPipeline { | 87 FlowGraph* DartCompilationPipeline::BuildFlowGraph( |
101 public: | 88 Zone* zone, |
102 virtual void ParseFunction(ParsedFunction* parsed_function) { | 89 ParsedFunction* parsed_function, |
103 Parser::ParseFunction(parsed_function); | 90 const ZoneGrowableArray<const ICData*>& ic_data_array, |
104 parsed_function->AllocateVariables(); | 91 intptr_t osr_id) { |
105 } | 92 // Build the flow graph. |
| 93 FlowGraphBuilder builder(*parsed_function, |
| 94 ic_data_array, |
| 95 NULL, // NULL = not inlining. |
| 96 osr_id); |
106 | 97 |
107 virtual FlowGraph* BuildFlowGraph( | 98 return builder.BuildGraph(); |
108 Zone* zone, | 99 } |
109 ParsedFunction* parsed_function, | |
110 const ZoneGrowableArray<const ICData*>& ic_data_array, | |
111 intptr_t osr_id) { | |
112 // Build the flow graph. | |
113 FlowGraphBuilder builder(*parsed_function, | |
114 ic_data_array, | |
115 NULL, // NULL = not inlining. | |
116 osr_id); | |
117 | |
118 return builder.BuildGraph(); | |
119 } | |
120 | |
121 virtual void FinalizeCompilation() { } | |
122 }; | |
123 | 100 |
124 | 101 |
125 class IrregexpCompilationPipeline : public CompilationPipeline { | 102 void DartCompilationPipeline::FinalizeCompilation() { } |
126 public: | |
127 IrregexpCompilationPipeline() : backtrack_goto_(NULL) { } | |
128 | 103 |
129 virtual void ParseFunction(ParsedFunction* parsed_function) { | |
130 RegExpParser::ParseFunction(parsed_function); | |
131 // Variables are allocated after compilation. | |
132 } | |
133 | 104 |
134 virtual FlowGraph* BuildFlowGraph( | 105 void IrregexpCompilationPipeline::ParseFunction( |
135 Zone* zone, | 106 ParsedFunction* parsed_function) { |
136 ParsedFunction* parsed_function, | 107 RegExpParser::ParseFunction(parsed_function); |
137 const ZoneGrowableArray<const ICData*>& ic_data_array, | 108 // Variables are allocated after compilation. |
138 intptr_t osr_id) { | 109 } |
139 // Compile to the dart IR. | |
140 RegExpEngine::CompilationResult result = | |
141 RegExpEngine::CompileIR(parsed_function->regexp_compile_data(), | |
142 parsed_function, | |
143 ic_data_array); | |
144 backtrack_goto_ = result.backtrack_goto; | |
145 | 110 |
146 // Allocate variables now that we know the number of locals. | 111 FlowGraph* IrregexpCompilationPipeline::BuildFlowGraph( |
147 parsed_function->AllocateIrregexpVariables(result.num_stack_locals); | 112 Zone* zone, |
| 113 ParsedFunction* parsed_function, |
| 114 const ZoneGrowableArray<const ICData*>& ic_data_array, |
| 115 intptr_t osr_id) { |
| 116 // Compile to the dart IR. |
| 117 RegExpEngine::CompilationResult result = |
| 118 RegExpEngine::CompileIR(parsed_function->regexp_compile_data(), |
| 119 parsed_function, |
| 120 ic_data_array); |
| 121 backtrack_goto_ = result.backtrack_goto; |
148 | 122 |
149 // Build the flow graph. | 123 // Allocate variables now that we know the number of locals. |
150 FlowGraphBuilder builder(*parsed_function, | 124 parsed_function->AllocateIrregexpVariables(result.num_stack_locals); |
151 ic_data_array, | |
152 NULL, // NULL = not inlining. | |
153 osr_id); | |
154 | 125 |
155 return new(zone) FlowGraph(*parsed_function, | 126 // Build the flow graph. |
156 result.graph_entry, | 127 FlowGraphBuilder builder(*parsed_function, |
157 result.num_blocks); | 128 ic_data_array, |
158 } | 129 NULL, // NULL = not inlining. |
| 130 osr_id); |
159 | 131 |
160 virtual void FinalizeCompilation() { | 132 return new(zone) FlowGraph(*parsed_function, |
161 backtrack_goto_->ComputeOffsetTable(); | 133 result.graph_entry, |
162 } | 134 result.num_blocks); |
| 135 } |
163 | 136 |
164 private: | 137 void IrregexpCompilationPipeline::FinalizeCompilation() { |
165 IndirectGotoInstr* backtrack_goto_; | 138 backtrack_goto_->ComputeOffsetTable(); |
166 }; | 139 } |
167 | |
168 | 140 |
169 CompilationPipeline* CompilationPipeline::New(Zone* zone, | 141 CompilationPipeline* CompilationPipeline::New(Zone* zone, |
170 const Function& function) { | 142 const Function& function) { |
171 if (function.IsIrregexpFunction()) { | 143 if (function.IsIrregexpFunction()) { |
172 return new(zone) IrregexpCompilationPipeline(); | 144 return new(zone) IrregexpCompilationPipeline(); |
173 } else { | 145 } else { |
174 return new(zone) DartCompilationPipeline(); | 146 return new(zone) DartCompilationPipeline(); |
175 } | 147 } |
176 } | 148 } |
177 | 149 |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
438 const uint32_t prefix_invalidation_gen_at_start_; | 410 const uint32_t prefix_invalidation_gen_at_start_; |
439 | 411 |
440 DISALLOW_COPY_AND_ASSIGN(CompileParsedFunctionHelper); | 412 DISALLOW_COPY_AND_ASSIGN(CompileParsedFunctionHelper); |
441 }; | 413 }; |
442 | 414 |
443 | 415 |
444 void CompileParsedFunctionHelper::FinalizeCompilation( | 416 void CompileParsedFunctionHelper::FinalizeCompilation( |
445 Assembler* assembler, | 417 Assembler* assembler, |
446 FlowGraphCompiler* graph_compiler, | 418 FlowGraphCompiler* graph_compiler, |
447 FlowGraph* flow_graph) { | 419 FlowGraph* flow_graph) { |
| 420 ASSERT(!FLAG_precompilation); |
448 const Function& function = parsed_function()->function(); | 421 const Function& function = parsed_function()->function(); |
449 Zone* const zone = thread()->zone(); | 422 Zone* const zone = thread()->zone(); |
450 | 423 |
451 CSTAT_TIMER_SCOPE(thread(), codefinalizer_timer); | 424 CSTAT_TIMER_SCOPE(thread(), codefinalizer_timer); |
452 // CreateDeoptInfo uses the object pool and needs to be done before | 425 // CreateDeoptInfo uses the object pool and needs to be done before |
453 // FinalizeCode. | 426 // FinalizeCode. |
454 const Array& deopt_info_array = | 427 const Array& deopt_info_array = |
455 Array::Handle(zone, graph_compiler->CreateDeoptInfo(assembler)); | 428 Array::Handle(zone, graph_compiler->CreateDeoptInfo(assembler)); |
456 INC_STAT(thread(), total_code_size, | 429 INC_STAT(thread(), total_code_size, |
457 deopt_info_array.Length() * sizeof(uword)); | 430 deopt_info_array.Length() * sizeof(uword)); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
536 ASSERT(!is_osr); // OSR is compiled in background. | 509 ASSERT(!is_osr); // OSR is compiled in background. |
537 function.InstallOptimizedCode(code, is_osr); | 510 function.InstallOptimizedCode(code, is_osr); |
538 } | 511 } |
539 if (function.usage_counter() < 0) { | 512 if (function.usage_counter() < 0) { |
540 // Reset to 0 so that it can be recompiled if needed. | 513 // Reset to 0 so that it can be recompiled if needed. |
541 function.set_usage_counter(0); | 514 function.set_usage_counter(0); |
542 } | 515 } |
543 } | 516 } |
544 | 517 |
545 // Register code with the classes it depends on because of CHA and | 518 // Register code with the classes it depends on because of CHA and |
546 // fields it depends on because of store guards, unless we cannot | 519 // fields it depends on because of store guards. |
547 // deopt. | 520 // Deoptimize field dependent code first, before registering |
548 if (!FLAG_precompilation) { | 521 // this yet uninstalled code as dependent on a field. |
549 // Deoptimize field dependent code first, before registering | 522 // TODO(srdjan): Debugging dart2js crashes; |
550 // this yet uninstalled code as dependent on a field. | 523 // FlowGraphOptimizer::VisitStoreInstanceField populates |
551 // TODO(srdjan): Debugging dart2js crashes; | 524 // deoptimize_dependent_code() list, currently disabled. |
552 // FlowGraphOptimizer::VisitStoreInstanceField populates | 525 for (intptr_t i = 0; |
553 // deoptimize_dependent_code() list, currently disabled. | 526 i < flow_graph->deoptimize_dependent_code().length(); |
554 for (intptr_t i = 0; | 527 i++) { |
555 i < flow_graph->deoptimize_dependent_code().length(); | 528 const Field* field = flow_graph->deoptimize_dependent_code()[i]; |
556 i++) { | 529 field->DeoptimizeDependentCode(); |
557 const Field* field = flow_graph->deoptimize_dependent_code()[i]; | 530 } |
558 field->DeoptimizeDependentCode(); | 531 for (intptr_t i = 0; |
559 } | 532 i < thread()->cha()->leaf_classes().length(); |
560 for (intptr_t i = 0; | 533 ++i) { |
561 i < thread()->cha()->leaf_classes().length(); | 534 thread()->cha()->leaf_classes()[i]->RegisterCHACode(code); |
562 ++i) { | 535 } |
563 thread()->cha()->leaf_classes()[i]->RegisterCHACode(code); | 536 for (intptr_t i = 0; |
564 } | 537 i < flow_graph->guarded_fields()->length(); |
565 for (intptr_t i = 0; | 538 i++) { |
566 i < flow_graph->guarded_fields()->length(); | 539 const Field* field = (*flow_graph->guarded_fields())[i]; |
567 i++) { | 540 field->RegisterDependentCode(code); |
568 const Field* field = (*flow_graph->guarded_fields())[i]; | |
569 field->RegisterDependentCode(code); | |
570 } | |
571 } | 541 } |
572 } else { // not optimized. | 542 } else { // not optimized. |
573 if (!FLAG_precompilation && | 543 if (function.ic_data_array() == Array::null()) { |
574 (function.ic_data_array() == Array::null())) { | |
575 function.SaveICDataMap( | 544 function.SaveICDataMap( |
576 graph_compiler->deopt_id_to_ic_data(), | 545 graph_compiler->deopt_id_to_ic_data(), |
577 Array::Handle(zone, graph_compiler->edge_counters_array())); | 546 Array::Handle(zone, graph_compiler->edge_counters_array())); |
578 } | 547 } |
579 function.set_unoptimized_code(code); | 548 function.set_unoptimized_code(code); |
580 function.AttachCode(code); | 549 function.AttachCode(code); |
581 } | 550 } |
582 if (parsed_function()->HasDeferredPrefixes()) { | 551 if (parsed_function()->HasDeferredPrefixes()) { |
583 ASSERT(!FLAG_load_deferred_eagerly); | 552 ASSERT(!FLAG_load_deferred_eagerly); |
584 ZoneGrowableArray<const LibraryPrefix*>* prefixes = | 553 ZoneGrowableArray<const LibraryPrefix*>* prefixes = |
585 parsed_function()->deferred_prefixes(); | 554 parsed_function()->deferred_prefixes(); |
586 for (intptr_t i = 0; i < prefixes->length(); i++) { | 555 for (intptr_t i = 0; i < prefixes->length(); i++) { |
587 (*prefixes)[i]->RegisterDependentCode(code); | 556 (*prefixes)[i]->RegisterDependentCode(code); |
588 } | 557 } |
589 } | 558 } |
590 } | 559 } |
591 | 560 |
592 | 561 |
593 // Return false if bailed out. | 562 // Return false if bailed out. |
594 // If optimized_result_code is not NULL then it is caller's responsibility | 563 // If optimized_result_code is not NULL then it is caller's responsibility |
595 // to install code. | 564 // to install code. |
596 bool CompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) { | 565 bool CompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) { |
| 566 ASSERT(!FLAG_precompilation); |
597 const Function& function = parsed_function()->function(); | 567 const Function& function = parsed_function()->function(); |
598 if (optimized() && !function.IsOptimizable()) { | 568 if (optimized() && !function.IsOptimizable()) { |
599 return false; | 569 return false; |
600 } | 570 } |
601 bool is_compiled = false; | 571 bool is_compiled = false; |
602 Zone* const zone = thread()->zone(); | 572 Zone* const zone = thread()->zone(); |
603 TimelineStream* compiler_timeline = isolate()->GetCompilerStream(); | 573 TimelineStream* compiler_timeline = isolate()->GetCompilerStream(); |
604 CSTAT_TIMER_SCOPE(thread(), codegen_timer); | 574 CSTAT_TIMER_SCOPE(thread(), codegen_timer); |
605 HANDLESCOPE(thread()); | 575 HANDLESCOPE(thread()); |
606 | 576 |
607 // We may reattempt compilation if the function needs to be assembled using | 577 // We may reattempt compilation if the function needs to be assembled using |
608 // far branches on ARM and MIPS. In the else branch of the setjmp call, | 578 // far branches on ARM and MIPS. In the else branch of the setjmp call, |
609 // done is set to false, and use_far_branches is set to true if there is a | 579 // done is set to false, and use_far_branches is set to true if there is a |
610 // longjmp from the ARM or MIPS assemblers. In all other paths through this | 580 // longjmp from the ARM or MIPS assemblers. In all other paths through this |
611 // while loop, done is set to true. use_far_branches is always false on ia32 | 581 // while loop, done is set to true. use_far_branches is always false on ia32 |
612 // and x64. | 582 // and x64. |
613 bool done = false; | 583 bool done = false; |
614 // volatile because the variable may be clobbered by a longjmp. | 584 // volatile because the variable may be clobbered by a longjmp. |
615 volatile bool use_far_branches = false; | 585 volatile bool use_far_branches = false; |
616 volatile bool use_speculative_inlining = | 586 const bool use_speculative_inlining = false; |
617 FLAG_max_speculative_inlining_attempts > 0; | |
618 GrowableArray<intptr_t> inlining_black_list; | |
619 | 587 |
620 while (!done) { | 588 while (!done) { |
621 const intptr_t prev_deopt_id = thread()->deopt_id(); | 589 const intptr_t prev_deopt_id = thread()->deopt_id(); |
622 thread()->set_deopt_id(0); | 590 thread()->set_deopt_id(0); |
623 LongJumpScope jump; | 591 LongJumpScope jump; |
624 const intptr_t val = setjmp(*jump.Set()); | 592 const intptr_t val = setjmp(*jump.Set()); |
625 if (val == 0) { | 593 if (val == 0) { |
626 FlowGraph* flow_graph = NULL; | 594 FlowGraph* flow_graph = NULL; |
627 | 595 |
628 // Class hierarchy analysis is registered with the isolate in the | 596 // Class hierarchy analysis is registered with the isolate in the |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
717 TimelineDurationScope tds(thread(), | 685 TimelineDurationScope tds(thread(), |
718 compiler_timeline, | 686 compiler_timeline, |
719 "OptimizationPasses"); | 687 "OptimizationPasses"); |
720 inline_id_to_function.Add(&function); | 688 inline_id_to_function.Add(&function); |
721 // Top scope function has no caller (-1). | 689 // Top scope function has no caller (-1). |
722 caller_inline_id.Add(-1); | 690 caller_inline_id.Add(-1); |
723 CSTAT_TIMER_SCOPE(thread(), graphoptimizer_timer); | 691 CSTAT_TIMER_SCOPE(thread(), graphoptimizer_timer); |
724 | 692 |
725 FlowGraphOptimizer optimizer(flow_graph, | 693 FlowGraphOptimizer optimizer(flow_graph, |
726 use_speculative_inlining, | 694 use_speculative_inlining, |
727 &inlining_black_list); | 695 NULL); |
728 if (FLAG_precompilation) { | |
729 optimizer.PopulateWithICData(); | |
730 | |
731 optimizer.ApplyClassIds(); | |
732 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | |
733 | |
734 FlowGraphTypePropagator::Propagate(flow_graph); | |
735 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | |
736 } | |
737 optimizer.ApplyICData(); | 696 optimizer.ApplyICData(); |
738 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 697 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
739 | 698 |
740 // Optimize (a << b) & c patterns, merge operations. | 699 // Optimize (a << b) & c patterns, merge operations. |
741 // Run early in order to have more opportunity to optimize left shifts. | 700 // Run early in order to have more opportunity to optimize left shifts. |
742 optimizer.TryOptimizePatterns(); | 701 optimizer.TryOptimizePatterns(); |
743 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 702 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
744 | 703 |
745 FlowGraphInliner::SetInliningId(flow_graph, 0); | 704 FlowGraphInliner::SetInliningId(flow_graph, 0); |
746 | 705 |
747 // Inlining (mutates the flow graph) | 706 // Inlining (mutates the flow graph) |
748 if (FLAG_use_inlining) { | 707 if (FLAG_use_inlining) { |
749 TimelineDurationScope tds2(thread(), | 708 TimelineDurationScope tds2(thread(), |
750 compiler_timeline, | 709 compiler_timeline, |
751 "Inlining"); | 710 "Inlining"); |
752 CSTAT_TIMER_SCOPE(thread(), graphinliner_timer); | 711 CSTAT_TIMER_SCOPE(thread(), graphinliner_timer); |
753 // Propagate types to create more inlining opportunities. | 712 // Propagate types to create more inlining opportunities. |
754 FlowGraphTypePropagator::Propagate(flow_graph); | 713 FlowGraphTypePropagator::Propagate(flow_graph); |
755 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 714 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
756 | 715 |
757 // Use propagated class-ids to create more inlining opportunities. | 716 // Use propagated class-ids to create more inlining opportunities. |
758 optimizer.ApplyClassIds(); | 717 optimizer.ApplyClassIds(); |
759 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 718 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
760 | 719 |
761 FlowGraphInliner inliner(flow_graph, | 720 FlowGraphInliner inliner(flow_graph, |
762 &inline_id_to_function, | 721 &inline_id_to_function, |
763 &caller_inline_id, | 722 &caller_inline_id, |
764 use_speculative_inlining, | 723 use_speculative_inlining, |
765 &inlining_black_list); | 724 NULL); |
766 inliner.Inline(); | 725 inliner.Inline(); |
767 // Use lists are maintained and validated by the inliner. | 726 // Use lists are maintained and validated by the inliner. |
768 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 727 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
769 } | 728 } |
770 | 729 |
771 // Propagate types and eliminate more type tests. | 730 // Propagate types and eliminate more type tests. |
772 FlowGraphTypePropagator::Propagate(flow_graph); | 731 FlowGraphTypePropagator::Propagate(flow_graph); |
773 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 732 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
774 | 733 |
775 { | 734 { |
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1078 // We bailed out or we encountered an error. | 1037 // We bailed out or we encountered an error. |
1079 const Error& error = Error::Handle(thread()->sticky_error()); | 1038 const Error& error = Error::Handle(thread()->sticky_error()); |
1080 | 1039 |
1081 if (error.raw() == Object::branch_offset_error().raw()) { | 1040 if (error.raw() == Object::branch_offset_error().raw()) { |
1082 // Compilation failed due to an out of range branch offset in the | 1041 // Compilation failed due to an out of range branch offset in the |
1083 // assembler. We try again (done = false) with far branches enabled. | 1042 // assembler. We try again (done = false) with far branches enabled. |
1084 done = false; | 1043 done = false; |
1085 ASSERT(!use_far_branches); | 1044 ASSERT(!use_far_branches); |
1086 use_far_branches = true; | 1045 use_far_branches = true; |
1087 } else if (error.raw() == Object::speculative_inlining_error().raw()) { | 1046 } else if (error.raw() == Object::speculative_inlining_error().raw()) { |
1088 // The return value of setjmp is the deopt id of the check instruction | 1047 // Can only happen with precompilation. |
1089 // that caused the bailout. | 1048 UNREACHABLE(); |
1090 done = false; | |
1091 #if defined(DEBUG) | |
1092 ASSERT(FLAG_precompilation); | |
1093 ASSERT(use_speculative_inlining); | |
1094 for (intptr_t i = 0; i < inlining_black_list.length(); ++i) { | |
1095 ASSERT(inlining_black_list[i] != val); | |
1096 } | |
1097 #endif | |
1098 inlining_black_list.Add(val); | |
1099 const intptr_t max_attempts = FLAG_max_speculative_inlining_attempts; | |
1100 if (inlining_black_list.length() >= max_attempts) { | |
1101 use_speculative_inlining = false; | |
1102 if (FLAG_trace_compiler || FLAG_trace_optimizing_compiler) { | |
1103 THR_Print("Disabled speculative inlining after %" Pd " attempts.\n", | |
1104 inlining_black_list.length()); | |
1105 } | |
1106 } | |
1107 } else { | 1049 } else { |
1108 // If the error isn't due to an out of range branch offset, we don't | 1050 // If the error isn't due to an out of range branch offset, we don't |
1109 // try again (done = true), and indicate that we did not finish | 1051 // try again (done = true), and indicate that we did not finish |
1110 // compiling (is_compiled = false). | 1052 // compiling (is_compiled = false). |
1111 if (FLAG_trace_bailout) { | 1053 if (FLAG_trace_bailout) { |
1112 THR_Print("%s\n", error.ToErrorCString()); | 1054 THR_Print("%s\n", error.ToErrorCString()); |
1113 } | 1055 } |
1114 done = true; | 1056 done = true; |
1115 } | 1057 } |
1116 | 1058 |
1117 // Clear the error if it was not a real error, but just a bailout. | 1059 // Clear the error if it was not a real error, but just a bailout. |
1118 if (error.IsLanguageError() && | 1060 if (error.IsLanguageError() && |
1119 (LanguageError::Cast(error).kind() == Report::kBailout)) { | 1061 (LanguageError::Cast(error).kind() == Report::kBailout)) { |
1120 thread()->clear_sticky_error(); | 1062 thread()->clear_sticky_error(); |
1121 } | 1063 } |
1122 is_compiled = false; | 1064 is_compiled = false; |
1123 } | 1065 } |
1124 // Reset global isolate state. | 1066 // Reset global isolate state. |
1125 thread()->set_deopt_id(prev_deopt_id); | 1067 thread()->set_deopt_id(prev_deopt_id); |
1126 } | 1068 } |
1127 return is_compiled; | 1069 return is_compiled; |
1128 } | 1070 } |
1129 | 1071 |
1130 | 1072 |
1131 static void DisassembleCode(const Function& function, bool optimized) { | |
1132 const char* function_fullname = function.ToFullyQualifiedCString(); | |
1133 THR_Print("Code for %sfunction '%s' {\n", | |
1134 optimized ? "optimized " : "", | |
1135 function_fullname); | |
1136 const Code& code = Code::Handle(function.CurrentCode()); | |
1137 code.Disassemble(); | |
1138 THR_Print("}\n"); | |
1139 | |
1140 THR_Print("Pointer offsets for function: {\n"); | |
1141 // Pointer offsets are stored in descending order. | |
1142 Object& obj = Object::Handle(); | |
1143 for (intptr_t i = code.pointer_offsets_length() - 1; i >= 0; i--) { | |
1144 const uword addr = code.GetPointerOffsetAt(i) + code.EntryPoint(); | |
1145 obj = *reinterpret_cast<RawObject**>(addr); | |
1146 THR_Print(" %d : %#" Px " '%s'\n", | |
1147 code.GetPointerOffsetAt(i), addr, obj.ToCString()); | |
1148 } | |
1149 THR_Print("}\n"); | |
1150 | |
1151 THR_Print("PC Descriptors for function '%s' {\n", function_fullname); | |
1152 PcDescriptors::PrintHeaderString(); | |
1153 const PcDescriptors& descriptors = | |
1154 PcDescriptors::Handle(code.pc_descriptors()); | |
1155 THR_Print("%s}\n", descriptors.ToCString()); | |
1156 | |
1157 uword start = Instructions::Handle(code.instructions()).EntryPoint(); | |
1158 const Array& deopt_table = Array::Handle(code.deopt_info_array()); | |
1159 intptr_t deopt_table_length = DeoptTable::GetLength(deopt_table); | |
1160 if (deopt_table_length > 0) { | |
1161 THR_Print("DeoptInfo: {\n"); | |
1162 Smi& offset = Smi::Handle(); | |
1163 TypedData& info = TypedData::Handle(); | |
1164 Smi& reason_and_flags = Smi::Handle(); | |
1165 for (intptr_t i = 0; i < deopt_table_length; ++i) { | |
1166 DeoptTable::GetEntry(deopt_table, i, &offset, &info, &reason_and_flags); | |
1167 const intptr_t reason = | |
1168 DeoptTable::ReasonField::decode(reason_and_flags.Value()); | |
1169 ASSERT((0 <= reason) && (reason < ICData::kDeoptNumReasons)); | |
1170 THR_Print("%4" Pd ": 0x%" Px " %s (%s)\n", | |
1171 i, | |
1172 start + offset.Value(), | |
1173 DeoptInfo::ToCString(deopt_table, info), | |
1174 DeoptReasonToCString( | |
1175 static_cast<ICData::DeoptReasonId>(reason))); | |
1176 } | |
1177 THR_Print("}\n"); | |
1178 } | |
1179 | |
1180 const ObjectPool& object_pool = ObjectPool::Handle(code.GetObjectPool()); | |
1181 object_pool.DebugPrint(); | |
1182 | |
1183 THR_Print("Stackmaps for function '%s' {\n", function_fullname); | |
1184 if (code.stackmaps() != Array::null()) { | |
1185 const Array& stackmap_table = Array::Handle(code.stackmaps()); | |
1186 Stackmap& map = Stackmap::Handle(); | |
1187 for (intptr_t i = 0; i < stackmap_table.Length(); ++i) { | |
1188 map ^= stackmap_table.At(i); | |
1189 THR_Print("%s\n", map.ToCString()); | |
1190 } | |
1191 } | |
1192 THR_Print("}\n"); | |
1193 | |
1194 THR_Print("Variable Descriptors for function '%s' {\n", | |
1195 function_fullname); | |
1196 const LocalVarDescriptors& var_descriptors = | |
1197 LocalVarDescriptors::Handle(code.GetLocalVarDescriptors()); | |
1198 intptr_t var_desc_length = | |
1199 var_descriptors.IsNull() ? 0 : var_descriptors.Length(); | |
1200 String& var_name = String::Handle(); | |
1201 for (intptr_t i = 0; i < var_desc_length; i++) { | |
1202 var_name = var_descriptors.GetName(i); | |
1203 RawLocalVarDescriptors::VarInfo var_info; | |
1204 var_descriptors.GetInfo(i, &var_info); | |
1205 const int8_t kind = var_info.kind(); | |
1206 if (kind == RawLocalVarDescriptors::kSavedCurrentContext) { | |
1207 THR_Print(" saved current CTX reg offset %d\n", var_info.index()); | |
1208 } else { | |
1209 if (kind == RawLocalVarDescriptors::kContextLevel) { | |
1210 THR_Print(" context level %d scope %d", var_info.index(), | |
1211 var_info.scope_id); | |
1212 } else if (kind == RawLocalVarDescriptors::kStackVar) { | |
1213 THR_Print(" stack var '%s' offset %d", | |
1214 var_name.ToCString(), var_info.index()); | |
1215 } else { | |
1216 ASSERT(kind == RawLocalVarDescriptors::kContextVar); | |
1217 THR_Print(" context var '%s' level %d offset %d", | |
1218 var_name.ToCString(), var_info.scope_id, var_info.index()); | |
1219 } | |
1220 THR_Print(" (valid %s-%s)\n", var_info.begin_pos.ToCString(), | |
1221 var_info.end_pos.ToCString()); | |
1222 } | |
1223 } | |
1224 THR_Print("}\n"); | |
1225 | |
1226 THR_Print("Exception Handlers for function '%s' {\n", function_fullname); | |
1227 const ExceptionHandlers& handlers = | |
1228 ExceptionHandlers::Handle(code.exception_handlers()); | |
1229 THR_Print("%s}\n", handlers.ToCString()); | |
1230 | |
1231 { | |
1232 THR_Print("Static call target functions {\n"); | |
1233 const Array& table = Array::Handle(code.static_calls_target_table()); | |
1234 Smi& offset = Smi::Handle(); | |
1235 Function& function = Function::Handle(); | |
1236 Code& code = Code::Handle(); | |
1237 for (intptr_t i = 0; i < table.Length(); | |
1238 i += Code::kSCallTableEntryLength) { | |
1239 offset ^= table.At(i + Code::kSCallTableOffsetEntry); | |
1240 function ^= table.At(i + Code::kSCallTableFunctionEntry); | |
1241 code ^= table.At(i + Code::kSCallTableCodeEntry); | |
1242 if (function.IsNull()) { | |
1243 Class& cls = Class::Handle(); | |
1244 cls ^= code.owner(); | |
1245 if (cls.IsNull()) { | |
1246 const String& code_name = String::Handle(code.Name()); | |
1247 THR_Print(" 0x%" Px ": %s, %p\n", | |
1248 start + offset.Value(), | |
1249 code_name.ToCString(), | |
1250 code.raw()); | |
1251 } else { | |
1252 THR_Print(" 0x%" Px ": allocation stub for %s, %p\n", | |
1253 start + offset.Value(), | |
1254 cls.ToCString(), | |
1255 code.raw()); | |
1256 } | |
1257 } else { | |
1258 THR_Print(" 0x%" Px ": %s, %p\n", | |
1259 start + offset.Value(), | |
1260 function.ToFullyQualifiedCString(), | |
1261 code.raw()); | |
1262 } | |
1263 } | |
1264 THR_Print("}\n"); | |
1265 } | |
1266 if (optimized && FLAG_trace_inlining_intervals) { | |
1267 code.DumpInlinedIntervals(); | |
1268 } | |
1269 } | |
1270 | |
1271 | |
1272 #if defined(DEBUG) | 1073 #if defined(DEBUG) |
1273 // Verifies that the inliner is always in the list of inlined functions. | 1074 // Verifies that the inliner is always in the list of inlined functions. |
1274 // If this fails run with --trace-inlining-intervals to get more information. | 1075 // If this fails run with --trace-inlining-intervals to get more information. |
1275 static void CheckInliningIntervals(const Function& function) { | 1076 static void CheckInliningIntervals(const Function& function) { |
1276 const Code& code = Code::Handle(function.CurrentCode()); | 1077 const Code& code = Code::Handle(function.CurrentCode()); |
1277 const Array& intervals = Array::Handle(code.GetInlinedIntervals()); | 1078 const Array& intervals = Array::Handle(code.GetInlinedIntervals()); |
1278 if (intervals.IsNull() || (intervals.Length() == 0)) return; | 1079 if (intervals.IsNull() || (intervals.Length() == 0)) return; |
1279 Smi& start = Smi::Handle(); | 1080 Smi& start = Smi::Handle(); |
1280 GrowableArray<Function*> inlined_functions; | 1081 GrowableArray<Function*> inlined_functions; |
1281 for (intptr_t i = 0; i < intervals.Length(); i += Code::kInlIntNumEntries) { | 1082 for (intptr_t i = 0; i < intervals.Length(); i += Code::kInlIntNumEntries) { |
1282 start ^= intervals.At(i + Code::kInlIntStart); | 1083 start ^= intervals.At(i + Code::kInlIntStart); |
1283 ASSERT(!start.IsNull()); | 1084 ASSERT(!start.IsNull()); |
1284 if (start.IsNull()) continue; | 1085 if (start.IsNull()) continue; |
1285 code.GetInlinedFunctionsAt(start.Value(), &inlined_functions); | 1086 code.GetInlinedFunctionsAt(start.Value(), &inlined_functions); |
1286 ASSERT(inlined_functions[inlined_functions.length() - 1]->raw() == | 1087 ASSERT(inlined_functions[inlined_functions.length() - 1]->raw() == |
1287 function.raw()); | 1088 function.raw()); |
1288 } | 1089 } |
1289 } | 1090 } |
1290 #endif | 1091 #endif |
1291 | 1092 |
1292 | 1093 |
1293 static RawError* CompileFunctionHelper(CompilationPipeline* pipeline, | 1094 static RawError* CompileFunctionHelper(CompilationPipeline* pipeline, |
1294 const Function& function, | 1095 const Function& function, |
1295 bool optimized, | 1096 bool optimized, |
1296 intptr_t osr_id) { | 1097 intptr_t osr_id) { |
1297 // Check that we optimize if 'FLAG_precompilation' is set to true, | 1098 ASSERT(!FLAG_precompilation); |
1298 // except if the function is marked as not optimizable. | |
1299 ASSERT(!function.IsOptimizable() || | |
1300 !FLAG_precompilation || optimized); | |
1301 ASSERT(!FLAG_precompilation || !function.HasCode()); | |
1302 LongJumpScope jump; | 1099 LongJumpScope jump; |
1303 if (setjmp(*jump.Set()) == 0) { | 1100 if (setjmp(*jump.Set()) == 0) { |
1304 Thread* const thread = Thread::Current(); | 1101 Thread* const thread = Thread::Current(); |
1305 Isolate* const isolate = thread->isolate(); | 1102 Isolate* const isolate = thread->isolate(); |
1306 StackZone stack_zone(thread); | 1103 StackZone stack_zone(thread); |
1307 Zone* const zone = stack_zone.GetZone(); | 1104 Zone* const zone = stack_zone.GetZone(); |
1308 const bool trace_compiler = | 1105 const bool trace_compiler = |
1309 FLAG_trace_compiler || | 1106 FLAG_trace_compiler || |
1310 (FLAG_trace_optimizing_compiler && optimized); | 1107 (FLAG_trace_optimizing_compiler && optimized); |
1311 Timer per_compile_timer(trace_compiler, "Compilation time"); | 1108 Timer per_compile_timer(trace_compiler, "Compilation time"); |
(...skipping 21 matching lines...) Expand all Loading... |
1333 pipeline->ParseFunction(parsed_function); | 1130 pipeline->ParseFunction(parsed_function); |
1334 const int64_t num_tokens_after = STAT_VALUE(thread, num_tokens_consumed); | 1131 const int64_t num_tokens_after = STAT_VALUE(thread, num_tokens_consumed); |
1335 INC_STAT(thread, | 1132 INC_STAT(thread, |
1336 num_func_tokens_compiled, | 1133 num_func_tokens_compiled, |
1337 num_tokens_after - num_tokens_before); | 1134 num_tokens_after - num_tokens_before); |
1338 } | 1135 } |
1339 | 1136 |
1340 CompileParsedFunctionHelper helper(parsed_function, optimized, osr_id); | 1137 CompileParsedFunctionHelper helper(parsed_function, optimized, osr_id); |
1341 const bool success = helper.Compile(pipeline); | 1138 const bool success = helper.Compile(pipeline); |
1342 if (!success) { | 1139 if (!success) { |
1343 if (optimized && !FLAG_precompilation) { | 1140 if (optimized) { |
1344 // Optimizer bailed out. Disable optimizations and never try again. | 1141 // Optimizer bailed out. Disable optimizations and never try again. |
1345 if (trace_compiler) { | 1142 if (trace_compiler) { |
1346 THR_Print("--> disabling optimizations for '%s'\n", | 1143 THR_Print("--> disabling optimizations for '%s'\n", |
1347 function.ToFullyQualifiedCString()); | 1144 function.ToFullyQualifiedCString()); |
1348 } else if (FLAG_trace_failed_optimization_attempts) { | 1145 } else if (FLAG_trace_failed_optimization_attempts) { |
1349 THR_Print("Cannot optimize: %s\n", | 1146 THR_Print("Cannot optimize: %s\n", |
1350 function.ToFullyQualifiedCString()); | 1147 function.ToFullyQualifiedCString()); |
1351 } | 1148 } |
1352 function.SetIsOptimizable(false); | 1149 function.SetIsOptimizable(false); |
1353 return Error::null(); | 1150 return Error::null(); |
(...skipping 17 matching lines...) Expand all Loading... |
1371 Code::Handle(function.CurrentCode()).EntryPoint(), | 1168 Code::Handle(function.CurrentCode()).EntryPoint(), |
1372 Code::Handle(function.CurrentCode()).Size(), | 1169 Code::Handle(function.CurrentCode()).Size(), |
1373 per_compile_timer.TotalElapsedTime()); | 1170 per_compile_timer.TotalElapsedTime()); |
1374 } | 1171 } |
1375 | 1172 |
1376 if (FLAG_support_debugger) { | 1173 if (FLAG_support_debugger) { |
1377 isolate->debugger()->NotifyCompilation(function); | 1174 isolate->debugger()->NotifyCompilation(function); |
1378 } | 1175 } |
1379 | 1176 |
1380 if (FLAG_disassemble && FlowGraphPrinter::ShouldPrint(function)) { | 1177 if (FLAG_disassemble && FlowGraphPrinter::ShouldPrint(function)) { |
1381 DisassembleCode(function, optimized); | 1178 Disassembler::DisassembleCode(function, optimized); |
1382 } else if (FLAG_disassemble_optimized && | 1179 } else if (FLAG_disassemble_optimized && |
1383 optimized && | 1180 optimized && |
1384 FlowGraphPrinter::ShouldPrint(function)) { | 1181 FlowGraphPrinter::ShouldPrint(function)) { |
1385 // TODO(fschneider): Print unoptimized code along with the optimized code. | 1182 // TODO(fschneider): Print unoptimized code along with the optimized code. |
1386 THR_Print("*** BEGIN CODE\n"); | 1183 THR_Print("*** BEGIN CODE\n"); |
1387 DisassembleCode(function, true); | 1184 Disassembler::DisassembleCode(function, true); |
1388 THR_Print("*** END CODE\n"); | 1185 THR_Print("*** END CODE\n"); |
1389 } | 1186 } |
1390 #if defined(DEBUG) | 1187 #if defined(DEBUG) |
1391 CheckInliningIntervals(function); | 1188 CheckInliningIntervals(function); |
1392 #endif | 1189 #endif |
1393 return Error::null(); | 1190 return Error::null(); |
1394 } else { | 1191 } else { |
1395 Thread* const thread = Thread::Current(); | 1192 Thread* const thread = Thread::Current(); |
1396 StackZone stack_zone(thread); | 1193 StackZone stack_zone(thread); |
1397 Error& error = Error::Handle(); | 1194 Error& error = Error::Handle(); |
1398 // We got an error during compilation. | 1195 // We got an error during compilation. |
1399 error = thread->sticky_error(); | 1196 error = thread->sticky_error(); |
1400 thread->clear_sticky_error(); | 1197 thread->clear_sticky_error(); |
1401 // Unoptimized compilation or precompilation may encounter compile-time | 1198 // Unoptimized compilation or precompilation may encounter compile-time |
1402 // errors, but regular optimized compilation should not. | 1199 // errors, but regular optimized compilation should not. |
1403 ASSERT(!optimized || FLAG_precompilation); | 1200 ASSERT(!optimized); |
1404 // Do not attempt to optimize functions that can cause errors. | 1201 // Do not attempt to optimize functions that can cause errors. |
1405 function.set_is_optimizable(false); | 1202 function.set_is_optimizable(false); |
1406 return error.raw(); | 1203 return error.raw(); |
1407 } | 1204 } |
1408 UNREACHABLE(); | 1205 UNREACHABLE(); |
1409 return Error::null(); | 1206 return Error::null(); |
1410 } | 1207 } |
1411 | 1208 |
1412 | 1209 |
1413 RawError* Compiler::CompileFunction(Thread* thread, | 1210 RawError* Compiler::CompileFunction(Thread* thread, |
1414 const Function& function) { | 1211 const Function& function) { |
| 1212 #ifdef DART_PRECOMPILER |
| 1213 if (FLAG_precompilation) { |
| 1214 return Precompiler::CompileFunction(thread, function); |
| 1215 } |
| 1216 #endif |
1415 Isolate* isolate = thread->isolate(); | 1217 Isolate* isolate = thread->isolate(); |
1416 VMTagScope tagScope(thread, VMTag::kCompileUnoptimizedTagId); | 1218 VMTagScope tagScope(thread, VMTag::kCompileUnoptimizedTagId); |
1417 TIMELINE_FUNCTION_COMPILATION_DURATION(thread, "Function", function); | 1219 TIMELINE_FUNCTION_COMPILATION_DURATION(thread, "Function", function); |
1418 | 1220 |
1419 if (!isolate->compilation_allowed()) { | 1221 if (!isolate->compilation_allowed()) { |
1420 FATAL3("Precompilation missed function %s (%s, %s)\n", | 1222 FATAL3("Precompilation missed function %s (%s, %s)\n", |
1421 function.ToLibNamePrefixedQualifiedCString(), | 1223 function.ToLibNamePrefixedQualifiedCString(), |
1422 function.token_pos().ToCString(), | 1224 function.token_pos().ToCString(), |
1423 Function::KindToCString(function.kind())); | 1225 Function::KindToCString(function.kind())); |
1424 } | 1226 } |
1425 | 1227 |
1426 CompilationPipeline* pipeline = | 1228 CompilationPipeline* pipeline = |
1427 CompilationPipeline::New(thread->zone(), function); | 1229 CompilationPipeline::New(thread->zone(), function); |
1428 | 1230 |
1429 const bool optimized = | |
1430 FLAG_precompilation && function.IsOptimizable(); | |
1431 | |
1432 return CompileFunctionHelper(pipeline, | 1231 return CompileFunctionHelper(pipeline, |
1433 function, | 1232 function, |
1434 optimized, | 1233 /* optimized = */ false, |
1435 kNoOSRDeoptId); | 1234 kNoOSRDeoptId); |
1436 } | 1235 } |
1437 | 1236 |
1438 | 1237 |
1439 RawError* Compiler::EnsureUnoptimizedCode(Thread* thread, | 1238 RawError* Compiler::EnsureUnoptimizedCode(Thread* thread, |
1440 const Function& function) { | 1239 const Function& function) { |
1441 if (function.unoptimized_code() != Object::null()) { | 1240 if (function.unoptimized_code() != Object::null()) { |
1442 return Error::null(); | 1241 return Error::null(); |
1443 } | 1242 } |
1444 Code& original_code = Code::ZoneHandle(thread->zone()); | 1243 Code& original_code = Code::ZoneHandle(thread->zone()); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1492 // This is only used from unit tests. | 1291 // This is only used from unit tests. |
1493 RawError* Compiler::CompileParsedFunction( | 1292 RawError* Compiler::CompileParsedFunction( |
1494 ParsedFunction* parsed_function) { | 1293 ParsedFunction* parsed_function) { |
1495 LongJumpScope jump; | 1294 LongJumpScope jump; |
1496 if (setjmp(*jump.Set()) == 0) { | 1295 if (setjmp(*jump.Set()) == 0) { |
1497 // Non-optimized code generator. | 1296 // Non-optimized code generator. |
1498 DartCompilationPipeline pipeline; | 1297 DartCompilationPipeline pipeline; |
1499 CompileParsedFunctionHelper helper(parsed_function, false, kNoOSRDeoptId); | 1298 CompileParsedFunctionHelper helper(parsed_function, false, kNoOSRDeoptId); |
1500 helper.Compile(&pipeline); | 1299 helper.Compile(&pipeline); |
1501 if (FLAG_disassemble) { | 1300 if (FLAG_disassemble) { |
1502 DisassembleCode(parsed_function->function(), false); | 1301 Disassembler::DisassembleCode(parsed_function->function(), false); |
1503 } | 1302 } |
1504 return Error::null(); | 1303 return Error::null(); |
1505 } else { | 1304 } else { |
1506 Error& error = Error::Handle(); | 1305 Error& error = Error::Handle(); |
1507 Thread* thread = Thread::Current(); | 1306 Thread* thread = Thread::Current(); |
1508 // We got an error during compilation. | 1307 // We got an error during compilation. |
1509 error = thread->sticky_error(); | 1308 error = thread->sticky_error(); |
1510 thread->clear_sticky_error(); | 1309 thread->clear_sticky_error(); |
1511 return error.raw(); | 1310 return error.raw(); |
1512 } | 1311 } |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1559 return error.raw(); | 1358 return error.raw(); |
1560 } | 1359 } |
1561 func.ClearICDataArray(); | 1360 func.ClearICDataArray(); |
1562 func.ClearCode(); | 1361 func.ClearCode(); |
1563 } | 1362 } |
1564 } | 1363 } |
1565 return error.raw(); | 1364 return error.raw(); |
1566 } | 1365 } |
1567 | 1366 |
1568 | 1367 |
1569 void Compiler::CompileStaticInitializer(const Field& field) { | |
1570 ASSERT(field.is_static()); | |
1571 if (field.HasPrecompiledInitializer()) { | |
1572 // TODO(rmacnak): Investigate why this happens for _enum_names. | |
1573 OS::Print("Warning: Ignoring repeated request for initializer for %s\n", | |
1574 field.ToCString()); | |
1575 return; | |
1576 } | |
1577 Thread* thread = Thread::Current(); | |
1578 StackZone zone(thread); | |
1579 | |
1580 ParsedFunction* parsed_function = Parser::ParseStaticFieldInitializer(field); | |
1581 | |
1582 parsed_function->AllocateVariables(); | |
1583 // Non-optimized code generator. | |
1584 DartCompilationPipeline pipeline; | |
1585 CompileParsedFunctionHelper helper(parsed_function, false, kNoOSRDeoptId); | |
1586 helper.Compile(&pipeline); | |
1587 const Function& initializer = parsed_function->function(); | |
1588 field.SetPrecompiledInitializer(initializer); | |
1589 } | |
1590 | |
1591 | |
1592 RawObject* Compiler::EvaluateStaticInitializer(const Field& field) { | 1368 RawObject* Compiler::EvaluateStaticInitializer(const Field& field) { |
| 1369 #ifdef DART_PRECOMPILER |
| 1370 if (FLAG_precompilation) { |
| 1371 return Precompiler::EvaluateStaticInitializer(field); |
| 1372 } |
| 1373 #endif |
1593 ASSERT(field.is_static()); | 1374 ASSERT(field.is_static()); |
1594 // The VM sets the field's value to transiton_sentinel prior to | 1375 // The VM sets the field's value to transiton_sentinel prior to |
1595 // evaluating the initializer value. | 1376 // evaluating the initializer value. |
1596 ASSERT(field.StaticValue() == Object::transition_sentinel().raw()); | 1377 ASSERT(field.StaticValue() == Object::transition_sentinel().raw()); |
1597 LongJumpScope jump; | 1378 LongJumpScope jump; |
1598 if (setjmp(*jump.Set()) == 0) { | 1379 if (setjmp(*jump.Set()) == 0) { |
1599 // Under precompilation, the initializer may have already been compiled, in | 1380 // Under lazy compilation initializer has not yet been created, so create |
1600 // which case use it. Under lazy compilation or early in precompilation, the | 1381 // it now, but don't bother remembering it because it won't be used again. |
1601 // initializer has not yet been created, so create it now, but don't bother | 1382 ASSERT(!field.HasPrecompiledInitializer()); |
1602 // remembering it because it won't be used again. | 1383 Thread* const thread = Thread::Current(); |
1603 Function& initializer = Function::Handle(); | 1384 StackZone zone(thread); |
1604 if (!field.HasPrecompiledInitializer()) { | 1385 ParsedFunction* parsed_function = |
1605 Thread* const thread = Thread::Current(); | 1386 Parser::ParseStaticFieldInitializer(field); |
1606 StackZone zone(thread); | |
1607 ParsedFunction* parsed_function = | |
1608 Parser::ParseStaticFieldInitializer(field); | |
1609 | 1387 |
1610 parsed_function->AllocateVariables(); | 1388 parsed_function->AllocateVariables(); |
1611 // Non-optimized code generator. | 1389 // Non-optimized code generator. |
1612 DartCompilationPipeline pipeline; | 1390 DartCompilationPipeline pipeline; |
1613 CompileParsedFunctionHelper helper(parsed_function, false, kNoOSRDeoptId); | 1391 CompileParsedFunctionHelper helper(parsed_function, false, kNoOSRDeoptId); |
1614 helper.Compile(&pipeline); | 1392 helper.Compile(&pipeline); |
1615 initializer = parsed_function->function().raw(); | 1393 const Function& initializer = |
1616 Code::Handle(initializer.unoptimized_code()).set_var_descriptors( | 1394 Function::Handle(parsed_function->function().raw()); |
1617 Object::empty_var_descriptors()); | 1395 Code::Handle(initializer.unoptimized_code()).set_var_descriptors( |
1618 } else { | 1396 Object::empty_var_descriptors()); |
1619 initializer ^= field.PrecompiledInitializer(); | |
1620 } | |
1621 // Invoke the function to evaluate the expression. | 1397 // Invoke the function to evaluate the expression. |
1622 return DartEntry::InvokeFunction(initializer, Object::empty_array()); | 1398 return DartEntry::InvokeFunction(initializer, Object::empty_array()); |
1623 } else { | 1399 } else { |
1624 Thread* const thread = Thread::Current(); | 1400 Thread* const thread = Thread::Current(); |
1625 StackZone zone(thread); | 1401 StackZone zone(thread); |
1626 const Error& error = Error::Handle(thread->zone(), thread->sticky_error()); | 1402 const Error& error = Error::Handle(thread->zone(), thread->sticky_error()); |
1627 thread->clear_sticky_error(); | 1403 thread->clear_sticky_error(); |
1628 return error.raw(); | 1404 return error.raw(); |
1629 } | 1405 } |
1630 UNREACHABLE(); | 1406 UNREACHABLE(); |
1631 return Object::null(); | 1407 return Object::null(); |
1632 } | 1408 } |
1633 | 1409 |
1634 | 1410 |
1635 | 1411 |
1636 RawObject* Compiler::ExecuteOnce(SequenceNode* fragment) { | 1412 RawObject* Compiler::ExecuteOnce(SequenceNode* fragment) { |
| 1413 #ifdef DART_PRECOMPILER |
| 1414 if (FLAG_precompilation) { |
| 1415 return Precompiler::ExecuteOnce(fragment); |
| 1416 } |
| 1417 #endif |
1637 LongJumpScope jump; | 1418 LongJumpScope jump; |
1638 if (setjmp(*jump.Set()) == 0) { | 1419 if (setjmp(*jump.Set()) == 0) { |
1639 Thread* const thread = Thread::Current(); | 1420 Thread* const thread = Thread::Current(); |
1640 if (FLAG_trace_compiler) { | 1421 if (FLAG_trace_compiler) { |
1641 THR_Print("compiling expression: "); | 1422 THR_Print("compiling expression: "); |
1642 AstPrinter::PrintNode(fragment); | 1423 AstPrinter::PrintNode(fragment); |
1643 } | 1424 } |
1644 | 1425 |
1645 // Create a dummy function object for the code generator. | 1426 // Create a dummy function object for the code generator. |
1646 // The function needs to be associated with a named Class: the interface | 1427 // The function needs to be associated with a named Class: the interface |
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1939 } | 1720 } |
1940 if (start_task) { | 1721 if (start_task) { |
1941 Dart::thread_pool()->Run(isolate->background_compiler()); | 1722 Dart::thread_pool()->Run(isolate->background_compiler()); |
1942 } | 1723 } |
1943 } | 1724 } |
1944 | 1725 |
1945 | 1726 |
1946 #else // DART_PRECOMPILED_RUNTIME | 1727 #else // DART_PRECOMPILED_RUNTIME |
1947 | 1728 |
1948 | 1729 |
| 1730 CompilationPipeline* CompilationPipeline::New(Zone* zone, |
| 1731 const Function& function) { |
| 1732 UNREACHABLE(); |
| 1733 return NULL; |
| 1734 } |
| 1735 |
| 1736 |
1949 DEFINE_RUNTIME_ENTRY(CompileFunction, 1) { | 1737 DEFINE_RUNTIME_ENTRY(CompileFunction, 1) { |
1950 const Function& function = Function::CheckedHandle(arguments.ArgAt(0)); | 1738 const Function& function = Function::CheckedHandle(arguments.ArgAt(0)); |
1951 FATAL3("Precompilation missed function %s (%" Pd ", %s)\n", | 1739 FATAL3("Precompilation missed function %s (%" Pd ", %s)\n", |
1952 function.ToLibNamePrefixedQualifiedCString(), | 1740 function.ToLibNamePrefixedQualifiedCString(), |
1953 function.token_pos().value(), | 1741 function.token_pos().value(), |
1954 Function::KindToCString(function.kind())); | 1742 Function::KindToCString(function.kind())); |
1955 } | 1743 } |
1956 | 1744 |
1957 | 1745 |
1958 bool Compiler::IsBackgroundCompilation() { | 1746 bool Compiler::IsBackgroundCompilation() { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2006 UNREACHABLE(); | 1794 UNREACHABLE(); |
2007 } | 1795 } |
2008 | 1796 |
2009 | 1797 |
2010 RawError* Compiler::CompileAllFunctions(const Class& cls) { | 1798 RawError* Compiler::CompileAllFunctions(const Class& cls) { |
2011 UNREACHABLE(); | 1799 UNREACHABLE(); |
2012 return Error::null(); | 1800 return Error::null(); |
2013 } | 1801 } |
2014 | 1802 |
2015 | 1803 |
2016 void Compiler::CompileStaticInitializer(const Field& field) { | |
2017 UNREACHABLE(); | |
2018 } | |
2019 | |
2020 | |
2021 RawObject* Compiler::EvaluateStaticInitializer(const Field& field) { | 1804 RawObject* Compiler::EvaluateStaticInitializer(const Field& field) { |
2022 ASSERT(field.HasPrecompiledInitializer()); | 1805 ASSERT(field.HasPrecompiledInitializer()); |
2023 const Function& initializer = | 1806 const Function& initializer = |
2024 Function::Handle(field.PrecompiledInitializer()); | 1807 Function::Handle(field.PrecompiledInitializer()); |
2025 return DartEntry::InvokeFunction(initializer, Object::empty_array()); | 1808 return DartEntry::InvokeFunction(initializer, Object::empty_array()); |
2026 } | 1809 } |
2027 | 1810 |
2028 | 1811 |
2029 | |
2030 RawObject* Compiler::ExecuteOnce(SequenceNode* fragment) { | 1812 RawObject* Compiler::ExecuteOnce(SequenceNode* fragment) { |
2031 UNREACHABLE(); | 1813 UNREACHABLE(); |
2032 return Object::null(); | 1814 return Object::null(); |
2033 } | 1815 } |
2034 | 1816 |
2035 | 1817 |
2036 void Compiler::AbortBackgroundCompilation(intptr_t deopt_id) { | 1818 void Compiler::AbortBackgroundCompilation(intptr_t deopt_id) { |
2037 UNREACHABLE(); | 1819 UNREACHABLE(); |
2038 } | 1820 } |
2039 | 1821 |
(...skipping 13 matching lines...) Expand all Loading... |
2053 } | 1835 } |
2054 | 1836 |
2055 | 1837 |
2056 void BackgroundCompiler::EnsureInit(Thread* thread) { | 1838 void BackgroundCompiler::EnsureInit(Thread* thread) { |
2057 UNREACHABLE(); | 1839 UNREACHABLE(); |
2058 } | 1840 } |
2059 | 1841 |
2060 #endif // DART_PRECOMPILED_RUNTIME | 1842 #endif // DART_PRECOMPILED_RUNTIME |
2061 | 1843 |
2062 } // namespace dart | 1844 } // namespace dart |
OLD | NEW |