Chromium Code Reviews| 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 |