OLD | NEW |
---|---|
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/pipeline.h" | 5 #include "src/compiler/pipeline.h" |
6 | 6 |
7 #include <fstream> // NOLINT(readability/streams) | 7 #include <fstream> // NOLINT(readability/streams) |
8 #include <sstream> | 8 #include <sstream> |
9 | 9 |
10 #include "src/base/platform/elapsed-timer.h" | 10 #include "src/base/platform/elapsed-timer.h" |
(...skipping 25 matching lines...) Expand all Loading... | |
36 #include "src/compiler/zone-pool.h" | 36 #include "src/compiler/zone-pool.h" |
37 #include "src/ostreams.h" | 37 #include "src/ostreams.h" |
38 #include "src/utils.h" | 38 #include "src/utils.h" |
39 | 39 |
40 namespace v8 { | 40 namespace v8 { |
41 namespace internal { | 41 namespace internal { |
42 namespace compiler { | 42 namespace compiler { |
43 | 43 |
44 class PipelineData { | 44 class PipelineData { |
45 public: | 45 public: |
46 PipelineData(CompilationInfo* info, ZonePool* zone_pool, | 46 explicit PipelineData(ZonePool* zone_pool, CompilationInfo* info) |
47 PipelineStatistics* pipeline_statistics) | |
48 : isolate_(info->zone()->isolate()), | 47 : isolate_(info->zone()->isolate()), |
49 info_(info), | 48 info_(info), |
50 outer_zone_(info->zone()), | |
51 zone_pool_(zone_pool), | |
52 pipeline_statistics_(pipeline_statistics), | |
53 compilation_failed_(false), | |
54 code_(Handle<Code>::null()), | |
55 graph_zone_scope_(zone_pool_), | |
56 graph_zone_(graph_zone_scope_.zone()), | |
57 graph_(new (graph_zone()) Graph(graph_zone())), | |
58 source_positions_(new SourcePositionTable(graph())), | |
59 machine_(new (graph_zone()) MachineOperatorBuilder( | |
60 graph_zone(), kMachPtr, | |
61 InstructionSelector::SupportedMachineOperatorFlags())), | |
62 common_(new (graph_zone()) CommonOperatorBuilder(graph_zone())), | |
63 javascript_(new (graph_zone()) JSOperatorBuilder(graph_zone())), | |
64 jsgraph_(new (graph_zone()) | |
65 JSGraph(graph(), common(), javascript(), machine())), | |
66 typer_(new Typer(graph(), info->context())), | |
67 context_node_(nullptr), | |
68 schedule_(nullptr), | |
69 instruction_zone_scope_(zone_pool_), | |
70 instruction_zone_(instruction_zone_scope_.zone()), | |
71 sequence_(nullptr), | |
72 frame_(nullptr) {} | |
73 | |
74 | |
75 // For machine graph testing only. | |
76 PipelineData(Graph* graph, Schedule* schedule, ZonePool* zone_pool) | |
77 : isolate_(graph->zone()->isolate()), | |
78 info_(nullptr), | |
79 outer_zone_(nullptr), | 49 outer_zone_(nullptr), |
80 zone_pool_(zone_pool), | 50 zone_pool_(zone_pool), |
81 pipeline_statistics_(nullptr), | 51 pipeline_statistics_(nullptr), |
82 compilation_failed_(false), | 52 compilation_failed_(false), |
83 code_(Handle<Code>::null()), | 53 code_(Handle<Code>::null()), |
84 graph_zone_scope_(zone_pool_), | 54 graph_zone_scope_(zone_pool_), |
85 graph_zone_(nullptr), | 55 graph_zone_(nullptr), |
86 graph_(graph), | 56 graph_(nullptr), |
87 source_positions_(new SourcePositionTable(graph)), | |
88 machine_(nullptr), | 57 machine_(nullptr), |
89 common_(nullptr), | 58 common_(nullptr), |
90 javascript_(nullptr), | 59 javascript_(nullptr), |
91 jsgraph_(nullptr), | 60 jsgraph_(nullptr), |
92 typer_(nullptr), | 61 typer_(nullptr), |
93 context_node_(nullptr), | 62 context_node_(nullptr), |
94 schedule_(schedule), | 63 schedule_(nullptr), |
95 instruction_zone_scope_(zone_pool_), | 64 instruction_zone_scope_(zone_pool_), |
96 instruction_zone_(instruction_zone_scope_.zone()), | 65 instruction_zone_(nullptr), |
97 sequence_(nullptr), | 66 sequence_(nullptr), |
98 frame_(nullptr) {} | 67 frame_(nullptr), |
68 register_allocator_(nullptr) {} | |
99 | 69 |
100 ~PipelineData() { | 70 ~PipelineData() { |
101 DeleteInstructionZone(); | 71 DeleteInstructionZone(); |
102 DeleteGraphZone(); | 72 DeleteGraphZone(); |
103 } | 73 } |
104 | 74 |
75 // For main entry point. | |
76 void Initialize(PipelineStatistics* pipeline_statistics) { | |
77 outer_zone_ = info()->zone(); | |
78 pipeline_statistics_ = pipeline_statistics; | |
79 graph_zone_ = graph_zone_scope_.zone(); | |
80 graph_ = new (graph_zone()) Graph(graph_zone()); | |
81 source_positions_.Reset(new SourcePositionTable(graph())); | |
82 machine_ = new (graph_zone()) MachineOperatorBuilder( | |
83 graph_zone(), kMachPtr, | |
84 InstructionSelector::SupportedMachineOperatorFlags()); | |
85 common_ = new (graph_zone()) CommonOperatorBuilder(graph_zone()); | |
86 javascript_ = new (graph_zone()) JSOperatorBuilder(graph_zone()); | |
87 jsgraph_ = | |
88 new (graph_zone()) JSGraph(graph(), common(), javascript(), machine()); | |
89 typer_.Reset(new Typer(graph(), info()->context())); | |
90 instruction_zone_ = instruction_zone_scope_.zone(); | |
91 } | |
92 | |
93 // For machine graph testing entry point. | |
94 void Initialize(Graph* graph, Schedule* schedule) { | |
Benedikt Meurer
2014/11/17 11:35:28
append ForTesting to name.
| |
95 graph_ = graph; | |
96 source_positions_.Reset(new SourcePositionTable(graph)); | |
97 schedule_ = schedule; | |
98 instruction_zone_ = instruction_zone_scope_.zone(); | |
99 } | |
100 | |
101 // For register allocation entry point. | |
102 void Initialize(InstructionSequence* sequence) { | |
103 instruction_zone_ = sequence->zone(); | |
104 sequence_ = sequence; | |
105 } | |
106 | |
105 Isolate* isolate() const { return isolate_; } | 107 Isolate* isolate() const { return isolate_; } |
106 CompilationInfo* info() const { return info_; } | 108 CompilationInfo* info() const { return info_; } |
107 ZonePool* zone_pool() const { return zone_pool_; } | 109 ZonePool* zone_pool() const { return zone_pool_; } |
108 PipelineStatistics* pipeline_statistics() { return pipeline_statistics_; } | 110 PipelineStatistics* pipeline_statistics() { return pipeline_statistics_; } |
109 bool compilation_failed() const { return compilation_failed_; } | 111 bool compilation_failed() const { return compilation_failed_; } |
110 void set_compilation_failed() { compilation_failed_ = true; } | 112 void set_compilation_failed() { compilation_failed_ = true; } |
111 Handle<Code> code() { return code_; } | 113 Handle<Code> code() { return code_; } |
112 void set_code(Handle<Code> code) { | 114 void set_code(Handle<Code> code) { |
113 DCHECK(code_.is_null()); | 115 DCHECK(code_.is_null()); |
114 code_ = code; | 116 code_ = code; |
(...skipping 20 matching lines...) Expand all Loading... | |
135 } | 137 } |
136 | 138 |
137 Schedule* schedule() const { return schedule_; } | 139 Schedule* schedule() const { return schedule_; } |
138 void set_schedule(Schedule* schedule) { | 140 void set_schedule(Schedule* schedule) { |
139 DCHECK_EQ(nullptr, schedule_); | 141 DCHECK_EQ(nullptr, schedule_); |
140 schedule_ = schedule; | 142 schedule_ = schedule; |
141 } | 143 } |
142 | 144 |
143 Zone* instruction_zone() const { return instruction_zone_; } | 145 Zone* instruction_zone() const { return instruction_zone_; } |
144 InstructionSequence* sequence() const { return sequence_; } | 146 InstructionSequence* sequence() const { return sequence_; } |
145 void set_sequence(InstructionSequence* sequence) { | |
146 DCHECK_EQ(nullptr, sequence_); | |
147 sequence_ = sequence; | |
148 } | |
149 Frame* frame() const { return frame_; } | 147 Frame* frame() const { return frame_; } |
150 void set_frame(Frame* frame) { | 148 RegisterAllocator* register_allocator() const { return register_allocator_; } |
151 DCHECK_EQ(nullptr, frame_); | |
152 frame_ = frame; | |
153 } | |
154 | 149 |
155 void DeleteGraphZone() { | 150 void DeleteGraphZone() { |
156 // Destroy objects with destructors first. | 151 // Destroy objects with destructors first. |
157 source_positions_.Reset(nullptr); | 152 source_positions_.Reset(nullptr); |
158 typer_.Reset(nullptr); | 153 typer_.Reset(nullptr); |
159 if (graph_zone_ == nullptr) return; | 154 if (graph_zone_ == nullptr) return; |
160 // Destroy zone and clear pointers. | 155 // Destroy zone and clear pointers. |
161 graph_zone_scope_.Destroy(); | 156 graph_zone_scope_.Destroy(); |
162 graph_zone_ = nullptr; | 157 graph_zone_ = nullptr; |
163 graph_ = nullptr; | 158 graph_ = nullptr; |
164 machine_ = nullptr; | 159 machine_ = nullptr; |
165 common_ = nullptr; | 160 common_ = nullptr; |
166 javascript_ = nullptr; | 161 javascript_ = nullptr; |
167 jsgraph_ = nullptr; | 162 jsgraph_ = nullptr; |
168 context_node_ = nullptr; | 163 context_node_ = nullptr; |
169 schedule_ = nullptr; | 164 schedule_ = nullptr; |
170 } | 165 } |
171 | 166 |
172 void DeleteInstructionZone() { | 167 void DeleteInstructionZone() { |
173 if (instruction_zone_ == nullptr) return; | 168 if (instruction_zone_ == nullptr) return; |
174 instruction_zone_scope_.Destroy(); | 169 instruction_zone_scope_.Destroy(); |
175 instruction_zone_ = nullptr; | 170 instruction_zone_ = nullptr; |
176 sequence_ = nullptr; | 171 sequence_ = nullptr; |
177 frame_ = nullptr; | 172 frame_ = nullptr; |
173 register_allocator_ = nullptr; | |
174 } | |
175 | |
176 void InitializeInstructionSequence() { | |
177 DCHECK_EQ(nullptr, sequence_); | |
178 InstructionBlocks* instruction_blocks = | |
179 InstructionSequence::InstructionBlocksFor(instruction_zone(), | |
180 schedule()); | |
181 sequence_ = new (instruction_zone()) | |
182 InstructionSequence(instruction_zone(), instruction_blocks); | |
183 } | |
184 | |
185 void InitializeRegisterAllocator(Zone* local_zone, | |
186 const RegisterConfiguration* config, | |
187 const char* debug_name) { | |
188 DCHECK_EQ(nullptr, register_allocator_); | |
189 DCHECK_EQ(nullptr, frame_); | |
190 frame_ = new (instruction_zone()) Frame(); | |
191 register_allocator_ = new (instruction_zone()) | |
192 RegisterAllocator(config, local_zone, frame(), sequence(), debug_name); | |
178 } | 193 } |
179 | 194 |
180 private: | 195 private: |
181 Isolate* isolate_; | 196 Isolate* isolate_; |
182 CompilationInfo* info_; | 197 CompilationInfo* info_; |
183 Zone* outer_zone_; | 198 Zone* outer_zone_; |
184 ZonePool* zone_pool_; | 199 ZonePool* const zone_pool_; |
185 PipelineStatistics* pipeline_statistics_; | 200 PipelineStatistics* pipeline_statistics_; |
186 bool compilation_failed_; | 201 bool compilation_failed_; |
187 Handle<Code> code_; | 202 Handle<Code> code_; |
188 | 203 |
189 ZonePool::Scope graph_zone_scope_; | 204 ZonePool::Scope graph_zone_scope_; |
190 Zone* graph_zone_; | 205 Zone* graph_zone_; |
191 // All objects in the following group of fields are allocated in graph_zone_. | 206 // All objects in the following group of fields are allocated in graph_zone_. |
192 // They are all set to NULL when the graph_zone_ is destroyed. | 207 // They are all set to NULL when the graph_zone_ is destroyed. |
193 Graph* graph_; | 208 Graph* graph_; |
194 // TODO(dcarney): make this into a ZoneObject. | 209 // TODO(dcarney): make this into a ZoneObject. |
195 SmartPointer<SourcePositionTable> source_positions_; | 210 SmartPointer<SourcePositionTable> source_positions_; |
196 MachineOperatorBuilder* machine_; | 211 MachineOperatorBuilder* machine_; |
197 CommonOperatorBuilder* common_; | 212 CommonOperatorBuilder* common_; |
198 JSOperatorBuilder* javascript_; | 213 JSOperatorBuilder* javascript_; |
199 JSGraph* jsgraph_; | 214 JSGraph* jsgraph_; |
200 // TODO(dcarney): make this into a ZoneObject. | 215 // TODO(dcarney): make this into a ZoneObject. |
201 SmartPointer<Typer> typer_; | 216 SmartPointer<Typer> typer_; |
202 Node* context_node_; | 217 Node* context_node_; |
203 Schedule* schedule_; | 218 Schedule* schedule_; |
204 | 219 |
205 // All objects in the following group of fields are allocated in | 220 // All objects in the following group of fields are allocated in |
206 // instruction_zone_. They are all set to NULL when the instruction_zone_ is | 221 // instruction_zone_. They are all set to NULL when the instruction_zone_ is |
207 // destroyed. | 222 // destroyed. |
208 ZonePool::Scope instruction_zone_scope_; | 223 ZonePool::Scope instruction_zone_scope_; |
209 Zone* instruction_zone_; | 224 Zone* instruction_zone_; |
210 InstructionSequence* sequence_; | 225 InstructionSequence* sequence_; |
211 Frame* frame_; | 226 Frame* frame_; |
227 RegisterAllocator* register_allocator_; | |
212 | 228 |
213 DISALLOW_COPY_AND_ASSIGN(PipelineData); | 229 DISALLOW_COPY_AND_ASSIGN(PipelineData); |
214 }; | 230 }; |
215 | 231 |
216 | 232 |
217 static inline bool VerifyGraphs() { | 233 static inline bool VerifyGraphs() { |
218 #ifdef DEBUG | 234 #ifdef DEBUG |
219 return true; | 235 return true; |
220 #else | 236 #else |
221 return FLAG_turbo_verify; | 237 return FLAG_turbo_verify; |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
310 | 326 |
311 | 327 |
312 template <typename Phase, typename Arg0> | 328 template <typename Phase, typename Arg0> |
313 void Pipeline::Run(Arg0 arg_0) { | 329 void Pipeline::Run(Arg0 arg_0) { |
314 PipelineRunScope scope(this->data_, Phase::phase_name()); | 330 PipelineRunScope scope(this->data_, Phase::phase_name()); |
315 Phase phase; | 331 Phase phase; |
316 phase.Run(this->data_, scope.zone(), arg_0); | 332 phase.Run(this->data_, scope.zone(), arg_0); |
317 } | 333 } |
318 | 334 |
319 | 335 |
320 // TODO(dcarney): this one should be unecessary. | |
321 template <typename Phase, typename Arg0, typename Arg1> | |
322 void Pipeline::Run(Arg0 arg_0, Arg1 arg_1) { | |
323 PipelineRunScope scope(this->data_, Phase::phase_name()); | |
324 Phase phase; | |
325 phase.Run(this->data_, scope.zone(), arg_0, arg_1); | |
326 } | |
327 | |
328 | |
329 struct GraphBuilderPhase { | 336 struct GraphBuilderPhase { |
330 static const char* phase_name() { return "graph builder"; } | 337 static const char* phase_name() { return "graph builder"; } |
331 | 338 |
332 void Run(PipelineData* data, Zone* temp_zone) { | 339 void Run(PipelineData* data, Zone* temp_zone) { |
333 AstGraphBuilderWithPositions graph_builder( | 340 AstGraphBuilderWithPositions graph_builder( |
334 temp_zone, data->info(), data->jsgraph(), data->source_positions()); | 341 temp_zone, data->info(), data->jsgraph(), data->source_positions()); |
335 if (graph_builder.CreateGraph()) { | 342 if (graph_builder.CreateGraph()) { |
336 data->set_context_node(graph_builder.GetFunctionContext()); | 343 data->set_context_node(graph_builder.GetFunctionContext()); |
337 } else { | 344 } else { |
338 data->set_compilation_failed(); | 345 data->set_compilation_failed(); |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
483 | 490 |
484 void Run(PipelineData* data, Zone* temp_zone, Linkage* linkage) { | 491 void Run(PipelineData* data, Zone* temp_zone, Linkage* linkage) { |
485 InstructionSelector selector(temp_zone, data->graph(), linkage, | 492 InstructionSelector selector(temp_zone, data->graph(), linkage, |
486 data->sequence(), data->schedule(), | 493 data->sequence(), data->schedule(), |
487 data->source_positions()); | 494 data->source_positions()); |
488 selector.SelectInstructions(); | 495 selector.SelectInstructions(); |
489 } | 496 } |
490 }; | 497 }; |
491 | 498 |
492 | 499 |
493 // TODO(dcarney): break this up. | 500 struct MeetRegisterConstraintsPhase { |
494 struct RegisterAllocationPhase { | 501 static const char* phase_name() { return "meet register constraints"; } |
495 static const char* phase_name() { return nullptr; } | |
496 | 502 |
497 void Run(PipelineData* data, Zone* temp_zone) { | 503 void Run(PipelineData* data, Zone* temp_zone) { |
498 int node_count = data->sequence()->VirtualRegisterCount(); | 504 data->register_allocator()->MeetRegisterConstraints(); |
499 if (node_count > UnallocatedOperand::kMaxVirtualRegisters) { | |
500 data->set_compilation_failed(); | |
501 return; | |
502 } | |
503 | |
504 SmartArrayPointer<char> debug_name; | |
505 #ifdef DEBUG | |
506 if (data->info() != nullptr) { | |
507 debug_name = GetDebugName(data->info()); | |
508 } | |
509 #endif | |
510 | |
511 RegisterAllocator allocator(RegisterConfiguration::ArchDefault(), temp_zone, | |
512 data->frame(), data->sequence(), | |
513 debug_name.get()); | |
514 | |
515 if (!allocator.Allocate(data->pipeline_statistics())) { | |
516 data->set_compilation_failed(); | |
517 return; | |
518 } | |
519 | |
520 if (FLAG_trace_turbo) { | |
521 OFStream os(stdout); | |
522 PrintableInstructionSequence printable = { | |
523 RegisterConfiguration::ArchDefault(), data->sequence()}; | |
524 os << "----- Instruction sequence after register allocation -----\n" | |
525 << printable; | |
526 } | |
527 | |
528 if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) { | |
529 TurboCfgFile tcf(data->isolate()); | |
530 tcf << AsC1VAllocator("CodeGen", &allocator); | |
531 } | |
532 } | 505 } |
533 }; | 506 }; |
534 | 507 |
508 | |
509 struct ResolvePhisPhase { | |
510 static const char* phase_name() { return "resolve phis"; } | |
511 | |
512 void Run(PipelineData* data, Zone* temp_zone) { | |
513 data->register_allocator()->ResolvePhis(); | |
514 } | |
515 }; | |
516 | |
517 | |
518 struct BuildLiveRangesPhase { | |
519 static const char* phase_name() { return "build live ranges"; } | |
520 | |
521 void Run(PipelineData* data, Zone* temp_zone) { | |
522 data->register_allocator()->BuildLiveRanges(); | |
523 } | |
524 }; | |
525 | |
526 | |
527 struct AllocateGeneralRegistersPhase { | |
528 static const char* phase_name() { return "allocate general registers"; } | |
529 | |
530 void Run(PipelineData* data, Zone* temp_zone) { | |
531 data->register_allocator()->AllocateGeneralRegisters(); | |
532 } | |
533 }; | |
534 | |
535 | |
536 struct AllocateDoubleRegistersPhase { | |
537 static const char* phase_name() { return "allocate double registers"; } | |
538 | |
539 void Run(PipelineData* data, Zone* temp_zone) { | |
540 data->register_allocator()->AllocateDoubleRegisters(); | |
541 } | |
542 }; | |
543 | |
544 | |
545 struct PopulatePointerMapsPhase { | |
546 static const char* phase_name() { return "populate pointer maps"; } | |
547 | |
548 void Run(PipelineData* data, Zone* temp_zone) { | |
549 data->register_allocator()->PopulatePointerMaps(); | |
550 } | |
551 }; | |
552 | |
553 | |
554 struct ConnectRangesPhase { | |
555 static const char* phase_name() { return "connect ranges"; } | |
556 | |
557 void Run(PipelineData* data, Zone* temp_zone) { | |
558 data->register_allocator()->ConnectRanges(); | |
559 } | |
560 }; | |
561 | |
562 | |
563 struct ResolveControlFlowPhase { | |
564 static const char* phase_name() { return "resolve control flow"; } | |
565 | |
566 void Run(PipelineData* data, Zone* temp_zone) { | |
567 data->register_allocator()->ResolveControlFlow(); | |
568 } | |
569 }; | |
570 | |
535 | 571 |
536 struct GenerateCodePhase { | 572 struct GenerateCodePhase { |
537 static const char* phase_name() { return "generate code"; } | 573 static const char* phase_name() { return "generate code"; } |
538 | 574 |
539 void Run(PipelineData* data, Zone* temp_zone, Linkage* linkage, | 575 void Run(PipelineData* data, Zone* temp_zone, Linkage* linkage) { |
540 CompilationInfo* info) { | 576 CodeGenerator generator(data->frame(), linkage, data->sequence(), |
541 CodeGenerator generator(data->frame(), linkage, data->sequence(), info); | 577 data->info()); |
542 data->set_code(generator.GenerateCode()); | 578 data->set_code(generator.GenerateCode()); |
543 } | 579 } |
544 }; | 580 }; |
545 | 581 |
546 | 582 |
547 struct PrintGraphPhase { | 583 struct PrintGraphPhase { |
548 static const char* phase_name() { return nullptr; } | 584 static const char* phase_name() { return nullptr; } |
549 | 585 |
550 void Run(PipelineData* data, Zone* temp_zone, const char* phase) { | 586 void Run(PipelineData* data, Zone* temp_zone, const char* phase) { |
551 CompilationInfo* info = data->info(); | 587 CompilationInfo* info = data->info(); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
593 static const char* phase_name() { return nullptr; } | 629 static const char* phase_name() { return nullptr; } |
594 | 630 |
595 void Run(PipelineData* data, Zone* temp_zone, const bool untyped) { | 631 void Run(PipelineData* data, Zone* temp_zone, const bool untyped) { |
596 Verifier::Run(data->graph(), FLAG_turbo_types && !untyped | 632 Verifier::Run(data->graph(), FLAG_turbo_types && !untyped |
597 ? Verifier::TYPED | 633 ? Verifier::TYPED |
598 : Verifier::UNTYPED); | 634 : Verifier::UNTYPED); |
599 } | 635 } |
600 }; | 636 }; |
601 | 637 |
602 | 638 |
639 void Pipeline::BeginPhaseKind(const char* phase_kind_name) { | |
640 if (data_->pipeline_statistics() != NULL) { | |
641 data_->pipeline_statistics()->BeginPhaseKind("phase_kind_name"); | |
642 } | |
643 } | |
644 | |
645 | |
603 void Pipeline::RunPrintAndVerify(const char* phase, bool untyped) { | 646 void Pipeline::RunPrintAndVerify(const char* phase, bool untyped) { |
604 if (FLAG_trace_turbo) { | 647 if (FLAG_trace_turbo) { |
605 Run<PrintGraphPhase>(phase); | 648 Run<PrintGraphPhase>(phase); |
606 } | 649 } |
607 if (VerifyGraphs()) { | 650 if (VerifyGraphs()) { |
608 Run<VerifyGraphPhase>(untyped); | 651 Run<VerifyGraphPhase>(untyped); |
609 } | 652 } |
610 } | 653 } |
611 | 654 |
612 | 655 |
(...skipping 10 matching lines...) Expand all Loading... | |
623 // TODO(turbofan): Make OSR work and remove this bailout. | 666 // TODO(turbofan): Make OSR work and remove this bailout. |
624 info()->is_osr()) { | 667 info()->is_osr()) { |
625 return Handle<Code>::null(); | 668 return Handle<Code>::null(); |
626 } | 669 } |
627 | 670 |
628 ZonePool zone_pool(isolate()); | 671 ZonePool zone_pool(isolate()); |
629 SmartPointer<PipelineStatistics> pipeline_statistics; | 672 SmartPointer<PipelineStatistics> pipeline_statistics; |
630 | 673 |
631 if (FLAG_turbo_stats) { | 674 if (FLAG_turbo_stats) { |
632 pipeline_statistics.Reset(new PipelineStatistics(info(), &zone_pool)); | 675 pipeline_statistics.Reset(new PipelineStatistics(info(), &zone_pool)); |
633 pipeline_statistics->BeginPhaseKind("graph creation"); | |
634 } | 676 } |
635 | 677 |
636 PipelineData data(info(), &zone_pool, pipeline_statistics.get()); | 678 PipelineData data(&zone_pool, info()); |
637 this->data_ = &data; | 679 this->data_ = &data; |
638 | 680 |
681 BeginPhaseKind("graph creation"); | |
682 data.Initialize(pipeline_statistics.get()); | |
683 | |
639 if (FLAG_trace_turbo) { | 684 if (FLAG_trace_turbo) { |
640 OFStream os(stdout); | 685 OFStream os(stdout); |
641 os << "---------------------------------------------------\n" | 686 os << "---------------------------------------------------\n" |
642 << "Begin compiling method " << GetDebugName(info()).get() | 687 << "Begin compiling method " << GetDebugName(info()).get() |
643 << " using Turbofan" << std::endl; | 688 << " using Turbofan" << std::endl; |
644 TurboCfgFile tcf(isolate()); | 689 TurboCfgFile tcf(isolate()); |
645 tcf << AsC1VCompilation(info()); | 690 tcf << AsC1VCompilation(info()); |
646 } | 691 } |
647 | 692 |
648 data.source_positions()->AddDecorator(); | 693 data.source_positions()->AddDecorator(); |
(...skipping 23 matching lines...) Expand all Loading... | |
672 | 717 |
673 // Bailout here in case target architecture is not supported. | 718 // Bailout here in case target architecture is not supported. |
674 if (!SupportedTarget()) return Handle<Code>::null(); | 719 if (!SupportedTarget()) return Handle<Code>::null(); |
675 | 720 |
676 if (info()->is_typing_enabled()) { | 721 if (info()->is_typing_enabled()) { |
677 // Type the graph. | 722 // Type the graph. |
678 Run<TyperPhase>(); | 723 Run<TyperPhase>(); |
679 RunPrintAndVerify("Typed"); | 724 RunPrintAndVerify("Typed"); |
680 } | 725 } |
681 | 726 |
682 if (!pipeline_statistics.is_empty()) { | 727 BeginPhaseKind("lowering"); |
683 data.pipeline_statistics()->BeginPhaseKind("lowering"); | |
684 } | |
685 | 728 |
686 if (info()->is_typing_enabled()) { | 729 if (info()->is_typing_enabled()) { |
687 // Lower JSOperators where we can determine types. | 730 // Lower JSOperators where we can determine types. |
688 Run<TypedLoweringPhase>(); | 731 Run<TypedLoweringPhase>(); |
689 RunPrintAndVerify("Lowered typed"); | 732 RunPrintAndVerify("Lowered typed"); |
690 | 733 |
691 // Lower simplified operators and insert changes. | 734 // Lower simplified operators and insert changes. |
692 Run<SimplifiedLoweringPhase>(); | 735 Run<SimplifiedLoweringPhase>(); |
693 RunPrintAndVerify("Lowered simplified"); | 736 RunPrintAndVerify("Lowered simplified"); |
694 | 737 |
695 // Lower changes that have been inserted before. | 738 // Lower changes that have been inserted before. |
696 Run<ChangeLoweringPhase>(); | 739 Run<ChangeLoweringPhase>(); |
697 // // TODO(jarin, rossberg): Remove UNTYPED once machine typing works. | 740 // // TODO(jarin, rossberg): Remove UNTYPED once machine typing works. |
698 RunPrintAndVerify("Lowered changes", true); | 741 RunPrintAndVerify("Lowered changes", true); |
699 | 742 |
700 Run<LateControlReductionPhase>(); | 743 Run<LateControlReductionPhase>(); |
701 RunPrintAndVerify("Late Control reduced"); | 744 RunPrintAndVerify("Late Control reduced"); |
702 } | 745 } |
703 | 746 |
704 // Lower any remaining generic JSOperators. | 747 // Lower any remaining generic JSOperators. |
705 Run<GenericLoweringPhase>(); | 748 Run<GenericLoweringPhase>(); |
706 // TODO(jarin, rossberg): Remove UNTYPED once machine typing works. | 749 // TODO(jarin, rossberg): Remove UNTYPED once machine typing works. |
707 RunPrintAndVerify("Lowered generic", true); | 750 RunPrintAndVerify("Lowered generic", true); |
708 | 751 |
709 if (!pipeline_statistics.is_empty()) { | 752 BeginPhaseKind("block building"); |
710 data.pipeline_statistics()->BeginPhaseKind("block building"); | |
711 } | |
712 | 753 |
713 data.source_positions()->RemoveDecorator(); | 754 data.source_positions()->RemoveDecorator(); |
714 | 755 |
715 // Compute a schedule. | 756 // Compute a schedule. |
716 Run<ComputeSchedulePhase>(); | 757 Run<ComputeSchedulePhase>(); |
717 | 758 |
718 { | 759 { |
719 // Generate optimized code. | 760 // Generate optimized code. |
720 Linkage linkage(data.instruction_zone(), info()); | 761 Linkage linkage(data.instruction_zone(), info()); |
721 GenerateCode(&linkage); | 762 GenerateCode(&linkage); |
(...skipping 13 matching lines...) Expand all Loading... | |
735 | 776 |
736 return code; | 777 return code; |
737 } | 778 } |
738 | 779 |
739 | 780 |
740 Handle<Code> Pipeline::GenerateCodeForMachineGraph(Linkage* linkage, | 781 Handle<Code> Pipeline::GenerateCodeForMachineGraph(Linkage* linkage, |
741 Graph* graph, | 782 Graph* graph, |
742 Schedule* schedule) { | 783 Schedule* schedule) { |
743 ZonePool zone_pool(isolate()); | 784 ZonePool zone_pool(isolate()); |
744 CHECK(SupportedBackend()); | 785 CHECK(SupportedBackend()); |
745 PipelineData data(graph, schedule, &zone_pool); | 786 PipelineData data(&zone_pool, info()); |
787 data.Initialize(graph, schedule); | |
746 this->data_ = &data; | 788 this->data_ = &data; |
747 if (schedule == NULL) { | 789 if (schedule == NULL) { |
748 // TODO(rossberg): Should this really be untyped? | 790 // TODO(rossberg): Should this really be untyped? |
749 RunPrintAndVerify("Machine", true); | 791 RunPrintAndVerify("Machine", true); |
750 Run<ComputeSchedulePhase>(); | 792 Run<ComputeSchedulePhase>(); |
751 } else { | 793 } else { |
752 TraceSchedule(schedule); | 794 TraceSchedule(schedule); |
753 } | 795 } |
754 | 796 |
755 GenerateCode(linkage); | 797 GenerateCode(linkage); |
756 Handle<Code> code = data.code(); | 798 Handle<Code> code = data.code(); |
757 | 799 |
758 #if ENABLE_DISASSEMBLER | 800 #if ENABLE_DISASSEMBLER |
759 if (!code.is_null() && FLAG_print_opt_code) { | 801 if (!code.is_null() && FLAG_print_opt_code) { |
760 CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer()); | 802 CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer()); |
761 OFStream os(tracing_scope.file()); | 803 OFStream os(tracing_scope.file()); |
762 code->Disassemble("test code", os); | 804 code->Disassemble("test code", os); |
763 } | 805 } |
764 #endif | 806 #endif |
765 return code; | 807 return code; |
766 } | 808 } |
767 | 809 |
768 | 810 |
811 bool Pipeline::AllocateRegisters(const RegisterConfiguration* config, | |
812 InstructionSequence* sequence, | |
813 bool run_verifier) { | |
814 CompilationInfo info(sequence->zone()->isolate(), sequence->zone()); | |
815 ZonePool zone_pool(sequence->zone()->isolate()); | |
816 PipelineData data(&zone_pool, &info); | |
817 data.Initialize(sequence); | |
818 Pipeline pipeline(&info); | |
819 pipeline.data_ = &data; | |
820 pipeline.AllocateRegisters(config, run_verifier); | |
821 return !data.compilation_failed(); | |
822 } | |
823 | |
824 | |
769 void Pipeline::GenerateCode(Linkage* linkage) { | 825 void Pipeline::GenerateCode(Linkage* linkage) { |
770 PipelineData* data = this->data_; | 826 PipelineData* data = this->data_; |
771 | 827 |
772 DCHECK_NOT_NULL(linkage); | 828 DCHECK_NOT_NULL(linkage); |
773 DCHECK_NOT_NULL(data->graph()); | 829 DCHECK_NOT_NULL(data->graph()); |
774 DCHECK_NOT_NULL(data->schedule()); | 830 DCHECK_NOT_NULL(data->schedule()); |
775 CHECK(SupportedBackend()); | 831 CHECK(SupportedBackend()); |
776 | 832 |
777 BasicBlockProfiler::Data* profiler_data = NULL; | 833 BasicBlockProfiler::Data* profiler_data = NULL; |
778 if (FLAG_turbo_profiling) { | 834 if (FLAG_turbo_profiling) { |
779 profiler_data = BasicBlockInstrumentor::Instrument(info(), data->graph(), | 835 profiler_data = BasicBlockInstrumentor::Instrument(info(), data->graph(), |
780 data->schedule()); | 836 data->schedule()); |
781 } | 837 } |
782 | 838 |
783 InstructionBlocks* instruction_blocks = | 839 data->InitializeInstructionSequence(); |
784 InstructionSequence::InstructionBlocksFor(data->instruction_zone(), | |
785 data->schedule()); | |
786 data->set_sequence(new (data->instruction_zone()) InstructionSequence( | |
787 data->instruction_zone(), instruction_blocks)); | |
788 | 840 |
789 // Select and schedule instructions covering the scheduled graph. | 841 // Select and schedule instructions covering the scheduled graph. |
790 Run<InstructionSelectionPhase>(linkage); | 842 Run<InstructionSelectionPhase>(linkage); |
791 | 843 |
792 if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) { | 844 if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) { |
793 TurboCfgFile tcf(isolate()); | 845 TurboCfgFile tcf(isolate()); |
794 tcf << AsC1V("CodeGen", data->schedule(), data->source_positions(), | 846 tcf << AsC1V("CodeGen", data->schedule(), data->source_positions(), |
795 data->sequence()); | 847 data->sequence()); |
796 } | 848 } |
797 | 849 |
798 data->DeleteGraphZone(); | 850 data->DeleteGraphZone(); |
799 | 851 |
800 if (data->pipeline_statistics() != NULL) { | 852 BeginPhaseKind("register allocation"); |
801 data->pipeline_statistics()->BeginPhaseKind("register allocation"); | |
802 } | |
803 | 853 |
854 bool run_verifier = false; | |
804 #ifdef DEBUG | 855 #ifdef DEBUG |
805 // Don't track usage for this zone in compiler stats. | 856 run_verifier = true; |
806 Zone verifier_zone(info()->isolate()); | |
807 RegisterAllocatorVerifier verifier( | |
808 &verifier_zone, RegisterConfiguration::ArchDefault(), data->sequence()); | |
809 #endif | 857 #endif |
810 | |
811 // Allocate registers. | 858 // Allocate registers. |
812 data->set_frame(new (data->instruction_zone()) Frame); | 859 AllocateRegisters(RegisterConfiguration::ArchDefault(), run_verifier); |
813 Run<RegisterAllocationPhase>(); | |
814 if (data->compilation_failed()) { | 860 if (data->compilation_failed()) { |
815 info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc); | 861 info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc); |
816 return; | 862 return; |
817 } | 863 } |
818 | 864 |
819 #ifdef DEBUG | 865 BeginPhaseKind("code generation"); |
820 verifier.VerifyAssignment(); | |
821 verifier.VerifyGapMoves(); | |
822 #endif | |
823 | |
824 if (data->pipeline_statistics() != NULL) { | |
825 data->pipeline_statistics()->BeginPhaseKind("code generation"); | |
826 } | |
827 | 866 |
828 // Generate native sequence. | 867 // Generate native sequence. |
829 Run<GenerateCodePhase>(linkage, info()); | 868 Run<GenerateCodePhase>(linkage); |
830 | 869 |
831 if (profiler_data != NULL) { | 870 if (profiler_data != NULL) { |
832 #if ENABLE_DISASSEMBLER | 871 #if ENABLE_DISASSEMBLER |
833 std::ostringstream os; | 872 std::ostringstream os; |
834 data->code()->Disassemble(NULL, os); | 873 data->code()->Disassemble(NULL, os); |
835 profiler_data->SetCode(&os); | 874 profiler_data->SetCode(&os); |
836 #endif | 875 #endif |
837 } | 876 } |
838 } | 877 } |
839 | 878 |
840 | 879 |
880 void Pipeline::AllocateRegisters(const RegisterConfiguration* config, | |
881 bool run_verifier) { | |
882 PipelineData* data = this->data_; | |
883 | |
884 int node_count = data->sequence()->VirtualRegisterCount(); | |
885 if (node_count > UnallocatedOperand::kMaxVirtualRegisters) { | |
886 data->set_compilation_failed(); | |
887 return; | |
888 } | |
889 | |
890 // Don't track usage for this zone in compiler stats. | |
891 SmartPointer<Zone> verifier_zone; | |
892 RegisterAllocatorVerifier* verifier = nullptr; | |
893 if (run_verifier) { | |
894 verifier_zone.Reset(new Zone(info()->isolate())); | |
895 verifier = new (verifier_zone.get()) RegisterAllocatorVerifier( | |
896 verifier_zone.get(), config, data->sequence()); | |
897 } | |
898 | |
899 SmartArrayPointer<char> debug_name; | |
900 #ifdef DEBUG | |
901 debug_name = GetDebugName(data->info()); | |
902 #endif | |
903 | |
904 ZonePool::Scope zone_scope(data->zone_pool()); | |
905 data->InitializeRegisterAllocator(zone_scope.zone(), config, | |
906 debug_name.get()); | |
907 | |
908 Run<MeetRegisterConstraintsPhase>(); | |
909 Run<ResolvePhisPhase>(); | |
910 Run<BuildLiveRangesPhase>(); | |
911 if (FLAG_trace_turbo) { | |
912 OFStream os(stdout); | |
913 PrintableInstructionSequence printable = {config, data->sequence()}; | |
914 os << "----- Instruction sequence before register allocation -----\n" | |
915 << printable; | |
916 } | |
917 DCHECK(!data->register_allocator()->ExistsUseWithoutDefinition()); | |
918 Run<AllocateGeneralRegistersPhase>(); | |
919 if (!data->register_allocator()->AllocationOk()) { | |
920 data->set_compilation_failed(); | |
921 return; | |
922 } | |
923 Run<AllocateDoubleRegistersPhase>(); | |
924 if (!data->register_allocator()->AllocationOk()) { | |
925 data->set_compilation_failed(); | |
926 return; | |
927 } | |
928 Run<PopulatePointerMapsPhase>(); | |
929 Run<ConnectRangesPhase>(); | |
930 Run<ResolveControlFlowPhase>(); | |
931 | |
932 if (FLAG_trace_turbo) { | |
933 OFStream os(stdout); | |
934 PrintableInstructionSequence printable = {config, data->sequence()}; | |
935 os << "----- Instruction sequence after register allocation -----\n" | |
936 << printable; | |
937 } | |
938 | |
939 if (verifier != nullptr) { | |
940 verifier->VerifyAssignment(); | |
941 verifier->VerifyGapMoves(); | |
942 } | |
943 | |
944 if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) { | |
945 TurboCfgFile tcf(data->isolate()); | |
946 tcf << AsC1VAllocator("CodeGen", data->register_allocator()); | |
947 } | |
948 } | |
949 | |
950 | |
841 void Pipeline::SetUp() { | 951 void Pipeline::SetUp() { |
842 InstructionOperand::SetUpCaches(); | 952 InstructionOperand::SetUpCaches(); |
843 } | 953 } |
844 | 954 |
845 | 955 |
846 void Pipeline::TearDown() { | 956 void Pipeline::TearDown() { |
847 InstructionOperand::TearDownCaches(); | 957 InstructionOperand::TearDownCaches(); |
848 } | 958 } |
849 | 959 |
850 } // namespace compiler | 960 } // namespace compiler |
851 } // namespace internal | 961 } // namespace internal |
852 } // namespace v8 | 962 } // namespace v8 |
OLD | NEW |